소스 검색

Fixed some 3rd class skill effects not displaying properly. (bugreport:8144, 8804) (Hercules 8cc9012)

aleos89 11 년 전
부모
커밋
cc59315323
7개의 변경된 파일203개의 추가작업 그리고 73개의 파일을 삭제
  1. 32 60
      src/map/clif.c
  2. 2 5
      src/map/clif.h
  3. 9 1
      src/map/pc.c
  4. 6 0
      src/map/pc.h
  5. 133 7
      src/map/status.c
  6. 13 0
      src/map/status.h
  7. 8 0
      src/map/unit.c

+ 32 - 60
src/map/clif.c

@@ -1314,6 +1314,7 @@ int clif_spawn(struct block_list *bl)
 {
 	unsigned char buf[128];
 	struct view_data *vd;
+	struct status_change *sc = status_get_sc(bl);
 	int len;
 
 	vd = status_get_viewdata(bl);
@@ -1352,29 +1353,14 @@ int clif_spawn(struct block_list *bl)
 				if( sd->talisman[i] > 0 )
 					clif_talisman(sd, i);
 			}
-			for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ ) {
-				if( sd->sc.data[i] )
-					clif_status_change(bl,StatusIconChangeTable[i],1,0,sd->sc.data[i]->val1,sd->sc.data[i]->val2,0);
+			for (i = 0; i < sd->sc_display_count; i++) {
+				if (sc && (sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE|OPTION_CHASEWALK)))
+					clif_status_change2(&sd->bl,sd->bl.id,AREA,SI_BLANK,0,0,0);
+				else
+					clif_status_change2(&sd->bl,sd->bl.id,AREA,StatusIconChangeTable[sd->sc_display[i]->type],sd->sc_display[i]->val1,sd->sc_display[i]->val2,sd->sc_display[i]->val3);
 			}
-		#ifdef NEW_CARTS
-			if( sd->sc.data[SC_PUSH_CART] )
-				clif_status_load_notick(&sd->bl, SI_ON_PUSH_CART, 2, sd->sc.data[SC_PUSH_CART]->val1, 0, 0);
-		#endif
 			if (sd->status.robe)
 				clif_refreshlook(bl,bl->id,LOOK_ROBE,sd->status.robe,AREA);
-			
-			if (!&sd->sc)
-				break;
-			if( sd->sc.data[SC_CAMOUFLAGE] )
-				clif_status_load(bl,SI_CAMOUFLAGE,1);
-			if( sd->sc.data[SC_MONSTER_TRANSFORM] )
-				clif_status_change(bl,SI_MONSTER_TRANSFORM,1,0,sd->sc.data[SC_MONSTER_TRANSFORM]->val1,0,0);
-			if( sd->sc.data[SC_MOONSTAR] )
-				clif_status_load(bl,SI_MOONSTAR,1);
-			if( sd->sc.data[SC_SUPER_STAR] )
-				clif_status_load(bl,SI_SUPER_STAR,1);
-			if( sd->sc.data[SC_ALL_RIDING] )
-				clif_status_load(bl,SI_ALL_RIDING,1);
 		}
 		break;
 	case BL_MOB:
@@ -4170,14 +4156,12 @@ static void clif_getareachar_pc(struct map_session_data* sd,struct map_session_d
 		if( dstsd->talisman[i] > 0 )
 			clif_talisman_single(sd->fd, dstsd, i);
 	}
-	for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ ) {
-		if( dstsd->sc.data[i] )
-			clif_status_load_single(sd->fd,dstsd->bl.id,StatusIconChangeTable[i],1,dstsd->sc.data[i]->val1,dstsd->sc.data[i]->val2,0);
+	for( i = 0; i < dstsd->sc_display_count; i++ ) {
+		if (dstsd->sc.option&(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE|OPTION_CHASEWALK))
+			clif_status_change2(&sd->bl, dstsd->bl.id, SELF, SI_BLANK, 0, 0, 0);
+		else
+			clif_status_change2(&sd->bl, dstsd->bl.id, SELF, StatusIconChangeTable[dstsd->sc_display[i]->type], dstsd->sc_display[i]->val1, dstsd->sc_display[i]->val2, dstsd->sc_display[i]->val3);
 	}
-#ifdef NEW_CARTS
-	if( dstsd->sc.data[SC_PUSH_CART] )
-		clif_status_load_single(sd->fd, dstsd->bl.id, SI_ON_PUSH_CART, 2, dstsd->sc.data[SC_PUSH_CART]->val1, 0, 0);
-#endif
 	if( (sd->status.party_id && dstsd->status.party_id == sd->status.party_id) || //Party-mate, or hpdisp setting.
 		(sd->bg_id && sd->bg_id == dstsd->bg_id) || //BattleGround
 		pc_has_permission(sd, PC_PERM_VIEW_HPMETER)
@@ -5543,6 +5527,27 @@ void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val
 	clif_send(buf,packet_len(WBUFW(buf,0)),bl, (sd && sd->status.option&OPTION_INVISIBLE) ? SELF : AREA);
 }
 
+
+void clif_status_change2(struct block_list *bl, int tid, enum send_target target, int type, int val1, int val2, int val3) {
+	unsigned char buf[32];
+
+	if (type == SI_BLANK) //It shows nothing on the client
+		return;
+
+	nullpo_retv(bl);
+
+	WBUFW(buf,0) = 0x43f;
+	WBUFW(buf,2) = type;
+	WBUFL(buf,4) = tid;
+	WBUFB(buf,8) = 1;
+	WBUFL(buf,9) = 9999;
+	WBUFL(buf,13) = val1;
+	WBUFL(buf,17) = val2;
+	WBUFL(buf,21) = val3;
+	clif_send(buf,packet_len(0x43f),bl,target);
+}
+
+
 /// Send message (modified by [Yor]) (ZC_NOTIFY_PLAYERCHAT).
 /// 008e <packet len>.W <message>.?B
 void clif_displaymessage(const int fd, const char* mes)
@@ -16740,42 +16745,9 @@ int clif_skill_itemlistwindow( struct map_session_data *sd, uint16 skill_id, uin
 #endif
 
 	return 1;
-
 }
-/**
- * Sends a new status without a tick (currently used by the new mounts)
- **/
-int clif_status_load_notick(struct block_list *bl,int type,int flag,int val1, int val2, int val3) {
-	unsigned char buf[32];
 
-	nullpo_ret(bl);
 
-	WBUFW(buf,0)=0x043f;
-	WBUFW(buf,2)=type;
-	WBUFL(buf,4)=bl->id;
-	WBUFB(buf,8)=flag;
-	WBUFL(buf,9)  = 0;
-	WBUFL(buf,13) = val1;
-	WBUFL(buf,17) = val2;
-	WBUFL(buf,21) = val3;
-
-	clif_send(buf,packet_len(0x043f),bl,AREA);
-	return 0;
-}
-//Notifies FD of ID's type
-int clif_status_load_single(int fd, int id,int type,int flag,int val1, int val2, int val3) {
-	WFIFOHEAD(fd, packet_len(0x043f));
-	WFIFOW(fd,0)=0x043f;
-	WFIFOW(fd,2)=type;
-	WFIFOL(fd,4)=id;
-	WFIFOB(fd,8)=flag;
-	WFIFOL(fd,9)  = 0;
-	WFIFOL(fd,13) = val1;
-	WFIFOL(fd,17) = val2;
-	WFIFOL(fd,21) = val3;
-	WFIFOSET(fd, packet_len(0x043f));
-	return 0;
-}
 // msgstringtable.txt
 // 0x291 <line>.W
 void clif_msgtable(int fd, int line) {

+ 2 - 5
src/map/clif.h

@@ -508,7 +508,8 @@ void clif_bladestop(struct block_list *src, int dst_id, int active);
 void clif_changemapcell(int fd, int16 m, int x, int y, int type, enum send_target target);
 
 #define clif_status_load(bl, type, flag) clif_status_change((bl), (type), (flag), 0, 0, 0, 0)
-void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val1, int val2, int val3);
+void clif_status_change(struct block_list *bl, int type, int flag, int tick, int val1, int val2, int val3);
+void clif_status_change2(struct block_list *bl, int tid, enum send_target target, int type, int val1, int val2, int val3);
 
 void clif_wis_message(int fd, const char* nick, const char* mes, int mes_len);
 void clif_wis_end(int fd, int flag);
@@ -806,10 +807,6 @@ int clif_poison_list(struct map_session_data *sd, uint16 skill_lv);
 
 int clif_autoshadowspell_list(struct map_session_data *sd);
 
-int clif_status_load_notick(struct block_list *bl,int type,int flag,int val1, int val2, int val3);
-int clif_status_load_single(int fd, int id,int type,int flag,int val1, int val2, int val3);
-
-
 int clif_skill_itemlistwindow( struct map_session_data *sd, uint16 skill_id, uint16 skill_lv );
 void clif_elemental_info(struct map_session_data *sd);
 void clif_elemental_updatestatus(struct map_session_data *sd, int type);

+ 9 - 1
src/map/pc.c

@@ -1163,6 +1163,10 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
 	}
 #endif
 
+	/* [Ind] */
+	sd->sc_display = NULL;
+	sd->sc_display_count = 0;
+
 	// Player has not yet received the CashShop list
 	sd->status.cashshop_sent = false;
 
@@ -8113,7 +8117,7 @@ bool pc_setcart(struct map_session_data *sd,int type) {
 				clif_cartlist(sd);
 			clif_updatestatus(sd, SP_CARTINFO);
 			sc_start(&sd->bl,&sd->bl, SC_PUSH_CART, 100, type, 0);
-			clif_status_load_notick(&sd->bl, SI_ON_PUSH_CART, 2 , type, 0, 0);
+			clif_status_change2(&sd->bl, sd->bl.id, AREA, SI_ON_PUSH_CART, type, 0, 0);
 			if( sd->sc.data[SC_PUSH_CART] )/* forcefully update */
 				sd->sc.data[SC_PUSH_CART]->val1 = type;
 			break;
@@ -10774,6 +10778,8 @@ void do_final_pc(void) {
 	db_destroy(itemcd_db);
 
 	do_final_pc_groups();
+
+	ers_destroy(pc_sc_display_ers);
 }
 
 void do_init_pc(void) {
@@ -10812,4 +10818,6 @@ void do_init_pc(void) {
 	}
 
 	do_init_pc_groups();
+
+	pc_sc_display_ers = ers_new(sizeof(struct sc_display_entry), "pc.c:pc_sc_display_ers", ERS_OPT_NONE);
 }

+ 6 - 0
src/map/pc.h

@@ -5,6 +5,7 @@
 #define _PC_H_
 
 #include "../common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus
+#include "../common/ers.h"
 #include "../common/timer.h" // INVALID_TIMER
 #include "map.h" // RC_ALL
 #include "atcommand.h" // AtCommandType
@@ -560,6 +561,10 @@ struct map_session_data {
 	unsigned char fontcolor; /* debug-only */
 	unsigned int channel_tick;
 
+	/* [Ind] */
+	struct sc_display_entry **sc_display;
+	unsigned char sc_display_count;
+
 	// temporary debugging of bug #3504
 	const char* delunit_prevfile;
 	int delunit_prevline;
@@ -593,6 +598,7 @@ struct map_session_data {
 	time_t expiration_time;
 };
 
+struct eri *pc_sc_display_ers;
 /* Global Expiration Timer ID */
 extern int pc_expiration_tid;
 

+ 133 - 7
src/map/status.c

@@ -64,12 +64,6 @@ int current_equip_item_index; /// Contains inventory index of an equipped item.
 int current_equip_card_id; /// To prevent card-stacking (from jA) [Skotlex]
 // We need it for new cards 15 Feb 2005, to check if the combo cards are insrerted into the CURRENT weapon only to avoid cards exploits
 
-static sc_type SkillStatusChangeTable[MAX_SKILL];  /// skill  -> status
-static unsigned int StatusChangeFlagTable[SC_MAX]; /// status -> flags
-static int StatusSkillChangeTable[SC_MAX];         /// status -> skill
-static int StatusRelevantBLTypes[SI_MAX];          /// "icon" -> enum bl_type (for clif_status_change to identify for which bl types to send packets)
-static unsigned int StatusChangeStateTable[SC_MAX]; /// status -> flags
-
 static unsigned short status_calc_str(struct block_list *,struct status_change *,int);
 static unsigned short status_calc_agi(struct block_list *,struct status_change *,int);
 static unsigned short status_calc_vit(struct block_list *,struct status_change *,int);
@@ -209,6 +203,7 @@ void initChangeTables(void)
 	memset(StatusSkillChangeTable, 0, sizeof(StatusSkillChangeTable));
 	memset(StatusChangeFlagTable, 0, sizeof(StatusChangeFlagTable));
 	memset(StatusChangeStateTable, 0, sizeof(StatusChangeStateTable));
+	memset(StatusDisplayType, 0, sizeof(StatusDisplayType));
 
 
 	/* First we define the skill for common ailments. These are used in skill_additional_effect through sc cards. [Skotlex] */
@@ -1071,6 +1066,46 @@ void initChangeTables(void)
 	if( !battle_config.display_hallucination ) // Disable Hallucination.
 		StatusIconChangeTable[SC_HALLUCINATION] = SI_BLANK;
 
+	/* StatusDisplayType Table [Ind] */
+	StatusDisplayType[SC_ALL_RIDING]	  = true;
+	StatusDisplayType[SC_PUSH_CART]		  = true;
+	StatusDisplayType[SC_SPHERE_1]		  = true;
+	StatusDisplayType[SC_SPHERE_2]		  = true;
+	StatusDisplayType[SC_SPHERE_3]		  = true;
+	StatusDisplayType[SC_SPHERE_4]		  = true;
+	StatusDisplayType[SC_SPHERE_5]		  = true;
+	StatusDisplayType[SC_CAMOUFLAGE]	  = true;
+	StatusDisplayType[SC_DUPLELIGHT]	  = true;
+	StatusDisplayType[SC_ORATIO]		  = true;
+	StatusDisplayType[SC_FREEZING]		  = true;
+	StatusDisplayType[SC_VENOMIMPRESS]	  = true;
+	StatusDisplayType[SC_HALLUCINATIONWALK]	  = true;
+	StatusDisplayType[SC_ROLLINGCUTTER]	  = true;
+	StatusDisplayType[SC_BANDING]		  = true;
+	StatusDisplayType[SC_CRYSTALIZE]	  = true;
+	StatusDisplayType[SC_DEEPSLEEP]		  = true;
+	StatusDisplayType[SC_CURSEDCIRCLE_ATKER]  = true;
+	StatusDisplayType[SC_CURSEDCIRCLE_TARGET] = true;
+	StatusDisplayType[SC_NETHERWORLD]	  = true;
+	StatusDisplayType[SC_VOICEOFSIREN]	  = true;
+	StatusDisplayType[SC_BLOODSUCKER]	  = true;
+	StatusDisplayType[SC__SHADOWFORM]	  = true;
+	StatusDisplayType[SC__MANHOLE]		  = true;
+	StatusDisplayType[SC_JYUMONJIKIRI]	  = true;
+	StatusDisplayType[SC_AKAITSUKI]		  = true;
+	StatusDisplayType[SC_MONSTER_TRANSFORM]	  = true;
+	StatusDisplayType[SC_DARKCROW]		  = true;
+	StatusDisplayType[SC_OFFERTORIUM]	  = true;
+	StatusDisplayType[SC_TELEKINESIS_INTENSE] = true;
+	StatusDisplayType[SC_UNLIMIT]		  = true;
+	StatusDisplayType[SC_ILLUSIONDOPING]	  = true;
+	StatusDisplayType[SC_C_MARKER]		  = true;
+	StatusDisplayType[SC_ANTI_M_BLAST]	  = true;
+	StatusDisplayType[SC_MOONSTAR]		  = true;
+	StatusDisplayType[SC_SUPER_STAR]	  = true;
+	StatusDisplayType[SC_STRANGELIGHTS]	  = true;
+	StatusDisplayType[SC_DECORATION_OF_MUSIC] = true;
+
 	/* StatusChangeState (SCS_) NOMOVE */
 	StatusChangeStateTable[SC_ANKLE]		|= SCS_NOMOVE;
 	StatusChangeStateTable[SC_AUTOCOUNTER]		|= SCS_NOMOVE;
@@ -7241,6 +7276,78 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
 	return tick;
 }
 
+/**
+* Applies SC effect to the player
+* @param sd: Source to apply effect [PC]
+* @param type: Status change (SC_*)
+* @param dval1~3: Depends on type of status change
+* Author: Ind
+**/
+void status_display_add(struct map_session_data *sd, enum sc_type type, int dval1, int dval2, int dval3) {
+	struct sc_display_entry *entry;
+	int i;
+
+	for( i = 0; i < sd->sc_display_count; i++ ) {
+		if( sd->sc_display[i]->type == type )
+			break;
+	}
+
+	if( i != sd->sc_display_count ) {
+		sd->sc_display[i]->val1 = dval1;
+		sd->sc_display[i]->val2 = dval2;
+		sd->sc_display[i]->val3 = dval3;
+		return;
+	}
+
+	entry = ers_alloc(pc_sc_display_ers, struct sc_display_entry);
+
+	entry->type = type;
+	entry->val1 = dval1;
+	entry->val2 = dval2;
+	entry->val3 = dval3;
+
+	RECREATE(sd->sc_display, struct sc_display_entry *, ++sd->sc_display_count);
+	sd->sc_display[sd->sc_display_count - 1] = entry;
+}
+
+/**
+* Removes SC effect of the player
+* @param sd: Source to remove effect [PC]
+* @param type: Status change (SC_*)
+* Author: Ind
+**/
+void status_display_remove(struct map_session_data *sd, enum sc_type type) {
+	int i;
+
+	for( i = 0; i < sd->sc_display_count; i++ ) {
+		if( sd->sc_display[i]->type == type )
+			break;
+	}
+
+	if( i != sd->sc_display_count ) {
+		int cursor;
+
+		ers_free(pc_sc_display_ers, sd->sc_display[i]);
+		sd->sc_display[i] = NULL;
+
+		/* The all-mighty compact-o-matic */
+		for( i = 0, cursor = 0; i < sd->sc_display_count; i++ ) {
+			if( sd->sc_display[i] == NULL )
+				continue;
+
+			if( i != cursor )
+				sd->sc_display[cursor] = sd->sc_display[i];
+
+			cursor++;
+		}
+
+		if( !(sd->sc_display_count = cursor) ) {
+			aFree(sd->sc_display);
+			sd->sc_display = NULL;
+		}
+	}
+}
+
 /**
 * Applies SC defense to a given status change
 * This function also determines whether or not the status change will be applied
@@ -9706,6 +9813,21 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 			break;
 	}
 
+	/* [Ind] */
+	if (sd && StatusDisplayType[type]) {
+		int dval1 = 0, dval2 = 0, dval3 = 0;
+
+		switch (type) {
+			case SC_ALL_RIDING:
+				dval1 = 1;
+				break;
+			default: /* All others: just copy val1 */
+				dval1 = val1;
+				break;
+		}
+		status_display_add(sd,type,dval1,dval2,dval3);
+	}
+
 	// Those that make you stop attacking/walking....
 	switch (type) {
 		case SC_FREEZE:
@@ -9941,7 +10063,8 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
 		calc_flag&=~SCB_DYE;
 	}
 
-	clif_status_change(bl,StatusIconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0);
+	if(!(flag&4 && StatusDisplayType[type]))
+		clif_status_change(bl,StatusIconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0);
 
 	// Used as temporary storage for scs with interval ticks, so that the actual duration is sent to the client first.
 	if( tick_time )
@@ -10248,6 +10371,9 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
 
 	sc->data[type] = NULL;
 
+	if (sd && StatusDisplayType[type])
+		status_display_remove(sd,type);
+
 	vd = status_get_viewdata(bl);
 	calc_flag = StatusChangeFlagTable[type];
 	switch(type) {

+ 13 - 0
src/map/status.h

@@ -1758,6 +1758,13 @@ struct weapon_atk {
 #endif
 };
 
+sc_type SkillStatusChangeTable[MAX_SKILL];   // skill  -> status
+int StatusIconChangeTable[SC_MAX];           // status -> "icon" (icon is a bit of a misnomer, since there exist values with no icon associated)
+unsigned int StatusChangeFlagTable[SC_MAX];  // status -> flags
+int StatusSkillChangeTable[SC_MAX];          // status -> skill
+int StatusRelevantBLTypes[SI_MAX];           // "icon" -> enum bl_type (for clif->status_change to identify for which bl types to send packets)
+unsigned int StatusChangeStateTable[SC_MAX]; // status -> flags
+bool StatusDisplayType[SC_MAX];
 
 ///For holding basic status (which can be modified by status changes)
 struct status_data {
@@ -1841,6 +1848,12 @@ struct regen_data {
 	struct regen_data_sub *sregen, *ssregen;
 };
 
+///Status display entry
+struct sc_display_entry {
+	enum sc_type type;
+	int val1, val2, val3;
+};
+
 ///Status change entry
 struct status_change_entry {
 	int timer;

+ 8 - 0
src/map/unit.c

@@ -2651,6 +2651,14 @@ int unit_free(struct block_list *bl, clr_type clrtype)
 				aFree(sd->combos.id);
 				sd->combos.count = 0;
 			}
+			/* [Ind] */
+			if( sd->sc_display_count ) {
+				for( i = 0; i < sd->sc_display_count; i++ )
+					ers_free(pc_sc_display_ers, sd->sc_display[i]);
+				sd->sc_display_count = 0;
+				aFree(sd->sc_display);
+				sd->sc_display = NULL;
+			}
 			break;
 		}
 		case BL_PET: