* -Exported additional entity IDs for dropped items to perl upon EVENT_CLICK_OBJECT (clicker_id) and EVENT_PLAYER_PICKUP ($picked_up_entity_id)

-Identified Size / SolidType fields in newer clients and properly exported it to EQEmu for use in UF, RoF, RoF2 via perl accessors. (Should work in LUA, no testing was done though for LUA)
-Added a sanity check for size to objects. Any size over 5000.f seems to crash the newer clients' graphical engines and PEQ has some containers filled in with bogus values.
-Added the ability to return a value on perl function EVENT_PLAYER_PICKUP which sends a fake dropped item ID to the client to generate the appropriate client response so the item can stay on the ground and not be 'picked up'. Should also work in LUA, didn't test LUA.
-Renamed unknown008 and unknown010 to size and solidtype respectively for objects.
This commit is contained in:
SecretsOTheP 2015-05-06 18:50:08 -04:00
parent 690274338d
commit 4a4a0c5e8b
8 changed files with 54 additions and 37 deletions

View File

@ -975,8 +975,8 @@ namespace RoF
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Same for all objects in the zone VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Same for all objects in the zone
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->heading); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->heading);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Normally 0, but seen (float)255.0 as well VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Normally 0, but seen (float)255.0 as well
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Unknown VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->solidtype); // Unknown
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 1); // Need to add emu->size to struct VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt.
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->z); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->z);

View File

@ -1046,8 +1046,8 @@ namespace RoF2
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Same for all objects in the zone VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Same for all objects in the zone
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->heading); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->heading);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Normally 0, but seen (float)255.0 as well VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Normally 0, but seen (float)255.0 as well
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 0); // Unknown VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->solidtype); // Unknown
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, 1); // Need to add emu->size to struct VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt.
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->z); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->z);

View File

@ -857,8 +857,8 @@ namespace UF
// field to be set to (float)255.0 to appear at all, and also the size field below to be 5, to be the correct size. I think SoD has the same // field to be set to (float)255.0 to appear at all, and also the size field below to be 5, to be the correct size. I think SoD has the same
// issue. // issue.
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0);
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // Unknown, observed 0 VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, emu->solidtype); // Unknown, observed 0
VARSTRUCT_ENCODE_TYPE(uint32, OutBuffer, 0); // This appears to be the size field. VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->size != 0 && (float)emu->size < 5000.f ? (float)((float)emu->size / 100.0f) : 1.f ); // This appears to be the size field. Hackish logic because some PEQ DB items were corrupt.
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->y);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->x);
VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->z); VARSTRUCT_ENCODE_TYPE(float, OutBuffer, emu->z);

View File

@ -4126,7 +4126,7 @@ void Client::Handle_OP_ClickObject(const EQApplicationPacket *app)
char buf[10]; char buf[10];
snprintf(buf, 9, "%u", click_object->drop_id); snprintf(buf, 9, "%u", click_object->drop_id);
buf[9] = '\0'; buf[9] = '\0';
parse->EventPlayer(EVENT_CLICK_OBJECT, this, buf, 0, &args); parse->EventPlayer(EVENT_CLICK_OBJECT, this, buf, GetID(), &args);
} }
// Observed in RoF after OP_ClickObjectAction: // Observed in RoF after OP_ClickObjectAction:

View File

@ -8549,20 +8549,20 @@ void command_object(Client *c, const Seperator *sep)
od.object_type = atoi(row[7]); od.object_type = atoi(row[7]);
icon = atoi(row[8]); icon = atoi(row[8]);
od.unknown008 = atoi(row[9]); od.size = atoi(row[9]);
od.unknown010 = atoi(row[10]); od.solidtype = atoi(row[10]);
od.unknown020 = atoi(row[11]); od.unknown020 = atoi(row[11]);
switch (od.object_type) { switch (od.object_type) {
case 0: // Static Object case 0: // Static Object
case staticType: // Static Object unlocked for changes case staticType: // Static Object unlocked for changes
if (od.unknown008 == 0) // Unknown08 field is optional Size parameter for static objects if (od.size == 0) // Unknown08 field is optional Size parameter for static objects
od.unknown008 = 100; // Static object default Size is 100% od.size = 100; // Static object default Size is 100%
c->Message(0, "- STATIC Object (%s): id %u, x %.1f, y %.1f, z %.1f, h %.1f, model %s, " c->Message(0, "- STATIC Object (%s): id %u, x %.1f, y %.1f, z %.1f, h %.1f, model %s, "
"size %u, solidtype %u, incline %u", "size %u, solidtype %u, incline %u",
(od.object_type == 0) ? "locked" : "unlocked", id, od.x, od.y, od.z, (od.object_type == 0) ? "locked" : "unlocked", id, od.x, od.y, od.z,
od.heading, od.object_name, od.unknown008, od.unknown010, od.unknown020); od.heading, od.object_name, od.size, od.solidtype, od.unknown020);
break; break;
case OT_DROPPEDITEM: // Ground Spawn case OT_DROPPEDITEM: // Ground Spawn
@ -8620,10 +8620,10 @@ void command_object(Client *c, const Seperator *sep)
switch (od.object_type) { switch (od.object_type) {
case 0: // Static Object case 0: // Static Object
if ((sep->argnum - col) > 3) { if ((sep->argnum - col) > 3) {
od.unknown008 = atoi(sep->arg[4 + col]); // Size specified od.size = atoi(sep->arg[4 + col]); // Size specified
if ((sep->argnum - col) > 4) { if ((sep->argnum - col) > 4) {
od.unknown010 = atoi(sep->arg[5 + col]); // SolidType specified od.solidtype = atoi(sep->arg[5 + col]); // SolidType specified
if ((sep->argnum - col) > 5) if ((sep->argnum - col) > 5)
od.unknown020 = atoi(sep->arg[6 + col]); // Incline specified od.unknown020 = atoi(sep->arg[6 + col]); // Incline specified
@ -8922,16 +8922,16 @@ void command_object(Client *c, const Seperator *sep)
return; return;
} }
od.unknown008 = atoi(sep->arg[4]); od.size = atoi(sep->arg[4]);
o->SetObjectData(&od); o->SetObjectData(&od);
if (od.unknown008 == 0) // 0 == unspecified == 100% if (od.size == 0) // 0 == unspecified == 100%
od.unknown008 = 100; od.size = 100;
c->Message(0, "Static Object %u set to %u%% size. Size will take effect when you commit to the " c->Message(0, "Static Object %u set to %u%% size. Size will take effect when you commit to the "
"database with '#object Save', after which the object will be unchangeable until " "database with '#object Save', after which the object will be unchangeable until "
"you unlock it again with '#object Edit' and zone out and back in.", "you unlock it again with '#object Edit' and zone out and back in.",
id, od.unknown008); id, od.size);
} else if (strcmp(sep->arg[3], "solidtype") == 0) { } else if (strcmp(sep->arg[3], "solidtype") == 0) {
if (od.object_type != staticType) { if (od.object_type != staticType) {
@ -8946,13 +8946,13 @@ void command_object(Client *c, const Seperator *sep)
return; return;
} }
od.unknown010 = atoi(sep->arg[4]); od.solidtype = atoi(sep->arg[4]);
o->SetObjectData(&od); o->SetObjectData(&od);
c->Message(0, "Static Object %u set to SolidType %u. Change will take effect when you commit " c->Message(0, "Static Object %u set to SolidType %u. Change will take effect when you commit "
"to the database with '#object Save'. Support for this property is on a " "to the database with '#object Save'. Support for this property is on a "
"per-model basis, mostly seen in smaller objects such as chests and tables.", "per-model basis, mostly seen in smaller objects such as chests and tables.",
id, od.unknown010); id, od.solidtype);
} else if (strcmp(sep->arg[3], "icon") == 0) { } else if (strcmp(sep->arg[3], "icon") == 0) {
if ((od.object_type < 2) || (od.object_type == staticType)) { if ((od.object_type < 2) || (od.object_type == staticType)) {
@ -9239,24 +9239,24 @@ void command_object(Client *c, const Seperator *sep)
"unknown08 = %u, unknown10 = %u, unknown20 = %u " "unknown08 = %u, unknown10 = %u, unknown20 = %u "
"WHERE ID = %u", "WHERE ID = %u",
zone->GetZoneID(), zone->GetInstanceVersion(), od.x, od.y, od.z, zone->GetZoneID(), zone->GetInstanceVersion(), od.x, od.y, od.z,
od.heading, od.object_name, od.object_type, icon, od.unknown008, od.heading, od.object_name, od.object_type, icon, od.size,
od.unknown010, od.unknown020, id); od.solidtype, od.unknown020, id);
else if (id == 0) else if (id == 0)
query = StringFormat("INSERT INTO object " query = StringFormat("INSERT INTO object "
"(zoneid, version, xpos, ypos, zpos, heading, objectname, " "(zoneid, version, xpos, ypos, zpos, heading, objectname, "
"type, icon, unknown08, unknown10, unknown20) " "type, icon, unknown08, unknown10, unknown20) "
"VALUES (%u, %u, %.1f, %.1f, %.1f, %.1f, '%s', %u, %u, %u, %u, %u)", "VALUES (%u, %u, %.1f, %.1f, %.1f, %.1f, '%s', %u, %u, %u, %u, %u)",
zone->GetZoneID(), zone->GetInstanceVersion(), od.x, od.y, od.z, zone->GetZoneID(), zone->GetInstanceVersion(), od.x, od.y, od.z,
od.heading, od.object_name, od.object_type, icon, od.unknown008, od.heading, od.object_name, od.object_type, icon, od.size,
od.unknown010, od.unknown020); od.solidtype, od.unknown020);
else else
query = StringFormat("INSERT INTO object " query = StringFormat("INSERT INTO object "
"(id, zoneid, version, xpos, ypos, zpos, heading, objectname, " "(id, zoneid, version, xpos, ypos, zpos, heading, objectname, "
"type, icon, unknown08, unknown10, unknown20) " "type, icon, unknown08, unknown10, unknown20) "
"VALUES (%u, %u, %u, %.1f, %.1f, %.1f, %.1f, '%s', %u, %u, %u, %u, %u)", "VALUES (%u, %u, %u, %.1f, %.1f, %.1f, %.1f, '%s', %u, %u, %u, %u, %u)",
id, zone->GetZoneID(), zone->GetInstanceVersion(), od.x, od.y, od.z, id, zone->GetZoneID(), zone->GetInstanceVersion(), od.x, od.y, od.z,
od.heading, od.object_name, od.object_type, icon, od.unknown008, od.heading, od.object_name, od.object_type, icon, od.size,
od.unknown010, od.unknown020); od.solidtype, od.unknown020);
results = database.QueryDatabase(query); results = database.QueryDatabase(query);
if (!results.Success()) { if (!results.Success()) {
@ -9314,12 +9314,12 @@ void command_object(Client *c, const Seperator *sep)
memcpy(door.dest_zone, "NONE", 5); memcpy(door.dest_zone, "NONE", 5);
if ((door.size = od.unknown008) == 0) // unknown08 = optional size percentage if ((door.size = od.size) == 0) // unknown08 = optional size percentage
door.size = 100; door.size = 100;
switch ( switch (
door.opentype = door.opentype =
od.unknown010) // unknown10 = optional request_nonsolid (0 or 1 or experimental number) od.solidtype) // unknown10 = optional request_nonsolid (0 or 1 or experimental number)
{ {
case 0: case 0:
door.opentype = 31; door.opentype = 31;
@ -9576,8 +9576,8 @@ void command_object(Client *c, const Seperator *sep)
strn0cpy(od.object_name, row[4], sizeof(od.object_name)); strn0cpy(od.object_name, row[4], sizeof(od.object_name));
od.object_type = atoi(row[5]); od.object_type = atoi(row[5]);
icon = atoi(row[6]); icon = atoi(row[6]);
od.unknown008 = atoi(row[7]); od.size = atoi(row[7]);
od.unknown010 = atoi(row[8]); od.solidtype = atoi(row[8]);
od.unknown020 = atoi(row[9]); od.unknown020 = atoi(row[9]);
if (od.object_type == 0) if (od.object_type == 0)

View File

@ -1277,6 +1277,7 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID
case EVENT_PLAYER_PICKUP:{ case EVENT_PLAYER_PICKUP:{
ExportVar(package_name.c_str(), "picked_up_id", data); ExportVar(package_name.c_str(), "picked_up_id", data);
ExportVar(package_name.c_str(), "picked_up_entity_id", extradata);
break; break;
} }
@ -1367,6 +1368,7 @@ void PerlembParser::ExportEventVariables(std::string &package_name, QuestEventID
case EVENT_CLICK_OBJECT: { case EVENT_CLICK_OBJECT: {
ExportVar(package_name.c_str(), "objectid", data); ExportVar(package_name.c_str(), "objectid", data);
ExportVar(package_name.c_str(), "clicker_id", extradata);
break; break;
} }

View File

@ -485,7 +485,22 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object)
buf[9] = '\0'; buf[9] = '\0';
std::vector<EQEmu::Any> args; std::vector<EQEmu::Any> args;
args.push_back(m_inst); args.push_back(m_inst);
parse->EventPlayer(EVENT_PLAYER_PICKUP, sender, buf, 0, &args); if(parse->EventPlayer(EVENT_PLAYER_PICKUP, sender, buf, this->GetID(), &args))
{
EQApplicationPacket* outapp = new EQApplicationPacket(OP_ClickObject, sizeof(ClickObject_Struct));
memcpy(outapp->pBuffer, click_object, sizeof(ClickObject_Struct));
ClickObject_Struct* co = (ClickObject_Struct*)outapp->pBuffer;
co->drop_id = 0;
entity_list.QueueClients(nullptr, outapp, false);
safe_delete(outapp);
// No longer using a tradeskill object
sender->SetTradeskillObject(nullptr);
user = nullptr;
return true;
}
// Transfer item to client // Transfer item to client
sender->PutItemInInventory(MainCursor, *m_inst, false); sender->PutItemInInventory(MainCursor, *m_inst, false);
@ -809,7 +824,7 @@ void Object::SetModelName(const char* modelname)
void Object::SetSize(uint16 size) void Object::SetSize(uint16 size)
{ {
m_data.unknown008 = size; m_data.size = size;
EQApplicationPacket* app = new EQApplicationPacket(); EQApplicationPacket* app = new EQApplicationPacket();
EQApplicationPacket* app2 = new EQApplicationPacket(); EQApplicationPacket* app2 = new EQApplicationPacket();
this->CreateDeSpawnPacket(app); this->CreateDeSpawnPacket(app);
@ -822,7 +837,7 @@ void Object::SetSize(uint16 size)
void Object::SetSolidType(uint16 solidtype) void Object::SetSolidType(uint16 solidtype)
{ {
m_data.unknown010 = solidtype; m_data.solidtype = solidtype;
EQApplicationPacket* app = new EQApplicationPacket(); EQApplicationPacket* app = new EQApplicationPacket();
EQApplicationPacket* app2 = new EQApplicationPacket(); EQApplicationPacket* app2 = new EQApplicationPacket();
this->CreateDeSpawnPacket(app); this->CreateDeSpawnPacket(app);
@ -835,12 +850,12 @@ void Object::SetSolidType(uint16 solidtype)
uint16 Object::GetSize() uint16 Object::GetSize()
{ {
return m_data.unknown008; return m_data.size;
} }
uint16 Object::GetSolidType() uint16 Object::GetSolidType()
{ {
return m_data.unknown010; return m_data.solidtype;
} }
const char* Object::GetModelName() const char* Object::GetModelName()

View File

@ -241,8 +241,8 @@ bool Zone::LoadZoneObjects() {
data.object_type = type; data.object_type = type;
data.linked_list_addr[0] = 0; data.linked_list_addr[0] = 0;
data.linked_list_addr[1] = 0; data.linked_list_addr[1] = 0;
data.unknown008 = (uint32)atoi(row[11]); data.size = (uint32)atoi(row[11]);
data.unknown010 = (uint32)atoi(row[12]); data.solidtype = (uint32)atoi(row[12]);
data.unknown020 = (uint32)atoi(row[13]); data.unknown020 = (uint32)atoi(row[13]);
data.unknown024 = (uint32)atoi(row[14]); data.unknown024 = (uint32)atoi(row[14]);
data.unknown076 = (uint32)atoi(row[15]); data.unknown076 = (uint32)atoi(row[15]);