Jump to content

[Explanation requested] Overriding a function, but I get an error


Recommended Posts

Hi,

I'm trying to modify the component hounded, specifically function self:OnUpdate(dt), so that I can increase the delay between each spawn (spawninforec.timetonext).

Unfortunately, I get the following error on line 16: attempt to get length of global '_activeplayers' (a nil value)

I thought that AddComponentPostInit would simply insert the function into hounded.lua and overwrite the function of the same name. I think there is a few concepts that I haven't quite grasped with AddComponentPostInit, since it doesn't seem to insert the function.

I've also tried to simply add a function that would print a message, but I can't call the function in-game, so I'm guessing it's not inserted in the component hounded.lua.

How does AddComponentPostInit work? What are my mistakes and/or misunderstandings?

Thank you so much for helping me with this.

You can find the modmain.lua attached to this post, or here:

local require = GLOBAL.require
local hounded = require "components/hounded"

local spawnDelayer = GetModConfigData("mySpawnDelay") or 0

if spawnDelayer ~= 0 then

	function hounded_postinit(component)
	
		function component:OnUpdate(dt)
			if _spawnmode == "never" then
				return
			end

			-- if there's no players, then don't even try
			if #_activeplayers == 0  or not _attackplanned then
				return
			end

			_timetoattack = _timetoattack - dt

			if _timetoattack < 0 then
				-- Okay, it's hound-day, get number of dogs for each player
				if not _spawninfo then
					GetWaveAmounts()
				end

				_warning = false

				local playersdone = {}
				for i,spawninforec in ipairs(_spawninfo) do
					spawninforec.timetonext = spawninforec.timetonext - dt
					if spawninforec.spawnstorelease > 0 and spawninforec.timetonext < 0 then
						-- hounds can attack anyone in the group, even new players.
						-- That's the risk you take!
						local playeridx = math.random(#spawninforec.players)
						ReleaseSpawn(spawninforec.players[playeridx])
						spawninforec.spawnstorelease = spawninforec.spawnstorelease - 1

						local day = spawninforec.averageplayerage / TUNING.TOTAL_DAY_TIME
						if day < 20 then
							spawninforec.timetonext = 3 + math.random()*5
						elseif day < 60 then
							spawninforec.timetonext = 2 + math.random()*3
						elseif day < 100 then
							spawninforec.timetonext = .5 + math.random()*3
						else
							spawninforec.timetonext = .5 + math.random()*1
						end
						-- ##########################################################
						-- ######### This is where I'm adding the mod delay #########
						-- ##########################################################
						spawninforec.timetonext = spawninforec.timetonext + spawnDelayer

					end
					if spawninforec.spawnstorelease <= 0 then
						table.insert(playersdone,i)
					end
				end
				for i,v in ipairs(playersdone) do
					table.remove(_spawninfo, v)
				end
				if #_spawninfo == 0 then
					_spawninfo = nil
					PlanNextAttack()
				end
			else
				if not _warning and _timetoattack < _warnduration then
					_warning = true
					_timetonextwarningsound = 0
				end
			end

			if _warning then
				_timetonextwarningsound	= _timetonextwarningsound - dt

				if _timetonextwarningsound <= 0 then
					_announcewarningsoundinterval = _announcewarningsoundinterval - 1
					if _announcewarningsoundinterval <= 0 then
						_announcewarningsoundinterval = 10 + math.random(5)
						self:DoWarningSpeech()
					end

					_timetonextwarningsound =
						(_timetoattack < 30 and .3 + math.random(1)) or
						(_timetoattack < 60 and 2 + math.random(1)) or
						(_timetoattack < 90 and 4 + math.random(2)) or
												5 + math.random(4)
					self:DoWarningSound()
				end
			end
		end
		
	end
	
	AddComponentPostInit("hounded", hounded_postinit)

end

 

modmain.lua

Link to comment
Share on other sites

The problem is scope.

AddComponentPostInit makes the component call your function in the mod's environment sandbox.

Then the variables referenced in the core file, hounded.lua, are in the local scope.

Thus no mod can directly change these without heavy use of lua's debug library, and it is impractical to do with its higher maintenance.

 

A lot of the older core files have this happening in them with a heavy amount of private variables and functions.

 

 

To call print from a mod, you must use the GLOBAL sandbox variable escape for functions defined elsewhere.

GLOBAL.print("Debug message!")

 

I see no clean way of editing this file with the current mod API and these old files having locals instead of globals.

 

 

Also I had a chuckle at this (components/hounded.lua:537-541):

function self:LongUpdate(dt)
	self:OnUpdate(dt)
end

--self.LongUpdate = self.OnUdpate
----------------------------^^

 

Link to comment
Share on other sites

Thank you so much for your clear answer CarlZalph! :wilson_love:

You really have helped clear lots of the fog in my head.
The errors I would get sometimes make so much sense now.

Thank you very much once again.

Link to comment
Share on other sites

7 hours ago, Nakiamiir said:

The errors I would get sometimes make so much sense now.

You can still kind of do your thing without using lua's debug library.

If in your mod, you have a scripts/components/hounded.lua, the game will use that file.

After that, in modmain you put something like

GLOBAL.TUNING.HOUNDSPAWNDELAYER = GetModConfigData("mySpawnDelay") or 0

And then, in your copy-pasted hounded.lua pasted into your mod folder, you edit it and you add your line:

spawninforec.timetonext = spawninforec.timetonext + TUNING.HOUNDSPAWNDELAYER

 

The downsides are that your mod would be incompatible with other mods that alter hounded.lua, or that your hounded.lua file won't have any updates the hounded.lua of the game receives.

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...