Explorar el Código

Adds support for object groups and titles (#5171)

* Fixes #4529.
* Adds support for applying groups and titles to non-player objects.
* Expands script command setunitdata and getunitdata to support group ID.
* Adds script commands setunittitle and getunittitle.
Co-authored-by: Lemongrass3110 <lemongrass@kstp.at>
Aleos hace 4 años
padre
commit
b13e4f0fbc
Se han modificado 7 ficheros con 196 adiciones y 44 borrados
  1. 20 0
      doc/script_commands.txt
  2. 95 41
      src/map/clif.cpp
  3. 2 3
      src/map/clif_packetdb.hpp
  4. 65 0
      src/map/script.cpp
  5. 6 0
      src/map/script.hpp
  6. 6 0
      src/map/script_constants.hpp
  7. 2 0
      src/map/unit.hpp

+ 20 - 0
doc/script_commands.txt

@@ -7977,6 +7977,20 @@ Returns "Unknown" if unit is not found.
 
 ---------------------------------------
 
+*setunittitle <GID>,<title>;
+
+Apply a <title> to the given <GID>.
+
+Note: This only works on non-player types. It also will only work on mobs if battle_config.show_mob_info is not enabled.
+
+---------------------------------------
+
+*getunittitle <GID>;
+
+Returns the title of the given <GID>.
+
+---------------------------------------
+
 *getunitdata <GID>,<arrayname>;
 *setunitdata <GID>,<parameter>,<new value>;
 
@@ -8043,6 +8057,7 @@ Parameters (indexes) for monsters are:
 	UMOB_TARGETID
 	UMOB_ROBE
 	UMOB_BODY2
+	UMOB_GROUP_ID
 
 -----
 
@@ -8087,6 +8102,7 @@ Parameter (indexes) for homunculi are:
 	UHOM_ADELAY
 	UHOM_DMOTION
 	UHOM_TARGETID
+	UHOM_GROUP_ID
 
 -----
 
@@ -8128,6 +8144,7 @@ Parameter (indexes) for pets are:
 	UPET_AMOTION
 	UPET_ADELAY
 	UPET_DMOTION
+	UPET_GROUP_ID
 
 -----
 
@@ -8169,6 +8186,7 @@ Parameter (indexes) for mercenaries are:
 	UMER_ADELAY
 	UMER_DMOTION
 	UMER_TARGETID
+	UMER_GROUP_ID
 
 -----
 
@@ -8212,6 +8230,7 @@ Parameter (indexes) for elementals are:
 	UELE_ADELAY
 	UELE_DMOTION
 	UELE_TARGETID
+	UELE_GROUP_ID
 
 -----
 
@@ -8261,6 +8280,7 @@ Parameter (indexes) for NPCs are:
 	UNPC_ROBE
 	UNPC_BODY2
 	UNPC_DEADSIT
+	UNPC_GROUP_ID
 
 *Notes:
 		- *_SIZE: small (0); medium (1); large (2)

+ 95 - 41
src/map/clif.cpp

@@ -9644,15 +9644,14 @@ void clif_name( struct block_list* src, struct block_list *bl, send_target targe
 	nullpo_retv( src );
 	nullpo_retv( bl );
 
-	struct PACKET_ZC_ACK_REQNAMEALL packet = { 0 };
-
-	packet.packet_id = HEADER_ZC_ACK_REQNAMEALL;
-	packet.gid = bl->id;
-
 	switch( bl->type ){
 		case BL_PC: {
-			struct map_session_data *sd = (struct map_session_data *)bl;
-			struct party_data *p = NULL;
+			PACKET_ZC_ACK_REQNAMEALL packet = { 0 };
+
+			packet.packet_id = HEADER_ZC_ACK_REQNAMEALL;
+			packet.gid = bl->id;
+
+			map_session_data *sd = (map_session_data *)bl;
 
 			//Requesting your own "shadow" name. [Skotlex]
 			if( src == bl && target == SELF && sd->disguise ){
@@ -9661,11 +9660,14 @@ void clif_name( struct block_list* src, struct block_list *bl, send_target targe
 
 			if( sd->fakename[0] ) {
 				safestrncpy( packet.name, sd->fakename, NAME_LENGTH );
-				break;
+				clif_send( &packet, sizeof(packet), src, target );
+				return;
 			}
 
 			safestrncpy( packet.name, sd->status.name, NAME_LENGTH );
 
+			party_data *p;
+
 			if( sd->status.party_id ){
 				p = party_search( sd->status.party_id );
 			}
@@ -9690,30 +9692,71 @@ void clif_name( struct block_list* src, struct block_list *bl, send_target targe
 #if PACKETVER_MAIN_NUM >= 20150225 || PACKETVER_RE_NUM >= 20141126 || defined( PACKETVER_ZERO )
 			packet.title_id = sd->status.title_id; // Title ID
 #endif
+
+			clif_send(&packet, sizeof(packet), src, target);
 		}
-		break;
-	//[blackhole89]
-	case BL_HOM:
-		safestrncpy( packet.name, ((TBL_HOM*)bl)->homunculus.name, NAME_LENGTH );
-		break;
-	case BL_MER:
-		safestrncpy( packet.name, ((TBL_MER*)bl)->db->name, NAME_LENGTH );
-		break;
-	case BL_PET:
-		safestrncpy( packet.name, ((TBL_PET*)bl)->pet.name, NAME_LENGTH );
-		break;
-	case BL_NPC:
-		safestrncpy( packet.name, ((TBL_NPC*)bl)->name, NAME_LENGTH );
-		break;
-	case BL_MOB: {
-			struct mob_data *md = (struct mob_data *)bl;
+			break;
+		//[blackhole89]
+		case BL_HOM:
+		case BL_MER:
+		case BL_PET:
+		case BL_NPC:
+		case BL_ELEM: {
+			PACKET_ZC_ACK_REQNAME_TITLE packet = { 0 };
+
+			packet.packet_id = HEADER_ZC_ACK_REQNAME_TITLE;
+			packet.gid = bl->id;
+
+			switch (bl->type) {
+				case BL_HOM:
+					memcpy(packet.name, ((TBL_HOM *)bl)->homunculus.name, NAME_LENGTH);
+					break;
+				case BL_MER:
+					memcpy(packet.name, ((TBL_MER *)bl)->db->name, NAME_LENGTH);
+					break;
+				case BL_PET:
+					safestrncpy(packet.name, ((TBL_PET *)bl)->pet.name, NAME_LENGTH);
+					break;
+				case BL_NPC:
+					safestrncpy(packet.name, ((TBL_NPC *)bl)->name, NAME_LENGTH);
+					break;
+				case BL_ELEM:
+					safestrncpy(packet.name, ((TBL_ELEM *)bl)->db->name, NAME_LENGTH);
+					break;
+			}
 
-			safestrncpy( packet.name, md->name, NAME_LENGTH );
+#if PACKETVER_MAIN_NUM >= 20180207 || PACKETVER_RE_NUM >= 20171129 || PACKETVER_ZERO_NUM >= 20171130
+			unit_data *ud = unit_bl2ud(bl);
+
+			if (ud != nullptr) {
+				memcpy(packet.title, ud->title, NAME_LENGTH);
+				packet.groupId = ud->group_id;
+			}
+#endif
+
+			clif_send(&packet, sizeof(packet), src, target);
+		}
+			break;
+		case BL_MOB: {
+			mob_data *md = (mob_data *)bl;
 
 			if( md->guardian_data && md->guardian_data->guild_id ){
+				PACKET_ZC_ACK_REQNAMEALL packet = { 0 };
+
+				packet.packet_id = HEADER_ZC_ACK_REQNAMEALL;
+				packet.gid = bl->id;
+				safestrncpy( packet.name, md->name, NAME_LENGTH );
 				safestrncpy( packet.guild_name, md->guardian_data->guild_name, NAME_LENGTH );
 				safestrncpy( packet.position_name, md->guardian_data->castle->castle_name, NAME_LENGTH );
+
+				clif_send(&packet, sizeof(packet), src, target);
 			}else if( battle_config.show_mob_info ){
+				PACKET_ZC_ACK_REQNAMEALL packet = { 0 };
+
+				packet.packet_id = HEADER_ZC_ACK_REQNAMEALL;
+				packet.gid = bl->id;
+				safestrncpy( packet.name, md->name, NAME_LENGTH );
+
 				char mobhp[50], *str_p = mobhp;
 
 				if( battle_config.show_mob_info&4 ){
@@ -9733,25 +9776,36 @@ void clif_name( struct block_list* src, struct block_list *bl, send_target targe
 					*(str_p-3) = '\0'; //Remove trailing space + pipe.
 					safestrncpy( packet.party_name, mobhp, NAME_LENGTH );
 				}
+
+				clif_send(&packet, sizeof(packet), src, target);
+			} else {
+				PACKET_ZC_ACK_REQNAME_TITLE packet = { 0 };
+
+				packet.packet_id = HEADER_ZC_ACK_REQNAME_TITLE;
+				packet.gid = bl->id;
+				safestrncpy(packet.name, md->name, NAME_LENGTH);
+
+#if PACKETVER_MAIN_NUM >= 20180207 || PACKETVER_RE_NUM >= 20171129 || PACKETVER_ZERO_NUM >= 20171130
+				unit_data *ud = unit_bl2ud(bl);
+
+				if (ud != nullptr) {
+					memcpy(packet.title, ud->title, NAME_LENGTH);
+					packet.groupId = ud->group_id;
+				}
+#endif
+
+				clif_send(&packet, sizeof(packet), src, target);
 			}
 		}
-		break;
-	case BL_CHAT:	//FIXME: Clients DO request this... what should be done about it? The chat's title may not fit... [Skotlex]
-//		safestrncpy(WBUFP(buf,6), (struct chat*)->title, NAME_LENGTH);
-//		break;
-		return;
-	case BL_ELEM:
-		safestrncpy( packet.name, ((TBL_ELEM*)bl)->db->name, NAME_LENGTH );
-		break;
-	case BL_SKILL:
-		// Newer clients request this, but do not need an answer
-		return;
-	default:
-		ShowError("clif_name: bad type %d(%d)\n", bl->type, bl->id);
-		return;
+			break;
+		case BL_CHAT:
+		case BL_SKILL:
+			// Newer clients request this, but do not need an answer
+			return;
+		default:
+			ShowError("clif_name: bad type %d(%d)\n", bl->type, bl->id);
+			return;
 	}
-
-	clif_send( &packet, sizeof( packet ), src, target );
 }
 
 /// Taekwon Jump (TK_HIGHJUMP) effect (ZC_HIGHJUMP).

+ 2 - 3
src/map/clif_packetdb.hpp

@@ -59,7 +59,7 @@
 	packet(0x0092,28);
 	packet(0x0093,2);
 	parseable_packet(0x0094,6,clif_parse_GetCharNameRequest,2);
-	packet(0x0095,30);
+	packet( HEADER_ZC_ACK_REQNAME_TITLE, sizeof( PACKET_ZC_ACK_REQNAME_TITLE ) );
 	parseable_packet(0x0096,-1,clif_parse_WisMessage,2,4,28);
 	packet(0x0097,-1);
 	packet(0x0098,3);
@@ -315,7 +315,7 @@
 	packet(0x0192,24);
 	parseable_packet(0x0193,6,clif_parse_SolveCharName,2);
 	packet(0x0194,30);
-	packet(0x0195,102);
+	packet( HEADER_ZC_ACK_REQNAMEALL, sizeof( struct PACKET_ZC_ACK_REQNAMEALL ) );
 	packet(0x0196,9);
 	parseable_packet(0x0197,4,clif_parse_ResetChar,2);
 	parseable_packet(0x0198,8,clif_parse_GMChangeMapType,2,4,6);
@@ -2294,7 +2294,6 @@
 	// Title System
 	parseable_packet(0x0A2E,6,clif_parse_change_title,0); // CZ_REQ_CHANGE_TITLE
 	packet(0x0A2F,7); // ZC_ACK_CHANGE_TITLE
-	packet(0x0A30,106); // ZC_ACK_REQNAMEALL2
 
 	// Quest UI
 	packet(0x08FE,-1); // ZC_HUNTING_QUEST_INFO

+ 65 - 0
src/map/script.cpp

@@ -17786,6 +17786,7 @@ BUILDIN_FUNC(getunitdata)
 			getunitdata_sub(UMOB_TARGETID, md->target_id);
 			getunitdata_sub(UMOB_ROBE, md->vd->robe);
 			getunitdata_sub(UMOB_BODY2, md->vd->body_style);
+			getunitdata_sub(UMOB_GROUP_ID, md->ud.group_id);
 			break;
 
 		case BL_HOM:
@@ -17833,6 +17834,7 @@ BUILDIN_FUNC(getunitdata)
 			getunitdata_sub(UHOM_ADELAY, hd->battle_status.adelay);
 			getunitdata_sub(UHOM_DMOTION, hd->battle_status.dmotion);
 			getunitdata_sub(UHOM_TARGETID, hd->ud.target);
+			getunitdata_sub(UHOM_GROUP_ID, hd->ud.group_id);
 			break;
 
 		case BL_PET:
@@ -17877,6 +17879,7 @@ BUILDIN_FUNC(getunitdata)
 			getunitdata_sub(UPET_AMOTION, pd->status.amotion);
 			getunitdata_sub(UPET_ADELAY, pd->status.adelay);
 			getunitdata_sub(UPET_DMOTION, pd->status.dmotion);
+			getunitdata_sub(UPET_GROUP_ID, pd->ud.group_id);
 			break;
 
 		case BL_MER:
@@ -17921,6 +17924,7 @@ BUILDIN_FUNC(getunitdata)
 			getunitdata_sub(UMER_ADELAY, mc->base_status.adelay);
 			getunitdata_sub(UMER_DMOTION, mc->base_status.dmotion);
 			getunitdata_sub(UMER_TARGETID, mc->ud.target);
+			getunitdata_sub(UMER_GROUP_ID, mc->ud.group_id);
 			break;
 
 		case BL_ELEM:
@@ -17967,6 +17971,7 @@ BUILDIN_FUNC(getunitdata)
 			getunitdata_sub(UELE_ADELAY, ed->base_status.adelay);
 			getunitdata_sub(UELE_DMOTION, ed->base_status.dmotion);
 			getunitdata_sub(UELE_TARGETID, ed->ud.target);
+			getunitdata_sub(UELE_GROUP_ID, ed->ud.group_id);
 			break;
 
 		case BL_NPC:
@@ -18019,6 +18024,7 @@ BUILDIN_FUNC(getunitdata)
 			getunitdata_sub(UNPC_ROBE, nd->vd.robe);
 			getunitdata_sub(UNPC_BODY2, nd->vd.body_style);
 			getunitdata_sub(UNPC_DEADSIT, nd->vd.dead_sit);
+			getunitdata_sub(UNPC_GROUP_ID, nd->ud.group_id);
 			break;
 
 		default:
@@ -18180,6 +18186,7 @@ BUILDIN_FUNC(setunitdata)
 			}
 			case UMOB_ROBE: clif_changelook(bl, LOOK_ROBE, (unsigned short)value); break;
 			case UMOB_BODY2: clif_changelook(bl, LOOK_BODY2, (unsigned short)value); break;
+			case UMOB_GROUP_ID: md->ud.group_id = value; unit_refresh(bl); break;
 			default:
 				ShowError("buildin_setunitdata: Unknown data identifier %d for BL_MOB.\n", type);
 				return SCRIPT_CMD_FAILURE;
@@ -18242,6 +18249,7 @@ BUILDIN_FUNC(setunitdata)
 				unit_attack(&hd->bl, target->id, 1);
 				break;
 			}
+			case UHOM_GROUP_ID: hd->ud.group_id = value; unit_refresh(bl); break;
 			default:
 				ShowError("buildin_setunitdata: Unknown data identifier %d for BL_HOM.\n", type);
 				return SCRIPT_CMD_FAILURE;
@@ -18293,6 +18301,7 @@ BUILDIN_FUNC(setunitdata)
 			case UPET_AMOTION: pd->status.amotion = (short)value; break;
 			case UPET_ADELAY: pd->status.adelay = (short)value; break;
 			case UPET_DMOTION: pd->status.dmotion = (short)value; break;
+			case UPET_GROUP_ID: pd->ud.group_id = value; unit_refresh(bl); break;
 			default:
 				ShowError("buildin_setunitdata: Unknown data identifier %d for BL_PET.\n", type);
 				return SCRIPT_CMD_FAILURE;
@@ -18350,6 +18359,7 @@ BUILDIN_FUNC(setunitdata)
 				unit_attack(&mc->bl, target->id, 1);
 				break;
 			}
+			case UMER_GROUP_ID: mc->ud.group_id = value; unit_refresh(bl); break;
 			default:
 				ShowError("buildin_setunitdata: Unknown data identifier %d for BL_MER.\n", type);
 				return SCRIPT_CMD_FAILURE;
@@ -18412,6 +18422,7 @@ BUILDIN_FUNC(setunitdata)
 				unit_attack(&ed->bl, target->id, 1);
 				break;
 			}
+			case UELE_GROUP_ID: ed->ud.group_id = value; unit_refresh(bl); break;
 			default:
 				ShowError("buildin_setunitdata: Unknown data identifier %d for BL_ELEM.\n", type);
 				return SCRIPT_CMD_FAILURE;
@@ -18470,6 +18481,7 @@ BUILDIN_FUNC(setunitdata)
 			case UNPC_ROBE: clif_changelook(bl, LOOK_ROBE, (unsigned short)value); break;
 			case UNPC_BODY2: clif_changelook(bl, LOOK_BODY2, (unsigned short)value); break;
 			case UNPC_DEADSIT: nd->vd.dead_sit = (char)value; unit_refresh(bl); break;
+			case UNPC_GROUP_ID: nd->ud.group_id = value; unit_refresh(bl); break;
 			default:
 				ShowError("buildin_setunitdata: Unknown data identifier %d for BL_NPC.\n", type);
 				return SCRIPT_CMD_FAILURE;
@@ -18578,6 +18590,57 @@ BUILDIN_FUNC(setunitname)
 	return SCRIPT_CMD_SUCCESS;
 }
 
+/**
+ * Sets a unit's title.
+ * setunittitle <GID>,<title>;
+ */
+BUILDIN_FUNC(setunittitle)
+{
+	int gid = script_getnum(st, 2);
+	block_list *bl = map_id2bl(gid);
+
+	if (bl == nullptr) {
+		ShowWarning("buildin_setunittitle: Unable to find object with given game ID %d!\n", gid);
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	unit_data *ud = unit_bl2ud(bl);
+
+	if (ud == nullptr) {
+		ShowWarning("buildin_setunittitle: Unable to find unit_data for given game ID %d!\n", gid);
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	safestrncpy(ud->title, script_getstr(st, 3), NAME_LENGTH);
+	clif_name_area(bl);
+	return SCRIPT_CMD_SUCCESS;
+}
+
+/**
+ * Gets a unit's title.
+ * getunittitle <GID>;
+ */
+BUILDIN_FUNC(getunittitle)
+{
+	int gid = script_getnum(st, 2);
+	block_list *bl = map_id2bl(gid);
+
+	if (bl == nullptr) {
+		ShowWarning("buildin_getunittitle: Unable to find object with given game ID %d!\n", gid);
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	unit_data *ud = unit_bl2ud(bl);
+
+	if (ud == nullptr) {
+		ShowWarning("buildin_getunittitle: Unable to find unit_data for given game ID %d!\n", gid);
+		return SCRIPT_CMD_FAILURE;
+	}
+
+	script_pushstrcopy(st, ud->title);
+	return SCRIPT_CMD_SUCCESS;
+}
+
 /// Makes the unit walk to target position or map.
 /// Returns if it was successful.
 ///
@@ -25118,6 +25181,8 @@ struct script_function buildin_func[] = {
 	BUILDIN_DEF(getunittype,"i"),
 	BUILDIN_DEF(getunitname,"i"),
 	BUILDIN_DEF(setunitname,"is"),
+	BUILDIN_DEF(setunittitle,"is"),
+	BUILDIN_DEF(getunittitle,"i"),
 	BUILDIN_DEF(getunitdata,"i*"),
 	BUILDIN_DEF(setunitdata,"iii"),
 	BUILDIN_DEF(unitwalk,"iii?"),

+ 6 - 0
src/map/script.hpp

@@ -478,6 +478,7 @@ enum unitdata_mobtypes {
 	UMOB_TARGETID,
 	UMOB_ROBE,
 	UMOB_BODY2,
+	UMOB_GROUP_ID,
 };
 
 enum unitdata_homuntypes {
@@ -521,6 +522,7 @@ enum unitdata_homuntypes {
 	UHOM_ADELAY,
 	UHOM_DMOTION,
 	UHOM_TARGETID,
+	UHOM_GROUP_ID,
 };
 
 enum unitdata_pettypes {
@@ -561,6 +563,7 @@ enum unitdata_pettypes {
 	UPET_AMOTION,
 	UPET_ADELAY,
 	UPET_DMOTION,
+	UPET_GROUP_ID,
 };
 
 enum unitdata_merctypes {
@@ -601,6 +604,7 @@ enum unitdata_merctypes {
 	UMER_ADELAY,
 	UMER_DMOTION,
 	UMER_TARGETID,
+	UMER_GROUP_ID,
 };
 
 enum unitdata_elemtypes {
@@ -643,6 +647,7 @@ enum unitdata_elemtypes {
 	UELE_ADELAY,
 	UELE_DMOTION,
 	UELE_TARGETID,
+	UELE_GROUP_ID,
 };
 
 enum unitdata_npctypes {
@@ -691,6 +696,7 @@ enum unitdata_npctypes {
 	UNPC_ROBE,
 	UNPC_BODY2,
 	UNPC_DEADSIT,
+	UNPC_GROUP_ID,
 };
 
 enum navigation_service {

+ 6 - 0
src/map/script_constants.hpp

@@ -4147,6 +4147,7 @@
 	export_constant(UMOB_TARGETID);
 	export_constant(UMOB_ROBE);
 	export_constant(UMOB_BODY2);
+	export_constant(UMOB_GROUP_ID);
 
 	/* unit control - homunculus */
 	export_constant(UHOM_SIZE);
@@ -4189,6 +4190,7 @@
 	export_constant(UHOM_ADELAY);
 	export_constant(UHOM_DMOTION);
 	export_constant(UHOM_TARGETID);
+	export_constant(UHOM_GROUP_ID);
 
 	/* unit control - pet */
 	export_constant(UPET_SIZE);
@@ -4228,6 +4230,7 @@
 	export_constant(UPET_AMOTION);
 	export_constant(UPET_ADELAY);
 	export_constant(UPET_DMOTION);
+	export_constant(UPET_GROUP_ID);
 
 	/* unit control - mercenary */
 	export_constant(UMER_SIZE);
@@ -4267,6 +4270,7 @@
 	export_constant(UMER_ADELAY);
 	export_constant(UMER_DMOTION);
 	export_constant(UMER_TARGETID);
+	export_constant(UMER_GROUP_ID);
 
 	/* unit control - elemental */
 	export_constant(UELE_SIZE);
@@ -4308,6 +4312,7 @@
 	export_constant(UELE_ADELAY);
 	export_constant(UELE_DMOTION);
 	export_constant(UELE_TARGETID);
+	export_constant(UELE_GROUP_ID);
 
 	/* unit control - NPC */
 	export_deprecated_constant3("UNPC_DISPLAY", UNPC_CLASS, "UNPC_CLASS");
@@ -4356,6 +4361,7 @@
 	export_constant(UNPC_ROBE);
 	export_constant(UNPC_BODY2);
 	export_constant(UNPC_DEADSIT);
+	export_constant(UNPC_GROUP_ID);
 
 	export_constant(NAV_NONE);
 	export_constant(NAV_AIRSHIP_ONLY);

+ 2 - 0
src/map/unit.hpp

@@ -59,6 +59,8 @@ struct unit_data {
 		unsigned blockedskill : 1;
 	} state;
 	char walk_done_event[EVENT_NAME_LENGTH];
+	char title[NAME_LENGTH];
+	int32 group_id;
 };
 
 struct view_data {