Jump to content

Wait for Animation to finish before executing a function


Recommended Posts

Hello,

I'm struggling on a couple things.

First, I'm attempting to play the jump animation, then once it's finished transform the character into a mole. Right now the character transforms before an animation plays, even if the animation goes first.

Second, The character transforms into a Mole however it seems the walking animation doesn't carry over.

Any help would be appreciated.

Thanks,

Red

Edited by RedHairedHero
Link to comment
Share on other sites

The first answer works perfectly, thanks for the help on that.

So to help explain the second part, my character transforms into a Mole to give the appearance of burrowing.

To do that after the animation happens they're assigned the Mole's build, bank, and stategraph.

But it seems that the Mole's walking/burrowing animation isn't working properly, normally when you the mole walks there's a trail of dirt behind him, but that doesn't occur.

Any ideas?

Thanks,

Red

Link to comment
Share on other sites

local MakePlayerCharacter = require "prefabs/player_common"

local assets = {
    Asset("SCRIPT", "scripts/prefabs/player_common.lua"),
	Asset( "ANIM", "anim/whisper.zip" ),
	Asset( "ANIM", "anim/whisper_furry.zip" ),
    Asset( "ANIM", "anim/whisper_dark.zip" ),
	Asset( "ANIM", "anim/whisper_dark_furry.zip" ),
	Asset("ANIM", "anim/mole_build.zip"),
    Asset("ANIM", "anim/mole_basic.zip"),
	Asset("ANIM", "anim/mole_move_fx.zip"),
	Asset("ANIM", "anim/player_jump.zip"),
    Asset("SOUND", "sound/mole.fsb"),
}

local prefabs = 
{
	"mole_move_fx",
}

-- Custom starting items
local start_inv = {
"carrot",
"carrot",
"carrot",
"carrot",
}

-- When the character is revived from human
local function onbecamehuman(inst)
	-- Set speed when reviving from ghost (optional)
	inst.components.locomotor:SetExternalSpeedMultiplier(inst, "whisper_speed_mod", 1 + .25)
end

local function onbecameghost(inst)
	-- Remove speed modifier when becoming a ghost
   inst.components.locomotor:RemoveExternalSpeedMultiplier(inst, "whisper_speed_mod")
end

-- When loading or spawning the character
local function onload(inst)
    inst:ListenForEvent("ms_respawnedfromghost", onbecamehuman)
    inst:ListenForEvent("ms_becameghost", onbecameghost)

    if inst:HasTag("playerghost") then
        onbecameghost(inst)
    else
        onbecamehuman(inst)
    end
end

local function oneat(inst, food)
	
	local extrahunger = 0
	
	if food.prefab == "carrot" or food.prefab == "carrot_cooked" then
		if food.components.perishable:IsStale() then
			extrahunger = 4
		else if food.components.perishable:IsSpoiled() then
			extrahunger = 2
		else --if it's fresh
			extrahunger = 6
		end
		end
	end
	
	if food and food.components.edible and food.prefab == "carrot"  then
		inst.components.hunger:DoDelta(extrahunger);
	end
	
	if food and food.components.edible and food.prefab == "carrot_cooked"  then
		inst.components.hunger:DoDelta(extrahunger);
	end
	
end

local function OnResetBeard(inst)
	inst:RemoveTag("FURRY")
	if inst:HasTag("DARK") then
		inst.AnimState:SetBuild("whisper_dark")
	else
		inst.AnimState:SetBuild("whisper")
	end
end 

	
local function OnGrowBeard(inst)    
	inst:AddTag("FURRY")
	if inst:HasTag("DARK") then
		inst.AnimState:SetBuild("whisper_dark_furry")
	else
		inst.AnimState:SetBuild("whisper_furry")
	end
	inst.components.beard.bits = 4
end
	
local function SetUnderPhysics(inst)
    if inst.isunder ~= true then
        inst.isunder = true
        inst.Physics:SetCollisionGroup(COLLISION.CHARACTERS)
        inst.Physics:ClearCollisionMask()
        inst.Physics:CollidesWith(COLLISION.WORLD)
        inst.Physics:CollidesWith(COLLISION.OBSTACLES)
    end
end

local function SetAbovePhysics(inst)
    if inst.isunder ~= false then
        inst.isunder = false
        ChangeToCharacterPhysics(inst)
    end
end

local function burrow_trail(inst)
    if inst.sg ~= nil and inst.sg:HasStateTag("moving") and inst:HasTag("underground") then
		SpawnPrefab("mole_move_fx").Transform:SetPosition(inst.Transform:GetWorldPosition())
    end
end

local function burrow (inst)
	if inst:HasTag("aboveground") and not inst:HasTag("DARK") then
		inst:RemoveTag("aboveground")
		inst:AddTag("underground")
		inst.AnimState:SetBank("mole")
		inst.AnimState:SetBuild("mole_build")
		inst:SetStateGraph("SGmole")
		inst.components.locomotor.fasteronroad = false
		inst.components.hunger:SetRate(2 * TUNING.WILSON_HUNGER_RATE)
		if inst:HasTag("underground") then
			inst:DoPeriodicTask(8 * FRAMES, burrow_trail)
		end
		--print("underground")
	else if inst:HasTag("underground") then
		inst:RemoveTag("underground")
		inst:AddTag("aboveground")
		inst.AnimState:SetBank("wilson")
		if inst:HasTag("FURRY") then
			inst.AnimState:SetBuild("whisper_furry")
		else
			inst.AnimState:SetBuild("whisper")
		end
		inst:SetStateGraph("SGwilson")
		inst.components.locomotor.fasteronroad = true
		inst.components.hunger:SetRate(1 * TUNING.WILSON_HUNGER_RATE)
		--print("aboveground")
	end
	end
end

local function OnKeyPressed(inst, data)    
	if data.inst == ThePlayer then 
			--burrow (inst)
		if data.key == KEY_B then
			if inst:HasTag("aboveground") then
				inst.AnimState:PlayAnimation("jump")
				inst:DoTaskInTime(inst.AnimState:GetCurrentAnimationLength(), burrow)
			else if inst:HasTag("underground") then
				inst.AnimState:PlayAnimation("jumpout")
				inst:DoTaskInTime(inst.AnimState:GetCurrentAnimationLength(), burrow)
			end
			end
		end
		if data.key == KEY_T then
			--print("KEY_T has been pressed.")            
		if TheWorld.ismastersim then
			BufferedAction(inst, inst, ACTIONS.DARKSIDE):Do()
			-- Since we are the server, do the action on the server.            
		else  
			SendRPCToServer(RPC.DoWidgetButtonAction, ACTIONS.DARKSIDE.code, inst, ACTIONS.DARKSIDE.mod_name)            
		end    
		end
	end
end

local function controltransform (inst, data)

if not inst:HasTag("playerghost") then
	if inst.components.sanity.current <= 30 and inst:HasTag("DARK") then
		--If in dark mode and sanity falls below 30 force the player back into normal mode
		SendRPCToServer(RPC.DoWidgetButtonAction, ACTIONS.DARKSIDE.code, inst, ACTIONS.DARKSIDE.mod_name)
		inst:AddTag("notransform")
	else if inst.components.sanity.current <= 30 then
		--If the players sanity is below or equal to 30 prevent them from transforming into dark mode
		inst:AddTag("notransform")
	else if inst.components.sanity.current > 30 then
		--If sanity is above 30 allow transformation
		inst:RemoveTag("notransform")
	end
	end
	end
end

end

local function sanityfn(inst)
    local delta = 0
    if TheWorld.state.isday then
            delta = TUNING.SANITY_NIGHT_MID
    end
    return delta
end

local function getstatus(inst)
    return (inst.components.inventoryitem ~= nil and inst.components.inventoryitem:IsHeld() and "HELD")
        or (inst.isunder and "UNDERGROUND")
        or "ABOVEGROUND"
end

-- This initializes for both the server and client. Tags can be added here.

local common_postinit = function(inst)
	inst:AddComponent("keyhandler")
	inst:ListenForEvent("keypressed", OnKeyPressed)
	-- Minimap icon
	inst.MiniMapEntity:SetIcon( "whisper.tex" )
	inst:AddTag("aboveground")
	inst:AddTag("bearded")
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 = "willow"
	
	-- Uncomment if "wathgrithr"(Wigfrid) or "webber" voice is used
    --inst.talker_path_override = "dontstarve_DLC001/characters/"
	
	inst.components.sanity.custom_rate_fn = sanityfn
	
	inst.components.eater:SetDiet({ FOODTYPE.VEGGIE }, { FOODTYPE.VEGGIE })
	
	inst:AddComponent("beard")
	inst.components.beard.onreset = OnResetBeard
	inst.components.beard:AddCallback( 7 , OnGrowBeard )
	 
	inst.components.sanity.night_drain_mult = 0
	 
	if not TheWorld.ismastersim then
        inst.isunder = nil --this flag is not valid on clients

        return inst
    end

	inst:AddComponent("lootdropper")
	
	if inst:HasTag("DARK") then
		inst.components.beard.prize = "beardhair"
	else
		inst.components.beard.prize = "manrabbit_tail"
	end
	
	-- Listener for eating
	inst.components.eater:SetOnEatFn(oneat)
		
	-- Stats	
	inst.components.health:SetMaxHealth(200)
	inst.components.hunger:SetMax(150)
	inst.components.sanity:SetMax(150)
	
	-- Damage multiplier (optional)
    inst.components.health:SetAbsorptionAmount(-0.25)
	inst.components.combat.damagemultiplier = 0.75
	
	-- Hunger rate (optional)
	inst.components.hunger.hungerrate = 1 * TUNING.WILSON_HUNGER_RATE 
	
	MakeCharacterPhysics(inst, 99999, 0.5)
    SetUnderPhysics(inst)
	
	inst:AddComponent("inspectable")
	inst.components.inspectable.getstatus = getstatus
	
	inst.SetUnderPhysics = SetUnderPhysics
    inst.SetAbovePhysics = SetAbovePhysics
	
	inst.OnLoad = onload
    inst.OnNewSpawn = onload

	inst:ListenForEvent("sanitydelta", controltransform)
	
	return inst
end

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

 

Instead of doing a state for the transformation I decided to change it inside the prefab, I've attempted both ways, but it results in the same thing.

Thanks,

Red

Link to comment
Share on other sites

Yeah, you may have noticed I had created my own variation of the walking animation using this bit of code, but I'd prefer to remove that and just use the normal walking animation if I can.

inst:DoPeriodicTask(8 * FRAMES, burrow_trail)
Edited by RedHairedHero
Link to comment
Share on other sites

I think the issue is the following:

the player actions are handled by the components playeractionpicker and playercontroller, which then send request to the component locomotor.

I believe these functions have call inside to states which exists in SGwilson.lua, like "walk_idle", "walk_careful", "run", etc..., regardless of what is the stategraph associated to the player.

SGmole.lua does not have any of these, it just has a "walk" state but it is never called because there are no state with this name in SGwilson.lua

Maybe you should try to add all the walk and run states from SGwilson.lua to SGmole.lua and modify their content so the proper animations are played.

I wrote this without testing nor verifying all my points. I'm just talking from my previous experience with modding the player actions, movement, targeting, etc...

Edited by ZupaleX
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...