Page 6 of 8
Re: Hiring party member(s) script - SOLVED
Posted: Mon Mar 23, 2015 10:18 pm
by JKos
it works with version 2.2.4
viewtopic.php?f=18&t=9578
Re: Hiring party member(s) script - SOLVED
Posted: Mon Mar 23, 2015 11:37 pm
by AndakRainor
OK I found the mistake ! Nothing related to this thread, I spawned the item before calling the insertItem function and forgot the "local" keyword for the variable holding it, sorry XD (didn't know it could do THAT to the editor !)
Now every thing is OK. But I also tried the function champion:removeItemFromSlot(slot), and noticed it destroys the item. I would like to store it and get it back later. Is there a way to move an item from the inventory to any location and later insert it back, knowing its game object ID ? Or do I have to destroy it and respawn it when needed (in this case I would have to manage its charges/stack size) ?
Re: Hiring party member(s) script - SOLVED
Posted: Tue Mar 24, 2015 5:05 am
by Isaac
AndakRainor wrote:Is there a way to move an item from the inventory to any location and later insert it back, knowing its game object ID ? Or do I have to destroy it and respawn it when needed (in this case I would have to manage its charges/stack size) ?
It's probably best to simply respawn the item again, and record only its number of charges; setting them after respawn.
It is possible (as you may have found out) to add an item from inventory to another location, and then to (immediately) destroy the original via removeItemFromSlot. You could (for instance) create an off-stage alcove for stored items, and use it to retrieve the [same] item later. I'm not recommending this though; nor have I tested it outside of just typing it into the console to see if it worked.
If the item is on the ground when added to the surface, then it disappears, and appears in the alcove. If the item is in inventory, when added to the surface, it (rather disturbingly) appears in the alcove, but stays in inventory as well. If you then pick it up from inventory, it vanishes from the alcove; but if you pick it up from the alcove, then you can add it to the inventory twice.

Re: Hiring party member(s) script - SOLVED
Posted: Tue Mar 24, 2015 6:28 am
by minmay
Respawning an object like that is generally a bad idea. Items in Grimrock 2 could be any GameObject with an ItemComponent. You can't just recreate them like you mostly could for Grimrock 1 items.
Champion:RemoveItemFromSlot() does not destroy the item. It just removes the item from the slot. Of course, since the item was in a champion's inventory when you removed it, its GameObject won't have a map so you can't use GameObject:setPosition() or find it using its id or findEntity(). Of course, you cannot store a reference to an item because it is unserializable, so to do what you want, you'll need to do the following:
- put a SurfaceComponent in some unreachable place
- when you want to take the item away, instead of just calling Champion:removeItemFromSlot(), use code like this:
Code: Select all
local champ = party.party:getChampion(1)
alcove_1.surface:addItem(champ:getItem(1))
champ:removeItemFromSlot(1)
Now the item's game object has been added to the map (via SurfaceComponent:addItem()) and you can find it using its id, which you can simply store as a string (which is serializable) and use in a findEntity() call to retrieve the object. When you want to add the item back, use Champion:insertItem()
and destroy the object with the surface you used. You need to destroy the surface as soon as you add the item back because otherwise the surface will end up with an unresolvable item reference when the game is saved and loaded.
Note that Champion:insertItem() fails if the slot you try to insert the item into is already occupied by an item. Therefore you should consider what to do if all inventory slots are full; perhaps just set the GameObject's position to right in front of the party.
Re: Hiring party member(s) script - SOLVED
Posted: Tue Mar 24, 2015 6:43 am
by Isaac
minmay wrote:
- put a SurfaceComponent in some unreachable place
- when you want to take the item away, instead of just calling Champion:removeItemFromSlot(), use code like this:
Code: Select all
local champ = party.party:getChampion(1)
alcove_1.surface:addItem(champ:getItem(1))
champ:removeItemFromSlot(1)
Now the item's game object has been added to the map (via SurfaceComponent:addItem()) and you can find it using its id, which you can simply store as a string (which is serializable) and use in a findEntity() call to retrieve the object.
This is [almost verbatim], the method from my post above, and has the same issues that I cautioned against. Are you sure this is good practice?
(That's an honest question, because I am not, and would myself like to know.)
The code you suggest, is the code that I typed when trying this out.
Also: What's wrong or risky [if you meant that] about spawning a new item instead, and setting its charges to the amount recorded prior to destroying the original object?
Champion:RemoveItemFromSlot() does not destroy the item. It just removes the item from the slot.
Do we know where the item is removed ~to? (Or is it just in limbo; accessible, but with no location in the game.)
Ah... Nevermind

Test confirmed, it's accessible and can be added to the surface even after removed from inventory. It's still disconcerting that the item stays in inventory even after placed into the surface, and can be picked up of from the surface, and added to inventory alongside itself; if not first removed from inventory. What's neat is that it is two references to the same object, and using any of them depletes the charges for all of them.
Re: Hiring party member(s) script - SOLVED
Posted: Tue Mar 24, 2015 7:25 am
by minmay
Isaac wrote:Also: What's wrong or risky [if you meant that] about spawning a new item instead, and setting its charges to a the amount recorded prior to destroying the original object?
Every single piece of state information other than the charges would be completely destroyed!
Isaac wrote:This is [almost verbatim], the method from my post above, and has the same issues that I cautioned against. Are you sure this is good practice?
(That's an honest question, because I am not, and would myself like to know.)
Using it for this specific purpose is certainly a hack and therefore bad practice, but I'm 99% sure the dangers are easily avoided so long as you:
1. remove the item from the inventory/mouse/container as soon as you add it to the surface. If you do not remove the item from inventory, then an ItemComponent reference will exist both the map and the inventory and this will cause it to be duplicated if the game is saved/loaded.
2. destroy the surface immediately upon giving the item back to the inventory. I only found this out while testing after the original post, sorry.
SurfaceComponent has to be able to add an item to the map cleanly for it to work at all, after all. Presumably there is an internal routine that just removes the item reference from the SurfaceComponent when it is picked up, but we don't have access to it (or it's not in the scripting reference that I can see, at least).
Re: Hiring party member(s) script - SOLVED
Posted: Tue Mar 24, 2015 11:59 am
by AndakRainor
Thank you! Should I use:
GameObject:createComponent(class, name)
GameObject:getComponent(name)
GameObject:removeComponent(component)
to manage a separate SurfaceComponent for each champion I wish to store (yes all this is about storing / getting back champions and their inventory in the party among a list larger than 4, so I won't have any problem with inserting items in occupied slots as they are all cleaned before hiring the new champion).
Or is it necessary to spawn and destroy one GameObject for each SurfaceComponent ?
Also, do you have any example of an item state other than charges and stack size that could be lost with the destroy / respawn item method ?
Re: Hiring party member(s) script - SOLVED
Posted: Tue Mar 24, 2015 1:26 pm
by kelly1111
Hello there,
Some help please. I just can't get the script to work. I get no error message from the game, but when I press the button nothing happens. The game kinda freezes up. I copied everything from the demo and named (the scripts) the same, connected it the same. I think the same thing happened as with duncan (see below). Can someone write a step by step proces for me so I can see what I am missing?
In case, what I have done in my mod :
Add a line in init.lua: import "mod_assets/jkos/init_champions.lua"
Put file jkos in mod_assets
Modify init_champions to define champions (and only that)
Put an instance of champions_recruit.script in the mod, but it seems to be unnecessary in your last version?
Create a script calling external champions.script
Connect reccruit script to a button to call it like in your demo... and crash (but editor keeps working)
Re: Hiring party member(s) script - SOLVED
Posted: Tue Mar 24, 2015 2:02 pm
by AndakRainor
Do you have the beta version 2.2.4 of the game ? it is required (at least for the resetXP function on a champion)
Re: Hiring party member(s) script - SOLVED
Posted: Tue Mar 24, 2015 6:39 pm
by minmay
AndakRainor wrote:Thank you! Should I use:
GameObject:createComponent(class, name)
GameObject:getComponent(name)
GameObject:removeComponent(component)
to manage a separate SurfaceComponent for each champion I wish to store (yes all this is about storing / getting back champions and their inventory in the party among a list larger than 4, so I won't have any problem with inserting items in occupied slots as they are all cleaned before hiring the new champion).
Or is it necessary to spawn and destroy one GameObject for each SurfaceComponent ?
I haven't tested it but it would probably work. I was trying to keep the instructions as simple as possible.
AndakRainor wrote:Also, do you have any example of an item state other than charges and stack size that could be lost with the destroy / respawn item method ?
Literally anything on this entire page, because an ItemComponent is attached to a GameObject which could have any number of any components of any state.