require("stategraphs/commonstates")

function TableConcat(t1,t2)
    for i=1,#t2 do
        t1[#t1+1] = t2[i]
    end
    return t1
end

local actionhandlers =
{
	ActionHandler(ACTIONS.EAT, "action"),
	ActionHandler(ACTIONS.ATTACK, "attack"),
	ActionHandler(ACTIONS.HAMMER, "attack"),
	ActionHandler(ACTIONS.MINE, "attack"),
	ActionHandler(ACTIONS.CHOP, "attack"),
	ActionHandler(ACTIONS.PICK, "action"),
	ActionHandler(ACTIONS.PICKUP, "action"),
	ActionHandler(ACTIONS.HARVEST, "action"),	
	ActionHandler(ACTIONS.DROP, "action"),
	ActionHandler(ACTIONS.GIVE, "action"),
	--ActionHandler(ACTIONS.HAMMER, "attack"),
	ActionHandler(ACTIONS.GIVETOPLAYER, "action"),
	ActionHandler(ACTIONS.GIVEALLTOPLAYER, "action"),	
	ActionHandler(ACTIONS.LAYEGG, "layegg2"),
	ActionHandler(ACTIONS.MIGRATE, "action"),
	ActionHandler(ACTIONS.COMBINESTACK, "action"),
	ActionHandler(ACTIONS.UNWRAP, "action"),
}

local mobCraftActions =
{

	ActionHandler(ACTIONS.ATTACK, "attack"),
	ActionHandler(ACTIONS.FEED, "action"),
	ActionHandler(ACTIONS.PICKUP, "action"),
	ActionHandler(ACTIONS.PICK, "action"),
	ActionHandler(ACTIONS.DROP, "action"),
	ActionHandler(ACTIONS.ACTIVATE, "action"),
	ActionHandler(ACTIONS.EAT, "action"),
	ActionHandler(ACTIONS.HEAL, "action"),
	ActionHandler(ACTIONS.FAN, "action"),
	ActionHandler(ACTIONS.DIG, "action"),
	ActionHandler(ACTIONS.CHOP, "attack"),
	ActionHandler(ACTIONS.MINE, "attack"),
	ActionHandler(ACTIONS.GIVE, "action"),
	ActionHandler(ACTIONS.GIVEALLTOPLAYER, "action"),
	ActionHandler(ACTIONS.COOK, "action"),
	ActionHandler(ACTIONS.FILL, "action"),
	ActionHandler(ACTIONS.DRY, "action"),
	ActionHandler(ACTIONS.ADDFUEL, "action"),
	ActionHandler(ACTIONS.ADDWETFUEL, "action"),
	ActionHandler(ACTIONS.LIGHT, "action"),
	ActionHandler(ACTIONS.BAIT, "action"),
	ActionHandler(ACTIONS.BUILD, "action"),
	ActionHandler(ACTIONS.PLANT, "action"),
	ActionHandler(ACTIONS.REPAIR, "action"),
	ActionHandler(ACTIONS.HARVEST, "action"),
	ActionHandler(ACTIONS.STORE, "action"),
	ActionHandler(ACTIONS.RUMMAGE, "action"),
	ActionHandler(ACTIONS.DEPLOY, "action"),
	ActionHandler(ACTIONS.HAMMER, "attack"),
	ActionHandler(ACTIONS.FERTILIZE, "action"),
	ActionHandler(ACTIONS.MURDER, "action"),
	ActionHandler(ACTIONS.UNLOCK, "action"),
	ActionHandler(ACTIONS.TURNOFF, "action"),
	ActionHandler(ACTIONS.TURNON, "action"),
	ActionHandler(ACTIONS.SEW, "action"),
	ActionHandler(ACTIONS.COMBINESTACK, "action"),
	ActionHandler(ACTIONS.UPGRADE, "action"),
	ActionHandler(ACTIONS.WRITE, "action"),
	ActionHandler(ACTIONS.FEEDPLAYER, "action"),
	ActionHandler(ACTIONS.TERRAFORM, "action"),
	ActionHandler(ACTIONS.NET, "action"),
	ActionHandler(ACTIONS.CHECKTRAP, "action"),
	ActionHandler(ACTIONS.SHAVE, "action"),
	ActionHandler(ACTIONS.FISH, "action"),
	ActionHandler(ACTIONS.REEL, "action"),
	ActionHandler(ACTIONS.CATCH, "action"),
	ActionHandler(ACTIONS.TEACH, "action"),
	ActionHandler(ACTIONS.MANUALEXTINGUISH, "action"),
	ActionHandler(ACTIONS.RESETMINE, "action"),
	ActionHandler(ACTIONS.BLINK, "action"),
	ActionHandler(ACTIONS.CHANGEIN, "action"),
	ActionHandler(ACTIONS.SMOTHER, "action"),
	ActionHandler(ACTIONS.CASTSPELL, "action"),
	ActionHandler(ACTIONS.WRAPBUNDLE, "action"),
	ActionHandler(ACTIONS.UNWRAP, "action"),
	ActionHandler(ACTIONS.UNLOCK, "action"),
	ActionHandler(ACTIONS.USEKLAUSSACKKEY, "action"),
}


local extraActions = 
{
	--ActionHandler(ACTIONS.SLEEPIN, "sleep"),
	ActionHandler(ACTIONS.TRAVEL, "taunt"),
	ActionHandler(ACTIONS.LOOKAT, "taunt"),
}

if MOBCRAFT == "Enable" then
	extraActions = mobCraftActions
end

actionhandlers = TableConcat(actionhandlers, extraActions)

local function onattackfn(inst)
	if inst.components.health and not inst.components.health:IsDead()
	   and (inst.sg:HasStateTag("hit") or not inst.sg:HasStateTag("busy")) then
		--if inst.CanDisarm then
			--inst.sg:GoToState("disarm")
		--else
			inst.sg:GoToState("attack")
		--end
	end
end

local events=
{
	EventHandler("locomote",
	function(inst)
		if (not inst.sg:HasStateTag("idle") and not inst.sg:HasStateTag("moving")) then return end

		if not inst.components.locomotor:WantsToMoveForward() then
			if not inst.sg:HasStateTag("idle") then
				inst.sg:GoToState("idle", {softstop = true})
			end
		else
			if not inst.sg:HasStateTag("hopping") then
				if inst.components.combat and not inst.components.health:IsDead() and inst.components.combat.target then
				inst.sg:GoToState("goosestep")
				else
				inst.sg:GoToState("hop")
				end
			end
		end
	end),

	CommonHandlers.OnSleep(),
	CommonHandlers.OnFreeze(),
	EventHandler("doattack", onattackfn),
	CommonHandlers.OnAttacked(),
	CommonHandlers.OnDeath(),

	EventHandler("flyaway", function(inst)
		if inst.components.health:GetPercent() > 0 and not inst.sg:HasStateTag("busy") then
			inst.sg:GoToState("flyaway")
		end
	end),
	
	EventHandler("ms_opengift",
        function(inst)
            if not inst.sg:HasStateTag("busy") then
                inst.sg:GoToState("opengift")
            end
        end),
}

local function ShakeIfClose(inst)
	for i, v in ipairs(AllPlayers) do
		v:ShakeCamera(CAMERASHAKE.FULL, .35, .02, 1.25, inst, 40)
	end
end

local function DeathCollapseShake(inst)
	for i, v in ipairs(AllPlayers) do
		v:ShakeCamera(CAMERASHAKE.FULL, .7, .02, 3., inst, 40)
	end
end

local states=
{
	State{
		name = "idle",
		tags = {"idle", "canrotate"},

		onenter = function(inst, data)
			inst.Physics:Stop()
			inst.AnimState:PlayAnimation("idle", true)
			inst.sg:SetTimeout(math.random()*10+2)
		end,

		timeline = {},

		ontimeout= function(inst)
			inst.sg:GoToState((math.random() < 0.5 and "twitch" or "preen"))
		end,
	},
	
	State{
		name = "action",
		tags = {"busy"},

		onenter = function(inst)
			inst.Physics:Stop()
			inst.AnimState:PlayAnimation("land")
			inst:PerformBufferedAction()
		end,

		timeline=
		{

		},

		events =
		{
			EventHandler("animqueueover", function(inst) inst.sg:GoToState("idle") end)
		},
	},
	
	State{
        name = "opengift",
        tags = { "busy", "pausepredict" },

        onenter = function(inst)
            inst.components.locomotor:Stop()
            inst.components.locomotor:Clear()
            inst:ClearBufferedAction()

            --if IsNearDanger(inst) then
                --inst.sg.statemem.isdanger = true
                --inst.sg:GoToState("idle")
                --if inst.components.talker ~= nil then
                   -- inst.components.talker:Say(GetString(inst, "ANNOUNCE_NODANGERGIFT"))
                --end
                --return
           -- end

            inst.SoundEmitter:PlaySound("dontstarve/common/player_receives_gift")
            inst.AnimState:PlayAnimation("idle", true)
            --inst.AnimState:PushAnimation("taunt", true)
            -- NOTE: the previously used ripping paper anim is called "giift_loop"

            if inst.components.playercontroller ~= nil then
                inst.components.playercontroller:RemotePausePrediction()
                inst.components.playercontroller:EnableMapControls(false)
                inst.components.playercontroller:Enable(false)
            end
            inst.components.inventory:Hide()
            inst:PushEvent("ms_closepopups")
            inst:ShowActions(false)
            inst:ShowGiftItemPopUp(true)

            if inst.components.giftreceiver ~= nil then
                inst.components.giftreceiver:OnStartOpenGift()
            end
        end,

        timeline =
        {
            -- Timing of the gift box opening animation on giftitempopup.lua
            TimeEvent(155 * FRAMES, function(inst)
               -- inst.AnimState:PlayAnimation("gift_open_pre")
                --inst.AnimState:PushAnimation("taunt", true)
            end),
        },

        events =
        {
            EventHandler("firedamage", function(inst)
                --inst.AnimState:PlayAnimation("taunt")
                inst.sg:GoToState("idle", true)
                if inst.components.talker ~= nil then
                    inst.components.talker:Say(GetString(inst, "ANNOUNCE_NODANGERGIFT"))
                end
            end),
            EventHandler("ms_doneopengift", function(inst, data)
                inst.sg:GoToState("idle", true)
            end),
        },

        onexit = function(inst)
            if inst.sg.statemem.isdanger then
                return
            elseif not inst.sg.statemem.isopeningwardrobe then
                if inst.components.playercontroller ~= nil then
                    inst.components.playercontroller:EnableMapControls(true)
                    inst.components.playercontroller:Enable(true)
                end
                inst.components.inventory:Show()
                inst:ShowActions(true)
            end
            inst:ShowGiftItemPopUp(false)
        end,
    },

	State{
		name = "twitch",
		tags = {"idle"},

		onenter = function(inst, playanim)
			inst.Physics:Stop()
			--inst:PerformBufferedAction()
			inst.AnimState:PlayAnimation("idle_2")
		end,

		events =
		{
			EventHandler("animqueueover", function(inst) inst.sg:GoToState("idle") end)
		}
	},
	
	State{
		name = "twitch2",
		tags = {"busy"},

		onenter = function(inst, playanim)
			inst.Physics:Stop()
			inst:PerformBufferedAction()
			inst.AnimState:PlayAnimation("idle_2")
		end,

		events =
		{
			EventHandler("animqueueover", function(inst) inst.sg:GoToState("idle") end)
		}
	},

	State{
		name = "preen",
		tags = {"idle"},

		onenter = function(inst)
			inst.Physics:Stop()
			--inst:PerformBufferedAction()
			inst.AnimState:PlayAnimation("idle_3")
			
		end,

		events =
		{
			EventHandler("animover", function(inst) inst.sg:GoToState("idle") end)
		},

		timeline =
		{
			TimeEvent(11*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/preen") end),
			TimeEvent(14*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/preen_feathers") end),
		},
	},
	
	State{
		name = "preen2",
		tags = {"busy"},

		onenter = function(inst)
			inst.Physics:Stop()
			inst:PerformBufferedAction()
			inst.AnimState:PlayAnimation("idle_3")
			
		end,

		events =
		{
			EventHandler("animover", function(inst) inst.sg:GoToState("idle") end)
		},

		timeline =
		{
			TimeEvent(11*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/preen") end),
			TimeEvent(14*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/preen_feathers") end),
		},
	},

	State{
		name = "hop",
		tags = {"moving", "canrotate", "hopping"},

		onenter = function(inst)
			inst.AnimState:PlayAnimation("hop")
			PlayFootstep(inst)
			inst.components.locomotor:WalkForward()
			inst.sg:SetTimeout(math.random()+.5)
		end,

		onupdate= function(inst)
			if not inst.components.locomotor:WantsToMoveForward() then
				inst.sg:GoToState("idle")
			end
		end,

		timeline=
		{
			TimeEvent(1*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/attack") end),
			TimeEvent(9*FRAMES, function(inst)
				inst.Physics:Stop()
				ShakeIfClose(inst)
				inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/dragonfly/land")
			end),
		},

		ontimeout= function(inst)
			inst.sg:GoToState("hop")
		end,
	},
	
	State{
		name = "goosestep",
		tags = {"moving", "canrotate", "hopping"},

		onenter = function(inst)
			inst.AnimState:PlayAnimation("hop")
			PlayFootstep(inst)
			inst.components.locomotor:RunForward()
		end,

		onupdate= function(inst)
			if not inst.components.locomotor:WantsToMoveForward() then
				inst.sg:GoToState("idle")
			end
		end,

		timeline=
		{
			TimeEvent(1*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/attack") end),
			TimeEvent(9*FRAMES, function(inst)
				inst.Physics:Stop()
				ShakeIfClose(inst)
				inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/dragonfly/land")
			end),
		},

		events =
		{
			EventHandler("animqueueover", function(inst) if inst.components.combat.target then inst.sg:GoToState("goosestep") else inst.sg:GoToState("idle") end end)
		},
	},

	--don't use, animations are missing(?)
	State{
		name = "action2",
		tags = {"busy"},

		onenter = function(inst)
			inst.Physics:Stop()
			inst.AnimState:PlayAnimation("action")
			inst.AnimState:PushAnimation("eat", false)
		end,

		timeline=
		{
			TimeEvent(FRAMES*1, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/attack") end),
			TimeEvent(10*FRAMES, function(inst)
				inst:PerformBufferedAction()
				inst.sg:RemoveStateTag("busy")
				inst.sg:AddStateTag("wantstoeat")
			end),
		},

		events =
		{
			EventHandler("animqueueover", function(inst) inst.sg:GoToState("eat_pst") end)
		},
	},
	
	State{
		name = "action",
		tags = {"busy"},

		onenter = function(inst)
			inst.Physics:Stop()
			inst.AnimState:PlayAnimation("land")
			inst:PerformBufferedAction()
		end,

		timeline=
		{

		},

		events =
		{
			EventHandler("animqueueover", function(inst) inst.sg:GoToState("idle") end)
		},
	},
-- ditto
	State{
		name = "eat_loop",
		tags = {"busy"},

		onenter = function(inst)
			inst.Physics:Stop()
			inst.AnimState:PushAnimation("eat", true)
			inst.sg:SetTimeout(math.random()*2+1)
		end,

		timeline = {},

		ontimeout = function(inst)
			inst:PerformBufferedAction()
			inst.sg:GoToState("eat_pst")
		end,

	},

	State{
		name = "eat_pst", --also broken
		tags = {"busy"},

		onenter = function(inst)
			inst.Physics:Stop()
			inst.AnimState:PlayAnimation("eat_pst")
		end,

		timeline = {},

		events =
		{
			EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
		},
	},

	State{
		name = "glide",
		tags = {"flying", "busy"},

		onenter= function(inst)
			inst.AnimState:PlayAnimation("glide", true)
			inst.Physics:SetMotorVelOverride(0,-11,0)
			inst.flapSound = inst:DoPeriodicTask(6*FRAMES,
				function(inst)
					inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/flap")
				end)
		end,

		onupdate= function(inst)
			inst.Physics:SetMotorVelOverride(0,-15,0)
			local pt = Point(inst.Transform:GetWorldPosition())
			if pt.y < 2 then
				inst.Physics:ClearMotorVelOverride()
				pt.y = 0
				inst.Physics:Stop()
				inst.Physics:Teleport(pt.x,pt.y,pt.z)
				inst.AnimState:PlayAnimation("land")
				inst.DynamicShadow:Enable(true)
				inst.sg:GoToState("idle", {softstop = true})
				ShakeIfClose(inst)
			end
		end,

		onexit = function(inst)
			if inst.flapSound then
				inst.flapSound:Cancel()
				inst.flapSound = nil
			end
			if inst:GetPosition().y > 0 then
				local pos = inst:GetPosition()
				pos.y = 0
				inst.Transform:SetPosition(pos:Get())
			end
			inst.components.knownlocations:RememberLocation("landpoint", inst:GetPosition())
		end,
	},

	State{
		name = "flyaway",
		tags = {"flying", "busy"},

		onenter = function(inst)
			inst.Physics:Stop()
			inst.DynamicShadow:Enable(false)
			inst.AnimState:PlayAnimation("takeoff_pre_vertical")
			inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/flap")
			inst.sg.statemem.flapSound = 9*FRAMES
		end,

		onupdate = function(inst, dt)
			inst.sg.statemem.flapSound = inst.sg.statemem.flapSound - dt
			if inst.sg.statemem.flapSound <= 0 then
				inst.sg.statemem.flapSound = 6*FRAMES
				inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/flap")
			end
		end,

		timeline =
		{
			TimeEvent(9*FRAMES, function(inst)
				inst.AnimState:PushAnimation("takeoff_vertical", true)
				inst.Physics:SetMotorVel(math.random()*4,7+math.random()*2,math.random()*4)
			end),
			TimeEvent(10, function(inst) inst:Remove() end)
		}
	},

	State{
		name = "disarm",
		tags = {"busy"},

		onenter = function(inst)
			inst.Physics:Stop()
			inst.AnimState:PlayAnimation("honk")
		end,

		timeline =
		{
			TimeEvent(2*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/flap") end),
			TimeEvent(10*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/flap") end),
			TimeEvent(11*FRAMES, function(inst)
				PlayFootstep(inst)
				inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/swhoosh")
			end),
			TimeEvent(12*FRAMES, function(inst)
				inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/honk")
				if inst.components.combat.target and inst.components.combat.target.ShakeCamera then
					inst.components.combat.target:ShakeCamera(CAMERASHAKE.FULL, 0.75, 0.01, 2, 40)
				end
			end),
			--TimeEvent(15*FRAMES, function(inst) DisarmTarget(inst, inst.components.combat.target) end),
			TimeEvent(29*FRAMES, function(inst) PlayFootstep(inst) end),
		},

		events=
		{
			EventHandler("animqueueover", function(inst)
				inst.sg:GoToState("idle")
			end ),
		},

	},
	
	State{
		name = "attack",
		tags = {"attack", "busy"},
     
		onenter = function(inst, target)
        local buffaction = inst:GetBufferedAction()
        local target = buffaction ~= nil and buffaction.target or nil
        inst.components.combat:SetTarget(target)
        inst.components.combat:StartAttack()
        inst.components.locomotor:Stop()
        inst.Physics:Stop()
        inst.AnimState:PlayAnimation("honk")
        --if target ~= nil then
            --if target:IsValid() then
                --inst:FacePoint(target:GetPosition())
                --inst.sg.statemem.attacktarget = target
           -- end
        --end
    end,
     
    onexit = function(inst)
        inst.components.combat:SetTarget(nil)
    end,
     
    timeline =
    {
			TimeEvent(2*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/flap") end),
			TimeEvent(10*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/flap") end),
			TimeEvent(11*FRAMES, function(inst)
				PlayFootstep(inst)
				inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/swhoosh")
				inst:PerformBufferedAction()
			end),
			TimeEvent(12*FRAMES, function(inst)
				inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/honk")
				if inst.components.combat.target and inst.components.combat.target.ShakeCamera then
					inst.components.combat.target:ShakeCamera(CAMERASHAKE.FULL, 0.75, 0.01, 2, 40)
				end
			end),
			--TimeEvent(15*FRAMES, function(inst) DisarmTarget(inst, inst.components.combat.target) end),
			TimeEvent(29*FRAMES, function(inst) PlayFootstep(inst) end),
			TimeEvent(13*FRAMES, function(inst) inst:PerformBufferedAction() end),
    },
     
    events =
    {
        EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
    },
},

	
	
	State{
		name = "special_atk2",
		tags = {"busy"},

		onenter = function(inst)
			if inst.specialatk == false then
				inst.sg:GoToState("idle")
			else
				inst.sg:GoToState("layegg2")
			end	
		end,
		
		onexit = function(inst)
            
			--if inst.components.timer:TimerExists(SpecialTimer) then
            --inst.components.timer:StartTimer(SpecialTimer, 10)
			--end
        end,
		
		timeline=
        {
           
        },

		events=
		{
			EventHandler("animqueueover", function(inst)
				inst.sg:GoToState("idle")
				--inst:AddTag("nospecial")
			end ),
		},

	},
	
	State{
		name = "special_atk1",
		tags = {"busy"},

		onenter = function(inst)
			inst.Physics:Stop()
			inst.AnimState:PlayAnimation("taunt_pre")
			inst.AnimState:PushAnimation("taunt")
			inst.AnimState:PushAnimation("taunt_pst", false)
		end,

		timeline=
		{
			TimeEvent(9*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/flap") end),
			TimeEvent(11*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/taunt") end),
			TimeEvent(13*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/flap") end),
			TimeEvent(17*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/flap") end),
			TimeEvent(21*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/flap") end),
			TimeEvent(27*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/flap") end),
			TimeEvent(37*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/flap") end),
		},

		events=
		{
			EventHandler("animqueueover", function(inst) inst.sg:GoToState("idle") end),
		},
	},
	
	State{
        name = "death",
        tags = {"busy", "pausepredict", "nomorph"},

        onenter = function(inst)
            inst.components.locomotor:Stop()
            inst.components.locomotor:Clear()
            inst:ClearBufferedAction()
            inst.AnimState:PlayAnimation("death")
			--inst.components.lootdropper:DropLoot(Vector3(inst.Transform:GetWorldPosition()))
			inst.components.lootdropper:DropLoot(inst:GetPosition())
			inst.components.inventory:DropEverything(true)
            if inst.components.playercontroller ~= nil then
                inst.components.playercontroller:RemotePausePrediction()
            end
        end,
		
		timeline =
	{
		TimeEvent(0*FRAMES, function(inst)
			inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/death")
		end),

		TimeEvent(22*FRAMES, function(inst)
			inst.components.inventory:DropEverything(true)
			DeathCollapseShake(inst)
		end),
		
		TimeEvent(50*FRAMES, function(inst)
			if MOBGHOST == "Enable" then
                     inst:PushEvent(inst.ghostenabled and "makeplayerghost" or "playerdied", { skeleton = false })
					else
						TheWorld:PushEvent("ms_playerdespawnanddelete", inst)
				end
		end),
	},

        events =
        {
           
        },
	},	
	
	State{
		name = "layegg2",
		tags = {"busy"},

		onenter = function(inst)
			inst.Physics:Stop()
			inst.specialatk = false
			inst.userfunctions.StartTimer(inst, inst.charge_time + 8640*2)
			inst.AnimState:PlayAnimation("honk")
			inst.AnimState:PushAnimation("idle", false)
			
		end,

		timeline =
		{
			TimeEvent(2*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/flap") end),
			TimeEvent(10*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/flap") end),
			TimeEvent(12*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/honk") end),

			TimeEvent(15*FRAMES, function(inst) TheWorld:PushEvent("ms_forceprecipitation", true) end),

			TimeEvent(50*FRAMES,
				function(inst)
					local egg = SpawnPrefab("mooseegg")
					local offset = FindWalkableOffset(inst:GetPosition(), math.random() * 2 * math.pi, 4, 12) or Vector3(0,0,0)
					local pt = offset + inst:GetPosition()
					local isname = inst:GetDisplayName()
					local selfpos = inst:GetPosition()
					print("LOGGED: "..isname.." spawned a mossling egg at "..selfpos.x..","..selfpos.y..","..selfpos.z.." as "..inst.prefab)

					egg.Transform:SetPosition(pt:Get())
					TheWorld:PushEvent("ms_sendlightningstrike", pt)
					inst.components.entitytracker:TrackEntity("egg", egg)
					egg.components.entitytracker:TrackEntity("mother", inst)
					egg:InitEgg()
				end)
		},

		events=
		{
			EventHandler("animqueueover", function(inst)
				inst.sg:GoToState("idle")
				--inst:DoTaskInTime(9640, function() inst:RemoveTag("nospecial") end)
			end ),
		},

	},
	
	State {
        name = "sleep",
        tags = { "sleeping" }, 

        onenter = function(inst)
            if inst.components.locomotor ~= nil then
                inst.components.locomotor:StopMoving()
            end
            inst.AnimState:PlayAnimation("sleep_pre")
            --if fns ~= nil and fns.onsleep ~= nil then
                --fns.onsleep(inst)
            --end
        end,

        --timeline = timelines ~= nil and timelines.starttimeline or nil,

        events =
        {
            EventHandler("animqueueover", function(inst) inst.sg:GoToState("sleeping") end ),
            EventHandler("onwakeup", function(inst) inst.sg:GoToState("wake") end),
        },
    },

    State
    {
        name = "sleeping",
        tags = { "sleeping" },

        --onenter = onentersleeping,
		
		onenter = function(inst)
				inst.components.locomotor:StopMoving()
				local hungerpercent = inst.components.hunger:GetPercent()
				if hungerpercent ~= nil and hungerpercent ~= 0 then -- We don't want players to heal out starvation.
				inst.components.health:DoDelta(20, false)
				end
				inst.AnimState:PlayAnimation("sleep_loop")
			end,

        --timeline = timelines ~= nil and timelines.sleeptimeline or nil,
		timeline=
        {
			TimeEvent(22*FRAMES, function(inst)
			inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/sleep")
			end),
        },

        events =
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("sleeping") end ),
			EventHandler("onwakeup", function(inst) inst.sg:GoToState("wake") end),
        },
    },

    State
    {
        name = "wake",
        tags = { "busy", "waking" },

        onenter = function(inst)
            if inst.components.locomotor ~= nil then
                inst.components.locomotor:StopMoving()
            end
            inst.AnimState:PlayAnimation("sleep_pst")
            if inst.components.sleeper ~= nil and inst.components.sleeper:IsAsleep() then
                inst.components.sleeper:WakeUp()
            end
            --if fns ~= nil and fns.onwake ~= nil then
                --fns.onwake(inst)
            --end
        end,

        --timeline = timelines ~= nil and timelines.waketimeline or nil,

        events =
        {
            EventHandler("animover", function(inst) inst.sg:GoToState("idle") end),
        },
    },

}

CommonStates.AddCombatStates(states,
{
	attacktimeline =
	{
		TimeEvent(0*FRAMES, function(inst) PlayFootstep(inst) end),
		TimeEvent(13*FRAMES, function(inst) inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/swhoosh") end),
		TimeEvent(19*FRAMES, function(inst) PlayFootstep(inst) end),
		TimeEvent(20*FRAMES, function(inst)
			--if not inst.components.timer:TimerExists("DisarmCooldown") then
				--inst.components.timer:StartTimer("DisarmCooldown", 10)
			--end
			inst:PerformBufferedAction()
			inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/attack")
		end),
		TimeEvent(25*FRAMES, function(inst) inst.sg:RemoveStateTag("attack") end),
	},

	deathtimeline =
	{
		TimeEvent(0*FRAMES, function(inst)
			inst.SoundEmitter:PlaySound("dontstarve_DLC001/creatures/moose/death")
		end),

		TimeEvent(22*FRAMES, function(inst)
			inst.components.inventory:DropEverything(true)
			DeathCollapseShake(inst)
		end),
		
		TimeEvent(50*FRAMES, function(inst)
			if MOBGHOST == "Enable" then
                     inst:PushEvent(inst.ghostenabled and "makeplayerghost" or "playerdied", { skeleton = false })
					else
						TheWorld:PushEvent("ms_playerdespawnanddelete", inst)
					end
		end),
	},
})

CommonStates.AddFrozenStates(states)


return StateGraph("moosegooseplayer", states, events, "idle", actionhandlers)
