--[[
BY
 _____   _____   __   _  
|  _  \ /  _  \ |  \ | | 
| | | | | | | | |   \| | 
| | | | | | | | | |\   | 
| |_| | | |_| | | | \  | 
|_____/ \_____/ |_|  \_| 

]]

local assets =
{
	Asset("ANIM", "anim/mob/maxwell_build_donmob.zip"),
    Asset("ANIM", "anim/mob/maxwell_basic_donmob.zip"),
	Asset("ANIM", "anim/mob/maxwell_adventure_donmob.zip"),
	Asset("ANIM", "anim/mob/maxwell_endgame_donmob.zip"),
	
	Asset("IMAGE", "images/minimap/donbossmaxwellsmap.tex"),
	Asset("ATLAS", "images/minimap/donbossmaxwellsmap.xml"),	
}


local maxbosswellmaxlife = 5500

local maxbosswellpets = 6
local num_lightnings = 5


local prefabs = 
{
}

SetSharedLootTable( 'donmob_maxwell_boss',
{
    {'donphonograph',   1.00},
    {'purplegem',       1.00},
    {'purplegem',       1.00},
    {'purplegem',       1.00},
    {'purplegem',       1.00},
    {'purplegem',       1.00},
    {'purplegem',       1.00},
    {'nightsword',       1.00},
    {'nightsword',       1.00},
    {'nightsword',       1.00},
    {'armor_sanity',       1.00},
    {'armor_sanity',       1.00},
    {'armor_sanity',       1.00},
    {'nightmarefuel',       1.00},
    {'nightmarefuel',       1.00},
    {'nightmarefuel',       1.00},
    {'nightmarefuel',       1.00},
    {'nightmarefuel',       1.00},
    {'nightmarefuel',       1.00},
    {'nightmarefuel',       1.00},
    {'nightmarefuel',       1.00},
    {'nightmarefuel',       1.00},
})

local bosswelltalks = {
STRINGS.DONRPG_LANG_BOSSMAXWELL_TALK1,
STRINGS.DONRPG_LANG_BOSSMAXWELL_TALK2,
STRINGS.DONRPG_LANG_BOSSMAXWELL_TALK3,
}

local function SuperPowerBossWell(inst)
	if not inst.components.health:IsDead() then
		ShakeAllCameras(CAMERASHAKE.FULL, .7, .02, .3, inst, 40)
		
		local pt = inst:GetPosition()
	
		inst:StartThread(function()
			for k = 0, num_lightnings do
				local rad = math.random(3, 15)
				local angle = k * 4 * PI / num_lightnings
				local pos = pt + Vector3(rad * math.cos(angle), 0, rad * math.sin(angle))
				TheWorld:PushEvent("ms_sendlightningstrike", pos)
				Sleep(.3 + math.random() * .2)
			end
		end)
	end			
end

local function BossWaveAttack(inst, starttime)
	
	if inst.setmaxwellbossdead == false then
		inst:DoTaskInTime(starttime, function() 
			inst.bosswelltalking = true

			if inst.setmaxwellbossdead == false then
			inst.components.health:SetInvincible(true)
			inst.AnimState:PlayAnimation("dialog5_pre") 
			inst.AnimState:PushAnimation("dialog5_loop", true)
			inst.SoundEmitter:PlaySound("dontstarve/maxwell/talk_LP", "talkbosswell")
			
			inst.components.talker:Say(bosswelltalks[math.random(3)])			
					
			inst:DoTaskInTime(4, function() 		
			inst.SoundEmitter:KillSound("talkbosswell")
			inst.AnimState:PlayAnimation("dialog5_pst")
			inst.AnimState:PushAnimation("idle5_loop", true)			
			inst.bosswelltalking = false
			inst.components.health:SetInvincible(false)

			SuperPowerBossWell(inst)
			
			BossWaveAttack(inst, 18) --loop wave		
			end)
			
			end
			
			inst:DoTaskInTime(22, function()
				inst.components.talker:Say("")
			end)

		end)
	end	
end

local function KillPets(inst)
	for pet, v in pairs(inst.pets) do
		SpawnPrefab("shadow_despawn").Transform:SetPosition(pet.Transform:GetWorldPosition())
		pet:Remove()		
	end
end

local function StartTrackingPet(inst, pet)
    inst.pets[pet] = true
    inst.numPets = inst.numPets + 1
	inst:ListenForEvent("onremove", inst._onstoptrackingpet, pet)
    inst:ListenForEvent("death", inst._onstoptrackingpet, pet)	
	SpawnPrefab("shadow_despawn").Transform:SetPosition(pet.Transform:GetWorldPosition())
end

local function SpawnPets(inst, attacker)
    if inst.numPets >= maxbosswellpets then
        return
    end

    local pt = inst:GetPosition()
    local pillarLoc = pt
    local minRadius = 3
    local ringdelta = 1.5
    local rings = 3
	
    local steps = math.floor((maxbosswellpets/2) / rings + 0.5)
  
    if attacker ~= nil and inst.spawnLocal then
        pt = attacker:GetPosition()
        minRadius = 1
        ringdelta = 1
        rings = 3
        steps = 4
        inst.spawnLocal = nil
    end
 
    local map = TheWorld.Map
    for r = 1, rings do
        local theta = GetRandomWithVariance(0, PI / 2)
        for i = 1, steps do
            local radius = GetRandomWithVariance(ringdelta, ringdelta / 3) + minRadius
            local x = pt.x + radius * math.cos(theta)
            local z = pt.z - radius * math.sin(theta)
            local pillars = TheSim:FindEntities(x, 0, z, 3.5, { "donmob_maxwell_boss" })
            if #pillars > 0 then
                pillarLoc = pillars[1]:GetPosition()
            end
            if map:IsAboveGroundAtPoint(x, 0, z) and
                distsq(x, z, pillarLoc.x, pillarLoc.z) > 8 and
                not map:IsPointNearHole(Vector3(x, 0, z)) then
                local pet = SpawnPrefab("donmod_maxwellboss_pet")
                StartTrackingPet(inst, pet)
                pet.Transform:SetPosition(x, 0, z)
				
				pet.components.combat:SuggestTarget(attacker)
				pet:PushEvent("attacked", { attacker = attacker, damage = 0, weapon = nil }) --damage
				
                if inst.numPets >= maxbosswellpets then
                    return
                end
            end
            theta = theta - 2 * PI / steps
        end
        minRadius = minRadius + ringdelta
    end
end

local function OnHit(inst, attacker, damage) 

	if not inst.components.health:IsDead() then
	
	if inst.bosswelltalking == false then
		inst.AnimState:PlayAnimation("dialog5_pre")
		inst.AnimState:PushAnimation("idle5_loop")
	end
	
	if attacker.components.combat ~= nil and not attacker:HasTag("player") and math.random() < .5 then
        attacker.components.combat:SetTarget(nil)
    end
	
	if attacker:HasTag("player") then
		attacker:ShakeCamera(CAMERASHAKE.SIDE, .5, .05, .2)
    end
	
	SpawnPets(inst, attacker)
	
	SpawnPrefab("shadow_despawn").Transform:SetPosition(inst.Transform:GetWorldPosition())
	
	end 
		
end

local function OnDeathEndMission(inst)
	inst.SoundEmitter:KillSound("talkbosswell")	
	inst.SoundEmitter:KillSound("talkbosswelldeath")	
	if inst.statuespawnerobjdon ~= nil then		
		inst.statuespawnerobjdon.bosswellisspawned = false
		inst.statuespawnerobjdon.bosswellisdead = true		
		inst.statuespawnerobjdon:AddComponent("inspectable")
		inst.statuespawnerobjdon:RemoveComponent("trader")
		inst.statuespawnerobjdon.AnimState:PlayAnimation("idle_full")	
		inst.statuespawnerobjdon.components.workable:SetWorkable(true)
	end
	inst.components.lootdropper:DropLoot()
	inst:Remove()	
end	

local function OnDeath(inst)
	inst.setmaxwellbossdead = true
	
	inst.DynamicShadow:SetSize(0, 0)

	KillPets(inst)
	
	SpawnPrefab("shadow_despawn").Transform:SetPosition(inst.Transform:GetWorldPosition())

	inst.AnimState:SetBank("maxwellthrone")
    inst.AnimState:SetBuild("maxwell_endgame")
    inst.AnimState:PlayAnimation("appear")
    inst.AnimState:PushAnimation("death", false)
	
	inst:RemoveComponent("inspectable")

	inst:DoTaskInTime(5, function()
		inst.SoundEmitter:PlaySound("rpgdongeralsounds/rpgdongeralsounds/maxwell_thronedeath", "talkbosswelldeath")		
		inst:DoTaskInTime(7.2, OnDeathEndMission)	
	end)
		
	
end

local function onsave(inst, data)
	data.reloadmaxwellbossspawned = inst.reloadmaxwellbossspawned
end

local function onload(inst, data)
	if data ~= nil and data.reloadmaxwellbossspawned then
		inst.reloadmaxwellbossspawned = data.reloadmaxwellbossspawned
	end
	
	if inst.reloadmaxwellbossspawned == true then
		KillPets(inst)
		inst:Remove()
	end
	
end

local function fn()
    local inst = CreateEntity()

    inst.entity:AddTransform()
    inst.entity:AddAnimState()
    inst.entity:AddSoundEmitter()
    inst.entity:AddMiniMapEntity()
	inst.entity:AddDynamicShadow()
    inst.entity:AddNetwork()

    MakeObstaclePhysics(inst, 2, 5)

	inst.Transform:SetTwoFaced()
	inst.DynamicShadow:SetSize( 2, .95 )
	inst.Transform:SetScale(2, 2, 2)

    inst.AnimState:SetBank("maxwell")
    inst.AnimState:SetBuild("maxwell_build")
    inst.AnimState:PlayAnimation("appear5")
    inst.AnimState:PushAnimation("idle5_loop", true)
	
	inst:AddTag("healthinfo")
	
	----
	inst:AddTag("epic")
    inst:AddTag("monster")
    inst:AddTag("hostile")
    inst:AddTag("scarytoprey")
    inst:AddTag("largecreature")
	----

    inst.entity:SetPristine()

	inst:AddComponent("lootdropper")
    inst.components.lootdropper:SetChanceLootTable('donmob_maxwell_boss')
	
	inst:AddComponent("talker")
    inst.components.talker.fontsize = 32
	inst.components.talker.font = TALKINGFONT
	inst.components.talker.offset = Vector3(80,-650,0)
	
    if not TheWorld.ismastersim then
        return inst
    end
	
	inst.setmaxwellbossdead = false
	inst.reloadmaxwellbossspawned = false
	inst.bosswelltalking = false
	
	inst.MiniMapEntity:SetIcon("donbossmaxwellsmap.tex")
	
    -------------------
    inst:AddComponent("health")
    inst.components.health:SetMaxHealth(maxbosswellmaxlife)
    inst.components.health.nofadeout = true
    inst:ListenForEvent("death", OnDeath)
    --------------------
    inst:AddComponent("combat")
    inst.components.combat:SetOnHit(OnHit)
    --------------------
    inst:AddComponent("inspectable")
    --------------------
    inst:AddComponent("teleporter")
    inst.components.teleporter:SetEnabled(false)


    inst.numPets = 0
    inst.pets = {}
    inst._onstoptrackingpet = function(pet)
        if inst.pets[pet] then
            inst.pets[pet] = nil
            inst.numPets = inst.numPets - 1
        end
    end
	
	inst.OnSave = onsave
    inst.OnLoad = onload
	
	KillPets(inst)

	BossWaveAttack(inst, 5)
	
    return inst
end

return Prefab("donmob_maxwell_boss", fn, assets, prefabs)
