anything other than a wall to prevent player throwing stuff?

Talk about creating Grimrock 1 levels and mods here. Warning: forum contains spoilers!
User avatar
Komag
Posts: 3659
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: anything other than a wall to prevent player throwing st

Post by Komag »

For scroll images, you can do it case by case like so:

in items.lua:

Code: Select all

	defineObject{
		name = "note_map1",
		class = "Item",
		uiName = "Note",
		model = "assets/models/items/note.fbx",
		gfxIndex = 114,
		scroll = true,
		weight = 0.1,
	}

	defineObject{
		name = "note_map2",
		class = "Item",
		uiName = "Note",
		model = "assets/models/items/note.fbx",
		gfxIndex = 114,
		scroll = true,
		weight = 0.1,
	}
in the script in the dungeon:

Code: Select all

     if wasHoldingName == "note_map1" then
        getMouseItem():setScrollImage("assets/textures/gui/scroll_images/treasure_map_slime.tga")
       elseif wasHoldingName == "note_map2" then
        getMouseItem():setScrollImage("assets/textures/gui/scroll_images/treasure_map_vault.tga")
     end
Finished Dungeons - complete mods to play
User avatar
Komag
Posts: 3659
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: anything other than a wall to prevent player throwing st

Post by Komag »

Xanathar wrote: As a difference from Komag script: I don't keep the id saved - if you need to save and restore it for any reason it must be added (in theory I prefer not to, and I never had the need, but I understand other mods may rely on the ids being preserved).
I actually don't need the IDs either, and found it problematic to try ever rely on it. If I wanted to restore special ids, I would need some way to either:
1 - check whether it had just a number id (assigned by the game) or a string id and only attempt to restore the id if it was a string (number IDs crash), or
2 - check the id against a table of items with ids that I want to preserve, and only if one of those attempt to restore the id.

By the way, is "c * 100 + i" enough room? What if a player had, say, 10 boxes all full with 10 items each! Just for super reliability, might want to change to "c * 1000 + i"
Finished Dungeons - complete mods to play
User avatar
Komag
Posts: 3659
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: anything other than a wall to prevent player throwing st

Post by Komag »

After banging my head on the keyboard for a couple hours and stretching my brain further than I have in a while, I've come up with a modified version of the script (which includes all the debug text I like), which works GREAT! 8-)

Code: Select all

wasHolding = 0
wasHoldingStored = { }

function mouseSave()
  print("running mouseSave")
  if getMouseItem() ~= nil then
     print("found an item in mouse, called "..getMouseItem().name)
     wasHolding = 1
     wasHoldingStored[1] = saveItem(getMouseItem())
     setMouseItem(nil)
  end
end

function saveItem(item)
   local itemTable = { }
   itemTable.name = item.name
   itemTable.stackSize = item:getStackSize()
    print("mouse item stack size "..itemTable.stackSize)
   itemTable.fuel = item:getFuel()
    print("mouse item fuel "..itemTable.fuel)
   itemTable.charges = item:getCharges()
    print("mouse item charges "..itemTable.charges)
   itemTable.scrollText = item:getScrollText()
    if itemTable.scrollText ~= nil then
       print(""..itemTable.scrollText)
    end
   
   local idx = 0
   for subItem in item:containedItems() do
      if (idx == 0) then
         itemTable.subItems = { }
      end
      
      itemTable.subItems[idx] = saveItem(subItem)
      idx = idx + 1
   end
   
   return itemTable
end

function mouseRestore()
  if wasHolding == 1 then
     setMouseItem(loadItem(wasHoldingStored[1]))
     wasHoldingStored = { }
     wasHolding = 0
  end
end

function loadItem(itemTable)
   local spitem = nil
   spitem = spawn(itemTable.name)

   if itemTable.stackSize > 0 then
      spitem:setStackSize(itemTable.stackSize)
      print("restoring stack size...")
   end

   if itemTable.charges > 0 then
      spitem:setCharges(itemTable.charges)
      print("restoring charges...")
   end

   if itemTable.scrollText ~= nil then
      spitem:setScrollText(itemTable.scrollText)
      print("restoring text...")
   end

   spitem:setFuel(itemTable.fuel)
   print("restoring fuel, if any...")

   if itemTable.name == "note_map1"  then
        spitem:setScrollImage("assets/textures/gui/scroll_images/treasure_map_slime.tga")
       elseif itemTable.name == "note_map2" then
        spitem:setScrollImage("assets/textures/gui/scroll_images/treasure_map_vault.tga")
   end

   if (itemTable.subItems ~= nil) then
      for _, subTable in pairs(itemTable.subItems) do
         local subItem = loadItem(subTable)
         spitem:addItem(subItem, false)
      end
   end
   
   return spitem
end
It even allows me to have on the mouse a box filled with various items with various properties, one of which can be a mortar with 6 more items inside of it! and it all works beautifully, all charges, fuel, text, images (for the two special cases), stack, everything fully restored on all the items! Amazing!!! :o :shock: :mrgreen:

I tried to test a variety of situations and items, and everything is good so far. I haven't tested all those situations/items in game mode with save games yet :?
Finished Dungeons - complete mods to play
User avatar
Komag
Posts: 3659
Joined: Sat Jul 28, 2012 4:55 pm
Location: Boston, USA

Re: anything other than a wall to prevent player throwing st

Post by Komag »

... and the final bit about what this whole thread was for is now in place, working perfectly!

Edsploration - I didn't end up using most of what you came up with, but the socket objects themselves (the x and y, not the moving ones) and the overall concept were absolutely invaluable. I adjusted how it works and tied it in to my mouseSave and mouseRestore functions. For the sockets, I simply have them run mouseSave and activate a timer which 0.01s runs mouseRestore. Those mouse functions delete the object before it even leaves your hands, and restores it, so there is no thrown/dropped noise. I also increased the target size middle number, and placed the sockets so that you can still place items right down on the square you occupy but not in the square ahead.

Code: Select all

defineObject{
   name = "no_throw_alcove_x",
   class = "Alcove",
   anchorPos = vec(0, 2, 1.5), -- the parts are all close to 0.5 in, so this should be "behind" them
   targetPos = vec(0, 2, 1.5),
   targetSize = vec(0, 3, 5),
   placement = "wall",
   onInsertItem = function(self, item)
      noThrowScript.noThrow()
	  return false
   end,
   editorIcon = 92,
}

defineObject{
   name = "no_throw_alcove_y",
   class = "Alcove",
   anchorPos = vec(0, 2, 1.5), -- the parts are all close to 0.5 in, so this should be "behind" them
   targetPos = vec(0, 2, 1.5),
   targetSize = vec(5, 3, 0),
   placement = "wall",
   onInsertItem = function(self, item)
      noThrowScript.noThrow()
	  return false
   end,
   editorIcon = 92,
}
and in the script it's just:

Code: Select all

function noThrow()
  mouseItemScript.mouseSave()
  noThrowTimer:activate()
end

function throwRestore()
  mouseItemScript.mouseRestore()
end
with the noThrowTimer set to 0.01s and connected to trigger throwRestore() (and deactivate itself)

I know I could have put those things in the object definition, but I really like to keep my hook links to the absolute minimum, and then handle everything inside the editor.

I absolutely could not have done this without you guys, thanks a ton! :mrgreen:
THANK YOU Edsploration for the script and concept, and
THANK YOU Xanathar for the item properties saving script
Finished Dungeons - complete mods to play
User avatar
Darklord
Posts: 2001
Joined: Sat Mar 03, 2012 12:44 pm
Location: England

Re: anything other than a wall to prevent player throwing st

Post by Darklord »

Well done guys, looks like some great team work here. :)

Daniel.
A gently fried snail slice is absolutely delicious with a pat of butter...
Post Reply