Modcraft - The community dedicated to quality WoW modding!

Wrath of the Lich King Modding => Miscellaneous => Topic started by: jar0fair on July 29, 2015, 10:24:52 pm

Title: [Question] Items that spawn temporary objects.
Post by: jar0fair on July 29, 2015, 10:24:52 pm
Greetings,

I am hoping that I might find some advice on getting a system working which would allow our players to use items in their bags to spawn temporary objects. I currently have a lua script which can add the objects well enough. But, what I can’t figure out how to do, is to give the player the ability to remove the object by using the item again. At the moment, it just spawns another object. While I’m at it, I would also like to ensure that the item will only allow one instance of the object to be spawned at any given time. The main issue I see is that once the item is spawned, it is temporary, so it does not have a GUID, and thus, I can’t target it for removal.

If anyone has any ideas on how to make this work, I would really appreciate the input.

Thanks.
Title: Re: [Question] Items that spawn temporary objects.
Post by: Rochet2 on July 29, 2015, 10:38:29 pm
What core / lua engine are you using?
On trinitycore all objects have a guid - however Im unsure if you can use it to get the object.
In any case when spawing an object the spawn function usually returns a reference to the object.
This reference could be used to identify and maybe access the object later on.

However such access is dangerous without guaranteeing the object still exists (dangling pointer).
A grid search with checking the guid might be a better way if needing access after time has passed.

Can you post what you have already?
Title: Re: [Question] Items that spawn temporary objects.
Post by: jar0fair on July 29, 2015, 10:54:47 pm
To answer your first question I am running An Eluna Trinity core, and I know your name, Rochet, I'm using some of your systems. Thank for those, btw. The code I am using  basically spawns a temporary object when it's corresponding Item is used, where the player stands.  When the player logs off, the object disappears. It's pretty simple at the moment and lacks the capabilities I mentioned in my op.

Code: [Select]
-- Cauldron
local CauldronItem = 200001
local CauldronObj = 186472
-- Chair
local ChairItem = 200002
local ChairObj = 186732
-- bed
local BedItem = 200003
local BedObj = 13948
-- vendor tent
local VendortentItem = 200004
local VendortentObj = 4000668

local function SpawnObj(plr, entry, despawn_time)
plr:SummonGameObject(entry, plr:GetX(), plr:GetY(), plr:GetZ(), plr:GetO(), despawn_time)
end

local function Cauldron(event, plr, item, target)
SpawnObj(plr, CauldronObj, 0)
end

local function Chair(event, plr, item, target)
SpawnObj(plr, ChairObj, 0)
end

local function Bed(event, plr, item, target)
SpawnObj(plr, BedObj, 5)
end

local function VendorTent(event, plr, item, target)
SpawnObj(plr, VendortentObj, 0)
end

RegisterItemEvent(CauldronItem, 2, Cauldron)
RegisterItemEvent(ChairItem, 2, Chair)
RegisterItemEvent(BedItem, 2, Bed)
RegisterItemEvent(vendortentItem, 2, VendorTent)

The idea here is that this script could grow as I add more objects to the list.

In a perfect world, what I want it to do, is what the temporary spawning in "Go Move" does, only to remove the object, you would simply use the item once more.
Title: Re: [Question] Items that spawn temporary objects.
Post by: Rochet2 on July 30, 2015, 12:14:18 am
GOMove is just stabbing the existing systems.
The temporary object guids are hacked into the system so that the high part is used as the spawn ID even if that is not intended. The objects are saved to some gameobject storage system used by spells.
Would probably code it a bit differently on the spell storage part now..

Yeah, tested and you should be able to use the guid:

Code: [Select]
local x,y,z,o = plr:GetLocation()
local tar = plr:SpawnCreature( 36, x, y, z, o )
-- save guid somewhere, I save it to global variable GUIDL, but then again this is just an example code
GUIDL = tar:GetGUID()

-- Later access the creature by the saved guid:
local creature = plr:GetMap():GetWorldObject( GUIDL )
creature:SendUnitSay("asd", 0)

ps. even though I wrote this for creaturem same code works with gameobjects except gameobjects cant say stuff :P
Title: Re: [Question] Items that spawn temporary objects.
Post by: jar0fair on July 30, 2015, 01:01:42 am
Thanks, so I tried to integrate your code in a way that made sense to me. But, It isn't working. I'm sorry if I'm retarded. Please don't hit me.

Code: [Select]
-- Cauldron
local CauldronItem = 200001
local CauldronObj = 186472
-- Chair
local ChairItem = 200002
local ChairObj = 186732
-- bed
local BedItem = 200003
local BedObj = 13948
-- vendor tent
local VendortentItem = 200004
local VendortentObj = 4000668
local GUIDL = 0

local function SpawnObj(plr, entry, despawn_time)
tar = plr:SummonGameObject(entry, plr:GetX(), plr:GetY(), plr:GetZ(), plr:GetO(), despawn_time)
GUIDL = tar:GetGUID()

end

local function Cauldron(event, plr, item, target)
if GUIDL:IsInWorld() == "IsInWorld" then
GUIDL:RemoveFromWorld( deleteFromDB )
else SpawnObj(plr, CauldronObj, 0 )
end

end

local function Chair(event, plr, item, target)
SpawnObj(plr, ChairObj, 0)
end

local function Bed(event, plr, item, target)
SpawnObj(plr, BedObj, 5)
end

local function VendorTent(event, plr, item, target)
SpawnObj(plr, VendortentObj, 0)
end


RegisterItemEvent(CauldronItem, 2, Cauldron)
RegisterItemEvent(ChairItem, 2, Chair)
RegisterItemEvent(BedItem, 2, Bed)
RegisterItemEvent(VendortentItem, 2, VendorTent)
Title: Re: [Question] Items that spawn temporary objects.
Post by: Kaev on July 30, 2015, 10:53:00 am
Didn't test it, but i think you can get the logic out of it. :)

Code: [Select]
-- Cauldron
local CauldronItem = 200001
local CauldronObj = 186472
-- Chair
local ChairItem = 200002
local ChairObj = 186732
-- bed
local BedItem = 200003
local BedObj = 13948
-- vendor tent
local VendortentItem = 200004
local VendortentObj = 4000668

local GUIDL

local function SpawnObj(plr, entry, despawn_time)
   if GUIDL then
      local spawnedGobject = plr:GetMap():GetWorldObject(GUIDL)
      if spawnedGobject then
         spawnedGobject:RemoveFromWorld(true)
         GUIDL = nil
      end
   else
      local gobject = plr:SummonGameObject(entry, plr:GetX(), plr:GetY(), plr:GetZ(), plr:GetO(), despawn_time)
      GUIDL = gobject:GetGUID()
   end
end

local function Cauldron(event, plr, item, target)
   SpawnObj(plr, CauldronObj, 0)
end

local function Chair(event, plr, item, target)
   SpawnObj(plr, ChairObj, 0)
end

local function Bed(event, plr, item, target)
   SpawnObj(plr, BedObj, 5)
end

local function VendorTent(event, plr, item, target)
   SpawnObj(plr, VendortentObj, 0)
end

RegisterItemEvent(CauldronItem, 2, Cauldron)
RegisterItemEvent(ChairItem, 2, Chair)
RegisterItemEvent(BedItem, 2, Bed)
RegisterItemEvent(vendortentItem, 2, VendorTent)
Title: Re: [Question] Items that spawn temporary objects.
Post by: jar0fair on July 30, 2015, 01:31:45 pm
Wow 10/10, thanks. This works, and the objects despawn on teh second use. But, are you ready for the next issue? If I spawn the chair, and then someone else has the chair item, and they try to spawn one, it de-spawns mine. I'm wondering if there is a way to have the code function differently for each player.
Title: Re: [Question] Items that spawn temporary objects.
Post by: Kaev on July 30, 2015, 02:39:56 pm
Quote from: "jar0fair"
Wow 10/10, thanks. This works, and the objects despawn on teh second use. But, are you ready for the next issue? If I spawn the chair, and then someone else has the chair item, and they try to spawn one, it de-spawns mine. I'm wondering if there is a way to have the code function differently for each player.
Create a table and use it like this:
gameobjectlist[playerguid] = gobject:GetGUID()

If you can't do it with that hint, just tell us and we'll show you. :)
(This is better for learning purposes instead of spoon feeding you :P)
Title: Re: [Question] Items that spawn temporary objects.
Post by: Rochet2 on July 30, 2015, 02:49:41 pm
Like Kaev said you should look into using a lua table.

Getting this stuff to work is not so stright forward though. You need to think about special cases.

For example if you try to fetch an object that is on another map it will return nil
If you try to fetch an object that is in an unloaded grid of the map you are on it will return nil

So that said, you can make it so that spawning an object on a map will block you from spawning on other maps or on same map until you successfully delete the already spawned object.
Or you block spawning from same map but allow spawning on other maps.
Or you allow spawning as long as the already spawned object is not within set distance of the player or similar.
Title: Re: [Question] Items that spawn temporary objects.
Post by: jar0fair on July 31, 2015, 01:33:43 am
Quote from: "Kaev"
Quote from: "jar0fair"
Wow 10/10, thanks. This works, and the objects despawn on teh second use. But, are you ready for the next issue? If I spawn the chair, and then someone else has the chair item, and they try to spawn one, it de-spawns mine. I'm wondering if there is a way to have the code function differently for each player.
Create a table and use it like this:
gameobjectlist[playerguid] = gobject:GetGUID()

If you can't do it with that hint, just tell us and we'll show you. :)
(This is better for learning purposes instead of spoon feeding you :P)

Thank you, I really am trying to learn how to do this stuff myself but, I am pretty new yet. Getting pretty frustrated with myself for not being able to figure it out. I've seen how to structure a table once or twice, but I don't think I am doing it right. This is what I did.

Code: [Select]

local spawns = {
GUIDL
owner = unit
}



local function SpawnObj(plr, entry, despawn_time)

   if spawns[2] then

      local spawnedGobject = plr:GetMap():GetWorldObject(GUIDL)

      if spawnedGobject then

         spawnedGobject:RemoveFromWorld(true)

spawns = {         
GUIDL = nil
owner = unit
}

      end

   else

      local gobject = plr:SummonGameObject(entry, plr:GetX(), plr:GetY(), plr:GetZ(), plr:GetO(), despawn_time)

      spawns = {
GUIDL = gobject:GetGUID()
owner = unit
}

   end

end
Title: Re: [Question] Items that spawn temporary objects.
Post by: Kaev on July 31, 2015, 07:52:26 am
Quote from: "jar0fair"
Quote from: "Kaev"
Quote from: "jar0fair"
Wow 10/10, thanks. This works, and the objects despawn on teh second use. But, are you ready for the next issue? If I spawn the chair, and then someone else has the chair item, and they try to spawn one, it de-spawns mine. I'm wondering if there is a way to have the code function differently for each player.
Create a table and use it like this:
gameobjectlist[playerguid] = gobject:GetGUID()

If you can't do it with that hint, just tell us and we'll show you. :)
(This is better for learning purposes instead of spoon feeding you :P)

Thank you, I really am trying to learn how to do this stuff myself but, I am pretty new yet. Getting pretty frustrated with myself for not being able to figure it out. I've seen how to structure a table once or twice, but I don't think I am doing it right. This is what I did.

Code: [Select]

local spawns = {
GUIDL
owner = unit
}



local function SpawnObj(plr, entry, despawn_time)

   if spawns[2] then

      local spawnedGobject = plr:GetMap():GetWorldObject(GUIDL)

      if spawnedGobject then

         spawnedGobject:RemoveFromWorld(true)

spawns = {         
GUIDL = nil
owner = unit
}

      end

   else

      local gobject = plr:SummonGameObject(entry, plr:GetX(), plr:GetY(), plr:GetZ(), plr:GetO(), despawn_time)

      spawns = {
GUIDL = gobject:GetGUID()
owner = unit
}

   end

end

You're doing it wrong.
You can create a table like this:
Code: [Select]
local table = {}
and now you can access the table like
Code: [Select]
table[123] = "foo"
table["bar"] = 234
table[2] = 12345

and get the value like
Code: [Select]
local tablevalue = table[123] -- this will return "foo"
local tablevalue2 = table["bar"] -- this will return 234
local tablevalue3 = table[2] -- this will return 12345

You can find more about tables here: http://lua-users.org/wiki/TablesTutorial (http://lua-users.org/wiki/TablesTutorial" onclick="window.open(this.href);return false;)

A small example how you could use it
Code: [Select]
table[plr:GetGUID()] = gobject:GetGUID() -- now you can access the GUID of the object via the GUID of the player
Title: Re: [Question] Items that spawn temporary objects.
Post by: jar0fair on July 31, 2015, 02:30:59 pm
Code: [Select]
local spawn = {}

local function SpawnObj(plr, entry, despawn_time)
   if spawn then
      local spawnedGobject = plr:GetMap():GetWorldObject(spawn[plr:GetGUID()])
      if spawnedGobject then
         spawnedGobject:RemoveFromWorld(true)
         spawn[plr:GetGUID()] = nil
      end
   else
      local gobject = plr:SummonGameObject(entry, plr:GetX(), plr:GetY(), plr:GetZ(), plr:GetO(), despawn_time)
      spawn[plr:GetGUID()] = gobject:GetGUID()
   end
end

Thanks, that actually helped, and I've redone what I had before. I feel like I am getting really close but, I still can't get it to function. I've tried several different ways and invariably I am getting an error, when I use any of the items in game,  in the following line:

local spawnedGobject = plr:GetMap():GetWorldObject(spawn[plr:GetGUID()])

"bad argument #1 to "GetWorldObject' (bad argument : unsigned long long expected, got nil)
Title: Re: [Question] Items that spawn temporary objects.
Post by: Rochet2 on July 31, 2015, 04:38:34 pm
This is because in your code you check
Code: [Select]
if spawn thenBut spawn is always defined. The check is useless.
The code inside the IF statement is run and it errors because the value for the key plr:GetGUID() is nil in the spawn table.

What you should check instead is
Code: [Select]
if spawn[plr:GetGUID()] then
Title: Re: [Question] Items that spawn temporary objects.
Post by: jar0fair on July 31, 2015, 11:54:03 pm
Quote from: "Rochet2"
This is because in your code you check
Code: [Select]
if spawn thenBut spawn is always defined. The check is useless.
The code inside the IF statement is run and it errors because the value for the key plr:GetGUID() is nil in the spawn table.

What you should check instead is
Code: [Select]
if spawn[plr:GetGUID()] then

Thanks, I appreciate everyone's help But...This just isn't working. The code now spawns the object, but it's back to the original state.  It spawns unlimited amounts and does not despawn, even though the code tells it to. I am not sure what I am missing.

Code: [Select]
-- Cauldron
local CauldronItem = 200001
local CauldronObj = 186472
-- Chair
local ChairItem = 200002
local ChairObj = 186732
-- bed
local BedItem = 200003
local BedObj = 13948
-- vendor tent
local VendortentItem = 200004
local VendortentObj = 4000668

local spawn = {}

local function SpawnObj(plr, entry, despawn_time)
   if spawn[plr:GetGUID()] then

         spawn[plr:GetGUID()]:RemoveFromWorld(true)
         spawn[plr:GetGUID()] = nil
   else
      gobject = plr:SummonGameObject(entry, plr:GetX(), plr:GetY(), plr:GetZ(), plr:GetO(), despawn_time)
      spawn[plr:GetGUID()] = gobject:GetGUID()
   end
end

local function Cauldron(event, plr, item, target)
   SpawnObj(plr, CauldronObj, 0)
end

local function Chair(event, plr, item, target)
   SpawnObj(plr, ChairObj, 0)
end

local function Bed(event, plr, item, target)
   SpawnObj(plr, BedObj, 5)
end

local function VendorTent(event, plr, item, target)
   SpawnObj(plr, VendortentObj, 0)
end

RegisterItemEvent(CauldronItem, 2, Cauldron)
RegisterItemEvent(ChairItem, 2, Chair)
RegisterItemEvent(BedItem, 2, Bed)
RegisterItemEvent(VendortentItem, 2, VendorTent)
Title: Re: [Question] Items that spawn temporary objects.
Post by: Rochet2 on August 01, 2015, 12:08:47 am
Try this. I basically just added back in the GetWorldObject you removed.

Code: [Select]
-- Cauldron
local CauldronItem = 200001
local CauldronObj = 186472
-- Chair
local ChairItem = 200002
local ChairObj = 186732
-- bed
local BedItem = 200003
local BedObj = 13948
-- vendor tent
local VendortentItem = 200004
local VendortentObj = 4000668

local spawn = {}

local function SpawnObj(plr, entry, despawn_time)
    local guid = plr:GetGUID()
    if spawn[guid] then
        local spawnedGobject = plr:GetMap():GetWorldObject(spawn[guid])
        if spawnedGobject then
            spawnedGobject:RemoveFromWorld(true)
            spawn[guid] = nil
        else
            plr:SendNotification("You need to be closer to the existing object to despawn it")
        end
    else
        local x, y, z, o = plr:GetLocation()
        local gobject = plr:SummonGameObject(entry, x, y, z, o, despawn_time)
        if gobject then
            spawn[guid] = gobject:GetGUID()
        end
    end
end

local function Cauldron(event, plr, item, target)
    SpawnObj(plr, CauldronObj, 0)
end

local function Chair(event, plr, item, target)
    SpawnObj(plr, ChairObj, 0)
end

local function Bed(event, plr, item, target)
    SpawnObj(plr, BedObj, 5)
end

local function VendorTent(event, plr, item, target)
    SpawnObj(plr, VendortentObj, 0)
end

RegisterItemEvent(CauldronItem, 2, Cauldron)
RegisterItemEvent(ChairItem, 2, Chair)
RegisterItemEvent(BedItem, 2, Bed)
RegisterItemEvent(VendortentItem, 2, VendorTent)
Title: Re: [Question] Items that spawn temporary objects.
Post by: jar0fair on August 01, 2015, 12:34:40 am
Quote from: "Rochet2"
Try this. I basically just added back in the GetWorldObject you removed.

Code: [Select]
-- Cauldron
local CauldronItem = 200001
local CauldronObj = 186472
-- Chair
local ChairItem = 200002
local ChairObj = 186732
-- bed
local BedItem = 200003
local BedObj = 13948
-- vendor tent
local VendortentItem = 200004
local VendortentObj = 4000668

local spawn = {}

local function SpawnObj(plr, entry, despawn_time)
    local guid = plr:GetGUID()
    if spawn[guid] then
        local spawnedGobject = plr:GetMap():GetWorldObject(spawn[guid])
        if spawnedGobject then
            spawnedGobject:RemoveFromWorld(true)
            spawn[guid] = nil
        else
            plr:SendNotification("You need to be closer to the existing object to despawn it")
        end
    else
        local x, y, z, o = plr:GetLocation()
        local gobject = plr:SummonGameObject(entry, x, y, z, o, despawn_time)
        if gobject then
            spawn[guid] = gobject:GetGUID()
        end
    end
end

local function Cauldron(event, plr, item, target)
    SpawnObj(plr, CauldronObj, 0)
end

local function Chair(event, plr, item, target)
    SpawnObj(plr, ChairObj, 0)
end

local function Bed(event, plr, item, target)
    SpawnObj(plr, BedObj, 5)
end

local function VendorTent(event, plr, item, target)
    SpawnObj(plr, VendortentObj, 0)
end

RegisterItemEvent(CauldronItem, 2, Cauldron)
RegisterItemEvent(ChairItem, 2, Chair)
RegisterItemEvent(BedItem, 2, Bed)
RegisterItemEvent(VendortentItem, 2, VendorTent)


Nope, It doesn't remove the objects, and I am not sure why, because, it really seems like would, reading the code.
Title: Re: [Question] Items that spawn temporary objects.
Post by: Rochet2 on August 01, 2015, 12:39:42 am
Quote from: "jar0fair"
Nope, It doesn't remove the objects, and I am not sure why, because, it really seems like would, reading the code.
Are you getting any errors?
The script does nothing after spawning one gameobject? No more spawns or any messages?
Title: Re: [Question] Items that spawn temporary objects.
Post by: Rochet2 on August 01, 2015, 12:51:25 am
Alright, I see the error now.
Change
local guid = plr:GetGUID()
to
local guid = plr:GetGUIDLow()

The difference here is that GetGUID returns an uint64 number which is represented as an object.
Each GetGUID returns a different object causing the lua table to map them to different locations.
GetGUIDLow returns a normal number.
To properly make the uint64 work as table key it might need to be converted to strings, but using lowguid is easier for this and might be faster.
Title: Re: [Question] Items that spawn temporary objects.
Post by: jar0fair on August 01, 2015, 02:57:08 pm
Quote from: "Rochet2"
Alright, I see the error now.
Change
local guid = plr:GetGUID()
to
local guid = plr:GetGUIDLow()

The difference here is that GetGUID returns an uint64 number which is represented as an object.
Each GetGUID returns a different object causing the lua table to map them to different locations.
GetGUIDLow returns a normal number.
To properly make the uint64 work as table key it might need to be converted to strings, but using lowguid is easier for this and might be faster.


Thank you so much! Both of you. It is finally working how I would like it to. Me and my entire team are very grateful.
Title: Re: [Question] Items that spawn temporary objects.
Post by: jar0fair on August 08, 2015, 03:06:29 pm
Hia, back again.

After a lot of testing I discovered that if I log out, with one of my objects spawned, and it disappears, I can no long use the item anymore without reloading the lua engine. This is because the object is gone, and the code does not recognize it. So, I have written an additional function to nil the spawns on logout. However, it does not work. I am wondering if anyone sees any glaring mistakes in the logout function that I am somehow missing.

Code: [Select]
-- Name Here
local item = 200002
local obj = 22713

-- Code
local spawn = {}

local function SpawnObj(plr, entry, despawn_time)
    local guid = plr:GetGUIDLow()
    if spawn[guid] then
        local spawnedGobject = plr:GetMap():GetWorldObject(spawn[guid])
        if spawnedGobject then
            spawnedGobject:RemoveFromWorld(true)
            spawn[guid] = nil
        end
    else
        local x, y, z, o = plr:GetLocation()
        local gobject = plr:SummonGameObject(entry, x, y, z, o, despawn_time)
        if gobject then
            spawn[guid] = gobject:GetGUID()
        end
    end
end

local function logoff(plr, entry)
    guid = plr.GetGUIDLow()
    spawn[guid] = nil
end
-- Spawn Function
local function use(event, plr, item, target)
    SpawnObj(plr, obj, 0)
end
-- Registers
RegisterItemEvent(item, 2, use)
RegisterPlayerEvent(4, logoff)
Title: Re: [Question] Items that spawn temporary objects.
Post by: Rochet2 on August 08, 2015, 04:34:55 pm
Quote
Code: [Select]
local function logoff(plr, entry)
    guid = plr.GetGUIDLow()
    spawn[guid] = nil
end
Erm .. thats ..
The reason the code doesnt work is because your parameters are wrong logoff(plr, entry).
If you look here: http://eluna.emudevs.com/Global/Registe ... Event.html (http://eluna.emudevs.com/Global/RegisterPlayerEvent.html" onclick="window.open(this.href);return false;) it says (event, player)

also make that guid variable local.
Also you call member functions with : not with a dot.
Title: Re: [Question] Items that spawn temporary objects.
Post by: jar0fair on August 09, 2015, 03:28:40 am
Thanks again, Rotchet, this works just how I needed it to, now. Couldn't have done it without you.