Re: question based on monster.lua
Posted: Fri Mar 08, 2013 3:50 am
Hi Ryeath_Greystalk. We certainly could start a new thread if you like. I would prefer not to use PM's unless it's something that really shouldn't be public (e.g. spoilers for a work-in-progress.) I suspect that hyteria won't mind if we keep using this thread, since he or she hasn't posted here since Jan 4.
then nil behaves the same as false. If you like, you could add this line:
at the top of bossScript. That line will not change the behavior of bossScript in any way, but it may clarify for you what is happening.
You have probably seen errors occur from attempting to index a nil value. This happens when you try to treat a nil value as if it was a table. For example:
Assuming that you do not have an entity called "NoSuchEntity" in your dungeon, then this code will produce an error. That's because the line "entity:destroy()" only makes sense if entity is a table (and that table contains a pair with key "destroy", and the value of that pair is a function), but in this case, entity is nil because findEntity couldn't find an entity with id "NoSuchEntity". That's why it's good practice to make sure the value you're working with isn't nil before you treat it like a table:
This code shouldn't crash. If you wanted to be even more defensive with your code, you could write:
In this code, I've used the native lua function "type". This function returns a string corresponding to the type of value of the argument. There are only eight native types in lua, of which I know that six (nil, boolean, number, string, table, function) are supported in Grimrock. Dungeon objects are always of type table. Nil is a special type. There is only one possible value of this type: nil itself. Its only real purpose is to be a special "non-value" that you can check for, for example when findEntity can't find an entity with the id you specified. As mentioned above, nil behaves the same as false in most cases. One important exception is that the Grimrock API hooks (e.g. onDie) are interested in the return value false, and only false. If a hook function returns nil, then Grimrock treats this the same as if that hook had returned true. If you want to cancel the pending action that triggered a hook, you must return false.
It seems I've rambled quite a bit already. I hope some of this has helped
Yes, that would work just fine. In the script I posted, there are actually two completely distinct functions referenced by the name "onDie" and two distinct functions referenced by the name "onDamage". Lua can tell apart the two "onDie" functions. The first "onDie" function (in monsters.lua) is a value in an anonymous table, corresponding to the key "onDie". That table is then used as the argument to the Grimrock API function cloneObject. The second "onDie" function (in bossScript) is stored in bossScript's non-local variable onDie. I prefer to reuse the names like this when the purpose of the two functions is so closely related (the function in monsters.lua does nothing except call the function in bossScript), but if you prefer to use distinct names for distinct functions, there's nothing wrong with that approach, either.Ryeath_Greystalk wrote:I see you have onDie and onDamage in both the monsters.lua and bossScript. Are they calling the same functions or are they separate? For example could I use
monsters.lua
onDie = function( monster )
return bossScript.isItDeadYet( monster )
end,
with bossScript
function isItDeadYet(monster)
That's correct.Ryeath_Greystalk wrote:Another unclear this is alreadyEscaped variable. I don't see it assigned to anything until after the monster has escaped where you give it alreadyEscaped = true.
Everything you said here is true, except for bringing up an error. Nil is a legitimate value in lua. The value of any variable which has not yet been initialized is nil. The same is true for values within a table which have not yet been initialized. So when lua checks alreadyEscaped before a value has been assigned to this variable, its value is nil. When nil is used as a condition or within complex logical operations:Ryeath_Greystalk wrote: Wouldn't that bring up an error for a nil value? I tend to think very linear. So I would think it would happen like this, I hit monster, monster takes damage, call bossScript.onDamage, function tries to compare not alreadyEscaped..lua say "whoa, what is this alreadyEscaped thing I haven't seen that yet, guess I will give it a nil value."
Code: Select all
if nil then
--lua will never reach this line
end
if (not nil) then
--lua will always reach this line
end
if ( nil or x ) then
--lua will reach this line if and only if the variable x is a "positive" value
--anything except for nil or false is a "positive" value
end
if ( nil and y ) then
--lua will never reach this line
--in fact, lua will never even check the value of y because ( nil and whatever ) is always a "negative" result
end
Code: Select all
alreadyEscaped = false
You have probably seen errors occur from attempting to index a nil value. This happens when you try to treat a nil value as if it was a table. For example:
Code: Select all
local entity = findEntity("NoSuchEntity")
entity:destroy()
Code: Select all
local entity = findEntity("NoSuchEntity")
if entity then
entity:destroy()
end
Code: Select all
local entity = findEntity("NoSuchEntity")
if ( type(entity) == "table" ) and ( type(entity.destroy) == "function" ) then
entity:destroy()
end
It seems I've rambled quite a bit already. I hope some of this has helped