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 :) )
(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 ' *******