Explorar el Código

Extended broadcast implementation:
- support for font formatting, like font-size
- `bc_woe` flag to allow client-side filtering of WoE announcements
- new broadcast packet 0x40C

git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@14120 54d463be-8e91-2dee-dedb-b68131a5f0ec

Gepard hace 15 años
padre
commit
f9cff9c6e0
Se han modificado 13 ficheros con 291 adiciones y 196 borrados
  1. 1 0
      db/const.txt
  2. 46 2
      db/packet_db.txt
  3. 40 24
      doc/script_commands.txt
  4. 17 11
      src/char/inter.c
  5. 16 10
      src/char_sql/inter.c
  6. 6 6
      src/map/atcommand.c
  7. 42 47
      src/map/clif.c
  8. 2 3
      src/map/clif.h
  9. 31 20
      src/map/intif.c
  10. 2 2
      src/map/intif.h
  11. 2 2
      src/map/mob.c
  12. 4 4
      src/map/pc.c
  13. 82 65
      src/map/script.c

+ 1 - 0
db/const.txt

@@ -176,6 +176,7 @@ bc_pc	0
 bc_npc	8
 bc_yellow	0
 bc_blue	16
+bc_woe	32
 
 mf_nomemo	0
 mf_noteleport	1

+ 46 - 2
db/packet_db.txt

@@ -64,7 +64,7 @@ packet_ver: 5
 0x0096,-1,wis,2:4:28
 0x0097,-1
 0x0098,3
-0x0099,-1,gmmessage,2:4
+0x0099,-1,broadcast,2:4
 0x009a,-1
 0x009b,5,changedir,2:4
 0x009c,9
@@ -323,7 +323,7 @@ packet_ver: 5
 0x0199,4
 0x019a,14
 0x019b,10
-0x019c,-1,lgmmessage,2:4
+0x019c,-1,localbroadcast,2:4
 0x019d,6,gmhide,0
 0x019e,2
 0x019f,6,catchpet,2
@@ -1202,6 +1202,50 @@ packet_ver: 22
 0x035f,-1
 0x0389,-1
 
+//2008-08-20aSakexe
+0x040c,-1
+0x040d,-1
+0x040e,-1
+0x040f,-1
+0x0410,-1
+0x0411,-1
+0x0412,-1
+0x0413,-1
+0x0414,-1
+0x0415,-1
+0x0416,-1
+0x0417,-1
+0x0418,-1
+0x0419,-1
+0x041a,-1
+0x041b,-1
+0x041c,-1
+0x041d,-1
+0x041e,-1
+0x041f,-1
+0x0420,-1
+0x0421,-1
+0x0422,-1
+0x0423,-1
+0x0424,-1
+0x0425,-1
+0x0426,-1
+0x0427,-1
+0x0428,-1
+0x0429,-1
+0x042a,-1
+0x042b,-1
+0x042c,-1
+0x042d,-1
+0x042e,-1
+0x042f,-1
+0x0430,-1
+0x0431,-1
+0x0432,-1
+0x0433,-1
+0x0434,-1
+0x0435,-1
+
 //2008-09-10aSakexe
 packet_ver: 23
 0x0436,19,wanttoconnection,2:6:10:14:18

+ 40 - 24
doc/script_commands.txt

@@ -5334,62 +5334,78 @@ Examples:
 5,1.- End of time-related commands
 //
 
-*announce "<text>",<flag>{,<color>};
+*announce "<text>",<flag>{,<fontColor>{,<fontType>{,<fontSize>{,<fontAlign>{,<fontY>}}}}}};
 
 This command will broadcast a message to all or most players, similar to 
 @kami/@kamib GM commands.
 
-The region the broadcast is heard in and the color the message will come up as 
-will be determined by the flags:
-
     announce "This will be shown to everyone at all in yellow.",0;
 
-The flag values are coded as constants in db/const.txt to make them easier to use:
-- bc_all: Broadcast message is sent server-wide
-- bc_map: Message is sent to everyone in the same map
+The region the broadcast is heard in (target), source of the broadcast
+and the color the message will come up as is determined by the flags.
+
+The flag values are coded as constants in db/const.txt to make them easier to use.
+
+Target flags:
+- bc_all: Broadcast message is sent server-wide (default).
+- bc_map: Message is sent to everyone in the same map as the source of the broadcast (see below).
 - bc_area: Message is sent to players in the vecinity of the source.
 - bc_self: Message is sent only to current player.
+You cannot use more than one target flag.
 
-- bc_npc: Broadcast source is the npc, not the player attached to the script
+Source flags:
+- bc_pc: Broadcast source is the attached player (default).
+- bc_npc: Broadcast source is the NPC, not the player attached to the script
   (useful when a player is not attached or the message should be sent to those
-  nearby the npc)
+  nearby the npc).
+You cannot use more than one source flag.
 
-- bc_yellow: The default is to send broadcasts in yellow color.
-- bc_blue: Alternate broadcast is displayed in blue color.
+Special flags:
+- bc_yellow: Broadcast will be displayed in yellow color (default).
+- bc_blue: Broadcast will be displayed in blue color.
+- bc_woe: Indicates that this broadcast is 'WoE Information' that can be disabled client-side.
+Due to the way client handles broadcasts, it is impossible to set both bc_blue and bc_woe.
+
+The optional parameters allow usage of broadcasts in custom colors, font-weights, sizes etc.
+If any of the optional parameters is used, special flag is ignored.
+Optional parameters may not work well (or at all) depending on a game client used.
 
-The optional parameter, color, allows usage of broadcasts in any custom color.
 The color parameter is a single number which can be in hexadecimal notation.
 For example:
-    announce "This will be shown to everyone at all in yellow.",bc_all,0xFFFF00;
-Will display a global announce in yellow. The color format is in RGB (0xRRGGBB).
+    announce "This will be shown to everyone at all in green.",bc_all,0x00FF00;
+Will display a global announce in green. The color format is in RGB (0xRRGGBB).
+
+In official scripts only two font-weights (types) are used:
+ - normal (FW_NORMAL = 400, default),
+ - bold (FW_BOLD = 700).
+
+Default font size is 12.
 
 Using this for private messages to players is probably not that good an idea,
 but it can be used instead in NPCs to "preview" an announce.
 
     // This will be a private message to the player using the NPC that made the 
-    // annonucement
+    // announcement
     announce "This is my message just for you",bc_blue|bc_self;
 
     // This will be shown on everyones screen that is in sight of the NPC.
-    announce "This is my message just for you people here",bc_area;
+    announce "This is my message just for you people here",bc_npc|bc_area;
 
 ---------------------------------------
 
-*mapannounce "<map name>","<text>",<flag>{,<color>};
+*mapannounce "<map name>","<text>",<flag>{,<fontColor>{,<fontType>{,<fontSize>{,<fontAlign>{,<fontY>}}}}}};
 
 This command will work like 'announce' but will only broadcast to characters 
-currently residing on the specified map. The flag and optional color
-parameters are the same as in 'announce', even though the only ones that make
-sense are the color related ones.
+currently residing on the specified map. The flag and optional paramaters
+parameters are the same as in 'announce', but target and source flags are ignored.
 
 ---------------------------------------
 
-*areaannounce "<map name>",<x1>,<y1>,<x2>,<y2>,"<text>",<flag>[,<color>];
+*areaannounce "<map name>",<x1>,<y1>,<x2>,<y2>,"<text>",<flag>{,<fontColor>{,<fontType>{,<fontSize>{,<fontAlign>{,<fontY>}}}}}};
 
 This command works like 'announce' but will only broadcast to characters 
-residing in the specified x1/y1-x2/y2 square on the map given. The flags and
-color parameter given are the same as in 'announce', but only the color
-related ones have effect.
+residing in the specified x1/y1-x2/y2 rectangle on the map given. The flags and
+optional parameters are the same as in 'announce', but target and source flags are ignored.
 
     areaannounce "prt_church",0,0,350,350,"God's in his heaven, all right with the world",0;
 

+ 17 - 11
src/char/inter.c

@@ -296,17 +296,23 @@ int inter_mapif_init(int fd) {
 //--------------------------------------------------------
 // sended packets to map-server
 
-// GMメッセージ送信
-int mapif_GMmessage(unsigned char *mes, int len, unsigned long color, int sfd) {
-	unsigned char buf[2048];
+// broadcast sending
+int mapif_broadcast(unsigned char *mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, int sfd)
+{
+	unsigned char *buf = (unsigned char*)aMallocA((len)*sizeof(unsigned char));
 
-	if (len > 2048) len = 2047; //Make it fit to avoid crashes. [Skotlex]
 	WBUFW(buf,0) = 0x3800;
 	WBUFW(buf,2) = len;
-	WBUFL(buf,4) = color;
-	memcpy(WBUFP(buf,8), mes, len - 8);
+	WBUFL(buf,4) = fontColor;
+	WBUFW(buf,8) = fontType;
+	WBUFW(buf,10) = fontSize;
+	WBUFW(buf,12) = fontAlign;
+	WBUFW(buf,14) = fontY;
+	memcpy(WBUFP(buf,16), mes, len - 16);
 	mapif_sendallwos(sfd, buf, len);
 
+	if (buf)
+		aFree(buf);
 	return 0;
 }
 
@@ -445,11 +451,11 @@ int check_ttl_wisdata(void) {
 //--------------------------------------------------------
 // received packets from map-server
 
-// GMメッセージ送信
-int mapif_parse_GMmessage(int fd) {
+// broadcast sending
+int mapif_parse_broadcast(int fd)
+{
 	RFIFOHEAD(fd);
-	mapif_GMmessage(RFIFOP(fd,8), RFIFOW(fd,2), RFIFOL(fd,4), fd);
-
+	mapif_broadcast(RFIFOP(fd,16), RFIFOW(fd,2), RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), fd);
 	return 0;
 }
 
@@ -690,7 +696,7 @@ int inter_parse_frommap(int fd) {
 		return 2;
 
 	switch(cmd) {
-	case 0x3000: mapif_parse_GMmessage(fd); break;
+	case 0x3000: mapif_parse_broadcast(fd); break;
 	case 0x3001: mapif_parse_WisRequest(fd); break;
 	case 0x3002: mapif_parse_WisReply(fd); break;
 	case 0x3003: mapif_parse_WisToGM(fd); break;

+ 16 - 10
src/char_sql/inter.c

@@ -336,17 +336,23 @@ int inter_mapif_init(int fd)
 
 //--------------------------------------------------------
 
-// GM message sending
-int mapif_GMmessage(unsigned char *mes, int len, unsigned long color, int sfd)
+// broadcast sending
+int mapif_broadcast(unsigned char *mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, int sfd)
 {
-	unsigned char buf[2048];
+	unsigned char *buf = (unsigned char*)aMallocA((len)*sizeof(unsigned char));
 
-	if (len > 2048) len = 2047; //Make it fit to avoid crashes. [Skotlex]
 	WBUFW(buf,0) = 0x3800;
 	WBUFW(buf,2) = len;
-	WBUFL(buf,4) = color;
-	memcpy(WBUFP(buf,8), mes, len - 8);
+	WBUFL(buf,4) = fontColor;
+	WBUFW(buf,8) = fontType;
+	WBUFW(buf,10) = fontSize;
+	WBUFW(buf,12) = fontAlign;
+	WBUFW(buf,14) = fontY;
+	memcpy(WBUFP(buf,16), mes, len - 16);
 	mapif_sendallwos(sfd, buf, len);
+
+	if (buf)
+		aFree(buf);
 	return 0;
 }
 
@@ -465,10 +471,10 @@ int check_ttl_wisdata(void)
 
 //--------------------------------------------------------
 
-// GM message sending
-int mapif_parse_GMmessage(int fd)
+// broadcast sending
+int mapif_parse_broadcast(int fd)
 {
-	mapif_GMmessage(RFIFOP(fd,8), RFIFOW(fd,2), RFIFOL(fd,4), fd);
+	mapif_broadcast(RFIFOP(fd,16), RFIFOW(fd,2), RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), fd);
 	return 0;
 }
 
@@ -709,7 +715,7 @@ int inter_parse_frommap(int fd)
 		return 2;
 
 	switch(cmd) {
-	case 0x3000: mapif_parse_GMmessage(fd); break;
+	case 0x3000: mapif_parse_broadcast(fd); break;
 	case 0x3001: mapif_parse_WisRequest(fd); break;
 	case 0x3002: mapif_parse_WisReply(fd); break;
 	case 0x3003: mapif_parse_WisToGM(fd); break;

+ 6 - 6
src/map/atcommand.c

@@ -1489,7 +1489,7 @@ int atcommand_kami(const int fd, struct map_session_data* sd, const char* comman
 		}
 
 		sscanf(message, "%199[^\n]", atcmd_output);
-		intif_GMmessage(atcmd_output, strlen(atcmd_output) + 1, (*(command + 5) == 'b' || *(command + 5) == 'B') ? 0x10 : 0);
+		intif_broadcast(atcmd_output, strlen(atcmd_output) + 1, (*(command + 5) == 'b' || *(command + 5) == 'B') ? 0x10 : 0);
 	
 	} else {
 	
@@ -1503,7 +1503,7 @@ int atcommand_kami(const int fd, struct map_session_data* sd, const char* comman
 			return -1;
 		}
 	
-		intif_announce(atcmd_output, strlen(atcmd_output) + 1, color, 0);
+		intif_broadcast2(atcmd_output, strlen(atcmd_output) + 1, color, 0x190, 12, 0, 0);
 	}
 	return 0;
 }
@@ -5294,7 +5294,7 @@ int atcommand_broadcast(const int fd, struct map_session_data* sd, const char* c
 	}
 
 	sprintf(atcmd_output, "%s: %s", sd->status.name, message);
-	intif_GMmessage(atcmd_output, strlen(atcmd_output) + 1, 0);
+	intif_broadcast(atcmd_output, strlen(atcmd_output) + 1, 0);
 
 	return 0;
 }
@@ -5315,7 +5315,7 @@ int atcommand_localbroadcast(const int fd, struct map_session_data* sd, const ch
 
 	sprintf(atcmd_output, "%s: %s", sd->status.name, message);
 
-	clif_GMmessage(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, 1); // 1: ALL_SAMEMAP
+	clif_broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, 0, ALL_SAMEMAP);
 
 	return 0;
 }
@@ -6855,7 +6855,7 @@ int atcommand_gmotd(const int fd, struct map_session_data* sd, const char* comma
 						break;
 					}
 				}
-				intif_GMmessage(buf,strlen(buf)+1,8);
+				intif_broadcast(buf, strlen(buf)+1, 0);
 			}
 			fclose(fp);
 		}
@@ -8087,7 +8087,7 @@ int atcommand_main(const int fd, struct map_session_data* sd, const char* comman
 			// I use 0xFE000000 color for signalizing that this message is
 			// main chat message. 0xFE000000 is invalid color, same using
 			// 0xFF000000 for simple (not colored) GM messages. [LuzZza]
-			intif_announce(atcmd_output, strlen(atcmd_output) + 1, 0xFE000000, 0);
+			intif_broadcast2(atcmd_output, strlen(atcmd_output) + 1, 0xFE000000, 0, 0, 0, 0);
 
 			// Chat logging type 'M' / Main Chat
 			if( log_config.chat&1 || (log_config.chat&32 && !((agit_flag || agit2_flag) && log_config.chat&64)) )

+ 42 - 47
src/map/clif.c

@@ -4739,27 +4739,25 @@ int clif_displaymessage(const int fd, const char* mes)
 
 /*==========================================
  * “V‚Ì�º‚ð‘—�M‚·‚é
+ * Send broadcast message in yellow or blue (without font formatting).
+ * S 009A <len>.W <message>.?B
  *------------------------------------------*/
-int clif_GMmessage(struct block_list* bl, const char* mes, int len, int flag)
+int clif_broadcast(struct block_list* bl, const char* mes, int len, int type, enum send_target target)
 {
-	unsigned char *buf;
-	int lp;
-
-	lp = (flag & 0x10) ? 8 : 4;
-	buf = (unsigned char*)aMallocA((len + lp + 8)*sizeof(unsigned char));
+	int            lp  = type ? 4 : 0;
+	unsigned char *buf = (unsigned char*)aMallocA((4 + lp + len)*sizeof(unsigned char));
 
 	WBUFW(buf,0) = 0x9a;
-	WBUFW(buf,2) = len + lp;
-	WBUFL(buf,4) = 0x65756c62; //"blue":
-	memcpy(WBUFP(buf,lp), mes, len);
-	flag &= 0x07;
-	clif_send(buf, WBUFW(buf,2), bl,
-	          (flag == 1) ? ALL_SAMEMAP :
-	          (flag == 2) ? AREA :
-	          (flag == 3) ? SELF :
-	          ALL_CLIENT);
-	if(buf) aFree(buf);
-
+	WBUFW(buf,2) = 4 + lp + len;
+	if (type == 0x10) // bc_blue
+		WBUFL(buf,4) = 0x65756c62; //If there's "blue" at the beginning of the message, game client will display it in blue instead of yellow.
+	else if (type == 0x20) // bc_woe
+		WBUFL(buf,4) = 0x73737373; //If there's "ssss", game client will recognize message as 'WoE broadcast'.
+	memcpy(WBUFP(buf, 4 + lp), mes, len);
+	clif_send(buf, WBUFW(buf,2), bl, target);
+	
+	if (buf)
+		aFree(buf);
 	return 0;
 }
 
@@ -4809,33 +4807,30 @@ void clif_MainChatMessage(const char* message)
 }
 
 /*==========================================
- * Does an announce message in the given color. 
+ * Send broadcast message with font formatting.
+ * S 01C3 <len>.W <fontColor>.L <fontType>.W <fontSize>.W <fontAlign>.W <fontY>.W <message>.?B
+ * S 040C <len>.W <fontColor>.L <fontType>.W <fontSize>.W <fontAlign>.W <fontY>.W <message>.?B
  *------------------------------------------*/
-int clif_announce(struct block_list* bl, const char* mes, int len, unsigned long color, int flag)
+int clif_broadcast2(struct block_list* bl, const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target)
 {
-	return clif_announce_ex(bl, mes, len, color, flag, 12);
-}
+	unsigned char *buf = (unsigned char*)aMallocA((16 + len)*sizeof(unsigned char));
 
-int clif_announce_ex(struct block_list* bl, const char* mes, int len, unsigned long color, int flag, int size)
-{
-	unsigned char *buf;
-	buf = (unsigned char*)aMallocA((len + 16)*sizeof(unsigned char));
-	WBUFW(buf,0) = 0x1c3;
-	WBUFW(buf,2) = len + 16;
-	WBUFL(buf,4) = color;
-	WBUFW(buf,8) = 0x190; //Font style? Type?
-	WBUFW(buf,10) = size;  // Font size
-	WBUFL(buf,12) = 0;	//Unknown!
+#if PACKETVER < 20080820
+	WBUFW(buf,0)  = 0x1c3;
+#else
+	WBUFW(buf,0)  = 0x40c;
+#endif
+	WBUFW(buf,2)  = len + 16;
+	WBUFL(buf,4)  = fontColor;
+	WBUFW(buf,8)  = fontType;
+	WBUFW(buf,10) = fontSize;
+	WBUFW(buf,12) = fontAlign;
+	WBUFW(buf,14) = fontY;
 	memcpy(WBUFP(buf,16), mes, len);
-	
-	flag &= 0x07;
-	clif_send(buf, WBUFW(buf,2), bl,
-	          (flag == 1) ? ALL_SAMEMAP :
-	          (flag == 2) ? AREA :
-	          (flag == 3) ? SELF :
-	          ALL_CLIENT);
+	clif_send(buf, WBUFW(buf,2), bl, target);
 
-	if(buf) aFree(buf);
+	if (buf)
+		aFree(buf);
 	return 0;
 }
 /*==========================================
@@ -8273,7 +8268,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd)
 		{
 			char output[128];
 			sprintf(output, "[ Kill Steal Protection Disable. KS is allowed in this map ]");
-			clif_announce(&sd->bl, output, strlen(output) + 1, 0x00CC66, 3);
+			clif_broadcast(&sd->bl, output, strlen(output) + 1, 0x10, SELF);
 		}
 
 		map_iwall_get(sd); // Updates Walls Info on this Map to Client
@@ -8879,7 +8874,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
 		else {
 			char output[256];
 			snprintf(output, ARRAYLENGTH(output), msg_txt(386), sd->status.name, message);
-			intif_announce(output, strlen(output) + 1, 0xFE000000, 0);
+			intif_broadcast2(output, strlen(output) + 1, 0xFE000000, 0, 0, 0, 0);
 		}
 
 		// Chat logging type 'M' / Main Chat
@@ -8954,7 +8949,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
  * /b /nb
  * S 0099 <packet len>.w <text>.?B 00
  *------------------------------------------*/
-void clif_parse_GMmessage(int fd, struct map_session_data* sd)
+void clif_parse_Broadcast(int fd, struct map_session_data* sd)
 {
 	char* msg = (char*)RFIFOP(fd,4);
 	unsigned int len = RFIFOW(fd,2)-4;
@@ -8968,7 +8963,7 @@ void clif_parse_GMmessage(int fd, struct map_session_data* sd)
 	// as the length varies depending on the command used, just block unreasonably long strings
 	mes_len_check(msg, len, CHAT_SIZE_MAX);
 
-	intif_GMmessage(msg, len, 0);
+	intif_broadcast(msg, len, 0);
 
 	if(log_config.gm && lv >= log_config.gm) {
 		char logmsg[CHAT_SIZE_MAX+4];
@@ -10036,7 +10031,7 @@ void clif_parse_ResetChar(int fd, struct map_session_data *sd)
  * /lb /nlb
  * S 019c <packet len>.w <text>.?B 00
  *------------------------------------------*/
-void clif_parse_LGMmessage(int fd, struct map_session_data* sd)
+void clif_parse_LocalBroadcast(int fd, struct map_session_data* sd)
 {
 	char* msg = (char*)RFIFOP(fd,4);
 	unsigned int len = RFIFOW(fd,2)-4;
@@ -10051,7 +10046,7 @@ void clif_parse_LGMmessage(int fd, struct map_session_data* sd)
 	// as the length varies depending on the command used, just block unreasonably long strings
 	mes_len_check(msg, len, CHAT_SIZE_MAX);
 
-	clif_GMmessage(&sd->bl, msg, len, 1);
+	clif_broadcast(&sd->bl, msg, len, 0, ALL_SAMEMAP);
 
 	if( log_config.gm && lv >= log_config.gm ) {
 		char logmsg[CHAT_SIZE_MAX+5];
@@ -13641,7 +13636,7 @@ static int packetdb_readdb(void)
 		{clif_parse_ActionRequest,"actionrequest"},
 		{clif_parse_Restart,"restart"},
 		{clif_parse_WisMessage,"wis"},
-		{clif_parse_GMmessage,"gmmessage"},
+		{clif_parse_Broadcast,"broadcast"},
 		{clif_parse_TakeItem,"takeitem"},
 		{clif_parse_DropItem,"dropitem"},
 		{clif_parse_UseItem,"useitem"},
@@ -13691,7 +13686,7 @@ static int packetdb_readdb(void)
 		{clif_parse_WeaponRefine,"weaponrefine"},
 		{clif_parse_SolveCharName,"solvecharname"},
 		{clif_parse_ResetChar,"resetchar"},
-		{clif_parse_LGMmessage,"lgmmessage"},
+		{clif_parse_LocalBroadcast,"localbroadcast"},
 		{clif_parse_MoveToKafra,"movetokafra"},
 		{clif_parse_MoveFromKafra,"movefromkafra"},
 		{clif_parse_MoveToKafraFromCart,"movetokafrafromcart"},

+ 2 - 3
src/map/clif.h

@@ -363,10 +363,9 @@ int clif_font_single(int fd, struct map_session_data *sd);
 int clif_displaymessage(const int fd,const char* mes);
 int clif_disp_onlyself(struct map_session_data *sd,const char *mes,int len);
 void clif_disp_message(struct block_list* src, const char* mes, int len, enum send_target target);
-int clif_GMmessage(struct block_list* bl, const char* mes, int len, int flag);
+int clif_broadcast(struct block_list *bl, const char* mes, int len, int type, enum send_target target);
 void clif_MainChatMessage(const char* message); //luzza
-int clif_announce(struct block_list *bl, const char* mes, int len, unsigned long color, int flag);
-int clif_announce_ex(struct block_list *bl, const char* mes, int len, unsigned long color, int flag, int size);
+int clif_broadcast2(struct block_list *bl, const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target);
 int clif_heal(int fd,int type,int val);
 int clif_resurrection(struct block_list *bl,int type);
 void clif_set0199(struct map_session_data* sd, int mode);

+ 31 - 20
src/map/intif.c

@@ -135,12 +135,12 @@ int intif_rename(struct map_session_data *sd, int type, char *name)
 }
 
 // GMƒ�ƒbƒZ�[ƒW‚ð‘—�M
-int intif_GMmessage(const char* mes,int len,int flag)
+int intif_broadcast(const char* mes, int len, int type)
 {
-	int lp = (flag&0x10) ? 8 : 4;
+	int lp = type ? 4 : 0;
 
 	// Send to the local players
-	clif_GMmessage(NULL, mes, len, flag);
+	clif_broadcast(NULL, mes, len, type, ALL_CLIENT);
 
 	if (CheckForCharServer())
 		return 0;
@@ -148,23 +148,30 @@ int intif_GMmessage(const char* mes,int len,int flag)
 	if (other_mapserver_count < 1)
 		return 0; //No need to send.
 
-	WFIFOHEAD(inter_fd,lp + len + 4);
-	WFIFOW(inter_fd,0) = 0x3000;
-	WFIFOW(inter_fd,2) = lp + len + 4;
-	WFIFOL(inter_fd,4) = 0xFF000000; //"invalid" color signals standard broadcast.
-	WFIFOL(inter_fd,8) = 0x65756c62;
-	memcpy(WFIFOP(inter_fd,4+lp), mes, len);
+	WFIFOHEAD(inter_fd, 16 + lp + len);
+	WFIFOW(inter_fd,0)  = 0x3000;
+	WFIFOW(inter_fd,2)  = 16 + lp + len;
+	WFIFOL(inter_fd,4)  = 0xFF000000; // 0xFF000000 color signals standard broadcast
+	WFIFOW(inter_fd,8)  = 0; // fontType not used with standard broadcast
+	WFIFOW(inter_fd,10) = 0; // fontSize not used with standard broadcast
+	WFIFOW(inter_fd,12) = 0; // fontAlign not used with standard broadcast
+	WFIFOW(inter_fd,14) = 0; // fontY not used with standard broadcast
+	if (type == 0x10) // bc_blue
+		WFIFOL(inter_fd,16) = 0x65756c62; //If there's "blue" at the beginning of the message, game client will display it in blue instead of yellow.
+	else if (type == 0x20) // bc_woe
+		WFIFOL(inter_fd,16) = 0x73737373; //If there's "ssss", game client will recognize message as 'WoE broadcast'.
+	memcpy(WFIFOP(inter_fd,16 + lp), mes, len);
 	WFIFOSET(inter_fd, WFIFOW(inter_fd,2));
 	return 0;
 }
 
-int intif_announce(const char* mes,int len, unsigned long color, int flag)
+int intif_broadcast2(const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY)
 {
 	// Send to the local players
-	if(color == 0xFE000000) // This is main chat message [LuzZza]
+	if (fontColor == 0xFE000000) // This is main chat message [LuzZza]
 		clif_MainChatMessage(mes);
 	else
-		clif_announce(NULL, mes, len, color, flag);
+		clif_broadcast2(NULL, mes, len, fontColor, fontType, fontSize, fontAlign, fontY, ALL_CLIENT);
 
 	if (CheckForCharServer())
 		return 0;
@@ -172,11 +179,15 @@ int intif_announce(const char* mes,int len, unsigned long color, int flag)
 	if (other_mapserver_count < 1)
 		return 0; //No need to send.
 
-	WFIFOHEAD(inter_fd, 8 + len);
-	WFIFOW(inter_fd,0) = 0x3000;
-	WFIFOW(inter_fd,2) = 8 + len;
-	WFIFOL(inter_fd,4) = color;
-	memcpy(WFIFOP(inter_fd,8), mes, len);
+	WFIFOHEAD(inter_fd, 16 + len);
+	WFIFOW(inter_fd,0)  = 0x3000;
+	WFIFOW(inter_fd,2)  = 16 + len;
+	WFIFOL(inter_fd,4)  = fontColor;
+	WFIFOW(inter_fd,8)  = fontType;
+	WFIFOW(inter_fd,10) = fontSize;
+	WFIFOW(inter_fd,12) = fontAlign;
+	WFIFOW(inter_fd,14) = fontY;
+	memcpy(WFIFOP(inter_fd,16), mes, len);
 	WFIFOSET(inter_fd, WFIFOW(inter_fd,2));
 	return 0;
 }
@@ -2001,11 +2012,11 @@ int intif_parse(int fd)
 	switch(cmd){
 	case 0x3800:
 		if (RFIFOL(fd,4) == 0xFF000000) //Normal announce.
-			clif_GMmessage(NULL,(char *) RFIFOP(fd,8),packet_len-8,0);
+			clif_broadcast(NULL, (char *) RFIFOP(fd,16), packet_len-16, 0, ALL_CLIENT);
 		else if (RFIFOL(fd,4) == 0xFE000000) //Main chat message [LuzZza]
-			clif_MainChatMessage((char *)RFIFOP(fd,8));
+			clif_MainChatMessage((char *)RFIFOP(fd,16));
 		else //Color announce.
-			clif_announce(NULL,(char *) RFIFOP(fd,8),packet_len-8,RFIFOL(fd,4),0);
+			clif_broadcast2(NULL, (char *) RFIFOP(fd,16), packet_len-16, RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), ALL_CLIENT);
 		break;
 	case 0x3801:	intif_parse_WisMessage(fd); break;
 	case 0x3802:	intif_parse_WisEnd(fd); break;

+ 2 - 2
src/map/intif.h

@@ -16,8 +16,8 @@ struct auction_data;
 
 int intif_parse(int fd);
 
-int intif_GMmessage(const char* mes,int len,int flag);
-int intif_announce(const char* mes,int len, unsigned long color, int flag);
+int intif_broadcast(const char* mes, int len, int type);
+int intif_broadcast2(const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY);
 
 int intif_wis_message(struct map_session_data *sd,char *nick,char *mes,int mes_len);
 int intif_wis_message_to_gm(char *Wisp_name, int min_gm_level, char *mes);

+ 2 - 2
src/map/mob.c

@@ -2220,7 +2220,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 				i_data = itemdb_search(ditem->item_data.nameid);
 				sprintf (message, msg_txt(541), (mvp_sd?mvp_sd->status.name:"???"), md->name, i_data->jname, (float)drop_rate/100);
 				//MSG: "'%s' won %s's %s (chance: %0.02f%%)"
-				intif_GMmessage(message,strlen(message)+1,0);
+				intif_broadcast(message,strlen(message)+1,0);
 			}
 			// Announce first, or else ditem will be freed. [Lance]
 			// By popular demand, use base drop rate for autoloot code. [Skotlex]
@@ -2346,7 +2346,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type)
 				i_data = itemdb_exists(item.nameid);
 				sprintf (message, msg_txt(541), mvp_sd->status.name, md->name, i_data->jname, temp/100.);
 				//MSG: "'%s' won %s's %s (chance: %0.02f%%)"
-				intif_GMmessage(message,strlen(message)+1,0);
+				intif_broadcast(message,strlen(message)+1,0);
 			}
 
 			if((temp = pc_additem(mvp_sd,&item,1)) != 0) {

+ 4 - 4
src/map/pc.c

@@ -3878,7 +3878,7 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, int lv)
 		i_data = itemdb_search(itemid);
 		sprintf (message, msg_txt(542), (sd->status.name != NULL)?sd->status.name :"GM", md->db->jname, i_data->jname, (float)md->db->dropitem[i].p/100);
 		//MSG: "'%s' stole %s's %s (chance: %0.02f%%)"
-		intif_GMmessage(message,strlen(message)+1,0);
+		intif_broadcast(message,strlen(message)+1,0);
 	}
 	return 1;
 }
@@ -7496,7 +7496,7 @@ int map_day_timer(int tid, unsigned int tick, int id, intptr data)
 	night_flag = 0; // 0=day, 1=night [Yor]
 	map_foreachpc(pc_daynight_timer_sub);
 	strcpy(tmp_soutput, (data == 0) ? msg_txt(502) : msg_txt(60)); // The day has arrived!
-	intif_GMmessage(tmp_soutput, strlen(tmp_soutput) + 1, 0);
+	intif_broadcast(tmp_soutput, strlen(tmp_soutput) + 1, 0);
 	return 0;
 }
 
@@ -7517,7 +7517,7 @@ int map_night_timer(int tid, unsigned int tick, int id, intptr data)
 	night_flag = 1; // 0=day, 1=night [Yor]
 	map_foreachpc(pc_daynight_timer_sub);
 	strcpy(tmp_soutput, (data == 0) ? msg_txt(503) : msg_txt(59)); // The night has fallen...
-	intif_GMmessage(tmp_soutput, strlen(tmp_soutput) + 1, 0);
+	intif_broadcast(tmp_soutput, strlen(tmp_soutput) + 1, 0);
 	return 0;
 }
 
@@ -7630,7 +7630,7 @@ int duel_invite(const unsigned int did, struct map_session_data* sd, struct map_
 	
 	// "Blue -- Player %s invites you to PVP duel (@accept/@reject) --"
 	sprintf(output, msg_txt(374), sd->status.name);
-	clif_GMmessage((struct block_list *)target_sd, output, strlen(output)+1, 3);
+	clif_broadcast((struct block_list *)target_sd, output, strlen(output)+1, 0x10, SELF);
 	return 0;
 }
 

+ 82 - 65
src/map/script.c

@@ -8091,63 +8091,77 @@ BUILDIN_FUNC(playerattached)
  *------------------------------------------*/
 BUILDIN_FUNC(announce)
 {
-	const char *str, *color=NULL;
-	int flag;
-	str=script_getstr(st,2);
-	flag=script_getnum(st,3);
-	if (script_hasdata(st,4))
-		color=script_getstr(st,4);
-
-	if(flag&0x0f){
-		struct block_list *bl=(flag&0x08)? map_id2bl(st->oid) :
-			(struct block_list *)script_rid2sd(st);
-		if( bl == NULL )
+	const char *mes       = script_getstr(st,2);
+	int         flag      = script_getnum(st,3);
+	const char *fontColor = script_hasdata(st,4) ? script_getstr(st,4) : NULL;
+	int         fontType  = script_hasdata(st,5) ? script_getnum(st,5) : 0x190; // default fontType (FW_NORMAL)
+	int         fontSize  = script_hasdata(st,6) ? script_getnum(st,6) : 12;    // default fontSize
+	int         fontAlign = script_hasdata(st,7) ? script_getnum(st,7) : 0;     // default fontAlign
+	int         fontY     = script_hasdata(st,8) ? script_getnum(st,8) : 0;     // default fontY
+	
+	if (flag&0x0f) // Broadcast source or broadcast region defined
+	{
+		send_target target;
+		struct block_list *bl = (flag&0x08) ? map_id2bl(st->oid) : (struct block_list *)script_rid2sd(st); // If bc_npc flag is set, use NPC as broadcast source
+		if (bl == NULL)
 			return 0;
-		if (color)
-			clif_announce(bl,str,(int)strlen(str)+1, strtol(color, (char **)NULL, 0),flag);
+		
+		flag &= 0x07;
+		target = (flag == 1) ? ALL_SAMEMAP :
+		         (flag == 2) ? AREA :
+		         (flag == 3) ? SELF :
+		                       ALL_CLIENT;
+		if (fontColor)
+			clif_broadcast2(bl, mes, (int)strlen(mes)+1, strtol(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY, target);
 		else
-			clif_GMmessage(bl,str,(int)strlen(str)+1,flag);
-	}else {
-		if (color)
-			intif_announce(str,(int)strlen(str)+1, strtol(color, (char **)NULL, 0), flag);
+			clif_broadcast(bl, mes, (int)strlen(mes)+1, flag&0xf0, target);
+	}
+	else
+	{
+		if (fontColor)
+			intif_broadcast2(mes, (int)strlen(mes)+1, strtol(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY);
 		else
-			intif_GMmessage(str,(int)strlen(str)+1,flag);
+			intif_broadcast(mes, (int)strlen(mes)+1, flag&0xf0);
 	}
 	return 0;
 }
 /*==========================================
  * 天の声アナウンス(特定マップ)
  *------------------------------------------*/
-static int buildin_mapannounce_sub(struct block_list *bl,va_list ap)
-{
-	char *str, *color;
-	int len,flag;
-	str=va_arg(ap,char *);
-	len=va_arg(ap,int);
-	flag=va_arg(ap,int);
-	color=va_arg(ap,char *);
-	if (color)
-		clif_announce(bl,str,len, strtol(color, (char **)NULL, 0), flag|3);
+static int buildin_announce_sub(struct block_list *bl, va_list ap)
+{
+	char *mes       = va_arg(ap, char *);
+	int   len       = va_arg(ap, int);
+	int   type      = va_arg(ap, int);
+	char *fontColor = va_arg(ap, char *);
+	short fontType  = va_arg(ap, short);
+	short fontSize  = va_arg(ap, short);
+	short fontAlign = va_arg(ap, short);
+	short fontY     = va_arg(ap, short);
+	if (fontColor)
+		clif_broadcast2(bl, mes, len, strtol(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY, SELF);
 	else
-		clif_GMmessage(bl,str,len,flag|3);
+		clif_broadcast(bl, mes, len, type, SELF);
 	return 0;
 }
+
 BUILDIN_FUNC(mapannounce)
 {
-	const char *mapname,*str, *color=NULL;
-	int flag,m;
-
-	mapname=script_getstr(st,2);
-	str=script_getstr(st,3);
-	flag=script_getnum(st,4);
-	if (script_hasdata(st,5))
-		color=script_getstr(st,5);
+	const char *mapname   = script_getstr(st,2);
+	const char *mes       = script_getstr(st,3);
+	int         flag      = script_getnum(st,4);
+	const char *fontColor = script_hasdata(st,5) ? script_getstr(st,5) : NULL;
+	int         fontType  = script_hasdata(st,6) ? script_getnum(st,6) : 0x190; // default fontType (FW_NORMAL)
+	int         fontSize  = script_hasdata(st,7) ? script_getnum(st,7) : 12;    // default fontSize
+	int         fontAlign = script_hasdata(st,8) ? script_getnum(st,8) : 0;     // default fontAlign
+	int         fontY     = script_hasdata(st,9) ? script_getnum(st,9) : 0;     // default fontY
+	int m;
 
-	if( (m=map_mapname2mapid(mapname))<0 )
+	if ((m = map_mapname2mapid(mapname)) < 0)
 		return 0;
 
-	map_foreachinmap(buildin_mapannounce_sub,
-		m, BL_PC, str,strlen(str)+1,flag&0x10, color);
+	map_foreachinmap(buildin_announce_sub, m, BL_PC,
+			mes, strlen(mes)+1, flag&0xf0, fontColor, fontType, fontSize, fontAlign, fontY);
 	return 0;
 }
 /*==========================================
@@ -8155,25 +8169,25 @@ BUILDIN_FUNC(mapannounce)
  *------------------------------------------*/
 BUILDIN_FUNC(areaannounce)
 {
-	const char *map,*str,*color=NULL;
-	int flag,m;
-	int x0,y0,x1,y1;
-
-	map=script_getstr(st,2);
-	x0=script_getnum(st,3);
-	y0=script_getnum(st,4);
-	x1=script_getnum(st,5);
-	y1=script_getnum(st,6);
-	str=script_getstr(st,7);
-	flag=script_getnum(st,8);
-	if (script_hasdata(st,9))
-		color=script_getstr(st,9);
+	const char *mapname   = script_getstr(st,2);
+	int         x0        = script_getnum(st,3);
+	int         y0        = script_getnum(st,4);
+	int         x1        = script_getnum(st,5);
+	int         y1        = script_getnum(st,6);
+	const char *mes       = script_getstr(st,7);
+	int         flag      = script_getnum(st,8);
+	const char *fontColor = script_hasdata(st,9) ? script_getstr(st,9) : NULL;
+	int         fontType  = script_hasdata(st,10) ? script_getnum(st,10) : 0x190; // default fontType (FW_NORMAL)
+	int         fontSize  = script_hasdata(st,11) ? script_getnum(st,11) : 12;    // default fontSize
+	int         fontAlign = script_hasdata(st,12) ? script_getnum(st,12) : 0;     // default fontAlign
+	int         fontY     = script_hasdata(st,13) ? script_getnum(st,13) : 0;     // default fontY
+	int m;
 
-	if( (m=map_mapname2mapid(map))<0 )
+	if ((m = map_mapname2mapid(mapname)) < 0)
 		return 0;
 
-	map_foreachinarea(buildin_mapannounce_sub,
-		m,x0,y0,x1,y1,BL_PC, str,strlen(str)+1,flag&0x10, color);
+	map_foreachinarea(buildin_announce_sub, m, x0, y0, x1, y1, BL_PC,
+		mes, strlen(mes)+1, flag&0xf0, fontColor, fontType, fontSize, fontAlign, fontY);
 	return 0;
 }
 
@@ -13894,16 +13908,18 @@ BUILDIN_FUNC(instance_init)
 
 BUILDIN_FUNC(instance_announce)
 {
-	const char *str, *color=NULL;
-	int flag,instance_id,i;
+	int         instance_id = script_getnum(st,2);
+	const char *mes         = script_getstr(st,3);
+	int         flag        = script_getnum(st,4);
+	const char *fontColor   = script_hasdata(st,5) ? script_getstr(st,5) : NULL;
+	int         fontType    = script_hasdata(st,6) ? script_getnum(st,6) : 0x190; // default fontType (FW_NORMAL)
+	int         fontSize    = script_hasdata(st,7) ? script_getnum(st,7) : 12;    // default fontSize
+	int         fontAlign   = script_hasdata(st,8) ? script_getnum(st,8) : 0;     // default fontAlign
+	int         fontY       = script_hasdata(st,9) ? script_getnum(st,9) : 0;     // default fontY
+
+	int i;
 	struct map_session_data *sd;
 	struct party_data *p;
-	
-	instance_id = script_getnum(st,2);
-	str = script_getstr(st,3);
-	flag = script_getnum(st,4);
-	if( script_hasdata(st,5) )
-		color = script_getstr(st,5);
 
 	if( instance_id == 0 )
 	{
@@ -13918,7 +13934,8 @@ BUILDIN_FUNC(instance_announce)
 		return 0;
 		
 	for( i = 0; i < instance[instance_id].num_map; i++ )
-		map_foreachinmap(buildin_mapannounce_sub, instance[instance_id].map[i], BL_PC, str, strlen(str) + 1, flag&0x10, color);
+		map_foreachinmap(buildin_announce_sub, instance[instance_id].map[i], BL_PC,
+			mes, strlen(mes)+1, flag&0xf0, fontColor, fontType, fontSize, fontAlign, fontY);
 
 	return 0;
 }