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>
This commit is contained in:
Aleos 2020-07-03 13:25:17 -04:00 committed by GitHub
parent 92a3c3abc4
commit b13e4f0fbc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 197 additions and 45 deletions

View File

@ -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)

View File

@ -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
}
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;
safestrncpy( packet.name, md->name, NAME_LENGTH );
clif_send(&packet, sizeof(packet), src, target);
}
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;
}
#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).

View File

@ -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

View File

@ -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?"),

View File

@ -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 {

View File

@ -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);

View File

@ -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 {