Jump to content

Recommended Posts

Hello,

I'm trying to make a whistle that will act like firecracker (startling hound). I got something that work, using panflute code. So it's fine except that using an instrument take time, too much time to make the item useful. (The hound are startled, and the instrument continue playing and they could move again, so it's useless)

I'm searching a way to make an usable item in inventory with multiple use and a way to do a custom function. Don't really care if i don't have an anim or sound.

Here is the code i'm using right now.

local assets =
{
    Asset("ANIM", "anim/pan_flute.zip"),
}

local function HearWhistle(inst, musician, instrument)
    if inst ~= musician then
    local x, y, z = inst.Transform:GetWorldPosition()

    for i, v in ipairs(TheSim:FindEntities(x, y, z, TUNING.FIRECRACKERS_STARTLE_RANGE, { "canbestartled" })) do
        v:PushEvent("startle", { source = inst })
    end

    end
end

local function fn()
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddNetwork()

    MakeInventoryPhysics(inst)

    inst:AddTag("whistle")

    inst.AnimState:SetBank("pan_flute")
    inst.AnimState:SetBuild("pan_flute")
    inst.AnimState:PlayAnimation("idle")

    inst.entity:SetPristine()

    if not TheWorld.ismastersim then
        return inst
    end

    inst:AddComponent("inspectable")
    inst:AddComponent("instrument")
    inst.components.instrument.range = TUNING.PANFLUTE_SLEEPRANGE
    inst.components.instrument:SetOnHeardFn(HearWhistle)

    inst:AddComponent("tool")
    inst.components.tool:SetAction(ACTIONS.PLAY)

    inst:AddComponent("finiteuses")
    inst.components.finiteuses:SetMaxUses(TUNING.PANFLUTE_USES)
    inst.components.finiteuses:SetUses(TUNING.PANFLUTE_USES)
    inst.components.finiteuses:SetOnFinished(inst.Remove)
    inst.components.finiteuses:SetConsumption(ACTIONS.PLAY, 1)

    inst:AddComponent("inventoryitem")

    MakeHauntableLaunch(inst)
    AddHauntableCustomReaction(inst, function(inst, haunter)
        if math.random() <= TUNING.HAUNT_CHANCE_HALF then
            if inst.components.finiteuses then
                inst.components.finiteuses:Use(1)
                inst.components.hauntable.hauntvalue = TUNING.HAUNT_MEDIUM
                return true
            end
        end
        return false
    end, true, false, true)

    return inst
end

return Prefab("whistle", fn, assets)

 

Try this:

local function PlayWhistle(instrument, musician)
	musician.AnimState:PlayAnimation("idle")
end

and add this to your fn() after inst:AddComponent("instrument"):

inst.components.instrument:SetOnPlayedFn(PlayWhistle)

Use DoTaskInTime to adjust the delay.

@Lumina Since you're creating a custom prefab with probably a custom texture and such, you might want to make a custom animation for it as well.

This'll let you customize the animations a bit better for when you have things ready but right now it's just the panflute that has had its animation timeline a bit edited to show its effects.

local myprefabname = "panflute"
local mycustomstate_name = "play_modded_"..myprefabname
local mycustomstate = GLOBAL.State{
    name = mycustomstate_name,
    tags = { "doing", "playing" },
    onenter = function(inst)
        inst.components.locomotor:Stop()
        inst.AnimState:PlayAnimation("action_uniqueitem_pre")
        inst.AnimState:PushAnimation("flute", false)
        inst.AnimState:OverrideSymbol("pan_flute01", "pan_flute", "pan_flute01")
        inst.AnimState:Hide("ARM_carry") 
        inst.AnimState:Show("ARM_normal")
        inst.components.inventory:ReturnActiveActionItem(inst.bufferedaction ~= nil and inst.bufferedaction.invobject or nil)
        inst.sg:SetTimeout(16*GLOBAL.FRAMES)
    end,
    timeline =
    {
        GLOBAL.TimeEvent(0*GLOBAL.FRAMES, function(inst)
            inst.SoundEmitter:PlaySound("dontstarve/wilson/flute_LP", "flute")
            inst:PerformBufferedAction()
        end),
        GLOBAL.TimeEvent(15*GLOBAL.FRAMES, function(inst)
            inst.SoundEmitter:KillSound("flute")
        end),
    },
    events =
    {
        GLOBAL.EventHandler("animqueueover", function(inst)
            if inst.AnimState:AnimDone() then
                inst.sg:GoToState("idle")
            end
        end),
    },
    onexit = function(inst)
        inst.SoundEmitter:KillSound("flute")
        if inst.components.inventory:GetEquippedItem(GLOBAL.EQUIPSLOTS.HANDS) then
            inst.AnimState:Show("ARM_carry") 
            inst.AnimState:Hide("ARM_normal")
        end
    end,
    ontimeout = function(inst)
        inst.AnimState:PlayAnimation("idle")
        inst.sg:GoToState("idle", true)
    end,
}
AddStategraphPostInit(
    "wilson",
    function(stategraph)
        stategraph.states[mycustomstate_name] = mycustomstate
        local playhandler = stategraph.actionhandlers[GLOBAL.ACTIONS.PLAY]
        if playhandler
        then
            local deststate_old = playhandler.deststate
            if deststate_old
            then
                playhandler.deststate = function(inst, action, ...)
                    if action.invobject and action.invobject.prefab == myprefabname
                    then
                        return mycustomstate_name
                    end
                    return deststate_old(inst, action, ...)
                end
            end
        end
    end
)

 

3 hours ago, CarlZalph said:

This'll let you customize the animations a bit better for when you have things ready but right now it's just the panflute that has had its animation timeline a bit edited to show its effects.

Thanks for the code, it seems to work fine. So if i understand well, this part is about showing the flute, but since it's a symbol, i don't have to change this part, all change will be about in the anim side ?


        inst.AnimState:OverrideSymbol("pan_flute01", "pan_flute", "pan_flute01")

 

So for example i could use the pan_flute as a base for the anim and just change tex/build and keep the symbol name here ?

16 minutes ago, Lumina said:

Thanks for the code, it seems to work fine. So if i understand well, this part is about showing the flute, but since it's a symbol, i don't have to change this part, all change will be about in the anim side ?



        inst.AnimState:OverrideSymbol("pan_flute01", "pan_flute", "pan_flute01")

 

So for example i could use the pan_flute as a base for the anim and just change tex/build and keep the symbol name here ?

Unfortunately I haven't played with spiter and its animation stuff at all, so I am unaware of what those symbols pertain to.

Perhaps it's a part of the panflute itself that it's hiding or showing, or a different angle all together.

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