Jump to content

Recommended Posts

Hello

I have a custom selection of monsters for hunts, my own hunter.lua

I have "AddComponentPostInit("hunter",Class)" in my modmain, however this means whenever Klei edits the file I have change my own file just the same or else everything breaks.

How can I include my new hunter monster list into my modmain.lua so I don't have to rely on a separate lua file?

Link to comment
https://forums.kleientertainment.com/forums/topic/130788-hunterlua/
Share on other sites

27 minutes ago, krylincy said:

as decduck3 said, you need to extend the file instead of overwriting it completely.

i dont know what you changed in that file but you can attach it with 


AddComponentPostInit("hunter", function() ... end)

 

My change is directly a modification of klei's code

local _alternate_beasts = { "claywarg", "warg", "gingerbreadwarg", "spat", "mermking", "lordfruitfly" }

so if I put it in my modman will that overwrite klei's alternate beasts?

The problem here is that your change is in a local variable, that means with a ComponentPostInit you won't be able to change it. 

_alternate_beasts is referenced in SpawnHuntedBeast, which in turn is referenced in self:OnDirtInvestigated, which is the first function you could change as it's not local. You could try and make a change to this function which calls a custom SpawnHuntedBeast which references your list. Then you would only need to change something if Klei changes self:OnDirtInvestigated or SpawnHuntedBeast.

Another way to do it would be with the upvalue hacker of Rezecib. You make your way up to the local table of _alternate_beasts and change these parameters. The advantage is that as long Klei does not change which function calls which function, you won't need to update you mod, even if there are changes in the code. It's a little bit more complex this way, I don't know if it's worse in a performance way, but it works.

  • Like 2
11 hours ago, Monti18 said:

He is a modder, he made the upvalue hacker, you can find the file here in his mod.

https://github.com/rezecib/Rezecib-s-Rebalance/blob/master/scripts/tools/upvaluehacker.lua

 

I tried having a go at making my own block for hunter.lua

-- New Hunt
AddComponentPostInit("hunter", function(self)
local _alternate_NEW = { "claywarg", "warg", "gingerbreadwarg", "spat", "mermking", "lordfruitfly" }
local function SpawnHuntedBeast(hunt, pt)
    assert(hunt)
    --print("Hunter:SpawnHuntedBeast")

    local spawn_pt = GetSpawnPoint(pt, TUNING.HUNT_SPAWN_DIST, hunt)
    if spawn_pt ~= nil then
		local spawn_x, spawn_y, spawn_z = spawn_pt:Get()
        local huntedbeast = SpawnPrefab(
            (self:IsWargShrineActive() and "claywarg") or
            (math.random() <= GetAlternateBeastChance() and GetRandomItem(_alternate_NEW)) or
            (TheWorld.state.iswinter and _beast_prefab_winter) or
			(TheWorld.state.isspring and TheWorld.state.israining and TheWorld.Map:FindVisualNodeAtPoint(spawn_x, spawn_y, spawn_z, "sandstorm") and _beast_prefab_spring) or
            _beast_prefab_summer
        )

        if huntedbeast ~= nil then
            --print("Kill the Beast!")
            huntedbeast.Physics:Teleport(spawn_x, spawn_y, spawn_z)

            huntedbeast:PushEvent("spawnedforhunt")
            return true
        end
    end
    --print("Hunter:SpawnHuntedBeast FAILED")
    return false
	end
end)

It doesn't work, the game still spawns the default stuff. I don't get it

I forgot that the function self:OnDirtInvestigated has more local functions that are called, but perhaps it still works.

You now have your two local functions, but the game adds them after the component is loaded, that means that the references to the local functions that are in the function OnDirtInvestigated are already set, which means that your functions cannot be called as nobody knows where they are.

You will then need to save the previous OnDirtInvestigated and write a new one that references your functions. As the function OnDirtInvestigated is not local, it will overwrite the previous one from the original file.

You could try something like this:

Spoiler

AddComponentPostInit("hunter", function(self)
   --your code frome before--
    local old_ondirtinvestigated = self.OnDirtInvestigated  --we save the old OnDirtInvestigated
    self.OnDirtInvestigated = function(self,pt,doer) --we write a new OnDirtInvestigated
      local hunt = nil
    -- find the hunt this pile belongs to
    for i,v in ipairs(_activehunts) do
        if v.lastdirt ~= nil and v.lastdirt:GetPosition() == pt then
            hunt = v
            inst:RemoveEventCallback("onremove", v.lastdirt._ondirtremove, v.lastdirt)
            break
        end
    end

    if hunt == nil then
        return
    end
    hunt.activeplayer = doer
    if hunt.numtrackstospawn ~= nil and hunt.numtrackstospawn > 0 then
        if SpawnTrack(pt, hunt) then
            --print("    ", hunt.trackspawned, hunt.numtrackstospawn)
            if hunt.trackspawned == hunt.numtrackstospawn then
          		if SpawnHuntedBeast(hunt,pt) then
                    --print("...you found the last track, now find the beast!")
                    hunt.activeplayer:PushEvent("huntbeastnearby")
                    StartCooldown(inst, hunt)
                else
            		return old_ondirtinvestigated(self,pt,doer) --we return the old OnDirtInvestigated to get the same results
            	end
           else
          	  return old_ondirtinvestigated(self,pt,doer)
          end
     end
end)
      

 

You would need to add SpawnTrack and StartCooldown to the list of functions that you need to define like they are in the game right now. 

The problem is here again that it's now a lot of functions that could change if Klei decides to change something.

I think I would then rather go with the upvalue hacker.

Add the upvalue hacker file to your scripts folder and try if this works.

AddClassPostConstruct("components/hunter", function(self)
    local _alternate_beasts = UpvalueHacker.GetUpvalue(self.OnDirtInvestigated, "SpawnHuntedBeast", "_alternate_beasts")
    --if you understand the principle, upvalue hacking is pretty easy. We start in the component itself. To get to our table of _alternate_beasts, 
    --we need to go through self.OnDirtInvestigated, then go through the local function SpawnHuntedBeast, which is why it's between "". 
    --In SpawnHuntedBeast, we have the reference to the table _alternate_beasts, which we then write as the last argument. 
    --As this is only a table that needs to be changed, you don't even need to use SetUpvalue.
    _alternate_beasts = {} --we clear the table
    _alternate_beasts {"your beasts"} --we set the new beasts
 end)

 

  • Like 3
local UpvalueHacker = GLOBAL.require("tools/upvaluehacker")

--[[ Adding to the Hunt Component]]
AddClassPostConstruct("components/hunter", function (self)
    local alternate_beasts = { "warg", "spat", "MyCustomMob" }
    UpvalueHacker.SetUpvalue(self.OnDirtInvestigated, alternate_beasts, "SpawnHuntedBeast", "_alternate_beasts")
end)

Adding this in your modmain.lua will make your mob spawns with equal chance when the hunt returns a hostile mob.

@edit

Also, you need the Rezecib's UpvalueHacker in the folder "scripts/tools"

 

Edited by kavaline
  • Like 2
1 hour ago, kavaline said:

local UpvalueHacker = GLOBAL.require("tools/upvaluehacker")

--[[ Adding to the Hunt Component]]
AddClassPostConstruct("components/hunter", function (self)
    local alternate_beasts = { "warg", "spat", "MyCustomMob" }
    UpvalueHacker.SetUpvalue(self.OnDirtInvestigated, alternate_beasts, "SpawnHuntedBeast", "_alternate_beasts")
end)

Adding this in your modmain.lua will make your mob spawns with equal chance when the hunt returns a hostile mob.

@edit

Also, you need the Rezecib's UpvalueHacker in the folder "scripts/tools"

 

To add on, I think it'd be better to do something like

local UpvalueHacker = GLOBAL.require("tools/upvaluehacker")

AddComponentPostInit("hunter", function(self)
	local alternate_beasts = UpvalueHacker.GetUpValue(self.OnDirtInvestigated, "_alternate_beasts")

	table.insert(alternate_beasts, "MyCustomMob") --insert custom mob into the table

	UpvalueHacker.SetUpValue(self.OnDirtInvestigated, alternate_beasts, "SpawnHauntedBeast", "_alternate_beasts")
end)

This way, you don't overwrite the entire table and simply insert your mob into it, Just in case Klei, or another mod, adds alternate beasts too your mod won't clash with it.

  • Sanity 1
2 minutes ago, Hornete said:

To add on, I think it'd be better to do something like


local UpvalueHacker = GLOBAL.require("tools/upvaluehacker")

AddComponentPostInit("hunter", function(self)
	local alternate_beasts = UpvalueHacker.GetUpValue(self.OnDirtInvestigated, "_alternate_beasts")

	table.insert(alternate_beasts, "MyCustomMob") --insert custom mob into the table

	UpvalueHacker.SetUpValue(self.OnDirtInvestigated, alternate_beasts, "SpawnHauntedBeast", "_alternate_beasts")
end)

This way, you don't overwrite the entire table and simply insert your mob into it, Just in case Klei, or another mod, adds alternate beasts too your mod won't clash with it.

ok but two things

It's just for hunt surprises, not koalefants

and I don't have a custom mob. I just want to put more klei mobs along the warg/ewecus

6 minutes ago, Well-met said:

Crashes with the error [00:00:25]: [string "../mods/mymod/modmain.lua"]:119: attempt to call field 'GetUpValue' (a nil value)

I accidentally capitalised the V in Value. Change GetUpValue to GetUpvalue and SetUpValue to SetUpvalue and itll hopefully work.

  • Potato Cup 1
4 minutes ago, Hornete said:

I accidentally capitalised the V in Value. Change GetUpValue to GetUpvalue and SetUpValue to SetUpvalue and itll hopefully work.

Thank you

but now it crashes with [00:05:46]: [string "../mods/mymod/modmain.lua"]:122: bad argument #1 to 'insert' (table expected, got nil)

Is this the correct format?

table.insert(alternate_beasts, "claywarg", "warg", "gingerbreadwarg", "spat", "mermking", "lordfruitfly" ) --insert custom mob into the table

 

  • Like 1
30 minutes ago, Well-met said:

Thank you

but now it crashes with [00:05:46]: [string "../mods/mymod/modmain.lua"]:122: bad argument #1 to 'insert' (table expected, got nil)

Is this the correct format?


table.insert(alternate_beasts, "claywarg", "warg", "gingerbreadwarg", "spat", "mermking", "lordfruitfly" ) --insert custom mob into the table

 

Nah, table.insert doesn't work like that, you'd need to do something like...
 

table.insert(alternate_beasts, "claywarg")
table.insert(alternate_beasts, "gingerbreadwarg")
table.insert(alternate_beasts, "mermking")
...etc...

Or, if you'd like to make it cleaner and shorter you can make a 2nd table to loop through and then add into alternate_beasts in that loop
 

local alternate_beasts_to_add = {
	"claywarg",
	"gingerbreadwarg",
	--etc
}

for k, v in pairs(alternate_beasts_to_add) do
	table.insert(alternate_beasts, v)
end

 

  • GL Happy 1
25 minutes ago, Hornete said:

Nah, table.insert doesn't work like that, you'd need to do something like...
 


table.insert(alternate_beasts, "claywarg")
table.insert(alternate_beasts, "gingerbreadwarg")
table.insert(alternate_beasts, "mermking")
...etc...

Or, if you'd like to make it cleaner and shorter you can make a 2nd table to loop through and then add into alternate_beasts in that loop
 


local alternate_beasts_to_add = {
	"claywarg",
	"gingerbreadwarg",
	--etc
}

for k, v in pairs(alternate_beasts_to_add) do
	table.insert(alternate_beasts, v)
end

 

Thank you

one last question, do I need to re-add the warg and ewecus since they are already in the base game?

1 minute ago, Well-met said:

Thank you

one last question, do I need to re-add the warg and ewecus since they are already in the base game?

Nope, you won't need to re-add warg and ewecus, since we're adding onto the existing table into the game which already has warg and ewecus.

  • Big Ups 1
17 minutes ago, Hornete said:

Nope, you won't need to re-add warg and ewecus, since we're adding onto the existing table into the game which already has warg and ewecus.

I'm still having a crash:(

[01:07:37]: [string "../mods/mymod/modmain.lua"]:122: bad argument #1 to 'insert' (table expected, got nil)

The code looks like this

-- New Hunts
local UpvalueHacker = GLOBAL.require("tools/upvaluehacker")

AddComponentPostInit("hunter", function(self)
	local alternate_beasts = UpvalueHacker.GetUpvalue(self.OnDirtInvestigated, "_alternate_beasts")

	table.insert(alternate_beasts, "claywarg")
	table.insert(alternate_beasts, "gingerbreadwarg")
	table.insert(alternate_beasts, "mermking")
	table.insert(alternate_beasts, "lordfruitfly")

	UpvalueHacker.SetUpvalue(self.OnDirtInvestigated, alternate_beasts, "SpawnHauntedBeast", "_alternate_beasts")
end)

 

Edited by Well-met
  • Like 1
37 minutes ago, Well-met said:

I'm still having a crash:(

[01:07:37]: [string "../mods/mymod/modmain.lua"]:122: bad argument #1 to 'insert' (table expected, got nil)

The code looks like this


-- New Hunts
local UpvalueHacker = GLOBAL.require("tools/upvaluehacker")

AddComponentPostInit("hunter", function(self)
	local alternate_beasts = UpvalueHacker.GetUpvalue(self.OnDirtInvestigated, "_alternate_beasts")

	table.insert(alternate_beasts, "claywarg")
	table.insert(alternate_beasts, "gingerbreadwarg")
	table.insert(alternate_beasts, "mermking")
	table.insert(alternate_beasts, "lordfruitfly")

	UpvalueHacker.SetUpvalue(self.OnDirtInvestigated, alternate_beasts, "SpawnHauntedBeast", "_alternate_beasts")
end)

 

Ah woops, This should now work hopefully :)
 

-- New Hunts
local UpvalueHacker = GLOBAL.require("tools/upvaluehacker")

AddComponentPostInit("hunter", function(self)
	local _SpawnedHuntedBeast = UpvalueHacker.GetUpvalue(self.OnDirtInvestigated, "SpawnHuntedBeast") --We need to get the SpawnHauntedBeast function since that's where the _alternate_beasts table is used
	local alternate_beasts = UpvalueHacker.GetUpvalue(_SpawnedHauntedBeast, "_alternate_beasts") --Now we can get the alternate_beasts table

	table.insert(alternate_beasts, "claywarg")
	table.insert(alternate_beasts, "gingerbreadwarg")
	table.insert(alternate_beasts, "mermking")
	table.insert(alternate_beasts, "lordfruitfly")

	UpvalueHacker.SetUpValue(_SpawnHuntedBeast, "_alternate_beasts", alternate_beasts)
end)

 

Edited by Hornete
  • Like 1
7 minutes ago, Hornete said:

Ah woops, This should now work hopefully :)
 


-- New Hunts
local UpvalueHacker = GLOBAL.require("tools/upvaluehacker")

AddComponentPostInit("hunter", function(self)
	local _SpawnedHuntedBeast = UpvalueHacker.GetUpvalue(self.OnDirtInvestigated, "SpawnHuntedBeast") --We need to get the SpawnHauntedBeast function since that's where the _alternate_beasts table is used
	local alternate_beasts = UpvalueHacker.GetUpvalue(_SpawnedHauntedBeast, "_alternate_beasts") --Now we can get the alternate_beasts table

	table.insert(alternate_beasts, "claywarg")
	table.insert(alternate_beasts, "gingerbreadwarg")
	table.insert(alternate_beasts, "mermking")
	table.insert(alternate_beasts, "lordfruitfly")

	UpvalueHacker.SetUpValue(_SpawnHuntedBeast, "_alternate_beasts", alternate_beasts)
end)

 

Now it's crashing with the oddest error message I've ever seen

[00:40:51]: [string "../mods/mymod/scripts/tools/upvaluehacker...."]:14: We were looking for _alternate_beasts, but the value before it, (the starting point), wasn't a function (it was a nil). Here's the full chain: (the starting point), _alternate_beasts

 

Edited by Well-met
  • Like 1
12 minutes ago, Well-met said:

Now it's crashing with the oddest error message I've ever seen


[00:40:51]: [string "../mods/mymod/scripts/tools/upvaluehacker...."]:14: We were looking for _alternate_beasts, but the value before it, (the starting point), wasn't a function (it was a nil). Here's the full chain: (the starting point), _alternate_beasts

 

Oh, i'm a moron, I accidentally spelled _SpawnedHauntedBeast instead of _SpawnHuntedBeast

local alternate_beasts = UpvalueHacker.GetUpvalue(_SpawnedHauntedBeast, "_alternate_beasts")

Just correct the typo and it'll work haha.

  • Haha 1

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
×
  • Create New...