Ask a simple question, get a simple answer

Ask for help about creating mods and scripts for Grimrock 2 or share your tips, scripts, tools and assets with other modders here. Warning: forum contains spoilers!
User avatar
Isaac
Posts: 3185
Joined: Fri Mar 02, 2012 10:02 pm

Re: Ask a simple question, get a simple answer

Post by Isaac »

Zo Kath Ra wrote: Thu Mar 12, 2020 10:09 pmGameMode.getStatistic("tiles_moved")
Thanks! Image

______
Modraneth wrote: Sat Mar 14, 2020 1:27 am where do I failed?

Code: Select all

function SpawnRewards()
  local s = Laurent_spot.surface
    for _,e in s:contents() do
      if e.go.name == "corga_amulet" then
        e.go:destroy()
	 spawn("fire_gauntlets", self.go.level, self.go.x, self.go.y, self.go.facing, self.go.elevation)
	end
	end
end
This does not interact with the surface in the way you intend.

Try this:

Code: Select all

function SpawnRewards()
  local s = Laurent_spot.surface
    for _,e in s:contents() do
      if e.go.name == "corga_amulet" then
        e.go:destroyDelayed() --Updated as per suggestions.
	s:addItem(spawn("fire_gauntlets").item)
	s.go:spawn('teleportation_effect')	
	end
	end
end
If you explain exactly the effect and behavior that you intend, there might be a better way to script this.
_____
Last edited by Isaac on Mon Mar 16, 2020 2:45 am, edited 1 time in total.
User avatar
Zo Kath Ra
Posts: 937
Joined: Sat Apr 21, 2012 9:57 am
Location: Germany

Re: Ask a simple question, get a simple answer

Post by Zo Kath Ra »

Isaac wrote: Sat Mar 14, 2020 4:29 am Try this:

Code: Select all

function SpawnRewards()
	local s = Laurent_spot.surface
	for _,e in s:contents() do
		if e.go.name == "corga_amulet" then
			e.go:destroy()
			s:addItem(spawn("fire_gauntlets").item)
			s.go:spawn('teleportation_effect')	
		end
	end
end
The code adds items to and destroys items on a surface while iterating over the surface.
Is that allowed, or could it cause undefined behavior?

I'd at least add a break statement to the end of the if-block.
(assuming that there can only be one "corga_amulet" on the surface at any time)
User avatar
Isaac
Posts: 3185
Joined: Fri Mar 02, 2012 10:02 pm

Re: Ask a simple question, get a simple answer

Post by Isaac »

Zo Kath Ra wrote: Sat Mar 14, 2020 9:36 am The code adds items to and destroys items on a surface while iterating over the surface.
Is that allowed, or could it cause undefined behavior?
AFAIK, the only way to safely (?) remove an item from a surface is to destroy it; there is no :removeItem() for surface components.
I'd at least add a break statement to the end of the if-block.
(assuming that there can only be one "corga_amulet" on the surface at any time)
This is a good idea (generally). I don't know if there can be more than one amulet, or how that function is called. If it's called by a timer, then the player might have time to place more than one. I tried not to alter its behavior—aside from the cosmetic effect.
User avatar
Zo Kath Ra
Posts: 937
Joined: Sat Apr 21, 2012 9:57 am
Location: Germany

Re: Ask a simple question, get a simple answer

Post by Zo Kath Ra »

Isaac wrote: Sat Mar 14, 2020 9:44 am
Zo Kath Ra wrote: Sat Mar 14, 2020 9:36 am The code adds items to and destroys items on a surface while iterating over the surface.
Is that allowed, or could it cause undefined behavior?
AFAIK, the only way to safely (?) remove an item from a surface is to destroy it; there is no :removeItem() for surface components.
Sure, adding items to surfaces and destroying items on surfaces is no problem.

But are you allowed to do these things while you're iterating over the surface?
More specifically: If you do one of these things while iterating over a surface, are you then allowed to continue iterating, or do you have to break?
User avatar
Isaac
Posts: 3185
Joined: Fri Mar 02, 2012 10:02 pm

Re: Ask a simple question, get a simple answer

Post by Isaac »

Zo Kath Ra wrote: Sat Mar 14, 2020 9:52 am But are you allowed to do these things while you're iterating over the surface?
More specifically: If you do one of these things while iterating over a surface, are you then allowed to continue iterating, or do you have to break?
Officially? You'd have to ask minmay or Petri. In practice I have never noticed an error from it—not that I couldn't have missed them, but I have done stranger things within the iterator than just deleting an entry, and with seemingly no ill effect.
User avatar
Modraneth
Posts: 95
Joined: Thu Aug 27, 2015 8:27 pm
Location: Portugal

Re: Ask a simple question, get a simple answer

Post by Modraneth »

Isaac wrote: Sat Mar 14, 2020 4:29 am Try this:

Code: Select all

function SpawnRewards()
  local s = Laurent_spot.surface
    for _,e in s:contents() do
      if e.go.name == "corga_amulet" then
        e.go:destroy()
	s:addItem(spawn("fire_gauntlets").item)
	s.go:spawn('teleportation_effect')	
	end
	end
end
If you explain exactly the effect and behavior that you intend, there might be a better way to script this.
_____
im making a Quest.
i placed a invisible surface in front of the quest giver (a ratling leaning on a dungeon_wall_open)
so the dude gives a quest to find corga_amulet
then when i place the corga_amulet on the survace he gives the reward
the teleportation_effect wont be good there, its suppose to be him giving the reward so the reward should appear on the invisible surface

EDIT: that worked pretty well, i just delete the teleportation_effect
thank you a lot
Mods:
Isle of Gunger
The Bloody Path Dropped
A World of Power work in progress
User avatar
Isaac
Posts: 3185
Joined: Fri Mar 02, 2012 10:02 pm

Re: Ask a simple question, get a simple answer

Post by Isaac »

There is a ratling in the ORRR3 mod dungeon, who has a bit of cheese in her hand. This is done by adding a model component for the cheese, and parenting it to the weapon hand. The cheese can be visible or invisible, by enabling or disabling that model component.

Image

Here is the monster definition to examine:

Code: Select all

defineObject{
	name = "or3_ratling_smith",
	placement = "floor",
	components = {
		{
			class = "Model",
			model = "assets/models/monsters/ratling3.fbx",
			boundBox = {pos=vec(0,0.9,0.2),size=vec(3,1.8,2.5)},
			materialOverrides = {pistol="nothing"},
		},

		{
			class = "Model",
			name = "cheese",
			model = "assets/models/items/cheese.fbx",
			parentNode = "sword",
		},

		{
			class = "Animation",
			animations = {
				idle = "mod_assets/core/animations/ratling3_anvil_idle.fbx", 
				accept_ore = "mod_assets/core/animations/Isaac/ratling3_anvil_accept_ore.fbx",
				accept_ore_wait_loop = "mod_assets/core/animations/Isaac/ratling3_anvil_accept_ore_wait_loop.fbx",
				accept_ore_revert_to_idle = "mod_assets/core/animations/Isaac/ratling3_anvil_accept_ore_revert_to_idle.fbx",

			},
			currentLevelOnly = true,
			playOnInit = "idle",
			loop = true,
		},
	},
	editorIcon = 4,
}
The animations are custom, but the cheese in the hand is automatic.
Notice though, that this is not actually a monster, just an animated object.
SluisE
Posts: 8
Joined: Fri Nov 30, 2018 4:56 pm

Re: Ask a simple question, get a simple answer

Post by SluisE »

Isaac wrote: Sat Mar 14, 2020 10:24 am
Zo Kath Ra wrote: Sat Mar 14, 2020 9:52 am But are you allowed to do these things while you're iterating over the surface?
More specifically: If you do one of these things while iterating over a surface, are you then allowed to continue iterating, or do you have to break?
Officially? You'd have to ask minmay or Petri. In practice I have never noticed an error from it—not that I couldn't have missed them, but I have done stranger things within the iterator than just deleting an entry, and with seemingly no ill effect.
You should indeed not do this.
Use destroyDelayed instead of destroy. That way the item is destroyed when you end the function.
And only spawn and add the new item after you are done with the iteration. Use a variable to check if the first item is on the surface (found = true) and at the end cheek this variable, and only then add and spawn the item.
User avatar
Modraneth
Posts: 95
Joined: Thu Aug 27, 2015 8:27 pm
Location: Portugal

Re: Ask a simple question, get a simple answer

Post by Modraneth »

Isaac wrote: Sat Mar 14, 2020 1:29 pm The animations are custom, but the cheese in the hand is automatic.
Notice though, that this is not actually a monster, just an animated object.
i had the animations the problem was the reward
but already get it, thank you
Mods:
Isle of Gunger
The Bloody Path Dropped
A World of Power work in progress
User avatar
Isaac
Posts: 3185
Joined: Fri Mar 02, 2012 10:02 pm

Re: Ask a simple question, get a simple answer

Post by Isaac »

SluisE wrote: Sat Mar 14, 2020 8:22 pm Use destroyDelayed instead of destroy. That way the item is destroyed when you end the function.
This is very good; best practice I think. (And thanks for the comment on it. 8-) )

But what really happens under the hood when the object is destroyed (by the usual method)? Is its position shifted? Can an entry be missed?

It seems to make sense to almost always (or to only) use destroyDelayed just as a matter of course, because it does bypass some nasty crashes in some situations. But does anyone know (or can reasonably speculate on) what could actually happen if an object gets destroyed in the iterator loop—and is never accessed again? Could it actually crash?

minmay will tell you (with good reason) that the monster.contents iterator is damaged, or broken; it DOES (or can? IIRC) cause crashes when it returns nil. I never had a crash with it after I added a 'pocket_lint' item before using it. :lol:
Post Reply