Jump to content

Calling GetModConfigData from outside of modmain


Recommended Posts

Hello modders community!

I've been working on a Light Potion and decided to add some configuration to it in the modinfo so I can choose the light color!

I attempted to call in my prefab the data chosen on the config option screen. The problem is that the game do not pick the data from the modinfo and the light on the character remains unchanged, very normal.

I saw this threat on the forum and tried to put what is proposed but it is not working. I just want to add several configuration options in my lightpotion.lua so the color fits the choice made in the configuration options.

I will show you what's in my modinfo, in the top of my modmain and what's in the prefab so far, followed with the crash log. Ask anything if u need!

Modinfo :

Spoiler

name = Ada-Hadabra --GetModConfigData : USE NAME FOLDER INSTEAD!!! 
configuration_options =
{
	{
		name = "LIGHTCOLOR",
		label = "Potion Light Color",
		options = {
		
						{description = "Red", data = "Red"},
						{description = "Blue", data = "Blue"},
						{description = "Green", data = "Green"},
						{description = "Purple", data = "Purple"},
						{description = "Orange", data = "Orange"},
						{description = "Yellow", data = "Yellow"},
						{description = "White", data = "White"},
				},
				
		default = "Red",
	
	},
}

 

Modmain :

Spoiler

--I Really Don't Know What Should Be Here, But Not Crash...

GLOBAL.package.loaded["korrigan.modenv"] = env
GLOBAL.Red = (GetModConfigData("LIGHTCOLOR")=="Red")
GLOBAL.Blue = (GetModConfigData("LIGHTCOLOR")=="Blue")
GLOBAL.Green = (GetModConfigData("LIGHTCOLOR")=="Green")
GLOBAL.Purple = (GetModConfigData("LIGHTCOLOR")=="Purple")
GLOBAL.Orange = (GetModConfigData("LIGHTCOLOR")=="Orange")
GLOBAL.Yellow = (GetModConfigData("LIGHTCOLOR")=="Yellow")
GLOBAL.White = (GetModConfigData("LIGHTCOLOR")=="White")

 

Lightpotion.lua :

Spoiler

local name = "korrigan" --This is the mod folder name, not the one in modinfo!!!
local folder = KnownModIndex:GetModActualName(name)
local foldername = KnownModIndex:GetModActualName("korrigan") --This is the mod folder name!!!
local LIGHTCOLOR=GetModConfigData("LIGHTCOLOR", folder)
local modenv = require "korrigan.modenv" --As Told By Simplex
local Red = GetModConfigData("LIGHTCOLOR", foldername) --Not Sure
local Red = modenv.GetModConfigData("LIGHTCOLOR") --Not Sure

----Tested, Not Working
--local Red=ModIndex:GetModActualName(name)
--local Blue=ModIndex:GetModActualName(name)
--local Green=ModIndex:GetModActualName(name)
--local Purple=ModIndex:GetModActualName(name)
--local Orange=ModIndex:GetModActualName(name)
--local Yellow=ModIndex:GetModActualName(name)
--local White=ModIndex:GetModActualName(name)

local intens = 0.75
local potiontime = 105
local breakcounter = 0

local assets=
{
    Asset("ANIM", "anim/lightpotion.zip"),
    Asset("ATLAS", "images/inventoryimages/lightpotion.xml"),
    Asset("IMAGE", "images/inventoryimages/lightpotion.tex"),
}

 PrefabFiles = {
    "lightpotion",
}

local function reduce1(inst) --Works
	
	if breakcounter > 1 then
	else
		intens = 0.5
		inst.Light:SetIntensity(intens)
	end
	
end

local function reduce2(inst) --Works
	
	if breakcounter > 1 then
	else
		intens = 0.25
		inst.Light:SetIntensity(intens)	
	end
	
	inst.components.talker:Say("Light is reducing!", 4) --Hard To Make It Works (Talker nil value...)
	
end

local function reduce3(inst) --Works
	
	if breakcounter > 1 then
		breakcounter = breakcounter - 1
	else
		intens = 0
		inst.Light:SetIntensity(intens)
		inst.Light:Enable(false)
		print "Light off"
		breakcounter = breakcounter - 1
	end
	
	inst.components.talker:Say("Light has gone...", 4) --Hard To Make It Works (Talker nil value...)
	
end


local function oneaten(inst, eater)

	addlight(eater) --It MUST Work
	eater:DoTaskInTime(potiontime-80, reduce1) --Works
	eater:DoTaskInTime(potiontime-40, reduce2) --Works
	eater:DoTaskInTime(potiontime-1, reduce3)	--Works
	eater.components.talker:Say("Let there be light!", 4) --Works
end

local function addlight(eater) --It MUST Work

if inst.Light then
	else 
		inst.entity:AddLight()
		print "new light :("
	end
	
	intens = 0.75
	
	
	--
	breakcounter = breakcounter + 1
	print (breakcounter)
    --
	
    if Red then
    inst.Light:Enable(true)
    inst.Light:SetRadius(2)
    inst.Light:SetFalloff(.8)
    inst.Light:SetIntensity(intens)
    inst.Light:SetColour(255/255,0,0)

    else
    if Blue then
    inst.Light:Enable(true)
    inst.Light:SetRadius(2)
    inst.Light:SetFalloff(.8)
    inst.Light:SetIntensity(intens)
    inst.Light:SetColour(0,0,255/255) 

    else
    if Green then
    inst.Light:Enable(true)
    inst.Light:SetRadius(2)
    inst.Light:SetFalloff(.8)
    inst.Light:SetIntensity(intens)
    inst.Light:SetColour(0,255/255,0)

    else
    if Purple then
    inst.Light:Enable(true)
    inst.Light:SetRadius(2)
    inst.Light:SetFalloff(.8)
    inst.Light:SetIntensity(intens)
    inst.Light:SetColour(153/255,0,153)

	else
    if Orange then
    inst.Light:Enable(true)
    inst.Light:SetRadius(2)
    inst.Light:SetFalloff(.8)
    inst.Light:SetIntensity(intens)
    inst.Light:SetColour(255/255,128/255,0)

	else
    if Yellow then
    inst.Light:Enable(true)
    inst.Light:SetRadius(2)
    inst.Light:SetFalloff(.8)
    inst.Light:SetIntensity(intens)
    inst.Light:SetColour(255/255,255/255,0)
 
	else
    if White then
    inst.Light:Enable(true)
    inst.Light:SetRadius(2)
    inst.Light:SetFalloff(.8)
    inst.Light:SetIntensity(intens)
    inst.Light:SetColour(255/255,255/255,255/255)
							end
						end
					end
				end
			end
		end
	end
 end    

 

Crash log :

Spoiler

[00:01:17]: [string "scripts/modutil.lua"]:13: modname must be supplied manually if calling GetModConfigData from outside of modmain or modworldgenmain. Use ModIndex:GetModActualName(fancyname) function [fancyname is name string from modinfo].
LUA ERROR stack traceback:
        =[C] in function 'assert'
        scripts/modutil.lua(13,1) in function 'GetModConfigData'
        ../mods/korrigan/scripts/prefabs/lightpotion.lua(4,1) in function 'fn'
        scripts/mainfunctions.lua(95,1)
        =(tail call) ?
        =[C] in function 'xpcall'
        scripts/mods.lua(123,1)
        scripts/mods.lua(494,1) in function 'RegisterPrefabs'
        scripts/gamelogic.lua(206,1) in function 'LoadAssets'
        scripts/gamelogic.lua(772,1)
        =[C] in function 'SetPersistentString'
        scripts/saveindex.lua(70,1) in function 'Save'
        scripts/saveindex.lua(294,1)
        =[C] in function 'SerializeWorldSession'
        scripts/networking.lua(209,1) in function 'SerializeWorldSession'
        scripts/saveindex.lua(297,1) in function 'OnGenerateNewWorld'
        scripts/gamelogic.lua(783,1) in function 'cb'
        scripts/screens/worldgenscreen.lua(171,1) in function 'OnUpdate'
        scripts/frontend.lua(597,1) in function 'Update'
        scripts/update.lua(94,1)   

There is something wrong in modmain/prefab but I can't figure what it is. I tried different schemes, without luck. Red only is written for testing purpose.

Any help would be really appreciated, I'm sure I almost got it worked!

Note : Potions are stackable. I tried to put the addlight(eater) function in the oneaten function, which worked. But, when dropping the potions on the ground, the character loses its light!  The light entity was hold by the potions, not the character!

D4rkh0bb1T

Edited by D4rkh0bb1T
Link to comment
Share on other sites

GetModConfigData function that is available in modmain is defined in modutil|InsertPostInitFunctions() as follows:

env.GetModConfigData = function( optionname, get_local_config )
    initprint("GetModConfigData", optionname, get_local_config)
    return GetModConfigData(optionname, env.modname, get_local_config)
end

it calls the global GetModConfigData() with the modname parameter equal to the name of the current mod.

 

Thus if you want to use GetModConfigData() outside of modmain you have to specify mod name you are trying to access:

GetModConfigData("LIGHTCOLOR", "<your_temporary_dev_folder_name>") , but GetModConfigData("LIGHTCOLOR", "workshop-<your_mod's_id>") for uploaded version.

 

If you want to specify the name of the mod instead of its id, you can use modindex's translation service:

local modnameFancy = "Ada-Hadabra"
local modnameActual = KnownModIndex:GetModActualName(modnameFancy)
local optcolor
if modnameActual == nil then
    print(string.format("Mod '%s' not found", modnameFancy))
    optcolor = "Red"
else
    optcolor = GetModConfigData("LIGHTCOLOR", modnameActual)
end

 

You can also store the value in GLOBAL, just make sure the probability of the clash with other mod is low enough; something like

-- modmain:
GLOBAL.global("mods")
if GLOBAL.mods == nil then
    GLOBAL.mods = {}
end
GLOBAL.assert(type(GLOBAL.mods) == "table", string.format("Type of GLOBAL.mods is %s, expected table; caused most probably by incompatibility between mods.", type(GLOBAL.mods)))
GLOBAL.assert(GLOBAL.mods.AdaHadabra == nil, string.format("GLOBAL.mods.AdaHadabra is %s, expected nil; caused most probably by incompatibility between mods.", tostring(GLOBAL.mods.AdaHadabra)))
GLOBAL.mods.AdaHadabra = {}
GLOBAL.mods.AdaHadabra.LIGHTCOLOR = GetModConfigData("LIGHTCOLOR")

-- prefab:
local optcolor = mods.AdaHadabra.LIGHTCOLOR

 

Edited by Muche
Link to comment
Share on other sites

2 hours ago, Muche said:

Thus if you want to use GetModConfigData() outside of modmain you have to specify mod name you are trying to access:

GetModConfigData("LIGHTCOLOR", "<your_temporary_dev_folder_name>") , but GetModConfigData("LIGHTCOLOR", "workshop-<your_mod's_id>") for uploaded version.

 

If you want to specify the name of the mod instead of its id, you can use modindex's translation service:


local modnameFancy = "Ada-Hadabra"
local modnameActual = KnownModIndex:GetModActualName(modnameFancy)
local optcolor
if modnameActual == nil then
    print(string.format("Mod '%s' not found", modnameFancy))
    optcolor = "Red"
else
    optcolor = GetModConfigData("LIGHTCOLOR", modnameActual)
end

I put these lines in lightpotion at the top. But how do I call optcolor?

Then I also added local optcolor = mods.AdaHadabra.LIGHTCOLOR just below, the headline prefab looks like this :

Spoiler

local name = "korrigan"
local folder = KnownModIndex:GetModActualName(name)
local foldername = KnownModIndex:GetModActualName("korrigan")
local modenv = require "korrigan.modenv"
local Red = modenv.GetModConfigData("LIGHTCOLOR")

GetModConfigData("LIGHTCOLOR", "korrigan") --To be sure
local modnameFancy = "Ada-Hadabra"
local modnameActual = KnownModIndex:GetModActualName(modnameFancy)

local optcolor
if modnameActual == nil then
    print(string.format("Mod '%s' not found", modnameFancy))
    optcolor = "Red"
else
    optcolor = GetModConfigData("LIGHTCOLOR", modnameActual)
end

local optcolor = mods.AdaHadabra.LIGHTCOLOR

local intens = 0.75
local potiontime = 105
local breakcounter = 0

--Code below, just like the first post

 

 

2 hours ago, Muche said:

You can also store the value in GLOBAL, just make sure the probability of the clash with other mod is low enough; something like


-- modmain:
GLOBAL.global("mods")
if GLOBAL.mods == nil then
    GLOBAL.mods = {}
end
GLOBAL.assert(type(GLOBAL.mods) == "table", string.format("Type of GLOBAL.mods is %s, expected table; caused most probably by incompatibility between mods.", type(GLOBAL.mods)))
GLOBAL.assert(GLOBAL.mods.AdaHadabra == nil, string.format("GLOBAL.mods.AdaHadabra is %s, expected nil; caused most probably by incompatibility between mods.", tostring(GLOBAL.mods.AdaHadabra)))
GLOBAL.mods.AdaHadabra = {}
GLOBAL.mods.AdaHadabra.LIGHTCOLOR = GetModConfigData("LIGHTCOLOR")

-- prefab:
local optcolor = mods.AdaHadabra.LIGHTCOLOR

With this code, my modmain headline looks like this now :

Spoiler

--Headlines		
local STRINGS = GLOBAL.STRINGS
local Ingredient = GLOBAL.Ingredient
local RECIPETABS = GLOBAL.RECIPETABS
local TECH = GLOBAL.TECH
local require = GLOBAL.require

GLOBAL.global("mods")
if GLOBAL.mods == nil then
    GLOBAL.mods = {}
end
GLOBAL.assert(type(GLOBAL.mods) == "table", string.format("Type of GLOBAL.mods is %s, expected table; caused most probably by incompatibility between mods.", type(GLOBAL.mods)))
GLOBAL.assert(GLOBAL.mods.AdaHadabra == nil, string.format("GLOBAL.mods.AdaHadabra is %s, expected nil; caused most probably by incompatibility between mods.", tostring(GLOBAL.mods.AdaHadabra)))
GLOBAL.mods.AdaHadabra = {}
GLOBAL.mods.AdaHadabra.LIGHTCOLOR = GetModConfigData("LIGHTCOLOR")

GLOBAL.package.loaded["korrigan.modenv"] = env

GLOBAL.Red = (GetModConfigData("LIGHTCOLOR")=="Red")
GLOBAL.Blue = (GetModConfigData("LIGHTCOLOR")=="Blue")
GLOBAL.Green = (GetModConfigData("LIGHTCOLOR")=="Green")
GLOBAL.Purple = (GetModConfigData("LIGHTCOLOR")=="Purple")
GLOBAL.Orange = (GetModConfigData("LIGHTCOLOR")=="Orange")
GLOBAL.Yellow = (GetModConfigData("LIGHTCOLOR")=="Yellow")
GLOBAL.White = (GetModConfigData("LIGHTCOLOR")=="White")

 

I have no crash, but the color remains the same, unchanged. Beside, what could cause the mod to clash with other mod?

D4rkh0bb1T

Edited by D4rkh0bb1T
Link to comment
Share on other sites

The thing is, you need only one of those options.

So 1) either with the GetModConfigData:

Spoiler

--
-- modmain
--
--Headlines     
local STRINGS = GLOBAL.STRINGS
local Ingredient = GLOBAL.Ingredient
local RECIPETABS = GLOBAL.RECIPETABS
local TECH = GLOBAL.TECH
local require = GLOBAL.require

--
-- prefab
--
local modnameFancy = "Ada-Hadabra"
local modnameActual = KnownModIndex:GetModActualName(modnameFancy)

local optcolor
if modnameActual == nil then
    print(string.format("Mod '%s' not found", modnameFancy))
    optcolor = "Red"
else
    optcolor = GetModConfigData("LIGHTCOLOR", modnameActual)
end

local colors = {
    Red = {0, 0, 255/255},
    Green = {0, 255/255, 0},
    Purple = {153/255, 0, 153/255},
    Orange = {255/255, 128/255, 0},
    Yellow = {255/255, 255/255, 0},
    White = {255/255, 255/255, 255/255}
}

local intens = 0.75
local potiontime = 105
local breakcounter = 0

local assets=
{
    Asset("ANIM", "anim/lightpotion.zip"),
    Asset("ATLAS", "images/inventoryimages/lightpotion.xml"),
    Asset("IMAGE", "images/inventoryimages/lightpotion.tex"),
}

PrefabFiles = {
    "lightpotion",
}

local function reduce1(inst) --Works
    if breakcounter > 1 then
    else
        intens = 0.5
        inst.Light:SetIntensity(intens)
    end
end

local function reduce2(inst) --Works
    if breakcounter > 1 then
    else
        intens = 0.25
        inst.Light:SetIntensity(intens) 
    end
    
    inst.components.talker:Say("Light is reducing!", 4) --Hard To Make It Works (Talker nil value...)
end

local function reduce3(inst) --Works
    if breakcounter > 1 then
        breakcounter = breakcounter - 1
    else
        intens = 0
        inst.Light:SetIntensity(intens)
        inst.Light:Enable(false)
        print "Light off"
        breakcounter = breakcounter - 1
    end
    
    inst.components.talker:Say("Light has gone...", 4) --Hard To Make It Works (Talker nil value...)
end


local function oneaten(inst, eater)
    addlight(eater) --It MUST Work
    eater:DoTaskInTime(potiontime-80, reduce1) --Works
    eater:DoTaskInTime(potiontime-40, reduce2) --Works
    eater:DoTaskInTime(potiontime-1, reduce3)   --Works
    eater.components.talker:Say("Let there be light!", 4) --Works
end

local function addlight(eater) --It MUST Work
    if inst.Light then
    else 
        inst.entity:AddLight()
        print "new light :("
    end
    
    intens = 0.75
    
    --
    breakcounter = breakcounter + 1
    print (breakcounter)
    --
    
    inst.Light:Enable(true)
    inst.Light:SetRadius(2)
    inst.Light:SetFalloff(.8)
    inst.Light:SetIntensity(intens)
    inst.Light:SetColour(unpack(colors[optcolor]))
end

 

or 2) storing it in GLOBAL:

Spoiler

--
-- modmain
--
--Headlines     
local STRINGS = GLOBAL.STRINGS
local Ingredient = GLOBAL.Ingredient
local RECIPETABS = GLOBAL.RECIPETABS
local TECH = GLOBAL.TECH
local require = GLOBAL.require

GLOBAL.global("mods")
if GLOBAL.mods == nil then
    GLOBAL.mods = {}
end
GLOBAL.assert(type(GLOBAL.mods) == "table", string.format("Type of GLOBAL.mods is %s, expected table; caused most probably by incompatibility between mods.", type(GLOBAL.mods)))
GLOBAL.assert(GLOBAL.mods.AdaHadabra == nil, string.format("GLOBAL.mods.AdaHadabra is %s, expected nil; caused most probably by incompatibility between mods.", tostring(GLOBAL.mods.AdaHadabra)))
GLOBAL.mods.AdaHadabra = {}
GLOBAL.mods.AdaHadabra.LIGHTCOLOR = GetModConfigData("LIGHTCOLOR")

--
-- prefab
--
local optcolor = mods.AdaHadabra.LIGHTCOLOR

local colors = {
    Red = {0, 0, 255/255},
    Green = {0, 255/255, 0},
    Purple = {153/255, 0, 153/255},
    Orange = {255/255, 128/255, 0},
    Yellow = {255/255, 255/255, 0},
    White = {255/255, 255/255, 255/255}
}

local intens = 0.75
local potiontime = 105
local breakcounter = 0

local assets=
{
    Asset("ANIM", "anim/lightpotion.zip"),
    Asset("ATLAS", "images/inventoryimages/lightpotion.xml"),
    Asset("IMAGE", "images/inventoryimages/lightpotion.tex"),
}

PrefabFiles = {
    "lightpotion",
}

local function reduce1(inst) --Works
    if breakcounter > 1 then
    else
        intens = 0.5
        inst.Light:SetIntensity(intens)
    end
end

local function reduce2(inst) --Works
    if breakcounter > 1 then
    else
        intens = 0.25
        inst.Light:SetIntensity(intens) 
    end
    
    inst.components.talker:Say("Light is reducing!", 4) --Hard To Make It Works (Talker nil value...)
end

local function reduce3(inst) --Works
    if breakcounter > 1 then
        breakcounter = breakcounter - 1
    else
        intens = 0
        inst.Light:SetIntensity(intens)
        inst.Light:Enable(false)
        print "Light off"
        breakcounter = breakcounter - 1
    end
    
    inst.components.talker:Say("Light has gone...", 4) --Hard To Make It Works (Talker nil value...)
end


local function oneaten(inst, eater)
    addlight(eater) --It MUST Work
    eater:DoTaskInTime(potiontime-80, reduce1) --Works
    eater:DoTaskInTime(potiontime-40, reduce2) --Works
    eater:DoTaskInTime(potiontime-1, reduce3)   --Works
    eater.components.talker:Say("Let there be light!", 4) --Works
end

local function addlight(eater) --It MUST Work
    if inst.Light then
    else 
        inst.entity:AddLight()
        print "new light :("
    end
    
    intens = 0.75
    
    --
    breakcounter = breakcounter + 1
    print (breakcounter)
    --
    
    inst.Light:Enable(true)
    inst.Light:SetRadius(2)
    inst.Light:SetFalloff(.8)
    inst.Light:SetIntensity(intens)
    inst.Light:SetColour(unpack(colors[optcolor]))
end

 

 

1 hour ago, D4rkh0bb1T said:

Beside, what could cause the mod to clash with other mod?

If the other mod chose the same name and method of accessing its configuration options, or version of your own mod, if you by accident enable both the version in workshop-<id> and dev folder.

Edited by Muche
Link to comment
Share on other sites

I'm really trying to make it works. I commented out some lines on the top of my script, which I don't know if they are right.

Spoiler

--local name = "korrigan"
--local folder = KnownModIndex:GetModActualName(name)
--local foldername = KnownModIndex:GetModActualName("korrigan")
--local modenv = require "korrigan.modenv"
--local Red = modenv.GetModConfigData("LIGHTCOLOR")

--GetModConfigData("LIGHTCOLOR", "korrigan") --To be sure

Then I tried the 1st option. Nothing in the modmain + the new things in the prefab - just like in your post. The light remains unchanged.

So I tried the 2nd option. Global things in the modmain + the new things in the prefab. The light remains unchanged...

When I say "new things", I mean local optcolor, local color and (unpack(colors[optcolor]))

I might misunderstand something... and the modname should'nt be the mod actual folder (korrigan)? AdaHadabra "Ada-Hadabra" = modinfo's name.

Link to comment
Share on other sites

Well, I assumed that your hard-coded way of specifying the color worked, and just needed it to be configurable. By seeing just the snippets of the code, I have no idea how they are used.

For example, addlight function is being called in oneaten function, but is defined after it; addlight function references inst, but that's nowhere to be seen to be defined.

 

Anyways, there's always the old-fashioned way. Add some debug prints, e.g. print(string.format("[lightpotion|addlight(%s)] optcolor=%s", tostring(eater), tostring(optcolor))) at the start of the addlight function, run it and see what the log says the color it read is.

 

Yes, modname of a mod (used for global version of GetModConfigData) is the folder name of the mod. That's why the KnownModIndex:GetModActualName(modnameFancy) is used, it translates mod's name as it is specified in modinfo into modname as its folder name.

This way you wouldn't have to change all the names after you upload the mod onto the workshop from your temporary dev folder name into final workshop-<id> folder name; which you don't know before you actually upload the mod.

Link to comment
Share on other sites

Good! I passed eater all the way into the addlight function instead of inst and put the local function above oneaten and that's all!

It seems that your code nor mine was the trouble. I must admit that your way to simplify the color makes things easier to understand, this is a punch in my face, but a relief to my brain!

A very big thanks to you and the time you took to help me out! Time to play!

D4rkh0bb1T

Link to comment
Share on other sites

I'm also having some trouble with this type of coding.  I have a couple of mods that I'm using configuration settings to change prefab variables, sort of the equivalent of TUNING variables. I have a mod that works that adds new tuning variables via string referencing, but it uses an existing component and I'm trying to do it with prefabs

Link to comment
Share on other sites

@mf99k You can just add them to the TUNING table. For example, GLOBAL.TUNING.MY_PREFABS_SPECIAL_VALUE = 30 (in the modmain).

That's really just another version of converting config data into variables in the global space. To reduce the probability of namespace clashes, you could also make it a subtable of TUNING, like:

GLOBAL.TUNING.MYMODNAME = {
	SPECIALVALUE = 30,
}

 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
  • Create New...