PDA

View Full Version : Dyanmic Object Spawning


Deimos
01-21-2009, 12:38 AM
It'd be nice to be able to spawn an object (like a campfire) via perl and have it render immediately.

I was looking at this code:

// Add new Zone Object (theoretically only called for items dropped to ground)
uint32 ZoneDatabase::AddObject(uint32 type, uint32 icon, const Object_Struct& object, const ItemInst* inst)


Line 481-482 in object.cpp
The actual function is below it

I'm planning to make it myself, but it'd be nice to get some help with it since I'm not very familiar with the eqemu source ^^.

Richardo
01-21-2009, 11:19 AM
I would actually love to see this. To anyone able to help, I think it would be greatly appreciated! :)

AndMetal
01-21-2009, 05:33 PM
It appears the AddObject (http://code.google.com/p/projecteqemu/source/browse/trunk/EQEmuServer/zone/Object.cpp#482) function basically adds the object into the database (the object table specifically), not necessarily spawning it:

zone/Object.cpp (http://code.google.com/p/projecteqemu/source/browse/trunk/EQEmuServer/zone/Object.cpp#481)

// Add new Zone Object (theoretically only called for items dropped to ground)
uint32 ZoneDatabase::AddObject(uint32 type, uint32 icon, const Object_Struct& object, const ItemInst* inst)
{
char errbuf[MYSQL_ERRMSG_SIZE];
char* query = 0;

uint32 database_id = 0;
uint32 item_id = 0;
sint8 charges = 0;

if (inst && inst->GetItem()) {
item_id = inst->GetItem()->ID;
charges = inst->GetCharges();
}

// SQL Escape object_name
uint32 len = strlen(object.object_name) * 2 + 1;
char* object_name = new char[len];
DoEscapeString(object_name, object.object_name, strlen(object.object_name));

// Construct query
uint32 len_query = MakeAnyLenString(&query,
"insert into object (zoneid, xpos, ypos, zpos, heading, itemid, charges, objectname, "
"type, icon) values (%i, %f, %f, %f, %f, %i, %i, '%s', %i, %i)",
object.zone_id, object.x, object.y, object.z, object.heading,
item_id, charges, object_name, type, icon);

// Save new record for object
if (!RunQuery(query, len_query, errbuf, NULL, NULL, &database_id)) {
LogFile->write(EQEMuLog::Error, "Unable to insert object: %s", errbuf);
}
else {
// Save container contents, if container
if (inst && inst->IsType(ItemClassContainer)) {
SaveWorldContainer(object.zone_id, database_id, inst);
}
}

safe_delete_array(object_name);
safe_delete_array(query);
return database_id;
}


KLS made a question function to allow items to be dropped via quest back in SVN Rev 126 (http://code.google.com/p/projecteqemu/source/detail?r=126):

changelog.txt (http://code.google.com/p/projecteqemu/source/browse/trunk/EQEmuServer/changelog.txt?r=126)

==10/21/2008
KLS: Some changes to make compiling with profiler enabled more error free.
KLS: Added player quest event EVENT_TASK_STAGE_COMPLETE exports $task_id and $activity_id.
KLS: Added player quest event EVENT_PICK_UP exports $picked_up_id for when a player picks up a ground spawn or dropped item.
KLS: Added quest::CreateGroundObject(itemid, x, y, z, heading) which lets the quest script create ground objects in the zone like if they had been dropped.
KLS: Objects should decay after they're loaded back into the world. Might want to backup your objects table till I can confirm this works 100%.
KLS: Lowered ground object decay time from 30 min to 5 min.

From the Wiki (http://www.eqemulator.net/wiki/wikka.php?wakka=QuestTutorial):
quest::creategroundobject(itemid, x, y, z, heading, decaytime) - Creates a ground spawn object/item.

However, I'm not sure if it can be used to create something that can't be picked up (campfire). Then again, are campfires even handled server side? If anything, I think they may be handled in the *_EnvironmentEmitters.txt files.

Deimos
01-21-2009, 06:02 PM
As I said, I'm not actually too familiar with the eqemu source code, but I know it can be done. One person's done it and because of the fact that items can be rendered upon dropping, objects should be able to be rendered as well.

Actually, he may have done them as doors? That's what I had from one person.

Hm... I wonder if doors are immediately rendered.

And if it was a door... could create scripts for it as well.

Oh well, : )... I'll look into the matter as well as some other matters. I got quite a bit on my plate atm : P.

Derision
01-21-2009, 06:02 PM
I had a quick look at this earlier. At least in qeytoqrg, campfires are 'doors':


mysql> select id, doorid, name from doors where zone='qeytoqrg';
+------+--------+----------+
| id | doorid | name |
+------+--------+----------+
| 2089 | 1 | SHAK |
| 2090 | 2 | SHAK |
| 2091 | 3 | SHAK |
| 2088 | 4 | DOOR1 |
| 2087 | 5 | CAMPFIRE |
| 2086 | 6 | TORCH1 |
| 2085 | 7 | BARREL3 |
| 2084 | 8 | CAMPFIRE |
| 2083 | 9 | TORCH1 |
| 2082 | 10 | BARREL3 |
| 2081 | 11 | CAMPFIRE |
| 2080 | 12 | TORCH1 |
| 2079 | 13 | BARREL3 |
+------+--------+----------+
13 rows in set (0.01 sec)

Deimos
01-21-2009, 07:05 PM
Well, I looked into spawning items on the ground and changing the models and what not works for dynamic object spawning, but as you said, they can be picked up and I'm unsure of how to make it so they can't be picked up : \.

Another issue with them is that they have an expiration timer. This can be used advantageously though if an expiration timer of 0 means the object will stay alive until it is removed.

Now, for getting the thing to work as quickly as possible, I think the click events for the items need to be investigated to see about making an item spawn that can't be selected (isn't added to the click event), but once again, if this is defined client side and the server is simply syncing with the client, then object spawning via items is a 100% dead end and other methods have to be looked into.

If it isn't, then the modifications shouldn't take more than 20-40 minutes for someone who knows what they're doing.

^_-

Secrets
01-22-2009, 06:50 AM
I'm not sure how to find these other than looking at packet collected logs, but I am almost certain world objects can be spawned as containers; aza77 did this ages ago in paradigma, making campfires that could be summoned and stored in your inventory with a spell effect (see the spells code in zone)

I looked up an old OLD OLD (but relevant) post on this;

http://www.eqemulator.net/forums/showthread.php?t=3870&highlight=campfire

and then I looked at this command:

quest::CreateGroundObject(itemid, x, y, z, heading) which lets the quest script create ground objects in the zone like if they had been dropped.

now, make an item with a weapon model ID of IT78, spawn the campfire on the ground with quest::CreateGroundObject or even make it droppable and drop it yourself, and you have yourself a portable campfire. Now, objects can obviously be told to do a lot more than this; they can store items (see: tradeskill containers) act as doors (I think?) etc, and you could expand upon the quest command CreateGroundObject to even store the entry in objects and place it on the entitylist instantly rather than having to zone out for a door to take effect (meaning dynamic containers theoretically)

also, expand upon this and you could have people storing items in their temporary boxes you could place on the ground. i'll mess with the code when I have time, i'm personally intrigued by this :p

Secrets
01-22-2009, 07:36 AM
The victim:

http://img407.imageshack.us/img407/5431/fiyahlk4.jpg

Place it on the ground and...

http://img212.imageshack.us/img212/499/fiyah1zl8.jpg

Pick it up and it goes back into the inventory. Portable campfires for all!

SQL, uses item ID 999:

INSERT INTO items
(`id`, `minstatus`, `Name`, `aagi`, `ac`, `accuracy`, `acha`, `adex`, `aint`, `artifactflag`, `asta`, `astr`, `attack`, `augrestrict`, `augslot1type`, `augslot1unk`, `augslot2type`, `augslot2unk`, `augslot3type`, `augslot3unk`, `augslot4type`, `augslot4unk`, `augslot5type`, `augslot5unk`, `augtype`, `avoidance`, `awis`, `bagsize`, `bagslots`, `bagtype`, `bagwr`, `banedmgamt`, `banedmgraceamt`, `banedmgbody`, `banedmgrace`, `bardtype`, `bardvalue`, `book`, `casttime`, `casttime_`, `charmfile`, `charmfileid`, `classes`, `color`, `combateffects`, `extradmgskill`, `extradmgamt`, `price`, `cr`, `damage`, `damageshield`, `deity`, `delay`, `augdistiller`, `dotshielding`, `dr`, `clicktype`, `clicklevel2`, `elemdmgtype`, `elemdmgamt`, `endur`, `factionamt1`, `factionamt2`, `factionamt3`, `factionamt4`, `factionmod1`, `factionmod2`, `factionmod3`, `factionmod4`, `filename`, `focuseffect`, `fr`, `fvnodrop`, `haste`, `clicklevel`, `hp`, `regen`, `icon`, `idfile`, `itemclass`, `itemtype`, `ldonprice`, `ldontheme`, `ldonsold`, `light`, `lore`, `loregroup`, `magic`, `mana`, `manaregen`, `enduranceregen`, `material`, `maxcharges`, `mr`, `nodrop`, `norent`, `pendingloreflag`, `pr`, `procrate`, `races`, `range`, `reclevel`, `recskill`, `reqlevel`, `sellrate`, `shielding`, `size`, `skillmodtype`, `skillmodvalue`, `slots`, `clickeffect`, `spellshield`, `strikethrough`, `stunresist`, `summonedflag`, `tradeskills`, `favor`, `weight`, `unknown002`, `unknown003`, `unknown005`, `unknown007`, `unknown018`, `unknown019`, `unknown020`, `UNK012`, `UNK013`, `benefitflag`, `unknown061`, `UNK054`, `unknown067`, `unknown069`, `UNK059`, `UNK061`, `unknown081`, `unknown105`, `booktype`, `unknown122`, `unknown123`, `unknown124`, `recastdelay`, `recasttype`, `guildfavor`, `unknown128`, `UNK123`, `UNK124`, `attuneable`, `nopet`, `unknown133`, `updated`, `comment`, `UNK127`, `pointtype`, `potionbelt`, `potionbeltslots`, `stacksize`, `notransfer`, `stackable`, `UNK134`, `UNK137`, `proceffect`, `proctype`, `proclevel2`, `proclevel`, `UNK142`, `worneffect`, `worntype`, `wornlevel2`, `wornlevel`, `UNK147`, `focustype`, `focuslevel2`, `focuslevel`, `UNK152`, `scrolleffect`, `scrolltype`, `scrolllevel2`, `scrolllevel`, `UNK157`, `serialized`, `verified`, `serialization`, `source`, `UNK033`, `lorefile`, `UNK014`, `svcorruption`, `UNK038`, `UNK060`, `augslot1unk2`, `augslot2unk2`, `augslot3unk2`, `augslot4unk2`, `augslot5unk2`, `UNK098`, `UNK109`, `UNK120`, `UNK121`, `questitemflag`, `UNK131`, `UNK132`, `clickunk5`, `clickunk6`, `clickunk7`, `procunk1`, `procunk2`, `procunk3`, `procunk4`, `procunk6`, `procunk7`, `wornunk1`, `wornunk2`, `wornunk3`, `wornunk4`, `wornunk5`, `wornunk6`, `wornunk7`, `focusunk1`, `focusunk2`, `focusunk3`, `focusunk4`, `focusunk5`, `focusunk6`, `focusunk7`, `scrollunk1`, `scrollunk2`, `scrollunk3`, `scrollunk4`, `scrollunk5`, `scrollunk6`, `scrollunk7`, `UNK193`, `purity`, `evolvinglevel`, `UNK129`)
VALUES
(999, 0, 'Campfire of Doom', 0, 0, 0, 0, 0, 0, '0', 0, 0, 0, 0, 0, '1', 0, '1', 0, '1', 0, '1', 0, '1', 0, 0, 0, 4, 10, 1, 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', '0', 65535, 4278190080, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', -1, 0, 0, 0, 0, 0, 0, 1103, 'IT78', 0, 1, 0, 0, '0', 0, 'Full Muffin Crate', -1, '0', 0, 0, 0, 0, -1, 0, 0, 255, 0, 0, 0, 32767, 0, 0, 0, 0, 1111, 0, '3', 255, 0, 0, -1, 0, 0, 0, 0, 0, 0, 30, '0', '0', '0', '0', '0', '0', '0', '0', '1', 0, '0', '0', '0', '0', '0', '0', '0', '0', 0, '0', '0', '0', 0, -1, 0, '0', '0', '0', '0', '0', '0', "10/21/2007 07:59:29", '', '0', 0, '0', '0', 20, '0', '0', '', '0', -1, '0', 0, 0, '0', -1, '0', 0, 0, '0', '0', 0, 0, '0', -1, '0', 0, 0, '0', "0/0/0000 00:00:00", "3/2/2006 15:27:54", '', '13THFLOOR', '0', '', 0, 0, '0', '0', '0', '0', '0', '0', '0', '0', '0', -1, '0', '0', '0', '0', '0', '', 0, '0', '0', '0', '0', '', '0', 0, '0', '0', '0', '0', '', '0', 0, 0, '0', '0', '0', '', '0', '0', '0', '0', '0', '0', '', '0', 0, 0, 0, 0);



I didn't bother making it a container, but I bet you could make it one and store items in it, drop it, and have someone come along and take your campfire, put more items in it, etc.

This works with all objects that have a model file, too. Imagine actual portable tradeskill stations, you could make a quest command to depop and repop the item and you could use it as a tradeskill station, when you are done trigger the quest again and put the tradeskill item back on the cursor. I would like to see this done if not for eqemulator functionality, but if for something like EQBots unique to show the limits of the client.

of course i'm kind of lost at the coding part of that...

but hey, I can dream can't I? :p

edited: forgot SQL.

Deimos
01-22-2009, 04:17 PM
The problem we were discussing is making it so that it can't be picked up.

Deimos
02-12-2009, 06:00 PM
So... anyone make any progress on this yet? : p

Oogbar
09-22-2010, 03:47 AM
Hehe, a terrible thought... A Door shield... and if you click on it, while wearing it, the door opens, and instead of it counting in the deflection bonus while blocking (when closed), the attack that is blocked or parried has no damage reduced, because the door is open. XD