Page 342 of 396
Re: Ask a simple question, get a simple answer
Posted: Sat Mar 14, 2020 4:29 am
by Isaac
Zo Kath Ra wrote: ↑Thu Mar 12, 2020 10:09 pmGameMode.getStatistic("tiles_moved")
Thanks!
______
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.
_____
Re: Ask a simple question, get a simple answer
Posted: Sat Mar 14, 2020 9:36 am
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)
Re: Ask a simple question, get a simple answer
Posted: Sat Mar 14, 2020 9:44 am
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.
Re: Ask a simple question, get a simple answer
Posted: Sat Mar 14, 2020 9:52 am
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?
Re: Ask a simple question, get a simple answer
Posted: Sat Mar 14, 2020 10:24 am
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.
Re: Ask a simple question, get a simple answer
Posted: Sat Mar 14, 2020 11:20 am
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
Re: Ask a simple question, get a simple answer
Posted: Sat Mar 14, 2020 1:29 pm
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.
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.
Re: Ask a simple question, get a simple answer
Posted: Sat Mar 14, 2020 8:22 pm
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.
Re: Ask a simple question, get a simple answer
Posted: Sat Mar 14, 2020 9:01 pm
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
Re: Ask a simple question, get a simple answer
Posted: Sun Mar 15, 2020 4:49 am
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.
)
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.