
local S = core.get_translator("mobs_monster")

-- custom dungeon master types

local master_types = {

	{	nodes = {"nether:rack"},
		skins = {"mobs_dungeon_master_nether.png"},
	},
	{	nodes = {"nether:rack_deep"},
		skins = {"mobs_dungeon_master_netherdeep.png"},
	}
}

local function gen_drops(pos)
	local res = {}

	if pos.y < -20000 and minetest.get_modpath("nether") then
		table.insert(res, {name = "nether:nether_lump", chance = 1, min = 1, max = 1})
	elseif pos.y < -1024 and minetest.get_modpath("moreores") then
		table.insert(res, {name = "moreores:mithril_lump", chance = 1, min = 1, max = 1})
	elseif pos.y < -256 or pos.y > 1024 then
		table.insert(res, {name = "default:diamond", chance = 1, min = 1, max = 1})
	elseif pos.y < -128 then
		table.insert(res, {name = "default:gold_lump", chance = 1, min = 1, max = 1})
	else
		table.insert(res, {name = "default:tin_lump", chance = 1, min = 1, max = 1})
		table.insert(res, {name = "default:copper_lump", chance = 1, min = 4, max = 4})
		table.insert(res, {name = "default:iron_lump", chance = 1, min = 1, max = 1})
	end

	if minetest.get_modpath("magic_materials") then
		table.insert(res,
			{name = "magic_materials:egerum_crystal", chance = 1, min = 1, max = 4}
		)
		table.insert(res,
			{name = "magic_materials:februm_crystal", chance = 1, min = 1, max = 1}
		)
	end

	if minetest.get_modpath("yams_materials") then
		table.insert(res,
			{name = "yams_materials:fire_essence", chance = 1, min = 1, max = 1}
		)
	end

	return res
end

-- Dungeon Master by PilzAdam

mobs:register_mob("mobs_monster:dungeon_master", {
	type = "monster",
	passive = false,
	damage = 6,
	damage_max = 90,
	arrow_damage = 8,
	arrow_damage_max = 120,
	melee_knockback = 12.0,
	attack_type = "dogshoot",
	attack_animals = true,
	pathfinding = true,
	dogshoot_switch = 1,
	dogshoot_count_max = 12, -- shoot for 10 seconds
	dogshoot_count2_max = 3, -- dogfight for 3 seconds
	reach = 2,
	shoot_interval = 2.2,
	arrow = "mobs_monster:fireball",
	friendly_fire = true,  -- Required to take damage from reflected fireballs
	shoot_offset = 1.9,
	hp_min = 60,
	hp_max = 600,
	armor = 100,
	yams_resists = {
		yams_fire = {damage = 50, knockback = 50}
	},
	collisionbox = {-0.7, -1, -0.7, 0.7, 1.6, 0.7},
	visual = "mesh",
	mesh = "mobs_dungeon_master.b3d",
	textures = {
		{"mobs_dungeon_master.png"},
		{"mobs_dungeon_master2.png"},
		{"mobs_dungeon_master3.png"}
	},
	makes_footstep_sound = true,
	sounds = {
		random = "mobs_dungeonmaster",
		war_cry = "mobs_dungeonmaster",
		shoot_attack = "mobs_fireball"
	},
	walk_velocity = 1,
	run_velocity = 3,
	run_velocity_max = 5,
	jump = true,
	jump_height = 6.0,
	view_range = 15,
	drops = gen_drops,
	water_damage = 0,
	lava_damage = 8,
	light_damage = 0,
	fear_height = 3,
	animation = {
		stand_start = 0, stand_end = 19,
		walk_start = 20, walk_end = 35,
		punch_start = 36, punch_end = 48,
		shoot_start = 36, shoot_end = 48,
		speed_normal = 15, speed_run = 15
	},
	base_exp = 400,
	max_exp = 40000,

	-- check surrounding nodes and spawn a specific monster
	on_spawn = function(self)
		local pos = self.object:get_pos() ; pos.y = pos.y - 1
		local tmp

		for n = 1, #master_types do
			tmp = master_types[n]

			if core.find_node_near(pos, 1, tmp.nodes) then
				self.base_texture = tmp.skins
				self.object:set_properties({textures = tmp.skins})
				break
			end
		end

		-- Make it throw less fireballs if it is near the surface to make it
		-- easier for beginners to defeat
		if pos.y > -256 and pos.y < 1024 then
			self.shoot_interval = 3.3
		-- Otherwise, make it spam more fireballs after reaching -2048 or if
		-- in the cloudlands
		elseif pos.y < -2048 or pos.y >= 1024 then
			self.shoot_interval = 1.1
		end

		-- Dungeon masters that spawn in the nether are immune to fire and lava
		if pos.y < -20000 then
			self.lava_damage = 0
			self.fire_damage = 0
		end

		return true -- run only once, false/nil runs every activation
	end,

	do_punch = function(self, hitter, tflp, tool_capabilities, dir)
		-- Approach the player if hit by a projectile, including its own
		if self.dogshoot_switch == 1 and self.dogshoot_count > 3 and
				math.random(1, 2) == 1 then
			self.dogshoot_switch = 2
			self.dogshoot_count = 0
		end

		return true
	end,

	on_blast = function(self, damage)
		if self._block_fireball then
			-- Mob is taking splash damage from their own fireball and it was
			-- not hit back at them; prevents dungeon masters from killing
			-- themselves with their own splash damage
			self._block_fireball = false  -- Do this only once per own fireball
			return false, false, {}
		else
			-- Take the dungeon master's 50% fire resistance into account and
			-- how explosion damage is 50% fire and 50% neutral
			damage = math.ceil(damage * 0.75)

			-- Copied from Mobs Redo (yams branch)
			self.object:punch(self.object, 1.0, {
				full_punch_interval = 1.0, damage_groups = {fleshy = damage}}, nil)

			-- return no damage and no item drops, but let knockback be applied
			return false, true, {}
		end
	end
})

-- where to spawn

if not mobs.custom_spawn_monster then

	mobs:spawn({
		name = "mobs_monster:dungeon_master",
		nodes = {"default:stone", "default:desert_stone", "default:sandstone",
		"default:sand", "default:desert_sand", "default:silver_sand",
		"default:ice", "caverealms:stone_with_moss",
		"caverealms:stone_with_lichen", "caverealms:stone_with_algae",
		"caverealms:stone_with_salt", "caverealms:hot_cobble",
		"caverealms:thin_ice", "caverealms:glow_obsidian",
		"caverealms:glow_obsidian_2", "caverealms:coal_dust"},
		max_light = 4,
		interval = 15,
		chance = 320000,
		min_height = -19990,
		max_height = -4096
	})

end

-- spawn egg

mobs:register_egg("mobs_monster:dungeon_master", S("Dungeon Master"),
		"fire_basic_flame.png", 1, false)

-- old mobs mod compatibility

mobs:alias_mob("mobs:dungeon_master", "mobs_monster:dungeon_master")

-- Crappy hack that protects dungeon masters from the splash damage of their
-- own fireballs unless it was hit back at them
local function protect_owner(pos, owner)
	if owner == nil then  -- Was hit by the player
		return
	end

	local objs = minetest.get_objects_inside_radius(pos, 4)
	for _, obj in pairs(objs) do
		local obj_pos = obj:get_pos()  -- Test for validity
		if obj_pos and tostring(obj) == owner then
			local ent = obj:get_luaentity()
			-- Protect owner from the next explosion from their own fireball
			ent._block_fireball = true
		end
	end
end

-- fireball arrow

mobs:register_arrow("mobs_monster:fireball", {
	visual = "sprite",
	visual_size = {x = 1, y = 1},
	textures = {"mobs_fireball.png"},
	collisionbox = {-0.2, -0.2, -0.2, 0.2, 0.2, 0.2},
	velocity = 8,
	tail = 1,
	tail_texture = "mobs_fireball.png",
	tail_size = 10,
	glow = 5,
	expire = 0.1,
	damage = 8,

	on_activate = function(self, staticdata, dtime_s)
		-- make fireball indestructable
		self.object:set_armor_groups({immortal = 1, fleshy = 100})
	end,

	-- if player has a weapon it can deflect fireball
	on_punch = function(self, hitter, tflp, caps, dir)
		if hitter and hitter:is_player() and caps and dir then
			local is_weapon = caps.damage_groups and caps.damage_groups.fleshy
				and caps.damage_groups.fleshy > 1
			local fpi = caps.full_punch_interval or 1.4

			if is_weapon and tflp >= fpi then
				self.object:set_velocity({
					x = dir.x * self.velocity,
					y = dir.y * self.velocity,
					z = dir.z * self.velocity
				})

				-- Normally monsters are immune to their own projectiles
				self.owner_id = nil

				self._player_that_hit = hitter:get_player_name()
			end
		end
	end,

	hit_player = function(self, player)
		-- We use self.lastpos and not self.pos to ensure that the knockback
		-- is going in the correct direction
		protect_owner(self.lastpos, self.owner_id)
		mobs:boom(self, self.lastpos, 1, 2, nil, self.damage)
	end,

	hit_mob = function(self, mob)
		-- Allow the player that hit the fireball to gain exp
		if self._player_that_hit then
			local m = mob:get_luaentity()
			m.exp_players[self._player_that_hit] = true
		end

		protect_owner(self.lastpos, self.owner_id)
		mobs:boom(self, self.lastpos, 1, 2, nil, self.damage)
	end,

	-- node hit
	hit_node = function(self, pos, node)
		protect_owner(self.lastpos, self.owner_id)
		mobs:boom(self, pos, 1, 2, nil, self.damage)
	end
})

--core.override_item("default:obsidian", {on_blast = function() end})
