
local MakePlayerCharacter = require "prefabs/player_common"


local assets = {
    Asset("SCRIPT", "scripts/prefabs/player_common.lua"),
}

local start_inv = {
	"koishi_hat", "koi_knife", "third_eye"
}

-- When the character is revived from human
local function onbecamehuman(inst)
	inst.components.locomotor.walkspeed = 1.2 * TUNING.WILSON_WALK_SPEED
	inst.components.locomotor.runspeed = 1.2 *TUNING.WILSON_RUN_SPEED
end

-- When loading or spawning the character

local function IsValidVictim(victim)
    return victim ~= nil
        and not victim:HasTag("veggie") or
                victim:HasTag("structure") or
                victim:HasTag("wall") or
                victim:HasTag("companion")
        and victim.components.health ~= nil
        and victim.components.combat ~= nil
end

local function shifting(inst)
    if inst:HasTag("id") then
		inst.components.locomotor.walkspeed = (0.4 + 0.7*TUNING.PW) * TUNING.WILSON_WALK_SPEED
		inst.components.locomotor.runspeed = (0.4 + 0.7*TUNING.PW) *TUNING.WILSON_RUN_SPEED
		inst.components.health.absorb = -0.35 + 0.1 * TUNING.PW
		inst.components.combat.min_attack_period = 0.4-0.1*TUNING.PW
		inst.components.combat.damagemultiplier = 1.25 * TUNING.PW
		inst.components.sanity.dapperness= - 0.5 + 0.3 * TUNING.SYS
		if inst:HasTag("invsb") then
			inst.components.hunger.hungerrate = 4.5 * TUNING.WILSON_HUNGER_RATE
		else
			inst.components.hunger.hungerrate = 1.3 * TUNING.WILSON_HUNGER_RATE
		end
		if TUNING.SYS == 0 then		
			inst.IsInvisible = false
			inst:RemoveTag("notarget")
			inst.AnimState:SetMultColour(1.0,1.0,1.0,1.0)
			inst:AddTag("scarytoprey")
		end
		if TUNING.SYS == 0 and inst.components.sanity:GetPercent() < 0.04 then
			inst:RemoveTag("id")
			inst:AddTag("superego")
		elseif TUNING.SYS == 1 and inst.components.sanity:GetPercent() < 0.7 then
			if TUNING.LANG == 1 then
				inst.components.talker:Say("Pseudo-Ego State", 3, false)
			else
				inst.components.talker:Say("伪自我姿态", 3, false)
			end
			inst:RemoveTag("id")
			inst:AddTag("Calm")
		end
	end
    if inst:HasTag("superego") then
		inst.components.locomotor.walkspeed = (0.4 + 0.5*TUNING.PW) * TUNING.WILSON_WALK_SPEED
		inst.components.locomotor.runspeed = (0.4+0.5*TUNING.PW) *TUNING.WILSON_RUN_SPEED
		inst.components.health.absorb = 0.05 + 0.2 * TUNING.PW
		inst.components.combat.min_attack_period = 0.6-0.1*TUNING.PW
		inst.components.combat.damagemultiplier = 0.8 * TUNING.PW
		inst.components.sanity.dapperness= 0.5 - 0.3 * TUNING.SYS
		if inst:HasTag("invsb") then
			inst.components.hunger.hungerrate = 2.8 * TUNING.WILSON_HUNGER_RATE
		else
			inst.components.hunger.hungerrate = 0.8 * TUNING.WILSON_HUNGER_RATE
		end
		if TUNING.SYS == 0 then
			inst.isCamouflage = true
			local x,y,z = inst.Transform:GetWorldPosition() 
			local ents = TheSim:FindEntities(x, y, z, 20)
			for k,v in pairs(ents) do
				if v.components.combat and v.components.combat.target == inst then
					v.components.combat:BlankOutAttacks(0.5)
				end
			end
			inst:RemoveTag("scarytoprey")
			inst:AddTag("notarget")
			inst.AnimState:SetMultColour(.1,.1,.1,.5)
		end
		if TUNING.SYS == 0 and inst.components.sanity:GetPercent() > 0.96 then
			inst:RemoveTag("superego")
			inst:AddTag("id")
		elseif TUNING.SYS == 1 and inst.components.sanity:GetPercent() > 0.3 then
			if TUNING.LANG == 1 then
				inst.components.talker:Say("Pseudo-Ego State", 3, false)
			else
				inst.components.talker:Say("伪自我姿态", 3, false)
			end
			inst:RemoveTag("superego")
			inst:AddTag("Calm")
		end
	end
	if inst:HasTag("Calm") then
		inst.components.locomotor.walkspeed = (0.5 + 0.5*TUNING.PW) * TUNING.WILSON_WALK_SPEED
		inst.components.locomotor.runspeed = (0.5+0.5*TUNING.PW) *TUNING.WILSON_RUN_SPEED
		inst.components.health.absorb = 0
		inst.components.combat.min_attack_period = 0.5-0.1*TUNING.PW
		if inst:HasTag("invsb") then
			inst.components.hunger.hungerrate = 3.5 * TUNING.WILSON_HUNGER_RATE
		else
			inst.components.hunger.hungerrate = 1 * TUNING.WILSON_HUNGER_RATE
		end
		inst.components.sanity.dapperness= 0
		inst.components.combat.damagemultiplier = 1 * TUNING.PW
		if inst.components.sanity:GetPercent() > 0.9 then
			if TUNING.LANG == 1 then
				inst.components.talker:Say("Id State", 3, false)
			else
				inst.components.talker:Say("本我姿态", 3, false)
			end
			inst:RemoveTag("Calm")
			inst:AddTag("id")		
		end
		if inst.components.sanity:GetPercent() < 0.1 then
			if TUNING.LANG == 1 then
				inst.components.talker:Say("Superego State", 3, false)
			else
				inst.components.talker:Say("超我姿态", 3, false)
			end
			inst:RemoveTag("Calm")
			inst:AddTag("superego")			
		end
	end
	if inst:HasTag("invsb") then
		inst.isCamouflage = true
		local x,y,z = inst.Transform:GetWorldPosition() 
		local ents = TheSim:FindEntities(x, y, z, 20)
		for k,v in pairs(ents) do
			if v.components.combat and v.components.combat.target == inst then
				v.components.combat:BlankOutAttacks(0.5)
			end
		end
		inst:RemoveTag("scarytoprey")
		inst:AddTag("notarget")
		inst.AnimState:SetMultColour(.1,.1,.1,.5)
	elseif inst:HasTag("superego") and TUNING.SYS == 0 then
		inst.isCamouflage = true
		local x,y,z = inst.Transform:GetWorldPosition() 
		local ents = TheSim:FindEntities(x, y, z, 20)
		for k,v in pairs(ents) do
			if v.components.combat and v.components.combat.target == inst then
				v.components.combat:BlankOutAttacks(0.5)
			end
		end
		inst:RemoveTag("scarytoprey")
		inst:AddTag("notarget")
		inst.AnimState:SetMultColour(.1,.1,.1,.5)
	else
		inst.IsInvisible = false
		inst:RemoveTag("notarget")
		inst.AnimState:SetMultColour(1.0,1.0,1.0,1.0)
		inst:AddTag("scarytoprey")
	end
end

local function NightVision(inst)
	if TUNING.VISION == 0 then
			if TheWorld:HasTag("cave") or TheWorld.state.isnight then
				--inst.Light:Enable(true)
				--inst.Light:SetRadius(1.0)
				--inst.Light:SetFalloff(0.75)
				--inst.Light:SetIntensity(.5)
				--inst.Light:SetColour(255/255,255/255,255/255)
				inst.components.playervision:ForceNightVision(true)
				inst.components.playervision:SetCustomCCTable("images/colour_cubes/purple_moon_cc.tex")
			else
				inst.components.playervision:ForceNightVision(false)
				inst.components.playervision:SetCustomCCTable(nil)
				--inst.Light:Enable(false)
			end
	end
end

local function rose(inst)
	if TheWorld.state.isfullmoon then
		local x, y, z = inst.Transform:GetWorldPosition()
		local a = 0
		local b = 0
		repeat
			a = math.random(-5, 5)
			b = math.random(-5, 5)
		until(TheWorld.Map:IsAboveGroundAtPoint(x+a, y, z+b))
		SpawnPrefab("blue_rose").Transform:SetPosition(x+a, y, z+b, 0)
		SpawnPrefab("small_puff").Transform:SetPosition(x+a, y, z+b, 0)	
	end
end
		
local function onattack(inst, data)
	if TUNING.SYS == 0 then
		if inst:HasTag("superego") then
			inst.components.sanity:DoDelta(0.5)
		else
			inst.components.sanity:DoDelta(-0.5)
		end
	end
end

local function onload(inst)
    inst:ListenForEvent("ms_respawnedfromghost", onbecamehuman)
    if not inst:HasTag("playerghost") then
        onbecamehuman(inst)
    end
end

local function onkilled(inst, data)
    local victim = data.victim
    if IsValidVictim(victim) then
		local x, y, z = inst.Transform:GetWorldPosition()
        if victim:HasTag("epic") then
			local n = 0
			repeat
				local a = math.random(-5, 5)
				local b = math.random(-5, 5)
				if TheWorld.Map:IsAboveGroundAtPoint(x+a, y, z+b) then
					SpawnPrefab("blue_rose").Transform:SetPosition(x+a, y, z+b, 0)
					SpawnPrefab("small_puff").Transform:SetPosition(x+a, y, z+b, 0)
					n = n + 1
				end
			until(n == 3)
		elseif not victim:HasTag("chess") then
			local a = 0
			local b = 0
			local c = math.random(0, 10)
			if c < 1.5 then
				repeat
					a = math.random(-5, 5)
					b = math.random(-5, 5)
				until(TheWorld.Map:IsAboveGroundAtPoint(x+a, y, z+b))
				SpawnPrefab("blue_rose").Transform:SetPosition(x+a, y, z+b, 0)
				SpawnPrefab("small_puff").Transform:SetPosition(x+a, y, z+b, 0)
			end
        end
    end
end

-- This initializes for both the server and client. Tags can be added here.
local common_postinit = function(inst) 
	-- Minimap icon
	inst.MiniMapEntity:SetIcon( "koishi.tex" )
	inst:AddTag("koishi_builder")
    local Rt = 2
    inst:DoPeriodicTask(Rt, function() NightVision(inst, Rt) end)
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"
	inst.components.sanity.night_drain_mult = 0
	inst.components.sanity.neg_aura_mult = 0
	-- Uncomment if "wathgrithr"(Wigfrid) or "webber" voice is used
    --inst.talker_path_override = "dontstarve_DLC001/characters/"
	
	-- Stats	
	inst.components.health:SetMaxHealth(135 * TUNING.PW)
	inst.components.hunger:SetMax(100 + 25 * TUNING.PW)
	inst.components.sanity:SetMax(50)
	inst.components.combat:SetDefaultDamage(20 * TUNING.PW)
	inst.components.health.absorb = -0.35 + 0.1 * TUNING.PW
	inst.components.combat:SetRange(2.5, 2.5)

    local rt = 0.5
	local RT = 15
    inst:DoPeriodicTask(rt, function() shifting(inst, rt) end)
    inst:DoPeriodicTask(RT, function() rose(inst, RT) end)
    inst:ListenForEvent("onattackother", onattack)
    inst:ListenForEvent("killed", onkilled)
	inst:AddTag("id")
	inst:AddTag("koishi")
	inst:AddTag("scarytoprey")
	inst:AddTag("koishi_builder")
	inst.OnLoad = onload
    inst.OnNewSpawn = onload
	if TUNING.PW == 2 then
		inst.components.health:StartRegen(1, 2)
	end
	if TUNING.SYS == 0 then
		local selfeater = inst.components.eater
		local old = selfeater.Eat
		function inst.components.eater:Eat(food)
			if selfeater:CanEat(food) then
				food.components.edible.sanityvalue = 0
			end
		return old(selfeater, food)
		end
	end
end

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