local MakePlayerCharacter = require "prefabs/player_common"

---------------------------
----------==Notes==--------
--
---------------------------

--Don't add assets unless absolutely needed.
local assets = 
{
	Asset("ANIM", "anim/lightning_goat_shiny_build_01.zip"),
	Asset("ANIM", "anim/lightning_goat_shocked_shiny_build_01.zip"),
}
--Might be completely pointless here. I don't know.
local prefabs = 
{	

}
	
--Note: Becareful when adding starting items.
--People are likely to spam changecharacter to get more of them.	
local start_inv = 
{
	--'prefab',
	--"spear",
}

local start_inv2 = {

}

if MOBHOUSE == "Enable1" or MOBHOUSE == "Enable3" then
	start_inv = start_inv2
end
-----------------------
local mob = 
{
	health = TUNING.LIGHTNING_GOAT_HEALTH,
	hunger = 150,
	hungerrate = 0.15, --I think .25 is defualt.
	sanity = 100,
	runspeed = TUNING.LIGHTNING_GOAT_RUN_SPEED,
	walkspeed = TUNING.LIGHTNING_GOAT_WALK_SPEED,
	damage = 30*2,
	range = TUNING.LIGHTNING_GOAT_ATTACK_RANGE,
	bank = "lightning_goat",
	build = "lightning_goat_build",
	scale = 1,
	--build2 = "alternate build here",
	stategraph = "SGgoatp",
	minimap = "goatp.tex",
	
}
-----------------------
--Loot that drops when you die, duh.
SetSharedLootTable('goatp',
-----Prefab---------------------Chance------------
{
    {'meat',			1.00},
	{'meat',			1.00},
	{'lightninggoathorn',			0.25},
    
   
})

SetSharedLootTable( 'goat2p',
{
    {'meat',              1.00},
    {'meat',              1.00},
    {'goatmilk',          1.00},  
    {'lightninggoathorn', 0.25},
})

local function PvPAbillity(inst)
--
end

local function discharge(inst)
    inst:RemoveTag("charged")
    inst.components.lootdropper:SetChanceLootTable('goatp') 
    inst.sg:GoToState("discharge")
    inst.AnimState:ClearBloomEffectHandle()
    inst.charged = false
    inst.Light:Enable(false)
    inst.chargeleft = nil
	inst.components.combat:SetDefaultDamage(mob.damage)
	inst.components.locomotor.runspeed = (mob.runspeed)
	inst.components.locomotor.walkspeed = (mob.walkspeed)
	
end

local function ReduceCharges(inst)
    if inst.chargeleft then
        inst.chargeleft = inst.chargeleft - 1
        if inst.chargeleft <= 0 then
            discharge(inst)
        end
    end
end

local function setcharged(inst, instant)
    inst:AddTag("charged")
    inst.components.lootdropper:SetChanceLootTable('goat2p')
	if inst.isshiny ~= 0 then
	inst.AnimState:SetBuild("lightning_goat_shocked_shiny_build_0"..inst.isshiny)
	else
    inst.AnimState:SetBuild("lightning_goat_shocked_build")
	end
    inst.AnimState:Show("fx") 
    if not instant then
        inst.sg:GoToState("shocked")
    end
    inst.AnimState:SetBloomEffectHandle("shaders/anim.ksh")
    inst.charged = true
    inst.chargeleft = 3
    inst.Light:Enable(true)
	
	inst.components.combat:SetDefaultDamage(mob.damage*1.5)
	inst.components.locomotor.runspeed = (mob.runspeed + 2)
	inst.components.locomotor.walkspeed = (mob.walkspeed + 2)
	
    inst:WatchWorldState("cycles", ReduceCharges)
end

local function OnAttacked(inst, data)
    inst.components.combat:SetTarget(data.attacker)

    if inst.charged then
        if data.attacker.components.health then
            if (data.weapon == nil or (not data.weapon:HasTag("projectile") and data.weapon.projectile == nil))
                and not (data.attacker.components.inventory and data.attacker.components.inventory:IsInsulated()) then

                data.attacker.components.health:DoDelta(-TUNING.LIGHTNING_GOAT_DAMAGE)
                if data.attacker:HasTag("player") then
                    data.attacker.sg:GoToState("electrocute")
                end
            end
        end
    end

    if not inst.charged and data and data.weapon and data.weapon.components.weapon and data.weapon.components.weapon.stimuli == "electric" then
        setcharged(inst)
    end

    local attacker = data and data.attacker
    inst.components.combat:SetTarget(attacker)
    inst.components.combat:ShareTarget(attacker, 20, function(dude) return dude:HasTag("lightninggoat") and dude:HasTag("charged") end, 3)
end

local function EquipHat(inst) --If a hat removes the head, this fixes that.
    local head = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HEAD)
	if head then
		inst.AnimState:Show("HEAD")
	end 
end

local function onhitother2(inst, other)
    inst.components.combat:SetTarget(other)
    inst.components.combat:ShareTarget(other, 30, function(dude) return dude:HasTag("lightninggoat") and not dude.components.health:IsDead() end, 10)
end

local function OnHitOther(inst)
    local hands = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS) or nil
	if hands ~= nil and hands.components.finiteuses then
		hands.components.finiteuses:SetPercent(1)
	end 
end

local function Equip(inst)
    local hands = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS) or nil
	local head = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HEAD) or nil
	local body = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.BODY) or nil
	if hands ~= nil and hands.components.weapon then
		hands.components.weapon:SetDamage(45*2)
        hands.components.weapon:SetRange(TUNING.BISHOP_ATTACK_DIST+2, TUNING.BISHOP_ATTACK_DIST+6)
        hands.components.weapon:SetProjectile("spider_web_spit")
	end
end

local NIGHTVISION_COLOURCUBES =
{
    day = "images/colour_cubes/ruins_light_cc.tex",
    dusk = "images/colour_cubes/ruins_dim_cc.tex",
    night = "images/colour_cubes/purple_moon_cc.tex",
    full_moon = "images/colour_cubes/purple_moon_cc.tex",
}

local function SetNightVision(inst, enable) --This should be obvious
    if TheWorld.state.isnight or TheWorld:HasTag("cave") then
        inst.components.playervision:ForceNightVision(true)
        inst.components.playervision:SetCustomCCTable(NIGHTVISION_COLOURCUBES)
    else
        inst.components.playervision:ForceNightVision(false)
        inst.components.playervision:SetCustomCCTable(nil)
    end
end

local function getwildposition(inst)
    local ground = TheWorld
    local centers = {}
    for i, node in ipairs(ground.topology.nodes) do
        if ground.Map:IsPassableAtPoint(node.x, 0, node.y) then
            table.insert(centers, {x = node.x, z = node.y})
        end
    end
    if #centers > 0 then
        local pos = centers[math.random(#centers)]
        return Point(pos.x, 0, pos.z)
    else
        return inst:GetPosition()
    end
end

local function PvPTeleport(inst)
if inst.mobteleported == nil or inst.mobteleported == false then
	local ground = TheWorld
	local pt = getwildposition(inst)--Point(inst.Transform:GetWorldPosition())
      if pt.y <= .1 then
         pt.y = 0
         inst.Physics:Stop()
         inst.Physics:Teleport(pt.x,pt.y,pt.z)
		 inst.mobteleported = true
      end
	end
end

------------------------------------------------------
 local function OnLoad(inst, data)
	if data ~= nil then
		inst.mobteleported = data.mobteleported or false
		inst.isshiny = data.isshiny or 0
		if data and data.charged and data.chargeleft then
        setcharged(inst, true)
        inst.chargeleft = data.chargeleft
		end
	end
end

local function OnSave(inst, data)
	data.mobteleported = inst.mobteleported or false
	data.isshiny = inst.isshiny or 0
	if inst.charged then
        data.charged = inst.charged
        data.chargeleft = inst.chargeleft
    end
end

local function setSkin(inst)
	if not inst:HasTag("playerghost") then
		local mobskin = inst.components.skinner.skin_name
		local getshiny = (mobskin ~= inst.prefab and mobskin ~= "") and string.gsub(mobskin, inst.prefab.."_", "" ) --will return false if no skin is equipped.
		if SKIN_RARITY_COLORS.ModMade ~= nil then
			if getshiny ~= false then
				inst.isshiny = getshiny --used for other purposes
				inst.AnimState:SetBuild("lightning_goat_shiny_build_0"..inst.isshiny)
			end		
		end
	end	
end
------------------------------------------------------

local function RestoreNightImmunity(inst) --Resets immunity to Grue

	inst:DoTaskInTime(3, function(inst) 
	inst.Light:Enable(true)
	inst.Light:SetRadius(0)
	inst.Light:SetFalloff(.1)
	inst.Light:SetIntensity(.1)
	inst.Light:SetColour(245/255,40/255,0/255)
	end, inst)
end

local function setChar(inst) --sets character when the player loads.
	if not inst:HasTag("playerghost") then
    inst.AnimState:SetBank(mob.bank)
    inst.AnimState:SetBuild(mob.build)
	if inst.charged then
	inst.AnimState:SetBuild("lightning_goat_shocked_build")
	end
    inst:SetStateGraph(mob.stategraph)
	end
	if MONSTERHUNGER == "Disable" then
		inst.components.hunger:Pause()
	end
	if MOBPVPMODE == "Enable" then
		PvPTeleport(inst)
	end
	inst.components.sanity.ignore = true
    inst.components.locomotor.runspeed = (mob.runspeed)
	inst.components.locomotor.walkspeed = (mob.walkspeed)
	inst.components.locomotor.fasteronroad = false
end

local function RemovePenalty(inst)
	inst.components.health:DeltaPenalty(-1.00) --Removes health penalty when reviving
	inst.components.health:DoDelta(20000, false) --Returns health to max health upon reviving
end

local function SetSandstormImmunity(inst)
	if TheWorld.state.issummer and not TheWorld:HasTag("cave") then
        inst.components.playervision:ForceGoggleVision(true)
    else
        inst.components.playervision:ForceGoggleVision(false)
    end
end

local common_postinit = function(inst) 
	--inst.soundsname = "beefalo"

	inst.MiniMapEntity:SetIcon(mob.minimap)
	--inst.AnimState:SetMultColour(1, 1, 1, 0.5)

	inst:DoTaskInTime(0, function() 
   if ThePlayer then
      inst:EnableMovementPrediction(false)
   end
end)
	--Night Vision that toggles, might be a better way to do this.
	--Enables at night, disables during the day.
	inst:WatchWorldState( "isday", function() SetNightVision(inst) end)
  	inst:WatchWorldState( "isdusk", function() SetNightVision(inst) end)
  	inst:WatchWorldState( "isnight", function() SetNightVision(inst)  end)
	inst:WatchWorldState( "iscaveday", function() SetNightVision(inst) end)
  	inst:WatchWorldState( "iscavedusk", function() SetNightVision(inst) end)
  	inst:WatchWorldState( "iscavenight", function() SetNightVision(inst)  end)
	
	SetNightVision(inst) --This is here to make sure the NightVision is enabled when a player rejoins.
	
	inst:WatchWorldState( "issummer", function() SetSandstormImmunity(inst) end) --makes immune to Sandstorm visual issues.
	
	SetSandstormImmunity(inst)
	
end

local function DontTriggerCreep(inst)
    inst.components.locomotor.runspeed = (mob.runspeed)
	inst.components.locomotor.walkspeed = (mob.walkspeed)
end


local master_postinit = function(inst)
	------------------------------------------
	--Stats--
    inst.components.health:SetMaxHealth(mob.health)
	inst.components.hunger:SetMax(mob.hunger)
	inst.components.sanity:SetMax(mob.sanity)
	inst.components.hunger:SetRate(mob.hungerrate)
	------------------------------------------
	--Combat--
	--inst:AddComponent("healthSRegenerate")
	inst.components.combat.playerdamagepercent = MOBPVP
	--inst.components.combat.pvp_damagemod = 1 --disables second pvp override.
	--inst.components.combat:SetAttackPeriod(TUNING.WORM_ATTACK_PERIOD)
	inst.components.combat:SetRange(mob.range)
	inst.components.combat:SetDefaultDamage(mob.damage) --does double damage against mobs.
	inst.components.combat:SetHurtSound("dontstarve_DLC001/creatures/lightninggoat/hurt")	
    inst.components.temperature.inherentinsulation = -TUNING.INSULATION_SMALL
	inst.AnimState:SetBank(mob.bank)
	inst.AnimState:SetBuild(mob.build)
	
	inst.OnSetSkin = function(skin_name)
		inst.AnimState:SetBuild(mob.build)
		inst:SetStateGraph(mob.stategraph)
	
		inst:ListenForEvent("ms_respawnedfromghost", DontTriggerCreep)
		DontTriggerCreep(inst)	
	end
	inst:SetStateGraph(mob.stategraph)
	inst.components.talker:IgnoreAll()
	if MONSTERHUNGER == "Disable" then
		inst.components.hunger:Pause()
	end
	inst.components.sanity.ignore = true
	----------------------------------
	--Locomotor--
    inst.components.locomotor.runspeed = (mob.runspeed)
	inst.components.locomotor.walkspeed = (mob.walkspeed)
	inst.components.locomotor.fasteronroad = false
	--inst.components.locomotor:SetSlowMultiplier( 1 )
    --inst.components.locomotor:SetTriggersCreep(false)
    --inst.components.locomotor.pathcaps = { ignorecreep = true }
	MakeMediumBurnableCharacter(inst, "lightning_goat_body")
	----------------------------------
	--Loot drops--
	inst:AddComponent("lootdropper")
    inst.components.lootdropper:SetChanceLootTable('goatp')
	----------------------------------
	--Temperature and Weather Components--
	inst.components.temperature.maxtemp = 60 --prevents overheating
	--inst.components.temperature.mintemp = 20 --prevents freezing
	inst.components.moisture:SetInherentWaterproofness(1) --Prevents getting wet.
	----------------------------------
	--Tags--
	inst:RemoveTag("character") --This is removed to make certain mobs to not treat you like a player.
	inst:AddTag("mobplayer") --lets mod know that you're a mob.
	inst:AddTag("lightninggoat")
    inst:AddTag("animal")
    inst:AddTag("lightningrod")
	
	inst.components.combat.onhitotherfn = onhitother2
	
	inst.AnimState:Hide("fx")
	
	inst.mobsleep = true
	inst.taunt = true
	inst.ghostbuild = "ghost_monster_build"
	inst.mobteleported = false
	inst.specialatk2 = true
	inst.isshiny = 0
	
	inst:ListenForEvent("lightningstrike", setcharged)
    inst.setcharged = setcharged
	----------------------------------
	--SanityAura--
	--inst:AddComponent("sanityaura")
	
	----------------------------------
	--Eater--
	
	--Kinds of diets I know of: MEAT, ROUGHAGE(grass and stuff), GEARS, OMNI(no idea it prevents eating entirely, just disable this if you want both meat and veggies).
	inst.components.eater:SetDiet({ FOODTYPE.VEGGIE, FOODTYPE.ROUGHAGE }, { FOODTYPE.VEGGIE, FOODTYPE.ROUGHAGE })
    inst.components.eater:SetAbsorptionModifiers(4,1,1)
	inst.components.eater:SetCanEatHorrible() --check to make them eat monster meat.
	inst.components.eater.strongstomach = true -- can eat monster meat!
	--inst.components.eater.eatwholestack = true --should eat the entire stack and get all the benefits.
	--inst.components.eater.ignoresspoilage = true -- Can eat spoiled food without consequence. Might keep food stats as if fresh.
    --inst.components.eater:SetCanEatGears() --self explanatory.
    --inst.components.eater:SetOnEatFn(OnEat) --Runs a function when the player eats something.
	---------------------------------
	--Physics and Scale--
	
	MakeCharacterPhysics(inst, 10, .5)
	--MakeGhostPhysics(inst, 1, .5) --Special physics for flying characters(?)
    inst.Transform:SetScale(mob.scale, mob.scale, mob.scale)
    inst.DynamicShadow:SetSize(1.5, .5)
	--inst.DynamicShadow:Enable(false) --Disables shadows.
    inst.Transform:SetFourFaced()
	---------------------------------
	--Shedder--
	
	inst:AddComponent("shedder")
	inst.components.shedder.shedItemPrefab = "goatmilk"
	inst.components.shedder.shedHeight = 0.1
	inst.components.shedder:StartShedding(1200) --Note: 480 is 1 day. 480 x n = n amount of days.
	---------------------------------
	--Periodic Spawner--
	
	--inst:AddComponent("periodicspawner")
   -- inst.components.periodicspawner:SetPrefab("guano")
    --inst.components.periodicspawner:SetRandomTimes(120,240)
    --inst.components.periodicspawner:SetDensityInRange(30, 2)
    --inst.components.periodicspawner:SetMinimumSpacing(8)
    --inst.components.periodicspawner:Start()
	---------------------------------
	--Listeners--
	
	--inst:ListenForEvent("equip", EquipHat) --Shows head when hats make heads disappear.
	--inst:ListenForEvent("equip", Equip) --Enables spitting.
	inst:ListenForEvent("attacked", OnAttacked)
	inst:ListenForEvent("onhitother", OnHitOther)
	---------------------------------
	--Functions that saves and loads data.
	
	--inst.OnLongUpdate = onlongupdate
    inst.OnSave = OnSave
	inst.OnLoad = OnLoad
    --inst.OnPreLoad = onpreload
	------------------------------------------------------
    ------------------------------------------------------
	--Light and Character Functions. Don't Touch.--
    
	inst.components.grue:AddImmunity() --lights are used for charging, this should've been used anyways.
  	inst.Light:Enable(false)
    inst.Light:SetRadius(.85)
    inst.Light:SetFalloff(0.5)
    inst.Light:SetIntensity(.75)
    inst.Light:SetColour(255 / 255, 255 / 255, 236 / 255)
	
	inst.components.talker.colour = Vector3(127/255, 0/255, 0/255) --Text color when player Examines.
	inst:ListenForEvent("respawnfromghost", RestoreNightImmunity)

    inst:DoTaskInTime(0, setChar) --Sets Character.
	inst:DoTaskInTime(3, setSkin)
    inst:ListenForEvent("respawnfromghost", function() --Runs functions when character revives from Ghost.
		inst:DoTaskInTime(3, function()  inst.components.health:SetInvincible(false) --Prevents mobs from getting stuck when reviving.
            if inst.components.playercontroller ~= nil then
				inst.components.playercontroller:EnableMapControls(true)
				inst.components.playercontroller:Enable(true)
			end
			inst.components.inventory:Show()
			inst:ShowActions(true)
            inst:ShowHUD(true)
            inst:SetCameraDistance()
			inst.sg:RemoveStateTag("busy")
            SerializeUserSession(inst) 
		end)
        inst:DoTaskInTime(5, setChar)
		inst:DoTaskInTime(5.1, setSkin)
		inst:DoTaskInTime(6, RemovePenalty) --Removes death penalties and restore health if wanted.
		inst:DoTaskInTime(6, DontTriggerCreep)-- Restores speed on revive.
		inst:DoTaskInTime(10, RestoreNightImmunity) --explains itself.
    end)
	
    return inst
	
end


if SKIN_RARITY_COLORS.ModMade ~= nil then
AddModCharacterSkin("goatp", 1, {normal_skin = "deerclops_shiny_build_01", ghost_skin = "ghost_monster_build"}, {"deerclops_shiny_build_01", "ghost_monster_build"}, {"DEERPLAYER", "FORMAL"})
end

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