// File: Path.agc
// Created: 20-04-07


#constant NODE_FAST		0
#constant NODE_SLOW		1

#constant TURN_RIGHT		1
#constant TURN_LEFT		2

type tNode
	id				as integer
	pos				as tPoint
	turn			as integer
	count			as integer
	slots			as tPoint[]
endtype

type tFNode
	laps			as integer[]
	pos				as tPoint
	grounded			as integer
endtype

type tFollow
	current			as integer
	nodes			as tFNode[]
endtype


type tPath
	name			as string
	colour			as color
	current			as integer
	nodes			as tNode[]
endtype

type tLoadPath
	name			as string
	colour			as color
	nodes			as tPoint[]
endtype

global gPaths		as tPath[]
global gFollow		as tFollow

type tCell
	coins			as integer[]
	pickups			as tPickup[]
	boost			as integer
endtype

type tGrid
	offset			as tPoint
	cells			as tCell[-1,-1,-1]
endtype 

global gGrid		as tGrid

function GetPathStart(vehicle as tVehicle)
endfunction vehicle.path.nodes[0].pos

function GetPathPoint(vehicle as tVehicle, node as integer)
	p 			as tPoint
	nextPath	as tPath
	
	if node <= vehicle.path.nodes.length
		if node < 0 
			p = vehicle.path.nodes[vehicle.path.nodes.length].pos
		elseif node > vehicle.path.nodes.length
			if vehicle.path.name <> "path"
				nextPath = FindPathByName("path")
				p = nextPath.nodes[0].pos
			else
				p = vehicle.path.nodes[0].pos
			endif
		else
			p = vehicle.path.nodes[node].pos			
		endif
	endif
endfunction p

function GetPathColour(path as tPath)
endfunction path.colour

function	GetNextNode(vehicle ref as tVehicle)
	p	 	as tPoint
	node		as tNode

	if DEBUG
		node = vehicle.path.nodes[vehicle.path.current]
			
		if GetObjectExists(node.id)
			SetObjectScale(node.id, 1, 1, 1)
			SetObjectColor(node.id, 0xff, 0xfd, 0xff, 0xff)
		endif
	endif
	
	inc vehicle.path.current
	
	if vehicle.path.current > vehicle.path.nodes.length
		if vehicle.path.name <> "path"
			vehicle.path = FindPathByName("path")
		endif
		vehicle.path.current = 0
	endif
	
	if DEBUG
		if GetObjectExists(node.id)		
			SetObjectScale(node.id, 3, 3, 3)		
			SetObjectColor(node.id, vehicle.path.colour.r, vehicle.path.colour.g, vehicle.path.colour.b, 0xff)	
		endif
	endif

	p = vehicle.path.nodes[vehicle.path.current].pos

endfunction	p

function GetPathNode(vehicle as tVehicle, node as integer)
	if node < 0
		node = vehicle.path.nodes.length
	endif
	if node > vehicle.path.nodes.length
		node = 0
	endif	
endfunction vehicle.path.nodes[node]

function GetPathCurrentIndex(vehicle as tVehicle)
endfunction vehicle.path.current

function GetPathCurrentPoint(vehicle as tVehicle)
	p as tPoint
	p = vehicle.path.nodes[vehicle.path.current].pos
endfunction p

type	tTile
	name 	as string
	pos		as tPoint
	angle	as integer
endtype

function LoadPaths(folder as string, env ref as tEnvironment, level ref as tLevel)
	i 		as integer
	x		as integer
	z		as integer	
	y		as integer		
	id 		as integer	
	f 		as tLoadPath
	t		as tPath
	l		as tPath
	p		as tPoint
	w		as tPoint
	n 		as integer
	node 	as tNode
	newNode	as tNode
	tiles	as tTile[]
	tile	as tTile
	lPaths	as tLoadPath[]
	xd		as integer
	zd		as integer
	nxt		as tPoint
	fnode1	as tFNode
	fNode2	as tFNode
	size	as tPoint
	
		
	tiles.load(folder+"level.trk")
	
	gGrid.offset.x = 99999999
	gGrid.offset.z = 99999999
	gGrid.offset.y = 99999999
	
	w.x = -99999999
	w.z = -99999999
	w.y = -99999999	
	
	for i=0 to tiles.length
		tile = tiles[i]
		
		tile.pos.x = round(tile.pos.x / 4)
		tile.pos.z = round(tile.pos.z / 4)		
		
		if tile.pos.x < gGrid.offset.x
			gGrid.offset.x = tile.pos.x
		endif

		if tile.pos.y < gGrid.offset.y
			gGrid.offset.y = tile.pos.y
		endif
				
		if tile.pos.z < gGrid.offset.z
			gGrid.offset.z = tile.pos.z
		endif
		
		if tile.pos.x > w.x
			w.x = tile.pos.x
		endif
		
		if tile.pos.y > w.y
			w.y = tile.pos.y
		endif
		
		if tile.pos.z > w.z
			w.z = tile.pos.z
		endif
		
	next
	
	size.x = abs(w.x - gGrid.offset.x)
	size.z = abs(w.z - gGrid.offset.z)	
	size.y = abs(w.y - gGrid.offset.y)		

	gGrid.cells.length = round(size.z)
	
	for z=0 to size.z
		gGrid.cells[z].length = round(size.x)
		for x=0 to size.x
			gGrid.cells[z, x].length = round(size.y)
		next
	next	
		
	lPaths.load(folder+"level.pth")
		
	for i=0 to lPaths.length
		f = lPaths[i]
		
		t.name = f.name
		t.colour = f.colour
		t.nodes.length = -1
		
		for n=0 to f.nodes.length
			p = f.nodes[n]
			
			node = newNode
			
			if t.name = "path" 
				xd = p.x / abs(p.x) * 2
				zd = p.z / abs(p.z) * 2				
				
				w.x = round(round(p.x + xd) / 4) * 4
				w.z = round(round(p.z + zd) / 4) * 4	
							
				for x=0 to tiles.length
					tile = tiles[x]
					if tile.name <> "turn"
						continue
					endif
					if 	w.x = tile.pos.x and w.z = tile.pos.z 
						if  round(p.y) = round(tile.pos.y)
							node.turn = FindDirection(f, n, tile, node)
						endif
					endif
				next
				
				if node.slots.length < 0
					Message("Invalid path node ("+str(n)+")")
					node.turn = node.turn
				endif
				
			endif
			
			node.pos.x = p.x * MAP_SCALE_X * TRACK_SCALE
			node.pos.y = p.y * MAP_SCALE_Y * TRACK_SCALE
			node.pos.z = p.z * MAP_SCALE_Z * TRACK_SCALE						
			
			if DEBUG
				if t.name = "path"
					for x=0 to node.slots.length
						node.id = CreateObjectBox(80, 80, 80)
						SetObjectPosition(node.id, node.slots[x].x, node.slots[x].y, node.slots[x].z) 
						SetObjectColor(node.id, lPaths[x].colour.r,  lPaths[x].colour.g, lPaths[x].colour.b, 0xff)
					next
				endif
			endif
			
			t.nodes.insert(node)
		next
		
		if t.name = "follow"
			l = t
		else
			gPaths.insert(t)
		endif
	next
/*	
	id = CreateObjectSphere(50, 8, 8)
	SetObjectColor(id, 0xff, 0, 0, 0xff)
	SetObjectPos(id, l.nodes[0].pos)
	*/
	
	for i=0 to l.nodes.length
		fnode1.pos = l.nodes[i].pos
		fnode1.laps.length = 5
		fnode1.grounded = TRUE
		gFollow.nodes.insert(fnode1)
				
				/*
		if i < l.nodes.length
			fnode2.pos = l.nodes[i + 1].pos
			fnode2.grounded = FALSE
			fnode2.laps.length = 5			
			fnode2.pos.x = fnode1.pos.x + (fnode2.pos.x - fnode1.pos.x) / 2
			fnode2.pos.y = fnode1.pos.y + (fnode2.pos.y - fnode1.pos.y) / 2
			fnode2.pos.z = fnode1.pos.z + (fnode2.pos.z - fnode1.pos.z) / 2 	
			gFollow.nodes.insert(fnode2)
		endif
		*/
	next

endfunction

function FindDirection(path ref as tLoadPath, t as integer, tile as tTile, n ref as tNode)
	f 		as integer
	v 		as tPoint
	turn	as integer
	i		as float
	fp		as tPoint
	tp		as tPoint
	s		as tPoint
	stp		as tPoint
	p		as tPoint
	st		as float
	start	as float
	
	start = 1.4
	st = 3.5 / 8
	
	f = t - 1
	
	if f < 0
		f = path.nodes.length
	endif
	
	fp = path.nodes[f]
	tp = path.nodes[t]
	
	v.x = tp.x - fp.x
	v.z = tp.z - fp.z	
	
	if abs(v.x) > abs(v.z)
		
		select tile.angle
			case 180
				p.z = tile.pos.z + start : stp.z = -st
				p.x = tile.pos.x - start : stp.x = st								
				turn = -1
			endcase
			case 0
				p.z = tile.pos.z - start : stp.z = st			
				p.x = tile.pos.x + start : stp.x = -st								
				turn = -1
			endcase
			case 90
				p.z = tile.pos.z - start : stp.z = st
				p.x = tile.pos.x - start : stp.x = st								
				turn = 1			
			endcase
			case 270
				p.z = tile.pos.z + start : stp.z = -st
				p.x = tile.pos.x + start : stp.x = -st								
				turn = 1			
			endcase
			case default
				p.z = tile.pos.z + start : stp.z = -st
				p.x = tile.pos.x - start : stp.x = st								
				turn = 1			
			endcase
		endselect
		
		for i=0 to 4
			s.z = p.z * MAP_SCALE_Z * TRACK_SCALE
			s.x = p.x * MAP_SCALE_X * TRACK_SCALE			
			s.y = tile.pos.y * MAP_SCALE_Y * TRACK_SCALE	
			n.slots.insert(s)
			p.z = p.z + stp.z
			p.x = p.x + stp.x			
		next				
	else
		
		select tile.angle
			case 180
				p.x = tile.pos.x - start : stp.x = st				
				p.z = tile.pos.z + start : stp.z = -st
				turn = 1
			endcase
			case 0
				p.x = tile.pos.x + start : stp.x = -st				
				p.z = tile.pos.z - start : stp.z = st
				turn = 1
			endcase
			case 270
				p.x = tile.pos.x + start : stp.x = -st				
				p.z = tile.pos.z + start : stp.z = -st			
				turn = -1	
			endcase
			case 90
				p.x = tile.pos.x - start : stp.x = st	
				p.z = tile.pos.z - start : stp.z = st
				turn = -1			
			endcase			
			case default
				p.x = tile.pos.x - start : stp.x = st	
				p.z = tile.pos.z - start : stp.z = st
				turn = -1			
			endcase
		endselect		
		
		for i=0 to 4
			s.x = p.x * MAP_SCALE_X * TRACK_SCALE
			s.z = p.z * MAP_SCALE_Z * TRACK_SCALE
			s.y = tile.pos.y * MAP_SCALE_Y * TRACK_SCALE	
			n.slots.insert(s)
			p.x = p.x + stp.x			
			p.z = p.z + stp.z						
		next						
	endif	
			
endfunction turn

function FindPathByName(name as string)
	i as integer
	p as tPath
	
	for i=0 to gPaths.length
		p = gPaths[i]
		if p.name = name
			exitfunction p
		endif
	next
	
	p.name = "bad"
		
endfunction p