Trinity3D Open Source

BlitzMax Forums/BlitzMax Programming/Trinity3D Open Source

this is not a part of the official release, but here goes.

(nick it and you will pay a great consequence.(I'll send the boys round :) )
Global MainEng:TEngine
Global camList:TList
Include "tactics.bmx"
Include "col.bmx"
Include "rscript.bmx"
Global BallCam:TCamera
Global RViewMode
Global ActiveBot:Bot
Global TrackBot:Bot
Global TotFps,AcFps,Frames,LastM

Const FPS=30
Global Display:TBatch = New TBatch 'Spawn batch visualizer.
Local Why:String
Global period=1000/FPS
Global time=MilliSecs()-period
Global Arena:Level = Null 
Team.Init()
Global MainBall:Ball = New Ball
bot.bots = CreateList()
bot.botlist = CreateList()
bot.activeBots = CreateList()
inf.Init()
Global Visual:TBatch = New TBatch
Team.Visuals = Visual
registerFuncs(rifas)
	Global Sun:TLight
	Global TopLight:TLight

	'Basic Shadow Information. 
	Global bShadow:TEntity[255]
	Global BallMark:TEntity
	Global ActiveMark:TEntity
	rifas.addfunc(setuprifa,"InitRifa")
Function SetUpRifa:Int(ls:Byte Ptr)
	bShadow[0] = TFileIo.LoadEntity("media\roboshadow.b3d")
	If bShadow[0] = Null Throw "Roboshadow.b3d not found."
	bShadow[0].UsePipeline( New TVertexArray )
	TopLight:TLight = New TLight
	TopLight.Y=300
	TopLight.Diffuse(50,255,255,1)
	TopLight.Sync()
	SetUpSun()


	ActiveMark:TEntity = TFileIO.LoadEntity("Media\RoboBase.b3d")
	ActiveMark.UsePipeline(New TVertexArray)
	BallMark:TEntity = New TEntity
	TEntity.Clone( ActiveMark,BallMark ) 'Return of Clone strikes back.
	ballCam = New Tcamera
	ballCam.Viewport(20,20,200,200)
	
End Function


Global oMark:TEntity[50000],oCount


rifas.Load("Script\config.txt")
rifas.Run()

If MainEng = Null Throw "Environment script must create main engine context"
Main_Error.failOn( 505090909)

Function fprint(txt:String)
	WriteLine debugStream,txt
End Function
'Main_Error.printFunction( fprint )
Global debugStream:TStream = WriteFile( "Debug.Txt" )

Type Level
	Field colMap:Tentity
	Function Load:Level(File:String)
		Out:Level = New Level
		fPath:String = ExtractDir( file)
		Out.Mesh = TFileIo.LoadEntity( File)
		out.colmap =tfileIo.loadentity(fPath+"/"+StripAll(File)+"_col.b3d")
		If out.colmap = Null Throw "Col map "+fPath+"! not fond"
		out.colmap.updatenormals()
		
		
		If out.colmap=Null Throw "Collision map not found"
		TGame.AddStatic( Out.colmap )	
		Out.Mesh.UsePipeline( New TVertexArray )
		Local nFile:String = fPath+"/"+StripAll(File)+"_ai.b3d"
		Out.AiMap = TFileIo.LoadEntity(NFile)
		Out.AiMap.UsePipeline( New TVertexArray )	
		If Out.Mesh = Null Throw "Could not open level file :"+File
		If Out.AiMap = Null Throw "Could not open ai map file :"+File
		out.nodeMap = out.aimap
		Map:TEntity =TEntity( Out.AiMap.GetChild(1))
		'Map:TEntity = out.AiMap
		If Map = Null
			Throw "Ai map does not contain a _ai tagged node. File:"+File
		EndIf
		Map.UpdateNormals()
		Out.AiMap = Map
		Map.AddMaterial( New TMaterial )
		Map.ScaleMesh( 1,1,-1 )
		Tactic.FindNodes( Out.NodeMap )
		
		'Map.UsePipeline( New TVertexArray )
		Visual.AddEntity( Out.Mesh )
		Visual.AddEntity( ActiveMark )
		Visual.AddEntity( BallMark )
		Return Out
	End Function
	
	'Ai map specific
	Field nodeMap:TEntity
	'end ai map
	
	Method Render()
		If Mesh = Null Throw "mesh not present in level data"
'		vCam.RenderEntity( Mesh )
	'	vcam.renderentity( aimap )
	End Method
	Field Mesh:TEntity
	Field Col:TEntity
	Field AiMap:TEntity
End Type

Type Team
	Function init()
		aTeam = New Team[25]
	End Function

	Field Tact:Tactic	

	Function UseTactics(Tea:Team,Id:String)
	
		Tea.Tact = Tactic.GetTactics( Id )
			
	End Function
		
	Function Create:Team(Name:String,Nick:String)
		Local Out:Team = New Team
		Out.Name = Name
		aTeam[teamcount]=out
		out.nick = nick
		out.TeamID = teamCount
		teamcount:+1
		out.tact = New Tactic
		out.bots =CreateList()
		Return out
	End Function
	Field TeamID:Byte
	
	Method AddBot:Bot(BotType:String,PlayerName:String="",Posi:String="")
		Master:Bot = Bot.FindMaster( BotType )
		If Master = Null
			Bot.LoadBotType( BotType )
			Master = Bot.FindMaster( BotType )
			If Master = Null Throw "Cannot add bot of non existent bot type "+BotType+" For player "+PlayerName
		EndIf
		TBot:Bot = Bot.Spawn( Master,Team( Self ),PlayerName )
		ListAddLast Bots,tBot
		NewId=TeamId+1
		Local APos:String = Posi+NewId
		Print "Bot team>"+name+" Team Pos Node>"+Apos
		tbot.zone = tactic.addPosition( tact,apos )
		If tbot.zone = Null
			RuntimeError "Position "+Apos+" Not valid"
		EndIf

		tbot.x=tbot.zone.x
		tbot.z=tbot.zone.z
			
		Return tBot	
	End Method
	
	Method Sync()
		For TBot:Bot = EachIn Bots
			Visuals.AddEntity( Tbot )
		Next
	End Method
	
	Global Visuals:TBatch
	
	Function reset()
		teamcount=0
	End Function
	
	Field Name:String
	Field nick:String 'nickname.
	Field Played:Int,Won:Int,Drawn:Int,Lost:Int
	Field MetalGhosts:Int
	Field Bots:TList
	Field Money:Int 
	Global aTeam:Team[]
	Global TeamCount
End Type

'eam.Init(
Type Ball
	Method New()
		Drag= 0.98
		Bounce = 0.66
		Friction = 0.93
	End Method
	
	Method Render()
'			vCam.RenderEntity( Mesh)
'			Vcam.RenderEntity( BallMark )
	End Method
	
	Method Kick(Xf!,Yf!,zF!)
		Xi=xi+Xf
		yi=yi+yf
		zi=zi+zf
	End Method
	Method Undo()
		Mesh.X = OldX
		Mesh.Z = OldZ
		Mesh.Y = OldY	
	End Method
	Field oldx!,oldy!,oldz!
	Method push( fx!,fy!,fz! )
		xi = fx
		yi =fy
		zi= fz
	End Method
	Method Give( Now:Tentity )
		has = Now
	End Method
	Field Has:TEntity
	Method MoldBall( Mold:TEntity, Base:TEntity )
		Local xd! = mesh.x-oldx
		Local yd! = mesh.y-oldy
		Local zd! = mesh.z-oldz
		xd=0-xd
		yd=0-yd
		zd=0-zd
		surfI=0
		For surf:Tsurface = EachIn base.surface
			Local mSurf:Tsurface= tSurface(mold.surface.valueatindex(surfI))
			For vertI=0 To surf.verts.length-6 Step 3
				x! = surf.verts[verti]
				y! = surf.verts[vertI+1]
				z! = surf.verts[vertI+2]
				
				xv! = xd-x
				yv! = yd-y
				zv! = zd-z
												
				msurf.verts[vertI]=x+xv
				msurf.verts[vertI+1]=y+yv
				msurf.verts[vertI+2]=z+zv '+Sin(y*200)*3
			Next
			msurf.pipeline.sync()
			surfI:+1
		Next
		eInd=0
		For tent:tentity = EachIn mold.pchild
			sent:tentity = tentity(base.pchild.valueatindex( eInd ))
			moldball( tent,sent) 
			eind:+1
		Next
		
		
	End Method
	
	Method update()
		Local Profile=Profiler.Enter("Update")
		'moldBall(Mesh,ballmod )
		
		'	oldX=mesh.x
		'	oldY=mesh.y
		'	oldZ=mesh.Z
		'	MoldBall( Mesh,BallMod )
		
		If Yi>-2 Yi:-0.1


		Local nx!,ny!,nz!
		Nx=Mesh.X+Xi
		Ny=Mesh.Y+yi
		Nz=Mesh.Z+zi
'	     Yi:-0.3
		
		Local Width!=350,Depth!=340,Height!=40
		
		If mesh.y<2.1
		Xi:*Friction
		ZI:*Friction
		EndIf


'		Yi:-0.2
'		If yi>2 yi=2
'		If yi<-2 yi=-2
		

		If ny<=2 
			yI=Abs( yi)*Bounce
			If YI<(Weight*8)
				Yi=0
				Mesh.Y = 2
			EndIf
			Ny = Mesh.Y
		EndIf
'		If Ny>50
'			Ny = Mesh.Y
'			Yi=-Abs(YI)
'		EndIf

						
	'	If Nx<-Depth
	'		Xi=Abs(XI)*Bounce
	'		Nx=Mesh.X
	'	Else If Nx>Depth
	'		NX=Mesh.X
	'		Xi=-Abs(XI)*Bounce
	'	EndIf
		
	'	If Nz<-Width
	'		Zi=Abs(Zi)*Bounce
	'		Nz=Mesh.Z
	'	Else If nz>Width
	'		Zi=-Abs(zi)*Bounce
	'		Nz=Mesh.Z
	'	EndIf
		BallYaw! = ATan2( zi*4,xi*4)
		If Sqr(zi*zi+xi*xi)>0.1
			BallMark.Rotate( 0,BallYaw,0 )
		EndIf
		BallMark.X = Mesh.X
		BallMark.Z = Mesh.Z
		Mesh.X = Nx
		Mesh.Y = Ny
		Mesh.Z = Nz	
		FlushMem
		If has=Null
		Else
		EndIf
		LeaveFunction( Profile )
	End Method
	Field lx!,lz!
	Field Bounce:Double
	Field Friction:Double
	Field Mesh:TEntity,drag:Double
	Field XI:Double,YI:Double,ZI:Double
End Type

Type Bot Extends TEntity 
	Global IDC:Short
	Field Id:Short
	Field InfM:Inf
	
	
	Global BotPath:String
	Global BotList:TList
	Function register(botType:String)
		ListAddLast botList,botType
	End Function
	
	Field Zone:Position
	
	Function LoadBotType:Byte( BotType:String )
		'For check:String =EachIn botlist
		'	check= check.tolower()
		'	If botType = check
	Print "Loading Bot Type"+BotTYpe
				Local Temp:REngine = New REngine
				registerFuncs( temp)
				temp.load("Bot/"+botType+"/setup.txt")
				Print "About to run bot initilization"
				temp.run()
				Print "Run ok"
				
		'		Print "Load type "+BotType
				Return True
		'	EndIf
		'Next
	End Function
	
	Function getBot:Bot(num:Int)
		Return bot(activebots.valueatindex( num ))
	End Function
	
	
	Method New()
		InfM = Inf.Create(0,0,0,-500,0,30,Bot.Idc)
		Bot.Idc:+1
		Id = bot.idc-1
		Active = False 
		TurnSpeed = 0.1
		Brain = IAL.Create( Bot(Self) )
		'active = True
		BasicShadow = New TEntity
		TEntity.Clone( bShadow[0],BasicShadow) 
		Visual.AddEntity(BasicShadow)
		
		'	Display.AddEntity(BasicShadow)

	End Method
	Function SetName( in:Bot,nName:String )
		in.name = nname
	End Function
	
	Function getName:String( in:bot )
		Return in.name
	End Function
	
	
	Field BasicShadow:TEntity
	Method Place( nX!,nY!,nZ!)
		x=nx
		y=ny
		z=nz
	End Method
		
	Function FindMaster:Bot( Name:String)
		Name = Name.ToLower()
		For tBot:Bot = EachIn Bots
			Local TName:String = tBot.name.tolower()
			If tname.find( name)<>-1 Return tBot			
		Next
		Return Null
	End Function
		
	Function Load:Bot(File:String)
	

		Local Out:Bot
		Print "Loading base bot "+File
		If FileSize(file)<5 RuntimeError file
	'	Throw "Entity::"+file
		Local Tmp:Tentity = TFileIo.LoadEntity( File )
		If tmp = Null Throw "Unable to Load Bot:"+File
		Out = New Bot
		Local Nu:TEntity 
		Nu = TEntity( out )
		Tmp.Parent( TEntity( Out) )	
		Out.UsePipeline( New TVertexArray )
		ListAddLast Bot.Bots,Out
'		Visual.AddEntity(Out)
		TGame.AddSphere( Out,15,0,20,0)
		Return Out
		
	End Function
	
	Function Spawn:Bot( From:Bot,Owner:Team,bName:String)
		
		Local Out:Bot
		?debug
		If From = Null Throw "Cannot clone nulality."
		?
		Out =  New Bot
Print "Spawning "+From.Name+" Bot"
		TEntity.Clone( From,Out )
		Out.Name = bName
		out.localcache = from.localCache
		out.place( Rnd(-50,50),0,Rnd(-50,50))
		ListAddLast Bot.ActiveBots,Out
		'Display.AddEntity( Out )
		
		Visual.AddEntity( Out )
		Return Out
	
	End Function
			
	Function RenderActive()
		For Local TmpBot:Bot = EachIn ActiveBots
'			Vcam.RenderEntity( TmpBot )
'			vCam.RenderEntity( tmpBot.basicshadow )
		Next
		
'	''''	Vcam.RenderEntity( ActiveMark )
	End Function
	
	Function SpawnBot:Bot( Name:String)
		
	End Function
	
	Method FindNear()
		
	End Method
	Field control:Byte
	Method Update()
		Local Mx:Double,My:Double
		InfM.x=x
		infm.y=y
		infm.z=z
		If Active=True
			
				ActiveMark.X = X
				ActiveMark.Y = 1
				ActiveMark.Z = Z
				ActiveMark.Rotate(0,Yaw,0) 
				
				'Keyboard
				Select control
				Case 1
					mx=JoyX()
					my=JoyY()
				Case 0
				If KeyDown(KEY_A)
					my=-1
				EndIf
				If KeyDown(KEY_S)
					Mx=-1
				EndIf
				If KeyDown(KEY_D)
					My=1
				End If
				If KeyDown(KEY_W)
					mx=1
				EndIf
				'Joypad
				End Select
		Else
			Brain.Cycle( mx,my )
		EndIf	
		Mx:*0.8
		My:*0.8
		Local Mag! = Sqr(Mx*mx+My*my)
		
		If mag>0.2
			aYaw:Double = ATan2(my*10,mx*10)
			If aYaw<0 aYaw:+360
		EndIf
		
		Lean! = Sqr( Xi*Xi+Zi*zi) * 40
		pback! = -xi*8.6
		oback! = zi*8.6
	'	If oback<-30 oback=-30
		'If oback>30 oback=30
			
	'	EndIf
	'pback:+ joyz()*40
	'oback:+ -joyv()*40
	
			
			
			
		If Yaw<aYaw
		D1! = aYaw-Yaw
		D2! = Yaw+(360-aYaw)
		If D2>D1
			Rotate(pback,Yaw+(aYaw-Yaw)*TurnSpeed,oback)
		Else
			Rotate(pBack,Yaw-D2*TurnSpeed,oback)
		EndIf
		Else
		D1! = Yaw-aYaw
		D2! = aYaw+(360-Yaw)
		If D2>D1
			Rotate(pback,Yaw+(aYaw-Yaw)*TurnSpeed,oback)
		Else
			Rotate(pBack,Yaw+D2*TurnSpeed,oback)
		EndIf
		EndIf
		If Yaw<0 Yaw=360.0+Yaw
		If Yaw>360 Yaw:-360
		'	Move(0,0,Sqr(xi*xi+yi*yi)*0.01)
	
		If Mag>0.05	
			Xi:+My*0.2
			Zi:+Mx*0.2
		EndIf
		
		XI:*0.96
		Zi:*0.96
		
		If Sqr( xi*xi+zi*zi)>0.05
			Z:+Xi
			X:+Zi
	
		EndIf
		BasicShadow.X = X
		BasicShadow.Z = Z
		basicshadow.y=2			
	End Method
		
	Function UpdateAll()
		For B:Bot = EachIn ActiveBots
			B.Update()
			Xd! = B.X - MainBall.Mesh.x
			Zd! = B.Z - MainBall.Mesh.Z
			'yd! = (B.Y) - MainBall.Mesh.Y
			
			Dis! = Sqr(xd*xd+zd*zd)
			If Dis<12
				If Sqr( MainBall.Xi*MainBall.XI+MainBall.Zi*MainBall.ZI)<9
					B.hasBall = True
				EndIf
			EndIf
				
			If B.HasBall=True   'And Dis<8.0+DisMod!
				Ent:TEntity = Tentity( b)
				If KeyDown(KEY_SPACE)
				ImpulseMod!=0.2
				EndIf
				
				tX! = B.X+B.Xi*4
				TZ! = B.z+B.Zi*4
				vx! = tx-mainball.mesh.x
				vz! = tz-mainball.mesh.z
				
				If Sqr(vx*vx+vz*vz)>2			
			
					MainBall.xi:+vx*0.05 '*(0.3+ImpulseMod)
					MainBall.zi:+vz*0.05 '*(0.3+ImpulseMod)
			
				Else
				EndIf
				B.DisMod=4
				
				BallMark.Y =4
				If KeyDown(	Key_Up) Or JoyDown(1)
					If ShotIn=0
					shotin=1
					MainBall.Xi:+Cos(B.Yaw)*4
					MainBall.Yi=Rnd(0,1)
					MainBall.Zi:+Sin(B.Yaw)*4
					B.HasBall=False
					
					EndIf
				Else
					ShotIn = 0
				EndIf
			Else 
				B.DisMod:*0.94
				BallMark.Y=2
			EndIf
			If B.hasBall=True 
				If B.DisMod<0.1 B.hasBall = False
				
			EndIf
		Next
		
	End Function
	Field DisMod!
	Field HasBall:Int
	Field xI!,zi!,shotIn:Byte
	Field aYaw:Double
	Field TeamI:Byte
	Field Mx:Double,My:Double
	Field Face:Double
	Field Active:Byte
	Field Cpu:Short
	Field TurnSpeed:Double
	Field Brain:IAL
	Field LastTri[1000],LastC 'Memory
	Global ActiveBots:TList
	Global Bots:TList
End Type


Type Junction

	Method New()
		Port[0]=-1
	End Method
	Field X!,Y!,Z!
	Field This:Short
	Field Port:Int[25],Cons:Int
	Field Fear:Byte,Attract:Byte
	Field Weight:Float[25]
End Type


Type Path
	
	Method AddWayPoint( Junct:Junction)
		Junc[jc] = Junct
		Jc:+1
	End Method
	
	Method Update()
		If goJunc=Null
			goJunc = Junc[Jc-1]
		EndIf
		
		
	End Method

	Field Owner:Bot		
	Field Junc:Junction[300],Jc
	Field TarJunc:Junction
	Field GoJunc:Junction
	Field PathFind:Byte
	Field GoMode
End Type


Type Inf
	Function init()
	ignoreId=-1
		IList = CreateList()
	End Function
	
	Function Create:inf( X!,Y,Z!,BaseEffect!,Mode=0,Radius=20,id=0)
		Local out:inf = New inf
		out.x=x
		out.id=id
		out.effect=baseeffect
		out.y=y
		out.z=z
		out.radius=radius
		ListAddLast ilist,out
		Return out
	End Function
	Global ignoreId
	Function	ScoreAt:Double(x!,y!,z!,id=0)
		TotScore!=0
		
		For i:Inf = EachIn iList
			If ignoreId=i.id Continue
			xd!=i.x-x
			yd!=i.y-y
			zd!=i.z-z
			td!= Sqr(xd*xd+yd*yd+zd*zd)/i.Radius
			If td<0 td=0
			If td>1 td=1
			td=1-td
			Select i.mode
				Case 0
					score!=i.Effect*td
				
				Case 1
					Throw "Not supported"
			End Select
			TotScore:+Score
		Next
		'If totScore<>0
		'Print "Tot Score>"+TotScore
		'endif
		Return TotScore
	End Function
	Function Reset()
		ClearList iList
		ignoreId0=-1
	End Function
	
	Field id:Short
	Field X!,Y!,Z!
	Field Mode,Radius!
	Field Effect!
	Global IList:TList
End Type
Inf.Init()

Type IAL
	
	Function Create:Ial( Own:Bot )
		Out:Ial = New Ial
		out.owner = own
	'	ial.setupjstar( out,own )
		
		Return out
	End Function
	Function SetUpJStar(out:ial,own:bot)
		Out.Asurf = Arena.AiMap.GetSurface(1)
		Out.Tris = Out.ASurf.Tris
		Out.Verts = Out.aSurf.verts
		Out.TriC = Out.Asurf.Triangles()
		Out.VertC = out.asurf.vertices()
		main_Error.invoke "Ai Map Verts>"+Out.vertC+" Tris>"+Out.TriC
	'	out.junc = New Junction[Out.Verts.length/3]
		out.ResetJunctions()
		Out.Owner = Own
	End Function
	
	Method ResetJunctions()
		Vert=0
		While Vert<Verts.Length/3
			Junc[Vert] = New Junction
			Junc[Vert].This = Vert
			Junc[Vert].X = Verts[Vert*3]
			Junc[Vert].Y = Verts[Vert*3+1]
			Junc[Vert].Z = Verts[Vert*3+2]
			Local Con = 0
			J=0
			While J<Tris.Length
				If Tris[J] = Vert
					Junc[Vert].Port[Con] = Tris[j+1]
					Junc[Vert].Port[Con+1] = Tris[J+2]
					con:+2
				EndIf
				If Tris[J+1] = Vert
					Junc[Vert].port[Con] = Tris[j]
					Junc[Vert].port[con+1] = tris[j+2]
					con:+2
				EndIf
				If Tris[J+2] = Vert
					Junc[vert].port[Con] = Tris[j]
					Junc[Vert].port[con+1] = Tris[j+1]
					con:+2
				EndIf
				
				J:+3
			Wend
			Junc[Vert].Cons = Con
			'Print "Cons>"+Junc[vert].cons
			Vert:+1
		Wend
	End Method
	
	
	Method PlaceNear( X,Y,Z)
		TriI = NearestTri(X,Y,Z)
		Owner.X = TriX
		Owner.Y = TriY
		Owner.Z = TriZ
	End Method
	Method NearTri:Int()
		Return NearestTri( owner.x,owner.y,owner.z)
	End Method
		
	Field lastJUP
	
	Method UpdateJuncs()
		Return
		ms=MilliSecs()
		If ms-lastJup>5
		lastJup=ms
		While J<vertC
			k=0
			junct:junction = junc[j]
			cons = junct.cons
			While k<cons
				junct.weight[k]:*0.93
				k:+1
			Wend
			j:+1
		Wend
		'		Print "Update junctions"
		EndIf
	End Method
	
	Method NetMove:Double( from:Junction,StopAT:Int=10,LastD!=0,Score!=0,Par:Junction=Null)
		bJump!=99999
		If stopAt<0 Return Score
		Local bJunc:Junction
		xd! = from.x-tjunc.x
		zd! = from.z-tjunc.z
		td! = Sqr(xd*xd+zd*zd)
		BigScore!=-9999999
		OrigScore=Score
		Score!:+LastD-Td+Inf.ScoreAt( from.x,from.y,from.z)
		For j=0 To from.cons-1
			
			way:junction = junc[from.port[j]]
			
				
		'	If Way<>From 'Prevent back tracking.
				NewScore! =NetMove( Way,StopAt-1,Td,Score,From)-from.weight[j]	
				'NewScore:-from.weight[j]
				
				If newScore>BigScore
		'			If newScore>Junc
					BigScore=NewScore
					bJunc = Way
					WayI=J
				EndIf
		
		'	EndIf
		Next
		from.weight[wayI]:+bigScore '22
		
	'	Marker(bJunc.x,3,bjunc.z)
		NetJuncOut = bJunc	
		Return Score+BigScore
	
	End Method
	Field NetJuncOut:Junction
	Field TempAng!
	Field AngTurns!,Fear!,Attract!
	Field MovA!
	Field Task,TargetX!,TargetY!,TargetZ!
	Const MoveTo =1,SneakTo=2
	Field LastAng
	Field Been:BSTree
	Method Cycle( MoveX:Double Var,MoveY:Double Var)
		Select Task
			Case IAL.MoveTo
				updateJuncs()	
			'	If aJunc =Null
				 aJunc= JuncNear(owner.x,owner.y,owner.z)
			'	endif
				inf.ignoreId =owner.id
				Xd!=ajunc.x-tjunc.x
				zd!=ajunc.z-tjunc.z
				aDist!=Sqr(xd*xd+zd*zd)
				BestScore!=NetMove(aJunc,2,ADist,0,Null)
								
				xd!=owner.x-tJunc.x
				zd!=owner.z-tJunc.z
				td!=Sqr(Xd*xd+zd*zd)
				gJunc:Junction =NetJuncOut
				If gJunc = Null
					Task = 0
					Return
				EndIf
				If Td<12
			'	Task=0
				Return
					'Print "New Junc"
				'	aJunc = gJunc
				EndIf
				
					
				VertAt = Ajunc.this*3
				Marker( Verts[vertat],5+Cos(locA)*3.5,verts[VertAt+2])
			'	TVert = tJunc.this*3
			'	Marker( Verts[TVert],5+Cos(LocA)*3.5,Verts[tvert+2] )
							
				If gJunc<>Null
					If gJunc=aJunc
					Else
						Xd! = gjunc.x-owner.x
						zd! = gjunc.z-owner.z
						ang! = ATan2(zd,xd)
						td! = Sqr(xd*xd+yd*yd)
						ms! = td/20.0
						If ms>1 ms=1
						If ms<0 ms=0
						ms=1
						ms=1-AngTurns/20
						ms=1
						If ms<0 ms=0
						If ms>0.9 ms=0.9
						movex=Cos(ang)*ms
						movey=Sin(ang)*ms
					EndIf
				EndIf
				LocA:+15
				Return 
		End Select
	End Method
	Field MainPath:Path
	Field TurnMod!
	Method PathCycle( Vert:Int)
		Vert:/3
		Local Star:Int[60],Con:Short
		While J<Tris.Length-1
			If Tris[J] = Vert
				Star[Con] = Tris[j+1]
				Star[Con+1] = Tris[J+2]
				con:+2
			EndIf
			
			If Tris[J+1] = Vert
				Star[Con] = Tris[j]
				Star[con+1] = tris[j+2]
				con:+2
			EndIf
			If Tris[J+2] = Vert
				Star[Con] = Tris[j]
				Star[con] = Tris[j+1]
				con:+2
			EndIf
			J:+3
		Wend
		For J=0 To Verts.Length/3
			
		Next
		
		Throw "Vert>"+Vert+" Has "+Con+" Connected Verts!"
	End Method
	
	
	Field LocA:Float
	
	Method SmartMove( X!,Y!,Z!)
		Task = IAL.MoveTO
		TargetX =X
		TargetY =Y
		TargetZ =Z
		aJunc = JuncNear(Owner.X,Owner.Y,Owner.Z)
		tJunc = JuncNear(x,y,z)
		If ajunc=tjunc
			'Print "Already there!"
			'Task = 0
			'Return 
		EndIf
		
		If aJunc = Null 
			Throw "No Active Junction"
		EndIf
				
	End Method
	Field tJunc:Junction 'target junction
	
	
	Method JuncNear:Junction(X!,Y!,Z!)
		Return Junc[NearVert(X,Y,Z)/3]
	End Method
	
	Field aJunc:Junction
	
	Method NearVert( X!,Y!,Z!)
		Local Xd!,Yd!,Zd!
		Local VertI=0
		Local CloseD!,CloseV:Int
		CloseD=999999999
		While VertI<Verts.Length	
			Xd = X-Verts[VertI]
			Zd = Z-Verts[VertI+2]
			Td = Sqr(Xd*Xd+Zd*Zd)
			If Td<CloseD
				CloseD=TD
				CloseV=VertI
			End If
			
			VertI:+3
		Wend
		Return CloseV
	End Method
	
	
	'debug stuff
	Field debugMark
	Field goMark,cMark
	Method FillTri(TriIndex)
			v0 = Tris[TriIndex]
			v1 = Tris[TriIndex+1]
			v2 = Tris[TriIndex+2]
			xMi!= min3( verts[v0],verts[v1],verts[v2])
			xMa!= max3( verts[v0],verts[v1],verts[v2]) 
			FillX = xmi+(xma-xmi)/2.0
			yMi!= min3( verts[v0+1],verts[v1+1],verts[v2+1])
			yMa!= max3( verts[v0+1],verts[v1+1],verts[v2+1])
			FillY! =yMi+(yMa-yMi)/2.0
			zMi! = min3( verts[v0+2],verts[v1+2],verts[v2+2]) 
			zMa!= max3( verts[v0+2],verts[v1+2],verts[v2+2])
			FillZ! = zMi+(zMa-zMi)/2.0	
	End Method
	'
	Field FillX!,FillY!,FillZ!
	
	Method NearestTri:Int( X!,Y!,Z!)
		TriI=0
		Temp:TProfile =Profiler.Enter("Nearest Tri")
		It=0
		Local Sd!=9999999
		While TriI<(TriC*3)
			V0 = Tris[TriI]*3
			V1 = Tris[TriI+1]*3
			V2 = Tris[TriI+2]*3
			xMi!= min3( verts[v0],verts[v1],verts[v2])
			xMa!= max3( verts[v0],verts[v1],verts[v2]) 
			vX = xmi+(xma-xmi)/2.0
			
			yMi!= min3( verts[v0+1],verts[v1+1],verts[v2+1])
			yMa!= max3( verts[v0+1],verts[v1+1],verts[v2+1])
			vY! =yMi+(yMa-yMi)/2.0
			zMi! = min3( verts[v0+2],verts[v1+2],verts[v2+2]) 
			zMa!= max3( verts[v0+2],verts[v1+2],verts[v2+2])
			vZ! = zMi+(zMa-zMi)/2.0
			
			tD! = Dist( x,y,z,vx,vy,vz )
			If tD<sd
				sd = td
				TriX = Vx
				TriY = vY
				triZ = vZ
				'TriX = Verts[v0]
			'	TriY = Verts[v0+1]
				'TriZ = Verts[v0+2]
				NearI = TriI								
			EndIf
			TriI:+3
		Wend
		Temp.Leave()
	
		Return NearI
	End Method
	Field TriX!,TriY!,TriZ!
	Method max3!(v1!,v2!,v3!)
		If v1>v2
			If v1>v3
				Return v1
			EndIf
			Return v3
		Else If v2>v3
			Return v2
		Else
			Return v3
		EndIf
	End Method
	
	Method min3!(v1!,v2!,v3!)
		If v1<v2
			If v1<v3
				Return v1
			EndIf
			Return v3
		Else If v2<v3
			Return v2
		Else
			Return v3
		EndIf
	End Method
	
	Method Dist:Double(X!,Y!,z!,x2!,y2!,z2!)
		xd! = x2-x
		yd! = y2-y
		zd! = z2-z
		Return Sqr(xd*xd+yd*yd+zd*zd)
		Return Sqr( (x2-x)^2+(y2-y)^2+(z2-z)^2)
	End Method
	Field Owner:Bot
	Field TriI:Int
	Field Tris:Int[],Verts:Double[]
	Field Junc:Junction[10000]
	Field aSurf:TSurface,VertC:Int,TriC:Int
End Type
Bot.ActiveBots = CreateList()
Bot.Bots = CreateList()

Function marker:Int(x!,y!,z!)
	If oMark[oCount] = Null
		oMark[oCount] = New TEntity
	EndIf
	TEntity.Clone( ActiveMark,oMark[oCount] )
	oMark[oCount].x=x
	oMark[oCount].y=y
	oMark[oCount].z=z
	oCount:+1
	
	Return ocount-1
End Function
'-----------
Function removeMarker(id:Int)
	Return 
	If id<(ocount-1)
		omark[id] =omark[ocount-1]
	EndIf
	If ocount>0
		ocount:-1
	EndIf
End Function
Function renderMarker()
	For Local j=0 To oCount-1
'		vcam.renderentity( omark[j] )
	Next
End Function
Function resetMarker()
	ocount=0
End Function
Local Players:Bot[255]
MainBall.Mesh.Y=5

Function Nope()
	Repeat
	Delay 20
		Until KeyDown(K_ESCAPE)
End Function


Function SetUpSun()

Sun:TLight = New TLight
Sun.Ambient( 32,32,32,1)
Sun.Diffuse( 32,32,32,1)
Sun.Specular(0,0,0,0)

Sun.Constant( 0.2 )
Sun.Linear( 0.001 )
Sun.Quadratic( 0.0001 )
Sun.Sync()
TopLight.Ambient(32,32,32,0)
TopLight.Diffuse(255,0,0,0)
TopLight.Specular( 1,1,1,0)
TopLight.Constant( 0.1 )
TopLight.Linear( 0.001 )
TopLight.Quadratic( 0.0001 )
TopLight.Y=50
topLight.Sync()

End Function

' ************************************************************************
Type TVector
	Const VINVALID:Byte=0 ; Const VDEFAULT:Byte=1 ; Const VUNIT:Byte=2
	Field _x:Double , _y:Double , _z:Double
	Field _Status:Byte

	' ********************************************************************
	' Constructor
	' ********************************************************************
	Function Constructor:TVector(a:Double, b:Double, c:Double)
		result:TVector=New TVector
		result._x=a ; result._y=b ; result._z=c
		result._Status=VDEFAULT
		Return result
	End Function
	Function Constructor1:TVector(v:TVector)
		result:TVector=New TVector
		result._x=v._x ; result._y=v._y ; result._z=v._z ; result._Status=v._Status
		Return result
	End Function
	' ********************************************************************
	' Selectors
	' ********************************************************************
	Method x:Double()
		Return _x
	End Method
	Method y:Double()
		Return _y
	End Method
	Method z:Double()
		Return _z
	End Method
	Method isUnit()
		Return _Status=VUNIT
	End Method
	Method isDefault()
		Return _Status=VDEFAULT
	End Method
	Method isValid()
		Return _Status<>VINVALID
	End Method
	' ********************************************************************
	' Magnitude
	' ********************************************************************
	Method mag:Double()
		If isValid() Then
			If isUnit() Then
				Return 1.0
			Else
				Return Sqr(x()*x() + y()*y() + z()*z())
			EndIf
		Else
			Return 0.0
		EndIf
	End Method
	Method magSqr:Double()
		If isValid() Then
			If isUnit() Then
				Return 1.0
			Else
				Return x()*x() + y()*y() + z()*z()
			EndIf
		Else
			Return 0.0
		EndIf
	End Method	
	' ********************************************************************
	' Dot or scalar product
	' ********************************************************************
	Function dot1:Double(v1:TVector, v2:TVector)
		Return v1.dot(v2)
	End Function
	Method dot:Double(v:TVector)
		If isValid() And v.isValid() Then
			Return x()*v.x() + y()*v.y() + z()*v.z()
		Else
			Return 0.0
		EndIf
	End Method
	' ********************************************************************
	' Distance between two vectors
	' ********************************************************************
	Method dist:Double(v:TVector)	
		VEC:TVector=TVector.Constructor((_x-v._x),(_y-v._y),(_z-v._z))
		Return VEC.mag()
	End Method
	Method distSqr:Double(v:TVector)
		VEC:TVector=TVector.Constructor((_x-v._x),(_y-v._y),(_z-v._z))
		Return VEC.magSqr()
	End Method
	' ********************************************************************
	' Make a unit vector
	' ********************************************************************
	Method unit:TVector()
		If isDefault() Then
			rep:Double=Self.mag()
				If rep<EPSILON Then
					_x=0.0
					_y=0.0
					_z=0.0
				Else
					temp:Double=1.0/rep
					_x:*temp
					_y:*temp
					_z:*temp
				EndIf
				_Status = VUNIT
		EndIf
		Return Self
	End Method
	Function unit1:TVector(v:TVector)
		VEC:TVector=TVector.Constructor(v._x, v._y, v._z)
		Return VEC.unit()
	End Function
	Function unit2:TVector(v:TVector, result:TVector)
		result._x=v._x ; result._y=v._y ; result._z=v._z ; result._Status=v._Status
		Return result.unit()
	End Function
	' ********************************************************************
	' Make a default vector
	' ********************************************************************	
	Method V_defaut:TVector()
		If isUnit() Then
			_Status = VDEFAULT
		EndIf
		Return Self
	End Method
	Function V_defaut1:TVector(v:TVector)
		VEC:TVector=TVector.Constructor(v._x, v._y, v._z)
		Return VEC.V_defaut()
	End Function
	Function V_defaut2:TVector(v:TVector, result:TVector)
		result._x=v._x ; result._y=v._y ; result._z=v._z ; result._Status=v._Status
		Return result.V_defaut()
	End Function
	' ********************************************************************
	' Optimised arithmetic methods
	' Return a TVector (Function, don't operate with this TVector)
	' ********************************************************************
	' Addition 2 vectors and return new vector (Result = v1 + v2)
	Function Addition:TVector(v1:TVector, v2:TVector)
		result:TVector=New TVector
		If v1.isValid() And v2.isValid() Then
			result._x = v1._x + v2._x
			result._y = v1._y + v2._y
			result._z = v1._z + v2._z
			result._Status = VDEFAULT
		EndIf
		Return result
	End Function
	' Substract 2 vectors and return new vector (Result = v1 - v2)
	Function Substract:TVector(v1:TVector, v2:TVector)
		result:TVector=New TVector
		If v1.isValid() And v2.isValid() Then
			result._x = v1._x - v2._x
			result._y = v1._y - v2._y
			result._z = v1._z - v2._z
			result._Status = VDEFAULT
		EndIf
		Return result
	End Function
	' Crossproduct of 2 vectors and return new vector (Result = v1 * v2)
	Function Cross:TVector(v1:TVector, v2:TVector)
		result:TVector=New TVector
		If v1.isValid() And v2.isValid() Then
			result._x = v1._y * v2._z - v1._z * v2._y
			result._y = v1._z * v2._x - v1._x * v2._z
			result._z = v1._x * v2._y - v1._y * v2._x
			result._Status = VDEFAULT
		EndIf
		Return result
	End Function	
	' Invert a vector and return new vector (Result = -(v1))
	Function Invert:TVector(v1:TVector)
		result:TVector=New TVector
		If v1.isValid() Then
			result._x = - v1._x
			result._y = - v1._y
			result._z = - v1._z
			result._Status = VDEFAULT
		EndIf
		Return result
	End Function	
	' Multiply 1 vector by scale and return new vector (Result = v1 * scale)
	Function Multiply:TVector(v1:TVector, scale:Double)
		result:TVector=New TVector
		If v1.isValid() Then
			result._x = v1._x * scale
			result._y = v1._y * scale
			result._z = v1._z * scale
			result._Status = VDEFAULT
		EndIf
		Return result
	End Function
	' ********************************************************************
	' Operator
	' ( Method, operate with this TVector )
	' ********************************************************************
	' Negat this vector and return a vector ( result = - self ) (v2=v1.Negat())
	Method Negat:TVector()
		Return TVector.Invert(Self)
	End Method
	' Assign a vector to this vector ( self = v1 ) (v2=v2.Equal(v1))
	Method Equal:TVector(v1:TVector)
		_x=v1._x ; _y=v1._y ; _z=v1._z ; _Status=v1._Status
	End Method	
	' Add to this vector a vector and return this vector ( self :+ v1 ) (v2=v2.AddEqual(v1))
	Method AddEqual:TVector(v1:TVector)
		Return TVector.Addition(Self, v1)
	End Method
	' Sub to this vector a vector and return this vector ( self :- v1 ) (v2=v2.SubEqual(v1))
	Method SubEqual:TVector(v1:TVector)
		Return TVector.Substract(Self, v1)
	End Method
	' Mult this vector by a vector and return this vector (Crossproduct) ( self :* v1 ) (v2=v2.MultEqualVec(v1))
	Method MultEqualVec:TVector(v1:TVector)
		Return TVector.Cross(Self, v1)
	End Method
	' Mult this vector by a val and return this vector ( self :* value ) (v2=v2.MultEqualVal(scale))
	Method MultEqualVal:TVector(scale:Double)
		Return TVector.Multiply(Self, scale)
	End Method
	' Add to this vector a vector and return a vector ( result = self + v1 ) (v3=v1.Add(v2))
	Method Add:TVector(v1:TVector)
		Return TVector.Addition(Self, v1)
	End Method
	' Sub to this vector a vector and return a vector ( result = self - v1 ) (v3=v1.Sub(v2))
	Method Sub:TVector(v1:TVector)
		Return TVector.Substract(Self, v1)
	End Method	
	' Mult to this vector a vector and return a vector (Crossproduct) ( result = self * v1 ) (v3=v1.MultVec(v2))
	Method MultVec:TVector(v1:TVector)
		Return TVector.Cross(Self, v1)
	End Method	
	' Mult to this vector by a value and return a vector ( result = self * scale ) (v3=v1.MultVal(scale))
	Method MultVal:TVector(scale:Double)
		Return TVector.Multiply(Self, scale)
	End Method
End Type
' *******