PrefabFiles = {
   "ruikong",
   "ruikong_skins",
   "ruikong_fx",
   ------------
   "yinkong",
   "yinkong_skins",
   "yinkong_fx",

   "firetooth",
   "xzfire",
   "memorymetal",
   "shadowyinkong",
   "ykshadow_fx",

   --------------
   "zhuikong",
   "zhuikong_skins",

   "zhuikongsword",
   "memorymetal_z",
   "seedgift",
   "healingseed",
   "shadowzhuikong",
}

Assets = {
	Asset( "ANIM", "anim/zhuikong_exp.zip" ),
	Asset( "ANIM", "anim/ruikong_exp.zip" ),
	Asset( "ANIM", "anim/yinkong_exp.zip" ),
	-----------------------------------
	Asset( "ANIM", "anim/yk_annihilation.zip"),
	Asset("ATLAS", "images/status_bgs.xml"),

	Asset( "IMAGE", "bigportraits/yinkong_newyear.tex" ),
    Asset( "ATLAS", "bigportraits/yinkong_newyear.xml" ),

    Asset( "IMAGE", "bigportraits/ruikong_newyear.tex" ),
    Asset( "ATLAS", "bigportraits/ruikong_newyear.xml" ),

    Asset( "IMAGE", "bigportraits/zhuikong_newyear.tex" ),
    Asset( "ATLAS", "bigportraits/zhuikong_newyear.xml" ),

    Asset( "IMAGE", "bigportraits/yinkong_none.tex" ),
    Asset( "ATLAS", "bigportraits/yinkong_none.xml" ),
	
	Asset( "IMAGE", "images/avatars/avatar_yinkong_newyear.tex" ),
    Asset( "ATLAS", "images/avatars/avatar_yinkong_newyear.xml" ),

    Asset( "IMAGE", "bigportraits/zhuikong_newyear.tex" ),
    Asset( "ATLAS", "bigportraits/zhuikong_newyear.xml" ),

    Asset( "IMAGE", "bigportraits/zhuikong_none.tex" ),
    Asset( "ATLAS", "bigportraits/zhuikong_none.xml" ),
	
	Asset( "IMAGE", "images/avatars/avatar_zhuikong_newyear.tex" ),
    Asset( "ATLAS", "images/avatars/avatar_zhuikong_newyear.xml" ),

    Asset( "IMAGE", "bigportraits/ruikong_newyear.tex" ),
    Asset( "ATLAS", "bigportraits/ruikong_newyear.xml" ),

    Asset( "IMAGE", "bigportraits/ruikong_none.tex" ),
    Asset( "ATLAS", "bigportraits/ruikong_none.xml" ),
	
	Asset( "IMAGE", "images/avatars/avatar_ruikong_newyear.tex" ),
    Asset( "ATLAS", "images/avatars/avatar_ruikong_newyear.xml" ),
        
    Asset( "IMAGE", "images/inventoryimages/healingseed.tex" ),
    Asset( "ATLAS", "images/inventoryimages/healingseed.xml" ),

    Asset( "IMAGE", "images/inventoryimages/seedgift.tex" ),
    Asset( "ATLAS", "images/inventoryimages/seedgift.xml" ),
}

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

TUNING.RUIKONG_MINHUNGER = 80
TUNING.RUIKONG_MINHEALTH = 100
TUNING.RUIKONG_MINSANITY = 300
TUNING.RUIKONG_LEVELBUFF = 5
TUNING.RUIKONG_SANITYLEVELBUFF = 15
TUNING.RUIKONG_MAXLEVEL = 4
TUNING.RUIKONGMKCONSUME = 0.15
TUNING.FIRETOOTH_DAMAGE = 40
TUNING.EXP_EPIC = 75
TUNING.EXP_HUGE = 225
TUNING.SANITYAURA_FAMILY = TUNING.SANITYAURA_SMALL

TUNING.ZHUIKONG_ATTACKHEALTH = 1
TUNING.ZHUIKONG_ATTACKSANITY = 1
TUNING.ZHUIKONGSWORD_DAMAGE = 40

AddMinimapAtlas("images/map_icons/ruikong.xml")
AddModCharacter("ruikong", "FEMALE")

AddMinimapAtlas("images/map_icons/yinkong.xml")
AddModCharacter("yinkong", "FEMALE")

AddMinimapAtlas("images/map_icons/zhuikong.xml")
AddModCharacter("zhuikong", "MALE")

local zhuikong_exp = require("widgets/zhuikong_exp")
local ruikong_exp = require("widgets/ruikong_exp")
local yinkong_exp = require("widgets/yinkong_exp")
AddClassPostConstruct("widgets/controls",function(self)
	if self.owner and self.owner:HasTag("zhuikong") then
		self.zhuikong_exp = self.status:AddChild(zhuikong_exp(self.owner))	
		self.zhuikong_exp:SetPosition(-80,-40,0)	
	end
end)
AddClassPostConstruct("widgets/controls",function(self)
	if self.owner and self.owner:HasTag("yinkong") then
		self.yinkong_exp = self.status:AddChild(yinkong_exp(self.owner))	
		self.yinkong_exp:SetPosition(-80,-40,0)	
	end
end)
AddClassPostConstruct("widgets/controls",function(self)
	if self.owner and self.owner:HasTag("ruikong") then
		self.ruikong_exp = self.status:AddChild(ruikong_exp(self.owner))	
		self.ruikong_exp:SetPosition(-80,-40,0)	
	end
end)
------------------------------------------------------------------------------------------------------------------------
local function FuckGlobalUsingMetatable()
	GLOBAL.setmetatable(env, {	-- 注意: setmetatable和rawget属于GLOBAL环境, 因此它们要GLOBAL一下。
		__index = function(t, k)
			return GLOBAL.rawget(GLOBAL, k)
		end,
	})	
end
FuckGlobalUsingMetatable()

TUNING.TELESCOPE_RANGE = 200
TUNING.TELESCOPE_ARC = 15
TUNING.SHADOWYINKONG_DAMAGE = 40
TUNING.SHADOWYINKONG_LIFE = 170
-------------------蕊空------------------------
local function GetCharacter()
	return "'"..ThePlayer.userid.."'"
end

local function Look(inst, range, x, y, z, angle, arc)
		local minimap = GetWorld().minimap.MiniMap
		local map = GetWorld().Map
		local arclength = 0.5 * range * arc * DEGREES

		print("range"..range.." arc"..arc)

		--for d = 1, 2 do -- need this to speed it up
		for i= 1, range, 8 do
				for j = 0, arclength, 4 do
					local a = angle + (j / (0.5 * range * DEGREES))
					print(string.format("%4.2f = (%4.2f / %4.2f)", a, j, arclength))
					local c = math.cos(a * DEGREES)
					local s = math.sin(a * DEGREES)
					local x0, z0 = x + i * c, z + i * s
					local cx, cy, cz = map:GetTileCenterPoint(x0, 0, z0)
					if cx and cy and cz then
						minimap:ShowArea(cx, cy, cz, 30)
						print("Reveal Map:"..cx.." "..cy.." "..cz.."\n")
						inst.player_classified.MapExplorer:RevealArea(cx,cy,cz) 
						map:VisitTile(map:GetTileCoordsAtPoint(cx, cy, cz))
					end
				end
		end
end

--技能RPC,服务端
local ruikong_skills = {
	z = function(inst, x, y, z)
			local myx, myy, myz = inst.Transform:GetWorldPosition()
			local angle = -inst:GetAngleToPoint(x, y, z) - (TUNING.TELESCOPE_ARC/2)
			local level = inst.components.exp.levelpoint
			if not inst.components.health:IsDead() then
				inst.components.sanity:DoDelta(-30)
				Look(inst, TUNING.TELESCOPE_RANGE + level*50 , myx, myy, myz, angle, TUNING.TELESCOPE_ARC)
			end
		end,
	v = function(inst)
			if inst.modskin == "ruikong" then
				inst.AnimState:SetBuild("ruikong_newyear")
				inst.modskin = "ruikong_newyear"
			else
				inst.AnimState:SetBuild("ruikong")
				inst.modskin = "ruikong"
			end
		end,
}
for key, v in pairs(ruikong_skills) do
	AddModRPCHandler("ruikong", key.."_skill", v)
end

local function ruikong_onupdate(inst)
	local level = inst.components.exp.levelpoint
    inst.components.health:SetMaxHealth(100 + level*5)
    inst.components.hunger:SetMax(80 + level*5)
    inst.components.sanity:SetMax(400 + level*15)
    inst.components.exp.maxtimepiont = level*70 + 50
    if level > 0 then
    	inst:AddTag("telescope")
    end
    if level > 1 then
    	inst.components.locomotor.walkspeed = 4*1.1
    	inst.components.locomotor.runspeed = 6*1.1
    	inst.components.combat.damagemultiplier = 1
    end
    if level > 2 then
    	inst:AddTag("cancontrol")
    end
    if level > 3 then
    	inst.components.sanity.dapperness = -TUNING.DAPPERNESS_SMALL
    end
end
--------------------樱空------------------------
local function IsHUDScreen()
	local defaultscreen = false
	if TheFrontEnd:GetActiveScreen() and TheFrontEnd:GetActiveScreen().name 
		and type(TheFrontEnd:GetActiveScreen().name) == "string" 
		and TheFrontEnd:GetActiveScreen().name == "HUD" then
		defaultscreen = true
	end
	--defaultscreen = true
	return defaultscreen
end

local function DoFx(inst)
    inst.SoundEmitter:PlaySound("dontstarve/common/ghost_spawn")

    local x, y, z = inst.Transform:GetWorldPosition()
    local fx = SpawnPrefab("statue_transition_2")
    if fx ~= nil then
        fx.Transform:SetPosition(x, y, z)
        fx.Transform:SetScale(1, 2, 1)
    end
    fx = SpawnPrefab("statue_transition")
    if fx ~= nil then
        fx.Transform:SetPosition(x, y, z)
        fx.Transform:SetScale(1, 1.5, 1)
    end
end

--技能RPC,服务端
local yinkong_skills = {
	x = function(inst) --双人之镜
			if not inst:HasTag("CanUseX") then return end
			if inst:HasTag("HasShadow") then
				local followers = inst.components.leader.followers
	            for k, v in pairs(followers) do
	                if k:HasTag("shadowyinkong") then
	                    k.components.health:Kill()
	                    inst:RemoveTag("HasShadow")
	                end
	            end
			else
				local theta = math.random() * 2 * PI
			    local pt = inst:GetPosition()
			    local radius = math.random(3, 6)
			    local offset = FindWalkableOffset(pt, theta, radius, 12, true)
			    if offset then
			        local image = SpawnPrefab("shadowyinkong")
			        local pos = pt + offset
			        inst.components.sanity.penalty = 0.5
			        SpawnPrefab("ykshadowfx").Transform:SetPosition(pos:Get())
			        image.Transform:SetPosition(pos:Get())
			        image.components.follower:SetLeader(inst)
			        inst.components.health:SetMinHealth(1)
			        inst:AddTag("HasShadow")
			    end
			end
		end,
	c = function(inst) --湮灭
			if not inst:HasTag("CanUseX") then return end
			if inst:HasTag("yinkong_destory") then
				inst:RemoveTag("yinkong_destory")
				DoFx(inst)
				inst.AnimState:ClearOverrideBuild("yk_annihilation")
				inst.components.sanity.dapperness = 0
				inst.components.freezable:SetResistance(4)
				inst.components.health.fire_damage_scale = inst.components.health.fire_damage_scale + TUNING.ARMORDRAGONFLY_FIRE_RESIST
			else
				inst:AddTag("yinkong_destory")
				DoFx(inst)
				inst.AnimState:AddOverrideBuild("yk_annihilation")
				inst.components.sanity.dapperness = -TUNING.DAPPERNESS_LARGE
				inst.components.freezable:SetResistance(100)
				inst.components.health.fire_damage_scale = inst.components.health.fire_damage_scale - TUNING.ARMORDRAGONFLY_FIRE_RESIST
			end
		end,
	z = function(inst) --闪灵强化
			if inst:HasTag("yinkong_quick") then return end
			inst.components.locomotor.walkspeed = inst.components.locomotor.walkspeed*1.2
    		inst.components.locomotor.runspeed = inst.components.locomotor.runspeed*1.2
    		inst.components.hunger.hungerrate = 2 * TUNING.WILSON_HUNGER_RATE
    		inst.components.health:SetAbsorptionAmount(-0.2)
    		inst.fx = SpawnPrefab("yinkong_fx")
        	inst.fx.entity:SetParent(inst.entity)
    		inst:AddTag("yinkong_quick")
    		inst:ScreenFlash(1)
    		inst:DoTaskInTime(30,function()
    				inst:RemoveTag("yinkong_quick")
    				if inst.fx ~= nil then inst.fx:Remove() end
    				inst.components.hunger.hungerrate = TUNING.WILSON_HUNGER_RATE
    				inst.components.health:SetAbsorptionAmount(0)
    				inst.components.exp:ApplyUpgrades()
    			end)
		end,
	v = function(inst)
			if inst.modskin == "yinkong" then
				inst.AnimState:SetBuild("yinkong_newyear")
				inst.modskin = "yinkong_newyear"
			else
				inst.AnimState:SetBuild("yinkong")
				inst.modskin = "yinkong"
			end
		end,
}
for key, v in pairs(yinkong_skills) do
	AddModRPCHandler("yinkong", key.."_skill", v)
end

local function yinkong_onupdate(inst)
	local level = inst.components.exp.levelpoint
    inst.components.health:SetMaxHealth(150 + level*5)
    inst.components.hunger:SetMax(120 + level*5)
    inst.components.sanity:SetMax(200 + level*15)
    inst.components.exp.maxtimepiont = level*70 + 50
    inst.components.locomotor.walkspeed = 4*1.2
    inst.components.locomotor.runspeed = 6*1.2
    inst.components.combat.damagemultiplier = 1.2
    if level > 0 then
    	inst:AddTag("zhuaji")
    	inst.components.combat:SetDefaultDamage(30)
    	inst.components.combat:SetAttackPeriod(0)
    end
    if level > 1 then
    	inst.components.locomotor.walkspeed = 4*1.3
    	inst.components.locomotor.runspeed = 6*1.3
    	inst.components.combat.damagemultiplier = 1.3
    end
    if level > 3 then
    	inst:AddTag("CanUseX")
    end
end

--------------------缀空-----------------------
local zhuikong_skills = {
	z = function(inst) --镜像
			if inst:HasTag("HasShadow") then
				local followers = inst.components.leader.followers
	            for k, v in pairs(followers) do
	                if k:HasTag("shadowzhuikong") then
	                    k.components.health:Kill()
	                end
	            end
	            inst:RemoveTag("notarget")
			else
				local theta = math.random() * 2 * PI
			    local pt = inst:GetPosition()
			    local radius = math.random(3, 6)
			    local offset = FindWalkableOffset(pt, theta, radius, 12, true)
			    if offset then
			        local image = SpawnPrefab("shadowzhuikong")
			        local pos = pt + offset
			        if inst.components.exp.levelpoint < 4 then
			        	inst.components.sanity.penalty = 0.28
			        else
			        	inst.components.sanity.penalty = 0.32
			        	image.components.health:SetMaxHealth(20)
			        end
			        image.Transform:SetPosition(pos:Get())
			        image.components.follower:SetLeader(inst)
			        inst:AddTag("HasShadow")
			    end
			    inst:AddTag("notarget")
			end
		end,
	v = function(inst)
			if inst.modskin == "zhuikong" then
				inst.AnimState:SetBuild("zhuikong_newyear")
				inst.modskin = "zhuikong_newyear"
			else
				inst.AnimState:SetBuild("zhuikong")
				inst.modskin = "zhuikong"
			end
		end,
}
for key, v in pairs(zhuikong_skills) do
	AddModRPCHandler("zhuikong", key.."_skill", v)
end
local function zhuikong_onupdate(inst)
	local level = inst.components.exp.levelpoint
    inst.components.health:SetMaxHealth(150 + level*5)
    inst.components.hunger:SetMax(120 + level*5)
    inst.components.sanity:SetMax(320 + level*10)
    inst.components.exp.maxtimepiont = level*80 + 50
    inst.components.locomotor.walkspeed = 4*1.05
    inst.components.locomotor.runspeed = 6*1.05
    inst.components.combat.damagemultiplier = 0.75
    if level > 0 then
    	inst.components.locomotor.walkspeed = 4*1.1
    	inst.components.locomotor.runspeed = 6*1.1
    	inst.components.combat.damagemultiplier = 1.0
    	--陷阱大师
    end
    if level > 1 then
    	inst.components.locomotor.walkspeed = 4*1.2
    	inst.components.locomotor.runspeed = 6*1.2
    	inst.components.combat.damagemultiplier = 1.1
    end
    if level > 2 then
    	inst.components.combat.damagemultiplier = 1.25
    end
    if level > 3 then
    	inst:AddTag("zkcunbu")
    	inst.components.sanity.dapperness = -TUNING.DAPPERNESS_SMALL
    end
end
-----------------------------------------------

---Player--------------------------------------
AddPlayerPostInit(function(inst)
	if inst:HasTag("ruikong") then
		inst.exp_max = GLOBAL.net_shortint(inst.GUID, "exp_max", "exp_maxdirty")
		inst.exp_current = GLOBAL.net_shortint(inst.GUID, "exp_current", "exp_currentdirty")
		inst.exp_level = GLOBAL.net_shortint(inst.GUID, "exp_level", "exp_leveldirty")
		if GLOBAL.TheWorld.ismastersim then
			inst:AddComponent("exp")
			inst.components.exp.updatefn = ruikong_onupdate
			inst.components.exp.maxlevel = 4
		end
			TheInput:AddKeyDownHandler(GLOBAL["KEY_Z"], function() 
				if inst == ThePlayer and inst:HasTag("telescope") and not inst.HUD:IsMapScreenOpen() and IsHUDScreen() then
					local x, y, z = ( TheInput:GetWorldPosition() or Vector3(0,0,0) ):Get()
					local myx, myy, myz = inst.Transform:GetWorldPosition()
					local angle = -inst:GetAngleToPoint(x, y, z) - (TUNING.TELESCOPE_ARC/2)
					inst.AnimState:PlayAnimation("emote_hat")
					SendModRPCToServer(MOD_RPC["ruikong"]["z_skill"], x, y, z,GetCharacter())
					inst:DoTaskInTime(1,function()
						ThePlayer.HUD.controls:ToggleMap()
						end)
				end
			end)
			TheInput:AddKeyDownHandler(GLOBAL["KEY_V"], function() 
				if inst == ThePlayer  and IsHUDScreen() then
					SendModRPCToServer(MOD_RPC["ruikong"]["v_skill"])
				end
			end)
	elseif inst:HasTag("yinkong") then
		inst.exp_max = GLOBAL.net_shortint(inst.GUID, "exp_max", "exp_maxdirty")
		inst.exp_current = GLOBAL.net_shortint(inst.GUID, "exp_current", "exp_currentdirty")
		inst.exp_level = GLOBAL.net_shortint(inst.GUID, "exp_level", "exp_leveldirty")

		inst:AddComponent("fenshensaver")
		local _OnDespawn = inst._OnDespawn or function() end
		function inst._OnDespawn(inst, ...)
			_OnDespawn(inst, ...)
			inst.components.fenshensaver:SaveFenshen()
		end

		if GLOBAL.TheWorld.ismastersim then
			inst:AddComponent("exp")
			inst.components.exp.updatefn = yinkong_onupdate
			inst.components.exp.maxlevel = 4
			inst.components.exp:ApplyUpgrades()
		end
			TheInput:AddKeyDownHandler(GLOBAL["KEY_Z"], function() 
				if inst == ThePlayer and IsHUDScreen() then
					SendModRPCToServer(MOD_RPC["yinkong"]["z_skill"])
				end
			end)
			TheInput:AddKeyDownHandler(GLOBAL["KEY_X"], function() 
				if inst == ThePlayer  and IsHUDScreen() then
					SendModRPCToServer(MOD_RPC["yinkong"]["x_skill"])
				end
			end)
			TheInput:AddKeyDownHandler(GLOBAL["KEY_C"], function() 
				if inst == ThePlayer  and IsHUDScreen() then
					SendModRPCToServer(MOD_RPC["yinkong"]["c_skill"])
				end
			end)
			TheInput:AddKeyDownHandler(GLOBAL["KEY_V"], function() 
				if inst == ThePlayer  and IsHUDScreen() then
					SendModRPCToServer(MOD_RPC["yinkong"]["v_skill"])
				end
			end)
	elseif inst:HasTag("zhuikong") then
		inst.exp_max = GLOBAL.net_shortint(inst.GUID, "exp_max", "exp_maxdirty")
		inst.exp_current = GLOBAL.net_shortint(inst.GUID, "exp_current", "exp_currentdirty")
		inst.exp_level = GLOBAL.net_shortint(inst.GUID, "exp_level", "exp_leveldirty")

		inst:AddComponent("fenshensaver")
		local _OnDespawn = inst._OnDespawn or function() end
		function inst._OnDespawn(inst, ...)
			_OnDespawn(inst, ...)
			inst.components.fenshensaver:SaveFenshen()
		end

		if GLOBAL.TheWorld.ismastersim then
			inst:AddComponent("exp")
			inst.components.exp.updatefn = zhuikong_onupdate
			inst.components.exp.maxlevel = 4
			inst.components.exp:ApplyUpgrades()
		end
			TheInput:AddKeyDownHandler(GLOBAL["KEY_Z"], function() 
				if inst == ThePlayer and IsHUDScreen() then
					SendModRPCToServer(MOD_RPC["zhuikong"]["z_skill"])
				end
			end)
			TheInput:AddKeyDownHandler(GLOBAL["KEY_V"], function() 
				if inst == ThePlayer  and IsHUDScreen() then
					SendModRPCToServer(MOD_RPC["zhuikong"]["v_skill"])
				end
			end)
	end
end)

----------Recipe-------------------------
local Recipe = GLOBAL.Recipe
local RECIPETABS = GLOBAL.RECIPETABS
local TECH = GLOBAL.TECH

local healingseed = Recipe("healingseed",{ Ingredient("twigs", 2), Ingredient("cutgrass", 3), Ingredient("seeds_cooked", 4) }, RECIPETABS.SURVIVAL, TECH.NONE, nil, nil, nil, nil, "zhuikong")
healingseed.atlas = "images/inventoryimages/healingseed.xml"
healingseed.sortkey = 1

local seedgift = Recipe("seedgift",{ Ingredient("seeds", 10), Ingredient("papyrus", 1)}, RECIPETABS.SURVIVAL, TECH.NONE, nil, nil, nil, nil, "zhuikong")
seedgift.atlas = "images/inventoryimages/seedgift.xml"
seedgift.sortkey = 2
-----------------------------------------

-- Actions ------------------------------
local RUIKONGMK = Action({distance=36})
RUIKONGMK.id = "RUIKONGMK"
RUIKONGMK.str = "控制/解控"
RUIKONGMK.fn = function(act)
	if act.doer ~= nil and act.target ~= nil and act.doer:HasTag('player') then
		if act.target:HasTag("player") then
			local doer = act.doer
			local learner = act.target
			local mapscroll1 = GLOBAL.SpawnPrefab("mapscroll")
			local mapscroll2 = GLOBAL.SpawnPrefab("mapscroll")
			mapscroll1.components.maprecorder:RecordMap(learner)
			mapscroll1.components.maprecorder:TeachMap(doer)
			if mapscroll1 ~= nil then mapscroll1:Remove() end
			mapscroll2.components.maprecorder:RecordMap(doer)
			mapscroll2.components.maprecorder:TeachMap(learner)
			if mapscroll2 ~= nil then mapscroll2:Remove() end
			doer.components.sanity:DoDelta(-10)
			return true
		end
		if act.target:HasTag("controled") then
			act.doer.components.leader:RemoveFollower(act.target)
			act.target:RemoveTag("controled")
			act.doer.components.sanity.penalty = act.doer.components.sanity.penalty - TUNING.RUIKONGMKCONSUME
		else
			if act.doer.components.sanity.penalty >= 1 - TUNING.RUIKONGMKCONSUME then return false end
			act.doer:PushEvent("makefriend")
	        act.doer.components.leader:AddFollower(act.target)
	        act.doer.components.sanity.penalty = act.doer.components.sanity.penalty + TUNING.RUIKONGMKCONSUME
	        act.target:AddTag("controled")
		end
		return true
	else
		return false
	end
end

AddAction(RUIKONGMK)

GLOBAL.ACTIONS.RUIKONGMK.stroverridefn = function(act)
	local target = act.target
	if target == nil then return end
	if target:HasTag("pig") then
		return target:HasTag("controled") and "解控" or "控制"
	else 
		return "精神锁链"
	end
end

local ZKCUNBU = Action({distance=36})
ZKCUNBU.id = "ZKCUNBU"
ZKCUNBU.str = "寸步"
ZKCUNBU.fn = function(act)
	if act.doer ~= nil and act.doer:HasTag("zkcunbu") and act.target ~= nil and act.doer:HasTag('player') 
		and act.target.components.combat and act.target.components.health then
		local damage = 10
		local item = act.doer.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS)
        if item and item.components.weapon then
        	damage = item.components.weapon.damage
        end
        damage = damage * act.doer.components.combat.damagemultiplier * 2
		act.target.components.health:DoDelta(-damage)
		act.target:PushEvent("attacked", { attacker = act.doer, damage = 0 })
		act.doer.components.sanity:DoDelta(-5)
		return true
	else
		return false
	end
end
AddAction(ZKCUNBU)

-- Component actions ---------------------
AddComponentAction("SCENE", "combat", function(inst, doer, actions, right)
	if right then
		if doer:HasTag("cancontrol") and inst.replica.health ~= nil and inst:HasTag("pig") 
			and not inst:HasTag("werepig") and not inst:HasTag("guard") then
			table.insert(actions, GLOBAL.ACTIONS.RUIKONGMK)
		end
		if doer:HasTag("ruikong") and inst:HasTag("player") and inst ~= doer then
			table.insert(actions, GLOBAL.ACTIONS.RUIKONGMK)
		end
		if doer:HasTag("zkcunbu") and inst.replica.health ~= nil and not inst:HasTag("player") then
			table.insert(actions, GLOBAL.ACTIONS.ZKCUNBU)
		end
	end
end)

------State---------------
local state_ruikongmk = GLOBAL.State{ name = "ruikongmk",
	tags = { "doing", "busy" },

	onenter = function(inst)
		inst.components.locomotor:Stop()
		
		local handitem = nil
		if inst.components.inventory then
			handitem = inst.components.inventory.equipslots[GLOBAL.EQUIPSLOTS.HANDS]
		elseif inst.replica.inventory then
			handitem = inst.replica.inventory:GetEquippedItem(GLOBAL.EQUIPSLOTS.HANDS)
		end
		if handitem then
			inst.AnimState:Hide("ARM_carry")
			inst.AnimState:Show("ARM_normal")
		end
		
		inst.AnimState:PlayAnimation("emote_waving")
		--inst.SoundEmitter:PlaySound("dontstarve/wilson/attack_whoosh", nil, nil, true)
		
		inst.sg.statemem.action = inst.bufferedaction
		inst.sg:SetTimeout(2)
		
		if not GLOBAL.TheWorld.ismastersim then
			inst:PerformPreviewBufferedAction()
		end
	end,

	timeline =
	{
		GLOBAL.TimeEvent(8 * GLOBAL.FRAMES, function(inst)
			if GLOBAL.TheWorld.ismastersim then
				inst:PerformBufferedAction()
			end
		end),
		GLOBAL.TimeEvent(15 * GLOBAL.FRAMES, function(inst)
			inst.sg:RemoveStateTag("busy")
		end),
	},
	
	onupdate = function(inst)
		if not GLOBAL.TheWorld.ismastersim then
			if inst:HasTag("doing") then
				if inst.entity:FlattenMovementPrediction() then
					inst.sg:GoToState("idle", "noanim")
				end
			elseif inst.bufferedaction == nil then
				inst.sg:GoToState("idle", true)
			end
		end
	end,
	
	ontimeout = function(inst)
		local handitem = nil
		if inst.components.inventory then
			handitem = inst.components.inventory.equipslots[GLOBAL.EQUIPSLOTS.HANDS]
		elseif inst.replica.inventory then
			handitem = inst.replica.inventory:GetEquippedItem(GLOBAL.EQUIPSLOTS.HANDS)
		end
		if handitem then
			inst.AnimState:Show("ARM_carry")
			inst.AnimState:Hide("ARM_normal")
		end
		
		if not GLOBAL.TheWorld.ismastersim then
			inst:ClearBufferedAction()  -- client
		end
		inst.sg:GoToState("idle")
	end,
	
	onexit = function(inst)
		local handitem = nil
		if inst.components.inventory then
			handitem = inst.components.inventory.equipslots[GLOBAL.EQUIPSLOTS.HANDS]
		elseif inst.replica.inventory then
			handitem = inst.replica.inventory:GetEquippedItem(GLOBAL.EQUIPSLOTS.HANDS)
		end
		if handitem then
			inst.AnimState:Show("ARM_carry")
			inst.AnimState:Hide("ARM_normal")
		end
		
		if inst.bufferedaction == inst.sg.statemem.action then
			inst:ClearBufferedAction()
		end
		inst.sg.statemem.action = nil
	end,
}
AddStategraphState("wilson", state_ruikongmk)
AddStategraphState("wilson_client", state_ruikongmk)
AddStategraphActionHandler("wilson", GLOBAL.ActionHandler(GLOBAL.ACTIONS.RUIKONGMK, "ruikongmk"))
AddStategraphActionHandler("wilson_client", GLOBAL.ActionHandler(GLOBAL.ACTIONS.RUIKONGMK, "ruikongmk"))
AddStategraphActionHandler("wilson", GLOBAL.ActionHandler(GLOBAL.ACTIONS.ZKCUNBU, "quickcastspell"))
AddStategraphActionHandler("wilson_client", GLOBAL.ActionHandler(GLOBAL.ACTIONS.ZKCUNBU, "quickcastspell"))

local function SGwilsonPostInit(self)
    self.states["attack"].onenter = function(inst)
            local buffaction = inst:GetBufferedAction()
            local target = buffaction ~= nil and buffaction.target or nil
            local equip = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS)
            inst.components.combat:SetTarget(target)
            inst.components.combat:StartAttack()
            inst.components.locomotor:Stop()
            local cooldown = inst.components.combat.min_attack_period + .5 * FRAMES
            if inst.components.rider:IsRiding() then
                if equip ~= nil and (equip.components.projectile ~= nil or equip:HasTag("rangedweapon")) then
                    inst.AnimState:PlayAnimation("player_atk_pre")
                    inst.AnimState:PushAnimation("player_atk", false)
                    if (equip.projectiledelay or 0) > 0 then
                        inst.sg.statemem.projectiledelay = 8 * FRAMES - equip.projectiledelay
                        if inst.sg.statemem.projectiledelay > FRAMES then
                            inst.sg.statemem.projectilesound =
                                (equip:HasTag("icestaff") and "dontstarve/wilson/attack_icestaff") or
                                (equip:HasTag("firestaff") and "dontstarve/wilson/attack_firestaff") or
                                "dontstarve/wilson/attack_weapon"
                        elseif inst.sg.statemem.projectiledelay <= 0 then
                            inst.sg.statemem.projectiledelay = nil
                        end
                    end
                    if inst.sg.statemem.projectilesound == nil then
                        inst.SoundEmitter:PlaySound(
                            (equip:HasTag("icestaff") and "dontstarve/wilson/attack_icestaff") or
                            (equip:HasTag("firestaff") and "dontstarve/wilson/attack_firestaff") or
                            "dontstarve/wilson/attack_weapon",
                            nil, nil, true
                        )
                    end
                    cooldown = math.max(cooldown, 13 * FRAMES)
                else
                    inst.AnimState:PlayAnimation("atk_pre")
                    inst.AnimState:PushAnimation("atk", false)
                    DoMountSound(inst, inst.components.rider:GetMount(), "angry", true)
                    cooldown = math.max(cooldown, 16 * FRAMES)
                end
            elseif equip ~= nil and equip:HasTag("whip") then
                inst.AnimState:PlayAnimation("whip_pre")
                inst.AnimState:PushAnimation("whip", false)
                inst.sg.statemem.iswhip = true
                inst.SoundEmitter:PlaySound("dontstarve/common/whip_pre", nil, nil, true)
                cooldown = math.max(cooldown, 17 * FRAMES)
            elseif equip ~= nil and equip:HasTag("book") then
                inst.AnimState:PlayAnimation("attack_book")
                inst.sg.statemem.isbook = true
                inst.SoundEmitter:PlaySound("dontstarve/wilson/attack_whoosh", nil, nil, true)
                cooldown = math.max(cooldown, 19 * FRAMES)
            elseif equip ~= nil and equip:HasTag("chop_attack") and inst:HasTag("woodcutter") then
                inst.AnimState:PlayAnimation(inst.AnimState:IsCurrentAnimation("woodie_chop_loop") and inst.AnimState:GetCurrentAnimationTime() < 7.1 * FRAMES and "woodie_chop_atk_pre" or "woodie_chop_pre")
                inst.AnimState:PushAnimation("woodie_chop_loop", false)
                inst.sg.statemem.ischop = true
                cooldown = math.max(cooldown, 11 * FRAMES)
            elseif equip ~= nil and equip.components.weapon ~= nil and not equip:HasTag("punch") then
                inst.AnimState:PlayAnimation("atk_pre")
                inst.AnimState:PushAnimation("atk", false)
                if (equip.projectiledelay or 0) > 0 then
                    --V2C: Projectiles don't show in the initial delayed frames so that
                    --     when they do appear, they're already in front of the player.
                    --     Start the attack early to keep animation in sync.
                    inst.sg.statemem.projectiledelay = 8 * FRAMES - equip.projectiledelay
                    if inst.sg.statemem.projectiledelay > FRAMES then
                        inst.sg.statemem.projectilesound =
                            (equip:HasTag("icestaff") and "dontstarve/wilson/attack_icestaff") or
                            (equip:HasTag("firestaff") and "dontstarve/wilson/attack_firestaff") or
                            "dontstarve/wilson/attack_weapon"
                    elseif inst.sg.statemem.projectiledelay <= 0 then
                        inst.sg.statemem.projectiledelay = nil
                    end
                end
                if inst.sg.statemem.projectilesound == nil then
                    inst.SoundEmitter:PlaySound(
                        (equip:HasTag("icestaff") and "dontstarve/wilson/attack_icestaff") or
                        (equip:HasTag("shadow") and "dontstarve/wilson/attack_nightsword") or
                        (equip:HasTag("firestaff") and "dontstarve/wilson/attack_firestaff") or
                        "dontstarve/wilson/attack_weapon",
                        nil, nil, true
                    )
                end
                cooldown = math.max(cooldown, 13 * FRAMES)
            elseif equip ~= nil and (equip:HasTag("light") or equip:HasTag("nopunch")) then
                inst.AnimState:PlayAnimation("atk_pre")
                inst.AnimState:PushAnimation("atk", false)
                inst.SoundEmitter:PlaySound("dontstarve/wilson/attack_weapon", nil, nil, true)
                cooldown = math.max(cooldown, 13 * FRAMES)
            elseif inst:HasTag("beaver") then
                inst.sg.statemem.isbeaver = true
                inst.AnimState:PlayAnimation("atk_pre")
                inst.AnimState:PushAnimation("atk", false)
                inst.SoundEmitter:PlaySound("dontstarve/wilson/attack_whoosh", nil, nil, true)
                cooldown = math.max(cooldown, 13 * FRAMES)
            elseif inst:HasTag("zhuaji") then
            	--[[
                inst.AnimState:PlayAnimation("atk_pre")
                inst.AnimState:PushAnimation("atk", false)
                ]]
                inst.AnimState:PlayAnimation("punch")
                inst.SoundEmitter:PlaySound("dontstarve/wilson/attack_whoosh", nil, nil, true)
                cooldown = math.max(cooldown, 13 * FRAMES)
            else
                inst.AnimState:PlayAnimation("punch")
                inst.SoundEmitter:PlaySound("dontstarve/wilson/attack_whoosh", nil, nil, true)
                cooldown = math.max(cooldown, 24 * FRAMES)
            end

            inst.sg:SetTimeout(cooldown)

            if target ~= nil then
                inst.components.combat:BattleCry()
                if target:IsValid() then
                    inst:FacePoint(target:GetPosition())
                    inst.sg.statemem.attacktarget = target
                end
            end
        end
end

AddStategraphPostInit("wilson",SGwilsonPostInit)

local function zhuikongoverride(parent)
    parent.AnimState:SetClientSideBuildOverrideFlag("zhuikong", parent:HasTag("zhuikong"))
end
local function RegisterNetListeners(inst)
	if inst._parent ~= nil then
		zhuikongoverride(inst._parent)
	end
end
AddPrefabPostInit("player_classified",function(inst)
		inst:DoTaskInTime(0, RegisterNetListeners)
	end)

GLOBAL.FUELTYPE.GOLD = "gold"

table.insert(GLOBAL.FUELTYPE,GLOBAL.FUELTYPE.GOLD)

AddPrefabPostInit("goldnugget", function(inst)
	inst:AddComponent("fuel")
	--inst:AddTag("gold_fuel")
	if inst.components.fuel then
	    inst.components.fuel.fuelvalue = 10
	    inst.components.fuel.fueltype = "CHEMICAL"
	end
end)

-----------皮肤--------------
modimport("scripts/ruikongmod_skins.lua")
modimport("scripts/yinkongmod_skins.lua")
modimport("scripts/zhuikongmod_skins.lua")