
-- WARNING Full of misleading names because I have changed my mind so many times between versions.

local wand_craft= function(crystal, wand)
minetest.register_craft({
	output = wand,
	recipe = {
		{ crystal },
		{ "group:stick" },
		{ "group:stick" },
	} });
end

local function wand_add_wear(wand, amount, pos)
	-- like add_wear_by_uses, but this time don't ignore sound.break, m'kay?
	local def=wand:get_definition()
        wand:add_wear_by_uses(amount)
	if def.sound and def.sound.breaks and wand:get_count() == 0 then
		core.sound_play(def.sound.breaks, { def.sound.breaks, pos=pos, gain=0.5}, true)
	end
end

mobs:register_arrow("wands:missile", {
	visual = "sprite",
	visual_size = {x = 1, y = 1},
	textures = {"magic_wand_lightning.png"},
	velocity = 8,
	tail_texture="magic_wand_lightning.png",
	tail_size=0.5,
	glow=7,
	expire=0.1,
	ttl=1,

	hit_player = function(self, player)
		-- if player==self.owner_id then return end
		player:punch(self.object, 1.0, {
			full_punch_interval = 0.1,
			damage_groups = {fleshy = 1}, -- don't damage armor.
		})
	end,

	hit_mob = function(self, player)
		player:punch(self.object, 1.0, {
			full_punch_interval = 0.1,
			damage_groups = {fleshy = 2},
		})
	end,

	hit_node = function(self, pos, node)
		self.object:remove()
	end,
})

minetest.register_tool("wands:mese", {
	description = "Mese Wand\n2 damage/short range/~500 uses.",
	inventory_image = "lightning_wand.png",
	groups={not_repaired_by_anvil=1},
	sound = {breaks = "default_break_glass"},
	on_use=function(itemstack, player)
		if player:get_attach() then return end
		local name=player:get_player_name()
		if mfplayers[name].energy<1 then return nil end
		mfplayers[name].energy=mfplayers[name].energy-1
		local p=player:get_pos()
		p.y=p.y+1.65
		local look_dir=player:get_look_dir()
		local obj=minetest.add_entity(vector.add(p, vector.multiply(look_dir,1)), "wands:missile")
		local ent=obj:get_luaentity()
		ent.owner_id=player
		ent.switch=1
		obj:set_velocity(vector.multiply(look_dir, 14))
		minetest.sound_play("tnt_ignite", {pos=p, gain=0.5, pitch=4, max_hear_distance=16}, true)
		local wear=512+((mf.perk(name)=="ranger" and 64) or 0)
		wand_add_wear(itemstack, wear, p)
		return itemstack
	end
})

wand_craft("default:mese_crystal", "wands:mese")

mobs:register_arrow("wands:missile_orange", {
	visual = "sprite",
	visual_size = {x = 2, y = 2},
	textures = {"magic_wand_lightning.png^[multiply:orange"},
	velocity = 8,
	tail_texture="magic_wand_lightning.png",
	tail_size=0.5,
	glow=7,
	ttl=5,
	-- unlike the standard mese missile, this one will hit hard players and damage armor.
	-- material is too valuable to use it for trolling.
	hit_player = function(self, player)
		-- if player==self.owner_id then return end
		player:punch(self.object, 1.0, {
			full_punch_interval = 0.1,
			damage_groups = {fleshy = 6},
		})
	end,

	hit_mob = function(self, player)
		player:punch(self.object, 1.0, {
			full_punch_interval = 0.1,
			damage_groups = {fleshy = 6},
		})
	end,

	hit_node = function(self, pos, node)
		self.object:remove()
	end,
})

minetest.register_tool("wands:invis", {
	description = "Greater Mese Wand\n6 damage/long range/~500 uses.",
	inventory_image = "nyan_wand.png",
	groups={not_repaired_by_anvil=1},
	sound = {breaks = "default_break_glass"},
	on_use=function(itemstack, player)
		if player:get_attach() then return end
		local name=player:get_player_name()
		if mfplayers[name].energy<2 then return nil end
		mfplayers[name].energy=mfplayers[name].energy-2
		local p=player:get_pos()
		p.y=p.y+1.65
		local look_dir=player:get_look_dir()
		local obj=minetest.add_entity(vector.add(p, vector.multiply(look_dir,1)), "wands:missile_orange")
		local ent=obj:get_luaentity()
		ent.owner_id=player
		ent.switch=1
		obj:set_velocity(vector.multiply(look_dir, 18))
		minetest.sound_play("tnt_ignite", {pos=p, gain=0.5, pitch=4, max_hear_distance=16}, true)
		wand_add_wear(itemstack, 512, p)
		return itemstack
	end
})


wand_craft("more_mese:mese_crystal_orange", "wands:invis")


mobs:register_arrow("wands:explosive_missile", {
	visual = "sprite",
	visual_size = {x = 1.5, y = 1.5},
	textures = {"horror_flame3.png"},
	glow=10,
	velocity = 8,
	tail = 1, -- enable tail
	tail_texture = "horror_flame2.png",

	hit_player = function(self, player)
		mobs:explosion(player:get_pos(), 4)
	end,

	hit_mob = function(self, player)
		mobs:explosion(player:get_pos(), 4)
	end,

	hit_node = function(self, pos, node)
		mobs:explosion(pos, 4)
	end,
})



mobs:register_arrow("wands:missile_confuse", {
	visual = "sprite",
	visual_size = {x = 0.2, y = 0.2},
	textures = {"horror_shadow.png"},
	velocity = 8,
	tail_texture="horror_shadow.png",
	tail_size=0.5,
	ttl=5,
	glow=7,

	hit_mob = function(self, ent)
		local mob=ent:get_luaentity()
		if mob and mob.type=="monster" then
			mob.type="npc"
			mob.regen=-0.1
			mob.state="stand"
			mob.attacks_monsters=true
		end
	end,
})

minetest.register_tool("wands:confusion", {
	description = "Confusion Wand\n Target attacks monsters. Long range, ~30 uses.",
	inventory_image = "bubble_wand.png",
	groups={not_repaired_by_anvil=1},
	sound = {breaks = "default_break_glass"},
	on_use=function(itemstack, player)
		if player:get_attach() then return end
		local name=player:get_player_name()
		if mfplayers[name].energy<2 then return nil end
		mfplayers[name].energy=mfplayers[name].energy-2
		local p=player:get_pos()
		p.y=p.y+1.65
		local look_dir=player:get_look_dir()
		local obj=minetest.add_entity(vector.add(p, vector.multiply(look_dir,1)), "wands:missile_confuse")
		local ent=obj:get_luaentity()
		ent.owner_id=player
		ent.switch=1
		obj:set_velocity(vector.multiply(look_dir, 18))
		minetest.sound_play("tnt_ignite", {pos=p, gain=0.5, pitch=4, max_hear_distance=16}, true)
		wand_add_wear(itemstack, 32, p)
		return itemstack
	end
})

minetest.register_tool("wands:blast", {
	description = "Blast wand.\n4m-radius explosion at point of impact.\nLong range, ~60 uses.",
	inventory_image = "fire_wand.png",
	groups={not_repaired_by_anvil=1},
	sound = {breaks = "default_break_glass"},
	on_use=function(itemstack, player)
		if player:get_attach() then return end
		local name=player:get_player_name()
		if mfplayers[name].energy<3 then return nil end
		mfplayers[name].energy=mfplayers[name].energy-3
		local p=player:get_pos()
		p.y=p.y+1.65
		local look_dir=player:get_look_dir()
		local obj=minetest.add_entity(vector.add(p, vector.multiply(look_dir,1)), "wands:explosive_missile")
		local ent=obj:get_luaentity()
		ent.owner_id=player
		ent.switch=1
		obj:set_velocity(vector.multiply(look_dir, 18))
		minetest.sound_play("mobs_spell", {object=obj, gain=0.25, max_hear_distance=16}, true)
		wand_add_wear(itemstack,64, p)
		return itemstack
	end
})

wand_craft("more_mese:mese_crystal_red", "wands:blast")

-- BUTTERFLY WAND

minetest.register_node("wands:lit_water", {
	description = "Magically lit water Source",
	drawtype = "airlike",
	use_texture_alpha="clip",
	paramtype = "light",
	walkable = false,
	pointable = false,
	diggable = false,
	buildable_to = true,
	is_ground_content = false,
	drop = "",
	liquidtype = "node",
	liquid_viscosity = 1,
	liquid_renewable=false,
	post_effect_color = {a = 103, r = 30, g = 60, b = 90},
	groups = {igniter=1, noblast=1},
	sounds = default.node_sound_water_defaults(),
	light_source=14,
	on_construct=function(pos)
		local timer=minetest.get_node_timer(pos)
		timer:start(60)
	end,

	on_timer=function(pos)
		-- could replace with water_source, but air is safer in case of a bug
		minetest.swap_node(pos, {name="air"})
	end,

})


local function _(pos)
	local target=minetest.find_node_near(pos, 1, "air", true)
	if target and not minetest.is_protected(target) then
		minetest.set_node(target, {name="wands:lit_water"})
		minetest.add_particlespawner
		{
			amount=600,
			time=60,
			pos=target,
			exptime=1,
			attract={kind="point", strenght=1},
			radius=0.25,
			glow=14,
			texture={name="default_mese_crystal.png", alpha_tween={1,0}, scale=0.5},
			jitter={min={x=-10, y=-10, z=-10}, max={x=10,y=10,z=10}},
		}
		return
	end
end

mobs:register_arrow("wands:butterfly_missile", {
	visual = "sprite",
	visual_size = {x = 1, y = 1},
	textures = {"magic_wand_noogberry_orange.png"},
	velocity = 8,
	tail=1,
	tail_texture="magic_wand_noogberry_orange.png",
	tail_size=2,
	glow=7,
	expire=0.05,

	hit_player = function(self, player)
		-- if player==self.owner_id then return end
		player:punch(self.object, 1.0, {
			full_punch_interval = 0.1,
			damage_groups = {fleshy = 1}, -- don't damage armor.
		})
	end,

	hit_mob = function(self, mob) _(mob:get_pos()) end,
	hit_node = function(self, pos) _(self.lastpos or pos) end, 
})

-- Teleportation WAND

local vero={x=0, y=0, z=0}

mobs:register_arrow("wands:teleport_missile", {
	visual = "sprite",
	visual_size = {x = 0.5, y = 0.5},
	textures = {"magic_wand_noogberry.png"},
	velocity = 8,
	tail=1,
	tail_texture="magic_wand_noogberry.png",
	tail_size=2,
	glow=7,
	expire=0.05,

	hit_player = function(self, player)
		if player==self.owner_id or not self.owner_id then return end
		local target=player:get_pos()
		local owner=self.owner_id:get_pos()
		if target and owner then
			self.owner_id:set_velocity(vero)
			self.owner_id:move_to(target, true)
			player:move_to(owner, true)
			minetest.sound_play("nether_portal_teleport", {pos=target, max_hear_distance=16, gain=0.5}, true)
		end
	end,

	hit_mob = function(self, player)
		if not self.owner_id then return end
		local target=player:get_pos()
		local owner=self.owner_id:get_pos()
		if target and owner then
			self.owner_id:set_velocity(vero)
			self.owner_id:move_to(target, true)
			owner.y=owner.y-player:get_properties().collisionbox[2]
			player:move_to(owner, true)
			player:set_velocity(vero)
			local mob=player:get_luaentity()
			mob.state="stand"
			mob.pause_timer=2 -- 2 secs stun
			minetest.sound_play("nether_portal_teleport", {pos=target, max_hear_distance=16, gain=0.5}, true)
		end
	end,

	hit_node = function(self, pos, node)
		--if node.name=="ignore" then return end
		local target=minetest.find_node_near(self.lastpos or pos, 1, { "air", "group:liquid" }, true)
		if target then
			local owner=self.owner_id
			if owner then
				owner:set_velocity(vero)
				owner:move_to(target, true)
				minetest.sound_play("nether_portal_teleport", {pos=target, max_hear_distance=16, gain=0.25}, true)
			end
		end

		self.object:remove()
	end,
})


minetest.register_tool("wands:teleport", {
	description = "Teleportation Wand\nTeleports you at point of impact or swaps places with mob or player.\nLong range.\n~130 uses.",
	inventory_image = "stone_wand.png",
	groups={not_repaired_by_anvil=1},
	sound = {breaks = "default_break_glass"},
	on_use=function(itemstack, player)
		if player:get_attach() then return end
		local name=player:get_player_name()
		if mfplayers[name].energy<1 then return nil end
		mfplayers[name].energy=mfplayers[name].energy-1
		local p=player:get_pos()
		p.y=p.y+1.65
		local look_dir=player:get_look_dir()
		local obj=minetest.add_entity(vector.add(p, vector.multiply(look_dir,1)), "wands:teleport_missile")
		local ent=obj:get_luaentity()
		ent.owner_id=player
		ent.switch=1
		obj:set_velocity(vector.multiply(look_dir, 18))
		minetest.sound_play("mobs_spell", {object=obj, gain=0.25, max_hear_distance=16}, true)
		wand_add_wear(itemstack, 128, p)
		return itemstack
	end
})

wand_craft("more_mese:mese_crystal_grey", "wands:teleport")

local freeze=function(self, impact)
	local r=8
	local t=1/r
	minetest.add_particlespawner{
		amount = 250,
		time = t,
		exptime={min=t, max=t},
		pos = impact,
		minvel = {x = -r, y = -r, z = -r},
		maxvel = {x = r, y = r, z = r},
		texture ={name="dot.png"} ,
		collisiondetection=true,
		collision_removal=true,
	}
	local p1={x=impact.x-1, y=impact.y-1, z=impact.z-1}
	local p2={x=impact.x+1, y=impact.y+1, z=impact.z+1}
	for _, p in ipairs(minetest.find_nodes_in_area(p1, p2,{"default:water_source", "default:water_flowing"})) do
		-- no need for protection checks, I think
		minetest.set_node(p, {name="default:ice"})
		-- will eventually melt in non-freezing biomes (see melt mod).
	end
	for ntt in core.objects_inside_radius(impact, 2) do
		ntt:punch(self.object, 1.0, {
			full_punch_interval=0.1,
			damage_groups={fleshy=4}
		})
	end

end


mobs:register_arrow("wands:ice_missile", {
	visual = "sprite",
	visual_size = {x = 1, y = 1},
	textures = {"default_snowball.png"},
	velocity = 10,
	glow=7,
	expire=0.05,

	hit_player = function(self, player)
		freeze(self, player:get_pos())
	end,

	hit_mob = function(self, player)
		freeze(self, player:get_pos())
	end,

	hit_node = function(self, pos, node)
		freeze(self, self.lastpos or pos)
	end,
})

minetest.register_tool("wands:water", {
	description = "Ice Wand.\nFreezes water (1m radius) and deals 4 dmg (2m radius).\nLong range.\n~130 uses.",
	inventory_image = "ice_wand.png",
	groups={not_repaired_by_anvil=1},
	sound = {breaks = "default_break_glass"},
	on_use=function(itemstack, player)
		if player:get_attach() then return end
		local name=player:get_player_name()
		if mfplayers[name].energy<1 then return nil end
		mfplayers[name].energy=mfplayers[name].energy-1
		local p=player:get_pos()
		p.y=p.y+1.65
		local look_dir=player:get_look_dir()
		local obj=minetest.add_entity(vector.add(p, vector.multiply(look_dir,1)), "wands:ice_missile")
		local ent=obj:get_luaentity()
		ent.owner_id=player
		ent.switch=1
		obj:set_velocity(vector.multiply(look_dir, 18))
		minetest.sound_play("mobs_spell", {object=obj, gain=0.25, max_hear_distance=16}, true)
		wand_add_wear(itemstack, 128, p)
		return itemstack
	end
})

wand_craft("more_mese:mese_crystal_cyan", "wands:water")


elements=minetest.get_mod_storage()
local ecache={}

wands={
	get_focus=function(name)
		if not ecache[name] then ecache[name]=elements:get_string(name) end
		return ecache[name] 
	end
}

minetest.register_chatcommand("focus", {
	description="Choose a Focus",
	params="<focus nane>",
	func=function(name, param)
		local player=minetest.get_player_by_name(name)
		if not player then return end
		local bmode=bones.get_mode_for(player)
		local element=wands.get_focus(name)
		if param=="" then
			if element ~= "" then
				minetest.chat_send_player(name, "Your current focus is: ".. element)
			else
				minetest.chat_send_player(name, "No focus selected. See Help tab for information.")
			end
			return true
		end
		local valid={air=true, light=true, shadow=true, wind=true}
		if not valid[param] then
			minetest.chat_send_player(name, "this is not a valid focus name")
			return true
		end
		if rp.get_player_count(name) > 20 then
			rp.award(name, -20, false)
		else
			minetest.chat_send_player(name, "Not enough RP.")
			return true
		end
		if param==element then
			minetest.chat_send_player(name, "This is already your Focus.")
			return true
		end
		elements:set_string(name, param)
		if bmode=="keep" and (element=="") then
			minetest.chat_send_all(minetest.colorize("green", name.." became a Regular player!"))
			bones.set_mode_for(player, "bones")
			minetest.sound_play("ding", {gain=1}, true)
		end
		minetest.chat_send_player(name, "Your focus is now: "..param)
		ecache[name]=param
		return true
	end
})

local dlg={
	"How rude?! What do you want!",
	"Good thing I wasn't in the shower...",
	"When one says \"call me anytime\", that's usually a figure of speech you know...",
	"I supposed you have a good reason to do that?",
	"Well, let's see what you have.",
	"May I help you?",
}

minetest.register_tool("wands:focus", {
	description = "Focus Wand\n~130 uses. Needs 1 mana.\nEffect depends on the Focus you select (see /focus). No focus: summons a trader (16 uses)",
	inventory_image = "plant_wand.png",
	sound = {breaks = "default_break_glass"},
	groups={not_repaired_by_anvil=1},
	tool_capabilities = {
		full_punch_interval = 0.01,
	},
	on_use=function(itemstack, player)
		if player:get_attach() then
			return itemstack
		end
		local name=player:get_player_name()
		local element=wands.get_focus(name)
		if mfplayers[name].energy<1 then
			return itemstack
		end
		mfplayers[name].energy=mfplayers[name].energy-1
		local p=player:get_pos()
		if element=="air" then
			glider.deploy(nil, player)
			wand_add_wear(itemstack, 128, p)
			return itemstack
		end
		if element=="wind" then
			minetest.sound_play("tnt_explode", {object=obj, gain=0.25, pitch=2, max_hear_distance=16}, true)
			player:add_velocity(player:get_look_dir()*20)
			wand_add_wear(itemstack, 128, p)
			return itemstack
		end
		if element=="light" then
			p.y=p.y+1.65
			local look_dir=player:get_look_dir()
			local obj=minetest.add_entity(vector.add(p, vector.multiply(look_dir,1)), "wands:butterfly_missile")
			local ent=obj:get_luaentity()
			ent.owner_id=player
			ent.switch=1
			obj:set_velocity(vector.multiply(look_dir, 14))
			minetest.sound_play("mobs_spell", {object=obj, gain=0.25, max_hear_distance=16}, true)
			wand_add_wear(itemstack, 128, p)
			return itemstack
		end
		if element=="shadow" then
			-- We have to add wear before and exit if the wand breaks because otherwise the player will punch the Shadow.
			wand_add_wear(itemstack, 128, p)
			if itemstack:get_count()==0 then return itemstack end
			local v=player:get_look_dir()
			v.y=0.5
			local obj=minetest.add_entity(vector.add(p, v), "mob_shadow:shadow")
			minetest.sound_play("mobs_spell", {object=obj, gain=0.25, max_hear_distance=16}, true)
			return itemstack
		end
		-- bug/beginner players: summon trader
		if itemstack:get_count()==0 then return itemstack end
		local v=player:get_look_dir()
		v.y=1
		local obj=minetest.add_entity(vector.add(p, v), "mf_npc:npc")
		minetest.sound_play("mobs_spell", {object=obj, gain=0.25, max_hear_distance=16}, true)
		minetest.chat_send_player(name, minetest.colorize("cyan", dlg[math.random(1, #dlg)]))
		wand_add_wear(itemstack, 16, p)
		return itemstack

	end
})

wand_craft("more_mese:mese_crystal_green", "wands:focus")

minetest.register_craftitem("wands:scroll_return", {
	description = "Scroll of Return. Sets your secondary waypoint (white) to your current position.",
	inventory_image = "scroll_01e.png",
	groups = {flammable = 3},
	on_use= function(itemstack, player)
		local name=player:get_player_name()
		compass.set_wp2(name, player:get_pos())
		itemstack:take_item()
		return itemstack
	end
})

minetest.register_craft {
	type="shapeless",
	output="wands:scroll_return",
	recipe={"default:paper", "compass:compass"}
}

