mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-16 22:58:34 +00:00
[Commands] Cleanup #object Command (#3722)
* [Commands] Cleanup #object Command # Notes - Cleanup messages and logic. - Introduce enum for object types. - Set ground work for object manipulation similar to door manipulation. * Update object_manipulation.cpp * Final push * Update client_packet.cpp * Update object_manipulation.cpp * Update object_manipulation.cpp * Update object.h * Update client_packet.cpp * Update client_packet.cpp * Push. * Update version.h * Update database_update_manifest.cpp * Update zone.cpp
This commit is contained in:
@@ -10355,6 +10355,16 @@ void Client::SetDoorToolEntityId(uint16 door_tool_entity_id)
|
||||
Client::m_door_tool_entity_id = door_tool_entity_id;
|
||||
}
|
||||
|
||||
uint16 Client::GetObjectToolEntityId() const
|
||||
{
|
||||
return m_object_tool_entity_id;
|
||||
}
|
||||
|
||||
void Client::SetObjectToolEntityId(uint16 object_tool_entity_id)
|
||||
{
|
||||
Client::m_object_tool_entity_id = object_tool_entity_id;
|
||||
}
|
||||
|
||||
int Client::GetIPExemption()
|
||||
{
|
||||
return database.GetIPExemption(GetIPString());
|
||||
|
||||
@@ -1814,9 +1814,12 @@ private:
|
||||
bool dev_tools_enabled;
|
||||
|
||||
uint16 m_door_tool_entity_id;
|
||||
uint16 m_object_tool_entity_id;
|
||||
public:
|
||||
uint16 GetDoorToolEntityId() const;
|
||||
void SetDoorToolEntityId(uint16 door_tool_entity_id);
|
||||
uint16 GetObjectToolEntityId() const;
|
||||
void SetObjectToolEntityId(uint16 object_tool_entity_id);
|
||||
private:
|
||||
|
||||
int32 max_end;
|
||||
|
||||
@@ -60,6 +60,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "../common/repositories/criteria/content_filter_criteria.h"
|
||||
#include "../common/shared_tasks.h"
|
||||
#include "gm_commands/door_manipulation.h"
|
||||
#include "gm_commands/object_manipulation.h"
|
||||
#include "client.h"
|
||||
#include "../common/repositories/account_repository.h"
|
||||
|
||||
@@ -4650,6 +4651,20 @@ void Client::Handle_OP_ClickObject(const EQApplicationPacket *app)
|
||||
std::vector<std::any> args = { object };
|
||||
parse->EventPlayer(EVENT_CLICK_OBJECT, this, std::to_string(click_object->drop_id), GetID(), &args);
|
||||
}
|
||||
|
||||
if (IsDevToolsEnabled()) {
|
||||
SetObjectToolEntityId(entity->GetID());
|
||||
ObjectManipulation::CommandHeader(this);
|
||||
Message(
|
||||
Chat::White,
|
||||
fmt::format(
|
||||
"Object ({}) [{}] [{}]",
|
||||
entity->CastToObject()->GetDBID(),
|
||||
Saylink::Silent("#object edit", "Edit"),
|
||||
Saylink::Silent("#object delete", "Delete")
|
||||
).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Observed in RoF after OP_ClickObjectAction:
|
||||
|
||||
@@ -866,6 +866,7 @@ void command_bot(Client *c, const Seperator *sep)
|
||||
#include "gm_commands/nukebuffs.cpp"
|
||||
#include "gm_commands/nukeitem.cpp"
|
||||
#include "gm_commands/object.cpp"
|
||||
#include "gm_commands/object_manipulation.cpp"
|
||||
#include "gm_commands/path.cpp"
|
||||
#include "gm_commands/peqzone.cpp"
|
||||
#include "gm_commands/petitems.cpp"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "../client.h"
|
||||
#include "door_manipulation.h"
|
||||
#include "../doors.h"
|
||||
|
||||
void command_door(Client *c, const Seperator *sep)
|
||||
{
|
||||
|
||||
+2
-1258
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,15 @@
|
||||
#ifndef EQEMU_OBJECT_MANIPULATION_H
|
||||
#define EQEMU_OBJECT_MANIPULATION_H
|
||||
|
||||
#include "../client.h"
|
||||
|
||||
class ObjectManipulation {
|
||||
|
||||
public:
|
||||
static void CommandHandler(Client *c, const Seperator *sep);
|
||||
static void CommandHeader(Client *c);
|
||||
static void SendSubcommands(Client *c);
|
||||
};
|
||||
|
||||
|
||||
#endif //EQEMU_OBJECT_MANIPULATION_H
|
||||
+25
-19
@@ -40,19 +40,24 @@ extern EntityList entity_list;
|
||||
extern WorldServer worldserver;
|
||||
|
||||
// Loading object from database
|
||||
Object::Object(uint32 id, uint32 type, uint32 icon, const Object_Struct& object, const EQ::ItemInstance* inst)
|
||||
: respawn_timer(0), decay_timer(300000)
|
||||
Object::Object(
|
||||
uint32 id,
|
||||
uint32 type,
|
||||
uint32 icon,
|
||||
const Object_Struct &object,
|
||||
const EQ::ItemInstance *inst
|
||||
) : respawn_timer(0), decay_timer(300000)
|
||||
{
|
||||
|
||||
user = nullptr;
|
||||
user = nullptr;
|
||||
last_user = nullptr;
|
||||
|
||||
// Initialize members
|
||||
m_id = id;
|
||||
m_type = type;
|
||||
m_icon = icon;
|
||||
m_inst = nullptr;
|
||||
m_ground_spawn=false;
|
||||
m_id = id;
|
||||
m_type = type;
|
||||
m_icon = icon;
|
||||
m_inst = nullptr;
|
||||
m_ground_spawn = false;
|
||||
|
||||
// Copy object data
|
||||
memcpy(&m_data, &object, sizeof(Object_Struct));
|
||||
if (inst) {
|
||||
@@ -61,13 +66,14 @@ Object::Object(uint32 id, uint32 type, uint32 icon, const Object_Struct& object,
|
||||
} else {
|
||||
decay_timer.Disable();
|
||||
}
|
||||
|
||||
respawn_timer.Disable();
|
||||
|
||||
// Set drop_id to zero - it will be set when added to zone with SetID()
|
||||
m_data.drop_id = 0;
|
||||
m_data.size = object.size;
|
||||
m_data.tilt_x = object.tilt_x;
|
||||
m_data.tilt_y = object.tilt_y;
|
||||
m_data.size = object.size;
|
||||
m_data.tilt_x = object.tilt_x;
|
||||
m_data.tilt_y = object.tilt_y;
|
||||
|
||||
FixZ();
|
||||
}
|
||||
@@ -85,7 +91,7 @@ Object::Object(const EQ::ItemInstance* inst, char* name,float max_x,float min_x,
|
||||
m_min_y=min_y;
|
||||
m_id = 0;
|
||||
m_inst = (inst) ? inst->Clone() : nullptr;
|
||||
m_type = OT_DROPPEDITEM;
|
||||
m_type = ObjectTypes::Temporary;
|
||||
m_icon = 0;
|
||||
m_ground_spawn = true;
|
||||
decay_timer.Disable();
|
||||
@@ -116,7 +122,7 @@ Object::Object(Client* client, const EQ::ItemInstance* inst)
|
||||
// Initialize members
|
||||
m_id = 0;
|
||||
m_inst = (inst) ? inst->Clone() : nullptr;
|
||||
m_type = OT_DROPPEDITEM;
|
||||
m_type = ObjectTypes::Temporary;
|
||||
m_icon = 0;
|
||||
m_ground_spawn = false;
|
||||
// Set as much struct data as we can
|
||||
@@ -179,7 +185,7 @@ Object::Object(const EQ::ItemInstance *inst, float x, float y, float z, float he
|
||||
// Initialize members
|
||||
m_id = 0;
|
||||
m_inst = (inst) ? inst->Clone() : nullptr;
|
||||
m_type = OT_DROPPEDITEM;
|
||||
m_type = ObjectTypes::Temporary;
|
||||
m_icon = 0;
|
||||
m_ground_spawn = false;
|
||||
// Set as much struct data as we can
|
||||
@@ -436,7 +442,7 @@ void Object::CreateDeSpawnPacket(EQApplicationPacket* app)
|
||||
}
|
||||
|
||||
bool Object::Process(){
|
||||
if(m_type == OT_DROPPEDITEM && decay_timer.Enabled() && decay_timer.Check()) {
|
||||
if(m_type == ObjectTypes::Temporary && decay_timer.Enabled() && decay_timer.Check()) {
|
||||
// Send click to all clients (removes entity on client)
|
||||
auto outapp = new EQApplicationPacket(OP_ClickObject, sizeof(ClickObject_Struct));
|
||||
ClickObject_Struct* click_object = (ClickObject_Struct*)outapp->pBuffer;
|
||||
@@ -497,7 +503,7 @@ bool Object::HandleClick(Client* sender, const ClickObject_Struct* click_object)
|
||||
if(m_ground_spawn) {//This is a Cool Groundspawn
|
||||
respawn_timer.Start();
|
||||
}
|
||||
if (m_type == OT_DROPPEDITEM) {
|
||||
if (m_type == ObjectTypes::Temporary) {
|
||||
bool cursordelete = false;
|
||||
bool duplicate_lore = false;
|
||||
if (m_inst && sender) {
|
||||
@@ -969,7 +975,7 @@ void Object::SetSize(float size)
|
||||
|
||||
void Object::SetSolidType(uint16 solidtype)
|
||||
{
|
||||
m_data.solidtype = solidtype;
|
||||
m_data.solid_type = solidtype;
|
||||
auto app = new EQApplicationPacket();
|
||||
auto app2 = new EQApplicationPacket();
|
||||
CreateDeSpawnPacket(app);
|
||||
@@ -987,7 +993,7 @@ float Object::GetSize()
|
||||
|
||||
uint16 Object::GetSolidType()
|
||||
{
|
||||
return m_data.solidtype;
|
||||
return m_data.solid_type;
|
||||
}
|
||||
|
||||
const char* Object::GetModelName()
|
||||
|
||||
+45
-2
@@ -73,8 +73,6 @@ IT10714_ACTORDEF=Augmentation Sealer
|
||||
IT10725_ACTORDEF=Shuriken
|
||||
*/
|
||||
|
||||
#define OT_DROPPEDITEM EQ::item::BagTypeLargeBag
|
||||
|
||||
// Icon values:
|
||||
//0x0453 a pie
|
||||
//0x0454 cookies?
|
||||
@@ -89,6 +87,51 @@ IT10725_ACTORDEF=Shuriken
|
||||
//0x045D is a hammer
|
||||
//0x045E is a wierd rope shape
|
||||
|
||||
enum ObjectTypes {
|
||||
StaticLocked = 0,
|
||||
Temporary = 1,
|
||||
ToolBox = 10,
|
||||
Research = 11,
|
||||
Mortar = 12,
|
||||
SelfDusting = 13,
|
||||
Baking1 = 14,
|
||||
Baking2 = 15,
|
||||
Tailoring = 16,
|
||||
Forge = 17,
|
||||
Fletching = 18,
|
||||
BrewBarrel = 19,
|
||||
Jewelcrafting = 20,
|
||||
PotteryWheel = 21,
|
||||
PotteryKiln = 22,
|
||||
WizardResearch = 24,
|
||||
MagicianResearch = 25,
|
||||
NecromancerResearch = 26,
|
||||
EnchanterResearch = 27,
|
||||
Invalid1 = 28,
|
||||
Invalid2 = 29,
|
||||
Experimental = 30,
|
||||
HighElfForge = 31,
|
||||
DarkElfForge = 32,
|
||||
OgreForge = 33,
|
||||
DwarfForge = 34,
|
||||
GnomeForge = 35,
|
||||
BarbarianForge = 36,
|
||||
IksarForge = 38,
|
||||
HumanForge = 39,
|
||||
HumanForge2 = 40,
|
||||
HalflingTailoring = 41,
|
||||
EruditeTailoring = 42,
|
||||
WoodElfTailoring = 43,
|
||||
WoodElfFletching = 44,
|
||||
IksarPotteryWheel = 45,
|
||||
TrollForge = 47,
|
||||
WoodElfForge = 48,
|
||||
HalflingForge = 49,
|
||||
EruditeForge = 50,
|
||||
AugmentationPool = 53,
|
||||
StaticUnlocked = 255
|
||||
};
|
||||
|
||||
class Object: public Entity
|
||||
{
|
||||
public:
|
||||
|
||||
+74
-80
@@ -56,6 +56,7 @@
|
||||
#include "zone_reload.h"
|
||||
#include "../common/repositories/criteria/content_filter_criteria.h"
|
||||
#include "../common/repositories/merchantlist_repository.h"
|
||||
#include "../common/repositories/object_repository.h"
|
||||
#include "../common/repositories/rule_sets_repository.h"
|
||||
#include "../common/serverinfo.h"
|
||||
|
||||
@@ -172,101 +173,94 @@ bool Zone::Bootup(uint32 iZoneID, uint32 iInstanceID, bool is_static) {
|
||||
//this really loads the objects into entity_list
|
||||
bool Zone::LoadZoneObjects()
|
||||
{
|
||||
std::string query = StringFormat(
|
||||
"SELECT id, zoneid, xpos, ypos, zpos, heading, itemid, charges, objectname, type, icon, "
|
||||
"unknown08, unknown10, unknown20, unknown24, unknown76, size, tilt_x, tilt_y, display_name "
|
||||
"FROM object WHERE zoneid = %i AND (version = %u OR version = -1) %s",
|
||||
zoneid,
|
||||
instanceversion,
|
||||
ContentFilterCriteria::apply().c_str()
|
||||
const auto &l = ObjectRepository::GetWhere(
|
||||
content_db,
|
||||
fmt::format(
|
||||
"zoneid = {} AND (version = {} OR version = -1) {}",
|
||||
zoneid,
|
||||
instanceversion,
|
||||
ContentFilterCriteria::apply()
|
||||
)
|
||||
);
|
||||
auto results = content_db.QueryDatabase(query);
|
||||
if (!results.Success()) {
|
||||
LogError("Error Loading Objects from DB: [{}]",
|
||||
results.ErrorMessage().c_str());
|
||||
if (l.empty()) {
|
||||
LogError("Error Loading Objects for Zone [{}] Version [{}]", zoneid, instanceversion);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto row = results.begin(); row != results.end(); ++row) {
|
||||
if (Strings::ToInt(row[9]) == 0) {
|
||||
// Type == 0 - Static Object
|
||||
const char *shortname = ZoneName(Strings::ToInt(row[1]), false); // zoneid -> zone_shortname
|
||||
for (const auto &e : l) {
|
||||
if (e.type == ObjectTypes::StaticLocked) {
|
||||
const std::string &zone_short_name = ZoneName(e.zoneid, false);
|
||||
|
||||
if (!shortname)
|
||||
if (zone_short_name.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// todo: clean up duplicate code with command_object
|
||||
auto d = DoorsRepository::NewEntity();
|
||||
|
||||
d.zone = shortname;
|
||||
d.id = 1000000000 + Strings::ToInt(row[0]); // Out of range of normal use for doors.id
|
||||
d.doorid = -1; // Client doesn't care if these are all the same door_id
|
||||
d.pos_x = Strings::ToFloat(row[2]); // xpos
|
||||
d.pos_y = Strings::ToFloat(row[3]); // ypos
|
||||
d.pos_z = Strings::ToFloat(row[4]); // zpos
|
||||
d.heading = Strings::ToFloat(row[5]); // heading
|
||||
d.zone = zone_short_name;
|
||||
d.id = 1000000000 + e.id;
|
||||
d.doorid = -1;
|
||||
d.pos_x = e.xpos;
|
||||
d.pos_y = e.ypos;
|
||||
d.pos_z = e.zpos;
|
||||
d.heading = e.heading;
|
||||
d.name = Strings::Replace(e.objectname, "_ACTORDEF", "");
|
||||
d.dest_zone = "NONE";
|
||||
d.incline = e.incline;
|
||||
d.client_version_mask = 0xFFFFFFFF;
|
||||
|
||||
d.name = row[8]; // objectname
|
||||
|
||||
// Strip trailing "_ACTORDEF" if present. Client won't accept it for doors.
|
||||
int pos = d.name.size() - strlen("_ACTORDEF");
|
||||
if (pos > 0 && d.name.compare(pos, std::string::npos, "_ACTORDEF") == 0)
|
||||
{
|
||||
d.name.erase(pos);
|
||||
}
|
||||
|
||||
d.dest_zone = "NONE";
|
||||
|
||||
if ((d.size = Strings::ToInt(row[11])) == 0) // unknown08 = optional size percentage
|
||||
if (e.size_percentage == 0) {
|
||||
d.size = 100;
|
||||
|
||||
switch (d.opentype = Strings::ToInt(row[12])) // unknown10 = optional request_nonsolid (0 or 1 or experimental number)
|
||||
{
|
||||
case 0:
|
||||
d.opentype = 31;
|
||||
break;
|
||||
case 1:
|
||||
d.opentype = 9;
|
||||
break;
|
||||
}
|
||||
|
||||
d.incline = Strings::ToInt(row[13]); // unknown20 = optional model incline value
|
||||
d.client_version_mask = 0xFFFFFFFF; // We should load the mask from the zone.
|
||||
switch (d.opentype = e.solid_type)
|
||||
{
|
||||
case 0:
|
||||
d.opentype = 31;
|
||||
break;
|
||||
case 1:
|
||||
d.opentype = 9;
|
||||
break;
|
||||
}
|
||||
|
||||
auto door = new Doors(d);
|
||||
entity_list.AddDoor(door);
|
||||
}
|
||||
|
||||
Object_Struct data = {0};
|
||||
uint32 id = 0;
|
||||
uint32 icon = 0;
|
||||
uint32 type = 0;
|
||||
uint32 itemid = 0;
|
||||
uint32 idx = 0;
|
||||
int16 charges = 0;
|
||||
Object_Struct data = {0};
|
||||
uint32 id = 0;
|
||||
uint32 icon = 0;
|
||||
uint32 type = 0;
|
||||
uint32 itemid = 0;
|
||||
uint32 idx = 0;
|
||||
int16 charges = 0;
|
||||
|
||||
id = e.id;
|
||||
|
||||
data.zone_id = e.zoneid;
|
||||
data.x = e.xpos;
|
||||
data.y = e.ypos;
|
||||
data.z = e.zpos;
|
||||
data.heading = e.heading;
|
||||
|
||||
itemid = e.itemid;
|
||||
charges = e.charges;
|
||||
type = e.type;
|
||||
icon = e.icon;
|
||||
|
||||
id = (uint32)Strings::ToInt(row[0]);
|
||||
data.zone_id = Strings::ToInt(row[1]);
|
||||
data.x = Strings::ToFloat(row[2]);
|
||||
data.y = Strings::ToFloat(row[3]);
|
||||
data.z = Strings::ToFloat(row[4]);
|
||||
data.heading = Strings::ToFloat(row[5]);
|
||||
itemid = (uint32)Strings::ToInt(row[6]);
|
||||
charges = (int16)Strings::ToInt(row[7]);
|
||||
strcpy(data.object_name, row[8]);
|
||||
type = (uint8)Strings::ToInt(row[9]);
|
||||
icon = (uint32)Strings::ToInt(row[10]);
|
||||
data.object_type = type;
|
||||
data.linked_list_addr[0] = 0;
|
||||
data.linked_list_addr[1] = 0;
|
||||
|
||||
data.solidtype = (uint32)Strings::ToInt(row[12]);
|
||||
data.unknown020 = (uint32)Strings::ToInt(row[13]);
|
||||
data.unknown024 = (uint32)Strings::ToInt(row[14]);
|
||||
data.unknown076 = (uint32)Strings::ToInt(row[15]);
|
||||
data.size = Strings::ToFloat(row[16]);
|
||||
data.tilt_x = Strings::ToFloat(row[17]);
|
||||
data.tilt_y = Strings::ToFloat(row[18]);
|
||||
strn0cpy(data.object_name, e.objectname.c_str(), sizeof(data.object_name));
|
||||
|
||||
data.solid_type = e.solid_type;
|
||||
data.incline = e.incline;
|
||||
data.unknown024 = e.unknown24;
|
||||
data.unknown076 = e.unknown76;
|
||||
data.size = e.size;
|
||||
data.tilt_x = e.tilt_x;
|
||||
data.tilt_y = e.tilt_y;
|
||||
data.unknown084 = 0;
|
||||
|
||||
|
||||
@@ -280,9 +274,8 @@ bool Zone::LoadZoneObjects()
|
||||
}
|
||||
|
||||
EQ::ItemInstance *inst = nullptr;
|
||||
// FatherNitwit: this dosent seem to work...
|
||||
// tradeskill containers do not have an itemid of 0... at least what I am seeing
|
||||
if (itemid == 0) {
|
||||
// tradeskill containers do not have an itemid of 0
|
||||
if (!itemid) {
|
||||
// Generic tradeskill container
|
||||
inst = new EQ::ItemInstance(ItemInstWorldContainer);
|
||||
} else {
|
||||
@@ -290,8 +283,7 @@ bool Zone::LoadZoneObjects()
|
||||
inst = database.CreateItem(itemid);
|
||||
}
|
||||
|
||||
// Father Nitwit's fix... not perfect...
|
||||
if (inst == nullptr && type != OT_DROPPEDITEM) {
|
||||
if (!inst && type != ObjectTypes::Temporary) {
|
||||
inst = new EQ::ItemInstance(ItemInstWorldContainer);
|
||||
}
|
||||
|
||||
@@ -301,15 +293,17 @@ bool Zone::LoadZoneObjects()
|
||||
}
|
||||
|
||||
auto object = new Object(id, type, icon, data, inst);
|
||||
object->SetDisplayName(row[19]);
|
||||
object->SetDisplayName(e.display_name.c_str());
|
||||
entity_list.AddObject(object, false);
|
||||
if (type == OT_DROPPEDITEM && itemid != 0)
|
||||
|
||||
if (type == ObjectTypes::Temporary && itemid) {
|
||||
entity_list.RemoveObject(object->GetID());
|
||||
}
|
||||
|
||||
safe_delete(inst);
|
||||
}
|
||||
|
||||
LogInfo("Loaded [{}] world objects", Strings::Commify(results.RowCount()));
|
||||
LogInfo("Loaded [{}] world objects", Strings::Commify(l.size()));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user