// File: level.agc
// Created: 20-05-08

type tLights
	obj				as tObject
	colour			as integer
	time			as float
	blink			as integer
	red				as integer
	yellow			as integer
	elapsed			as float
	mode			as integer
	init			as integer
endtype

type tMiniMap
	id				as integer
	scale			as tPoint
	offset			as tPoint
endtype

type tStart
	obj				as tObject
	line			as tLine
endtype

type tLevel
	folder			as string
	ground			as tObject
	walls			as tObject
	objs			as tObject[]
	grass			as tObject
	bridge			as tObject	
	map				as tMiniMap
	lights			as tLights
	start			as tStart
	vm				as tObject	
	laps			as integer
	speed			as integer[]
endtype

global gTweens		as tTween[]
global gLevel		as tLevel

function LoadLevel(folder as string, e ref as tEnvironment)
	i			as integer
	p			as tPoint
	s			as string
	w			as float
	obj			as tObject
	clone		as tObject
	level		as tLevel
	f			as integer
	line		as string
	typ			as string
	name		as string
	images		as tLevelImage[]
	id			as integer
	newPath		as tPath
	newFollow	as tFollow

	delete3DPhysicsWorld()	
	create3DPhysicsWorld(SCALE_3D)
	
	f = OpenToRead(folder+"level.map")
	
	repeat
		line = ReadLine(f)
				
		if left(line,1) = "#"
			continue
		endif
		
		typ = GetStringToken2(line, "=", 1)
		line = GetStringToken2(line, "=", 2)		
		
		select lower(typ)
			case "laps"
				level.laps = val(GetStringToken2(line, ",", 1))
			endcase			
			case "speed"
				level.speed.insert(val(GetStringToken2(line, ",", 1)))
				level.speed.insert(val(GetStringToken2(line, ",", 2)))
				level.speed.insert(val(GetStringToken2(line, ",", 3)))
				level.speed.insert(val(GetStringToken2(line, ",", 4)))
				level.speed.insert(val(GetStringToken2(line, ",", 5)))
				level.speed.insert(val(GetStringToken2(line, ",", 6)))																				
			endcase			
			case "img"
				images.insertsorted(LoadLevelImage(line))
			endcase
			case "obj"
				level.objs.insertsorted(LoadLevelObject(folder, line, images))
			endcase
			case "clone"
				obj = level.objs[level.objs.find(GetStringToken2(line, ",", 2))]				
				clone = obj
				clone.name = GetStringToken2(line, ",", 1)
				clone.id = CloneObject(obj.id)
				level.objs.insertsorted(clone)
			endcase			
			case "pos"
				obj = level.objs[level.objs.find(GetStringToken2(line, ",", 1))]
				p.x = ValFloat(GetStringToken2(line, ",", 2)) * TRACK_SCALE
				p.y = ValFloat(GetStringToken2(line, ",", 3)) * TRACK_SCALE
				p.z = -ValFloat(GetStringToken2(line, ",", 4)) * TRACK_SCALE							
				SetObjectPosition(obj.id, p.x, p.y, p.z)
				RotateObjectLocalY(obj.id, ValFloat(GetStringToken2(line, ",", 5)))
			endcase
			case "", "#"
			endcase
			case default
				Message("Invalid token("+typ+")")
			endcase
		endselect
	until FileEOF(f)
	
	CloseFile(f)
	
	
	
	level.start.obj = level.objs[level.objs.find("start")]

	id = CreateObjectPlane(.5, .5)
	SetObjectPosition(id, GetObjectMeshSizeMinX(level.start.obj.id, 1) , 0, 0)
	FixObjectToObject(id, level.start.obj.id)
	level.start.line.f = GetObjectPos(id)
	level.start.line.f.y = GetObjectY(level.start.obj.id) - GetObjectHeight(level.start.obj.id) * 0.5
	DeleteObject(id)

	id = CreateObjectPlane(.5, .5)
	SetObjectPosition(id, GetObjectMeshSizeMaxX(level.start.obj.id, 1) , 0, 0)
	FixObjectToObject(id, level.start.obj.id)
	level.start.line.t = GetObjectPos(id)
	level.start.line.t.y = GetObjectY(level.start.obj.id) - GetObjectHeight(level.start.obj.id) * 0.5
	DeleteObject(id)
	
	level.ground = level.objs[level.objs.find("ground")]
	SetObjectDepthBias(level.ground.id, -4 ) 	
	
	i = level.objs.find("grass")
	if i <> -1	
		level.grass = level.objs[i]
	endif
	level.walls = level.objs[level.objs.find("walls1")]
	i = level.objs.find("bridge")
	if i <> -1
		level.bridge = level.objs[i]	
	endif
	
//	level.vm = level.objs[level.objs.find("vm")]		

	level.lights.obj = level.objs[level.objs.find("lights")]
	SetObjectColor(level.lights.obj.id, 0xff, 0, 0, 0xff)
	SetObjectColorEmissive( level.lights.obj.id, 0xff, 0, 0)
	SetObjectLightMap(level.lights.obj.id, 0)
	level.objs.insertsorted(level.lights.obj)
	level.lights.mode = LIGHTS_DONE
		
	for i=1 to 10
		s = folder+"light"+str(i)+".3ds"
		if GetFileExists(s)
			obj.id = LoadObject(s)	
			w = GetObjectWidth(obj.id)
			p = MultiplyPoint(GetObjectMeshPosition(obj.id), TRACK_SCALE)
			DeleteObject(obj.id)
			CreatePointLight(i, p.x, p.y, p.z, w * 2 * TRACK_SCALE, 0x32, 0x2A, 0x66)		// #FF8eFF #AD69F3 #0D0B1A #322A66
			SetPointLightMode(i, 1)	
		endif
	next	
				
	// 2D imagess
	level.map.id = CreateSprite(LoadImage(folder+left(folder, len(folder)-1)+".png"))
	SetSpritePosition(level.map.id, 64 - GetSpriteWidth(level.map.id),  0)
	SetSpriteOffset(level.map.id, 0, 0)		
	SetSpriteDepth(level.map.id, 100)
	level.map.scale.x = GetSpriteWidth(level.map.id) / GetObjectWidth(level.walls.id) 
	level.map.scale.z = GetSpriteHeight(level.map.id) / GetObjectDepth(level.walls.id) 	
	
	level.map.offset.x = GetObjectX(level.walls.id) - ( GetObjectMeshSizeMaxX(level.walls.id, 1) - GetObjectMeshSizeMinX(level.walls.id, 1)) / 2
	level.map.offset.z = GetObjectZ(level.walls.id) - ( GetObjectMeshSizeMaxZ(level.walls.id, 1) - GetObjectMeshSizeMinZ(level.walls.id, 1)) / 2
	
	// Text
	e.msg = CreateText("")
	SetTextSize(e.msg, 24)
	SetTextPosition(e.msg, 0, GetVirtualHeight() - GetTextTotalHeight(e.msg))

	// 	#62AEF9 Matches colour at the top of the background.png image
	SetClearColor(0x95, 0xb4, 0xd6) // 3C8CD5 95B4D6
	ClearScreen()
				
	level.folder = folder
		
	gPaths.length = -1	
	gFollow = newFollow
	LoadPaths(folder, e, level)

	gPickups.length = -1	
	LoadPickups(e)

	gCoins = newPath
	LoadCoins(e)	
	
	gBoosts = newPath
	LoadBoosts(e)

endfunction level

function LoadLevelObject(folder as string, line as string, images	as tLevelImage[])
	obj		as tObject
	img		as integer
	name	as string
	i		as integer	
	
	obj.name = GetFileName(GetStringToken2(line,",",1))
	
	if FindStringCount( GetStringToken2(line,",",1), "/" ) 
		obj.id = LoadObject(GetStringToken2(line,",",1))
	else
		obj.id = LoadObject(folder+GetStringToken2(line,",",1))
	endif
	
	SetObjectScalePermanent(obj.id, TRACK_SCALE, TRACK_SCALE, TRACK_SCALE)
	
	name = GetStringToken2(line,",",2)
	
	if name <> ""
		i = images.find(name)
		if i = -1
			Message("Cannot find texture ("+name+")")
		endif
		
		obj.image = images[i].id
		SetObjectImage(obj.id, obj.image, 1)		
	endif

	select GetStringToken2(line,",",3)
		case "none"
			SetObjectCastShadow(obj.id, 0)									
			SetObjectReceiveShadow(obj.id, 0)
		endcase
		case "receive"
			SetObjectReceiveShadow(obj.id, 1)
			SetObjectCastShadow(obj.id, 0)			
		endcase
		case "cast"
			SetObjectCastShadow(obj.id, 1)									
			SetObjectReceiveShadow(obj.id, 0)
		endcase
		case "both"
			SetObjectCastShadow(obj.id, 1)									
			SetObjectReceiveShadow(obj.id, 1)
		endcase
		case default
			Message("Invalid shadow token ("+GetStringToken2(line,",",3)+")")
		endcase
	endselect			

	select GetStringToken2(line,",",4)
		case "physics"
			obj.physics = TRUE
			Create3DPhysicsStaticBody(obj.id)
			SetObjectShapeStaticPolygon(obj.id)
		endcase
		case "nophysics"
		endcase
		case default
			Message("Invalid physics token ("+GetStringToken2(line,",",4)+")")
		endcase		
	endselect			

	select GetStringToken2(line,",",5)
		case "light"
			SetObjectLightMode(obj.id, 1)
		endcase
		case "nolight"
			SetObjectLightMode(obj.id, 0)			
		endcase
		case default
			Message("Invalid light token ("+GetStringToken2(line,",",5)+")")
		endcase		
	endselect			

	select GetStringToken2(line,",",6)
		case "transparent"
			SetObjectTransparency(obj.id, 1)
		endcase
		case "notransparent"
			SetObjectTransparency(obj.id, 0)
		endcase
		case default
			Message("Invalid transparent token ("+GetStringToken2(line,",",6)+")")
		endcase		
	endselect			
	
	select GetStringToken2(line,",",7)
		case "visible"
			SetObjectVisible(obj.id, 1)
		endcase
		case "invisible"
			SetObjectVisible(obj.id, 0)
		endcase
		case default
			Message("Invalid visible token ("+GetStringToken2(line,",",7)+")")
		endcase		
	endselect			
	
	
	CenterObject(obj.id)

endfunction obj
				
function LoadLevelImage(line as string)
	image as tLevelImage
	name as string
	
	name = GetStringToken2(line,",",1)
	image.name = GetFileName(name)
	image.id = LoadImage(name)
	SetImageWrapU(image.id, Val(GetStringToken2(line,",",2)))
	SetImageWrapV(image.id, Val(GetStringToken2(line,",",3)))
endfunction image

function GetFileName(name as string)
	i as integer
	
	for i=len(name) to 1 step -1
		if mid(name,i,1) = "/"
			exit
		endif
	next
	
	inc i
	name = mid(name,i,-1)
	
	for i=1 to len(name)
		if mid(name,i,1) = "."
			exit
		endif
	next
	
	dec i
	name = mid(name,1, i)
endfunction	name


function DestroyLevel(env as tEnvironment, level as tLevel)
	i as integer
	for i=0 to level.objs.length
		if level.objs[i].physics = TRUE
			Delete3DPhysicsBody(level.objs[i].id)
		endif
		DestroyObjectAndTexture(level.objs[i])
	next

	level.objs.length = -1
			
	for i=0 to gTweens.length
		DeleteTweenChain(gTweens[i].chain)
		DeleteTween(gTweens[i].tweens[0])
		DeleteTween(gTweens[i].tweens[1])				
	next
	
	gTweens.length = -1
	
	for i=0 to gVehicles.length
		DeleteVehicle(gvehicles[i])
	next
	
	gVehicles.length = -1
	
	for i=0 to gCoins.nodes.length
		DeleteObject(gCoins.nodes[i].id)
	next
		
	gCoins.nodes.length = -1
	
	for i=0 to gPickups.length
		DeleteObject(gPickups[i])
	next
		
	gPickups.length = -1
	
	DestroySprite(level.map.id)
	
	for i=1 to 10
		if GetPointLightExists(i)
			DeletePointLight(i)
		endif
	next
	
	gPaths.length = -1
	
	gGrid.cells.length = -1
	
	SetSpriteVisible(env.stop.id, 0)
	env.stop.time = 0	
endfunction
