I'm going to have to disagree with Antti on this one. In this code:
Code: Select all
function setVariable(variable, value)
variable = value
end
Both variable and value are implicitly local to the function setVariable. Arguments are always local. So when lua evaluates the line "variable = value", it sets the local named "variable" to whatever value was passed in as the second argument. That has no effect on the "global" variables of the script_entity named variable_storage. Grimrock lua does not support the function loadstring either, which could also solve this problem. I think you would have to make a setter function for each variable that you want to be able to set from outside of the script entity, and hardcode the variable to be set by that function.
Reading
this thread raised my blood pressure for a minute, until I confirmed that tables are indeed now supported in save games.
And I am aware that this is an old thread and the people who were originally interested may not be here anymore.
As a general matter of scripting habits, whenever you find yourself wanting to set a variable inside another script, you should consider why you need to. If at all possible, you should avoid this. Data should be housed in the same place where it is used. Reading a variable from another script_entity is tolerable, but writing to a variable in another script_entity can get very messy very quickly. You could end up with weird values in your variables (possibly the wrong data type,) and have no idea how those values got there. If possible, all the code that can modify any specific variable should live in the same script as that variable. It can help a lot to organize your scripts into an informal hierarchy: this is a top level (level 1) script, so it is allowed to call any script. This other script is a lower level script, so it should do all of its own nitty-gritty work, and other scripts should call on it to perform very specific tasks.
As an example, suppose I have a script that tracks a "burn" effect that can be applied to a party member by a monster or trap:
Code: Select all
setBurned = function( champion )
burned = champion
end
setBurnTimeRemaining = function( time )
burnTimeRemaining = time
end
function onTick() --called by a Timer
if burned then
burned:damage( 3 , "fire" )
end
burnTimeRemaining = burnTimeRemaining - 1
if burnTimeRemaining == 0 then
burned = nil
end
end
And I use that script like so:
Code: Select all
burnScript.setBurned(party:getChampion(1))
burnScript.setBurnTimeRemaining(5)
But this script only allows one champion to be burning at a time. If I try to make another champion burning, it will overwrite the value that was already present in the variable "burned". And there's a couple other little changes I want to make. So I decide to change how I implemented burning to use a table instead:
Code: Select all
burned = {} --keys are ordinals, value is the time remaining for that champion to burn
setBurn = function( champion , time )
local oldTime = burned[champion:getOrdinal()]
if oldTime and ( oldTime > time ) then --don't reduce the time if the champion was already burning
return
end
burned[champion:getOrdinal()] = time
end
function onTick() --called by timer
for i = 1,4 do
local ordinal = party:getChampion(i):getOrdinal()
if burned[ordinal] then
party:getChampion(i):damage( 3 , "fire" )
local newTime = burned[ordinal] - 1
if newTime == 0 then
newTime = nil
end
burned[ordinal] = newTime
end
end
end
And now I have to use my script like so:
Code: Select all
burnScript.setBurn( party:getChampion(1) , 5 )
So I have to rewrite (slightly) everything that uses my burnScript. But even when I wasn't using a table to implement the burning, I should have written burnScript differently in the first place. I should have written it so that other scripts call burnScript and tell it
what to do, not how to do it. If I had thought of making a champion burn as a single "action" that always requires both a champion and a duration, then I would have written burnScript as:
Code: Select all
setBurn = function( champion , time )
burned = champion
burnTimeRemaining = time
end
function onTick() --called by a Timer
if burned then
burned:damage( 3 , "fire" )
end
burnTimeRemaining = burnTimeRemaining - 1
if burnTimeRemaining == 0 then
burned = nil
end
end
and my calls to burnScript as:
Code: Select all
burnScript.setBurn( party:getChampion(1) , 5 )
in the first place, so I would only have to change burnScript. The calling scripts wouldn't depend on setting specific variables within burnScript. I wouldn't have to change the calling scripts to change the implementation and improve the functionality. That is absolutely huge, in terms of keeping script development moving forward while still being able to fix bugs and enhance functionality in scripts that you've already written.