[bb] FPSNetUpdate by Jeremy Alessi [ 1+ years ago ]

Started by BlitzBot, June 29, 2017, 00:28:39

Previous topic - Next topic

BlitzBot

Title : FPSNetUpdate
Author : Jeremy Alessi
Posted : 1+ years ago

Description : This is a fully networked FPS deathmatch game with server listing via Gnet.  3 weapons (Semi-Automatic, Shotgun, and Flamethrower) are included with various strengths and weaknesses.  Everything is done using Blitz3D code with no extra media.  The only additional library needed is Gnet which is included in the source code below.

Code :
Code (blitzbasic) Select
;====== FPSNet: A NETWORKED FIRST PERSON SHOOTER EXAMPLE ==================
;====== UTILIZING ONLY BUILT IN BLITZ3D FEATURES ==========================
;====== A CODESKETCH BY JEREMY ALESSI =====================================
;====== THANKS MARK SIBLY FOR GNET ========================================

;====== WASD OR CURSORS MOVE, MOUSE LOOKS, LEFT MOUSE BUTTON SHOOTS =======
;====== SPACE BAR OR 0 ON NUMPAD JUMPS, PRESS C TO CHAT ===================
;====== PRESS 2 TO UNLOCK MOUSE FROM CENTER (USEFUL TO PLAY ===============
;====== AND ALSO BE ABLE TO MULTITASK IF NEED BE) PRESS 1 TO RELOCK =======
;====== MOUSE BACK TO CENTER OF SCREEN ====================================
;====== YEAH EVERYONE HAS THE SOURCE ... DON'T CHEAT! =====================


;====== INCLUDES ==========================================================

;Include "gnet_inc.bb" This is included at the bottom of this source!

;==========================================================================



;====== GRAPHICS ==========================================================

Graphics3D(640, 480, 16, 2)
SetBuffer BackBuffer()
HidePointer

;==========================================================================



;====== COLLISIONS ========================================================

Global BODY = 1
Global SCENE = 2
Collisions(BODY,SCENE, 2, 2)
Collisions(BODY,BODY, 2, 2)

;==========================================================================



;====== GLOBALS ===========================================================

Global gameState$ = "Title Screen"

;Mousehit Vars
Global mb1pressed, mb2pressed

;Keyhit Vars
Global upKeyPressed, downKeyPressed, leftKeyPressed, rightKeyPressed, enterKeyPressed, spaceKeyPressed
Global chatKeyPressed

;Font Vars
Global font, bigFont

;Menu Var
Global menuCount

;Server Vars
Global serverCount
Global serverPointer

;Local Player Network Vars
Global localPlayerName$, localPlayerPointer

;Scenery Vars
Global level,copySprite, lightPivot

;Camera Var
Global camera

;Player Gameplay Vars
Global health#, shot, shot2, shot3, shotTimer#, positionUpdateTimer#, serverRefreshTimer#, hosting
Global vX#, vY#, vZ#, oldX#, oldY#, oldZ#, centerMouse = True, enteringChat = False, chat$
Global copyPowerUp, weapon$ = "Semi-Automatic", powerUpSpawned, ammo# = 50, randPos, randNum
Global justDied#
;==========================================================================



;====== INCOMING ==========================================================

Dim incoming$(100)

;==========================================================================



;====== CONTENTS OF A KEY =================================================

Dim keys$(237)
LoadKeyboardContent()

;==========================================================================



;====== SHOT ARRAY ========================================================

Dim pickedArray(3,3)

;==========================================================================



;====== TYPES =============================================================

Type Player

Field iD, name$, mesh[10], score

End Type

Type Particle

Field mesh, name$, alpha#
Field vX#, vY#, vZ#

End Type

Type chatMsg

Field msg$, born#, from

End Type

Type powerUp

Field mesh, name$

End Type

;==========================================================================



;====== INITIAL SETUP =====================================================

Setup("Title Screen")

;==========================================================================



;==========================================================================
.Main
;====== RUN ===============================================================
period=1000 / 30
tweentime = MilliSecs()-period
While 1
;====== CALCULATE TWEEN ===================================================
Repeat
elapsed = MilliSecs() - tweentime
Until elapsed
ticks = elapsed/period
tween# = Float(elapsed Mod period) / Float(period)
;==========================================================================

;====== MAIN LOOP =========================================================
For k=1 To ticks
tweentime = tweentime+period
If k = ticks Then CaptureWorld
If KeyDown(1)
If Not GNET_RemoveServer("FPSNetUpdate")
If hosting = True
RuntimeError "Failed to remove server"
EndIf
EndIf
ClearWorld()
End
EndIf
UpdateLogic()
UpdateWorld
Next
RenderWorld(tween#)
Draw()
Flip
Wend
;===========================================================================



;====== UPDATE LOGIC =======================================================

Function UpdateLogic()

Select gameState$

Case "Title Screen"
UpdateTitleInput()
UpdateTitleScreen()
Case "Game"
DetectPowerUpCollision()
UpdateGameInput()
ControlChat()
UpdateLights()
UpdateCamera()
UpdatePlayerMovement()
HostSpawnPowerups()
UpdateParticles()
UpdateNetwork()
UpdateCenterMouse()
End Select

End Function

;===========================================================================



;====== DRAW ===============================================================

Function Draw()

Select gameState$

Case "Title Screen"
DrawTitleScreen()
Case "Game"
DrawGamePlay()

End Select

End Function

;===========================================================================



;====== UPDATE TITLE INPUT =================================================

Function UpdateTitleInput()

mb1pressed = MouseHit(1)

mb2pressed = MouseHit(2)

upKeyPressed = KeyHit(17) Or KeyHit(200)

downKeyPressed = KeyHit(31) Or KeyHit(208)

leftKeyPressed = KeyHit(30) Or KeyHit(203)

rightKeyPressed = KeyHit(32) Or KeyHit(205)

enterKeyPressed = KeyHit(28)

spaceKeyPressed = KeyHit(57)


End Function

;===========================================================================



;====== UPDATE GAME INPUT ==================================================

Function UpdateGameInput()

chatKeyPressed = KeyHit(46)

enterKeyPressed = KeyHit(28)

End Function

;===========================================================================



;====== UPDATE CENTER MOUSE ================================================

Function UpdateCenterMouse()

If centerMouse = True
MoveMouse(CorrectX(320), CorrectY(240))
EndIf
If KeyHit(2)
centerMouse = True
EndIf
If KeyHit(3)
centerMouse = False
EndIf

End Function

;===========================================================================



;====== UPDATE TITLE SCREEN ================================================

Function UpdateTitleScreen()

If upKeyPressed And menuCount > 0
menuCount = menuCount - 1
EndIf

If downKeyPressed And menuCount < serverCount - 1
menuCount = menuCount + 1
EndIf

If enterKeyPressed
gns.GNET_Server = Object.GNET_Server(serverPointer)
If JoinNetGame(gnsserver$, gnsip$)
FlushKeys
Color(255,0,0)
Locate(200,130)
localPlayerName$ = Input("Name - ")
Delay(500)
FlushKeys
p.Player = New Player
localPlayerPointer = Handle(p.Player)
piD = CreateNetPlayer(localPlayerName$)
Setup("Game")
hosting = False
EndIf
EndIf

If spaceKeyPressed
FlushKeys
Color(255,0,0)
Locate(200,130)
localPlayerName$ = Input("Name - ")
Delay(500)
FlushKeys
If HostNetGame(localPlayerName$) = 2

If GNET_AddServer("FPSNetUpdate", localPlayerName$)
p.Player = New Player
localPlayerPointer = Handle(p.Player)
piD = CreateNetPlayer(localPlayerName$)
Setup("Game")
hosting = True
serverRefreshTimer# = MilliSecs()
Else
RuntimeError("Failed to Add Server!")
EndIf

Else

RuntimeError("Failed to Create Net Game!")

EndIf


EndIf



End Function

;===========================================================================



;====== UPDATE PLAYER MOVEMENT =============================================

Function UpdatePlayerMovement()

If enteringChat Return

p.Player = Object.Player(localPlayerPointer)

oldX# = EntityX(pmesh[1])
oldY# = EntityY(pmesh[1])
oldZ# = EntityZ(pmesh[1])

If KeyDown(17) Or KeyDown(200)
MoveEntity(pmesh[1], 0, 0, .5)
EndIf
If KeyDown(31) Or KeyDown(208)
MoveEntity(pmesh[1], 0, 0, -.5)
EndIf
If KeyDown(30) Or KeyDown(203)
MoveEntity(pmesh[1], -.5, 0, 0)
EndIf
If KeyDown(32) Or KeyDown(205)
MoveEntity(pmesh[1], .5, 0, 0)
EndIf

numColls = CountCollisions(pmesh[1])

If numColls = 0
vY# = vY# - .01
Else
vY# = 0
EndIf

If (KeyDown(57) Or KeyDown(82)) And numColls > 0
vY# = .2
EndIf

TranslateEntity(pmesh[1],0, vY#, 0)
RotateEntity(pmesh[1], 0, EntityYaw(pmesh[1]) - MouseXSpeed(), 0)

vX# = EntityX(pmesh[1]) - oldX#
vY# = EntityY(pmesh[1]) - oldY#
vZ# = EntityZ(pmesh[1]) - oldZ#

End Function

;===========================================================================



;====== UPDATE LIGHTS ======================================================

Function UpdateLights()

TurnEntity(lightPivot, 0, 10, 0)

End Function

;===========================================================================



;====== UPDATE CAMERA ======================================================

Function UpdateCamera()

p.Player = Object.Player(localPlayerPointer)

shot = 0
shot2 = 0
shot3 = 0
If MouseDown(1)
Select weapon$

Case "Semi-Automatic"
If shotTimer# + 200 < MilliSecs() And ammo# > 0
ammo# = ammo# - 1
shot = CameraPick(camera, CorrectX(320), CorrectY(240))
shotTimer# = MilliSecs()
If shot
CreateSomeParticles(PickedX(), PickedY(), PickedZ(), 50, 50, 50, 10)
SendNetMsg(4,"1," + PickedX() + "," + PickedY() + "," + PickedZ() + "-", piD, 0, 0)
EndIf
EndIf
Case "Shotgun"
If shotTimer# + 750 < MilliSecs() And ammo# >= 3
ammo# = ammo# - 3
For i = 1 To 3

Select i
Case 1
shot = CameraPick(camera, CorrectX(320 - 20), CorrectY(240))
Case 2
shot2 = CameraPick(camera, CorrectX(320), CorrectY(240))
Case 3
shot3 = CameraPick(camera, CorrectX(320 + 20), CorrectY(240))
End Select

pickedArray(i,1) = PickedX()
pickedArray(i,2) = PickedY()
pickedArray(i,3) = PickedZ()

Next
shotTimer# = MilliSecs()
If shot Or shot2 Or shot3
For i = 1 To 3
If (i = 1 And shot <> 0) Or (i = 2 And shot2 <> 0) Or (i = 3 And shot3 <> 0)
CreateSomeParticles(pickedArray(i,1), pickedArray(i,2), pickedArray(i,3), 200, 200, 200, 10)
EndIf
Next
SendNetMsg(4,"2," + pickedArray(1,1) + "," + pickedArray(1,2) + "," + pickedArray(1,3) + "," + pickedArray(2,1) + "," + pickedArray(2,2) + "," + pickedArray(2,3) + "," + pickedArray(3,1) + "," + pickedArray(3,2) + "," + pickedArray(3,3) + "-", piD, 0, 0)
EndIf
EndIf
Case "Flamethrower"
If shotTimer# + 50 < MilliSecs() And ammo# >= .1
ammo# = ammo# - .1
pvX# = vX# + (EntityX(pmesh[3], True) - EntityX(pmesh[2], True)) / 10
pvY# = vY# + (EntityY(pmesh[3], True) - EntityY(pmesh[2], True)) / 10
pvZ# = vZ# + (EntityZ(pmesh[3], True) - EntityZ(pmesh[2], True)) / 10

SendNetMsg(9, pvX# + "," + pvY# + "," + pvZ# + "-", piD, 0, 0)
CreateSomeParticles(EntityX(pmesh[2],True), EntityY(pmesh[2], True), EntityZ(pmesh[2], True), 255, 200, 100, 10,  pvX# + Rnd(-.05, .05), pvY# + Rnd(-.05, .05), pvZ#, "Flame")
shot = LinePick(EntityX(camera, True), EntityY(camera, True), EntityZ(camera, True), EntityX(pmesh[3], True) - EntityX(camera, True), EntityY(pmesh[3], True) - EntityY(camera, True), EntityZ(pmesh[3], True) - EntityZ(camera, True))
shotTimer# = MilliSecs()
If shot
CreateSomeParticles(PickedX(), PickedY(), PickedZ(), 255, 200, 100, 10, "Flame")
SendNetMsg(4,"3," + PickedX() + "," + PickedY() + "," + PickedZ() + "-", piD, 0, 0)
EndIf
EndIf

End Select

EndIf

RotateEntity(camera,EntityPitch(camera) + MouseYSpeed(),0,0)
If EntityPitch(camera) > 90
RotateEntity(camera, 90, 0, 0)
EndIf
If EntityPitch(camera) < - 90
RotateEntity(camera, -90, 0, 0)
EndIf

End Function

;===========================================================================



;====== UPDATE NETWORK =====================================================

Function UpdateNetwork()

While RecvNetMsg()

Select NetMsgType()

Case 1

For p.Player = Each Player
If piD = NetMsgFrom()
DecodeIncomingMessage(NetMsgData$())
PositionEntity(pmesh[1], incoming$(1), incoming$(2), incoming$(3))
RotateEntity(pmesh[1], incoming$(4), incoming$(5), 0)
If incoming$(6) <> ""
pscore = incoming$(6)
EndIf
EndIf
Next

Case 2

p.Player = Object.Player(localPlayerPointer)
CreateSomeParticles(EntityX(pmesh[1]), EntityY(pmesh[1]), EntityZ(pmesh[1]), 255, 0, 0, 10)

If justDied# + 500 < MilliSecs()
DecodeIncomingMessage(NetMsgData$())
Select incoming$(1)
Case 1
health# = health# - 5
Case 2
count = 0
If incoming$(2) <> 0
count = count + 1
EndIf
If incoming$(3) <> 0
count = count + 1
EndIf
If incoming$(4) <> 0
count = count + 1
EndIf
health# = health# - (5 * count)
Case 3
health# = health# - 25
End Select
EndIf

If health# <= 0
health# = 100
PositionEntity(pmesh[1],5,1,Rand(0, 50))
SendNetMsg(3, "1", piD, NetMsgFrom(), 1)
CreateSomeParticles(EntityX(pmesh[1]), EntityY(pmesh[1]), EntityZ(pmesh[1]), 255, 0, 0, 100)
SendNetMsg(5, "1",piD, 0, 0)
justDied# = MilliSecs()
EndIf

Case 3

p.Player = Object.Player(localPlayerPointer)
pscore = pscore + 1

Case 4

DecodeIncomingMessage(NetMsgData$())

Select incoming$(1)

Case 1
CreateSomeParticles(incoming$(2), incoming$(3), incoming$(4), 50, 50, 50, 10)
Case 2
CreateSomeParticles(incoming$(2), incoming$(3), incoming$(4), 255, 255, 255, 10)
CreateSomeParticles(incoming$(5), incoming$(6), incoming$(7), 255, 255, 255, 10)
CreateSomeParticles(incoming$(8), incoming$(9), incoming$(10), 255, 255, 255, 10)
Case 3
CreateSomeParticles(incoming$(2), incoming$(3), incoming$(4), 255, 200, 100, 10)

End Select

Case 5

For p.Player = Each Player
If piD = NetMsgFrom()
CreateSomeParticles(EntityX(pmesh[1]), EntityY(pmesh[1]), EntityZ(pmesh[1]), 255, 0, 0, 100)
EndIf
Next

Case 6

c.chatMsg = New chatMsg
cmsg = NetMsgData$()
corn# = MilliSecs()
cfrom = NetMsgFrom()

Case 7

DecodeIncomingMessage(NetMsgData$())
pup.powerUp = New powerUp
pupmesh = CopyEntity(copyPowerup)
powerUpSpawned = True

PositionEntity(pupmesh, EntityX(GetChild(level, incoming$(1)), True), EntityY(GetChild(level, incoming$(1)), True) + 2, EntityZ(GetChild(level, incoming$(1)), True))

Select incoming$(2)

Case 1
pup
ame$ = "Semi-Automatic"
EntityColor(pupmesh, 255, 255, 255)
Case 2
pup
ame$ = "Shotgun"
EntityColor(pupmesh, 100, 100, 255)
Case 3
pup
ame$ = "Flamethrower"
EntityColor(pupmesh, 200, 150, 100)

End Select
randPos = incoming$(1)
randNum = incoming$(2)

Case 8

For pup.powerUp = Each powerUP
FreeEntity(pupmesh)
Delete(pup)
Next
powerUpSpawned = False

Case 9

For op.Player = Each Player
If opiD = NetMsgFrom()
DecodeIncomingMessage(NetMsgData$())
CreateSomeParticles(EntityX(opmesh[2],True), EntityY(opmesh[2], True), EntityZ(opmesh[2], True), 255, 200, 100, 10,  incoming$(1) + Rnd(-.05, .05), incoming$(2) + Rnd(-.05, .05), incoming$(3), "Flame")
EndIf
Next

Case 100

p.Player = New Player
piD = NetMsgFrom()
pmesh[1] = CreateSphere(8)
p
ame$ = NetPlayerName$(piD)
EntityColor(pmesh[1], 0, 255, 0)
PositionEntity(pmesh[1], 5, 1.5, Rand(50,100))
EntityType(pmesh[1],BODY)
EntityRadius(pmesh[1], 1.5)
EntityPickMode(pmesh[1], 2)

pmesh[2] = CreateCube(pmesh[1])
PositionEntity(pmesh[2], 1, -.5, 1)
ScaleEntity(pmesh[2], .1, .1, .4)
EntityColor(pmesh[2], 20, 20, 20)

pmesh[3] = CreatePivot(pmesh[1])
PositionEntity(pmesh[3], 0, 0, 5)

If hosting
p.Player = Object.Player(localPlayerPointer)
SendNetMsg(7, randPos + "," + randNum + "-", piD#, NetMsgFrom(), 1)
EndIf

Case 101

For p.Player = Each Player
If piD = NetMsgFrom()
FreeEntity(pmesh[1])
Delete(p)
EndIf
Next

Case 102

GNET_AddServer("FPSNetUpdate", localPlayerName$)
hosting = True

End Select

Wend

p.Player = Object.Player(localPlayerPointer)
If positionUpdateTimer# + 50 < MilliSecs()
SendNetMsg(1, EntityX(pmesh[1]) + "," + EntityY(pmesh[1]) + "," + EntityZ(pmesh[1]) + "," + EntityPitch(camera) + "," + EntityYaw(pmesh[1]) + "," + pscore + "-", piD, 0, 0)
positionUpdateTimer# = MilliSecs()
EndIf

For op.Player = Each Player
Select weapon$

Case "Semi-Automatic"
If shot = opmesh[1]
CreateSomeParticles(PickedX(), PickedY(), PickedZ(), 255, 0, 0, 10)
SendNetMsg(2, "1-", piD, opiD, 0)
EndIf
Case "Shotgun"
If shot = opmesh[1] Or shot2 = opmesh[1] Or shot3 = opmesh[1]
Select opmesh[1]
Case shot
CreateSomeParticles(pickedArray(1, 1), pickedArray(1, 2), pickedArray(1, 3), 255, 0, 0, 10)
Case shot2
CreateSomeParticles(pickedArray(2, 1), pickedArray(2, 2), pickedArray(2, 3), 255, 0, 0, 10)
Case shot3
CreateSomeParticles(pickedArray(3, 1), pickedArray(3, 2), pickedArray(3, 3), 255, 0, 0, 10)
End Select
SendNetMsg(2, "2," + Left(Str(shot), 1) + "," + Left(Str(shot2), 1) + "," + Left(Str(shot3), 1) + "-", piD, opiD, 0)
EndIf
Case "Flamethrower"
If shot = opmesh[1]
CreateSomeParticles(PickedX(), PickedY(), PickedZ(), 255, 0, 0, 10)
SendNetMsg(2, "3-", piD, opiD, 0)
EndIf

End Select
Next

If hosting = True
If serverRefreshTimer# + 250000 < MilliSecs()
GNET_RefreshServer( "FPSNetUpdate",localPlayerName$ )
serverRefreshTimer# = MilliSecs()
EndIf
EndIf

End Function

;===========================================================================



;====== UPDATE PARTICLES ===================================================

Function UpdateParticles()

For p.Particle = Each Particle
If palpha# <= 0
FreeEntity(pmesh)
Delete(p)
Else

Select p
ame$
Case "Flame"
TranslateEntity(pmesh,pvX#, pvY#, pvZ# )
palpha# = palpha# - Rnd(.3)
EntityAlpha(pmesh, palpha#)
Default
pvY# = pvY# - .01
TranslateEntity(pmesh,pvX#, pvY#, pvZ#)
palpha# = palpha# - .02
EntityAlpha(pmesh, palpha#)

End Select

EndIf
Next

End Function

;===========================================================================


;====== DRAW TITLE SCREEN ==================================================

Function DrawTitleScreen()

Cls
FPSNetText(font, 320, 0, String$("+",80), 1, 1, 100, 100, 100)
FPSNetText(font, 320, 480, String$("+",80), 1, 1, 100, 100, 100)

For i = 0 To 640 Step 640
For j = 10 To 470 Step 10
FPSNetText(font, i, j, "+", 1, 1, 100, 100, 100)
Next
Next

FPSNetText(bigFont, 320, 30, "FPSNet:", 1, 1, 255, 0, 0)
FPSNetText(font, 320, 60, "A NETWORKED First Person Shooter Example", 1, 1, 100, 100, 100)
FPSNetText(font, 320, 80, "Press Up/Down to Select a Game to Join!", 1, 1, 100, 100, 100)
FPSNetText(font, 320, 100, "Press Space to Host a New Game!", 1, 1, 100, 100, 100)
FPSNetText(font, 320, 120, "Games In Progress:" , 1, 1, 200, 255, 150)

serverCount = 0
For gns.GNET_Server = Each GNET_Server

Select serverCount

Case menuCount
FPSNetText(font, 320, 160 + 20 * serverCount, gnsserver$ + " - Press Enter to Join ...", 1, 1, 255, 255, 255)
serverPointer = Handle(gns)
Default
FPSNetText(font, 320, 160 + 20 * serverCount, gnsserver$, 1, 1, 100, 100, 100)

End Select
serverCount = serverCount + 1

Next

End Function

;===========================================================================



;====== DRAW GAMEPLAY ======================================================

Function DrawGamePlay()

Select weapon$

Case "Semi-Automatic"
FPSNetText(font, 320, 240, "+", 1, 1, 255, 255, 255)
Case "Shotgun"
FPSNetText(font, 300, 240, "+", 1, 1, 255, 255, 255)
FPSNetText(font, 320, 240, "+", 1, 1, 255, 255, 255)
FPSNetText(font, 340, 240, "+", 1, 1, 255, 255, 255)
Case "Flamethrower"
FPSNetText(font, 320, 240, "()", 1, 1, 255, 200, 100)

End Select

p.Player = Object.Player(localPlayerPointer)
FPSNetText(font, 0, 0, "Your Score: " + pscore, 0, 0, 255, 0, 0)

FPSNetText(font, 150, 0, "Health: ", 0, 0, 0, 255, 0)
Color(255, 0, 0)
Rect(CorrectX(221), CorrectY(4), CorrectX(health#), CorrectY(10), 1)
Color(255, 255, 255)
Rect(CorrectX(220), CorrectY(2), CorrectX(102), CorrectY(14), 0)

FPSNetText(font, 400, 0, "Ammo: " + Int(ammo#), 0, 0, 255, 255, 255)


printI = 50
For c.chatMsg = Each chatMsg

secondsAround = (MilliSecs() - corn#) / 50
FPSNetText(font, 0, 0 + printI, NetPlayerName(cfrom) + " - " + cmsg$, 0, 0, 255 - secondsAround, 255 - secondsAround, 255 - secondsAround)
printI = printI + 15

Next

If enteringChat = True

FPSNetText(font, 0, 460, localPlayerName$ + " - " + chat$, 0, 0, 255, 255, 255)

EndIf

For p.Player = Each Player

If Handle(p.Player) <> localPlayerPointer
CameraProject(camera, EntityX(pmesh[1]), EntityY(pmesh[1]), EntityZ(pmesh[1]))
FPSNetText(font, ProjectedX(), ProjectedY() - 20, p
ame$ + "  -  " + pscore, 1, 1, 255, 255, 255)
EndIf

Next

End Function

;===========================================================================



;====== DETECT POWERUP COLLISION ===========================================

Function DetectPowerUpCollision()

If Not powerUpSpawned Return

p.Player = Object.Player(localPlayerPointer)
For pup.powerUp = Each powerUp

If EntityDistance(pmesh[1], pupmesh) < 3

If weapon$ = pup
ame$
Select weapon$
Case "Semi-Automatic"
ammo# = ammo# + 50
Case "Shotgun"
ammo# = ammo# + 45
Case "Flamethrower"
ammo# = ammo# + 30
End Select
Else
Select pup
ame$
Case "Semi-Automatic"
ammo# = 50
Case "Shotgun"
ammo# = 45
Case "Flamethrower"
ammo# = 30
End Select
EndIf
weapon$ = pup
ame$
powerUpSpawned = False
FreeEntity(pupmesh)
Delete(pup)
SendNetMsg(8, "", piD, 0, 1)

EndIf

Next

End Function

;===========================================================================



;====== HOST SPAWN POWERUPS ================================================

Function HostSpawnPowerups()

If (Not hosting) Or (powerUpSpawned)
Return
EndIf

randPos = Rand(1, CountChildren(level))

pup.powerUp = New powerUp
pupmesh = CopyEntity(copyPowerUp)
PositionEntity(pupmesh, EntityX(GetChild(level, randPos), True), EntityY(GetChild(level, randPos), True) + 2, EntityZ(GetChild(level, randPos), True))
randNum = Rand(1,3)
Select randNum

Case 1
pup
ame$ = "Semi-Automatic"
EntityColor(pupmesh, 255, 255, 255)
Case 2
pup
ame$ = "Shotgun"
EntityColor(pupmesh, 100, 100, 255)
Case 3
pup
ame$ = "Flamethrower"
EntityColor(pupmesh, 200, 150, 100)

End Select
p.Player = Object.Player(localPlayerPointer)
SendNetMsg(7, randPos + "," + randNum + "-", piD#, 0, 1)
powerUpSpawned = True


End Function

;===========================================================================


;====== CONTROL CHAT =======================================================

Function ControlChat()

If chatKeyPressed

enteringChat = True
FlushKeys

EndIf

If enterKeyPressed And enteringChat = True

p.Player = Object.Player(localPlayerPointer)

c.chatMsg = New chatMsg
cmsg$ = chat$
corn# = MilliSecs()
cfrom = piD

SendNetMsg(6, chat$, piD , 0, 0)

chat$ = ""
enteringChat = False

EndIf

If enteringChat = True

EnterChat()

EndIf

For c.chatMsg = Each chatMsg

If corn# + 10000 < MilliSecs()

Delete(c)

EndIf

Next

End Function

;===========================================================================



;====== CREATE SOME ParticleS ==============================================

Function CreateSomeParticles(x#, y#, z#, r, g, b, numParticles, optvX# = 0, optvY# = 0, optvZ# = 0, passedName$ = "")

For i = 1 To numParticles
p.Particle = New Particle
pmesh = CopyEntity(copySprite)
If passedName$ <> ""
p
ame$ = passedName$
EndIf
PositionEntity(pmesh,x#, y#, z#, True)
EntityColor(pmesh, r, g, b)
If optvX# = 0
pvX# = Rnd(-.2, .2)
Else
pvx# = optvX#
EndIf
If optvY# = 0
pvY# = Rnd(.2)
Else
pvY# = optvY#
EndIf
If optvZ# = 0
pvZ# = Rnd(-.2, .2)
Else
pvZ# = optvZ#
EndIf
palpha = 1
Next

End Function

;===========================================================================



;====== SETUP ==============================================================

Function Setup(mode$)

Select mode$

Case "Title Screen"

font = LoadFont("Arial",20,1)
bigFont = LoadFont("Arial",50,1)
GNET_ListServers()

Case "Game"

gameState$ = "Game"

p.Player = Object.Player(localPlayerPointer)
pmesh[1] = CreatePivot()
PositionEntity(pmesh[1], 5, 1.5, Rand(0, 50))
EntityType(pmesh[1],BODY)
EntityRadius(pmesh[1], 1.5)
health# = 100
pscore = 0
p
ame$ = localPlayerName$

camera = CreateCamera(pmesh[1])
CameraRange(camera,.1, 500)

pmesh[2] = CreateCube(camera)
PositionEntity(pmesh[2], 1, -.5, 1)
ScaleEntity(pmesh[2], .1, .1, .4)
EntityColor(pmesh[2], 20, 20, 20)

pmesh[3] = CreatePivot(camera)
PositionEntity(pmesh[3], 0, 0, 5)

LoadLevel()
PointEntity(pmesh[1], level)
MoveMouse(CorrectX(320), CorrectY(240))




End Select

End Function

;===========================================================================



;====== LOAD LEVEL =========================================================

Function LoadLevel()

copyPowerUp = CreateSphere()
HideEntity(copyPowerUp)

copySprite = CreateSprite()
ScaleSprite(copySprite, .1, .1)
EntityFX(copySprite, 1+8)
HideEntity(copySprite)

level = CreatePlane(16)
EntityPickMode(level, 2)

For i = -1 To 1 Step 2
For j = -4 To 4
cube = CreateCube(level)
EntityType(cube, SCENE)
EntityPickMode(cube, 2)
EntityColor(cube, 100, 100, 100)
PositionEntity(cube, i * 10, 1, j * 10)
Next
Next

For i = 1 To 8
cube = CreateCube(level)
EntityType(cube, SCENE)
EntityPickMode(cube, 2)
EntityColor(cube,100,100,100)
PositionEntity(cube, 0, i * 2, i * 5)
Next

For i = 1 To 8
cube = CreateCube(level)
EntityType(cube, SCENE)
EntityPickMode(cube, 2)
EntityColor(cube,100,100,100)
PositionEntity(cube, 0, i * 2, i * -5)
Next

EntityType(level,SCENE)

lightPivot = CreatePivot()
NameEntity(lightPivot,"Light Pivot")

light = CreateLight(3,lightPivot)
NameEntity(light, "light1")
PositionEntity(light,25, 25, 0)
RotateEntity(light, 90, 0, 0)
LightRange(light, 500)
LightColor(light, 255, 0, 0)

light = CreateLight(3,lightPivot)
NameEntity(light, "light2")
PositionEntity(light,-25, 25, 0)
RotateEntity(light, 90, 0, 0)
LightRange(light, 500)
LightColor(light, 0, 0, 255)

light = CreateLight(3,lightPivot)
NameEntity(light, "light3")
PositionEntity(light,0, 25, 25)
RotateEntity(light, 90, 0, 0)
LightRange(light, 500)
LightColor(light, 0, 255, 0)

End Function

;===========================================================================



;====== FPSNET TEXT ========================================================

Function FPSNetText(fontType, X, Y, theText$, centerX = 0, centerY = 0,r = 255, g = 255, b = 255)

Color(r, g, b)
SetFont(fontType)
Text(CorrectX(X), CorrectY(Y), theText$, centerX, centerY)

End Function

;==========================================================================



;====== CORRECTX ==========================================================

Function CorrectX(pixel)

Return (pixel * GraphicsWidth() / 640)

End Function

;==========================================================================



;====== CORRECTY ==========================================================

Function CorrectY(pixel)

Return (pixel * GraphicsHeight() / 480)

End Function

;==========================================================================



;====== DECODE INCOMING MESSAGE ===========================================

Function DecodeIncomingMessage(message$)

For i = 1 To 100
incoming$(i) = ""
Next
i = 1
part = 1
incoming$(part) = Mid(message$, i, 1)
i = i + 1
While Mid(message$, i, 1)<>"-"
While Mid(message$, i, 1)<>","
incoming$(part)=incoming$(part)+Mid(message$, i, 1)
i = i + 1
If Mid(message$, i, 1)="-"
Exit
EndIf
Wend
If Mid(message$, i, 1)=","
i = i + 1
part = part + 1
incoming$(part) = Mid(message$, i, 1)
i = i + 1
EndIf
Wend

End Function

;==========================================================================

;====== ENTER CHAT ========================================================

Function EnterChat()

For i = 1 To 237
If (i >= 2 And i <= 11) Or (i >= 16 And i <= 25) Or (i >= 30 And i <= 38) Or (i >= 44 And i <= 50)
If KeyHit(i)
If Len(chat$) <= 25
chat$ = chat$ + keys$(i)
EndIf
EndIf
EndIf
Next

If KeyHit(14) And Len(chat$) >= 1 And  keytimer# + 100 < MilliSecs()
chat$ = Left(chat$,Len(chat$) - 1)
keytimer# = MilliSecs()
EndIf
If KeyHit(211) And Len(chat$) >= 1 And  keytimer# + 100 < MilliSecs()
chat$ = Right(chat$,Len(chat$) - 1)
keytimer# = MilliSecs()
EndIf

If KeyHit(57) And Len(chat$) <= 25 And  keytimer# + 100 < MilliSecs()
chat$ = chat$ + " "
keytimer# = MilliSecs()
EndIf

If KeyHit(53) And Len(chat$) <= 25 And (KeyDown(42) Or KeyDown(54))
chat$ = chat$ + "?"
EndIf

If KeyHit(2) And Len(chat$) <= 25 And (KeyDown(42) Or KeyDown(54))
chat$ = chat$ + "!"
EndIf

If KeyHit(3) And Len(chat$) <= 25 And (KeyDown(42) Or KeyDown(54))
chat$ = chat$ + "@"
EndIf

If KeyHit(4) And Len(chat$) <= 25 And (KeyDown(42) Or KeyDown(54))
chat$ = chat$ + "#"
EndIf

If KeyHit(5) And Len(chat$) <= 25 And (KeyDown(42) Or KeyDown(54))
chat$ = chat$ + "$"
EndIf

If KeyHit(6) And Len(chat$) <= 25 And (KeyDown(42) Or KeyDown(54))
chat$ = chat$ + "%"
EndIf

If KeyHit(7) And Len(chat$) <= 25 And (KeyDown(42) Or KeyDown(54))
chat$ = chat$ + "^"
EndIf

If KeyHit(8) And Len(chat$) <= 25 And (KeyDown(42) Or KeyDown(54))
chat$ = chat$ + "&"
EndIf

If KeyHit(9) And Len(chat$) <= 25 And (KeyDown(42) Or KeyDown(54))
chat$ = chat$ + "*"
EndIf

If KeyHit(10) And Len(chat$) <= 25 And (KeyDown(42) Or KeyDown(54))
chat$ = chat$ + "("
EndIf

If KeyHit(11) And Len(chat$) <= 25 And (KeyDown(42) Or KeyDown(54))
chat$ = chat$ + ")"
EndIf

If KeyHit(12) And Len(chat$) <= 25 And (KeyDown(42) Or KeyDown(54))
chat$ = chat$ + "-"
EndIf

If KeyHit(13) And Len(chat$) <= 25 And (KeyDown(42) Or KeyDown(54))
chat$ = chat$ + "+"
EndIf

If KeyHit(40)
chat$ = chat$ + "'"
EndIf

If KeyHit(51)
chat$ = chat$ + ","
EndIf  

End Function

;==========================================================================

;===== KEYS CONTENT =======================================================

Function LoadKeyboardContent()

keys$(1) = "ESCAPE"
keys$(2) = "1"
keys$(3) = "2"
keys$(4) = "3"
keys$(5) = "4"
keys$(6) = "5"
keys$(7) = "6"
keys$(8) = "7"
keys$(9) = "8"
keys$(10) = "9"
keys$(11) = "0"
keys$(12) = "-"
keys$(13) = "="
keys$(14) = "BACKSPACE"
keys$(15) = "TAB"
keys$(16) = "Q"
keys$(17) = "W"
keys$(18) = "E"
keys$(19) = "R"
keys$(20) = "T"
keys$(21) = "Y"
keys$(22) = "U"
keys$(23) = "I"
keys$(24) = "O"
keys$(25) = "P"
keys$(26) = "["
keys$(27) = "]"
keys$(28) = "ENTER"
keys$(29) = "LEFTCONTROL"
keys$(30) = "A"
keys$(31) = "S"
keys$(32) = "D"
keys$(33) = "F"
keys$(34) = "G"
keys$(35) = "H"
keys$(36) = "J"
keys$(37) = "K"
keys$(38) = "L"
keys$(39) = ";"
keys$(40) = "'"
keys$(41) = "GRAVE"
keys$(42) = "LEFTSHIFT"
keys$(43) = "BACKSLASH()"
keys$(44) = "Z"
keys$(45) = "X"
keys$(46) = "C"
keys$(47) = "V"
keys$(48) = "B"
keys$(49) = "N"
keys$(50) = "M"
keys$(51) = "COMMA(,)"
keys$(52) = "PERIOD(.)"
keys$(53) = "SLASH(/)"
keys$(54) = "RIGHTSHIFT"
keys$(55) = "MULTIPLY(*)NUMPAD"
keys$(56) = "LEFTALT/MENU"
keys$(57) = "SPACE"
keys$(58) = "CAPITAL"
keys$(59) = "F1"
keys$(60) = "F2"
keys$(61) = "F3"
keys$(62) = "F4"
keys$(63) = "F5"
keys$(64) = "F6"
keys$(65) = "F7"
keys$(66) = "F8"
keys$(67) = "F9"
keys$(68) = "F10"
keys$(69) = "NUMLOCK"
keys$(70) = "SCROLLLOCK"
keys$(71) = "NUMPAD7"
keys$(72) = "NUMPAD8"
keys$(73) = "NUMPAD9"
keys$(74) = "SUBTRACT(-)NUMPAD"
keys$(75) = "NUMPAD4"
keys$(76) = "NUMPAD5"
keys$(77) = "NUMPAD6"
keys$(78) = "ADD(+)NUMPAD"
keys$(79) = "NUMPAD1"
keys$(80) = "NUMPAD2"
keys$(81) = "NUMPAD3"
keys$(82) = "NUMPAD0"
keys$(83) = "DECIMAL(.)NUMPAD"
keys$(84) = "-"
keys$(85) = "-"
keys$(86) = "OEM_102"
keys$(87) = "F11"
keys$(88) = "F12"
keys$(89) = "-"
keys$(90) = "-"
keys$(91) = "-"
keys$(92) = "-"
keys$(93) = "-"
keys$(94) = "-"
keys$(95) = "-"
keys$(96) = "-"
keys$(97) = "-"
keys$(98) = "-"
keys$(99) = "-"
keys$(100) = "F13"
keys$(101) = "F14"
keys$(102) = "F15"
keys$(103) = "-"
keys$(104) = "-"
keys$(105) = "-"
keys$(106) = "-"
keys$(107) = "-"
keys$(108) = "-"
keys$(109) = "-"
keys$(110) = "-"
keys$(111) = "-"
keys$(112) = "KANA"
keys$(113) = "-"
keys$(114) = "-"
keys$(115) = "ABNT_C1"
keys$(116) = "-"
keys$(117) = "-"
keys$(118) = "-"
keys$(119) = "-"
keys$(120) = "-"
keys$(121) = "CONVERT"
keys$(122) = "-"
keys$(123) = "NOCONVERT"
keys$(124) = "-"
keys$(125) = "YEN"
keys$(126) = "ABNT_C2"
keys$(127) = "-"
keys$(128) = "-"
keys$(129) = "-"
keys$(130) = "-"
keys$(131) = "-"
keys$(132) = "-"
keys$(133) = "-"
keys$(134) = "-"
keys$(135) = "-"
keys$(136) = "-"
keys$(137) = "-"
keys$(138) = "-"
keys$(139) = "-"
keys$(140) = "-"
keys$(141) = "EQUALS"
keys$(142) = "-"
keys$(143) = "-"
keys$(144) = "PREVTRACK"
keys$(145) = "AT"
keys$(146) = "COLON(:)"
keys$(147) = "UNDERLINE"
keys$(148) = "KANJI"
keys$(149) = "STOP"
keys$(150) = "AX"
keys$(151) = "UNLABELED"
keys$(152) = "-"
keys$(153) = "NEXTTRACK"
keys$(154) = "-"
keys$(155) = "-"
keys$(156) = "ENTER (NUMPAD)"
keys$(157) = "RIGHTCONTROL"
keys$(158) = "-"
keys$(159) = "-"
keys$(160) = "MUTE"
keys$(161) = "CALCULATOR"
keys$(162) = "PLAY/PAUSE"
keys$(163) = "-"
keys$(164) = "MEDIASTOP"
keys$(165) = "-"
keys$(166) = "-"
keys$(167) = "-"
keys$(168) = "-"
keys$(169) = "-"
keys$(170) = "-"
keys$(171) = "-"
keys$(172) = "-"
keys$(173) = "-"
keys$(174) = "VOLUMEDOWN"
keys$(175) = "-"
keys$(176) = "VOLUMEUP"
keys$(177) = "-"
keys$(178) = "WEBHOME"
keys$(179) = "COMMA(,)"
keys$(180) = "-"
keys$(181) = "DIVIDE(/)"
keys$(182) = "-"
keys$(183) = "SYSREQ"
keys$(184) = "RIGHTALT/MENU"
keys$(185) = "-"
keys$(186) = "-"
keys$(187) = "-"
keys$(188) = "-"
keys$(189) = "-"
keys$(190) = "-"
keys$(191) = "-"
keys$(192) = "-"
keys$(193) = "-"
keys$(194) = "-"
keys$(195) = "-"
keys$(196) = "-"
keys$(197) = "PAUSE"
keys$(198) = "-"
keys$(199) = "HOME"
keys$(200) = "UP"
keys$(201) = "PAGEUP/PRIOR"
keys$(202) = "-"
keys$(203) = "LEFT"
keys$(204) = "-"
keys$(205) = "RIGHT"
keys$(206) = "-"
keys$(207) = "END"
keys$(208) = "DOWN"
keys$(209) = "NEXT"
keys$(210) = "INSERT"
keys$(211) = "DELETE"
keys$(212) = "-"
keys$(213) = "-"
keys$(214) = "-"
keys$(215) = "-"
keys$(216) = "-"
keys$(217) = "-"
keys$(218) = "-"
keys$(219) = "LEFTWINDWOS"
keys$(220) = "RIGHTWINDOWS"
keys$(221) = "APPS"
keys$(222) = "POWER"
keys$(223) = "SLEEP"
keys$(224) = "-"
keys$(225) = "-"
keys$(226) = "-"
keys$(227) = "WAKE"
keys$(228) = "-"
keys$(229) = "WEBSEARCH"
keys$(230) = "WEBFAVORITES"
keys$(231) = "WEBREFRESH"
keys$(232) = "WEBSTOP"
keys$(233) = "WEBFORWARD"
keys$(234) = "WEBBACK"
keys$(235) = "MYCOMPUTER"
keys$(236) = "MAIL"
keys$(237) = "MEDIASELECT"

End Function

;==========================================================================



;====== GNET SOURCE CODE ==================================================


Const GNET_HOST$="www.blitzbasic.com"
Const GNET_PORT=80
Const GNET_GET$="/gnet/gnet.php"

Type GNET_Server
Field game$,server$,ip$
End Type

Function GNET_Esc$( t$ )
t$=Replace$( t$,"&","" )
t$=Replace$( t$,"%","" )
t$=Replace$( t$,"'","" )
t$=Replace$( t$,Chr$(34),"" )
t$=Replace$( t$," ","_" )
Return t$
End Function

Function GNET_Open( opt$ )
t=OpenTCPStream( GNET_HOST$,GNET_PORT )
If Not t Return 0

WriteLine t,"GET "+GNET_GET$+"?opt="+opt$+" HTTP/1.0"
WriteLine t,"HOST: "+GNET_HOST$
WriteLine t,""

While ReadLine$(t)<>""
Wend

Return t
End Function

Function GNET_Exec( opt$,game$,server$ )
opt$=opt$+"&game="+GNET_Esc$(game$)
If server$<>"" opt$=opt$+"&server="+GNET_Esc$(server$)
t=GNET_Open( opt$ )
If Not t Return 0

ok=False
If( ReadLine$(t)="OK" ) ok=True

CloseTCPStream t
Return ok
End Function

Function GNET_Ping$()
t=GNET_Open( "ping" )
If Not t Return 0

ip$=ReadLine$(t)

CloseTCPStream t
Return ip$
End Function

Function GNET_AddServer( game$,server$="" )
Return GNET_Exec( "add",game$,server$ )
End Function

Function GNET_RefreshServer( game$,server$="" )
Return GNET_Exec( "ref",game$,server$ )
End Function

Function GNET_RemoveServer( game$ )
Return GNET_Exec( "rem",game$,"" )
End Function

Function GNET_ListServers( game$="" )
Delete Each GNET_Server
t=GNET_Open( "list" )
If Not t Return 0

Repeat
t_game$=ReadLine$(t)
If t_game$="" Exit
t_server$=ReadLine$(t)
t_ip$=ReadLine(t)
If game$="" Or game$=t_game$
p.GNET_Server=New GNET_Server
pgame$=t_game$
pserver$=t_server$
pip$=t_ip$
EndIf
Forever

CloseTCPStream t
Return 1

End Function

;==========================================================================


Comments :


Mustang(Posted 1+ years ago)

 Woot! Have to check this out...


Ricky Smith(Posted 1+ years ago)

 If you can't find anyone to play with you can practise with some Bots !Added Bots with very simple A.I.All Bots are Host controlled and will scan for and attack all human players and will collect weapons/ammo - they use up ammo in exactly the same way as a human player.Bots can have a skill rating of from 1 to 10 affecting rate of turn,rate of fire,alertness and accuracy.You can assign a skill level to all bots or random values.Bots have a kills score as well.Thanks to Fredborg's 3d line of sight function. .bb and .exe<a href="http://webzoom.freewebs.com/smiff/botnetfps.zip" target="_blank">http://webzoom.freewebs.com/smiff/botnetfps.zip</a>
[code]

;====== FPSNet: A NETWORKED FIRST PERSON SHOOTER EXAMPLE ==================
;====== UTILIZING ONLY BUILT IN BLITZ3D FEATURES ==========================
;====== A CODESKETCH BY JEREMY ALESSI =====================================
;====== THANKS MARK SIBLY FOR GNET ========================================

;====== BOT CODE ADDED BY SMIFF 20/09/2004

;====== WASD OR CURSORS MOVE, MOUSE LOOKS, LEFT MOUSE BUTTON SHOOTS =======
;====== SPACE BAR OR 0 ON NUMPAD JUMPS, PRESS C TO CHAT ===================
;====== PRESS 2 TO UNLOCK MOUSE FROM CENTER (USEFUL TO PLAY ===============
;====== AND ALSO BE ABLE TO MULTITASK IF NEED BE) PRESS 1 TO RELOCK =======
;====== MOUSE BACK TO CENTER OF SCREEN ====================================
;====== YEAH EVERYONE HAS THE SOURCE ... DON'T CHEAT! =====================


;====== INCLUDES ==========================================================

;Include "gnet_inc.bb" This is included at the bottom of this source!

;==========================================================================



;====== GRAPHICS ==========================================================

Graphics3D(640, 480, 16, 2)
SetBuffer BackBuffer()
HidePointer

;==========================================================================



;====== COLLISIONS ========================================================

Global BODY = 1
Global SCENE = 2
Collisions(BODY,SCENE, 2, 2)
Collisions(BODY,BODY, 2, 2)

;==========================================================================



;====== GLOBALS ===========================================================

Global gameState$ = "Title Screen"

;Mousehit Vars
Global mb1pressed, mb2pressed

;Keyhit Vars
Global upKeyPressed, downKeyPressed, leftKeyPressed, rightKeyPressed, enterKeyPressed, spaceKeyPressed
Global chatKeyPressed

;Font Vars
Global font, bigFont

;Menu Var
Global menuCount

;Server Vars
Global serverCount
Global serverPointer

;Local Player Network Vars
Global localPlayerName$, localPlayerPointer

;Scenery Vars
Global level,copySprite, lightPivot

;Camera Var
Global camera

;Player Gameplay Vars
Global health#, shot, shot2, shot3, shotTimer#, positionUpdateTimer#, serverRefreshTimer#, hosting
Global vX#, vY#, vZ#, oldX#, oldY#, oldZ#, centerMouse = True, enteringChat = False, chat$
Global copyPowerUp, weapon$ = "Semi-Automatic", powerUpSpawned, ammo# = 50, randPos, randNum
Global justDied#,respawndelay#=7000
;Bot globals
Global bots=1,botskillbots=1,botpositionUpdateTimer#
Global giro=CreatePivot()
;Bot movement constants
Const walk=1
Const backup=2
Const strafeL=4
Const strafeR=8
Const jump=16
Const rotate=32

;bot state constants

Const scan=1
Const attack=2
Const getammo=4
Const respawn=8

;==========================================================================



;====== INCOMING ==========================================================

Dim incoming$(100)

;==========================================================================



;====== CONTENTS OF A KEY =================================================

Dim keys$(237)
LoadKeyboardContent()

;==========================================================================



;====== SHOT ARRAY ========================================================

Dim pickedArray(3,3)

;==========================================================================



;====== TYPES =============================================================

Type Player

   Field iD, name$, mesh[10], score
   
End Type

Global Host.Player

Type Bot

   Field iD, name$, mesh[10],health#,score,weapon,ammo#,skill#,range#,state,seq
   Field firing,shot,shot2,shot3,shotTimer#,target,targetItem,justDied#,botscantime#,timer#
   Field vX#, vY#, vZ#, oldX#, oldY#, oldZ#

End Type

Dim Botnames$(3,10)

Type Particle
   
   Field mesh, name$, alpha#
   Field vX#, vY#, vZ#
   
End Type

Type chatMsg
   
   Field msg$, born#, from
   
End Type

Type powerUp

   Field mesh, name$,iD
   
End Type

;==========================================================================



;====== INITIAL SETUP =====================================================

Setup("Title Screen")

;==========================================================================



;==========================================================================
.Main
;====== RUN ===============================================================
period=1000 / 30
tweentime = MilliSecs()-period
While 1
;====== CALCULATE TWEEN ===================================================
   Repeat
      elapsed = MilliSecs() - tweentime
   Until elapsed
   ticks = elapsed/period
   tween# = Float(elapsed Mod period) / Float(period)
;==========================================================================

;====== MAIN LOOP =========================================================
   For k=1 To ticks
      tweentime = tweentime+period
      If k = ticks Then CaptureWorld
      If KeyDown(1)
         If Not GNET_RemoveServer("BOT-FPSNetUpdate")
            If hosting = True
               RuntimeError "Failed to remove server"
            EndIf
         EndIf
         ClearWorld()
         End
      EndIf
      UpdateLogic()
      UpdateWorld
   Next
   RenderWorld(tween#)
   Draw()
   Flip
Wend
;===========================================================================



;====== UPDATE LOGIC =======================================================

Function UpdateLogic()
   
   Select gameState$
      
      Case "Title Screen"
         UpdateTitleInput()
         UpdateTitleScreen()
      Case "Game"
         DetectPowerUpCollision()
         UpdateGameInput()
         ControlChat()
         UpdateLights()
         UpdateBots()
         UpdateCamera()
         UpdatePlayerMovement()
         HostSpawnPowerups()
         UpdateParticles()
         UpdateNetwork()
         UpdateCenterMouse()
   End Select
   
End Function

;===========================================================================



;====== DRAW ===============================================================

Function Draw()

   Select gameState$
   
      Case "Title Screen"
         DrawTitleScreen()
      Case "Game"
         DrawGamePlay()
      
   End Select
   
End Function

;===========================================================================



;====== UPDATE TITLE INPUT =================================================

Function UpdateTitleInput()

   mb1pressed = MouseHit(1)
   
   mb2pressed = MouseHit(2)
   
   upKeyPressed = KeyHit(17) Or KeyHit(200)
   
   downKeyPressed = KeyHit(31) Or KeyHit(208)
   
   leftKeyPressed = KeyHit(30) Or KeyHit(203)
   
   rightKeyPressed = KeyHit(32) Or KeyHit(205)
   
   enterKeyPressed = KeyHit(28)
   
   spaceKeyPressed = KeyHit(57)
   
      
End Function

;===========================================================================



;====== UPDATE GAME INPUT ==================================================

Function UpdateGameInput()

   chatKeyPressed = KeyHit(46)
   
   enterKeyPressed = KeyHit(28)
      
End Function

;===========================================================================



;====== UPDATE CENTER MOUSE ================================================

Function UpdateCenterMouse()

   If centerMouse = True
      MoveMouse(CorrectX(320), CorrectY(240))
   EndIf
   If KeyHit(2)
      centerMouse = True
   EndIf
   If KeyHit(3)
      centerMouse = False
   EndIf

End Function

;===========================================================================



;====== UPDATE TITLE SCREEN ================================================

Function UpdateTitleScreen()

   If upKeyPressed And menuCount > 0
      menuCount = menuCount - 1
   EndIf
   
   If downKeyPressed And menuCount < serverCount - 1
      menuCount = menuCount + 1
   EndIf
   
   If enterKeyPressed
      gns.GNET_Server = Object.GNET_Server(serverPointer)
      If JoinNetGame(gnsserver$, gnsip$)
         FlushKeys
         Color(255,0,0)
         Locate(200,130)
         localPlayerName$ = Input("Name - ")
         Delay(500)
         FlushKeys
         p.Player = New Player
         localPlayerPointer = Handle(p.Player)
         piD = CreateNetPlayer(localPlayerName$)
         Setup("Game")
         hosting = False
      EndIf
   EndIf
   
   If spaceKeyPressed
      FlushKeys
      Color(255,0,0)
      Locate(150,130)
      localPlayerName$ = Input("Name - ")
      Locate(150,150)
      bots=Input("Number of Bots (Recommended Max 8)(0=None) - ")
      If bots>8 bots=8
      If bots>0 Then
      FillBotNames()
         Locate(150,170)
         botskill=Input("Bot Skill 1-10 (0=Random) - ")
      End If
      If botskill>10 botskill=10
      Delay(500)
      FlushKeys
      If HostNetGame(localPlayerName$) = 2
         
         If GNET_AddServer("BOT-FPSNetUpdate", localPlayerName$)
            p.Player = New Player
            localPlayerPointer = Handle(p.Player)
            piD = CreateNetPlayer(localPlayerName$)
            Setup("Game")
            hosting = True
            serverRefreshTimer# = MilliSecs()
            Host.Player=p.Player
         Else
            RuntimeError("Failed to Add Server!")
         EndIf
            
      Else
         
         RuntimeError("Failed to Create Net Game!")   
            
      EndIf
      
      For x=1 To bots
      HostSpawnBots()
      Next
      
   EndIf
      
      

End Function



;===========================================================================



;====== UPDATE PLAYER MOVEMENT =============================================

Function UpdatePlayerMovement()

   If enteringChat Return

   p.Player = Object.Player(localPlayerPointer)
   
   oldX# = EntityX(pmesh[1])
   oldY# = EntityY(pmesh[1])
   oldZ# = EntityZ(pmesh[1])
   
   If KeyDown(17) Or KeyDown(200)
      MoveEntity(pmesh[1], 0, 0, .5)
   EndIf
   If KeyDown(31) Or KeyDown(208)
      MoveEntity(pmesh[1], 0, 0, -.5)
   EndIf
   If KeyDown(30) Or KeyDown(203)
      MoveEntity(pmesh[1], -.5, 0, 0)
   EndIf
   If KeyDown(32) Or KeyDown(205)
      MoveEntity(pmesh[1], .5, 0, 0)
   EndIf
   
   numColls = CountCollisions(pmesh[1])
   
   If numColls = 0
      vY# = vY# - .01
   Else
      vY# = 0
   EndIf
   
   If (KeyDown(57) Or KeyDown(82)) And numColls > 0
      vY# = .2
   EndIf
      
   TranslateEntity(pmesh[1],0, vY#, 0)      
   RotateEntity(pmesh[1], 0, EntityYaw(pmesh[1]) - MouseXSpeed(), 0)
   
   vX# = EntityX(pmesh[1]) - oldX#
   vY# = EntityY(pmesh[1]) - oldY#
   vZ# = EntityZ(pmesh[1]) - oldZ#
         
End Function


;===========================================================================



;====== UPDATE BOTS =======================================================
Function UpdateBots()
   p.Player = Object.Player(localPlayerPointer)

   If Not hosting Then Return
   
   
   
   For b.bot=Each bot
   
   ; State Defaults
   If bstate=0 bstate=scan
   If bseq=0 bseq=rotate
   If bammo#<.1 Then
        bstate=getammo
   End If
   
   Select bstate
   
   Case respawn
      bseq=rotate
      If b   imer#+respawndelay# < MilliSecs()
         EntityAlpha bmesh[1],1
         EntityAlpha bmesh[2],1
         bstate=scan
         SendNetMsg(96,biD+",1-",piD,0,1)
      End If
   
   Case Scan
   
      bseq=rotate
      If botscantime# + 1000 <MilliSecs()
      
         d1=10000
         d2=0
         
         For op.player=Each player
            d2= EntityDistance(bmesh[1],opmesh[1])
            If d2=<d1 Then
               If LineOfSight3D(bmesh[1],opmesh[1],1000.00)
                  b   arget=opmesh[1]
                  bstate=attack
               End If
               d1=d2
            End If
         Next
         
         
         
         botscantime#=MilliSecs()
      End If   
      
   Case attack
      
      If b   arget >0
         PositionEntity giro,EntityX(bmesh[1]),EntityY(bmesh[1]),EntityZ(bmesh[1])
         PointEntity giro,b   arget
               
               turn#=20-bskill#
               tx#=curveangle#(EntityPitch(giro),EntityPitch(bmesh[1]),turn#)
               ty#=curveangle#(EntityYaw(giro),EntityYaw(bmesh[1]),turn#)
               
               RotateEntity bmesh[1],tx#,ty#,0
               If EntityDistance(bmesh[1],b   arget)<bange#
                  bseq=jump
                  If LineOfSight3D(bmesh[1],b   arget,bange,90-bskill)
                     bfiring=True;not yet used !
                     shoot=Rand(1,15-bskill)
                  If shoot=1 Then   Botshoot(b.bot)
                  Else
                     bfiring=False
                  End If
               Else
                  bseq=walk
                  bfiring=False
               End If
      Else
               bstate=scan
               bfiring=False
               
      End If   
      
      
      Case getammo
      bseq=walk
      If powerUpSpawned
         pup.powerUp=First powerUp
         b   argetItem=pupmesh
         PositionEntity giro,EntityX(bmesh[1]),EntityY(bmesh[1]),EntityZ(bmesh[1])
         PointEntity giro,b   argetItem
               
               turn#=10-bskill#;allow more agility when collectimg items
               tx#=curveangle#(EntityPitch(giro),EntityPitch(bmesh[1]),turn#)
               ty#=curveangle#(EntityYaw(giro),EntityYaw(bmesh[1]),turn#)
               
               RotateEntity bmesh[1],tx#,ty#,0
               If DetectBotPowerUpCollision(b.bot)
                  bstate=attack                  
               End If
      
      End If         
      



   End Select
   Next
   
   
   
.movebot   
   
   For b.bot = Each bot
   numColls = CountCollisions(bmesh[1])
   boldX# = EntityX(bmesh[1])
   boldY# = EntityY(bmesh[1])
   boldZ# = EntityZ(bmesh[1])
   
   If (bseq And walk) ;KeyDown(17) Or KeyDown(200)
      If b   arget>0
         d#=EntityDistance(bmesh[1],b   arget)
            
         
               speed#=curvevalue#(d,bvZ#,20)
               If speed#>.5 speed#=.5
               
               MoveEntity(bmesh[1], 0, 0, speed#)
            
      Else
         MoveEntity(bmesh[1], 0, 0, .5)
      End If
   EndIf
   If bseq And backup;KeyDown(31) Or KeyDown(208)
      MoveEntity(bmesh[1], 0, 0, -.5)
   EndIf
   If bseq And strafeL;KeyDown(30) Or KeyDown(203)
      MoveEntity(bmesh[1], -.5, 0, 0)
   EndIf
   If bseq And strafeR;KeyDown(32) Or KeyDown(205)
      MoveEntity(bmesh[1], .5, 0, 0)
   EndIf
   If bseq And rotate
      TurnEntity (bmesh[1],0,.5+(bskill/20),0)
   End If
   
   ;numColls = CountCollisions(bmesh[1])
   
   If numColls = 0
      bvY# = bvY# - .01
   Else
      bvY# = 0
   EndIf
   
   If bseq = jump And (EntityCollided(bmesh[1],SCENE)>0)
      bvY# = .2
   EndIf
      
   TranslateEntity(bmesh[1],0, bvY#, 0)      
   
   
   bvX# = EntityX(bmesh[1]) - boldX#
   bvY# = EntityY(bmesh[1]) - boldY#
   bvZ# = EntityZ(bmesh[1]) - boldZ#
         


   Next












   If botpositionUpdateTimer# + 50 < MilliSecs()

      p.Player = Object.Player(localPlayerPointer)
      For b.bot= Each bot
         SendNetMsg(91, biD+","+EntityX(bmesh[1]) + "," + EntityY(bmesh[1]) + "," + EntityZ(bmesh[1]) + "," + EntityPitch(bmesh[1]) + "," + EntityYaw(bmesh[1]) + "," + bscore+ "," +bammo+ "," +bstate + "," +bseq + "," +bhealth + "," + bweapon +" ," + bange +"-", piD, 0, 0)
      
      Next
      botpositionUpdateTimer# = MilliSecs()
   EndIf


End Function

Function BotShoot(b.bot)


p.Player = Object.Player(localPlayerPointer)

      TFormVector 0,0,100,bmesh[1],0
      Local dx# = TFormedX()
      Local dy# = TFormedY()
      Local dz# = TFormedZ()


   bshot = 0
   bshot2 = 0
   bshot3 = 0
         Select bweapon
      
         Case 1;"Semi-Automatic"
            If bshotTimer# + 200 < MilliSecs() And bammo# > 0
               bammo# = bammo# - 1
               bshot = LinePick(EntityX(bmesh[1]),EntityY(bmesh[1]),EntityZ(bmesh[1]), dx#,dy#,dz#,0.1)
               bshotTimer# = MilliSecs()
               If bshot
                  CreateSomeParticles(PickedX(), PickedY(), PickedZ(), 50, 50, 50, 10)
                  SendNetMsg(4,"1," + PickedX() + "," + PickedY() + "," + PickedZ() + "-", piD, 0, 0)
               EndIf
            EndIf
         Case 2;"Shotgun"
            If bshotTimer# + 750 < MilliSecs() And bammo# >= 3
               bammo# = bammo# - 3
               For i = 1 To 3
                  
                  Select i
                     Case 1
                        bshot = LinePick(EntityX(bmesh[1])-0.5,EntityY(bmesh[1]),EntityZ(bmesh[1]), dx#-0.5,dy#,dz#,0.01)
                     Case 2
                        bshot2 = LinePick(EntityX(bmesh[1]),EntityY(bmesh[1]),EntityZ(bmesh[1]), dx#,dy#,dz#,0.01)
                     Case 3
                        bshot3 = LinePick(EntityX(bmesh[1])+0.5,EntityY(bmesh[1]),EntityZ(bmesh[1]), dx#+0.5,dy#,dz#,0.01)
                  End Select
               
                  pickedArray(i,1) = PickedX()
                  pickedArray(i,2) = PickedY()
                  pickedArray(i,3) = PickedZ()
               
               Next
               bshotTimer# = MilliSecs()
               If bshot Or bshot2 Or bshot3
                  For i = 1 To 3
                     If (i = 1 And bshot <> 0) Or (i = 2 And bshot2 <> 0) Or (i = 3 And bshot3 <> 0)
                        CreateSomeParticles(pickedArray(i,1), pickedArray(i,2), pickedArray(i,3), 200, 200, 200, 10)
                     EndIf
                  Next
                  SendNetMsg(4,"2," + pickedArray(1,1) + "," + pickedArray(1,2) + "," + pickedArray(1,3) + "," + pickedArray(2,1) + "," + pickedArray(2,2) + "," + pickedArray(2,3) + "," + pickedArray(3,1) + "," + pickedArray(3,2) + "," + pickedArray(3,3) + "-", piD, 0, 0)
               EndIf
            EndIf
         Case 3;"Flamethrower"
            If bshotTimer# + 50 < MilliSecs() And bammo# >= .1
               bammo# = bammo# - .1
               pvX# = bvX# + (EntityX(bmesh[3], True) - EntityX(bmesh[2], True)) / 10
               pvY# = bvY# + (EntityY(bmesh[3], True) - EntityY(bmesh[2], True)) / 10
               pvZ# = bvZ# + (EntityZ(bmesh[3], True) - EntityZ(bmesh[2], True)) / 10
               
               SendNetMsg(90, pvX# + "," + pvY# + "," + pvZ# + ","+biD+ "-", piD, 0, 0)
               CreateSomeParticles(EntityX(bmesh[2],True), EntityY(bmesh[2], True), EntityZ(bmesh[2], True), 255, 200, 100, 10,  pvX# + Rnd(-.05, .05), pvY# + Rnd(-.05, .05), pvZ#, "Flame")
               bshot = LinePick(EntityX(bmesh[1], True), EntityY(bmesh[1], True), EntityZ(bmesh[1], True), EntityX(bmesh[3], True) - EntityX(bmesh[1], True), EntityY(bmesh[3], True) - EntityY(bmesh[1], True), EntityZ(bmesh[3], True) - EntityZ(bmesh[1], True))
               shotTimer# = MilliSecs()
               If bshot
                  CreateSomeParticles(PickedX(), PickedY(), PickedZ(), 255, 200, 100, 10, "Flame")
                  SendNetMsg(4,"3," + PickedX() + "," + PickedY() + "," + PickedZ() + "-", piD, 0, 0)
               EndIf
            EndIf
      
      End Select
               
   



;;;
   For op.Player = Each Player
      Select bweapon
      
         Case 1;"Semi-Automatic"
            If bshot = opmesh[1]
               
               CreateSomeParticles(PickedX(), PickedY(), PickedZ(), 255, 0, 0, 10)
               
               If Handle(op.Player)=localPlayerPointer
                  health#=health#-5
                  SendNetMsg(5, "1,10-", piD, 0, 0)
               Else
                  SendNetMsg(2, "1,"+biD+"-", piD, opiD, 0)   
               End If
            EndIf
         Case 2;"Shotgun"
            If bshot = opmesh[1] Or shot2 = opmesh[1] Or shot3 = opmesh[1]
               Select opmesh[1]
                  Case bshot
                        If Handle(op.Player)=localPlayerPointer
                           health#=health#-5
                           SendNetMsg(5, "2,10-", piD, 0, 0)
                           
                        End If

                     CreateSomeParticles(pickedArray(1, 1), pickedArray(1, 2), pickedArray(1, 3), 255, 0, 0, 10)
                  Case bshot2
                     If Handle(op.Player)=localPlayerPointer
                           health#=health#-5
                           SendNetMsg(5, "2,10-", piD, 0, 0)
                           
                        End If
                     CreateSomeParticles(pickedArray(2, 1), pickedArray(2, 2), pickedArray(2, 3), 255, 0, 0, 10)
                  Case bshot3
                     If Handle(op.Player)=localPlayerPointer
                           health#=health#-5
                           SendNetMsg(5, "2,10-", piD, 0, 0)
                        
                        End If
                     CreateSomeParticles(pickedArray(3, 1), pickedArray(3, 2), pickedArray(3, 3), 255, 0, 0, 10)
               End Select
               SendNetMsg(2, "2," + Left(Str(shot), 1) + "," + Left(Str(shot2), 1) + "," + Left(Str(shot3), 1)+","+biD+"-", piD, opiD, 0)
            EndIf
         Case 3;"Flamethrower"
            If bshot = opmesh[1]
               CreateSomeParticles(PickedX(), PickedY(), PickedZ(), 255, 0, 0, 10)
                     If Handle(op.Player)=localPlayerPointer
                           health#=health#-10
                           SendNetMsg(5, "3,10-", piD, 0, 0)
                        Else
                           SendNetMsg(2, "3,"+biD+"-", piD, opiD ,0)   
                     End If
               
            EndIf
      
      End Select
      
      
      If health# <= 0;respawn
               health# = 100
               
            ;   SendNetMsg(3, "1", piD, NetMsgFrom(), 1)
               bscore=bscore+1
               b   arget=0
               bstate=scan