#Conditional Hooks
$Application: FS2_Open

$On Game Init:
[

VS2 = {}

function VS2:Init(ingame)

	ba.print("*****Initializing Visual Novel System...\n")
	self.Lexer = require ("lexer.lua")
	--self.Ease = require ("easing.lua")

	self.CanTalk = nil
	self.Enabled = false
	self.Debug = false
	self.Config = axemParse:ReadJSON("vs2.cfg")
	self.Config.ScaleFactor = self.Config.ScaleFactor or 1
	self.Config.IconScaleFactor = self.Config.IconScaleFactor or 0.75
	self.Characters = self.Config.Characters
	self.Config.DefaultRepeat = self.Config.DefaultRepeat or 1
	self.Variables = self.Variables or {}
	self.Images = {}
	self.Transitions = {}
	self.ShowCursor = true
	self.ShowBox = true
	self.IntKey = nil
	self.IntButton = nil
	self.IntGoto = nil
	self.IntOffset = nil
	
	self.CanAdvance = true
	self.Speaking = nil
	self.Sender = nil
	self.Menu = nil
	self.OkayTime = 0
	self.BG = nil
	self.LastClicked = ba.getFrametimeOverall()
	
	self.Ingame = true
	self.Message = self.Message or mn.addMessage("VS2Message", " ")
	self.BlankMsg = self.BlankMsg or mn.addMessage("VS2Blank", " ")
			
	AXUI:SetFocus(0)

end

function VS2:L (filename,start)

	self:LoadScene(filename .. ".txt", start)
	
end

function VS2:LoadScene(filename, start)

	if cf.fileExists(filename, "data/fiction", true) then
	
		VS2:Init()
		
		local config = self.Config
		local fontconfig = config.Font
	
		self.Scene = axemParse:Open(filename, "data/fiction")
		
		self.ParseVersion = 1
		
		self.Scene.NextLine = self.NextLine
		self.Scene.GoToLine = self.GoToLine
		self.Scene.SeekStarts = self.SeekStarts
		self.Scene.ProcessLine = self.ProcessLine
		self.Scene.EvalIf = self.EvalIf
		
		self.Enabled = true
		
		--I will never do this again...
		AXMessage.AlwaysDrawMsgBox = true
		AXMessage.RawString = nil
		AXMessage.DisplayString = nil
		AXMessage.Sender = nil
		AXMessage.DrawControl = "VS2"
		AXMessage.Monochrome = false
		AXMessage.Speed = config.TextDraw or 0.03
		AXMessage.Fonts.Title = gr.Fonts[fontconfig.Title.Font or 2]
		AXMessage.Fonts.Text = gr.Fonts[fontconfig.Text.Font or 3]
		AXMessage:LoadMsgBox(config.TextBox.File or "messagebox_big")
		AXMessage.Position.x = (gr.getScreenWidth() * (config.Position.X or 0.5) - (AXMessage.Image.w/2))
		AXMessage.Position.y = (gr.getScreenHeight() * (config.Position.Y or 0.7 ))
		
		if (AXMessage.Position.y + AXMessage.Image.h) > gr.getScreenHeight() then
			AXMessage.Position.y = gr.getScreenHeight() - AXMessage.Image.h - 5
		end
		
		AXMessage.Image.w = AXMessage.Image.w - config.TextBox.Offsets.Right
		AXMessage.Image.h = AXMessage.Image.h - config.TextBox.Offsets.Bottom
		AXMessage.Color.Title = {fontconfig.Title.Color[1] or 161, fontconfig.Title.Color[2] or 184, fontconfig.Title.Color[3] or 161, fontconfig.Title.Color[4] or 255}
		AXMessage.Color.Text = {fontconfig.Text.Color[1] or 161, fontconfig.Text.Color[2] or 184, fontconfig.Text.Color[3] or 161, fontconfig.Text.Color[4] or 255}
		AXMessage.Offsets.Sender.x = config.TextBox.Offsets.Left
		AXMessage.Offsets.Sender.y = config.TextBox.Offsets.Top
		AXMessage.Offsets.Text.x = config.TextBox.Offsets.Left + 10
		AXMessage.Offsets.Text.y = config.TextBox.Offsets.Top + 20
		
		AXUI.InGame = true
		AXUI:ScreenInit()
		
		mn.runSEXP("(hud-disable 1)")
		
		if string.lower(self.Config.Anchor) == "screen" then
			self.Anchor = AXUI.Screen.y + AXUI.Screen.h
		else
			self.Anchor = AXMessage.Position.y
		end
		
		self.Scene:SeekStarts()
				
		if start then
			if self.Scene.Starts[start] then
				ba.print("VN: Using start " .. start .. "at line " .. self.Scene.Starts[start] .. "\n")
				self.Scene.Line = self.Scene.Starts[start]
			else
				ba.print("VN: Problem finding 'LABEL " .. start .. "' in file!!\n")
			end
		else
			self.Scene.Line = 0
		end
		
		self.Scene:NextLine()
		
	else
		ba.error("VN: Error loading " .. filename .. ".txt")
	end

end

function VS2:ParseLine(s)
	
	local t = {}
	local index = 1
		
	for k, v in self.Lexer.scan(s) do
		t[index] = v
		index = index + 1
	end
		
	return t

end

function VS2:SeekStarts()

	self.Starts = {}

	for i,v in ipairs(self) do
	
		local line = VS2:ParseLine(v)
		local token, content = string.upper(line[1]), line[2]
		
		if token == "LABEL" then
			ba.print("VN: LABEL FOUND!! " .. content .. " at line " ..  i .. "\n")
			self.Starts[content] = i
		elseif token == "FILEVERSION" then
			VS2:SetVersion(content)
		end
	
	end

end

function VS2:NextLine()

	self.Line = self.Line + 1
	self:ProcessLine()

end

function VS2:SetVersion(version)

	self.ParseVersion = version or 1

end

function VS2:ProcessLine()

	local thisLine = self[self.Line]
	
	if thisLine then
		local t = VS2:ParseLine(thisLine)
		local command = string.upper(t[1])
		
		ba.print("VN: At line " .. self.Line .. ", Command is " .. command .. "\n")
		--[[for k, v in pairs(t) do
			ba.print("'" .. v .. "' ")
		end
			ba.print("\n")]]--

		if command == "GOTO" then
			self:GoToLine(self.Starts[t[2]])
		elseif command == "SETINT" then
			VS2:SetInterrupt(t)
			self:NextLine()
		elseif command == "INTRETURN" then
			VS2:ReturnFromInterrupt()
		elseif command == "FILEVERSION" then
			self:NextLine()
		elseif command == "LABEL" then
			self:NextLine()
		elseif command == "ACTION" then
			VS2:Action(t)
		elseif command == "PLAY" then
			VS2:Play(t)
			self:NextLine()
		elseif command == "STOPMUSIC" then
			VS2:StopMusic()
			self:NextLine()
		elseif command == "SHOW" then
			if VS2.ParseVersion == 2 then
				VS2:Show2(t)
			else
				VS2:Show(t)
			end
			self:NextLine()
		elseif command == "SHOWICON" then
			if VS2.ParseVersion == 2 then
				VS2:ShowIcon2(t)
			else
				VS2:ShowIcon(t)
			end
			self:NextLine()
		elseif command == "MOVE" then
			if VS2.ParseVersion == 2 then
				VS2:Move2(t)
			else
				VS2:Move(t)
			end
			self:NextLine()
		elseif command == "CHANGE" then
			if VS2.ParseVersion == 2 then
				VS2:Change2(t)
			else
				VS2:Change(t)
			end
			self:NextLine()
		elseif command == "HIDE" then
			VS2:Hide(t)
			self:NextLine()
		elseif command == "SETBG" then
			VS2:SetBG(t)
			self:NextLine()
		elseif command == "MENU" then
			VS2:CreateMenu(t)
		elseif command == "IF" or command == "EIF" or command == "ELSE" then
			self:EvalIf(t)
		elseif command == "ENDIF" or command == "END" then
			self:NextLine()
		elseif command == "WAIT" then
			VS2:Wait(t[2], true)
		elseif command == "SETVAR" then
			VS2:SetVar(t)
			self:NextLine()
		elseif command == "SETSEXPVAR" then
			VS2:SetVar(t, true)
			self:NextLine()
		elseif command == "SETFLAG" then
			VS2:SetFlag(t)
			self:NextLine()
		elseif command == "SETFONT" then
			VS2:SetFont(t)
			self:NextLine()
		else
			VS2:SendMsg(t)
		end
	else
		ba.print("VISUAL NOVEL: END OF FILE REACHED!\n************************\n")
	end

end

function VS2:GoToLine(line)

	self.Line = line
	self:ProcessLine()
	
end

function VS2:SetInterrupt(t)

	--t[1] = token
	--  2  = key or button name (prefixed with @)
	--  3  = label to hit
	--  4  = lines to move after returning from interrupt
	
	for i=1, t[2]:len() do
		ba.print(i .. ": " .. t[2]:sub(i) .. "\n")
	end
	
	if t[2] == "NULL" then
		self.IntKey = nil
		self.IntGoto = nil
		self.IntButton = nil
	elseif t[2] == "PAUSE" then
		self.IntDraw = false
	elseif t[2]:find("@") == 1 then
		local filename = string.sub(t[2],2)
		local x = AXUI.Screen.w/2 - gr.getImageWidth(filename)/2
		--local y = 100
		local y = AXMessage.Position.y - gr.getImageHeight(filename) - 10

		self.IntButton = AXUI:CreateButton(nil, x, y, nil, nil, nil, nil, nil, filename, 0, 0, filename .. "_h", filename .. "_c", false, 0, nil)
		self.IntGoto = self.Scene.Starts[t[3]]
		self.IntOffset = t[4] or 1
		self.IntDraw = true
		
		ba.print("VN: Interrupt Set: Button Filename: " .. filename .. " Line: " .. self.IntGoto .. "\n")
	else
		self.IntKey = t[2]
		self.IntGoto = self.Scene.Starts[t[3]]
		self.IntOffset = t[4] or 1
		
		ba.print("VN: Interrupt Set: Key: " .. self.IntKey .. " Line: " .. self.IntGoto .. "\n")
		
	end

end

function VS2:Interrupt()

	self.ReturnTo = self.Scene.Line + self.IntOffset
	self.Scene:GoToLine(self.IntGoto)
	
end

function VS2:ReturnFromInterrupt()

	if self.IntButton then
		self.IntDraw = true
	end
	self.Scene:GoToLine(self.ReturnTo)

end

function VS2:Action(t)

	--t[1] = token
	--  2  = action
	--  3+ = parameter
	
	local action = string.lower(t[2])

	axemParse:Validate("line " .. self.Scene.Line .. ": argument 1", t[3], "number", true)
	axemParse:Validate("line " .. self.Scene.Line .. ": argument 2", t[4], "number", true)
	axemParse:Validate("line " .. self.Scene.Line .. ": argument 3", t[5], "number", true)
	axemParse:Validate("line " .. self.Scene.Line .. ": argument 4", t[6], "number", true)
	
	if action == "fadein" then
		local r, g, b = t[4] or 0, t[5] or 0, t[6] or 0
		self.Fade = {}
		self.Fade.Color = {r,g,b}
		self.Fade.A1 = 255
		self.Fade.A2 = 0
		self.Fade.StartTime = ba.getFrametimeOverall()
		self.Fade.EndTime = ba.getFrametimeOverall() + (t[3] or 0)
		self.Fade.Duration = t[3]
		VS2:Wait(t[3], true)
		ba.print("VN: Fadein set!\n")
	elseif action == "fadeout" then
		local r, g, b = t[4] or 0, t[5] or 0, t[6] or 0
		self.Fade = {}
		self.Fade.Color = {r,g,b}
		self.Fade.A1 = 0
		self.Fade.A2 = 255
		self.Fade.StartTime = ba.getFrametimeOverall()
		self.Fade.EndTime = ba.getFrametimeOverall() + 9999
		self.Fade.Duration = t[3] or 0
		VS2:Wait(t[3], true)
		ba.print("VN: Fadeout set!\n")
	elseif action == "lockdown" then
		if Lockdown then
			Lockdown()
			if t[3] and string.lower(t[3])=="everything" then Freeze() end
			VS2:Wait(0,true)
		end
	elseif action == "unlockdown" then
		if UnLockdown then
			UnLockdown()
			UnFreeze()
			VS2:Wait(0,true)
		end
	elseif action == "endmission" then
		ba.print("VN: Ending mission!\n")
		mn.runSEXP("(end-mission)")
	elseif action == "endscene" then
		ba.print("VN: Ending Scene!\n")
		VS2:Exit(true)		--The true will keep variables alive
	elseif action == "hidecursor" then
		VS2.ShowCursor = false
		VS2:Wait(0,true)
	elseif action == "showcursor" then
		VS2.ShowCursor = true
		VS2:Wait(0,true)
	elseif action == "hidebox" then
		VS2.ShowBox = false
		VS2:Wait(0,true)
	elseif action == "showbox" then
		VS2.ShowBox = true
		VS2:Wait(0,true)
	else
		ba.print("VN: Invalid action given, ignoring...\n")
	end

end

function VS2:StopMusic()

	if VS2.MusicHandle then
		ad.stopMusic(VS2.MusicHandle, true)
		VS2.MusicHandle = nil
	end

end

function VS2:Play(t)

	if string.lower(t[2]) == "music" then
		if VS2.MusicHandle then ad.stopMusic(VS2.MusicHandle, true) end
		ba.print("VN: Attempting to play " .. t[2] .."\n")
		if t[4] and string.lower(t[4]) == "once" then
			VS2.MusicHandle = ad.playMusic(t[3],1,false)
		else
			VS2.MusicHandle = ad.playMusic(t[3])
		end
	elseif string.lower(t[2]) == "gamesound" then
		ad.playGameSound(t[3])
	elseif string.lower(t[2]) == "interfacesound" then
		ad.playInterfaceSound(t[3])
	else
		ba.warning("VN: Invalid play command given, should be music, gamesound, or interfacesound")
	end

end

function VS2:FindParam(name, t)

	local numargs = (#t-2)/3
	
	for i = 3, #t, 3 do
		if string.lower(t[i]) == string.lower(name) and t[i+1] == "=" then
			return t[i+2]
		end
	end
	
	return nil

end

function VS2:Show2(t)

	--for i,v in ipairs(t) do
	--	ba.print("t["..i.."]="..v.."\n")
	--end
	
	--ba.print("Number of passed arguments = " .. numargs .. "\n")

	local id = t[2]
	local filename = VS2:FindParam("file", t)
	local x_pct = VS2:FindParam("x", t)
	local x_flip = VS2:FindParam("xflip", t)
	local y_pct = VS2:FindParam("y", t)
	local y_flip = VS2:FindParam("yflip", t)
	local play = VS2:FindParam("repeat", t)
	local layer = VS2:FindParam("layer", t)
	local fadetime = VS2:FindParam("fadetime", t)
	
	if x_flip and string.lower(x_flip) == "true" then x_flip = true else x_flip = nil end
	if y_flip and string.lower(y_flip) == "true" then y_flip = true else y_flip = nil end
	
	local passedLine = {"SHOW",id,filename,x_pct,x_flip,y_pct,y_flip,play,layer,fadetime}
	
	VS2:Show(passedLine)
	
	
end

function VS2:Show(t)

	--t[1] = token
	--  2  = id
	--  3  = filename
	--  4  = x pos (defaults to 50)
	--  5  = flipped x
	--  6  = y pos (relative to message box top, defaults to 0)
	--  7  = flipped y
	--  8  = play method (alwaysloop, playonce)
	--  9  = layer (1-5)
	
	local thisImage = {}
	local id = t[2]
	local filename = t[3]
	local x_pct = t[4]
	local x_flip = t[5]
	local y_pct = t[6]
	local y_flip = t[7]
	local play = t[8]
	local layer = t[9] or 3
	local fadetime = t[10] or 0.5
	local create = true
	local scale = 1
	
	axemParse:Validate("line " .. self.Scene.Line .. ": argument 1", t[2], "string")
	axemParse:Validate("line " .. self.Scene.Line .. ": argument 3", t[4], "number", true)
	axemParse:Validate("line " .. self.Scene.Line .. ": argument 4", t[5], "string", true)
	axemParse:Validate("line " .. self.Scene.Line .. ": argument 5", t[6], "number", true)
	axemParse:Validate("line " .. self.Scene.Line .. ": argument 6", t[7], "string", true)
	
	if self.Images[id] then
		create = false
		thisImage = self.Images[id]
		thisImage.X_0 = self.Images[id].X
		thisImage.Y_0 = self.Images[id].Y
		thisImage.Alpha = 1
		thisImage.Bitmap:unload()
		if thisImage.BitmapH and thisImage.BitmapH:isValid() then
			thisImage.BitmapH:unload()
		end
		
		if thisImage.BitmapAlt and thisImage.BitmapAlt:isValid() then
			thisImage.BitmapAlt:unload()
		end
		
	else
		thisImage.Alpha = 0
	end
	
	thisImage.Bitmap = gr.loadTexture(filename,true)
	if not thisImage.Bitmap:isValid() then return else ba.print(filename .. " found! Loading...\n") end
	
	hilite = gr.loadTexture(filename .. "_h",true)
	idle = gr.loadTexture(filename .. "_b", true)
	
	if not idle:isValid() and self.Config.Characters[id] and self.Config.Characters[id].Idle then
		idle = gr.loadTexture(self.Config.Characters[id].Idle, true)
	end
	
	if hilite and hilite:isValid() then
		thisImage.BitmapH = hilite
		ba.print("VN Script: _h bitmap found, loading...\n")
	end
	
	if idle and idle:isValid() then
		thisImage.BitmapAlt = idle
		ba.print("VN Script: _b bitmap found, loading...\n")
	else
		thisImage.BitmapAlt = nil
	end

	if gr.getScreenWidth() / self.Config.MinRes < 1 then
		scale = gr.getScreenWidth() / self.Config.MinRes
	end
	
	thisImage.Height = thisImage.Bitmap:getHeight() * scale * self.Config.ScaleFactor
	thisImage.Width = thisImage.Bitmap:getWidth() * scale * self.Config.ScaleFactor
	
	thisImage.Frames = thisImage.Bitmap:getFramesLeft()
	thisImage.FPS = thisImage.Bitmap:getFPS()
		
	if x_pct then
		x_pct = x_pct / 100
	else
		x_pct = 0.5
	end
	
	thisImage.X = AXUI.Screen.x + (AXUI.Screen.w * x_pct) - thisImage.Width * 0.5
	
	if y_pct then
		thisImage.Y = AXUI.Screen.y + AXUI.Screen.h * (y_pct/100)
	else
		thisImage.Y = self.Anchor - thisImage.Height
	end
		
	if x_flip then
		if string.lower(x_flip) ~= "false" then
			thisImage.UVx1 = 1
			thisImage.UVx2 = 0
		else
			thisImage.UVx1 = 0
			thisImage.UVx2 = 1
		end
	end

	if y_flip then
		if string.lower(y_flip) ~= "false" then
			thisImage.UVy1 = 1
			thisImage.UVy2 = 0
		else
			thisImage.UVy1 = 0
			thisImage.UVy2 = 1
		end
	end
	
	if play then
		if string.lower(play) == "talking" then
			thisImage.Repeat = 1
		elseif string.lower(play) == "always" then
			thisImage.Repeat = 2
		elseif string.lower(play) == "once" then
			thisImage.Repeat = 0
		end
	end
	
	thisImage.Repeat = thisImage.Repeat or self.Config.DefaultRepeat

	thisImage.Layer = layer
	if (not thisImage.Timestamp) or thisImage.Repeat == 0 then
		thisImage.Timestamp = ba.getFrametimeOverall()
	end
	ba.print("layer = " .. thisImage.Layer .. "\n")
		
	self.Images[id] = thisImage

	if create then
		VS2:ImageEffect(id, "fadein", fadetime)
	else
		VS2:ImageEffect(id, "move", 0)
	end

end

function VS2:ShowIcon2(t)

	--for i,v in ipairs(t) do
	--	ba.print("t["..i.."]="..v.."\n")
	--end
	
	--ba.print("Number of passed arguments = " .. numargs .. "\n")

	local id = t[2]
	local filename = VS2:FindParam("file", t)
	local text = VS2:FindParam("text",t)
	local color = VS2:FindParam("color",t)
	local x_pct = VS2:FindParam("x", t)
	local x_flip = VS2:FindParam("xflip", t)
	local y_pct = VS2:FindParam("y", t)
	local y_flip = VS2:FindParam("yflip", t)
	
	local passedLine = {"SHOWICON",id,filename,text,color,x_pct,x_flip,y_pct,y_flip}
	
	VS2:ShowIcon(passedLine)
	
	
end

function VS2:ShowIcon(t)

	--t[1] = token
	--  2  = id
	--  3  = class name
	--  4  = text
	--  5  = color ("red", "green", "blue", "purple", "white", "yellow")
	--  6  = x pos (defaults to 50)
	--  7  = x flip
	--  8  = y pos (relative to message box top, defaults to 0)
	--  9  = y flip
	
	local thisImage = {}
	local id = t[2]
	local filename = t[3]
	local text = t[4]
	local color = t[5]
	local x_pct = t[6]
	local x_flip = t[7]
	local y_pct = t[8]
	local y_flip = t[9]
	local create = true
	local scale = 1
			
	if self.Images[id] then
		create = false
		thisImage = self.Images[id]
		thisImage.X_0 = self.Images[id].X
		thisImage.Y_0 = self.Images[id].Y
		thisImage.Alpha = 1
		thisImage.Bitmap:unload()
	else
		thisImage.Alpha = 0
	end
	
	thisImage.Bitmap = gr.loadTexture(filename)
	if not thisImage.Bitmap:isValid() then return end

	if color then
	
		if string.lower(color) == "red" then
			thisImage.Base = gr.loadTexture("icon_base_r")
		elseif string.lower(color) == "green" then
			thisImage.Base = gr.loadTexture("icon_base_g")
		elseif string.lower(color) == "blue" then
			thisImage.Base = gr.loadTexture("icon_base_b")
		elseif string.lower(color) == "purple" then
			thisImage.Base = gr.loadTexture("icon_base_p")
		elseif string.lower(color) == "yellow" then
			thisImage.Base = gr.loadTexture("icon_base_y")
		elseif string.lower(color) == "white" then
			thisImage.Base = gr.loadTexture("icon_base_w")
		end
	end
			
	if gr.getScreenWidth() / self.Config.MinRes < 1 then
		scale = gr.getScreenWidth() / self.Config.MinRes
	end

	thisImage.Height = thisImage.Bitmap:getHeight() * scale * self.Config.IconScaleFactor
	thisImage.Width = thisImage.Bitmap:getWidth() * scale * self.Config.IconScaleFactor
		
	if x_pct then
		x_pct = x_pct / 100
	else
		x_pct = 0.5
	end
	
	thisImage.X = AXUI.Screen.x + (AXUI.Screen.w * x_pct) - thisImage.Width * 0.5
	
	if y_pct then
		y_pct = y_pct / 100
	else
		y_pct = 0.5
	end
	
	thisImage.Y = AXUI.Screen.y + AXUI.Screen.h * (y_pct) -- thisImage.Height * 0.5

		
	if x_flip then
		if string.lower(x_flip) ~= "false" then
			thisImage.UVx1 = 1
			thisImage.UVx2 = 0
		--elseif gr.getImageWidth(thisImage.Bitmap .. "_m") > 0 then
		--	thisImage.Bitmap = thisImage.Bitmap .. "_m"
		else
			thisImage.UVx1 = 0
			thisImage.UVx2 = 1
		end
	end

	if y_flip then
		if string.lower(y_flip) ~= "false" then
			thisImage.UVy1 = 1
			thisImage.UVy2 = 0
		else
			thisImage.UVy1 = 0
			thisImage.UVy2 = 1
		end
	end
		
	if text then
		thisImage.Text = {}
		thisImage.Text.String = text
		--gr.CurrentFont = AXMessage.Fonts.Text
		gr.CurrentFont = gr.Fonts[3]
		thisImage.Text.X = gr.getStringWidth(text) / 2
		thisImage.Text.Y = gr.CurrentFont.Height + 5 -- + thisImage.Height
	end
	
	thisImage.Layer = 1 --Icons are always layer 1

	self.Images[id] = thisImage

	if create then
		VS2:ImageEffect(id, "fadein", 0.5)
	else
		VS2:ImageEffect(id, "move", 0)
	end

end

function VS2:Move2(t)

	--for i,v in ipairs(t) do
	--	ba.print("t["..i.."]="..v.."\n")
	--end
	
	--ba.print("Number of passed arguments = " .. numargs .. "\n")

	local id = t[2]
	local duration = VS2:FindParam("time", t) or 1
	local x_pct = VS2:FindParam("x", t)
	local x_flip = VS2:FindParam("xflip", t)
	local y_pct = VS2:FindParam("y", t)
	local y_flip = VS2:FindParam("yflip", t)
	
	local passedLine = {"MOVE",id,duration,x_pct,x_flip,y_pct,y_flip}
	
	VS2:Move(passedLine)
	
	
end

function VS2:Move(t)

	local thisImage = {}
	local id = t[2]
	local duration = t[3]
	local x_pct = t[4]
	local x_flip = t[5]
	local y_pct = t[6]
	local y_flip = t[7]
	
	if self.Images[id] then
	
		thisImage = self.Images[id]
	
		thisImage.X_0 = self.Images[id].X
		thisImage.Y_0 = self.Images[id].Y
		
		if x_pct then
			x_pct = x_pct / 100
		else
			x_pct = 0.5
		end
		
		thisImage.X = AXUI.Screen.x + (AXUI.Screen.w * x_pct) - thisImage.Width * 0.5
	
		if y_pct then
			thisImage.Y = AXUI.Screen.y + AXUI.Screen.h * (y_pct/100)
		else
			thisImage.Y = self.Anchor - thisImage.Height
		end
			
		if x_flip then
			if string.lower(x_flip) ~= "false" then
				thisImage.UVx1 = 1
				thisImage.UVx2 = 0
			else
				thisImage.UVx1 = 0
				thisImage.UVx2 = 1
			end
		end

		if y_flip then
			if string.lower(y_flip) ~= "false" then
				thisImage.UVy1 = 1
				thisImage.UVy2 = 0
			else
				thisImage.UVy1 = 0
				thisImage.UVy2 = 1
			end
		end

		--self.Images[id] = thisImage
		
		VS2:ImageEffect(id, "move", duration)
	end

end

function VS2:Change2(t)

	--for i,v in ipairs(t) do
	--	ba.print("t["..i.."]="..v.."\n")
	--end
	
	--ba.print("Number of passed arguments = " .. numargs .. "\n")

	local id = t[2]
	local filename = VS2:FindParam("file", t)
	local x_flip = VS2:FindParam("xflip", t)
	local y_flip = VS2:FindParam("yflip", t)
	local play = VS2:FindParam("repeat", t)
	local layer = VS2:FindParam("layer", t)
	
	local passedLine = {"CHANGE",id,filename,x_flip,y_flip,play,layer}
	
	VS2:Change(passedLine)
	
	
end

function VS2:Change(t)

	--t[1] = token
	--  2  = id
	--  3  = filename
	--  4  = flip x
	--  5  = flip y
	
	local id = t[2]
	local filename = t[3]
	local x_flip = t[4]
	local y_flip = t[5]
	local play = t[6]
	local layer = t[7] or 3 --need to fix this so it might also take the old layer
	local scale = 1
	
	axemParse:Validate("line " .. self.Scene.Line .. ": argument 1", t[2], "string")
	
	local thisImage = self.Images[id]
	
	if not thisImage then
		return
	end
	
	if filename then
	
		thisImage.Bitmap:unload()
		
		if thisImage.BitmapH and thisImage.BitmapH:isValid() then
			thisImage.BitmapH:unload()
		end
		
		if thisImage.BitmapAlt and thisImage.BitmapAlt:isValid() then
			thisImage.BitmapAlt:unload()
		end

		thisImage.Bitmap = gr.loadTexture(filename,true)
		
		if not thisImage.Bitmap:isValid() then return else ba.print(filename .. " found! Loading...\n") end
		
		if thisImage.Bitmap:isValid() then
		
			if gr.getScreenWidth() / self.Config.MinRes < 1 then
				scale = gr.getScreenWidth() / self.Config.MinRes
			end
			
			thisImage.Height = thisImage.Bitmap:getHeight() * scale * self.Config.ScaleFactor
			thisImage.Width = thisImage.Bitmap:getWidth() * scale * self.Config.ScaleFactor
			
			thisImage.Frames = thisImage.Bitmap:getFramesLeft()
			thisImage.FPS = thisImage.Bitmap:getFPS()
			
			hilite = gr.loadTexture(filename .. "_h",true)
			idle = gr.loadTexture(filename .. "_b", true)
			
			if not idle:isValid() and self.Config.Characters[id] and self.Config.Characters[id].Idle then
				idle = gr.loadTexture(self.Config.Characters[id].Idle, true)
			end
			
			if hilite and hilite:isValid() then
				thisImage.BitmapH = hilite
				ba.print("VN Script: _h bitmap found, loading...\n")
			end
			
			if idle and idle:isValid() then
				thisImage.BitmapAlt = idle
				ba.print("VN Script: _b bitmap found, loading...\n")
			end
				
		end
	end
	
	if x_flip then
		if string.lower(x_flip) ~= "false" then
			thisImage.UVx1 = 1
			thisImage.UVx2 = 0
		else
			thisImage.UVx1 = 0
			thisImage.UVx2 = 1
		end
	end

	if y_flip then
		if string.lower(y_flip) ~= "false" then
			thisImage.UVy1 = 1
			thisImage.UVy2 = 0
		else
			thisImage.UVy1 = 0
			thisImage.UVy2 = 1
		end
	end
	
	if play then
		if string.lower(play) == "talking" then
			thisImage.Repeat = 1
		elseif string.lower(play) == "always" then
			thisImage.Repeat = 2
		elseif string.lower(play) == "once" then
			thisImage.Repeat = 0
		end
	end
	
	thisImage.Repeat = thisImage.Repeat or self.Config.DefaultRepeat

	thisImage.Layer = thisImage.Layer or layer
	
	if (not thisImage.Timestamp) or thisImage.Repeat == 0 then
		thisImage.Timestamp = ba.getFrametimeOverall()
	end

end

function VS2:ImageEffect(img, style, duration)

	local overwrite

	for i,v in ipairs(self.Transitions) do
		if v.Handle == img and v.Type == style then
			overwrite = i
		end
	end

	local eff = {}
	local image = self.Images[img]

	if style == "fadein" then
		eff.A1 = 0
		eff.A2 = 1
	elseif style == "fadeout" then
		eff.A1 = 1
		eff.A2 = 0
	elseif style == "move" then
		eff.X1 = image.X_0
		eff.X2 = image.X
		eff.Y1 = image.Y_0
		eff.Y2 = image.Y
	end
		
	eff.Handle = img
	eff.Type = style
	eff.StartTime = ba.getFrametimeOverall()
	eff.Duration = duration or 0.5
	eff.EndTime = eff.StartTime + eff.Duration
	
	if overwrite then
		ba.print("Updating " .. img .. "'s image effect...\n")
		self.Transitions[overwrite] = eff
	else
		ba.print("Creating " .. img .. "'s image effect...\n")
		self.Transitions[#self.Transitions+1] = eff
	end
	--self.Transitions[img] = eff

end

function VS2:Hide(t)

	--t[1] = token
	--  2  = id
	--  3  = hide right away
	
	local id = t[2]
	local now = t[3]
	
	if id and string.upper(id) == "ALL" then
		if now then
			for k,v in pairs(VS2.Images) do
				ba.print("VN: Hiding " .. k .. "without fadeout\n")
				VS2:ImageEffect(k, "fadeout", 0.01)
				VS2.Images[k].Expire = true
			end
		else
			for k,v in pairs(VS2.Images) do
				ba.print("VN: Hiding " .. k .. "...\n")
				VS2:ImageEffect(k, "fadeout", 0.05)
				VS2.Images[k].Expire = true
			end
		end
	elseif VS2.Images[id] then
		if now then
			ba.print("VN: Hiding " .. id .. "without fadeout\n")
			VS2:ImageEffect(id, "fadeout", 0.01)
			VS2.Images[id].Expire = true
		else
			ba.print("VN: Hiding " .. id .. "...\n")
			VS2:ImageEffect(id, "fadeout", 0.5)
			VS2.Images[id].Expire = true
		end
	else
		ba.print("VN: Bad id given, ignoring...\n")
	end
	
end

function VS2:SetBG(t)

	--t[1] = token
	--  2  = filname
	--  3  = scaling type, defaults to noscaledown (noscale, noscaleup, noscaledown, scaletofit)
	
	if self.BG and self.BG.Image and self.BG.Image:isValid() then
		self.BG.Image:unload()
		self.BG = nil
	end

	local filename = t[2]
	local scaling = t[3] or "NOSCALEDOWN"
	
	scaling = string.upper(scaling)
	
	if string.upper(filename) == "NONE" then return	end
	
	if filename and gr.getImageWidth(filename) ~= 0 then
		self.BG = {}
		self.BG.Image = gr.loadTexture(filename)
		self.BG.Width = self.BG.Image:getWidth()
		self.BG.Height = self.BG.Image:getHeight()
		
		if (scaling == "NOSCALEDOWN" and (self.BG.Width < AXUI.Screen.w or self.BG.Height < AXUI.Screen.h)) or (scaling == "NOSCALEUP" and (self.BG.Width > AXUI.Screen.w or self.BG.Height > AXUI.Screen.h)) then
			ba.print("VN: We need to scale\n")
			ba.print(scaling .. "\n")
			local scalingFactor = 1

			if (AXUI.Screen.w / self.BG.Width) > (AXUI.Screen.h / self.BG.Height) then
				scalingFactor = AXUI.Screen.w / self.BG.Width
			else
				scalingFactor = AXUI.Screen.h / self.BG.Height
			end
			
			ba.print(scalingFactor .."\n")
			
			self.BG.Width = self.BG.Width * scalingFactor
			self.BG.Height = self.BG.Height * scalingFactor
		elseif scaling == "SCALETOFIT" then
			self.BG.Width = AXUI.Screen.w
			self.BG.Height = AXUI.Screen.h
		end
		self.BG.X = AXUI.Screen.x + AXUI.Screen.w/2 - self.BG.Width/2
		self.BG.Y = AXUI.Screen.y + AXUI.Screen.h/2 - self.BG.Height/2
	else
		ba.print("VN: Invalid background given, ignoring...\n")
	end

end

function VS2:CreateMenu(t)

	--t[1] = The Token
	--t[2] = The Variable the result will get saved too
	--t[3-7] = The Choices
	
	local choices = {}
	local index = 1
	
	axemParse:Validate("line " .. self.Scene.Line .. ": argument 1", t[2], "string")
	axemParse:Validate("line " .. self.Scene.Line .. ": argument 2", t[3], "string")
	
	for i = 3, 7 do
		if t[i] then
		
			if (t[i]:find("$") == 1) and mn.SEXPVariables[t[i]:sub(2)] and mn.SEXPVariables[t[i]:sub(2)]:isValid() then
				t[i] = mn.SEXPVariables[t[i]:sub(2)].Value
			end
		
			choices[index] = "> " .. t[i]
			index = index + 1
		end
	end
	
	self.Menu = AXUI:CreateListBox(choices, AXMessage.Position.x + 30, AXMessage.Position.y + 60, AXMessage.Image.w - 20, AXMessage.Image.h - 50, "white", "silver", "bright_white", false, 0, 2)
	self.Menu.FontHeight = self.Menu.FontHeight + 2
	self.Menu:UpdateList(0)
	self.Menu.Variable = t[2]
	
	local flagVariable = self.Variables["f_" .. self.Menu.Variable]
	
	if flagVariable then
		for i, v in ipairs(self.Menu.Item) do
			if bit.checkBit(flagVariable, i) then
				v.Hoverable = false
				v.Color = "invisible"
			end
		end
	end
	
	
end

function VS2:EvalIf(t)

	--So let me get this straight, you're parsing an IF statement, which will get parsed by Lua's IF functions, which will get parsed by C++'s IF functions... Wow.

	local token = string.upper(t[1])
	local a, op, b = t[2], t[3], t[4]
	
	ba.print("VN: Evaluating IF statment...\n")
	
	if type(a) == "string" then
		if VS2.Variables[a] then
			a = VS2.Variables[a]
		elseif mn.SEXPVariables[a]:isValid() then
			a = mn.SEXPVariables[a].Value
		else
			--a = 0
		end
	end
	
	if type(b) == "string" then
		if VS2.Variables[b] then
			b = VS2.Variables[b]
		elseif mn.SEXPVariables[b]:isValid() then
			b = mn.SEXPVariables[b].Value
		else
			--b = 0
		end
	end


	--if we hit an IF or an ElseIF
	if (token == "IF") or (token == "EIF" and not self.Result) then
	
		self.Result = VS2:EvalLogic(a, op, b)
		
		if self.Result then
			ba.print("VN: Returned true!\n")
			self:NextLine()
			return
		else
			ba.print("VN: Returned false...\n")
		end
	--or just an else (and we haven't gotten a good result yet)
	elseif token == "ELSE" and not self.Result then
		ba.print("VN: Hit Else...\n")
		self:NextLine()
		return
	end
	
	--If we're still out of luck, we should look for lines that we will be interested in
	ba.print("VN: Looking for next good line...\n")

	repeat

		self.Line = self.Line + 1
		local parsedLine = VS2:ParseLine(self[self.Line])
		local nextToken
		if parsedLine then
			nextToken = string.upper(parsedLine[1])
		else
			ba.error("VN: No ENDIF or END specified!!")
		end
		
		ba.print("VN: Searching line " .. self.Line .. ", token is " .. nextToken .. "... \n")
		
		if nextToken == "ENDIF" or nextToken == "END" then
			self.Result = false
		end
		
	until nextToken == "EIF" or nextToken == "ENDIF" or nextToken == "ELSE" or nextToken == "END"
	
	ba.print("VN: Broke out of the loop! Headed to line " .. self.Line .. "\n")
	
	self:GoToLine(self.Line)
	return
	
end

function VS2:EvalLogic(a, op, b)

	ba.print("VN: a='" .. a .. "', op='" .. op .. "', b='" .. b .. "'\n")
	
	if op == "=" or op == "==" then
		if a == b then
			return true
		end
	end
	
	if op == "~=" or op == "!=" then
		if a ~= b then
			return true
		end
	end
	
	if op == "<" then
		if a < b then
			return true
		end
	end
	
	if op == "<=" then
		if a <= b then
			return true
		end
	end
	
	if op == ">" then
		if a > b then
			return true
		end
	end
	
	if op == ">=" then
		if a >= b then
			return true
		end
	end
	
	return false

end

function VS2:Wait(length, auto)

	self.OkayTime = ba.getFrametimeOverall() + length
		
	if auto then
		self.Auto = true	
	end
		
end

function VS2:SetVar(t, sexp)

	local token = t[1]
	local variableName = t[2]
	local op = t[3]
	local num = {}
	local index = 1
	local variable
	
	--axemParse:Validate("line " .. self.Scene.Line .. ": argument 1", t[2], "string")
	
	--Is this supposed to be a sexpy party or what
	if sexp then
		if mn.SEXPVariables[variableName]:isValid() then
			variable = mn.SEXPVariables[variableName].Value
		else
			return
		end
	else
		variable = self.Variables[variableName]
	end
	
	--If our buddy doesn't exist yet, let us init him at 0
	if not variable then
		ba.print("VN: Variable doesn't exist, initializing at zero...\n")
		variable =  0
	end
	
	--Replace possible variable names with their values
	for i = 4, #t do
	
		if type(t[i]) == "string" then
			for k, v in pairs(self.Variables) do
				if k == t[i] then
					num[index] = v
				end
			end
			
			for j = 1, #mn.SEXPVariables do
				if mn.SEXPVariables[j] == t[i] then
					num[index] = mn.SEXPVariables[j].Value
				end
			end
		elseif type(t[i]) == "number" then
			num[index] = t[i]
		end
		
		if not num[index] then
			num[index] = 0
		end
		
		index = index + 1
		
	end
			
	if op == "=" then
		ba.print("assignment\n")
		variable = num[1]
	end
	
	local sum = 0
	
	for i, v in ipairs(num) do
		ba.print(v .. "\n")
		sum = sum + v
	end
		
	if op == "+" then
		ba.print("add\n")
		variable = variable + sum
	end
	
	if op == "-" then
		ba.print("subtract\n")
		variable = variable - sum
	end
	
	if op == "rand" then
		ba.print("random\n")
		local n1 = num[1]
		local n2 = num[2]
		variable = math.random(n1, n2)
	end
		
	if sexp then
		if mn.SEXPVariables[variableName]:isValid() then
			mn.SEXPVariables[variableName].Value = variable
		else
			return
		end
	else
		self.Variables[variableName] = variable
	end
	
	ba.print("VN: " .. variableName .. " was set to " .. variable .. "\n")

end

function VS2:SetFlag(t)

	--t[1] = The Token
	--  2  = The variable to associate with (will get f_ put in front)
	--  3  = The bit to set
	
	local varName = t[2]
	local rootVar = self.Variables[varName] or 0
	local flagVar = "f_" .. varName
	local flag = t[3] or rootVar
	
	axemParse:Validate("line " .. self.Scene.Line .. ": argument 1", t[2], "string")
	
	if type(flag) == "string" then
		for k, v in pairs(self.Variables) do
			if k == flag then
				flag = v
			end
		end
	end
	
	self.Variables[flagVar] = self.Variables[flagVar] or 0
	
	self.Variables[flagVar] = bit.toggleBit(self.Variables[flagVar],flag)


end

function VS2:SetFont(t)

	--t[2] = Font to use
	
	if t[2] then
		if gr.Fonts[t[2]]:isValid() then
			AXMessage.Fonts.Text = gr.Fonts[t[2]]
		else
			AXMessage.Fonts.Text = gr.Fonts[self.Config.Font.Text.Font or 3]
		end
	else
		AXMessage.Fonts.Text = gr.Fonts[self.Config.Font.Text.Font or 3]
	end

end

function VS2:SendMsg(t)

	--t[1] = The Sender
	--  2  = The Message Text
	--  3  = The Voice File
	--  last = If the message should advance without a prompt

	local sender
	local characters = self.Config.Characters
	local playsound
	
	axemParse:Validate("line " .. self.Scene.Line .. ": argument 1", t[2], "string")
	
	--self.Message = nil
	--self.Message = mn.addMessage("VS2Message" .. self.MsgNumber, " ")
	--self.MsgNumber = self.MsgNumber + 1
	
	if string.upper(t[1]) ~= "SELF" then
		sender = t[1]
	else
		sender = " "
	end
	
	self.Message.Message = t[2]
	

	ba.print("Message text: " .. t[2] .. "\n")
	
	if t[3] and t[3] ~= "AUTO" then
		playsound = true
		self.Message.VoiceFile = ad.loadSoundfile(t[3])
		--ba.print("Voice file is assigned\n")
	elseif characters[sender] and characters[sender].DefaultVoice then
		playsound = true
		self.Message.VoiceFile = ad.loadSoundfile(characters[sender].DefaultVoice)
		--ba.print("No voice file is assigned, trying to use DefaultVoice\n")
	else
		self.Message.VoiceFile = nil
		--ba.print("No voice file at all!\n")
	end
		
	if t[#t] == "AUTO" then
		self.Auto = true
		--ba.print("This message will auto advance\n")	
	else
		self.Auto = false
	end
	
	AXMessage.Speed = nil
		
	for i, v in ipairs(t) do
		if string.find(string.upper(v), "TEXTSPEED") == 1 then
			--ba.print("Custom speed specified: " .. t[i+2] .. "\n")
			if t[i+2] then
				AXMessage.Speed = t[i+2]
			end
			break
		end		
	end
	
	AXMessage.Speed = AXMessage.Speed or self.Config.TextDraw
	
	if characters[sender] and characters[sender].Name then	
		self.Speaking = characters[sender].Name
	else
		self.Speaking = sender
	end
	
	if (self.Message.Message == "...") or (string.find(self.Message.Message, "%(") == 1) then
		ba.print("VN: Message isn't supposed to be said outloud, no 'speaker'\n")
		self.Sender = nil
	else
		self.Sender = sender
	end
		
	if characters[sender] and characters[sender].Color then
		AXMessage.Color.Title = {characters[sender].Color[1],characters[sender].Color[2],characters[sender].Color[3],characters[sender].Color[4] or 255}
	elseif mn.Ships[self.Speaking]:isValid() then
		local r,g,b = mn.Ships[self.Speaking].Team:getColor()
		AXMessage.Color.Title = {r,g,b,255}
	else
		local titleFont = self.Config.Font.Title.Color
		AXMessage.Color.Title = {titleFont[1],titleFont[2],titleFont[3],255}
	end
	
	
	if mn.Ships[self.Speaking]:isValid() then
		self.Speaking = self.Speaking .. "" --This is a dumb hack, but the game has an issue with the speaker matching a real ship
	end
		
	--ba.print("Voice file: " .. tostring(self.Message.VoiceFile.Filename) .. "\n")
	ba.print("VN: Sending message: " .. sender .. ": " .. self.Message.Message .."\n")
	mn.sendMessage(self.Speaking, self.Message)
	
	if self.Message.VoiceFile:isValid() then
		self.OkayTime = ba.getFrametimeOverall() + self.Message.VoiceFile.Duration
	else
		self.OkayTime = ba.getFrametimeOverall() + 0.001
	end
	
	if self.Images[sender] and self.Images[sender].Repeat == 0 and self.Sender then
		self.Images[sender].Timestamp = ba.getFrametimeOverall()
	end
		
	self.MsgEndTime = nil
	self.ReleasedCheck = nil

end

function VS2:ProcessTransition(eff)
	
	local thisImage = self.Images[eff.Handle]
	
	if thisImage then
	
		local t = ba.getFrametimeOverall() - eff.StartTime
		local d = eff.Duration
		
		if eff.A1 and eff.A2 then
			thisImage.Alpha = VS2:Ease(t, eff.A1, eff.A2-eff.A1, d)
		end
		
		if eff.X1 and eff.X2 then
			--thisImage.Alpha = 1
			thisImage.X = VS2:Ease(t, eff.X1, eff.X2-eff.X1, d)
		end
		
		if eff.Y1 and eff.Y2 then
			--thisImage.Alpha = 1
			thisImage.Y = VS2:Ease(t, eff.Y1, eff.Y2-eff.Y1, d)
		end
	
	end
	
end

function VS2:Ease(t,b,c,d)
  t = t / d
  return -c * t * (t - 2) + b
end

function VS2:Draw()

	if self.BG then
		gr.drawImage(self.BG.Image, self.BG.X, self.BG.Y, self.BG.X+self.BG.Width, self.BG.Y+self.BG.Height)
	end

	
	if self.Scene then
		
		if self.Transitions then
			for i=1, #self.Transitions do
				local v = self.Transitions[i]
				if v then
					local image = v.Handle
					if ba.getFrametimeOverall() < v.EndTime then
						VS2:ProcessTransition(v)
					else
						ba.print("VS2: Transition time is up for " .. image .. "\n")
						if self.Images[image] then
							if v.A2 then
								self.Images[image].Alpha = v.A2
								ba.print("Transition set: Alpha\n")
							end
							
							if v.X2 then
								self.Images[image].X = v.X2
								ba.print("Transition set: X\n")
							end
							
							if v.Y2 then
								self.Images[image].Y = v.Y2
								ba.print("Transition set: Y\n")
							end
							
							if self.Images[image].Expire then
								self.Images[image].Bitmap:unload()
								
								if self.Images[image].BitmapH and self.Images[image].BitmapH:isValid() then
									self.Images[image].BitmapH:unload()
								end
								
								if self.Images[image].BitmapAlt and self.Images[image].BitmapAlt:isValid() then
									self.Images[image].BitmapAlt:unload()
								end
								
								if self.Images[image].Base then
									self.Images[image].Base:unload()
								end
								
								self.Images[image] = nil
							end
						end		
						table.remove(self.Transitions,i)						
					end					
				end
			end
		end
		
		if self.IntButton and self.IntDraw then
			self.IntButton:Draw()
		end
				
		if self.Images then

			for i = 1, 5 do
				for k, v in pairs(self.Images) do
					if i == v.Layer then
						local speak
						if self.Sender == k then
							speak = true
						end
						self:DrawBitmap(v, speak)
					end
				end		
			end
		end
			
		if AXMessage.Enabled and AXMessage.DrawControl == "VS2" and self.ShowBox then
			AXMessage:UpdateString()
			AXMessage:Draw()
		end
		
		if not AXMessage.Drawing and not self.PressedLastFrame then
			self.ReleasedCheck = true
		end
		
		if ba.getFrametimeOverall() > self.OkayTime and not self.Menu and not self.Auto and not AXMessage.Drawing and self.ShowBox then
		
			if not self.MsgEndTime then
				self.MsgEndTime = ba.getFrametimeOverall()
			end
						
			gr.currentFont = AXMessage.Fonts.Text
			gr.drawString(string.rep(">",(math.floor(ba.getFrametimeOverall() - self.MsgEndTime) % 3)+1), AXMessage.Position.x + AXMessage.Image.w - 50, AXMessage.Position.y + AXMessage.Image.h - 15)
			
		end
		
		if self.Menu and not AXMessage.Drawing and self.ShowBox then
			self.Menu:DrawList()
		end
				
		if self.Fade then
		
			if ba.getFrametimeOverall() < self.Fade.EndTime then
				local t = ba.getFrametimeOverall() - self.Fade.StartTime
				local b = self.Fade.A1
				local c = self.Fade.A2 - self.Fade.A1
				local d = self.Fade.Duration
				local alpha = (c * t / d + b)
				--ba.print(alpha.."\n")
				gr.setColor(self.Fade.Color[1], self.Fade.Color[2], self.Fade.Color[3], alpha)
				gr.drawRectangle(0,0,AXUI.Screen.w, AXUI.Screen.h)
			else
				self.Fade = nil	
			end
		end
	end

end

function VS2:DrawBitmap(entry, speaking)

		local bitmap
		local layer = entry.Layer
		local debugString1 = "Debug: "
		local debugString2 = ""
		
		gr.setColor(192,192,192,255)
		
		--Choose which bitmap to draw with
		if entry.BitmapAlt and entry.BitmapAlt:isValid() then
			debugString2 = debugString2 .. "Alt File Loaded "
			if entry.Repeat == 0 and (ba.getFrametimeOverall() - entry.Timestamp) > (entry.Frames / entry.FPS) then
				--if repeat is off and the alt hasn't played once
				debugString2 = debugString2 .. "Repeat Finished, Idle "
				bitmap = entry.BitmapAlt
			elseif (not speaking and entry.Repeat == 1) then
				--we're not speaking and repeat is normal
				debugString2 = debugString2 .. "Idle "
				bitmap = entry.BitmapAlt
			end
		end

		if entry.BitmapH and entry.BitmapH:isValid() then
			if speaking and entry.Repeat == 1 then
				debugString2 = debugString2 .. "H Talking "
				bitmap = entry.BitmapH
			elseif entry.Repeat == 2 then
				debugString2 = debugString2 .. "H Always Talking "
				bitmap = entry.BitmapH
			elseif entry.Repeat == 0 and (ba.getFrametimeOverall() - entry.Timestamp) < (entry.Frames / entry.FPS) then
				debugString2 = debugString2 .. "H Repeat Once "
				bitmap = entry.BitmapH
			end
		end
		
		bitmap = bitmap or entry.Bitmap
		
		debugString1 = debugString1 .. " " .. bitmap:getFilename() .. ": "

		if entry.Base then
			gr.drawImage(entry.Base, entry.X, entry.Y-self.Config.YBuffer, entry.X+entry.Width, entry.Y+entry.Height-self.Config.YBuffer, entry.UVx1 or 0,entry.UVy1 or 0,entry.UVx2 or 1,entry.UVy2 or 1,entry.Alpha)
		end
		
		local idx = 1
		
		if speaking then
			debugString2 = debugString2 .. "Talking "
		end
		
		--Animation Station
		if entry.Frames and entry.Frames > 1 then
			if (not entry.BitmapAlt:isValid()) or (entry.BitmapAlt and entry.BitmapAlt:isValid() and entry.BitmapAlt:getFramesLeft() == 1) then
				if entry.Repeat == 0 then
					debugString2 = debugString2 .. "Repeat Once "
					idx = math.min(entry.Frames, 1 + (((ba.getFrametimeOverall() - entry.Timestamp) * entry.FPS)))
				elseif (speaking and entry.Repeat == 1) or (entry.Repeat == 2) then
					debugString2 = debugString2 .. "Animating "
					idx = 1 + (((ba.getFrametimeOverall() - entry.Timestamp) * entry.FPS) % entry.Frames)
				end
			else
				debugString2 = debugString2 .. "Animating2 "
				idx = 1 + (((ba.getFrametimeOverall() - entry.Timestamp) * entry.FPS) % entry.Frames)
			end
		end
		--idx = 1 + (((ba.getFrametimeOverall() - entry.Timestamp) * entry.FPS) % entry.Frames)
		
		gr.drawImage(bitmap[idx], entry.X, entry.Y-self.Config.YBuffer, entry.X+entry.Width, entry.Y+entry.Height-self.Config.YBuffer, entry.UVx1 or 0,entry.UVy1 or 0,entry.UVx2 or 1,entry.UVy2 or 1,entry.Alpha)
		if self.Debug then
			if speaking then
				gr.setColor(192,0,0,255)
			else
				gr.setColor(255,255,255,255)
			end
			gr.setLineWidth(2)
			gr.drawRectangle(entry.X, entry.Y-self.Config.YBuffer, entry.X+entry.Width, entry.Y+entry.Height-self.Config.YBuffer,false)
			gr.drawString(debugString1,entry.X+5,entry.Y+5)
			gr.drawString(debugString2)
			gr.drawString("frame: " .. math.floor(idx))
		end

		if entry.Text then
			gr.CurrentFont = gr.Fonts[3]
			gr.setColor(AXMessage.Color.Text[1], AXMessage.Color.Text[2], AXMessage.Color.Text[3], 255 * entry.Alpha)
			gr.drawString(entry.Text.String, ((entry.X + (entry.X+entry.Width)) / 2)- entry.Text.X, entry.Y + entry.Height-self.Config.YBuffer)
		end
end

function VS2:Actions(key, pressed)

	local currentTime = ba.getFrametimeOverall()

	if self.Scene then
	
		if pressed then
				
			for k,v in pairs(self.Config.Keys.Hurry) do
				if key == v then
					AXMessage.Speed = AXMessage.Speed / 3
					self.PressedLastFrame = true
				end
			end
					
		else
			--[[ba.print("*********************\n")
			ba.print("time:" .. currentTime .. "\n")
			ba.print("oktime:" .. self.OkayTime .. "\n")
			ba.print("time > oktime? " .. tostring(currentTime > self.OkayTime) .. "\n")
			ba.print("drawing?" .. tostring(AXMessage.Drawing) .. "\n")]]--
		
		--(currentTime > (self.LastClicked + 0.2)) and
		
			if self.IntButton and self.IntDraw and self.IntButton:Clicked() then
				self:Interrupt()
			end
		
			if (currentTime > self.OkayTime) and not self.Menu and AXMessage.Drawing and not self.Auto then
			
			self.LastClicked = ba.getFrametimeOverall()
				
				for k,v in pairs(self.Config.Keys.Forward) do
					if key == v then
						ba.print("VN: Forward button pressed! Speed = 0\n")
						AXMessage.Speed = 0
					end
				end
							
				for k,v in pairs(self.Config.Keys.Hurry) do
					if key == v then
						self.Scene:NextLine()
					end
				end
			
			elseif (currentTime > self.OkayTime) and not self.Menu and not AXMessage.Drawing and not self.Auto then

				for k,v in pairs(self.Config.Keys.Forward) do
					if key == v then
						ba.print("VN: Forward button pressed! Advancing\n")
						self.Scene:NextLine()
					end
				end
				
			elseif (currentTime > self.OkayTime) and self.Menu and not AXMessage.Drawing and not self.Auto then
				
				for i, v in ipairs(self.Menu.Item) do
					if v:Clicked() or key == tostring(i) then
						ad.playInterfaceSound(0)
						self.Variables[self.Menu.Variable] = i
						self.Menu = nil
						self.Scene:NextLine()
					end
				end
			end
						
			for k,v in pairs(self.Config.Keys.Hurry) do
				if key == v then
					AXMessage.Speed = AXMessage.Speed * 3
					self.PressedLastFrame = nil
				end
			end
									
		end
	end

end

function VS2:CheckTimers(currentTime)

	if currentTime > self.OkayTime and not AXMessage.Drawing and not self.Menu and self.Auto then
		self.Auto = false
		self.Scene:NextLine()
	end
				
end

function VS2:Exit(keepvars)

	ba.print("Exiting Visual Novel Script...\n")

	self.Enabled = false
	if not keepvars then
		self.Scene = nil
		self.Variables = nil
		self.Message = nil
		self.Debug = nil
		self.IntKey = nil
		self.IntGoto = nil
		self.IntButton = nil
		self.IntOffset = nil
		
		if self.Images then
			for k,v in pairs(self.Images) do
				if v.Base then
					v.Base:unload()
				end
				v.Bitmap:unload()
				if v.BitmapH and v.BitmapH:isValid() then
					v.BitmapH:unload()
				end
				
				if v.BitmapAlt and v.BitmapAlt:isValid() then
					v.BitmapAlt:unload()
				end
			end
		end
		
		self.Images = nil
		self.Fade = nil
		self.CanAdvance = nil
		self.OkayTime = 0
	end
	if VS2.MusicHandle then
		ad.stopMusic(VS2.MusicHandle, true)
	end
	mn.runSEXP("(hud-disable 0)")
	AXUI:ScreenInit()
	AXMessage:Init()
	
end

function VS2:FreeToTalk()

	local result = 0

	if self.CanTalk then
		result = 1
		ba.print("VN: let's talk why not\n")
	end

	return result

end

function VS2:CheckInterrupt(key)

	if self.IntKey and self.IntKey == key then
		ba.print("VS2: INTERRUPT HIT!!!\n")
		self:Interrupt()
	end

end

]

$State: GS_STATE_GAME_PLAY
$On Gameplay Start:
[
	if VS2.Enabled then
		VS2:Exit()
	end
]

$On State End:
[
	--if VS2.Enabled then
		VS2:Exit()
		AXUI.Ingame = false
		AXUI:ScreenInit()
	--end
]

$On Message Received:
[

	if VS2.Enabled and AXMessage.DrawControl == "VS2" then
		AXMessage:SetupMessage(hv.SenderString, hv.Name, hv.Message)
	end

]

$On Frame:
[
	if VS2.Enabled then
		if VS2.ShowCursor then
			io.setCursorHidden(false)
		end
		VS2:CheckTimers(ba.getFrametimeOverall())
		VS2:Draw()
		--PrintDebug(VS2.Transitions)
	end
	
	if VS2.ExpireTalk then
		VS2.ExpireTalk = nil
		VS2.CanTalk = nil
		ba.print("VN: expiring talk status\n")
	end
	
	if VS2.CanTalk then
		VS2.ExpireTalk = true
		ba.print("VN: expire talk next frame\n")
	end
	
	--gr.setColor(255,255,255,255)
	--gr.drawString(ba.getFrametimeOverall(),100,100)
		
]

$On Action Stopped:
[
	if VS2.Enabled then
		VS2:Actions(hv.Action, false)
	end
]

$On Action:
[
	if VS2.Enabled then
		VS2:Actions(hv.Action, true)
	end
]

$On Key Released:
[
	if hv.Key == "Alt-C" then
		VS2.CanTalk = true
		--ba.print("VN: beep\n")
	end
		
	if VS2.Enabled then
	
		VS2:CheckInterrupt(hv.Key)
	
		if hv.Key == "0" then
			if VS2.Debug then
				VS2.Debug = false
			else
				VS2.Debug = true
			end
		end
	end


]

$On Mouse Released:
[
	--[[if VS2.Enabled then
		if bit.checkBit(hv.MouseButton, 0) then
			VS2:Actions("Left Mouse", false)
		elseif bit.checkBit(hv.MouseButton, 1) then
			VS2:Actions("Right Mouse", false)
		end
	end]]--
]

$On Mouse Pressed:
[
	--[[if VS2.Enabled then
		if bit.checkBit(hv.MouseButton, 0) then
			VS2:Actions("Left Mouse", true)
		elseif bit.checkBit(hv.MouseButton, 1) then
			VS2:Actions("Right Mouse", true)
		end
	end]]--
]

#End