// --------------------------------------
// Lua_Textbox
// Halberd text boxes
// --------------------------------------
freeslot("MT_AXEKNIGHT", "MT_MACEKNIGHT", "MT_TRIDENTKNIGHT", "MT_JAVELINKNIGHT", "MT_CAPTAINVUL", "MT_JAVELINDECOY", "MT_NPCNOTIF",
"S_NPCIDLE", "S_JDECIDLE", "S_NPCNOTIF",
"SPR_AXEK", "SPR_MCEK", "SPR_TRDK", "SPR_JVLK", "SPR_CVUL", "SPR_JDEC",

// Unrelated but these can go here...
"MT_HALBERDOBJ1", "MT_HALBERDOBJ2", "MT_HALBERDOBJ3", "MT_HALBERDOBJ4",
"S_HALBERDOBJ1", "S_HALBERDOBJ2", "S_HALBERDOBJ3", "S_HALBERDOBJ4",
"SPR_HLBO")

local metadialogue = {
	// Axe Knight 1
	[1] = {
		chara = 2,
		text = "Meta Knight, Boss, Sir! You're facing a tough mission, you should probably go through your moves again and train a bit!!",
		nextd = 100,
	},
	
	[100] = {
		chara = 2,
		text = "Just go forward and up and Mace will tell you how to get into the training course we made for you!",
		nextd = 0,
	},
	
	// Mace Knight 1
	[2] = {
		chara = 3,
		text = "Welcome Lord Meta Knight, the training course we organized is down that door, simply destroy it by making a downwards thrust.",
		nextd = 200,
	},
	
	[200] = {
		chara = 3,
		text = "In order to do so, just perform a jump, then press Custom Button #2.",
		nextd = 0,
	},
	
	// Trident Knight 1
	[3] = {
		chara = 4,
		text = "Welcome, My Lord. As the first part of your training, just defeat that robot we prepared for you there.",
		nextd = 300,
	},
	
	[300] = {
		chara = 4,
		text = "Slash its spirit and break his face with your powerful sword!!",
		nextd = 0,
	},
	
	// Axe Knight 2
	[4] = {
		chara = 2,
		text = "Those platforms may look tough to reach, but you can do it easily if you jump multiple times with your wings!",
		nextd = 0,
	},
	
	// Mace Knight 1
	[5] = {
		chara = 3,
		text = "In order to pass through this wall, simply crouch and attack to perform a slide thrust.",
		nextd = 500,
	},
	
	[500] = {
		chara = 3,
		text = "Do so by pressing the Custom Button #2, then the Jump command.",
		nextd = 0,
	},
	
	// Axe Knight 3
	[6] = {
		chara = 2,
		text = "Another trap door!! You already know the drill, Boss!!",
		nextd = 0,
	},
	
	// Trident Knight 2
	[7] = {
		chara = 4,
		text = "Blow this door to pieces with your Mighty Sword, Lord!",
		nextd = 0,
	},
	
	// Axe Knight 4
	[8] = {
		chara = 2,
		text = "And lastly, we prepared some robots to help you practice your special attacks!!",
		nextd = 800,
	},
	
	[800] = {
		chara = 2,
		text = "First is the Mach Tornado, to charge it, just hold your attack for a while, then let go to turn into a powerful electric tornado!",
		nextd = 801,
	},
	
	[801] = {
		chara = 2,
		text = "This helps you get some more height than with just your wings.",
		nextd = 802,
	},
	
	[802] = {
		chara = 2,
		text = "Or instead, you can jump after your energy is fully charged to store it, and throw a sword beam on your next attack.",
		nextd = 803,
	},
	
	[803] = {
		chara = 2,
		text = "Use this for distant combat!",
		nextd = 804,
	},
	
	[804] = {
		chara = 2,
		text = "Now try both on the robots!",
		nextd = 0,
	},
	
	// Captain Vul
	[9] = {
		chara = 1,
		text = "Lord Meta Knight, is your training fully complete?",
		nextd = 900,
	},
	
	[900] = {
		chara = 1,
		text = "No reason to waste more time then...",
		nextd = 901,
	},
	
	[901] = {
		chara = 0,
		text = "Spin:    Finish Tutorial\n\n\nJump:    Waste more time",
		nextd = 0,
	},
	
	// Camptein Vollbay :)
	[10] = {
		chara = 1,
		text = "Hellomst I am Captein Vollyball :)",
		nextd = 0,
	},
}

local function InsertNewLine(text, c)
	local half1 = string.sub(text, 1, c)
	local half2 = string.sub(text, c+1, textlen)
	return half1 + "\n" + half2
end

local function FormatText(text, maxperline)
	local c = 1
	local textlen = string.len(text)
	local thisline = 0
	while(c <= textlen)
		thisline = $1 + 1
		
		local curchar = string.sub(text, c, c)
		if(curchar == "\n")
			thisline = 0
		end
		
		if(thisline > maxperline)
			curchar = string.sub(text, c, c)
			if(curchar == " ")
				text = InsertNewLine(text, c)
				thisline = 0
			else
				// We need to backtrack!
				while(curchar != " " and c >= 0)
					c = $1 - 1
					curchar = string.sub(text, c, c)
				end
				
				if(c <= 0)
					// Bad text, cannot be formatted
					return text
				end
				
				text = InsertNewLine(text, c)
				thisline = 0
			end
		end
		
		c = $1 + 1
	end
	return text
end

local function SetPlayerDialogue(player, d)
	player.mkdialogue = d
	player.mkdialoguetime = 0
end

// DEBUG
COM_AddCommand("metatext", function(player, textnum)
	local num = tonumber(textnum)
	if(num and metadialogue[num])
		SetPlayerDialogue(player, num)
	else
		SetPlayerDialogue(player, 0)
	end
end)

// NPCS

// Animations
local npcanims = {
	// Axe Knight
	[MT_AXEKNIGHT] = {
		sprite = SPR_AXEK,
		idle = {
			A,
			A,
			A,
			B,
			B,
		},
		idlespeed = 6,
		talk = nil,
		talkspeed = 1,
	},
	
	// Mace Knight
	[MT_MACEKNIGHT] = {
		sprite = SPR_MCEK,
		idle = {
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			B,
			B,
			A,
			A,
			B,
		},
		idlespeed = 1,
		talk = nil,
		talkspeed = 1,
	},
	
	// Trident Knight
	[MT_TRIDENTKNIGHT] = {
		sprite = SPR_TRDK,
		idle = {
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			B,
			C,
			D,
			C,
			D,
			D,
			D,
			D,
			D,
			D,
			D,
			D,
			D,
			D,
			D,
			D,
			D,
			D,
			C,
			B,
			C,
			D,
			C,
			B,
		},
		idlespeed = 1,
		talk = nil,
		talkspeed = 1,
	},
	
	// Javelin Knight
	[MT_JAVELINKNIGHT] = {
		sprite = SPR_JVLK,
		idle = {
			A,
			E,
			B,
			F,
			C,
			G,
			D,
			H,
		},
		idlespeed = 1,
		talk = nil,
		talkspeed = 1,
	},
	
	// Captain Vul
	[MT_CAPTAINVUL] = {
		sprite = SPR_CVUL,
		idle = {
			A,
			A,
			A,
			A,
			A,
			A,
			A,
			B,
			C,
			B,
		},
		idlespeed = 4,
		talk = {
			D,
			E,
			D,
			A,
		},
		talkspeed = 3,
	},
}

local npccharas = {
	[MT_AXEKNIGHT] = 2,
	[MT_MACEKNIGHT] = 3,
	[MT_TRIDENTKNIGHT] = 4,
	[MT_JAVELINKNIGHT] = -1,
	[MT_CAPTAINVUL] = 1,
}

local function MetaNPCSpawn(mobj, thing)
	mobj.metadialogue = thing.extrainfo
	
	// Outside of the ship?
	if(mapheaderinfo[gamemap].halberd)
		if(mobj.x > -5297*FRACUNIT)
			or(mobj.y > 48*FRACUNIT)
			mobj.scale = $1 / 2
		end
	end
end

local notifheight = 40*FRACUNIT
local function MetaNPC(mobj)
	local istalking = false
	
	mobj.shadowscale = FRACUNIT
	
	// Death.
	if(mapheaderinfo[gamemap].halberd)
		for player in players.iterate
			if(mobj.metadialogue == 1)
				or(mobj.metadialogue == 2)
				if(player.mo.x < -5297*FRACUNIT)
					and(player.mo.y < 48*FRACUNIT)
					P_RemoveMobj(mobj)
					return
				end
			elseif(player.mo.x < -5297*FRACUNIT)
				and(player.mo.y < 48*FRACUNIT)
				mobj.flags2 = $1 & !MF2_DONTDRAW
			elseif not(mobj.spawndisable)
				mobj.spawndisable = true
				mobj.flags2 = $1|MF2_DONTDRAW
			end
		end
		
		if(mobj.flags2 & MF2_DONTDRAW)
			return
		end
	end
	
	// Player interaction
	if(mobj.metadialogue)
		for player in players.iterate
			if not(player.mo and player.mo.valid)
				continue
			end
			
			local dist = R_PointToDist2(mobj.x, mobj.y, player.mo.x, player.mo.y)
			dist = FixedHypot($1, mobj.z-player.mo.z)
			
			if(dist < 100*mobj.scale)
				and(dist >= 0)	// Overflow...
				and not(player.mkdialogue)
				if(P_IsObjectOnGround(player.mo))	// Don't talk to NPCs in the air!
					and(player.cmd.buttons & BT_SPIN)
					and not(player.metatextb and (player.metatextb & BT_SPIN))
					SetPlayerDialogue(player, mobj.metadialogue)
					mobj.angle = R_PointToAngle2(mobj.x, mobj.y, player.mo.x, player.mo.y)
					player.mo.momx = player.cmomx
					player.mo.momy = player.cmomy
					player.drawangle = R_PointToAngle2(player.mo.x, player.mo.y, mobj.x, mobj.y)
				else
					// Icon!
					local notif = P_SpawnMobj(mobj.x, mobj.y, (mobj.z+mobj.height/2)+FixedMul(notifheight*P_MobjFlip(mobj), mobj.scale), MT_NPCNOTIF)
					notif.scale = mobj.scale
					if(leveltime % 8 >= 4)
						notif.frame = $1 + 1
					end
				end
			end
			
			// Is this NPC talking to a player?
			local ourchara = npccharas[mobj.type]
			if(player.mkdialogue)
				and(metadialogue[player.mkdialogue].chara == ourchara)
				and(player.mkdialoguetime < string.len(metadialogue[player.mkdialogue].text))
				istalking = true
			end
		end
	end
	
	// Animation
	local anim = npcanims[mobj.type].idle
	local animspeed = npcanims[mobj.type].idlespeed
	
	if(istalking)
		and(npcanims[mobj.type].talk)
		anim = npcanims[mobj.type].talk
		animspeed = npcanims[mobj.type].talkspeed
	end
	
	// Init anim vars
	if(mobj.animframe == nil)
		mobj.animframe = 1
	end
	if(mobj.animtime == nil)
		mobj.animtime = 0
	end
	
	// Switched anim?
	if(mobj.curanim)
		and not(mobj.curanim == anim)
		mobj.animframe = 1
		mobj.animtime = 0
	end
	
	// Progress animation
	mobj.animtime = $1 + 1
	if(mobj.animtime >= animspeed)
		mobj.animframe = $1 + 1
		mobj.animtime = 0
	end
	
	// Loop
	if(anim[mobj.animframe] == nil)
		mobj.animframe = 1
	end
	
	// Apply animation
	mobj.frame = ($1 & !FF_FRAMEMASK)|anim[mobj.animframe]
	mobj.sprite = npcanims[mobj.type].sprite
	mobj.curanim = anim
end

addHook("MobjThinker", MetaNPC, MT_AXEKNIGHT)
addHook("MobjThinker", MetaNPC, MT_MACEKNIGHT)
addHook("MobjThinker", MetaNPC, MT_TRIDENTKNIGHT)
addHook("MobjThinker", MetaNPC, MT_JAVELINKNIGHT)
addHook("MobjThinker", MetaNPC, MT_CAPTAINVUL)

addHook("MapThingSpawn", MetaNPCSpawn, MT_AXEKNIGHT)
addHook("MapThingSpawn", MetaNPCSpawn, MT_MACEKNIGHT)
addHook("MapThingSpawn", MetaNPCSpawn, MT_TRIDENTKNIGHT)
addHook("MapThingSpawn", MetaNPCSpawn, MT_JAVELINKNIGHT)
addHook("MapThingSpawn", MetaNPCSpawn, MT_CAPTAINVUL)

// Player textbox thinker
addHook("ThinkFrame", function()
	for player in players.iterate
		if(player.metatextb == nil)
			player.metatextb = player.cmd.buttons
		end
		
		if(player.mkdialogue)
			player.mkdialoguetime = $1 + 1
			local text = metadialogue[player.mkdialogue]
			
			// Lock player control
			player.powers[pw_nocontrol] = max($1, 1)
			player.pflags = $1|PF_JUMPDOWN
			
			// Advance text
			if(player.cmd.buttons & BT_JUMP)
				and not(player.metatextb & BT_JUMP)
				
				// Text done
				if(player.mkdialoguetime > string.len(text.text))
					SetPlayerDialogue(player, text.nextd)
					S_StartSound(nil, sfx_menu1, player)
				else
					// Auto finish text
					player.mkdialoguetime = string.len(text.text)+500 	// Just the length is a little off.. maybe because of how I format it?
					S_StartSound(nil, sfx_menu1, player)				// Too lazy to fix the actual issue, this works just as well...
				end
			elseif(player.mkdialogue == 901)
				// HARDCODED BULLSHIT GO
				if(player.cmd.buttons & BT_SPIN)
					and not(player.metatextb & BT_SPIN)
					G_SetCustomExitVars(nil, 1)
					G_ExitLevel()
					player.mkdialogue = 0
				end
			end
		end
		
		player.metatextb = player.cmd.buttons
	end
end)

// Textbox drawing
hud.add(function(v, player, cam)
	// Cache patches!
	if not(v.mkbox and v.mkbox.valid)
		v.mkbox = v.cachePatch("MKTXTBOX")
		v.mkchars = {}
		v.mkchars[0] = v.cachePatch("METATALK")
		v.mkchars[1] = v.cachePatch("CVULTALK")
		v.mkchars[2] = v.cachePatch("AXEKTALK")
		v.mkchars[3] = v.cachePatch("MACETALK")
		v.mkchars[4] = v.cachePatch("TRIDTALK")
	end
	
	if(player.mkdialogue)
		local text = metadialogue[player.mkdialogue]
		
		// Calculate how many characters to the edge of the screen!
		local maxlen = ((v.width()/v.dupx())-70)/8
		
		// Format the text (doesn't *need* to be done every frame, but I'm lazy right now...)
		local ftext = FormatText(text.text, maxlen)
		
		// DRAW STUFF!
		v.drawScaled(FRACUNIT*160, FRACUNIT*130, FRACUNIT/5, v.mkbox, V_SNAPTOBOTTOM)
		v.drawScaled(FRACUNIT*15, FRACUNIT*130, FRACUNIT/5, v.mkchars[text.chara], V_SNAPTOLEFT|V_SNAPTOBOTTOM)
		v.drawString(70, 133, string.sub(ftext, 1, player.mkdialoguetime), V_SNAPTOLEFT|V_SNAPTOBOTTOM|V_YELLOWMAP|V_ALLOWLOWERCASE)
	end
end, "game")
