DICE PACKS BUNDLE
Page 1 of 2 12 Last
  1. #1
    Varsuuk's Avatar
    Join Date
    Dec 2015
    Location
    New York
    Posts
    2,075

    Approximating a switch when calling methods

    I started writing a six-check if/then chain for abilities when I said... hmmm no switch, I know - but you can make one via function table so I tried:

    Code:
    local aAbilityToUpdateSwitch = {
    	["strength"] = AbilityScoreBonusesManager.updateStrengthRelatedBonuses,
    	["dexterity"] = AbilityScoreBonusesManager.updateDexterityRelatedBonuses,
    	["constitution"] = AbilityScoreBonusesManager.updateConstitutionRelatedBonuses,
    	["intelligence"] = AbilityScoreBonusesManager.updateIntelligenceRelatedBonuses,
    	["wisdom"] = AbilityScoreBonusesManager.updateWisdomRelatedBonuses,
    	["charisma"] = AbilityScoreBonusesManager.updateCharismaRelatedBonuses
    }
    
    function updateAttributeBonuses(nodeScore)
    	local node func = aAbilityToUpdateSwitch[nodeScore.getParent().getName()];
    	
    	if func ~= nil then
    		func(nodeScore);
    	end
    end
    The above references methods in:
    <script name="AbilityScoreBonusesManager" file="scripts/manager_ability_score_bonuses.lua" />

    But the console logs the error complaining that "AbilityScoreBonusesManager is null in <first line referencing it>"


    Any way around this?
    I could create 6 one-liner methods that each call the method I want and put those one line names in the table. But anything else?

  2. #2
    I believe you need to move the initialization inside "onInit()" because AbilityScoreBonusesManager has not been created yet. This worked for me:

    Code:
    local aAbilityToUpdateSwitch = nil;
    
    function onInit()
    	aAbilityToUpdateSwitch = {
    		["strength"] = AbilityScoreBonusesManager.updateStrengthRelatedBonuses,
    		["dexterity"] = AbilityScoreBonusesManager.updateDexterityRelatedBonuses,
    		["constitution"] = AbilityScoreBonusesManager.updateConstitutionRelatedBonuses,
    		["intelligence"] = AbilityScoreBonusesManager.updateIntelligenceRelatedBonuses,
    		["wisdom"] = AbilityScoreBonusesManager.updateWisdomRelatedBonuses,
    		["charisma"] = AbilityScoreBonusesManager.updateCharismaRelatedBonuses
    	};
    
    	Debug.console("strength: " .. updateAttributeBonuses("strength"));
    	Debug.console("charisma: " .. updateAttributeBonuses("charisma"));
    	Debug.console("junk: " .. updateAttributeBonuses("junk"));
    end
    
    
    function updateAttributeBonuses(nodeScore)
    	local func = aAbilityToUpdateSwitch[nodeScore];
    	
    	if func ~= nil then
    		return func();
    	else
    		return "no matches";
    	end
    end
    with the AbilityScoreBonusesManager functions just being these:

    Code:
    function updateStrengthRelatedBonuses()
    	return "Strength";
    end
    
    function updateDexterityRelatedBonuses()
    	return "Dexterity";
    end
    
    function updateConstitutionRelatedBonuses()
    	return "Constitution";
    end
    
    function updateIntelligenceRelatedBonuses()
    	return "Intelligence";
    end
    
    function updateWisdomRelatedBonuses()
    	return "Wisdom";
    end
    
    function updateCharismaRelatedBonuses()
    	return "Charisma";
    end

  3. #3
    As a test extension attached
    Attached Files Attached Files

  4. #4
    Varsuuk's Avatar
    Join Date
    Dec 2015
    Location
    New York
    Posts
    2,075
    [PARTIALLY SOLVED - but without understanding why other way fails]

    So, I am back home and took a look at this. I ended up getting my code to work as well as identifying a single line of code that will cause this issue (although it is not fully covering all case, just a specific instance of the problem.)

    First, let me give my "solution" (again, not sure it's THE way, but it's the way I got it to work.)

    Code:
    function updateAbilityScores(nodeScore)
    	updateAttributeBonuses(nodeScore);
      -- just started this, so it's a one liner but more will be added as I continue...
    end
    
    
    function nodeCharFromAbilityScore(node)
    	return node.getChild("....");
    end
    
    ...
    
    local aAbilityToUpdateSwitch = {
    	["strength"] = function (nodeChar) AbilityScoreBonusesManager.updateStrengthRelatedBonuses(nodeChar) end,
    	["dexterity"] = function (nodeChar) AbilityScoreBonusesManager.updateDexterityRelatedBonuses(nodeChar) end,
    	["constitution"] = function (nodeChar) AbilityScoreBonusesManager.updateConstitutionRelatedBonuses(nodeChar) end,
    	["intelligence"] = function (nodeChar) AbilityScoreBonusesManager.updateIntelligenceRelatedBonuses(nodeChar) end,
    	["wisdom"] = function (nodeChar) AbilityScoreBonusesManager.updateWisdomRelatedBonuses(nodeChar) end,
    	["charisma"] = function (nodeChar) AbilityScoreBonusesManager.updateCharismaRelatedBonuses(nodeChar) end
    };
    
    function updateAttributeBonuses(nodeScore)
    	local func = aAbilityToUpdateSwitch[nodeScore.getParent().getName()];
    	
    	if func ~= nil then
    		func(nodeCharFromAbilityScore(nodeScore));
    	end
    end
    The problem is somehow likely related to whatever is happening under the hood when you preface a method in another script file with the "name" assigned to that "package" as it were.

    So, my original attempt at putting the calls to the method didn't work (see first post)
    Then I tried avoiding the explicit use of "AbilityScoreBonusesManager." in the function table. I figured, define a local var that references the function and put that var into the table instead (remember, total noob here so no clue if that was silly/crazy) then I got an error calling the method that I was calling up until now no problem. And the CALLER didn't change, yet the method it is calling became reported as being nil. So I looked and looked for typos, removed all code I could to keep it simple.

    Eventually, I found out if I simply added this before the method I was calling I got the error:
    local strBonusFunc = AbilityScoreBonusesManager.updateStrengthRelatedBo nuses;

    I moved it up in the script to above a method I call before this point (with no issues) and that method all of us sudden is reported as being nil now.

    Again, try this with one of your own package methods.



    So, not calling this [SOLVED] but I DID figure out what I wanted, which is how to call a method (defined in another script file) in a table like a switch.
    Added the above code block in case it helps anyone else.

    Pardon my overly verbose names - it isn't just that I am verbose (I am...) it's my ADHD+bad memory - there is NO WAY I could have picked this project back up after a 10 month hiatus if not for my occasional inline comment and common self-commenting var/method names. Happens on projects that I spend 18 months coding where I do over 90% of the coding alone and yet 6+ months later I forgot much of what I wrote if, as too often happens, all the bloody bugs were worked out between QA and myself before release and I didn't have to keep touching it

  5. #5
    Varsuuk's Avatar
    Join Date
    Dec 2015
    Location
    New York
    Posts
    2,075
    OOPS - I was typing my long message before these posts (I refreshed before starting - damn helpful race-conditions!) Will read now and see if you figured out what I was asking in last post!

  6. #6
    Varsuuk's Avatar
    Join Date
    Dec 2015
    Location
    New York
    Posts
    2,075
    That makes sense!

    But, as I typed that, I wondered about why it works when I define the method INSIDE the table ala "closure-esque" - but it still makes sense. Most likely (thinking indeterminate order of static definitions across compilation units in C) if it is "dereferenced" when first parsed? and it is nil still and never gets updated? But inside a table it is "created" after onInit and therefore at that time the reference is non nil.

    All theories out my butt BUT if my way (and yours) works it is good enough rationale for them and I will be satisfied enough not to rathole on it
    I will try your extension though to try my alt way to fix on it too and verify works there as well.

    Thanks - I LOVE how well folks help others here

    But now I am curious because what you said makes a lot of sense. Sure, the method is there and the package is there but maybe some of this is "evaluating

  7. #7
    Varsuuk's Avatar
    Join Date
    Dec 2015
    Location
    New York
    Posts
    2,075
    Gamerhawaii,

    I verified your fix - as expected, solves the issue.
    I then tried doing something like what I outlined, moving the call to the outside method into an indirect call in the table. This did not work (well, it solved the error complaining that the package name was nil) it CALLS the method (seems fixed then right?) but even though console shows it is in that method that returns "Strength", the console reports an attempt to concat a nil value?

    Anyhow - like said, the code now "works" that I listed above (I don't believe in leaving things not understood when I "solve" a problem because I might only have pushed it further down the line) but I will step away from it since now I can continue and perhaps thinking later on it and with your simple (well done - good idea) extension, I can isolate the issue better and find out the "why" and why it is still not good there.

    What I changed in test.lua from your zip file:
    Code:
    --local aAbilityToUpdateSwitch = nil;
    
    function onInit()
    --	aAbilityToUpdateSwitch = {
    --		["strength"] = AbilityScoreBonusesManager.updateStrengthRelatedBonuses,
    --		["dexterity"] = AbilityScoreBonusesManager.updateDexterityRelatedBonuses,
    --		["constitution"] = AbilityScoreBonusesManager.updateConstitutionRelatedBonuses,
    --		["intelligence"] = AbilityScoreBonusesManager.updateIntelligenceRelatedBonuses,
    --		["wisdom"] = AbilityScoreBonusesManager.updateWisdomRelatedBonuses,
    --		["charisma"] = AbilityScoreBonusesManager.updateCharismaRelatedBonuses
    --	};
    
    Debug.console("updateAttributeBonuses('strength') =", updateAttributeBonuses("strength"));
    	Debug.console("strength: " .. updateAttributeBonuses("strength"));
    	Debug.console("charisma: " .. updateAttributeBonuses("charisma"));
    	Debug.console("junk: " .. updateAttributeBonuses("junk"));
    end
    
    
    local	aAbilityToUpdateSwitch = {
    		["strength"] = function () AbilityScoreBonusesManager.updateStrengthRelatedBonuses() end,
    		["dexterity"] = function () AbilityScoreBonusesManager.updateDexterityRelatedBonuses() end,
    		["constitution"] = function () AbilityScoreBonusesManager.updateConstitutionRelatedBonuses() end,
    		["intelligence"] = function () AbilityScoreBonusesManager.updateIntelligenceRelatedBonuses() end,
    		["wisdom"] = function () AbilityScoreBonusesManager.updateWisdomRelatedBonuses() end,
    		["charisma"] = function () AbilityScoreBonusesManager.updateCharismaRelatedBonuses() end,
    	};
    
    function updateAttributeBonuses(nodeScore)
    -- the "local node func =" was a typo paste? "node" should not be there - didn't give error due to tuple feature ;)
    	local func = aAbilityToUpdateSwitch[nodeScore];
    	
    	if func ~= nil then
    		return func();
    	else
    		return "no matches";
    	end
    end

  8. #8
    Varsuuk's Avatar
    Join Date
    Dec 2015
    Location
    New York
    Posts
    2,075
    LOL - I am so obsessive... decided to verify one last diff between ours and I added an argument which should not make a difference...

    I added the following logging and method signature changes:
    Code:
    function updateStrengthRelatedBonuses(arg)
    Debug.console("updateStrengthRelatedBonuses");
    --	return "Strength";
    Debug.console("So, here is the arg: ", arg);
    return arg
    end
    
    -- left others as is, since it gets the error before they are called, didn't bother adding the args.

    WHY does it not want to return your string?
    Your original works...


    Received this in console:
    Code:
    Runtime Notice: Reloading ruleset
    Runtime Notice: s'updateStrengthRelatedBonuses'
    Runtime Notice: s'So, here is the arg: ' | s'hello world'
    Runtime Notice: s'updateAttributeBonuses('strength') ='
    Runtime Notice: s'updateStrengthRelatedBonuses'
    Runtime Notice: s'So, here is the arg: ' | s'hello world'
    Script Error: [string "test.lua"]:14: attempt to concatenate a nil value

  9. #9
    if you are using my test module, you need to change this line:
    Code:
    		return func();
    to

    Code:
    		return func(nodeScore);

    otherwise you are not passing anything to the function and you will get a nil error
    Attached Files Attached Files

  10. #10
    Varsuuk's Avatar
    Join Date
    Dec 2015
    Location
    New York
    Posts
    2,075
    Yup, I had already done that.
    I'll just attach what I did - remember, the reason I changed it from your WORKING example was that I got it to work in the post before I saw yours by making the an embedded method to call the one I wanted. So tried to duplicate it in your extension as well.

    See post #4 to see what I was trying to do here in my mod of yours to work like what I did.
    The odd thing is even though console prints "So here is the arg: hello world" and then does a return on it - the concat still says nil.

    Code:
      Debug.console("So, here is the arg: ", arg);
      return arg
    end

    Anyhow, attaching it
    Attached Files Attached Files

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
FG Spreadshirt Swag

Log in

Log in