Recommended Posts

TheSpecter    0

Hello, I am trying to make adjustments to a mod that makes birds spawn more frequently, but I would like to make that specific to crows. I already checked an archived post here:

 


But Mr.CarlZalph's code did not really go through, making the game say that "AddComponentPostInit" was not declared. I am not at all a lua strong guy, and I couldn't find any helpful information anywhere else but that one topic.

The code was:

 

AddComponentPostInit(
    "birdspawner",
    function(inst)
        if GLOBAL.TheWorld.ismastersim
        then
            if inst.SpawnBird and inst.GetSpawnPoint
            then
                local shouldSpawnCrow = false
                local GetSpawnPoint_old = inst.GetSpawnPoint
                inst.GetSpawnPoint = function(self, pt, ...)
                    shouldSpawnCrow = false
                    local spawnpoint_calculated = GetSpawnPoint_old(self, pt, ...)
                    if spawnpoint_calculated
                    then
                        for _,v in pairs(GLOBAL.AllPlayers)
                        do
                            local pt_2 = v:GetPosition()
                            if pt==pt_2 and v.prefab=="wilson" -- We have the owner being our mod character, in this case 'wilson'
                            then
                                shouldSpawnCrow = true
                                break
                            end
                        end
                    end
                    if shouldSpawnCrow and (math.random() > .3) -- 30% chance to force a crow spawn, 70% of doing default behaviour.
                    then
                        shouldSpawnCrow = false
                    end
                    return spawnpoint_calculated
                end
                local SpawnBird_old = inst.SpawnBird
                inst.SpawnBird = function(self, spawnpoint, ignorebait, ...)
                    if shouldSpawnCrow
                    then
                        shouldSpawnCrow = false
                        local birdtype = "crow"
                        local x, y, z = spawnpoint:Get() -- Crow to canary checks
                        local canarylure = GLOBAL.TheSim:FindEntities(x, y, z, GLOBAL.TUNING.BIRD_CANARY_LURE_DISTANCE, { "scarecrow" })
                        if #canarylure ~= 0 then
                            birdtype = "canary"
                        end
                        local bird = GLOBAL.SpawnPrefab(birdtype)
                        if math.random() < .5 then
                            bird.Transform:SetRotation(180)
                        end
                        if bird:HasTag("bird")
                        then
                            spawnpoint.y = 15
                        end
                        -- Ignore traps and bait
                        bird.Physics:Teleport(spawnpoint:Get())
                        return bird
                    else
                        return SpawnBird_old(self, spawnpoint, ignorebait, ...)
                    end
                end
            end
        end
    end
)

 

I ask for assistance, thank you.

20190611220029_1.jpg

Since it could be used to identify the issue easier, here's the whole code:
 


local MakePlayerCharacter = require "prefabs/player_common"


local assets = {
        Asset( "ANIM", "anim/player_basic.zip" ),
        Asset( "ANIM", "anim/player_idles_shiver.zip" ),
        Asset( "ANIM", "anim/player_actions.zip" ),
        Asset( "ANIM", "anim/player_actions_axe.zip" ),
        Asset( "ANIM", "anim/player_actions_pickaxe.zip" ),
        Asset( "ANIM", "anim/player_actions_shovel.zip" ),
        Asset( "ANIM", "anim/player_actions_blowdart.zip" ),
        Asset( "ANIM", "anim/player_actions_eat.zip" ),
        Asset( "ANIM", "anim/player_actions_item.zip" ),
        Asset( "ANIM", "anim/player_actions_uniqueitem.zip" ),
        Asset( "ANIM", "anim/player_actions_bugnet.zip" ),
        Asset( "ANIM", "anim/player_actions_fishing.zip" ),
        Asset( "ANIM", "anim/player_actions_boomerang.zip" ),
        Asset( "ANIM", "anim/player_bush_hat.zip" ),
        Asset( "ANIM", "anim/player_attacks.zip" ),
        Asset( "ANIM", "anim/player_idles.zip" ),
        Asset( "ANIM", "anim/player_rebirth.zip" ),
        Asset( "ANIM", "anim/player_jump.zip" ),
        Asset( "ANIM", "anim/player_amulet_resurrect.zip" ),
        Asset( "ANIM", "anim/player_teleport.zip" ),
        Asset( "ANIM", "anim/wilson_fx.zip" ),
        Asset( "ANIM", "anim/player_one_man_band.zip" ),
        Asset( "ANIM", "anim/shadow_hands.zip" ),
        Asset( "SOUND", "sound/sfx.fsb" ),

        Asset( "ANIM", "anim/fiddlesticks.zip" ),
        Asset( "ANIM", "anim/ghost_fiddlesticks_build.zip" ),
}
local prefabs = {}

-- Custom starting items
local start_inv = {
    'scare_scythe'
}


-- This initializes for both the server and client. Tags can be added here.
local common_postinit = function(inst) 
    -- Minimap icon
    inst.MiniMapEntity:SetIcon( "fiddlesticks.tex" )
    inst:AddTag( "scarecrow" )
end

-- This initializes for the server only. Components are added here.
local master_postinit = function(inst)
    -- choose which sounds this character will play
    inst.soundsname = "webber"
    inst.talker_path_override = "dontstarve_DLC001/characters/"
    
    -- Stats    
    inst.components.health:SetMaxHealth(100)
    inst.components.hunger:SetMax(150)
    inst.components.sanity:SetMax(200)
    
    -- Damage multiplier (optional)
    inst.components.combat.damagemultiplier = 1

    -- Souffre de la chaleur
    inst.components.temperature.overheattemp = TUNING.OVERHEAT_TEMP - 11
    inst.components.health.fire_damage_scale = 2

    -- Increase birds spawn
    local birdspawner = TheWorld.components.birdspawner
    if not TheWorld.ismastersim then
            return inst
    end
    if birdspawner ~= nil then
            birdspawner:SetSpawnTimes({min=2, max=5})
            birdspawner:SetMaxBirds(15)
    end

AddComponentPostInit(
    "birdspawner",
    function(inst)
        if GLOBAL.TheWorld.ismastersim
        then
            if inst.SpawnBird and inst.GetSpawnPoint
            then
                local shouldSpawnCrow = false
                local GetSpawnPoint_old = inst.GetSpawnPoint
                inst.GetSpawnPoint = function(self, pt, ...)
                    shouldSpawnCrow = false
                    local spawnpoint_calculated = GetSpawnPoint_old(self, pt, ...)
                    if spawnpoint_calculated
                    then
                        for _,v in pairs(GLOBAL.AllPlayers)
                        do
                            local pt_2 = v:GetPosition()
                            if pt==pt_2 and v.prefab=="scarecrow" -- We have the owner being our mod character, in this case 'scarecrow'
                            then
                                shouldSpawnCrow = true
                                break
                            end
                        end
                    end
                    if shouldSpawnCrow and (math.random() > .3) -- 30% chance to force a crow spawn, 70% of doing default behaviour.
                    then
                        shouldSpawnCrow = false
                    end
                    return spawnpoint_calculated
                end
                local SpawnBird_old = inst.SpawnBird
                inst.SpawnBird = function(self, spawnpoint, ignorebait, ...)
                    if shouldSpawnCrow
                    then
                        shouldSpawnCrow = false
                        local birdtype = "crow"
                        local x, y, z = spawnpoint:Get() -- Crow to canary checks
                        local canarylure = GLOBAL.TheSim:FindEntities(x, y, z, GLOBAL.TUNING.BIRD_CANARY_LURE_DISTANCE, { "scarecrow" })
                        if #canarylure ~= 0 then
                            birdtype = "canary"
                        end
                        local bird = GLOBAL.SpawnPrefab(birdtype)
                        if math.random() < .5 then
                            bird.Transform:SetRotation(180)
                        end
                        if bird:HasTag("bird")
                        then
                            spawnpoint.y = 15
                        end
                        -- Ignore traps and bait
                        bird.Physics:Teleport(spawnpoint:Get())
                        return bird
                    else
                        return SpawnBird_old(self, spawnpoint, ignorebait, ...)
                    end
                end
            end
        end
    end
)
	inst:ListenForEvent("killed",
    function(inst, data)
        local victim = data.victim
        if(victim~=nil and victim.prefab=="crow")
        then
            inst.components.sanity:DoDelta(-50)
        end
    end
)
    inst:ListenForEvent("killed",
    function(inst, data)
        local victim = data.victim
        if(victim~=nil and victim.prefab=="robin")
        then
            inst.components.sanity:DoDelta(-50)
        end
    end
) 
    inst:ListenForEvent("killed",
    function(inst, data)
        local victim = data.victim
        if(victim~=nil and victim.prefab=="robin_winter")
        then
            inst.components.sanity:DoDelta(-50)
        end
    end
) 
end


return MakePlayerCharacter("fiddlesticks", prefabs, assets, common_postinit, master_postinit, start_inv)

 

Share this post


Link to post
Share on other sites
TheSpecter    0

I am trying to run it in DST, as I've just read it might not be compatible. If it's not, is there a way to do this for DST?

Share this post


Link to post
Share on other sites

Did you try to remove the

   local birdspawner = TheWorld.components.birdspawner
    if not TheWorld.ismastersim then
            return inst
    end
    if birdspawner ~= nil then
            birdspawner:SetSpawnTimes({min=2, max=5})
            birdspawner:SetMaxBirds(15)
    end

?

Share this post


Link to post
Share on other sites
TheSpecter    0
15 minutes ago, CorvusCornix said:

Did you try to remove the


   local birdspawner = TheWorld.components.birdspawner
    if not TheWorld.ismastersim then
            return inst
    end
    if birdspawner ~= nil then
            birdspawner:SetSpawnTimes({min=2, max=5})
            birdspawner:SetMaxBirds(15)
    end

?

Yeah, I did. It is still crashing

Share this post


Link to post
Share on other sites
TheSpecter    0
5 hours ago, CarlZalph said:

AddComponentPostInit is done in modmain.lua.

Hm, it still doesn't seem to spawn more crows.

I tried putting it in modmain.lua, it doesn't crash my game anymore, but it doesn't seem to have any effect on the bird spawn rate or type no matter what I try.

Here's how the modmain.lua looks:

 

PrefabFiles = {
	"fiddlesticks",
	"scare_scythe"
}

Assets = {
    Asset( "IMAGE", "images/saveslot_portraits/fiddlesticks.tex" ),
    Asset( "ATLAS", "images/saveslot_portraits/fiddlesticks.xml" ),

    Asset( "IMAGE", "images/selectscreen_portraits/fiddlesticks.tex" ),
    Asset( "ATLAS", "images/selectscreen_portraits/fiddlesticks.xml" ),
	
    Asset( "IMAGE", "images/selectscreen_portraits/fiddlesticks_silho.tex" ),
    Asset( "ATLAS", "images/selectscreen_portraits/fiddlesticks_silho.xml" ),

    Asset( "IMAGE", "bigportraits/fiddlesticks.tex" ),
    Asset( "ATLAS", "bigportraits/fiddlesticks.xml" ),
	
	Asset( "IMAGE", "images/map_icons/fiddlesticks.tex" ),
	Asset( "ATLAS", "images/map_icons/fiddlesticks.xml" ),
	
	Asset( "IMAGE", "images/avatars/avatar_fiddlesticks.tex" ),
    Asset( "ATLAS", "images/avatars/avatar_fiddlesticks.xml" ),
	
	Asset( "IMAGE", "images/avatars/avatar_ghost_fiddlesticks.tex" ),
    Asset( "ATLAS", "images/avatars/avatar_ghost_fiddlesticks.xml" ),

}
local function RecheckForThreat(inst)
    local busy = inst.sg:HasStateTag("sleeping") or inst.sg:HasStateTag("busy") or inst.sg:HasStateTag("flying")
    if not busy then
        local threat = GLOBAL.FindEntity(inst, 5, nil, nil, {'notarget', 'scarecrow'}, {'player', 'monster', 'scarytoprey'})
        return threat ~= nil or GLOBAL.TheWorld.state.isnight
    end
end

AddStategraphPostInit("bird", function(sg)
    local old = sg.events.flyaway.fn
    sg.events.flyaway.fn = function(inst)
        if RecheckForThreat(inst) then
            old(inst)
        end
    end
end)
local function HealthPostInit(self)
	local OldRecalculatePenalty = self.RecalculatePenalty
	local function RecalculatePenalty(self, forceupdatewidget)
		local mult = GLOBAL.TUNING.REVIVE_HEALTH_PENALTY_AS_MULTIPLE_OF_EFFIGY
		mult = mult * GLOBAL.TUNING.EFFIGY_HEALTH_PENALTY
		local maxrevives = (self.maxhealth - 40)/mult
		if self.numrevives > maxrevives then
			self.numrevives = maxrevives
		end
		OldRecalculatePenalty(self, forceupdatewidget)
	end
	self.RecalculatePenalty = RecalculatePenalty
end

AddComponentPostInit('health', HealthPostInit) 



local require = GLOBAL.require
local STRINGS = GLOBAL.STRINGS


-- The character select screen lines
STRINGS.CHARACTER_TITLES.fiddlesticks = "The Harbinger of Doom"
STRINGS.CHARACTER_NAMES.fiddlesticks = "Fiddlesticks"
STRINGS.CHARACTER_DESCRIPTIONS.fiddlesticks = "*Can craft a mysterious weapon\n*crows love him\n*Doesn't like fire and summer"
STRINGS.CHARACTER_QUOTES.fiddlesticks = "\"I think I'll let you suffer for a while...\""

-- Custom speech strings
STRINGS.CHARACTERS.FIDDLESTICKS = require "speech_fiddlesticks"

-- The character's name as appears in-game 
STRINGS.NAMES.FIDDLESTICKS = "Fiddlesticks"

-- The default responses of examining the character
STRINGS.CHARACTERS.GENERIC.DESCRIBE.FIDDLESTICKS = 
{
	GENERIC = "A scarecrow?",
	ATTACKER = "That Fiddlesticks looks shifty...",
	MURDERER = "Murderer!",
	REVIVER = "Fiddlesticks, friend of ghosts.",
	GHOST = "Fiddlesticks looks scarier.",
}

-- From 492792310 ------------------------------
local function RecheckForThreat(inst)
    local busy = inst.sg:HasStateTag("sleeping") or inst.sg:HasStateTag("busy") or inst.sg:HasStateTag("flying")
    if not busy then
        local threat = GLOBAL.FindEntity(inst, 5, nil, nil, {'notarget', 'scarecrow'}, {'player', 'monster', 'scarytoprey'})
        return threat ~= nil or GLOBAL.TheWorld.state.isnight
    end
end

AddStategraphPostInit("bird", function(sg)
    local old = sg.events.flyaway.fn
    sg.events.flyaway.fn = function(inst)
        if RecheckForThreat(inst) then
            old(inst)
        end
    end
end)
------------------------------------------------

local function RecheckForThreat(inst)
    local busy = inst.sg:HasStateTag("sleeping") or inst.sg:HasStateTag("busy") or inst.sg:HasStateTag("flying")
    if not busy then
        local threat = GLOBAL.FindEntity(inst, 5, nil, nil, {'notarget', 'scarecrow'}, {'player', 'monster', 'scarytoprey'})
        return threat ~= nil or GLOBAL.TheWorld.state.isnight
    end
end

AddStategraphPostInit("crow", function(sg)
    local old = sg.events.flyaway.fn
    sg.events.flyaway.fn = function(inst)
        if RecheckForThreat(inst) then
            old(inst)
        end
    end
end)

local comb_rep = GLOBAL.require "components/combat_replica"
local old_IsAlly = comb_rep.IsAlly
function comb_rep:IsAlly(guy,...)
	if guy:HasTag("bird") then
		return true
	end
	return old_IsAlly(self,guy,...)
end
AddComponentPostInit(
    "birdspawner",
    function(inst)
        if GLOBAL.TheWorld.ismastersim
        then
            if inst.SpawnBird and inst.GetSpawnPoint
            then
                local shouldSpawnCrow = false
                local GetSpawnPoint_old = inst.GetSpawnPoint
                inst.GetSpawnPoint = function(self, pt, ...)
                    shouldSpawnCrow = false
                    local spawnpoint_calculated = GetSpawnPoint_old(self, pt, ...)
                    if spawnpoint_calculated
                    then
                        for _,v in pairs(GLOBAL.AllPlayers)
                        do
                            local pt_2 = v:GetPosition()
                            if pt==pt_2 and v.prefab=="scarecrow" -- We have the owner being our mod character, in this case 'wilson'
                            then
                                shouldSpawnCrow = true
                                break
                            end
                        end
                    end
                    if shouldSpawnCrow and (math.random() > .3) -- 30% chance to force a crow spawn, 70% of doing default behaviour.
                    then
                        shouldSpawnCrow = false
                    end
                    return spawnpoint_calculated
                end
                local SpawnBird_old = inst.SpawnBird
                inst.SpawnBird = function(self, spawnpoint, ignorebait, ...)
                    if shouldSpawnCrow
                    then
                        shouldSpawnCrow = false
                        local birdtype = "crow"
                        local x, y, z = spawnpoint:Get() -- Crow to canary checks
                        local canarylure = GLOBAL.TheSim:FindEntities(x, y, z, GLOBAL.TUNING.BIRD_CANARY_LURE_DISTANCE, { "scarecrow" })
                        if #canarylure ~= 0 then
                            birdtype = "canary"
                        end
                        local bird = GLOBAL.SpawnPrefab(birdtype)
                        if math.random() < .5 then
                            bird.Transform:SetRotation(180)
                        end
                        if bird:HasTag("bird")
                        then
                            spawnpoint.y = 15
                        end
                        -- Ignore traps and bait
                        bird.Physics:Teleport(spawnpoint:Get())
                        return bird
                    else
                        return SpawnBird_old(self, spawnpoint, ignorebait, ...)
                    end
                end
            end
        end
    end
)
-- Recette Faux
local Ingredient = GLOBAL.Ingredient
local RECIPETABS = GLOBAL.RECIPETABS
local STRINGS = GLOBAL.STRINGS
local TECH = GLOBAL.TECH

STRINGS.NAMES.SCARE_SCYTHE = "Scythe"
STRINGS.RECIPE_DESC.SCARE_SCYTHE = "A mysterious scarecrow scythe."
STRINGS.CHARACTERS.GENERIC.DESCRIBE.SCARE_SCYTHE = "A little scary.. no ?"

AddRecipe("scare_scythe", { Ingredient("log", 2), Ingredient("rope", 1), Ingredient("razor", 1)}, RECIPETABS.WAR,  TECH.NONE, nil, nil, nil, nil, "scarecrow", "images/inventoryimages/scare_scythe.xml", "scare_scythe.tex")

AddMinimapAtlas("images/map_icons/fiddlesticks.xml")
-- Add mod character to mod character list. Also specify a gender. Possible genders are MALE, FEMALE, ROBOT, NEUTRAL, and PLURAL.
AddModCharacter("fiddlesticks", "MALE")

 

Share this post


Link to post
Share on other sites
CarlZalph    2,962
38 minutes ago, TheSpecter said:

Hm, it still doesn't seem to spawn more crows.

I tried putting it in modmain.lua, it doesn't crash my game anymore, but it doesn't seem to have any effect on the bird spawn rate or type no matter what I try.

The code I provided to that other thread modifies the rate of crows while adhering to the scarecrow rules.

If you want your character to have an increased rate for birds around your character, check out the birdattractor component to modify the rate for him.

 

The line:

if pt==pt_2 and v.prefab=="scarecrow" -- We have the owner being our mod character, in this case 'wilson'

Should be:

if pt==pt_2 and v.prefab=="fiddlesticks" -- We have the owner being our mod character, in this case 'wilson'

 

Share this post


Link to post
Share on other sites
TheSpecter    0
14 minutes ago, CarlZalph said:

The code I provided to that other thread modifies the rate of crows while adhering to the scarecrow rules.

If you want your character to have an increased rate for birds around your character, check out the birdattractor component to modify the rate for him.

 

The line:


if pt==pt_2 and v.prefab=="scarecrow" -- We have the owner being our mod character, in this case 'wilson'

Should be:


if pt==pt_2 and v.prefab=="fiddlesticks" -- We have the owner being our mod character, in this case 'wilson'

 

should it still be "fiddlesticks" if his Tag in the character.lua is "scarecrow"?

I am guessing that by birdattractor you mean the percentage value in if shouldSpawnCrow and (math.random line, I changed it to .9 from .3
I also changed the character to if pt==pt_2 and v.prefab=="fiddlesticks", and it... still doesn't seems to have any effect...
It's probably something very obvious that I am too retarded to see

Share this post


Link to post
Share on other sites
CarlZalph    2,962
1 hour ago, TheSpecter said:

should it still be "fiddlesticks" if his Tag in the character.lua is "scarecrow"?

I am guessing that by birdattractor you mean the percentage value in if shouldSpawnCrow and (math.random line, I changed it to .9 from .3
I also changed the character to if pt==pt_2 and v.prefab=="fiddlesticks", and it... still doesn't seems to have any effect...
It's probably something very obvious that I am too retarded to see

Nah, the code I have there checks the entity's prefab name.  Since it'll be character specific this is the way to do that.

 

The birdattractor is a component, so for your character's master's postinit's callback function you'd do an AddComponent with it.

Then check the component's file for how to modify the bird spawn rate, and/or look at the feather hat in prefabs/hats.lua for how it uses it.

Share this post


Link to post
Share on other sites
TheSpecter    0

Okay, either I am getting the idea or getting more confused

I have
Modmain.lua
fiddlesticks.lua

1.I post the AddComponent  to Modmain.lua
2. Change v.prefab=="scarecrow" to v.prefab=="fiddlesticks"
3. Add

al function feather_equip(inst, owner)
        onequip(inst, owner)
        local attractor = owner.components.birdattractor
        if attractor then
            attractor.spawnmodifier:SetModifier(inst, TUNING.BIRD_SPAWN_MAXDELTA_FEATHERHAT, "maxbirds")
            attractor.spawnmodifier:SetModifier(inst, TUNING.BIRD_SPAWN_DELAYDELTA_FEATHERHAT.MIN, "mindelay")
            attractor.spawnmodifier:SetModifier(inst, TUNING.BIRD_SPAWN_DELAYDELTA_FEATHERHAT.MAX, "maxdelay")
            
            local birdspawner = TheWorld.components.birdspawner
            if birdspawner ~= nil then
                birdspawner:ToggleUpdate(true)
            end
        end
    end


to modmain.lua?
4. Add

    local function feather_unequip(inst, owner)
        onunequip(inst, owner)

        local attractor = owner.components.birdattractor
        if attractor then
            attractor.spawnmodifier:RemoveModifier(inst)

            local birdspawner = TheWorld.components.birdspawner
            if birdspawner ~= nil then
                birdspawner:ToggleUpdate(true)
            end
        end
    end


To fiddlesticks.lua?


How do I replace "TUNING.BIRD_SPAWN_MAXDELTA_FEATHERHAT" to make it character specific?
I am lost.

 

Share this post


Link to post
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