local MakePlayerCharacter = require "prefabs/player_common"

--Note: Once you get boss limits working, make this one of them.

local assets = 
{
	Asset("ANIM", "anim/spider_queen_build.zip"),
	Asset("ANIM", "anim/spider_queen_shiny_build_01.zip"),
    Asset("ANIM", "anim/spider_queen.zip"),
    Asset("ANIM", "anim/spider_queen_2.zip"),
	--Asset("ANIM", "anim/ghost_waxwell_build.zip"),
	
}
local prefabs =
{
    "monstermeat",
    "silk",
    "spiderhat",
    "spidereggsack",
}
local start_inv = {
	"silk",
	"silk",
	"silk",
	"silk",
	"spidereggsack",
	"spidereggsack",
	"spidereggsack",
}

local function RestoreNightvision(inst)

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

SetSharedLootTable( 'spiderqueen',
{
	{'monstermeat',			 1.00},
	{'monstermeat',			 1.00},
	{'monstermeat',			 1.00},
	{'monstermeat',			 1.00},
	{'monstermeat',			 1.00},
	{'spiderhat',		 1.00},
})

local function CanShareTarget(dude)
    return dude:HasTag("spider")
        and not dude:IsInLimbo()
        and not (dude.components.health:IsDead() or dude:HasTag("player"))
end

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

local function UnEquipHat(inst) --If a hat removes important tags, this fixes that.
    local head = inst.components.inventory:GetEquippedItem(EQUIPSLOTS.HEAD) or nil
	if head then
	
	else
		inst:AddTag("monster") --should make spiders not attack you when spider hat is unequipped.
		print "Hat was removed"
	end 
end

local function OnAttacked(inst, data)
        inst.components.combat:SetTarget(data.attacker)
        inst.components.combat:ShareTarget(data.attacker, 30, CanShareTarget, 5)
 end

------------------------------------------------------
----PvP Teleport----

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
	end
end

local function OnSave(inst, data)
	data.mobteleported = inst.mobteleported or false
	data.isshiny = inst.isshiny or 0
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("spider_queen_shiny_build_0"..inst.isshiny)
			end		
		end
	end	
end

local function setChar(inst)
	if not inst:HasTag("playerghost") then
    inst.AnimState:SetBank("spider_queen")
    inst.AnimState:SetBuild("spider_queen_build")
    inst:SetStateGraph("SGqueenspiderplayer")
	end
	inst.components.hunger:Pause()
	inst.components.sanity.ignore = true
	inst.components.locomotor.runspeed = (3)
	inst.components.locomotor.fasteronroad = false
	if MOBPVPMODE == "Enable" then
		PvPTeleport(inst)
	end
end

local function BabyCount(inst)
    return inst.components.leader.numfollowers
end

--Update the code to not rely on targets to make warriors as you lose the target when you spawn babies.
local function MakeBaby(inst)
    local angle = inst.Transform:GetRotation()/DEGREES
    local prefab = (math.random() < .2) and "spider_warrior" or "spider"
    local spider = inst.components.lootdropper:SpawnLootPrefab(prefab)
	--local warrior = TheSim:FindEntities(pt.x, pt.y, pt.z, TUNING.SPIDERQUEEN_NEARBYPLAYERSDIST, {"spider_warrior"}, {"playerghost"})
    local rad = spider.Physics:GetRadius()+inst.Physics:GetRadius()+.25;
    local pt = Vector3(inst.Transform:GetWorldPosition())
	--if prefab == "spider_warrior" and warrior > 8 then
		--prefab = "spider"
	--end
    if spider then	
        spider.Transform:SetPosition(pt.x + rad*math.cos(angle), pt.y, pt.z + rad*math.sin(angle))
        spider.sg:GoToState("taunt")
		if inst.isshiny ~= 0 then
			if prefab == "spider" then
			spider.AnimState:SetBuild("spider_shiny_build_0"..inst.isshiny)
			else
			spider.AnimState:SetBuild("spider_warrior_shiny_build_0"..inst.isshiny)
			end
		end
        inst.components.leader:AddFollower(spider)
        if inst.components.combat.target then
            spider.components.combat:SetTarget(inst.components.combat.target)
        end
    end
end

local function MaxBabies(inst)
    local pt = Vector3(inst.Transform:GetWorldPosition())
    local ents = TheSim:FindEntities(pt.x, pt.y, pt.z, TUNING.SPIDERQUEEN_NEARBYPLAYERSDIST, {"player"}, {"playerghost"})
    local spiders = #ents * 20

    return 15
end

local function AdditionalBabies(inst)
    local pt = Vector3(inst.Transform:GetWorldPosition())
    local ents = TheSim:FindEntities(pt.x, pt.y, pt.z, TUNING.SPIDERQUEEN_NEARBYPLAYERSDIST, {"player"}, {"playerghost"})
    local addspiders = #ents * 0.5

    return RoundBiasedUp(addspiders)
end

--local function ShouldWakeUp(inst)
    --return DefaultWakeTest(inst) or (inst.components.follower and inst.components.follower.leader and not inst.components.follower:IsNearLeader(WAKE_TO_FOLLOW_DISTANCE))
--end

--local function ShouldSleep(inst)
    --return inst:HasTag("hound")
    --and not TheWorld.state.isday
	--and not TheWorld.state.isdusk
    --and not (inst.components.combat and inst.components.combat.target)
    --and not (inst.components.burnable and inst.components.burnable:IsBurning() )
    --and (not inst.components.homeseeker or inst:IsNear(inst.components.homeseeker.home, SLEEP_NEAR_HOME_DISTANCE))
--end

local function OnNewTarget(inst, data)
    if inst.components.sleeper:IsAsleep() then
        inst.components.sleeper:WakeUp()
    end
end

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

local function SetNightVision(inst, enable)
    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 DontTriggerCreep(inst)
    inst.components.locomotor.runspeed = (3)
	inst.components.locomotor:SetSlowMultiplier( 1 )
    inst.components.locomotor:SetTriggersCreep(false)
    inst.components.locomotor.pathcaps = { ignorecreep = true }
end

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


local common_postinit = function(inst) 
	inst.soundsname = "wilson"

	inst.MiniMapEntity:SetIcon( "queenspiderplayer.tex" )

	inst:DoTaskInTime(0, function()
   if ThePlayer then
      inst:EnableMovementPrediction(false)
   end
end)

	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)
end




local master_postinit = function(inst)
    inst.components.health:SetMaxHealth(2000)
	--inst:AddComponent("healthRegenerate")
    inst.components.combat:SetAttackPeriod(TUNING.SPIDERQUEEN_ATTACKPERIOD)
	inst.components.combat:SetRange(TUNING.SPIDERQUEEN_ATTACKRANGE)
	inst.components.combat.playerdamagepercent = MOBPVP
    inst.components.locomotor.runspeed = (3)
	inst.components.combat:SetDefaultDamage(40*2)
	--inst.components.combat:SetHurtSound("dontstarve/creatures/hound/hit")
	--inst.components.health.fire_damage_scale = TUNING.WILLOW_FIRE_DAMAGE
	inst.components.temperature.hurtrate = 0
    inst.components.temperature.inherentinsulation = -TUNING.INSULATION_SMALL
	inst.AnimState:SetBank("spider_queen")
	inst.AnimState:SetBuild("spider_queen_build")	
	inst.OnSetSkin = function(skin_name)
    inst.AnimState:SetBuild("spider_queen_build")
	inst:SetStateGraph("SGqueenspiderplayer")
	
	
	inst:ListenForEvent("ms_respawnedfromghost", DontTriggerCreep)
    DontTriggerCreep(inst)
	
	
	
	end
	inst:SetStateGraph("SGqueenspiderplayer")
	inst.components.locomotor:SetShouldRun(true)
	inst.components.talker:IgnoreAll()
	inst.components.hunger:Pause()
	inst.components.sanity.ignore = true
	
	inst:AddComponent("locomotor")
    inst.components.locomotor:SetSlowMultiplier( 1 )
    inst.components.locomotor:SetTriggersCreep(false)
    inst.components.locomotor.pathcaps = { ignorecreep = true }
	
	inst:AddComponent("incrementalproducer")
    inst.components.incrementalproducer.countfn = BabyCount
    inst.components.incrementalproducer.producefn = MakeBaby
    inst.components.incrementalproducer.maxcountfn = MaxBabies
    inst.components.incrementalproducer.incrementfn = AdditionalBabies
    inst.components.incrementalproducer.incrementdelay = TUNING.SPIDERQUEEN_GIVEBIRTHPERIOD
	
	inst.components.eater:SetDiet({ FOODTYPE.MEAT }, { FOODTYPE.MEAT })
    inst.components.eater:SetCanEatHorrible()
	
	inst.components.temperature.maxtemp = 60
	inst.components.temperature.mintemp = 20

    inst.components.eater.strongstomach = true -- can eat monster meat!
	
	--inst:AddTag("spider")
	inst:AddTag("spiderwhisperer")
	inst:AddTag("monster")
	inst:RemoveTag("character")
	inst:AddTag("epic")
    inst:AddTag("largecreature")
    inst:AddTag("spiderqueen")
	
	inst.hit_recovery = 3

	inst.mobplayer = true
	inst.mobsleep = true
	inst.taunt = true
	inst.isshiny = 0
	inst.specialatk2 = true
	inst.ghostbuild = "ghost_monster_build"
	inst.mobteleported = false
	
	inst.OnSave = OnSave
	inst.OnLoad = OnLoad	
	
	
	MakeCharacterPhysics(inst, 1000, 1)
    inst.DynamicShadow:SetSize(7, 3)
    inst.Transform:SetFourFaced()

	inst:AddComponent("leader")
	
	inst:ListenForEvent("attacked", OnAttacked)
    inst:ListenForEvent("equip", EquipHat)
	--inst:ListenForEvent("unequip", UnEquipHat)
	
    inst:AddComponent("lootdropper")
	inst.components.lootdropper:SetChanceLootTable("spiderqueen")
	--inst.components.lootdropper:AddRandomLoot("monstermeat", 1)
    --inst.components.lootdropper:AddRandomLoot("silk", .5)
    --inst.components.lootdropper:AddRandomLoot("spidergland", .5)
    --inst.components.lootdropper:AddRandomHauntedLoot("spidergland", 1)
    --inst.components.lootdropper.numrandomloot = 1

	inst:AddComponent("shedder")
	inst.components.shedder.shedItemPrefab = "spidereggsack"
	inst.components.shedder.shedHeight = 0.5
	inst.components.shedder:StartShedding(4800)
	
    --inst:AddComponent("periodicspawner")
    --inst.components.periodicspawner:SetPrefab("silk")
    --inst.components.periodicspawner:SetRandomTimes(5, 10)
    --inst.components.periodicspawner:SetDensityInRange(20, 2)
    --inst.components.periodicspawner:SetMinimumSpacing(8)
    --inst.components.periodicspawner:Start()
	
	MakeLargeBurnableCharacter(inst, "body")
    MakeLargeFreezableCharacter(inst, "body")
    --inst.components.burnable.flammability = TUNING.SPIDER_FLAMMABILITY
    
	
	------------------
    
    ------------------

	
  	local light = inst.entity:AddLight()
  	inst.Light:Enable(true)
  	inst.Light:SetRadius(0)
  	inst.Light:SetFalloff(0.9)
  	inst.Light:SetIntensity(0.6)
  	inst.Light:SetColour(180/255,195/255,150/255)


	
	inst.components.talker.colour = Vector3(127/255, 0/255, 0/255)
	inst:ListenForEvent("respawnfromghost", RestoreNightvision)

    inst:DoTaskInTime(0, setChar)
	inst:DoTaskInTime(3, setSkin)
    inst:ListenForEvent("respawnfromghost", function()
		inst:DoTaskInTime(3, function()  inst.components.health:SetInvincible(false)
            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)
		inst:DoTaskInTime(6, DontTriggerCreep)
		inst:DoTaskInTime(10, RestoreNightvision)
    end)
	
    return inst
	
end

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


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