PrefabFiles = {
	"nightly"
}

Assets = {
    Asset( "IMAGE", "images/saveslot_portraits/nightly.tex" ),
    Asset( "ATLAS", "images/saveslot_portraits/nightly.xml" ),

    Asset( "IMAGE", "images/selectscreen_portraits/nightly.tex" ),
    Asset( "ATLAS", "images/selectscreen_portraits/nightly.xml" ),

    Asset( "IMAGE", "bigportraits/nightly.tex" ),
    Asset( "ATLAS", "bigportraits/nightly.xml" ),
	
	Asset( "IMAGE", "images/map_icons/nightly.tex" ),
	Asset( "ATLAS", "images/map_icons/nightly.xml" ),
	
	Asset( "IMAGE", "images/avatars/avatar_nightly.tex" ),
    Asset( "ATLAS", "images/avatars/avatar_nightly.xml" ),
	
	Asset( "IMAGE", "images/avatars/avatar_ghost_nightly.tex" ),
    Asset( "ATLAS", "images/avatars/avatar_ghost_nightly.xml" ),
	
	Asset("SOUNDPACKAGE", "sound/nightly.fev"),
    Asset("SOUND", "sound/nightly.fsb"),
}
 
RemapSoundEvent( "dontstarve/characters/nightly/death_voice", "nightly/characters/nightly/death_voice" )
RemapSoundEvent( "dontstarve/characters/nightly/hurt", "nightly/characters/nightly/hurt" )
RemapSoundEvent( "dontstarve/characters/nightly/talk_LP", "nightly/characters/nightly/talk_LP" )
RemapSoundEvent( "dontstarve/characters/nightly/emote", "nightly/characters/nightly/emote" )


GLOBAL.nightly_voice = GetModConfigData("nightly_voice")

GetPlayer = GLOBAL.GetPlayer
ACTIONS = GLOBAL.ACTIONS

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

-- The character select screen lines
STRINGS.CHARACTER_TITLES.nightly = "The Furry"
STRINGS.CHARACTER_NAMES.nightly = "Nightly"
STRINGS.CHARACTER_DESCRIPTIONS.nightly = "*Isn't scared of the dark\n*Loves anything that glows!\n*Is allergic to bees"
STRINGS.CHARACTER_QUOTES.nightly = "\"Someday this world will be mine!\""

-- Custom speech strings.
STRINGS.CHARACTERS.NIGHTLY = require "speech_nightly"

-- DST 
STRINGS.NAMES.NIGHTLY = "Nightly"
STRINGS.CHARACTERS.GENERIC.DESCRIBE.NIGHTLY = 
{
	GENERIC = "It's Nightly!",
	ATTACKER = "That Nightly looks shifty...",
	MURDERER = "Murderer!",
	REVIVER = "Nightly, friend of ghosts.",
	GHOST = "Nightly could use a heart.",
}
table.insert(GLOBAL.EMOTES,{command="/yap", anim={"emoteXL_waving1", "emoteXL_waving2", "emoteXL_waving4", "emoteXL_waving3", "emoteXL_happycheer", "emoteXL_angry", "emoteXL_annoyed", "research", "emoteXL_bonesaw", "emoteXL_facepalm"}, randomanim=true})
table.insert(GLOBAL.EMOTES,{command="/yip", anim={"emoteXL_waving1", "emoteXL_waving2", "emoteXL_waving4", "emoteXL_waving3", "emoteXL_happycheer", "emoteXL_angry", "emoteXL_annoyed", "research", "emoteXL_bonesaw", "emoteXL_facepalm"}, randomanim=true})


-- Add Fireflies as a food type
GLOBAL.FOODTYPE.FIREFLIES = "FIREFLIES"

-- Let the game know nightly is a male, for proper pronouns during the end-game sequence.
table.insert(GLOBAL.CHARACTER_GENDERS.MALE, "nightly")

-- Determine if post-initializations should be done (obsolete)
local initNightly = function()
	return true
end

local IsMasterSim = function()
	if not GLOBAL.TheWorld.ismastersim then
		return false
	end
	return true
end

local breakChance = function (doer)
	return doer.components.sanity and doer.components.sanity:GetPercent() < 0.20 and math.random() < .25
end
-- Function to add a breaking chance to actions
local AddBreakChance = function(fn_orig)
	return function(act)
		local actdone = fn_orig(act)
		local tar = act.target or act.invobject
		if tar.components.workable and initNightly() and act.doer.prefab == "nightly" then
			if breakChance(act.doer) then
				act.doer.components.talker:Say("Welp. I broke it.")
				tar.components.workable.onfinish(tar, act.doer)
				return true
			end
		end
		return actdone
	end
end

-- Breaking chance to actions
ACTIONS.TURNON.fn = AddBreakChance(ACTIONS.TURNON.fn)
ACTIONS.TURNOFF.fn = AddBreakChance(ACTIONS.TURNOFF.fn)
ACTIONS.HARVEST.fn = AddBreakChance(ACTIONS.HARVEST.fn)
ACTIONS.RUMMAGE.fn = AddBreakChance(ACTIONS.RUMMAGE.fn)
ACTIONS.REPAIR.fn = AddBreakChance(ACTIONS.REPAIR.fn)
if GLOBAL.IsDLCEnabled(GLOBAL.REIGN_OF_GIANTS)then
	ACTIONS.MANUALEXTINGUISH.fn = AddBreakChance(ACTIONS.MANUALEXTINGUISH.fn)
end

--function to add/change a sanity aura for specific objects
local setNightlyAura = function(NightlyAura)
	return function(prefab)
		if initNightly() and IsMasterSim() then
			if not prefab.components.sanityaura then
				prefab:AddComponent("sanityaura")
			end
			local aurafn_orig = prefab.components.sanityaura.aurafn
			local testaura = function() 
				if prefab:HasTag("burnt") then return false end
				return true
			end
			if prefab:HasTag("tree") then
				testaura = function()
					if prefab:HasTag("stump") or prefab:HasTag("burnt") then return false end
					return true
				end
			elseif prefab.components.pickable then
				-- Only activate when not picked
				testaura = function()
					if prefab.components.pickable:CanBePicked() then return true end
					return false
				end
			elseif prefab.prefab == "fireflies" then
				-- Only activate at night
				testaura = function()
					if GLOBAL.TheWorld.state.isnight then return true end
					return false
				end
				elseif prefab.prefab == "lightning_rod" then
				-- Check if charged
				testaura = function()
					if prefab.charged then return true end
					return false
				end
			end
			
			prefab.components.sanityaura.aurafn = function(inst, observer)
				-- Check if nightly and any other special conditions
				if observer.prefab == "nightly" and testaura() then
					return NightlyAura
				end
				if aurafn_orig then
					return aurafn_orig(inst, observer)
				end
				return 0
			end
		end
	end
end

--function to add/change dapperness for specific items
local setNightlyDapper = function(NightlyDapper)
	return function(prefab)
		if initNightly() and IsMasterSim() then
			local dapperfn_orig
			local dapperfn_plus = function(inst,owner)
				if owner.prefab == "nightly" then
					return NightlyDapper
				end
				if dapperfn_orig then
					return dapperfn_orig(inst,owner)
				end
				return 0
			end
			if GLOBAL.IsDLCEnabled(GLOBAL.REIGN_OF_GIANTS) then
				-- for RoG?
				dapperfn_orig = prefab.components.equippable.dapperfn
				prefab.components.equippable.dapperfn = dapperfn_plus
			else
				-- for classic?
				if not prefab.components.dapperness then
					prefab:AddComponent("dapperness")
				end
				dapperfn_orig = prefab.components.dapperness.dapperfn
				prefab.components.dapperness.dapperfn = dapperfn_plus
			end
		end
	end
end

-- Function to change sanity on attack
local setNightlyAttack = function (NightlyAttack)
	return function(prefab)
		if initNightly() and prefab.components.weapon then
			local onattack_orig = prefab.components.weapon.onattack -- Store original function
			local onattack_plus = function(attacker, target, projectile)
				if target.prefab == "nightly" then
					if target.components.sanity then
						target.components.sanity:DoDelta(NightlyAttack)
					end
				end
				if onattack_orig then
					onattack_orig(attacker, target, projectile) -- Add original to new function
				end
			end
			prefab.components.weapon.onattack = onattack_plus
		end
	end
end


-- Function to change sanity on finishing work
local setNightlyFinish = function (NightlyFinish)
	return function(prefab)
		if initNightly() and prefab.components.workable then
			local onfinish_orig = prefab.components.workable.onfinish -- Store original function
			local onfinish_plus = function(inst, worker)
				if worker.prefab == "nightly" then
					if worker and worker.components.sanity then
						worker.components.sanity:DoDelta(NightlyFinish)
					end
					local sayresponse = false
					if math.random() < .2 then
						sayresponse = true
					end
					if sayresponse then
						local possibleresponses = {"Gah!", "Fantastic!", "Destroy!", "It looks better this way."}
						worker.components.talker:Say(possibleresponses[math.random(5)])
					end
				end
				if onfinish_orig then
					onfinish_orig(inst, worker) -- Add original to new function
				end
			end
			prefab.components.workable.onfinish = onfinish_plus
		end
	end
end


-- Nightly hates sewing
local setNightlySew = function (NightlySew)
	return function(prefab)
		if initNightly() and prefab.components.sewing then
			local onsewn_orig = prefab.components.sewing.onsewn -- Store original function
			local onsewn_plus = function(inst, target, doer)
				if doer.prefab == "nightly" then
					if doer.components.sanity then
						doer.components.sanity:DoDelta(NightlySew)
					end
					doer.components.talker:Say("GAH! Scary needle!")
				end
				if onsewn_orig then
					onsewn_orig(inst, target, doer) -- Add original to new function
				end
			end
			prefab.components.sewing.onsewn = onsewn_plus
		end
	end
end

-- Function to change sanity on hit
local setNightlyHit = function (NightlyHit)
	return function(prefab)
		if initNightly() and prefab.components.combat then
			local onhitotherfn_orig = prefab.components.combat.onhitotherfn -- Store original function
			local onhitotherfn_plus = function(attacker, inst, damage)
				if inst.prefab == "nightly" then
					if inst.components.sanity then
						inst.components.sanity:DoDelta(NightlyHit)
					end
					inst.components.talker:Say("No! Stingers!")
				end
				if onhitotherfn_orig then
					onhitotherfn_orig(attacker, inst, damage) -- Add original to new function
				end
			end
			prefab.components.combat.onhitotherfn = onhitotherfn_plus
		end
	end
end

-- Functions to change effects of consumables
local setNightlyConsume = function (newvaluefn)
	return function(prefab)
		if initNightly() and IsMasterSim() then
			if not prefab.components.edible then
				prefab:AddComponent("edible")
			end
			local edible = prefab.components.edible
			edible.nightly_sanityvalue = edible.sanityvalue
			edible.nightly_hungervalue = edible.hungervalue
			edible.nightly_healthvalue = edible.healthvalue
			edible.GetSanity_nightly_redirect = edible.GetSanity
			edible.GetHunger_nightly_redirect = edible.GetHunger
			edible.GetHealth_nightly_redirect = edible.GetHealth
			
			function edible:GetSanity(eater)
				if eater and eater.prefab == "nightly" then
					local ignore_spoilage = (eater and eater.components.eater and eater.components.eater.ignoresspoilage) or edible.nightly_hungervalue < 0
					if edible.inst.components.perishable and not ignore_spoilage then
						if edible.inst.components.perishable:IsStale() then
							if edible.nightly_sanityvalue > 0 then
								return 0
							end
						elseif edible.inst.components.perishable:IsSpoiled() then
							return -TUNING.SANITY_SMALL
						end
					end
					return edible.nightly_sanityvalue
				end
				return edible:GetSanity_nightly_redirect(eater)
			end
			
			function edible:GetHunger(eater)
				if eater and eater.prefab == "nightly" then
					local multiplier = 1
					
					local ignore_spoilage = (eater and eater.components.eater and eater.components.eater.ignoresspoilage) or edible.nightly_hungervalue < 0
					
					if edible.inst.components.perishable and not ignore_spoilage then
						if edible.inst.components.perishable:IsStale() then
							multiplier = edible.stale_hunger
						elseif edible.inst.components.perishable:IsSpoiled() then
							multiplier = edible.spoiled_hunger
						end
					end
					
					return multiplier*(edible.nightly_hungervalue)
				end
				return edible:GetHunger_nightly_redirect(eater)
			end

			function edible:GetHealth(eater)
				if eater and eater.prefab == "nightly" then
					local multiplier = 1
					local healthvalue = edible.gethealthfn and edible.gethealthfn(edible.inst, eater) or edible.nightly_healthvalue

					local ignore_spoilage = (eater and eater.components.eater and eater.components.eater.ignoresspoilage) or healthvalue < 0
					
					if edible.inst.components.perishable and not ignore_spoilage then
						if edible.inst.components.perishable:IsStale() then
							multiplier = edible.stale_health
						elseif edible.inst.components.perishable:IsSpoiled() then
							multiplier = edible.spoiled_health
						end
					end
					return multiplier*(healthvalue)
				end
				return edible:GetHealth_nightly_redirect(eater)
			end
			
			newvaluefn(prefab)
		end
	end
end



-- Nightly is afraid of bees
AddPrefabPostInit("beehive", setNightlyAura(-TUNING.SANITYAURA_SMALL))
AddPrefabPostInit("wasphive", setNightlyAura(-TUNING.SANITYAURA_MED))
AddPrefabPostInit("beemine", setNightlyAura(-TUNING.SANITYAURA_MED))

AddPrefabPostInit("bee", setNightlyAura(-TUNING.SANITYAURA_MED))
AddPrefabPostInit("killerbee", setNightlyAura(-TUNING.SANITYAURA_LARGE))
AddPrefabPostInit("beebox", setNightlyAura(-TUNING.SANITYAURA_SMALL))
AddPrefabPostInit("honeycomb", setNightlyAura(-TUNING.SANITYAURA_TINY))

-- Eating honey products makes Nightly go insane
AddPrefabPostInit("honey", setNightlyConsume(
	function(inst)
	inst.components.edible.nightly_sanityvalue = -TUNING.SANITY_TINY
	end
))
AddPrefabPostInit("bandage", setNightlyConsume(
	function(inst)
	inst.components.edible.nightly_sanityvalue = -TUNING.SANITY_SMALL
	end
))
AddPrefabPostInit("honeyham", setNightlyConsume(
	function(inst)
	inst.components.edible.nightly_sanityvalue = -TUNING.SANITY_MED
	end
))
AddPrefabPostInit("honeynuggets", setNightlyConsume(
	function(inst)
	inst.components.edible.nightly_sanityvalue = -TUNING.SANITY_SMALL
	end
))


-- Nightly loves glowing things
AddPrefabPostInit("fireflies", setNightlyAura(TUNING.SANITYAURA_SMALL))
AddPrefabPostInit("lightning_rod", setNightlyAura(TUNING.SANITYAURA_SMALL))

AddPrefabPostInit("flower_cave", setNightlyAura(TUNING.SANITYAURA_TINY))
AddPrefabPostInit("flower_cave_double", setNightlyAura(TUNING.SANITYAURA_TINY))
AddPrefabPostInit("flower_cave_triple", setNightlyAura(TUNING.SANITYAURA_SMALL))

AddPrefabPostInit("stafflight", setNightlyAura(TUNING.SANITYAURA_LARGE))
AddPrefabPostInit("nightstick", setNightlyDapper(TUNING.DAPPERNESS_MED))


-- Containers
AddPrefabPostInit("treasurechest", setNightlyFinish(10))
AddPrefabPostInit("dragonflychest", setNightlyFinish(10))
AddPrefabPostInit("cookpot", setNightlyFinish(10))
AddPrefabPostInit("icebox", setNightlyFinish(10))
AddPrefabPostInit("pandoraschest", setNightlyFinish(15))
AddPrefabPostInit("minotaurchest", setNightlyFinish(15))

-- Minables
AddPrefabPostInit("rock1", setNightlyFinish(2))
AddPrefabPostInit("rock2", setNightlyFinish(2))
AddPrefabPostInit("rock_flintless", setNightlyFinish(2))
AddPrefabPostInit("rock_flintless_med", setNightlyFinish(2))
AddPrefabPostInit("rock_flintless_low", setNightlyFinish(2))
AddPrefabPostInit("rock_ice", setNightlyFinish(2))
AddPrefabPostInit("cave_entrance", setNightlyFinish(2))

AddPrefabPostInit("marblepillar", setNightlyFinish(5))
AddPrefabPostInit("marbletree", setNightlyFinish(5))

AddPrefabPostInit("statueharp", setNightlyFinish(10))
AddPrefabPostInit("statuemaxwell", setNightlyFinish(15))

AddPrefabPostInit("statueglommer", setNightlyFinish(10))

AddPrefabPostInit("stalagmite_full", setNightlyFinish(2))
AddPrefabPostInit("stalagmite_med", setNightlyFinish(2))
AddPrefabPostInit("stalagmite_low", setNightlyFinish(2))
AddPrefabPostInit("stalagmite", setNightlyFinish(2))
AddPrefabPostInit("stalagmite_tall_full", setNightlyFinish(2))
AddPrefabPostInit("stalagmite_tall_med", setNightlyFinish(2))
AddPrefabPostInit("stalagmite_tall_low", setNightlyFinish(2))
AddPrefabPostInit("stalagmite_tall", setNightlyFinish(2))
AddPrefabPostInit("spiderhole", setNightlyFinish(5))

AddPrefabPostInit("ruins_statue_head", setNightlyFinish(10))
AddPrefabPostInit("ruins_statue_head_nogem", setNightlyFinish(10))
AddPrefabPostInit("ruins_statue_mage", setNightlyFinish(10))
AddPrefabPostInit("ruins_statue_mage_nogem", setNightlyFinish(10))

-- Attacked
AddPrefabPostInit("bee", setNightlyHit(-3))
AddPrefabPostInit("killerbee", setNightlyHit(-4))

-- Foods
AddPrefabPostInit("fireflies", setNightlyConsume(
	function(inst)
	inst.components.edible.nightly_healthvalue = TUNING.HEALING_SMALL
    inst.components.edible.nightly_hungervalue = TUNING.CALORIES_TINY
	inst.components.edible.nightly_sanityvalue = TUNING.SANITY_LARGE
	inst.components.edible.foodtype = GLOBAL.FOODTYPE.FIREFLIES
	inst:AddTag("edible_"..GLOBAL.FOODTYPE.FIREFLIES)
	end
))

-- Add fireflies food type to eater
AddComponentPostInit("eater", function(Eater, inst)
	function Eater:SetCanEatFireflies()
		table.insert(Eater.foodprefs, GLOBAL.FOODTYPE.FIREFLIES)
		Eater.inst:AddTag(GLOBAL.FOODTYPE.FIREFLIES.."_eater")
	end
end)

--

AddMinimapAtlas("images/map_icons/nightly.xml")

AddModCharacter("nightly")
