Add code, unknown original date

This commit is contained in:
2026-05-18 12:41:53 -04:00
commit 7fddc22283
2373 changed files with 3420614 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
K 25
svn:wc:ra_dav:version-url
V 71
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame
END

View File

@@ -0,0 +1,40 @@
10
dir
44
https://127.0.0.1/svn/aklabs/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame
https://127.0.0.1/svn/aklabs
2007-05-26T21:34:02.309037Z
9
andrew
eb184899-6090-47d4-a65b-558f62f6ea1c
game
dir
CVS
dir
cgame
dir
ui
dir

View File

@@ -0,0 +1,29 @@
K 25
svn:wc:ra_dav:version-url
V 75
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/CVS
END
Repository
K 25
svn:wc:ra_dav:version-url
V 86
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/CVS/Repository
END
Root
K 25
svn:wc:ra_dav:version-url
V 80
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/CVS/Root
END
Entries
K 25
svn:wc:ra_dav:version-url
V 83
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/CVS/Entries
END
Entries.Log
K 25
svn:wc:ra_dav:version-url
V 87
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/CVS/Entries.Log
END

View File

@@ -0,0 +1,164 @@
10
dir
44
https://127.0.0.1/svn/aklabs/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/CVS
https://127.0.0.1/svn/aklabs
2007-05-26T21:34:02.309037Z
9
andrew
eb184899-6090-47d4-a65b-558f62f6ea1c
Repository
file
2010-02-05T03:38:19.370123Z
2e0b624d7e9b8e488e12d51c54ab5117
2007-05-26T21:34:02.309037Z
9
andrew
56
Root
file
2010-02-05T03:38:19.370123Z
7af14a164593104c1e7a07a572dd352a
2007-05-26T21:34:02.309037Z
9
andrew
24
Entries
file
2010-02-05T03:38:19.385748Z
57b8d745384127342f95660d97e1c9c2
2007-05-26T21:34:02.309037Z
9
andrew
2
Entries.Log
file
2010-02-05T03:38:19.385748Z
3bfbaaf494411b9ccd4c580f75b41a89
2007-05-26T21:34:02.309037Z
9
andrew
38

View File

@@ -0,0 +1,3 @@
A D/cgame////
A D/game////
A D/ui////

View File

@@ -0,0 +1 @@
D

View File

@@ -0,0 +1 @@
games/quake3/hypermod/code/debug-x86-Linux-2.3/TA/cgame

View File

@@ -0,0 +1 @@
andrew@gabbo:/home/cvsd

View File

@@ -0,0 +1 @@
D

View File

@@ -0,0 +1,3 @@
A D/cgame////
A D/game////
A D/ui////

View File

@@ -0,0 +1 @@
games/quake3/hypermod/code/debug-x86-Linux-2.3/TA/cgame

View File

@@ -0,0 +1 @@
andrew@gabbo:/home/cvsd

View File

@@ -0,0 +1,65 @@
cg_draw.o:1080791483 428bd99ef6939172c281bff5bf9e8499
cg_weapons.asm:1080791512 c9e5088c9a5822948f2b011bcc0d5af2
cg_event.asm:1080791512 19ea311f9263ccb603f1ca8804d40e70
cg_event.c:1080784657 - d15df26c8f572b72ec9a53978c6af5fa
cg_view.o:1080791488 3c6e729e1201d1fda50a3d9fca105fe3
cgamei386.so:1080791491 526bb6ce786edd562e145509e30883e2
cg_syscalls.c:1080784657 - 22fdc7ddb48285ddcdc3365d99684eec
cg_localents.asm:1080791512 05a5a6fe722751a036182ac4d8f507d6
cg_local.h:1080784657 - b057d91af178a987ad8a5fbd82b9f298
cg_predict.asm:1080791512 efe4dc0ac9de584e588afdaa6265a4c7
cg_syscalls.o:1080791489 6edc24aa88a5777c14eeff2d5e51e7d6
cg_marks.c:1080784657 - 0b8005ee129e94f6d00ac6de7db8b1b4
cg_draw.c:1080784657 - 50d395cfdb1321fd867e5c94be1dd48c
cg_weapons.o:1080791489 46fbd9fd0cc392e8881db815cf4843f0
cg_main.asm:1080791511 6f61543cf4c137184c28d35630dee213
cg_players.asm:1080791512 d97b8ea33e013a214091fcf16277e404
cg_scoreboard.o:1080791487 efbada1da79dc4861380a3165d0ba71d
cg_weapons.c:1080784657 - 43b9281a97eb5e15915b4728b573a1e7
cg_localents.o:1080791485 94727b68da2b925c37eccb1754494680
cg_public.h:1080784657 - a3c0dd7a5eea4276eecf72fd6e4e8033
cg_scoreboard.c:1080784657 - 40209f2555c330cc002f7dcaf39fa7d6
cg_servercmds.asm:1080791512 c3da6e7a5698c4edc71b415974863d6b
cg_event.o:1080791484 b2a28e255a72c841fb304d32dbbc6c99
tr_types.h:1080784657 - 3c0832ac2e6d1f188b3781f8b7066020
cg_marks.o:1080791486 187712749f15c78bde81b31845cfeb7e
cg_ents.asm:1080791511 9f8f96fc9670642e9f78cb7441dbb98a
cg_view.asm:1080791512 540237cb53d7d953f81a55c7d1905773
cg_ents.o:1080791484 af39713d4885c2b8bad833cc11c6fc80
cg_predict.o:1080791487 6c560ded9e4606bec7b1a416574dcd37
cg_newdraw.o:1080791490 6411332d4fe28d8f397a9f6b89022942
cg_info.o:1080791485 38bf492ec70499a91ecabc40f74bba5b
cg_predict.c:1080784657 - 3f8ed64bd3b44b9e38ec92adc2e71931
cg_info.asm:1080791512 538955ccd7323e10a767b38bea5b4d1f
cg_players.c:1080784657 - 0c2e2ceb72088443e4960d7591d29f50
cg_main.o:1080791481 fb3f88554aa0c07d3bb9ff7add1f6d18
cg_newdraw.c:1080784657 - 9a34daca3f145a074abcf894fc9464de
cg_main.c:1080784657 - 101b3885fff8d7baf8e4ddbc04f476d7
cg_newdraw.asm:1080791512 825d2c585b3d9dc37d8e0e2f62a93290
cgame.qvm:1080791517 e9829b8896cb1db9b8fb6f1c10882ef7
cg_drawtools.o:1080791483 30fa3ab380fd6987132b2600b8f4cd59
cg_draw.asm:1080791511 d398bb67a43d716b481eb02384f8c2ee
cg_view.c:1080784657 - 8be552e6cbfdaacfaa9846d320b2ac87
cg_consolecmds.c:1080784657 - 802e531b835824b793f522fb555c4dad
cg_syscalls.asm:1080784657 - 667b53ae03139e3a5bafa176d234f859
cg_drawtools.c:1080784657 - 1dda97d31902f3ee93bc45f53f913012
cg_localents.c:1080784657 - adcfb9d3690f417628feeb9f9ef67cf3
cg_players.o:1080791486 e45495dfd0a1e7d83f2cc9f357884f7b
cg_consolecmds.asm:1080791511 ead1a1a81ac4366999727ae7c2120c92
cg_playerstate.c:1080784657 - bb774d9b112cc40e87507d592db6162d
cg_ents.c:1080784657 - 7507cd68ae25a485370ced0af66b4995
cg_playerstate.asm:1080791512 0f3dde705b7a56ff7c96362adc8d47a4
cg_drawtools.asm:1080791511 8137caefcc941326b26c5239361f2813
cg_servercmds.o:1080791488 08db7ab9fff94f5015a8819d7aad089e
cg_info.c:1080784657 - d1c7d2583deefcbc4f40f5a8108c363b
cg_effects.o:1080791484 f3fa3d1620abbc533d37a103b0ce39a0
cg_snapshot.c:1080784657 - e318325bfbe9dcc3ec7811d1401cd03c
cg_consolecmds.o:1080791483 e896d34d18f12c2db5617d3a5e6eb227
cg_effects.c:1080784657 - 935965234b364388481325b7ac2baf91
cg_marks.asm:1080791512 29ab1b4167a34f8afcde2e92fa8f200f
cg_snapshot.o:1080791488 da1ed91f6452903841d3df5a950b145b
cg_servercmds.c:1080784657 - 23db883fd3e26c623a3a56e14a5023ef
cg_playerstate.o:1080791487 a90c8881a6cecb31bc0ff86e785fd860
cg_scoreboard.asm:1080791512 d458791e083b28075e7a07b87ff567b8
cg_effects.asm:1080791511 de9a6dd05b4cc925211944a94c334079
cg_snapshot.asm:1080791512 9d805d7e27fc2b4088f518a9fed0ea65

View File

@@ -0,0 +1,275 @@
K 25
svn:wc:ra_dav:version-url
V 77
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame
END
cg_predict.asm
K 25
svn:wc:ra_dav:version-url
V 92
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_predict.asm
END
cg_predict.c
K 25
svn:wc:ra_dav:version-url
V 90
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_predict.c
END
cg_playerstate.asm
K 25
svn:wc:ra_dav:version-url
V 96
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_playerstate.asm
END
cg_playerstate.c
K 25
svn:wc:ra_dav:version-url
V 94
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_playerstate.c
END
cg_snapshot.asm
K 25
svn:wc:ra_dav:version-url
V 93
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_snapshot.asm
END
cgame.map
K 25
svn:wc:ra_dav:version-url
V 87
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cgame.map
END
cg_local.h
K 25
svn:wc:ra_dav:version-url
V 88
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_local.h
END
cg_snapshot.c
K 25
svn:wc:ra_dav:version-url
V 91
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_snapshot.c
END
cg_weapons.asm
K 25
svn:wc:ra_dav:version-url
V 92
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_weapons.asm
END
cg_marks.asm
K 25
svn:wc:ra_dav:version-url
V 90
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_marks.asm
END
cg_drawtools.asm
K 25
svn:wc:ra_dav:version-url
V 94
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_drawtools.asm
END
cg_weapons.c
K 25
svn:wc:ra_dav:version-url
V 90
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_weapons.c
END
cg_players.asm
K 25
svn:wc:ra_dav:version-url
V 92
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_players.asm
END
cg_marks.c
K 25
svn:wc:ra_dav:version-url
V 88
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_marks.c
END
cg_drawtools.c
K 25
svn:wc:ra_dav:version-url
V 92
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_drawtools.c
END
cg_players.c
K 25
svn:wc:ra_dav:version-url
V 90
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_players.c
END
cg_event.asm
K 25
svn:wc:ra_dav:version-url
V 90
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_event.asm
END
cg_event.c
K 25
svn:wc:ra_dav:version-url
V 88
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_event.c
END
cg_localents.asm
K 25
svn:wc:ra_dav:version-url
V 94
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_localents.asm
END
cg_localents.c
K 25
svn:wc:ra_dav:version-url
V 92
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_localents.c
END
cg_info.asm
K 25
svn:wc:ra_dav:version-url
V 89
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_info.asm
END
cg_draw.asm
K 25
svn:wc:ra_dav:version-url
V 89
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_draw.asm
END
cg_info.c
K 25
svn:wc:ra_dav:version-url
V 87
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_info.c
END
cg_syscalls.asm
K 25
svn:wc:ra_dav:version-url
V 93
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_syscalls.asm
END
cg_draw.c
K 25
svn:wc:ra_dav:version-url
V 87
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_draw.c
END
cg_syscalls.c
K 25
svn:wc:ra_dav:version-url
V 91
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_syscalls.c
END
cg_newdraw.asm
K 25
svn:wc:ra_dav:version-url
V 92
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_newdraw.asm
END
tr_types.h
K 25
svn:wc:ra_dav:version-url
V 88
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/tr_types.h
END
cg_newdraw.c
K 25
svn:wc:ra_dav:version-url
V 90
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_newdraw.c
END
cg_consolecmds.asm
K 25
svn:wc:ra_dav:version-url
V 96
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_consolecmds.asm
END
cg_ents.asm
K 25
svn:wc:ra_dav:version-url
V 89
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_ents.asm
END
cg_view.asm
K 25
svn:wc:ra_dav:version-url
V 89
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_view.asm
END
cg_consolecmds.c
K 25
svn:wc:ra_dav:version-url
V 94
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_consolecmds.c
END
cg_ents.c
K 25
svn:wc:ra_dav:version-url
V 87
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_ents.c
END
cg_view.c
K 25
svn:wc:ra_dav:version-url
V 87
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_view.c
END
cg_servercmds.asm
K 25
svn:wc:ra_dav:version-url
V 95
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_servercmds.asm
END
cg_effects.asm
K 25
svn:wc:ra_dav:version-url
V 92
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_effects.asm
END
cg_servercmds.c
K 25
svn:wc:ra_dav:version-url
V 93
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_servercmds.c
END
cg_effects.c
K 25
svn:wc:ra_dav:version-url
V 90
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_effects.c
END
cg_scoreboard.asm
K 25
svn:wc:ra_dav:version-url
V 95
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_scoreboard.asm
END
cg_main.asm
K 25
svn:wc:ra_dav:version-url
V 89
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_main.asm
END
cg_public.h
K 25
svn:wc:ra_dav:version-url
V 89
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_public.h
END
cg_scoreboard.c
K 25
svn:wc:ra_dav:version-url
V 93
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_scoreboard.c
END
cg_main.c
K 25
svn:wc:ra_dav:version-url
V 87
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/cg_main.c
END
.consign
K 25
svn:wc:ra_dav:version-url
V 86
/svn/aklabs/!svn/ver/9/trunk/hypermod/code/debug-x86-Linux-2.3/TA/cgame/cgame/.consign
END

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,5 @@
K 14
svn:executable
V 0
END

View File

@@ -0,0 +1,65 @@
cg_draw.o:1080791483 428bd99ef6939172c281bff5bf9e8499
cg_weapons.asm:1080791512 c9e5088c9a5822948f2b011bcc0d5af2
cg_event.asm:1080791512 19ea311f9263ccb603f1ca8804d40e70
cg_event.c:1080784657 - d15df26c8f572b72ec9a53978c6af5fa
cg_view.o:1080791488 3c6e729e1201d1fda50a3d9fca105fe3
cgamei386.so:1080791491 526bb6ce786edd562e145509e30883e2
cg_syscalls.c:1080784657 - 22fdc7ddb48285ddcdc3365d99684eec
cg_localents.asm:1080791512 05a5a6fe722751a036182ac4d8f507d6
cg_local.h:1080784657 - b057d91af178a987ad8a5fbd82b9f298
cg_predict.asm:1080791512 efe4dc0ac9de584e588afdaa6265a4c7
cg_syscalls.o:1080791489 6edc24aa88a5777c14eeff2d5e51e7d6
cg_marks.c:1080784657 - 0b8005ee129e94f6d00ac6de7db8b1b4
cg_draw.c:1080784657 - 50d395cfdb1321fd867e5c94be1dd48c
cg_weapons.o:1080791489 46fbd9fd0cc392e8881db815cf4843f0
cg_main.asm:1080791511 6f61543cf4c137184c28d35630dee213
cg_players.asm:1080791512 d97b8ea33e013a214091fcf16277e404
cg_scoreboard.o:1080791487 efbada1da79dc4861380a3165d0ba71d
cg_weapons.c:1080784657 - 43b9281a97eb5e15915b4728b573a1e7
cg_localents.o:1080791485 94727b68da2b925c37eccb1754494680
cg_public.h:1080784657 - a3c0dd7a5eea4276eecf72fd6e4e8033
cg_scoreboard.c:1080784657 - 40209f2555c330cc002f7dcaf39fa7d6
cg_servercmds.asm:1080791512 c3da6e7a5698c4edc71b415974863d6b
cg_event.o:1080791484 b2a28e255a72c841fb304d32dbbc6c99
tr_types.h:1080784657 - 3c0832ac2e6d1f188b3781f8b7066020
cg_marks.o:1080791486 187712749f15c78bde81b31845cfeb7e
cg_ents.asm:1080791511 9f8f96fc9670642e9f78cb7441dbb98a
cg_view.asm:1080791512 540237cb53d7d953f81a55c7d1905773
cg_ents.o:1080791484 af39713d4885c2b8bad833cc11c6fc80
cg_predict.o:1080791487 6c560ded9e4606bec7b1a416574dcd37
cg_newdraw.o:1080791490 6411332d4fe28d8f397a9f6b89022942
cg_info.o:1080791485 38bf492ec70499a91ecabc40f74bba5b
cg_predict.c:1080784657 - 3f8ed64bd3b44b9e38ec92adc2e71931
cg_info.asm:1080791512 538955ccd7323e10a767b38bea5b4d1f
cg_players.c:1080784657 - 0c2e2ceb72088443e4960d7591d29f50
cg_main.o:1080791481 fb3f88554aa0c07d3bb9ff7add1f6d18
cg_newdraw.c:1080784657 - 9a34daca3f145a074abcf894fc9464de
cg_main.c:1080784657 - 101b3885fff8d7baf8e4ddbc04f476d7
cg_newdraw.asm:1080791512 825d2c585b3d9dc37d8e0e2f62a93290
cgame.qvm:1080791517 e9829b8896cb1db9b8fb6f1c10882ef7
cg_drawtools.o:1080791483 30fa3ab380fd6987132b2600b8f4cd59
cg_draw.asm:1080791511 d398bb67a43d716b481eb02384f8c2ee
cg_view.c:1080784657 - 8be552e6cbfdaacfaa9846d320b2ac87
cg_consolecmds.c:1080784657 - 802e531b835824b793f522fb555c4dad
cg_syscalls.asm:1080784657 - 667b53ae03139e3a5bafa176d234f859
cg_drawtools.c:1080784657 - 1dda97d31902f3ee93bc45f53f913012
cg_localents.c:1080784657 - adcfb9d3690f417628feeb9f9ef67cf3
cg_players.o:1080791486 e45495dfd0a1e7d83f2cc9f357884f7b
cg_consolecmds.asm:1080791511 ead1a1a81ac4366999727ae7c2120c92
cg_playerstate.c:1080784657 - bb774d9b112cc40e87507d592db6162d
cg_ents.c:1080784657 - 7507cd68ae25a485370ced0af66b4995
cg_playerstate.asm:1080791512 0f3dde705b7a56ff7c96362adc8d47a4
cg_drawtools.asm:1080791511 8137caefcc941326b26c5239361f2813
cg_servercmds.o:1080791488 08db7ab9fff94f5015a8819d7aad089e
cg_info.c:1080784657 - d1c7d2583deefcbc4f40f5a8108c363b
cg_effects.o:1080791484 f3fa3d1620abbc533d37a103b0ce39a0
cg_snapshot.c:1080784657 - e318325bfbe9dcc3ec7811d1401cd03c
cg_consolecmds.o:1080791483 e896d34d18f12c2db5617d3a5e6eb227
cg_effects.c:1080784657 - 935965234b364388481325b7ac2baf91
cg_marks.asm:1080791512 29ab1b4167a34f8afcde2e92fa8f200f
cg_snapshot.o:1080791488 da1ed91f6452903841d3df5a950b145b
cg_servercmds.c:1080784657 - 23db883fd3e26c623a3a56e14a5023ef
cg_playerstate.o:1080791487 a90c8881a6cecb31bc0ff86e785fd860
cg_scoreboard.asm:1080791512 d458791e083b28075e7a07b87ff567b8
cg_effects.asm:1080791511 de9a6dd05b4cc925211944a94c334079
cg_snapshot.asm:1080791512 9d805d7e27fc2b4088f518a9fed0ea65

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,558 @@
// Copyright (C) 1999-2000 Id Software, Inc.
//
// cg_consolecmds.c -- text commands typed in at the local console, or
// executed by a key binding
#include "cg_local.h"
#include "../ui/ui_shared.h"
#ifdef MISSIONPACK
extern menuDef_t *menuScoreboard;
#endif
void CG_TargetCommand_f( void ) {
int targetNum;
char test[4];
targetNum = CG_CrosshairPlayer();
if (!targetNum ) {
return;
}
trap_Argv( 1, test, 4 );
trap_SendConsoleCommand( va( "gc %i %i", targetNum, atoi( test ) ) );
}
/*
=================
CG_SizeUp_f
Keybinding command
=================
*/
static void CG_SizeUp_f (void) {
trap_Cvar_Set("cg_viewsize", va("%i",(int)(cg_viewsize.integer+10)));
}
/*
=================
CG_SizeDown_f
Keybinding command
=================
*/
static void CG_SizeDown_f (void) {
trap_Cvar_Set("cg_viewsize", va("%i",(int)(cg_viewsize.integer-10)));
}
/*
=============
CG_Viewpos_f
Debugging command to print the current position
=============
*/
static void CG_Viewpos_f (void) {
CG_Printf ("(%i %i %i) : %i\n", (int)cg.refdef.vieworg[0],
(int)cg.refdef.vieworg[1], (int)cg.refdef.vieworg[2],
(int)cg.refdefViewAngles[YAW]);
}
static void CG_ScoresDown_f( void ) {
#ifdef MISSIONPACK
CG_BuildSpectatorString();
#endif
if ( cg.scoresRequestTime + 2000 < cg.time ) {
// the scores are more than two seconds out of data,
// so request new ones
cg.scoresRequestTime = cg.time;
trap_SendClientCommand( "score" );
// leave the current scores up if they were already
// displayed, but if this is the first hit, clear them out
if ( !cg.showScores ) {
cg.showScores = qtrue;
cg.numScores = 0;
}
} else {
// show the cached contents even if they just pressed if it
// is within two seconds
cg.showScores = qtrue;
}
}
static void CG_ScoresUp_f( void ) {
if ( cg.showScores ) {
cg.showScores = qfalse;
cg.scoreFadeTime = cg.time;
}
}
#ifdef MISSIONPACK
extern menuDef_t *menuScoreboard;
void Menu_Reset(); // FIXME: add to right include file
static void CG_LoadHud_f( void) {
char buff[1024];
const char *hudSet;
memset(buff, 0, sizeof(buff));
String_Init();
Menu_Reset();
trap_Cvar_VariableStringBuffer("cg_hudFiles", buff, sizeof(buff));
hudSet = buff;
if (hudSet[0] == '\0') {
hudSet = "ui/hud.txt";
}
CG_LoadMenus(hudSet);
menuScoreboard = NULL;
}
static void CG_scrollScoresDown_f( void) {
if (menuScoreboard && cg.scoreBoardShowing) {
Menu_ScrollFeeder(menuScoreboard, FEEDER_SCOREBOARD, qtrue);
Menu_ScrollFeeder(menuScoreboard, FEEDER_REDTEAM_LIST, qtrue);
Menu_ScrollFeeder(menuScoreboard, FEEDER_BLUETEAM_LIST, qtrue);
}
}
static void CG_scrollScoresUp_f( void) {
if (menuScoreboard && cg.scoreBoardShowing) {
Menu_ScrollFeeder(menuScoreboard, FEEDER_SCOREBOARD, qfalse);
Menu_ScrollFeeder(menuScoreboard, FEEDER_REDTEAM_LIST, qfalse);
Menu_ScrollFeeder(menuScoreboard, FEEDER_BLUETEAM_LIST, qfalse);
}
}
static void CG_spWin_f( void) {
trap_Cvar_Set("cg_cameraOrbit", "2");
trap_Cvar_Set("cg_cameraOrbitDelay", "35");
trap_Cvar_Set("cg_thirdPerson", "1");
trap_Cvar_Set("cg_thirdPersonAngle", "0");
trap_Cvar_Set("cg_thirdPersonRange", "100");
CG_AddBufferedSound(cgs.media.winnerSound);
//trap_S_StartLocalSound(cgs.media.winnerSound, CHAN_ANNOUNCER);
CG_CenterPrint("YOU WIN!", SCREEN_HEIGHT * .30, 0);
}
static void CG_spLose_f( void) {
trap_Cvar_Set("cg_cameraOrbit", "2");
trap_Cvar_Set("cg_cameraOrbitDelay", "35");
trap_Cvar_Set("cg_thirdPerson", "1");
trap_Cvar_Set("cg_thirdPersonAngle", "0");
trap_Cvar_Set("cg_thirdPersonRange", "100");
CG_AddBufferedSound(cgs.media.loserSound);
//trap_S_StartLocalSound(cgs.media.loserSound, CHAN_ANNOUNCER);
CG_CenterPrint("YOU LOSE...", SCREEN_HEIGHT * .30, 0);
}
#endif
static void CG_TellTarget_f( void ) {
int clientNum;
char command[128];
char message[128];
clientNum = CG_CrosshairPlayer();
if ( clientNum == -1 ) {
return;
}
trap_Args( message, 128 );
Com_sprintf( command, 128, "tell %i %s", clientNum, message );
trap_SendClientCommand( command );
}
static void CG_TellAttacker_f( void ) {
int clientNum;
char command[128];
char message[128];
clientNum = CG_LastAttacker();
if ( clientNum == -1 ) {
return;
}
trap_Args( message, 128 );
Com_sprintf( command, 128, "tell %i %s", clientNum, message );
trap_SendClientCommand( command );
}
static void CG_VoiceTellTarget_f( void ) {
int clientNum;
char command[128];
char message[128];
clientNum = CG_CrosshairPlayer();
if ( clientNum == -1 ) {
return;
}
trap_Args( message, 128 );
Com_sprintf( command, 128, "vtell %i %s", clientNum, message );
trap_SendClientCommand( command );
}
static void CG_VoiceTellAttacker_f( void ) {
int clientNum;
char command[128];
char message[128];
clientNum = CG_LastAttacker();
if ( clientNum == -1 ) {
return;
}
trap_Args( message, 128 );
Com_sprintf( command, 128, "vtell %i %s", clientNum, message );
trap_SendClientCommand( command );
}
#ifdef MISSIONPACK
static void CG_NextTeamMember_f( void ) {
CG_SelectNextPlayer();
}
static void CG_PrevTeamMember_f( void ) {
CG_SelectPrevPlayer();
}
// ASS U ME's enumeration order as far as task specific orders, OFFENSE is zero, CAMP is last
//
static void CG_NextOrder_f( void ) {
clientInfo_t *ci = cgs.clientinfo + cg.snap->ps.clientNum;
if (ci) {
if (!ci->teamLeader && sortedTeamPlayers[cg_currentSelectedPlayer.integer] != cg.snap->ps.clientNum) {
return;
}
}
if (cgs.currentOrder < TEAMTASK_CAMP) {
cgs.currentOrder++;
if (cgs.currentOrder == TEAMTASK_RETRIEVE) {
if (!CG_OtherTeamHasFlag()) {
cgs.currentOrder++;
}
}
if (cgs.currentOrder == TEAMTASK_ESCORT) {
if (!CG_YourTeamHasFlag()) {
cgs.currentOrder++;
}
}
} else {
cgs.currentOrder = TEAMTASK_OFFENSE;
}
cgs.orderPending = qtrue;
cgs.orderTime = cg.time + 3000;
}
static void CG_ConfirmOrder_f (void ) {
trap_SendConsoleCommand(va("cmd vtell %d %s\n", cgs.acceptLeader, VOICECHAT_YES));
trap_SendConsoleCommand("+button5; wait; -button5");
if (cg.time < cgs.acceptOrderTime) {
trap_SendClientCommand(va("teamtask %d\n", cgs.acceptTask));
cgs.acceptOrderTime = 0;
}
}
static void CG_DenyOrder_f (void ) {
trap_SendConsoleCommand(va("cmd vtell %d %s\n", cgs.acceptLeader, VOICECHAT_NO));
trap_SendConsoleCommand("+button6; wait; -button6");
if (cg.time < cgs.acceptOrderTime) {
cgs.acceptOrderTime = 0;
}
}
static void CG_TaskOffense_f (void ) {
if (cgs.gametype == GT_CTF || cgs.gametype == GT_1FCTF) {
trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONGETFLAG));
} else {
trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONOFFENSE));
}
trap_SendClientCommand(va("teamtask %d\n", TEAMTASK_OFFENSE));
}
static void CG_TaskDefense_f (void ) {
trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONDEFENSE));
trap_SendClientCommand(va("teamtask %d\n", TEAMTASK_DEFENSE));
}
static void CG_TaskPatrol_f (void ) {
trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONPATROL));
trap_SendClientCommand(va("teamtask %d\n", TEAMTASK_PATROL));
}
static void CG_TaskCamp_f (void ) {
trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONCAMPING));
trap_SendClientCommand(va("teamtask %d\n", TEAMTASK_CAMP));
}
static void CG_TaskFollow_f (void ) {
trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONFOLLOW));
trap_SendClientCommand(va("teamtask %d\n", TEAMTASK_FOLLOW));
}
static void CG_TaskRetrieve_f (void ) {
trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONRETURNFLAG));
trap_SendClientCommand(va("teamtask %d\n", TEAMTASK_RETRIEVE));
}
static void CG_TaskEscort_f (void ) {
trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_ONFOLLOWCARRIER));
trap_SendClientCommand(va("teamtask %d\n", TEAMTASK_ESCORT));
}
static void CG_TaskOwnFlag_f (void ) {
trap_SendConsoleCommand(va("cmd vsay_team %s\n", VOICECHAT_IHAVEFLAG));
}
static void CG_TauntKillInsult_f (void ) {
trap_SendConsoleCommand("cmd vsay kill_insult\n");
}
static void CG_TauntPraise_f (void ) {
trap_SendConsoleCommand("cmd vsay praise\n");
}
static void CG_TauntTaunt_f (void ) {
trap_SendConsoleCommand("cmd vtaunt\n");
}
static void CG_TauntDeathInsult_f (void ) {
trap_SendConsoleCommand("cmd vsay death_insult\n");
}
static void CG_TauntGauntlet_f (void ) {
trap_SendConsoleCommand("cmd vsay kill_guantlet\n");
}
static void CG_TaskSuicide_f (void ) {
int clientNum;
char command[128];
clientNum = CG_CrosshairPlayer();
if ( clientNum == -1 ) {
return;
}
Com_sprintf( command, 128, "tell %i suicide", clientNum );
trap_SendClientCommand( command );
}
/*
==================
CG_TeamMenu_f
==================
*/
/*
static void CG_TeamMenu_f( void ) {
if (trap_Key_GetCatcher() & KEYCATCH_CGAME) {
CG_EventHandling(CGAME_EVENT_NONE);
trap_Key_SetCatcher(0);
} else {
CG_EventHandling(CGAME_EVENT_TEAMMENU);
//trap_Key_SetCatcher(KEYCATCH_CGAME);
}
}
*/
/*
==================
CG_EditHud_f
==================
*/
/*
static void CG_EditHud_f( void ) {
//cls.keyCatchers ^= KEYCATCH_CGAME;
//VM_Call (cgvm, CG_EVENT_HANDLING, (cls.keyCatchers & KEYCATCH_CGAME) ? CGAME_EVENT_EDITHUD : CGAME_EVENT_NONE);
}
*/
#endif
/*
==================
CG_StartOrbit_f
==================
*/
static void CG_StartOrbit_f( void ) {
char var[MAX_TOKEN_CHARS];
trap_Cvar_VariableStringBuffer( "developer", var, sizeof( var ) );
if ( !atoi(var) ) {
return;
}
if (cg_cameraOrbit.value != 0) {
trap_Cvar_Set ("cg_cameraOrbit", "0");
trap_Cvar_Set("cg_thirdPerson", "0");
} else {
trap_Cvar_Set("cg_cameraOrbit", "5");
trap_Cvar_Set("cg_thirdPerson", "1");
trap_Cvar_Set("cg_thirdPersonAngle", "0");
trap_Cvar_Set("cg_thirdPersonRange", "100");
}
}
/*
static void CG_Camera_f( void ) {
char name[1024];
trap_Argv( 1, name, sizeof(name));
if (trap_loadCamera(name)) {
cg.cameraMode = qtrue;
trap_startCamera(cg.time);
} else {
CG_Printf ("Unable to load camera %s\n",name);
}
}
*/
typedef struct {
char *cmd;
void (*function)(void);
} consoleCommand_t;
static consoleCommand_t commands[] = {
{ "testgun", CG_TestGun_f },
{ "testmodel", CG_TestModel_f },
{ "nextframe", CG_TestModelNextFrame_f },
{ "prevframe", CG_TestModelPrevFrame_f },
{ "nextskin", CG_TestModelNextSkin_f },
{ "prevskin", CG_TestModelPrevSkin_f },
{ "viewpos", CG_Viewpos_f },
{ "+scores", CG_ScoresDown_f },
{ "-scores", CG_ScoresUp_f },
{ "+zoom", CG_ZoomDown_f },
{ "-zoom", CG_ZoomUp_f },
{ "sizeup", CG_SizeUp_f },
{ "sizedown", CG_SizeDown_f },
{ "weapnext", CG_NextWeapon_f },
{ "weapprev", CG_PrevWeapon_f },
{ "weapon", CG_Weapon_f },
{ "tell_target", CG_TellTarget_f },
{ "tell_attacker", CG_TellAttacker_f },
{ "vtell_target", CG_VoiceTellTarget_f },
{ "vtell_attacker", CG_VoiceTellAttacker_f },
{ "tcmd", CG_TargetCommand_f },
#ifdef MISSIONPACK
{ "loadhud", CG_LoadHud_f },
{ "nextTeamMember", CG_NextTeamMember_f },
{ "prevTeamMember", CG_PrevTeamMember_f },
{ "nextOrder", CG_NextOrder_f },
{ "confirmOrder", CG_ConfirmOrder_f },
{ "denyOrder", CG_DenyOrder_f },
{ "taskOffense", CG_TaskOffense_f },
{ "taskDefense", CG_TaskDefense_f },
{ "taskPatrol", CG_TaskPatrol_f },
{ "taskCamp", CG_TaskCamp_f },
{ "taskFollow", CG_TaskFollow_f },
{ "taskRetrieve", CG_TaskRetrieve_f },
{ "taskEscort", CG_TaskEscort_f },
{ "taskSuicide", CG_TaskSuicide_f },
{ "taskOwnFlag", CG_TaskOwnFlag_f },
{ "tauntKillInsult", CG_TauntKillInsult_f },
{ "tauntPraise", CG_TauntPraise_f },
{ "tauntTaunt", CG_TauntTaunt_f },
{ "tauntDeathInsult", CG_TauntDeathInsult_f },
{ "tauntGauntlet", CG_TauntGauntlet_f },
{ "spWin", CG_spWin_f },
{ "spLose", CG_spLose_f },
{ "scoresDown", CG_scrollScoresDown_f },
{ "scoresUp", CG_scrollScoresUp_f },
#endif
{ "startOrbit", CG_StartOrbit_f },
//{ "camera", CG_Camera_f },
{ "loaddeferred", CG_LoadDeferredPlayers }
};
/*
=================
CG_ConsoleCommand
The string has been tokenized and can be retrieved with
Cmd_Argc() / Cmd_Argv()
=================
*/
qboolean CG_ConsoleCommand( void ) {
const char *cmd;
int i;
cmd = CG_Argv(0);
for ( i = 0 ; i < sizeof( commands ) / sizeof( commands[0] ) ; i++ ) {
if ( !Q_stricmp( cmd, commands[i].cmd ) ) {
commands[i].function();
return qtrue;
}
}
return qfalse;
}
/*
=================
CG_InitConsoleCommands
Let the client system know about all of our commands
so it can perform tab completion
=================
*/
void CG_InitConsoleCommands( void ) {
int i;
for ( i = 0 ; i < sizeof( commands ) / sizeof( commands[0] ) ; i++ ) {
trap_AddCommand( commands[i].cmd );
}
//
// the game server will interpret these commands, which will be automatically
// forwarded to the server after they are not recognized locally
//
trap_AddCommand ("kill");
trap_AddCommand ("say");
trap_AddCommand ("say_team");
trap_AddCommand ("tell");
trap_AddCommand ("vsay");
trap_AddCommand ("vsay_team");
trap_AddCommand ("vtell");
trap_AddCommand ("vtaunt");
trap_AddCommand ("vosay");
trap_AddCommand ("vosay_team");
trap_AddCommand ("votell");
trap_AddCommand ("give");
trap_AddCommand ("god");
trap_AddCommand ("notarget");
trap_AddCommand ("noclip");
trap_AddCommand ("team");
trap_AddCommand ("follow");
trap_AddCommand ("levelshot");
trap_AddCommand ("addbot");
trap_AddCommand ("setviewpos");
trap_AddCommand ("callvote");
trap_AddCommand ("vote");
trap_AddCommand ("callteamvote");
trap_AddCommand ("teamvote");
trap_AddCommand ("stats");
trap_AddCommand ("teamtask");
trap_AddCommand ("loaddefered"); // spelled wrong, but not changing for demo
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,804 @@
// Copyright (C) 1999-2000 Id Software, Inc.
//
// cg_drawtools.c -- helper functions called by cg_draw, cg_scoreboard, cg_info, etc
#include "cg_local.h"
/*
================
CG_AdjustFrom640
Adjusted for resolution and screen aspect ratio
================
*/
void CG_AdjustFrom640( float *x, float *y, float *w, float *h ) {
#if 0
// adjust for wide screens
if ( cgs.glconfig.vidWidth * 480 > cgs.glconfig.vidHeight * 640 ) {
*x += 0.5 * ( cgs.glconfig.vidWidth - ( cgs.glconfig.vidHeight * 640 / 480 ) );
}
#endif
// scale for screen sizes
*x *= cgs.screenXScale;
*y *= cgs.screenYScale;
*w *= cgs.screenXScale;
*h *= cgs.screenYScale;
}
/*
================
CG_FillRect
Coordinates are 640*480 virtual values
=================
*/
void CG_FillRect( float x, float y, float width, float height, const float *color ) {
trap_R_SetColor( color );
CG_AdjustFrom640( &x, &y, &width, &height );
trap_R_DrawStretchPic( x, y, width, height, 0, 0, 0, 0, cgs.media.whiteShader );
trap_R_SetColor( NULL );
}
/*
================
CG_DrawSides
Coords are virtual 640x480
================
*/
void CG_DrawSides(float x, float y, float w, float h, float size) {
CG_AdjustFrom640( &x, &y, &w, &h );
size *= cgs.screenXScale;
trap_R_DrawStretchPic( x, y, size, h, 0, 0, 0, 0, cgs.media.whiteShader );
trap_R_DrawStretchPic( x + w - size, y, size, h, 0, 0, 0, 0, cgs.media.whiteShader );
}
void CG_DrawTopBottom(float x, float y, float w, float h, float size) {
CG_AdjustFrom640( &x, &y, &w, &h );
size *= cgs.screenYScale;
trap_R_DrawStretchPic( x, y, w, size, 0, 0, 0, 0, cgs.media.whiteShader );
trap_R_DrawStretchPic( x, y + h - size, w, size, 0, 0, 0, 0, cgs.media.whiteShader );
}
/*
================
UI_DrawRect
Coordinates are 640*480 virtual values
=================
*/
void CG_DrawRect( float x, float y, float width, float height, float size, const float *color ) {
trap_R_SetColor( color );
CG_DrawTopBottom(x, y, width, height, size);
CG_DrawSides(x, y, width, height, size);
trap_R_SetColor( NULL );
}
/*
================
CG_DrawPic
Coordinates are 640*480 virtual values
=================
*/
void CG_DrawPic( float x, float y, float width, float height, qhandle_t hShader ) {
CG_AdjustFrom640( &x, &y, &width, &height );
trap_R_DrawStretchPic( x, y, width, height, 0, 0, 1, 1, hShader );
}
/*
===============
CG_DrawChar
Coordinates and size in 640*480 virtual screen size
===============
*/
void CG_DrawChar( int x, int y, int width, int height, int ch ) {
int row, col;
float frow, fcol;
float size;
float ax, ay, aw, ah;
ch &= 255;
if ( ch == ' ' ) {
return;
}
ax = x;
ay = y;
aw = width;
ah = height;
CG_AdjustFrom640( &ax, &ay, &aw, &ah );
row = ch>>4;
col = ch&15;
frow = row*0.0625;
fcol = col*0.0625;
size = 0.0625;
trap_R_DrawStretchPic( ax, ay, aw, ah,
fcol, frow,
fcol + size, frow + size,
cgs.media.charsetShader );
}
/*
==================
CG_DrawStringExt
Draws a multi-colored string with a drop shadow, optionally forcing
to a fixed color.
Coordinates are at 640 by 480 virtual resolution
==================
*/
void CG_DrawStringExt( int x, int y, const char *string, const float *setColor,
qboolean forceColor, qboolean shadow, int charWidth, int charHeight, int maxChars ) {
vec4_t color;
const char *s;
int xx;
int cnt;
if (maxChars <= 0)
maxChars = 32767; // do them all!
// draw the drop shadow
if (shadow) {
color[0] = color[1] = color[2] = 0;
color[3] = setColor[3];
trap_R_SetColor( color );
s = string;
xx = x;
cnt = 0;
while ( *s && cnt < maxChars) {
if ( Q_IsColorString( s ) ) {
s += 2;
continue;
}
CG_DrawChar( xx + 2, y + 2, charWidth, charHeight, *s );
cnt++;
xx += charWidth;
s++;
}
}
// draw the colored text
s = string;
xx = x;
cnt = 0;
trap_R_SetColor( setColor );
while ( *s && cnt < maxChars) {
if ( Q_IsColorString( s ) ) {
if ( !forceColor ) {
memcpy( color, g_color_table[ColorIndex(*(s+1))], sizeof( color ) );
color[3] = setColor[3];
trap_R_SetColor( color );
}
s += 2;
continue;
}
CG_DrawChar( xx, y, charWidth, charHeight, *s );
xx += charWidth;
cnt++;
s++;
}
trap_R_SetColor( NULL );
}
void CG_DrawBigString( int x, int y, const char *s, float alpha ) {
float color[4];
color[0] = color[1] = color[2] = 1.0;
color[3] = alpha;
CG_DrawStringExt( x, y, s, color, qfalse, qtrue, BIGCHAR_WIDTH, BIGCHAR_HEIGHT, 0 );
}
void CG_DrawBigStringColor( int x, int y, const char *s, vec4_t color ) {
CG_DrawStringExt( x, y, s, color, qtrue, qtrue, BIGCHAR_WIDTH, BIGCHAR_HEIGHT, 0 );
}
void CG_DrawSmallString( int x, int y, const char *s, float alpha ) {
float color[4];
color[0] = color[1] = color[2] = 1.0;
color[3] = alpha;
CG_DrawStringExt( x, y, s, color, qfalse, qfalse, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 );
}
void CG_DrawSmallStringColor( int x, int y, const char *s, vec4_t color ) {
CG_DrawStringExt( x, y, s, color, qtrue, qfalse, SMALLCHAR_WIDTH, SMALLCHAR_HEIGHT, 0 );
}
/*
=================
CG_DrawStrlen
Returns character count, skiping color escape codes
=================
*/
int CG_DrawStrlen( const char *str ) {
const char *s = str;
int count = 0;
while ( *s ) {
if ( Q_IsColorString( s ) ) {
s += 2;
} else {
count++;
s++;
}
}
return count;
}
/*
=============
CG_TileClearBox
This repeats a 64*64 tile graphic to fill the screen around a sized down
refresh window.
=============
*/
static void CG_TileClearBox( int x, int y, int w, int h, qhandle_t hShader ) {
float s1, t1, s2, t2;
s1 = x/64.0;
t1 = y/64.0;
s2 = (x+w)/64.0;
t2 = (y+h)/64.0;
trap_R_DrawStretchPic( x, y, w, h, s1, t1, s2, t2, hShader );
}
/*
==============
CG_TileClear
Clear around a sized down screen
==============
*/
void CG_TileClear( void ) {
int top, bottom, left, right;
int w, h;
w = cgs.glconfig.vidWidth;
h = cgs.glconfig.vidHeight;
if ( cg.refdef.x == 0 && cg.refdef.y == 0 &&
cg.refdef.width == w && cg.refdef.height == h ) {
return; // full screen rendering
}
top = cg.refdef.y;
bottom = top + cg.refdef.height-1;
left = cg.refdef.x;
right = left + cg.refdef.width-1;
// clear above view screen
CG_TileClearBox( 0, 0, w, top, cgs.media.backTileShader );
// clear below view screen
CG_TileClearBox( 0, bottom, w, h - bottom, cgs.media.backTileShader );
// clear left of view screen
CG_TileClearBox( 0, top, left, bottom - top + 1, cgs.media.backTileShader );
// clear right of view screen
CG_TileClearBox( right, top, w - right, bottom - top + 1, cgs.media.backTileShader );
}
/*
================
CG_FadeColor
================
*/
float *CG_FadeColor( int startMsec, int totalMsec ) {
static vec4_t color;
int t;
if ( startMsec == 0 ) {
return NULL;
}
t = cg.time - startMsec;
if ( t >= totalMsec ) {
return NULL;
}
// fade out
if ( totalMsec - t < FADE_TIME ) {
color[3] = ( totalMsec - t ) * 1.0/FADE_TIME;
} else {
color[3] = 1.0;
}
color[0] = color[1] = color[2] = 1;
return color;
}
/*
================
CG_TeamColor
================
*/
float *CG_TeamColor( int team ) {
static vec4_t red = {1, 0.2f, 0.2f, 1};
static vec4_t blue = {0.2f, 0.2f, 1, 1};
static vec4_t other = {1, 1, 1, 1};
static vec4_t spectator = {0.7f, 0.7f, 0.7f, 1};
switch ( team ) {
case TEAM_RED:
return red;
case TEAM_BLUE:
return blue;
case TEAM_SPECTATOR:
return spectator;
default:
return other;
}
}
/*
=================
CG_GetColorForHealth
=================
*/
void CG_GetColorForHealth( int health, int armor, vec4_t hcolor ) {
int count;
int max;
// calculate the total points of damage that can
// be sustained at the current health / armor level
if ( health <= 0 ) {
VectorClear( hcolor ); // black
hcolor[3] = 1;
return;
}
count = armor;
max = health * ARMOR_PROTECTION / ( 1.0 - ARMOR_PROTECTION );
if ( max < count ) {
count = max;
}
health += count;
// set the color based on health
hcolor[0] = 1.0;
hcolor[3] = 1.0;
if ( health >= 100 ) {
hcolor[2] = 1.0;
} else if ( health < 66 ) {
hcolor[2] = 0;
} else {
hcolor[2] = ( health - 66 ) / 33.0;
}
if ( health > 60 ) {
hcolor[1] = 1.0;
} else if ( health < 30 ) {
hcolor[1] = 0;
} else {
hcolor[1] = ( health - 30 ) / 30.0;
}
}
/*
=================
CG_ColorForHealth
=================
*/
void CG_ColorForHealth( vec4_t hcolor ) {
CG_GetColorForHealth( cg.snap->ps.stats[STAT_HEALTH],
cg.snap->ps.stats[STAT_ARMOR], hcolor );
}
// bk001205 - code below duplicated in q3_ui/ui-atoms.c
// bk001205 - FIXME: does this belong in ui_shared.c?
// bk001205 - FIXME: HARD_LINKED flags not visible here
#ifndef Q3_STATIC // bk001205 - q_shared defines not visible here
/*
=================
UI_DrawProportionalString2
=================
*/
static int propMap[128][3] = {
{0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1},
{0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1},
{0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1},
{0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1}, {0, 0, -1},
{0, 0, PROP_SPACE_WIDTH}, // SPACE
{11, 122, 7}, // !
{154, 181, 14}, // "
{55, 122, 17}, // #
{79, 122, 18}, // $
{101, 122, 23}, // %
{153, 122, 18}, // &
{9, 93, 7}, // '
{207, 122, 8}, // (
{230, 122, 9}, // )
{177, 122, 18}, // *
{30, 152, 18}, // +
{85, 181, 7}, // ,
{34, 93, 11}, // -
{110, 181, 6}, // .
{130, 152, 14}, // /
{22, 64, 17}, // 0
{41, 64, 12}, // 1
{58, 64, 17}, // 2
{78, 64, 18}, // 3
{98, 64, 19}, // 4
{120, 64, 18}, // 5
{141, 64, 18}, // 6
{204, 64, 16}, // 7
{162, 64, 17}, // 8
{182, 64, 18}, // 9
{59, 181, 7}, // :
{35,181, 7}, // ;
{203, 152, 14}, // <
{56, 93, 14}, // =
{228, 152, 14}, // >
{177, 181, 18}, // ?
{28, 122, 22}, // @
{5, 4, 18}, // A
{27, 4, 18}, // B
{48, 4, 18}, // C
{69, 4, 17}, // D
{90, 4, 13}, // E
{106, 4, 13}, // F
{121, 4, 18}, // G
{143, 4, 17}, // H
{164, 4, 8}, // I
{175, 4, 16}, // J
{195, 4, 18}, // K
{216, 4, 12}, // L
{230, 4, 23}, // M
{6, 34, 18}, // N
{27, 34, 18}, // O
{48, 34, 18}, // P
{68, 34, 18}, // Q
{90, 34, 17}, // R
{110, 34, 18}, // S
{130, 34, 14}, // T
{146, 34, 18}, // U
{166, 34, 19}, // V
{185, 34, 29}, // W
{215, 34, 18}, // X
{234, 34, 18}, // Y
{5, 64, 14}, // Z
{60, 152, 7}, // [
{106, 151, 13}, // '\'
{83, 152, 7}, // ]
{128, 122, 17}, // ^
{4, 152, 21}, // _
{134, 181, 5}, // '
{5, 4, 18}, // A
{27, 4, 18}, // B
{48, 4, 18}, // C
{69, 4, 17}, // D
{90, 4, 13}, // E
{106, 4, 13}, // F
{121, 4, 18}, // G
{143, 4, 17}, // H
{164, 4, 8}, // I
{175, 4, 16}, // J
{195, 4, 18}, // K
{216, 4, 12}, // L
{230, 4, 23}, // M
{6, 34, 18}, // N
{27, 34, 18}, // O
{48, 34, 18}, // P
{68, 34, 18}, // Q
{90, 34, 17}, // R
{110, 34, 18}, // S
{130, 34, 14}, // T
{146, 34, 18}, // U
{166, 34, 19}, // V
{185, 34, 29}, // W
{215, 34, 18}, // X
{234, 34, 18}, // Y
{5, 64, 14}, // Z
{153, 152, 13}, // {
{11, 181, 5}, // |
{180, 152, 13}, // }
{79, 93, 17}, // ~
{0, 0, -1} // DEL
};
static int propMapB[26][3] = {
{11, 12, 33},
{49, 12, 31},
{85, 12, 31},
{120, 12, 30},
{156, 12, 21},
{183, 12, 21},
{207, 12, 32},
{13, 55, 30},
{49, 55, 13},
{66, 55, 29},
{101, 55, 31},
{135, 55, 21},
{158, 55, 40},
{204, 55, 32},
{12, 97, 31},
{48, 97, 31},
{82, 97, 30},
{118, 97, 30},
{153, 97, 30},
{185, 97, 25},
{213, 97, 30},
{11, 139, 32},
{42, 139, 51},
{93, 139, 32},
{126, 139, 31},
{158, 139, 25},
};
#define PROPB_GAP_WIDTH 4
#define PROPB_SPACE_WIDTH 12
#define PROPB_HEIGHT 36
/*
=================
UI_DrawBannerString
=================
*/
static void UI_DrawBannerString2( int x, int y, const char* str, vec4_t color )
{
const char* s;
unsigned char ch; // bk001204 : array subscript
float ax;
float ay;
float aw;
float ah;
float frow;
float fcol;
float fwidth;
float fheight;
// draw the colored text
trap_R_SetColor( color );
ax = x * cgs.screenXScale + cgs.screenXBias;
ay = y * cgs.screenXScale;
s = str;
while ( *s )
{
ch = *s & 127;
if ( ch == ' ' ) {
ax += ((float)PROPB_SPACE_WIDTH + (float)PROPB_GAP_WIDTH)* cgs.screenXScale;
}
else if ( ch >= 'A' && ch <= 'Z' ) {
ch -= 'A';
fcol = (float)propMapB[ch][0] / 256.0f;
frow = (float)propMapB[ch][1] / 256.0f;
fwidth = (float)propMapB[ch][2] / 256.0f;
fheight = (float)PROPB_HEIGHT / 256.0f;
aw = (float)propMapB[ch][2] * cgs.screenXScale;
ah = (float)PROPB_HEIGHT * cgs.screenXScale;
trap_R_DrawStretchPic( ax, ay, aw, ah, fcol, frow, fcol+fwidth, frow+fheight, cgs.media.charsetPropB );
ax += (aw + (float)PROPB_GAP_WIDTH * cgs.screenXScale);
}
s++;
}
trap_R_SetColor( NULL );
}
void UI_DrawBannerString( int x, int y, const char* str, int style, vec4_t color ) {
const char * s;
int ch;
int width;
vec4_t drawcolor;
// find the width of the drawn text
s = str;
width = 0;
while ( *s ) {
ch = *s;
if ( ch == ' ' ) {
width += PROPB_SPACE_WIDTH;
}
else if ( ch >= 'A' && ch <= 'Z' ) {
width += propMapB[ch - 'A'][2] + PROPB_GAP_WIDTH;
}
s++;
}
width -= PROPB_GAP_WIDTH;
switch( style & UI_FORMATMASK ) {
case UI_CENTER:
x -= width / 2;
break;
case UI_RIGHT:
x -= width;
break;
case UI_LEFT:
default:
break;
}
if ( style & UI_DROPSHADOW ) {
drawcolor[0] = drawcolor[1] = drawcolor[2] = 0;
drawcolor[3] = color[3];
UI_DrawBannerString2( x+2, y+2, str, drawcolor );
}
UI_DrawBannerString2( x, y, str, color );
}
int UI_ProportionalStringWidth( const char* str ) {
const char * s;
int ch;
int charWidth;
int width;
s = str;
width = 0;
while ( *s ) {
ch = *s & 127;
charWidth = propMap[ch][2];
if ( charWidth != -1 ) {
width += charWidth;
width += PROP_GAP_WIDTH;
}
s++;
}
width -= PROP_GAP_WIDTH;
return width;
}
static void UI_DrawProportionalString2( int x, int y, const char* str, vec4_t color, float sizeScale, qhandle_t charset )
{
const char* s;
unsigned char ch; // bk001204 - unsigned
float ax;
float ay;
float aw;
float ah;
float frow;
float fcol;
float fwidth;
float fheight;
// draw the colored text
trap_R_SetColor( color );
ax = x * cgs.screenXScale + cgs.screenXBias;
ay = y * cgs.screenXScale;
s = str;
while ( *s )
{
ch = *s & 127;
if ( ch == ' ' ) {
aw = (float)PROP_SPACE_WIDTH * cgs.screenXScale * sizeScale;
} else if ( propMap[ch][2] != -1 ) {
fcol = (float)propMap[ch][0] / 256.0f;
frow = (float)propMap[ch][1] / 256.0f;
fwidth = (float)propMap[ch][2] / 256.0f;
fheight = (float)PROP_HEIGHT / 256.0f;
aw = (float)propMap[ch][2] * cgs.screenXScale * sizeScale;
ah = (float)PROP_HEIGHT * cgs.screenXScale * sizeScale;
trap_R_DrawStretchPic( ax, ay, aw, ah, fcol, frow, fcol+fwidth, frow+fheight, charset );
} else {
aw = 0;
}
ax += (aw + (float)PROP_GAP_WIDTH * cgs.screenXScale * sizeScale);
s++;
}
trap_R_SetColor( NULL );
}
/*
=================
UI_ProportionalSizeScale
=================
*/
float UI_ProportionalSizeScale( int style ) {
if( style & UI_SMALLFONT ) {
return 0.75;
}
return 1.00;
}
/*
=================
UI_DrawProportionalString
=================
*/
void UI_DrawProportionalString( int x, int y, const char* str, int style, vec4_t color ) {
vec4_t drawcolor;
int width;
float sizeScale;
sizeScale = UI_ProportionalSizeScale( style );
switch( style & UI_FORMATMASK ) {
case UI_CENTER:
width = UI_ProportionalStringWidth( str ) * sizeScale;
x -= width / 2;
break;
case UI_RIGHT:
width = UI_ProportionalStringWidth( str ) * sizeScale;
x -= width;
break;
case UI_LEFT:
default:
break;
}
if ( style & UI_DROPSHADOW ) {
drawcolor[0] = drawcolor[1] = drawcolor[2] = 0;
drawcolor[3] = color[3];
UI_DrawProportionalString2( x+2, y+2, str, drawcolor, sizeScale, cgs.media.charsetProp );
}
if ( style & UI_INVERSE ) {
drawcolor[0] = color[0] * 0.8;
drawcolor[1] = color[1] * 0.8;
drawcolor[2] = color[2] * 0.8;
drawcolor[3] = color[3];
UI_DrawProportionalString2( x, y, str, drawcolor, sizeScale, cgs.media.charsetProp );
return;
}
if ( style & UI_PULSE ) {
drawcolor[0] = color[0] * 0.8;
drawcolor[1] = color[1] * 0.8;
drawcolor[2] = color[2] * 0.8;
drawcolor[3] = color[3];
UI_DrawProportionalString2( x, y, str, color, sizeScale, cgs.media.charsetProp );
drawcolor[0] = color[0];
drawcolor[1] = color[1];
drawcolor[2] = color[2];
drawcolor[3] = 0.5 + 0.5 * sin( cg.time / PULSE_DIVISOR );
UI_DrawProportionalString2( x, y, str, drawcolor, sizeScale, cgs.media.charsetPropGlow );
return;
}
UI_DrawProportionalString2( x, y, str, color, sizeScale, cgs.media.charsetProp );
}
#endif // Q3STATIC

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,698 @@
// Copyright (C) 1999-2000 Id Software, Inc.
//
// cg_effects.c -- these functions generate localentities, usually as a result
// of event processing
#include "cg_local.h"
/*
==================
CG_BubbleTrail
Bullets shot underwater
==================
*/
void CG_BubbleTrail( vec3_t start, vec3_t end, float spacing ) {
vec3_t move;
vec3_t vec;
float len;
int i;
if ( cg_noProjectileTrail.integer ) {
return;
}
VectorCopy (start, move);
VectorSubtract (end, start, vec);
len = VectorNormalize (vec);
// advance a random amount first
i = rand() % (int)spacing;
VectorMA( move, i, vec, move );
VectorScale (vec, spacing, vec);
for ( ; i < len; i += spacing ) {
localEntity_t *le;
refEntity_t *re;
le = CG_AllocLocalEntity();
le->leFlags = LEF_PUFF_DONT_SCALE;
le->leType = LE_MOVE_SCALE_FADE;
le->startTime = cg.time;
le->endTime = cg.time + 1000 + random() * 250;
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
re = &le->refEntity;
re->shaderTime = cg.time / 1000.0f;
re->reType = RT_SPRITE;
re->rotation = 0;
re->radius = 3;
re->customShader = cgs.media.waterBubbleShader;
re->shaderRGBA[0] = 0xff;
re->shaderRGBA[1] = 0xff;
re->shaderRGBA[2] = 0xff;
re->shaderRGBA[3] = 0xff;
le->color[3] = 1.0;
le->pos.trType = TR_LINEAR;
le->pos.trTime = cg.time;
VectorCopy( move, le->pos.trBase );
le->pos.trDelta[0] = crandom()*5;
le->pos.trDelta[1] = crandom()*5;
le->pos.trDelta[2] = crandom()*5 + 6;
VectorAdd (move, vec, move);
}
}
/*
=====================
CG_SmokePuff
Adds a smoke puff or blood trail localEntity.
=====================
*/
localEntity_t *CG_SmokePuff( const vec3_t p, const vec3_t vel,
float radius,
float r, float g, float b, float a,
float duration,
int startTime,
int fadeInTime,
int leFlags,
qhandle_t hShader ) {
static int seed = 0x92;
localEntity_t *le;
refEntity_t *re;
// int fadeInTime = startTime + duration / 2;
le = CG_AllocLocalEntity();
le->leFlags = leFlags;
le->radius = radius;
re = &le->refEntity;
re->rotation = Q_random( &seed ) * 360;
re->radius = radius;
re->shaderTime = startTime / 1000.0f;
le->leType = LE_MOVE_SCALE_FADE;
le->startTime = startTime;
le->fadeInTime = fadeInTime;
le->endTime = startTime + duration;
if ( fadeInTime > startTime ) {
le->lifeRate = 1.0 / ( le->endTime - le->fadeInTime );
}
else {
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
}
le->color[0] = r;
le->color[1] = g;
le->color[2] = b;
le->color[3] = a;
le->pos.trType = TR_LINEAR;
le->pos.trTime = startTime;
VectorCopy( vel, le->pos.trDelta );
VectorCopy( p, le->pos.trBase );
VectorCopy( p, re->origin );
re->customShader = hShader;
// rage pro can't alpha fade, so use a different shader
if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO ) {
re->customShader = cgs.media.smokePuffRageProShader;
re->shaderRGBA[0] = 0xff;
re->shaderRGBA[1] = 0xff;
re->shaderRGBA[2] = 0xff;
re->shaderRGBA[3] = 0xff;
} else {
re->shaderRGBA[0] = le->color[0] * 0xff;
re->shaderRGBA[1] = le->color[1] * 0xff;
re->shaderRGBA[2] = le->color[2] * 0xff;
re->shaderRGBA[3] = 0xff;
}
re->reType = RT_SPRITE;
re->radius = le->radius;
return le;
}
/*
==================
CG_SpawnEffect
Player teleporting in or out
==================
*/
void CG_SpawnEffect( vec3_t org ) {
localEntity_t *le;
refEntity_t *re;
le = CG_AllocLocalEntity();
le->leFlags = 0;
le->leType = LE_FADE_RGB;
le->startTime = cg.time;
le->endTime = cg.time + 500;
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
re = &le->refEntity;
re->reType = RT_MODEL;
re->shaderTime = cg.time / 1000.0f;
#ifndef MISSIONPACK
re->customShader = cgs.media.teleportEffectShader;
#endif
re->hModel = cgs.media.teleportEffectModel;
AxisClear( re->axis );
VectorCopy( org, re->origin );
#ifdef MISSIONPACK
re->origin[2] += 16;
#else
re->origin[2] -= 24;
#endif
}
#ifdef MISSIONPACK
/*
===============
CG_LightningBoltBeam
===============
*/
void CG_LightningBoltBeam( vec3_t start, vec3_t end ) {
localEntity_t *le;
refEntity_t *beam;
le = CG_AllocLocalEntity();
le->leFlags = 0;
le->leType = LE_SHOWREFENTITY;
le->startTime = cg.time;
le->endTime = cg.time + 50;
beam = &le->refEntity;
VectorCopy( start, beam->origin );
// this is the end point
VectorCopy( end, beam->oldorigin );
beam->reType = RT_LIGHTNING;
beam->customShader = cgs.media.lightningShader;
}
/*
==================
CG_KamikazeEffect
==================
*/
void CG_KamikazeEffect( vec3_t org ) {
localEntity_t *le;
refEntity_t *re;
le = CG_AllocLocalEntity();
le->leFlags = 0;
le->leType = LE_KAMIKAZE;
le->startTime = cg.time;
le->endTime = cg.time + 3000;//2250;
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
VectorClear(le->angles.trBase);
re = &le->refEntity;
re->reType = RT_MODEL;
re->shaderTime = cg.time / 1000.0f;
re->hModel = cgs.media.kamikazeEffectModel;
VectorCopy( org, re->origin );
}
/*
==================
CG_ObeliskExplode
==================
*/
void CG_ObeliskExplode( vec3_t org, int entityNum ) {
localEntity_t *le;
vec3_t origin;
// create an explosion
VectorCopy( org, origin );
origin[2] += 64;
le = CG_MakeExplosion( origin, vec3_origin,
cgs.media.dishFlashModel,
cgs.media.rocketExplosionShader,
600, qtrue );
le->light = 300;
le->lightColor[0] = 1;
le->lightColor[1] = 0.75;
le->lightColor[2] = 0.0;
}
/*
==================
CG_ObeliskPain
==================
*/
void CG_ObeliskPain( vec3_t org ) {
float r;
sfxHandle_t sfx;
// hit sound
r = rand() & 3;
if ( r < 2 ) {
sfx = cgs.media.obeliskHitSound1;
} else if ( r == 2 ) {
sfx = cgs.media.obeliskHitSound2;
} else {
sfx = cgs.media.obeliskHitSound3;
}
trap_S_StartSound ( org, ENTITYNUM_NONE, CHAN_BODY, sfx );
}
/*
==================
CG_InvulnerabilityImpact
==================
*/
void CG_InvulnerabilityImpact( vec3_t org, vec3_t angles ) {
localEntity_t *le;
refEntity_t *re;
int r;
sfxHandle_t sfx;
le = CG_AllocLocalEntity();
le->leFlags = 0;
le->leType = LE_INVULIMPACT;
le->startTime = cg.time;
le->endTime = cg.time + 1000;
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
re = &le->refEntity;
re->reType = RT_MODEL;
re->shaderTime = cg.time / 1000.0f;
re->hModel = cgs.media.invulnerabilityImpactModel;
VectorCopy( org, re->origin );
AnglesToAxis( angles, re->axis );
r = rand() & 3;
if ( r < 2 ) {
sfx = cgs.media.invulnerabilityImpactSound1;
} else if ( r == 2 ) {
sfx = cgs.media.invulnerabilityImpactSound2;
} else {
sfx = cgs.media.invulnerabilityImpactSound3;
}
trap_S_StartSound (org, ENTITYNUM_NONE, CHAN_BODY, sfx );
}
/*
==================
CG_InvulnerabilityJuiced
==================
*/
void CG_InvulnerabilityJuiced( vec3_t org ) {
localEntity_t *le;
refEntity_t *re;
vec3_t angles;
le = CG_AllocLocalEntity();
le->leFlags = 0;
le->leType = LE_INVULJUICED;
le->startTime = cg.time;
le->endTime = cg.time + 10000;
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
re = &le->refEntity;
re->reType = RT_MODEL;
re->shaderTime = cg.time / 1000.0f;
re->hModel = cgs.media.invulnerabilityJuicedModel;
VectorCopy( org, re->origin );
VectorClear(angles);
AnglesToAxis( angles, re->axis );
trap_S_StartSound (org, ENTITYNUM_NONE, CHAN_BODY, cgs.media.invulnerabilityJuicedSound );
}
#endif
/*
==================
CG_ScorePlum
==================
*/
void CG_ScorePlum( int client, vec3_t org, int score ) {
localEntity_t *le;
refEntity_t *re;
vec3_t angles;
static vec3_t lastPos;
// only visualize for the client that scored
if (client != cg.predictedPlayerState.clientNum || cg_scorePlum.integer == 0) {
return;
}
le = CG_AllocLocalEntity();
le->leFlags = 0;
le->leType = LE_SCOREPLUM;
le->startTime = cg.time;
le->endTime = cg.time + 4000;
le->lifeRate = 1.0 / ( le->endTime - le->startTime );
le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
le->radius = score;
VectorCopy( org, le->pos.trBase );
if (org[2] >= lastPos[2] - 20 && org[2] <= lastPos[2] + 20) {
le->pos.trBase[2] -= 20;
}
//CG_Printf( "Plum origin %i %i %i -- %i\n", (int)org[0], (int)org[1], (int)org[2], (int)Distance(org, lastPos));
VectorCopy(org, lastPos);
re = &le->refEntity;
re->reType = RT_SPRITE;
re->radius = 16;
VectorClear(angles);
AnglesToAxis( angles, re->axis );
}
/*
====================
CG_MakeExplosion
====================
*/
localEntity_t *CG_MakeExplosion( vec3_t origin, vec3_t dir,
qhandle_t hModel, qhandle_t shader,
int msec, qboolean isSprite ) {
float ang;
localEntity_t *ex;
int offset;
vec3_t tmpVec, newOrigin;
if ( msec <= 0 ) {
CG_Error( "CG_MakeExplosion: msec = %i", msec );
}
// skew the time a bit so they aren't all in sync
offset = rand() & 63;
ex = CG_AllocLocalEntity();
if ( isSprite ) {
ex->leType = LE_SPRITE_EXPLOSION;
// randomly rotate sprite orientation
ex->refEntity.rotation = rand() % 360;
VectorScale( dir, 16, tmpVec );
VectorAdd( tmpVec, origin, newOrigin );
} else {
ex->leType = LE_EXPLOSION;
VectorCopy( origin, newOrigin );
// set axis with random rotate
if ( !dir ) {
AxisClear( ex->refEntity.axis );
} else {
ang = rand() % 360;
VectorCopy( dir, ex->refEntity.axis[0] );
RotateAroundDirection( ex->refEntity.axis, ang );
}
}
ex->startTime = cg.time - offset;
ex->endTime = ex->startTime + msec;
// bias the time so all shader effects start correctly
ex->refEntity.shaderTime = ex->startTime / 1000.0f;
ex->refEntity.hModel = hModel;
ex->refEntity.customShader = shader;
// set origin
VectorCopy( newOrigin, ex->refEntity.origin );
VectorCopy( newOrigin, ex->refEntity.oldorigin );
ex->color[0] = ex->color[1] = ex->color[2] = 1.0;
return ex;
}
/*
=================
CG_Bleed
This is the spurt of blood when a character gets hit
=================
*/
void CG_Bleed( vec3_t origin, int entityNum ) {
localEntity_t *ex;
if ( !cg_blood.integer ) {
return;
}
ex = CG_AllocLocalEntity();
ex->leType = LE_EXPLOSION;
ex->startTime = cg.time;
ex->endTime = ex->startTime + 500;
VectorCopy ( origin, ex->refEntity.origin);
ex->refEntity.reType = RT_SPRITE;
ex->refEntity.rotation = rand() % 360;
ex->refEntity.radius = 24;
ex->refEntity.customShader = cgs.media.bloodExplosionShader;
// don't show player's own blood in view
if ( entityNum == cg.snap->ps.clientNum ) {
ex->refEntity.renderfx |= RF_THIRD_PERSON;
}
}
/*
==================
CG_LaunchGib
==================
*/
void CG_LaunchGib( vec3_t origin, vec3_t velocity, qhandle_t hModel ) {
localEntity_t *le;
refEntity_t *re;
le = CG_AllocLocalEntity();
re = &le->refEntity;
le->leType = LE_FRAGMENT;
le->startTime = cg.time;
le->endTime = le->startTime + 5000 + random() * 3000;
VectorCopy( origin, re->origin );
AxisCopy( axisDefault, re->axis );
re->hModel = hModel;
le->pos.trType = TR_GRAVITY;
VectorCopy( origin, le->pos.trBase );
VectorCopy( velocity, le->pos.trDelta );
le->pos.trTime = cg.time;
le->bounceFactor = 0.6f;
le->leBounceSoundType = LEBS_BLOOD;
le->leMarkType = LEMT_BLOOD;
}
/*
===================
CG_GibPlayer
Generated a bunch of gibs launching out from the bodies location
===================
*/
#define GIB_VELOCITY 250
#define GIB_JUMP 250
void CG_GibPlayer( vec3_t playerOrigin ) {
vec3_t origin, velocity;
if ( !cg_blood.integer ) {
return;
}
VectorCopy( playerOrigin, origin );
velocity[0] = crandom()*GIB_VELOCITY;
velocity[1] = crandom()*GIB_VELOCITY;
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
if ( rand() & 1 ) {
CG_LaunchGib( origin, velocity, cgs.media.gibSkull );
} else {
CG_LaunchGib( origin, velocity, cgs.media.gibBrain );
}
// allow gibs to be turned off for speed
if ( !cg_gibs.integer ) {
return;
}
VectorCopy( playerOrigin, origin );
velocity[0] = crandom()*GIB_VELOCITY;
velocity[1] = crandom()*GIB_VELOCITY;
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
CG_LaunchGib( origin, velocity, cgs.media.gibAbdomen );
VectorCopy( playerOrigin, origin );
velocity[0] = crandom()*GIB_VELOCITY;
velocity[1] = crandom()*GIB_VELOCITY;
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
CG_LaunchGib( origin, velocity, cgs.media.gibArm );
VectorCopy( playerOrigin, origin );
velocity[0] = crandom()*GIB_VELOCITY;
velocity[1] = crandom()*GIB_VELOCITY;
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
CG_LaunchGib( origin, velocity, cgs.media.gibChest );
VectorCopy( playerOrigin, origin );
velocity[0] = crandom()*GIB_VELOCITY;
velocity[1] = crandom()*GIB_VELOCITY;
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
CG_LaunchGib( origin, velocity, cgs.media.gibFist );
VectorCopy( playerOrigin, origin );
velocity[0] = crandom()*GIB_VELOCITY;
velocity[1] = crandom()*GIB_VELOCITY;
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
CG_LaunchGib( origin, velocity, cgs.media.gibFoot );
VectorCopy( playerOrigin, origin );
velocity[0] = crandom()*GIB_VELOCITY;
velocity[1] = crandom()*GIB_VELOCITY;
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
CG_LaunchGib( origin, velocity, cgs.media.gibForearm );
VectorCopy( playerOrigin, origin );
velocity[0] = crandom()*GIB_VELOCITY;
velocity[1] = crandom()*GIB_VELOCITY;
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
CG_LaunchGib( origin, velocity, cgs.media.gibIntestine );
VectorCopy( playerOrigin, origin );
velocity[0] = crandom()*GIB_VELOCITY;
velocity[1] = crandom()*GIB_VELOCITY;
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
CG_LaunchGib( origin, velocity, cgs.media.gibLeg );
VectorCopy( playerOrigin, origin );
velocity[0] = crandom()*GIB_VELOCITY;
velocity[1] = crandom()*GIB_VELOCITY;
velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
CG_LaunchGib( origin, velocity, cgs.media.gibLeg );
}
/*
==================
CG_LaunchGib
==================
*/
void CG_LaunchExplode( vec3_t origin, vec3_t velocity, qhandle_t hModel ) {
localEntity_t *le;
refEntity_t *re;
le = CG_AllocLocalEntity();
re = &le->refEntity;
le->leType = LE_FRAGMENT;
le->startTime = cg.time;
le->endTime = le->startTime + 10000 + random() * 6000;
VectorCopy( origin, re->origin );
AxisCopy( axisDefault, re->axis );
re->hModel = hModel;
le->pos.trType = TR_GRAVITY;
VectorCopy( origin, le->pos.trBase );
VectorCopy( velocity, le->pos.trDelta );
le->pos.trTime = cg.time;
le->bounceFactor = 0.1f;
le->leBounceSoundType = LEBS_BRASS;
le->leMarkType = LEMT_NONE;
}
#define EXP_VELOCITY 100
#define EXP_JUMP 150
/*
===================
CG_GibPlayer
Generated a bunch of gibs launching out from the bodies location
===================
*/
void CG_BigExplode( vec3_t playerOrigin ) {
vec3_t origin, velocity;
if ( !cg_blood.integer ) {
return;
}
VectorCopy( playerOrigin, origin );
velocity[0] = crandom()*EXP_VELOCITY;
velocity[1] = crandom()*EXP_VELOCITY;
velocity[2] = EXP_JUMP + crandom()*EXP_VELOCITY;
CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
VectorCopy( playerOrigin, origin );
velocity[0] = crandom()*EXP_VELOCITY;
velocity[1] = crandom()*EXP_VELOCITY;
velocity[2] = EXP_JUMP + crandom()*EXP_VELOCITY;
CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
VectorCopy( playerOrigin, origin );
velocity[0] = crandom()*EXP_VELOCITY*1.5;
velocity[1] = crandom()*EXP_VELOCITY*1.5;
velocity[2] = EXP_JUMP + crandom()*EXP_VELOCITY;
CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
VectorCopy( playerOrigin, origin );
velocity[0] = crandom()*EXP_VELOCITY*2.0;
velocity[1] = crandom()*EXP_VELOCITY*2.0;
velocity[2] = EXP_JUMP + crandom()*EXP_VELOCITY;
CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
VectorCopy( playerOrigin, origin );
velocity[0] = crandom()*EXP_VELOCITY*2.5;
velocity[1] = crandom()*EXP_VELOCITY*2.5;
velocity[2] = EXP_JUMP + crandom()*EXP_VELOCITY;
CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,277 @@
// Copyright (C) 1999-2000 Id Software, Inc.
//
// cg_info.c -- display information while data is being loading
#include "cg_local.h"
#define MAX_LOADING_PLAYER_ICONS 16
#define MAX_LOADING_ITEM_ICONS 26
static int loadingPlayerIconCount;
static int loadingItemIconCount;
static qhandle_t loadingPlayerIcons[MAX_LOADING_PLAYER_ICONS];
static qhandle_t loadingItemIcons[MAX_LOADING_ITEM_ICONS];
/*
===================
CG_DrawLoadingIcons
===================
*/
static void CG_DrawLoadingIcons( void ) {
int n;
int x, y;
for( n = 0; n < loadingPlayerIconCount; n++ ) {
x = 16 + n * 78;
y = 324-40;
CG_DrawPic( x, y, 64, 64, loadingPlayerIcons[n] );
}
for( n = 0; n < loadingItemIconCount; n++ ) {
y = 400-40;
if( n >= 13 ) {
y += 40;
}
x = 16 + n % 13 * 48;
CG_DrawPic( x, y, 32, 32, loadingItemIcons[n] );
}
}
/*
======================
CG_LoadingString
======================
*/
void CG_LoadingString( const char *s ) {
Q_strncpyz( cg.infoScreenText, s, sizeof( cg.infoScreenText ) );
trap_UpdateScreen();
}
/*
===================
CG_LoadingItem
===================
*/
void CG_LoadingItem( int itemNum ) {
gitem_t *item;
item = &bg_itemlist[itemNum];
if ( item->icon && loadingItemIconCount < MAX_LOADING_ITEM_ICONS ) {
loadingItemIcons[loadingItemIconCount++] = trap_R_RegisterShaderNoMip( item->icon );
}
CG_LoadingString( item->pickup_name );
}
/*
===================
CG_LoadingClient
===================
*/
void CG_LoadingClient( int clientNum ) {
const char *info;
char *skin;
char personality[MAX_QPATH];
char model[MAX_QPATH];
char iconName[MAX_QPATH];
info = CG_ConfigString( CS_PLAYERS + clientNum );
if ( loadingPlayerIconCount < MAX_LOADING_PLAYER_ICONS ) {
Q_strncpyz( model, Info_ValueForKey( info, "model" ), sizeof( model ) );
skin = Q_strrchr( model, '/' );
if ( skin ) {
*skin++ = '\0';
} else {
skin = "default";
}
Com_sprintf( iconName, MAX_QPATH, "models/players/%s/icon_%s.tga", model, skin );
loadingPlayerIcons[loadingPlayerIconCount] = trap_R_RegisterShaderNoMip( iconName );
if ( !loadingPlayerIcons[loadingPlayerIconCount] ) {
Com_sprintf( iconName, MAX_QPATH, "models/players/characters/%s/icon_%s.tga", model, skin );
loadingPlayerIcons[loadingPlayerIconCount] = trap_R_RegisterShaderNoMip( iconName );
}
if ( !loadingPlayerIcons[loadingPlayerIconCount] ) {
Com_sprintf( iconName, MAX_QPATH, "models/players/%s/icon_%s.tga", DEFAULT_MODEL, "default" );
loadingPlayerIcons[loadingPlayerIconCount] = trap_R_RegisterShaderNoMip( iconName );
}
if ( loadingPlayerIcons[loadingPlayerIconCount] ) {
loadingPlayerIconCount++;
}
}
Q_strncpyz( personality, Info_ValueForKey( info, "n" ), sizeof(personality) );
Q_CleanStr( personality );
if( cgs.gametype == GT_SINGLE_PLAYER ) {
trap_S_RegisterSound( va( "sound/player/announce/%s.wav", personality ), qtrue );
}
CG_LoadingString( personality );
}
/*
====================
CG_DrawInformation
Draw all the status / pacifier stuff during level loading
====================
*/
void CG_DrawInformation( void ) {
const char *s;
const char *info;
const char *sysInfo;
int y;
int value;
qhandle_t levelshot;
qhandle_t detail;
char buf[1024];
info = CG_ConfigString( CS_SERVERINFO );
sysInfo = CG_ConfigString( CS_SYSTEMINFO );
s = Info_ValueForKey( info, "mapname" );
levelshot = trap_R_RegisterShaderNoMip( va( "levelshots/%s.tga", s ) );
if ( !levelshot ) {
levelshot = trap_R_RegisterShaderNoMip( "menu/art/unknownmap" );
}
trap_R_SetColor( NULL );
CG_DrawPic( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, levelshot );
// blend a detail texture over it
detail = trap_R_RegisterShader( "levelShotDetail" );
trap_R_DrawStretchPic( 0, 0, cgs.glconfig.vidWidth, cgs.glconfig.vidHeight, 0, 0, 2.5, 2, detail );
// draw the icons of things as they are loaded
CG_DrawLoadingIcons();
// the first 150 rows are reserved for the client connection
// screen to write into
if ( cg.infoScreenText[0] ) {
UI_DrawProportionalString( 320, 128-32, va("Loading... %s", cg.infoScreenText),
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
} else {
UI_DrawProportionalString( 320, 128-32, "Awaiting snapshot...",
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
}
// draw info string information
y = 180-32;
// don't print server lines if playing a local game
trap_Cvar_VariableStringBuffer( "sv_running", buf, sizeof( buf ) );
if ( !atoi( buf ) ) {
// server hostname
Q_strncpyz(buf, Info_ValueForKey( info, "sv_hostname" ), 1024);
Q_CleanStr(buf);
UI_DrawProportionalString( 320, y, buf,
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
y += PROP_HEIGHT;
// pure server
s = Info_ValueForKey( sysInfo, "sv_pure" );
if ( s[0] == '1' ) {
UI_DrawProportionalString( 320, y, "Pure Server",
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
y += PROP_HEIGHT;
}
// server-specific message of the day
s = CG_ConfigString( CS_MOTD );
if ( s[0] ) {
UI_DrawProportionalString( 320, y, s,
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
y += PROP_HEIGHT;
}
// some extra space after hostname and motd
y += 10;
}
// map-specific message (long map name)
s = CG_ConfigString( CS_MESSAGE );
if ( s[0] ) {
UI_DrawProportionalString( 320, y, s,
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
y += PROP_HEIGHT;
}
// cheats warning
s = Info_ValueForKey( sysInfo, "sv_cheats" );
if ( s[0] == '1' ) {
UI_DrawProportionalString( 320, y, "CHEATS ARE ENABLED",
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
y += PROP_HEIGHT;
}
// game type
switch ( cgs.gametype ) {
case GT_FFA:
s = "Free For All";
break;
case GT_SINGLE_PLAYER:
s = "Single Player";
break;
case GT_TOURNAMENT:
s = "Tournament";
break;
case GT_TEAM:
s = "Team Deathmatch";
break;
case GT_CTF:
s = "Capture The Flag";
break;
#ifdef MISSIONPACK
case GT_1FCTF:
s = "One Flag CTF";
break;
case GT_OBELISK:
s = "Overload";
break;
case GT_HARVESTER:
s = "Harvester";
break;
#endif
default:
s = "Unknown Gametype";
break;
}
UI_DrawProportionalString( 320, y, s,
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
y += PROP_HEIGHT;
value = atoi( Info_ValueForKey( info, "timelimit" ) );
if ( value ) {
UI_DrawProportionalString( 320, y, va( "timelimit %i", value ),
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
y += PROP_HEIGHT;
}
if (cgs.gametype < GT_CTF ) {
value = atoi( Info_ValueForKey( info, "fraglimit" ) );
if ( value ) {
UI_DrawProportionalString( 320, y, va( "fraglimit %i", value ),
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
y += PROP_HEIGHT;
}
}
if (cgs.gametype >= GT_CTF) {
value = atoi( Info_ValueForKey( info, "capturelimit" ) );
if ( value ) {
UI_DrawProportionalString( 320, y, va( "capturelimit %i", value ),
UI_CENTER|UI_SMALLFONT|UI_DROPSHADOW, colorWhite );
y += PROP_HEIGHT;
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,866 @@
// Copyright (C) 1999-2000 Id Software, Inc.
//
// cg_localents.c -- every frame, generate renderer commands for locally
// processed entities, like smoke puffs, gibs, shells, etc.
#include "cg_local.h"
#define MAX_LOCAL_ENTITIES 512
localEntity_t cg_localEntities[MAX_LOCAL_ENTITIES];
localEntity_t cg_activeLocalEntities; // double linked list
localEntity_t *cg_freeLocalEntities; // single linked list
/*
===================
CG_InitLocalEntities
This is called at startup and for tournement restarts
===================
*/
void CG_InitLocalEntities( void ) {
int i;
memset( cg_localEntities, 0, sizeof( cg_localEntities ) );
cg_activeLocalEntities.next = &cg_activeLocalEntities;
cg_activeLocalEntities.prev = &cg_activeLocalEntities;
cg_freeLocalEntities = cg_localEntities;
for ( i = 0 ; i < MAX_LOCAL_ENTITIES - 1 ; i++ ) {
cg_localEntities[i].next = &cg_localEntities[i+1];
}
}
/*
==================
CG_FreeLocalEntity
==================
*/
void CG_FreeLocalEntity( localEntity_t *le ) {
if ( !le->prev ) {
CG_Error( "CG_FreeLocalEntity: not active" );
}
// remove from the doubly linked active list
le->prev->next = le->next;
le->next->prev = le->prev;
// the free list is only singly linked
le->next = cg_freeLocalEntities;
cg_freeLocalEntities = le;
}
/*
===================
CG_AllocLocalEntity
Will allways succeed, even if it requires freeing an old active entity
===================
*/
localEntity_t *CG_AllocLocalEntity( void ) {
localEntity_t *le;
if ( !cg_freeLocalEntities ) {
// no free entities, so free the one at the end of the chain
// remove the oldest active entity
CG_FreeLocalEntity( cg_activeLocalEntities.prev );
}
le = cg_freeLocalEntities;
cg_freeLocalEntities = cg_freeLocalEntities->next;
memset( le, 0, sizeof( *le ) );
// link into the active list
le->next = cg_activeLocalEntities.next;
le->prev = &cg_activeLocalEntities;
cg_activeLocalEntities.next->prev = le;
cg_activeLocalEntities.next = le;
return le;
}
/*
====================================================================================
FRAGMENT PROCESSING
A fragment localentity interacts with the environment in some way (hitting walls),
or generates more localentities along a trail.
====================================================================================
*/
/*
================
CG_BloodTrail
Leave expanding blood puffs behind gibs
================
*/
void CG_BloodTrail( localEntity_t *le ) {
int t;
int t2;
int step;
vec3_t newOrigin;
localEntity_t *blood;
step = 150;
t = step * ( (cg.time - cg.frametime + step ) / step );
t2 = step * ( cg.time / step );
for ( ; t <= t2; t += step ) {
BG_EvaluateTrajectory( &le->pos, t, newOrigin );
blood = CG_SmokePuff( newOrigin, vec3_origin,
20, // radius
1, 1, 1, 1, // color
2000, // trailTime
t, // startTime
0, // fadeInTime
0, // flags
cgs.media.bloodTrailShader );
// use the optimized version
blood->leType = LE_FALL_SCALE_FADE;
// drop a total of 40 units over its lifetime
blood->pos.trDelta[2] = 40;
}
}
/*
================
CG_FragmentBounceMark
================
*/
void CG_FragmentBounceMark( localEntity_t *le, trace_t *trace ) {
int radius;
if ( le->leMarkType == LEMT_BLOOD ) {
radius = 16 + (rand()&31);
CG_ImpactMark( cgs.media.bloodMarkShader, trace->endpos, trace->plane.normal, random()*360,
1,1,1,1, qtrue, radius, qfalse );
} else if ( le->leMarkType == LEMT_BURN ) {
radius = 8 + (rand()&15);
CG_ImpactMark( cgs.media.burnMarkShader, trace->endpos, trace->plane.normal, random()*360,
1,1,1,1, qtrue, radius, qfalse );
}
// don't allow a fragment to make multiple marks, or they
// pile up while settling
le->leMarkType = LEMT_NONE;
}
/*
================
CG_FragmentBounceSound
================
*/
void CG_FragmentBounceSound( localEntity_t *le, trace_t *trace ) {
if ( le->leBounceSoundType == LEBS_BLOOD ) {
// half the gibs will make splat sounds
if ( rand() & 1 ) {
int r = rand()&3;
sfxHandle_t s;
if ( r == 0 ) {
s = cgs.media.gibBounce1Sound;
} else if ( r == 1 ) {
s = cgs.media.gibBounce2Sound;
} else {
s = cgs.media.gibBounce3Sound;
}
trap_S_StartSound( trace->endpos, ENTITYNUM_WORLD, CHAN_AUTO, s );
}
} else if ( le->leBounceSoundType == LEBS_BRASS ) {
}
// don't allow a fragment to make multiple bounce sounds,
// or it gets too noisy as they settle
le->leBounceSoundType = LEBS_NONE;
}
/*
================
CG_ReflectVelocity
================
*/
void CG_ReflectVelocity( localEntity_t *le, trace_t *trace ) {
vec3_t velocity;
float dot;
int hitTime;
// reflect the velocity on the trace plane
hitTime = cg.time - cg.frametime + cg.frametime * trace->fraction;
BG_EvaluateTrajectoryDelta( &le->pos, hitTime, velocity );
dot = DotProduct( velocity, trace->plane.normal );
VectorMA( velocity, -2*dot, trace->plane.normal, le->pos.trDelta );
VectorScale( le->pos.trDelta, le->bounceFactor, le->pos.trDelta );
VectorCopy( trace->endpos, le->pos.trBase );
le->pos.trTime = cg.time;
// check for stop, making sure that even on low FPS systems it doesn't bobble
if ( trace->allsolid ||
( trace->plane.normal[2] > 0 &&
( le->pos.trDelta[2] < 40 || le->pos.trDelta[2] < -cg.frametime * le->pos.trDelta[2] ) ) ) {
le->pos.trType = TR_STATIONARY;
} else {
}
}
/*
================
CG_AddFragment
================
*/
void CG_AddFragment( localEntity_t *le ) {
vec3_t newOrigin;
trace_t trace;
if ( le->pos.trType == TR_STATIONARY ) {
// sink into the ground if near the removal time
int t;
float oldZ;
t = le->endTime - cg.time;
if ( t < SINK_TIME ) {
// we must use an explicit lighting origin, otherwise the
// lighting would be lost as soon as the origin went
// into the ground
VectorCopy( le->refEntity.origin, le->refEntity.lightingOrigin );
le->refEntity.renderfx |= RF_LIGHTING_ORIGIN;
oldZ = le->refEntity.origin[2];
le->refEntity.origin[2] -= 16 * ( 1.0 - (float)t / SINK_TIME );
trap_R_AddRefEntityToScene( &le->refEntity );
le->refEntity.origin[2] = oldZ;
} else {
trap_R_AddRefEntityToScene( &le->refEntity );
}
return;
}
// calculate new position
BG_EvaluateTrajectory( &le->pos, cg.time, newOrigin );
// trace a line from previous position to new position
CG_Trace( &trace, le->refEntity.origin, NULL, NULL, newOrigin, -1, CONTENTS_SOLID );
if ( trace.fraction == 1.0 ) {
// still in free fall
VectorCopy( newOrigin, le->refEntity.origin );
if ( le->leFlags & LEF_TUMBLE ) {
vec3_t angles;
BG_EvaluateTrajectory( &le->angles, cg.time, angles );
AnglesToAxis( angles, le->refEntity.axis );
}
trap_R_AddRefEntityToScene( &le->refEntity );
// add a blood trail
if ( le->leBounceSoundType == LEBS_BLOOD ) {
CG_BloodTrail( le );
}
return;
}
// if it is in a nodrop zone, remove it
// this keeps gibs from waiting at the bottom of pits of death
// and floating levels
if ( trap_CM_PointContents( trace.endpos, 0 ) & CONTENTS_NODROP ) {
CG_FreeLocalEntity( le );
return;
}
// leave a mark
CG_FragmentBounceMark( le, &trace );
// do a bouncy sound
CG_FragmentBounceSound( le, &trace );
// reflect the velocity on the trace plane
CG_ReflectVelocity( le, &trace );
trap_R_AddRefEntityToScene( &le->refEntity );
}
/*
=====================================================================
TRIVIAL LOCAL ENTITIES
These only do simple scaling or modulation before passing to the renderer
=====================================================================
*/
/*
====================
CG_AddFadeRGB
====================
*/
void CG_AddFadeRGB( localEntity_t *le ) {
refEntity_t *re;
float c;
re = &le->refEntity;
c = ( le->endTime - cg.time ) * le->lifeRate;
c *= 0xff;
re->shaderRGBA[0] = le->color[0] * c;
re->shaderRGBA[1] = le->color[1] * c;
re->shaderRGBA[2] = le->color[2] * c;
re->shaderRGBA[3] = le->color[3] * c;
trap_R_AddRefEntityToScene( re );
}
/*
==================
CG_AddMoveScaleFade
==================
*/
static void CG_AddMoveScaleFade( localEntity_t *le ) {
refEntity_t *re;
float c;
vec3_t delta;
float len;
re = &le->refEntity;
if ( le->fadeInTime > le->startTime && cg.time < le->fadeInTime ) {
// fade / grow time
c = 1.0 - (float) ( le->fadeInTime - cg.time ) / ( le->fadeInTime - le->startTime );
}
else {
// fade / grow time
c = ( le->endTime - cg.time ) * le->lifeRate;
}
re->shaderRGBA[3] = 0xff * c * le->color[3];
if ( !( le->leFlags & LEF_PUFF_DONT_SCALE ) ) {
re->radius = le->radius * ( 1.0 - c ) + 8;
}
BG_EvaluateTrajectory( &le->pos, cg.time, re->origin );
// if the view would be "inside" the sprite, kill the sprite
// so it doesn't add too much overdraw
VectorSubtract( re->origin, cg.refdef.vieworg, delta );
len = VectorLength( delta );
if ( len < le->radius ) {
CG_FreeLocalEntity( le );
return;
}
trap_R_AddRefEntityToScene( re );
}
/*
===================
CG_AddScaleFade
For rocket smokes that hang in place, fade out, and are
removed if the view passes through them.
There are often many of these, so it needs to be simple.
===================
*/
static void CG_AddScaleFade( localEntity_t *le ) {
refEntity_t *re;
float c;
vec3_t delta;
float len;
re = &le->refEntity;
// fade / grow time
c = ( le->endTime - cg.time ) * le->lifeRate;
re->shaderRGBA[3] = 0xff * c * le->color[3];
re->radius = le->radius * ( 1.0 - c ) + 8;
// if the view would be "inside" the sprite, kill the sprite
// so it doesn't add too much overdraw
VectorSubtract( re->origin, cg.refdef.vieworg, delta );
len = VectorLength( delta );
if ( len < le->radius ) {
CG_FreeLocalEntity( le );
return;
}
trap_R_AddRefEntityToScene( re );
}
/*
=================
CG_AddFallScaleFade
This is just an optimized CG_AddMoveScaleFade
For blood mists that drift down, fade out, and are
removed if the view passes through them.
There are often 100+ of these, so it needs to be simple.
=================
*/
static void CG_AddFallScaleFade( localEntity_t *le ) {
refEntity_t *re;
float c;
vec3_t delta;
float len;
re = &le->refEntity;
// fade time
c = ( le->endTime - cg.time ) * le->lifeRate;
re->shaderRGBA[3] = 0xff * c * le->color[3];
re->origin[2] = le->pos.trBase[2] - ( 1.0 - c ) * le->pos.trDelta[2];
re->radius = le->radius * ( 1.0 - c ) + 16;
// if the view would be "inside" the sprite, kill the sprite
// so it doesn't add too much overdraw
VectorSubtract( re->origin, cg.refdef.vieworg, delta );
len = VectorLength( delta );
if ( len < le->radius ) {
CG_FreeLocalEntity( le );
return;
}
trap_R_AddRefEntityToScene( re );
}
/*
================
CG_AddExplosion
================
*/
static void CG_AddExplosion( localEntity_t *ex ) {
refEntity_t *ent;
ent = &ex->refEntity;
// add the entity
trap_R_AddRefEntityToScene(ent);
// add the dlight
if ( ex->light ) {
float light;
light = (float)( cg.time - ex->startTime ) / ( ex->endTime - ex->startTime );
if ( light < 0.5 ) {
light = 1.0;
} else {
light = 1.0 - ( light - 0.5 ) * 2;
}
light = ex->light * light;
trap_R_AddLightToScene(ent->origin, light, ex->lightColor[0], ex->lightColor[1], ex->lightColor[2] );
}
}
/*
================
CG_AddSpriteExplosion
================
*/
static void CG_AddSpriteExplosion( localEntity_t *le ) {
refEntity_t re;
float c;
re = le->refEntity;
c = ( le->endTime - cg.time ) / ( float ) ( le->endTime - le->startTime );
if ( c > 1 ) {
c = 1.0; // can happen during connection problems
}
re.shaderRGBA[0] = 0xff;
re.shaderRGBA[1] = 0xff;
re.shaderRGBA[2] = 0xff;
re.shaderRGBA[3] = 0xff * c * 0.33;
re.reType = RT_SPRITE;
re.radius = 42 * ( 1.0 - c ) + 30;
trap_R_AddRefEntityToScene( &re );
// add the dlight
if ( le->light ) {
float light;
light = (float)( cg.time - le->startTime ) / ( le->endTime - le->startTime );
if ( light < 0.5 ) {
light = 1.0;
} else {
light = 1.0 - ( light - 0.5 ) * 2;
}
light = le->light * light;
trap_R_AddLightToScene(re.origin, light, le->lightColor[0], le->lightColor[1], le->lightColor[2] );
}
}
#ifdef MISSIONPACK
/*
====================
CG_AddKamikaze
====================
*/
void CG_AddKamikaze( localEntity_t *le ) {
refEntity_t *re;
refEntity_t shockwave;
float c;
vec3_t test, axis[3];
int t;
re = &le->refEntity;
t = cg.time - le->startTime;
VectorClear( test );
AnglesToAxis( test, axis );
if (t > KAMI_SHOCKWAVE_STARTTIME && t < KAMI_SHOCKWAVE_ENDTIME) {
if (!(le->leFlags & LEF_SOUND1)) {
// trap_S_StartSound (re->origin, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.kamikazeExplodeSound );
trap_S_StartLocalSound(cgs.media.kamikazeExplodeSound, CHAN_AUTO);
le->leFlags |= LEF_SOUND1;
}
// 1st kamikaze shockwave
memset(&shockwave, 0, sizeof(shockwave));
shockwave.hModel = cgs.media.kamikazeShockWave;
shockwave.reType = RT_MODEL;
shockwave.shaderTime = re->shaderTime;
VectorCopy(re->origin, shockwave.origin);
c = (float)(t - KAMI_SHOCKWAVE_STARTTIME) / (float)(KAMI_SHOCKWAVE_ENDTIME - KAMI_SHOCKWAVE_STARTTIME);
VectorScale( axis[0], c * KAMI_SHOCKWAVE_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[0] );
VectorScale( axis[1], c * KAMI_SHOCKWAVE_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[1] );
VectorScale( axis[2], c * KAMI_SHOCKWAVE_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[2] );
shockwave.nonNormalizedAxes = qtrue;
if (t > KAMI_SHOCKWAVEFADE_STARTTIME) {
c = (float)(t - KAMI_SHOCKWAVEFADE_STARTTIME) / (float)(KAMI_SHOCKWAVE_ENDTIME - KAMI_SHOCKWAVEFADE_STARTTIME);
}
else {
c = 0;
}
c *= 0xff;
shockwave.shaderRGBA[0] = 0xff - c;
shockwave.shaderRGBA[1] = 0xff - c;
shockwave.shaderRGBA[2] = 0xff - c;
shockwave.shaderRGBA[3] = 0xff - c;
trap_R_AddRefEntityToScene( &shockwave );
}
if (t > KAMI_EXPLODE_STARTTIME && t < KAMI_IMPLODE_ENDTIME) {
// explosion and implosion
c = ( le->endTime - cg.time ) * le->lifeRate;
c *= 0xff;
re->shaderRGBA[0] = le->color[0] * c;
re->shaderRGBA[1] = le->color[1] * c;
re->shaderRGBA[2] = le->color[2] * c;
re->shaderRGBA[3] = le->color[3] * c;
if( t < KAMI_IMPLODE_STARTTIME ) {
c = (float)(t - KAMI_EXPLODE_STARTTIME) / (float)(KAMI_IMPLODE_STARTTIME - KAMI_EXPLODE_STARTTIME);
}
else {
if (!(le->leFlags & LEF_SOUND2)) {
// trap_S_StartSound (re->origin, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.kamikazeImplodeSound );
trap_S_StartLocalSound(cgs.media.kamikazeImplodeSound, CHAN_AUTO);
le->leFlags |= LEF_SOUND2;
}
c = (float)(KAMI_IMPLODE_ENDTIME - t) / (float) (KAMI_IMPLODE_ENDTIME - KAMI_IMPLODE_STARTTIME);
}
VectorScale( axis[0], c * KAMI_BOOMSPHERE_MAXRADIUS / KAMI_BOOMSPHEREMODEL_RADIUS, re->axis[0] );
VectorScale( axis[1], c * KAMI_BOOMSPHERE_MAXRADIUS / KAMI_BOOMSPHEREMODEL_RADIUS, re->axis[1] );
VectorScale( axis[2], c * KAMI_BOOMSPHERE_MAXRADIUS / KAMI_BOOMSPHEREMODEL_RADIUS, re->axis[2] );
re->nonNormalizedAxes = qtrue;
trap_R_AddRefEntityToScene( re );
// add the dlight
trap_R_AddLightToScene( re->origin, c * 1000.0, 1.0, 1.0, c );
}
if (t > KAMI_SHOCKWAVE2_STARTTIME && t < KAMI_SHOCKWAVE2_ENDTIME) {
// 2nd kamikaze shockwave
if (le->angles.trBase[0] == 0 &&
le->angles.trBase[1] == 0 &&
le->angles.trBase[2] == 0) {
le->angles.trBase[0] = random() * 360;
le->angles.trBase[1] = random() * 360;
le->angles.trBase[2] = random() * 360;
}
else {
c = 0;
}
memset(&shockwave, 0, sizeof(shockwave));
shockwave.hModel = cgs.media.kamikazeShockWave;
shockwave.reType = RT_MODEL;
shockwave.shaderTime = re->shaderTime;
VectorCopy(re->origin, shockwave.origin);
test[0] = le->angles.trBase[0];
test[1] = le->angles.trBase[1];
test[2] = le->angles.trBase[2];
AnglesToAxis( test, axis );
c = (float)(t - KAMI_SHOCKWAVE2_STARTTIME) / (float)(KAMI_SHOCKWAVE2_ENDTIME - KAMI_SHOCKWAVE2_STARTTIME);
VectorScale( axis[0], c * KAMI_SHOCKWAVE2_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[0] );
VectorScale( axis[1], c * KAMI_SHOCKWAVE2_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[1] );
VectorScale( axis[2], c * KAMI_SHOCKWAVE2_MAXRADIUS / KAMI_SHOCKWAVEMODEL_RADIUS, shockwave.axis[2] );
shockwave.nonNormalizedAxes = qtrue;
if (t > KAMI_SHOCKWAVE2FADE_STARTTIME) {
c = (float)(t - KAMI_SHOCKWAVE2FADE_STARTTIME) / (float)(KAMI_SHOCKWAVE2_ENDTIME - KAMI_SHOCKWAVE2FADE_STARTTIME);
}
else {
c = 0;
}
c *= 0xff;
shockwave.shaderRGBA[0] = 0xff - c;
shockwave.shaderRGBA[1] = 0xff - c;
shockwave.shaderRGBA[2] = 0xff - c;
shockwave.shaderRGBA[3] = 0xff - c;
trap_R_AddRefEntityToScene( &shockwave );
}
}
/*
===================
CG_AddInvulnerabilityImpact
===================
*/
void CG_AddInvulnerabilityImpact( localEntity_t *le ) {
trap_R_AddRefEntityToScene( &le->refEntity );
}
/*
===================
CG_AddInvulnerabilityJuiced
===================
*/
void CG_AddInvulnerabilityJuiced( localEntity_t *le ) {
int t;
t = cg.time - le->startTime;
if ( t > 3000 ) {
le->refEntity.axis[0][0] = (float) 1.0 + 0.3 * (t - 3000) / 2000;
le->refEntity.axis[1][1] = (float) 1.0 + 0.3 * (t - 3000) / 2000;
le->refEntity.axis[2][2] = (float) 0.7 + 0.3 * (2000 - (t - 3000)) / 2000;
}
if ( t > 5000 ) {
le->endTime = 0;
CG_GibPlayer( le->refEntity.origin );
}
else {
trap_R_AddRefEntityToScene( &le->refEntity );
}
}
/*
===================
CG_AddRefEntity
===================
*/
void CG_AddRefEntity( localEntity_t *le ) {
if (le->endTime < cg.time) {
CG_FreeLocalEntity( le );
return;
}
trap_R_AddRefEntityToScene( &le->refEntity );
}
#endif
/*
===================
CG_AddScorePlum
===================
*/
#define NUMBER_SIZE 8
void CG_AddScorePlum( localEntity_t *le ) {
refEntity_t *re;
vec3_t origin, delta, dir, vec, up = {0, 0, 1};
float c, len;
int i, score, digits[10], numdigits, negative;
re = &le->refEntity;
c = ( le->endTime - cg.time ) * le->lifeRate;
score = le->radius;
if (score < 0) {
re->shaderRGBA[0] = 0xff;
re->shaderRGBA[1] = 0x11;
re->shaderRGBA[2] = 0x11;
}
else {
re->shaderRGBA[0] = 0xff;
re->shaderRGBA[1] = 0xff;
re->shaderRGBA[2] = 0xff;
if (score >= 50) {
re->shaderRGBA[1] = 0;
} else if (score >= 20) {
re->shaderRGBA[0] = re->shaderRGBA[1] = 0;
} else if (score >= 10) {
re->shaderRGBA[2] = 0;
} else if (score >= 2) {
re->shaderRGBA[0] = re->shaderRGBA[2] = 0;
}
}
if (c < 0.25)
re->shaderRGBA[3] = 0xff * 4 * c;
else
re->shaderRGBA[3] = 0xff;
re->radius = NUMBER_SIZE / 2;
VectorCopy(le->pos.trBase, origin);
origin[2] += 110 - c * 100;
VectorSubtract(cg.refdef.vieworg, origin, dir);
CrossProduct(dir, up, vec);
VectorNormalize(vec);
VectorMA(origin, -10 + 20 * sin(c * 2 * M_PI), vec, origin);
// if the view would be "inside" the sprite, kill the sprite
// so it doesn't add too much overdraw
VectorSubtract( origin, cg.refdef.vieworg, delta );
len = VectorLength( delta );
if ( len < 20 ) {
CG_FreeLocalEntity( le );
return;
}
negative = qfalse;
if (score < 0) {
negative = qtrue;
score = -score;
}
for (numdigits = 0; !(numdigits && !score); numdigits++) {
digits[numdigits] = score % 10;
score = score / 10;
}
if (negative) {
digits[numdigits] = 10;
numdigits++;
}
for (i = 0; i < numdigits; i++) {
VectorMA(origin, (float) (((float) numdigits / 2) - i) * NUMBER_SIZE, vec, re->origin);
re->customShader = cgs.media.numberShaders[digits[numdigits-1-i]];
trap_R_AddRefEntityToScene( re );
}
}
//==============================================================================
/*
===================
CG_AddLocalEntities
===================
*/
void CG_AddLocalEntities( void ) {
localEntity_t *le, *next;
// walk the list backwards, so any new local entities generated
// (trails, marks, etc) will be present this frame
le = cg_activeLocalEntities.prev;
for ( ; le != &cg_activeLocalEntities ; le = next ) {
// grab next now, so if the local entity is freed we
// still have it
next = le->prev;
if ( cg.time >= le->endTime ) {
CG_FreeLocalEntity( le );
continue;
}
switch ( le->leType ) {
default:
CG_Error( "Bad leType: %i", le->leType );
break;
case LE_MARK:
break;
case LE_SPRITE_EXPLOSION:
CG_AddSpriteExplosion( le );
break;
case LE_EXPLOSION:
CG_AddExplosion( le );
break;
case LE_FRAGMENT: // gibs and brass
CG_AddFragment( le );
break;
case LE_MOVE_SCALE_FADE: // water bubbles
CG_AddMoveScaleFade( le );
break;
case LE_FADE_RGB: // teleporters, railtrails
CG_AddFadeRGB( le );
break;
case LE_FALL_SCALE_FADE: // gib blood trails
CG_AddFallScaleFade( le );
break;
case LE_SCALE_FADE: // rocket trails
CG_AddScaleFade( le );
break;
case LE_SCOREPLUM:
CG_AddScorePlum( le );
break;
#ifdef MISSIONPACK
case LE_KAMIKAZE:
CG_AddKamikaze( le );
break;
case LE_INVULIMPACT:
CG_AddInvulnerabilityImpact( le );
break;
case LE_INVULJUICED:
CG_AddInvulnerabilityJuiced( le );
break;
case LE_SHOWREFENTITY:
CG_AddRefEntity( le );
break;
#endif
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,506 @@
// Copyright (C) 1999-2000 Id Software, Inc.
//
// cg_playerstate.c -- this file acts on changes in a new playerState_t
// With normal play, this will be done after local prediction, but when
// following another player or playing back a demo, it will be checked
// when the snapshot transitions like all the other entities
#include "cg_local.h"
/*
==============
CG_CheckAmmo
If the ammo has gone low enough to generate the warning, play a sound
==============
*/
void CG_CheckAmmo( void ) {
int i;
int total;
int previous;
int weapons;
// see about how many seconds of ammo we have remaining
weapons = cg.snap->ps.stats[ STAT_WEAPONS ];
total = 0;
for ( i = WP_MACHINEGUN ; i < WP_NUM_WEAPONS ; i++ ) {
if ( ! ( weapons & ( 1 << i ) ) ) {
continue;
}
switch ( i ) {
case WP_ROCKET_LAUNCHER:
case WP_GRENADE_LAUNCHER:
case WP_RAILGUN:
case WP_SHOTGUN:
#ifdef MISSIONPACK
case WP_PROX_LAUNCHER:
#endif
total += cg.snap->ps.ammo[i] * 1000;
break;
default:
total += cg.snap->ps.ammo[i] * 200;
break;
}
if ( total >= 5000 ) {
cg.lowAmmoWarning = 0;
return;
}
}
previous = cg.lowAmmoWarning;
if ( total == 0 ) {
cg.lowAmmoWarning = 2;
} else {
cg.lowAmmoWarning = 1;
}
// play a sound on transitions
if ( cg.lowAmmoWarning != previous ) {
trap_S_StartLocalSound( cgs.media.noAmmoSound, CHAN_LOCAL_SOUND );
}
}
/*
==============
CG_DamageFeedback
==============
*/
void CG_DamageFeedback( int yawByte, int pitchByte, int damage ) {
float left, front, up;
float kick;
int health;
float scale;
vec3_t dir;
vec3_t angles;
float dist;
float yaw, pitch;
// show the attacking player's head and name in corner
cg.attackerTime = cg.time;
// the lower on health you are, the greater the view kick will be
health = cg.snap->ps.stats[STAT_HEALTH];
if ( health < 40 ) {
scale = 1;
} else {
scale = 40.0 / health;
}
kick = damage * scale;
if (kick < 5)
kick = 5;
if (kick > 10)
kick = 10;
// if yaw and pitch are both 255, make the damage always centered (falling, etc)
if ( yawByte == 255 && pitchByte == 255 ) {
cg.damageX = 0;
cg.damageY = 0;
cg.v_dmg_roll = 0;
cg.v_dmg_pitch = -kick;
} else {
// positional
pitch = pitchByte / 255.0 * 360;
yaw = yawByte / 255.0 * 360;
angles[PITCH] = pitch;
angles[YAW] = yaw;
angles[ROLL] = 0;
AngleVectors( angles, dir, NULL, NULL );
VectorSubtract( vec3_origin, dir, dir );
front = DotProduct (dir, cg.refdef.viewaxis[0] );
left = DotProduct (dir, cg.refdef.viewaxis[1] );
up = DotProduct (dir, cg.refdef.viewaxis[2] );
dir[0] = front;
dir[1] = left;
dir[2] = 0;
dist = VectorLength( dir );
if ( dist < 0.1 ) {
dist = 0.1f;
}
cg.v_dmg_roll = kick * left;
cg.v_dmg_pitch = -kick * front;
if ( front <= 0.1 ) {
front = 0.1f;
}
cg.damageX = -left / front;
cg.damageY = up / dist;
}
// clamp the position
if ( cg.damageX > 1.0 ) {
cg.damageX = 1.0;
}
if ( cg.damageX < - 1.0 ) {
cg.damageX = -1.0;
}
if ( cg.damageY > 1.0 ) {
cg.damageY = 1.0;
}
if ( cg.damageY < - 1.0 ) {
cg.damageY = -1.0;
}
// don't let the screen flashes vary as much
if ( kick > 10 ) {
kick = 10;
}
cg.damageValue = kick;
cg.v_dmg_time = cg.time + DAMAGE_TIME;
cg.damageTime = cg.snap->serverTime;
}
/*
================
CG_Respawn
A respawn happened this snapshot
================
*/
void CG_Respawn( void ) {
// no error decay on player movement
cg.thisFrameTeleport = qtrue;
// display weapons available
cg.weaponSelectTime = cg.time;
// select the weapon the server says we are using
cg.weaponSelect = cg.snap->ps.weapon;
}
extern char *eventnames[];
/*
==============
CG_CheckPlayerstateEvents
==============
*/
void CG_CheckPlayerstateEvents( playerState_t *ps, playerState_t *ops ) {
int i;
int event;
centity_t *cent;
if ( ps->externalEvent && ps->externalEvent != ops->externalEvent ) {
cent = &cg_entities[ ps->clientNum ];
cent->currentState.event = ps->externalEvent;
cent->currentState.eventParm = ps->externalEventParm;
CG_EntityEvent( cent, cent->lerpOrigin );
}
cent = &cg.predictedPlayerEntity; // cg_entities[ ps->clientNum ];
// go through the predictable events buffer
for ( i = ps->eventSequence - MAX_PS_EVENTS ; i < ps->eventSequence ; i++ ) {
// if we have a new predictable event
if ( i >= ops->eventSequence
// or the server told us to play another event instead of a predicted event we already issued
// or something the server told us changed our prediction causing a different event
|| (i > ops->eventSequence - MAX_PS_EVENTS && ps->events[i & (MAX_PS_EVENTS-1)] != ops->events[i & (MAX_PS_EVENTS-1)]) ) {
event = ps->events[ i & (MAX_PS_EVENTS-1) ];
cent->currentState.event = event;
cent->currentState.eventParm = ps->eventParms[ i & (MAX_PS_EVENTS-1) ];
CG_EntityEvent( cent, cent->lerpOrigin );
cg.predictableEvents[ i & (MAX_PREDICTED_EVENTS-1) ] = event;
cg.eventSequence++;
}
}
}
/*
==================
CG_CheckChangedPredictableEvents
==================
*/
void CG_CheckChangedPredictableEvents( playerState_t *ps ) {
int i;
int event;
centity_t *cent;
cent = &cg.predictedPlayerEntity;
for ( i = ps->eventSequence - MAX_PS_EVENTS ; i < ps->eventSequence ; i++ ) {
//
if (i >= cg.eventSequence) {
continue;
}
// if this event is not further back in than the maximum predictable events we remember
if (i > cg.eventSequence - MAX_PREDICTED_EVENTS) {
// if the new playerstate event is different from a previously predicted one
if ( ps->events[i & (MAX_PS_EVENTS-1)] != cg.predictableEvents[i & (MAX_PREDICTED_EVENTS-1) ] ) {
event = ps->events[ i & (MAX_PS_EVENTS-1) ];
cent->currentState.event = event;
cent->currentState.eventParm = ps->eventParms[ i & (MAX_PS_EVENTS-1) ];
CG_EntityEvent( cent, cent->lerpOrigin );
cg.predictableEvents[ i & (MAX_PREDICTED_EVENTS-1) ] = event;
if ( cg_showmiss.integer ) {
CG_Printf("WARNING: changed predicted event\n");
}
}
}
}
}
/*
==================
pushReward
==================
*/
static void pushReward(sfxHandle_t sfx, qhandle_t shader, int rewardCount) {
if (cg.rewardStack < (MAX_REWARDSTACK-1)) {
cg.rewardStack++;
cg.rewardSound[cg.rewardStack] = sfx;
cg.rewardShader[cg.rewardStack] = shader;
cg.rewardCount[cg.rewardStack] = rewardCount;
}
}
/*
==================
CG_CheckLocalSounds
==================
*/
void CG_CheckLocalSounds( playerState_t *ps, playerState_t *ops ) {
int highScore, health, armor, reward;
sfxHandle_t sfx;
// don't play the sounds if the player just changed teams
if ( ps->persistant[PERS_TEAM] != ops->persistant[PERS_TEAM] ) {
return;
}
// hit changes
if ( ps->persistant[PERS_HITS] > ops->persistant[PERS_HITS] ) {
armor = ps->persistant[PERS_ATTACKEE_ARMOR] & 0xff;
health = ps->persistant[PERS_ATTACKEE_ARMOR] >> 8;
#ifdef MISSIONPACK
if (armor > 50 ) {
trap_S_StartLocalSound( cgs.media.hitSoundHighArmor, CHAN_LOCAL_SOUND );
} else if (armor || health > 100) {
trap_S_StartLocalSound( cgs.media.hitSoundLowArmor, CHAN_LOCAL_SOUND );
} else {
trap_S_StartLocalSound( cgs.media.hitSound, CHAN_LOCAL_SOUND );
}
#else
trap_S_StartLocalSound( cgs.media.hitSound, CHAN_LOCAL_SOUND );
#endif
} else if ( ps->persistant[PERS_HITS] < ops->persistant[PERS_HITS] ) {
trap_S_StartLocalSound( cgs.media.hitTeamSound, CHAN_LOCAL_SOUND );
}
// health changes of more than -1 should make pain sounds
if ( ps->stats[STAT_HEALTH] < ops->stats[STAT_HEALTH] - 1 ) {
if ( ps->stats[STAT_HEALTH] > 0 ) {
CG_PainEvent( &cg.predictedPlayerEntity, ps->stats[STAT_HEALTH] );
}
}
// if we are going into the intermission, don't start any voices
if ( cg.intermissionStarted ) {
return;
}
// reward sounds
reward = qfalse;
if (ps->persistant[PERS_CAPTURES] != ops->persistant[PERS_CAPTURES]) {
pushReward(cgs.media.captureAwardSound, cgs.media.medalCapture, ps->persistant[PERS_CAPTURES]);
reward = qtrue;
//Com_Printf("capture\n");
}
if (ps->persistant[PERS_IMPRESSIVE_COUNT] != ops->persistant[PERS_IMPRESSIVE_COUNT]) {
#ifdef MISSIONPACK
if (ps->persistant[PERS_IMPRESSIVE_COUNT] == 1) {
sfx = cgs.media.firstImpressiveSound;
} else {
sfx = cgs.media.impressiveSound;
}
#else
sfx = cgs.media.impressiveSound;
#endif
pushReward(sfx, cgs.media.medalImpressive, ps->persistant[PERS_IMPRESSIVE_COUNT]);
reward = qtrue;
//Com_Printf("impressive\n");
}
if (ps->persistant[PERS_EXCELLENT_COUNT] != ops->persistant[PERS_EXCELLENT_COUNT]) {
#ifdef MISSIONPACK
if (ps->persistant[PERS_EXCELLENT_COUNT] == 1) {
sfx = cgs.media.firstExcellentSound;
} else {
sfx = cgs.media.excellentSound;
}
#else
sfx = cgs.media.excellentSound;
#endif
pushReward(sfx, cgs.media.medalExcellent, ps->persistant[PERS_EXCELLENT_COUNT]);
reward = qtrue;
//Com_Printf("excellent\n");
}
if (ps->persistant[PERS_GAUNTLET_FRAG_COUNT] != ops->persistant[PERS_GAUNTLET_FRAG_COUNT]) {
#ifdef MISSIONPACK
if (ops->persistant[PERS_GAUNTLET_FRAG_COUNT] == 1) {
sfx = cgs.media.firstHumiliationSound;
} else {
sfx = cgs.media.humiliationSound;
}
#else
sfx = cgs.media.humiliationSound;
#endif
pushReward(sfx, cgs.media.medalGauntlet, ps->persistant[PERS_GAUNTLET_FRAG_COUNT]);
reward = qtrue;
//Com_Printf("guantlet frag\n");
}
if (ps->persistant[PERS_DEFEND_COUNT] != ops->persistant[PERS_DEFEND_COUNT]) {
pushReward(cgs.media.defendSound, cgs.media.medalDefend, ps->persistant[PERS_DEFEND_COUNT]);
reward = qtrue;
//Com_Printf("defend\n");
}
if (ps->persistant[PERS_ASSIST_COUNT] != ops->persistant[PERS_ASSIST_COUNT]) {
pushReward(cgs.media.assistSound, cgs.media.medalAssist, ps->persistant[PERS_ASSIST_COUNT]);
reward = qtrue;
//Com_Printf("assist\n");
}
// if any of the player event bits changed
if (ps->persistant[PERS_PLAYEREVENTS] != ops->persistant[PERS_PLAYEREVENTS]) {
if ((ps->persistant[PERS_PLAYEREVENTS] & PLAYEREVENT_DENIEDREWARD) !=
(ops->persistant[PERS_PLAYEREVENTS] & PLAYEREVENT_DENIEDREWARD)) {
trap_S_StartLocalSound( cgs.media.deniedSound, CHAN_ANNOUNCER );
}
else if ((ps->persistant[PERS_PLAYEREVENTS] & PLAYEREVENT_GAUNTLETREWARD) !=
(ops->persistant[PERS_PLAYEREVENTS] & PLAYEREVENT_GAUNTLETREWARD)) {
trap_S_StartLocalSound( cgs.media.humiliationSound, CHAN_ANNOUNCER );
}
else if ((ps->persistant[PERS_PLAYEREVENTS] & PLAYEREVENT_HOLYSHIT) !=
(ops->persistant[PERS_PLAYEREVENTS] & PLAYEREVENT_HOLYSHIT)) {
trap_S_StartLocalSound( cgs.media.holyShitSound, CHAN_ANNOUNCER );
}
reward = qtrue;
}
// check for flag pickup
if ( cgs.gametype >= GT_TEAM ) {
if ((ps->powerups[PW_REDFLAG] != ops->powerups[PW_REDFLAG] && ps->powerups[PW_REDFLAG]) ||
(ps->powerups[PW_BLUEFLAG] != ops->powerups[PW_BLUEFLAG] && ps->powerups[PW_BLUEFLAG]) ||
(ps->powerups[PW_NEUTRALFLAG] != ops->powerups[PW_NEUTRALFLAG] && ps->powerups[PW_NEUTRALFLAG]) )
{
trap_S_StartLocalSound( cgs.media.youHaveFlagSound, CHAN_ANNOUNCER );
}
}
// lead changes
if (!reward) {
//
if ( !cg.warmup ) {
// never play lead changes during warmup
if ( ps->persistant[PERS_RANK] != ops->persistant[PERS_RANK] ) {
if ( cgs.gametype < GT_TEAM) {
if ( ps->persistant[PERS_RANK] == 0 ) {
CG_AddBufferedSound(cgs.media.takenLeadSound);
} else if ( ps->persistant[PERS_RANK] == RANK_TIED_FLAG ) {
CG_AddBufferedSound(cgs.media.tiedLeadSound);
} else if ( ( ops->persistant[PERS_RANK] & ~RANK_TIED_FLAG ) == 0 ) {
CG_AddBufferedSound(cgs.media.lostLeadSound);
}
}
}
}
}
// timelimit warnings
if ( cgs.timelimit > 0 ) {
int msec;
msec = cg.time - cgs.levelStartTime;
if ( !( cg.timelimitWarnings & 4 ) && msec > ( cgs.timelimit * 60 + 2 ) * 1000 ) {
cg.timelimitWarnings |= 1 | 2 | 4;
trap_S_StartLocalSound( cgs.media.suddenDeathSound, CHAN_ANNOUNCER );
}
else if ( !( cg.timelimitWarnings & 2 ) && msec > (cgs.timelimit - 1) * 60 * 1000 ) {
cg.timelimitWarnings |= 1 | 2;
trap_S_StartLocalSound( cgs.media.oneMinuteSound, CHAN_ANNOUNCER );
}
else if ( cgs.timelimit > 5 && !( cg.timelimitWarnings & 1 ) && msec > (cgs.timelimit - 5) * 60 * 1000 ) {
cg.timelimitWarnings |= 1;
trap_S_StartLocalSound( cgs.media.fiveMinuteSound, CHAN_ANNOUNCER );
}
}
// fraglimit warnings
if ( cgs.fraglimit > 0 && cgs.gametype < GT_CTF) {
highScore = cgs.scores1;
if ( !( cg.fraglimitWarnings & 4 ) && highScore == (cgs.fraglimit - 1) ) {
cg.fraglimitWarnings |= 1 | 2 | 4;
CG_AddBufferedSound(cgs.media.oneFragSound);
}
else if ( cgs.fraglimit > 2 && !( cg.fraglimitWarnings & 2 ) && highScore == (cgs.fraglimit - 2) ) {
cg.fraglimitWarnings |= 1 | 2;
CG_AddBufferedSound(cgs.media.twoFragSound);
}
else if ( cgs.fraglimit > 3 && !( cg.fraglimitWarnings & 1 ) && highScore == (cgs.fraglimit - 3) ) {
cg.fraglimitWarnings |= 1;
CG_AddBufferedSound(cgs.media.threeFragSound);
}
}
}
/*
===============
CG_TransitionPlayerState
===============
*/
void CG_TransitionPlayerState( playerState_t *ps, playerState_t *ops ) {
// check for changing follow mode
if ( ps->clientNum != ops->clientNum ) {
cg.thisFrameTeleport = qtrue;
// make sure we don't get any unwanted transition effects
*ops = *ps;
}
// damage events (player is getting wounded)
if ( ps->damageEvent != ops->damageEvent && ps->damageCount ) {
CG_DamageFeedback( ps->damageYaw, ps->damagePitch, ps->damageCount );
}
// respawning
if ( ps->persistant[PERS_SPAWN_COUNT] != ops->persistant[PERS_SPAWN_COUNT] ) {
CG_Respawn();
}
if ( cg.mapRestart ) {
CG_Respawn();
cg.mapRestart = qfalse;
}
if ( cg.snap->ps.pm_type != PM_INTERMISSION
&& ps->persistant[PERS_TEAM] != TEAM_SPECTATOR ) {
CG_CheckLocalSounds( ps, ops );
}
// check for going low on ammo
CG_CheckAmmo();
// run events
CG_CheckPlayerstateEvents( ps, ops );
// smooth the ducking viewheight change
if ( ps->viewheight != ops->viewheight ) {
cg.duckChange = ps->viewheight - ops->viewheight;
cg.duckTime = cg.time;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,608 @@
// Copyright (C) 1999-2000 Id Software, Inc.
//
// cg_predict.c -- this file generates cg.predictedPlayerState by either
// interpolating between snapshots from the server or locally predicting
// ahead the client's movement.
// It also handles local physics interaction, like fragments bouncing off walls
#include "cg_local.h"
static pmove_t cg_pmove;
static int cg_numSolidEntities;
static centity_t *cg_solidEntities[MAX_ENTITIES_IN_SNAPSHOT];
static int cg_numTriggerEntities;
static centity_t *cg_triggerEntities[MAX_ENTITIES_IN_SNAPSHOT];
/*
====================
CG_BuildSolidList
When a new cg.snap has been set, this function builds a sublist
of the entities that are actually solid, to make for more
efficient collision detection
====================
*/
void CG_BuildSolidList( void ) {
int i;
centity_t *cent;
snapshot_t *snap;
entityState_t *ent;
cg_numSolidEntities = 0;
cg_numTriggerEntities = 0;
if ( cg.nextSnap && !cg.nextFrameTeleport && !cg.thisFrameTeleport ) {
snap = cg.nextSnap;
} else {
snap = cg.snap;
}
for ( i = 0 ; i < snap->numEntities ; i++ ) {
cent = &cg_entities[ snap->entities[ i ].number ];
ent = &cent->currentState;
if ( ent->eType == ET_ITEM || ent->eType == ET_PUSH_TRIGGER || ent->eType == ET_TELEPORT_TRIGGER ) {
cg_triggerEntities[cg_numTriggerEntities] = cent;
cg_numTriggerEntities++;
continue;
}
if ( cent->nextState.solid ) {
cg_solidEntities[cg_numSolidEntities] = cent;
cg_numSolidEntities++;
continue;
}
}
}
/*
====================
CG_ClipMoveToEntities
====================
*/
static void CG_ClipMoveToEntities ( const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end,
int skipNumber, int mask, trace_t *tr ) {
int i, x, zd, zu;
trace_t trace;
entityState_t *ent;
clipHandle_t cmodel;
vec3_t bmins, bmaxs;
vec3_t origin, angles;
centity_t *cent;
for ( i = 0 ; i < cg_numSolidEntities ; i++ ) {
cent = cg_solidEntities[ i ];
ent = &cent->currentState;
if ( ent->number == skipNumber ) {
continue;
}
if ( ent->solid == SOLID_BMODEL ) {
// special value for bmodel
cmodel = trap_CM_InlineModel( ent->modelindex );
VectorCopy( cent->lerpAngles, angles );
BG_EvaluateTrajectory( &cent->currentState.pos, cg.physicsTime, origin );
} else {
// encoded bbox
x = (ent->solid & 255);
zd = ((ent->solid>>8) & 255);
zu = ((ent->solid>>16) & 255) - 32;
bmins[0] = bmins[1] = -x;
bmaxs[0] = bmaxs[1] = x;
bmins[2] = -zd;
bmaxs[2] = zu;
cmodel = trap_CM_TempBoxModel( bmins, bmaxs );
VectorCopy( vec3_origin, angles );
VectorCopy( cent->lerpOrigin, origin );
}
trap_CM_TransformedBoxTrace ( &trace, start, end,
mins, maxs, cmodel, mask, origin, angles);
if (trace.allsolid || trace.fraction < tr->fraction) {
trace.entityNum = ent->number;
*tr = trace;
} else if (trace.startsolid) {
tr->startsolid = qtrue;
}
if ( tr->allsolid ) {
return;
}
}
}
/*
================
CG_Trace
================
*/
void CG_Trace( trace_t *result, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end,
int skipNumber, int mask ) {
trace_t t;
trap_CM_BoxTrace ( &t, start, end, mins, maxs, 0, mask);
t.entityNum = t.fraction != 1.0 ? ENTITYNUM_WORLD : ENTITYNUM_NONE;
// check all other solid models
CG_ClipMoveToEntities (start, mins, maxs, end, skipNumber, mask, &t);
*result = t;
}
/*
================
CG_PointContents
================
*/
int CG_PointContents( const vec3_t point, int passEntityNum ) {
int i;
entityState_t *ent;
centity_t *cent;
clipHandle_t cmodel;
int contents;
contents = trap_CM_PointContents (point, 0);
for ( i = 0 ; i < cg_numSolidEntities ; i++ ) {
cent = cg_solidEntities[ i ];
ent = &cent->currentState;
if ( ent->number == passEntityNum ) {
continue;
}
if (ent->solid != SOLID_BMODEL) { // special value for bmodel
continue;
}
cmodel = trap_CM_InlineModel( ent->modelindex );
if ( !cmodel ) {
continue;
}
contents |= trap_CM_TransformedPointContents( point, cmodel, ent->origin, ent->angles );
}
return contents;
}
/*
========================
CG_InterpolatePlayerState
Generates cg.predictedPlayerState by interpolating between
cg.snap->player_state and cg.nextFrame->player_state
========================
*/
static void CG_InterpolatePlayerState( qboolean grabAngles ) {
float f;
int i;
playerState_t *out;
snapshot_t *prev, *next;
out = &cg.predictedPlayerState;
prev = cg.snap;
next = cg.nextSnap;
*out = cg.snap->ps;
// if we are still allowing local input, short circuit the view angles
if ( grabAngles ) {
usercmd_t cmd;
int cmdNum;
cmdNum = trap_GetCurrentCmdNumber();
trap_GetUserCmd( cmdNum, &cmd );
PM_UpdateViewAngles( out, &cmd );
}
// if the next frame is a teleport, we can't lerp to it
if ( cg.nextFrameTeleport ) {
return;
}
if ( !next || next->serverTime <= prev->serverTime ) {
return;
}
f = (float)( cg.time - prev->serverTime ) / ( next->serverTime - prev->serverTime );
i = next->ps.bobCycle;
if ( i < prev->ps.bobCycle ) {
i += 256; // handle wraparound
}
out->bobCycle = prev->ps.bobCycle + f * ( i - prev->ps.bobCycle );
for ( i = 0 ; i < 3 ; i++ ) {
out->origin[i] = prev->ps.origin[i] + f * (next->ps.origin[i] - prev->ps.origin[i] );
if ( !grabAngles ) {
out->viewangles[i] = LerpAngle(
prev->ps.viewangles[i], next->ps.viewangles[i], f );
}
out->velocity[i] = prev->ps.velocity[i] +
f * (next->ps.velocity[i] - prev->ps.velocity[i] );
}
}
/*
===================
CG_TouchItem
===================
*/
static void CG_TouchItem( centity_t *cent ) {
gitem_t *item;
if ( !cg_predictItems.integer ) {
return;
}
if ( !BG_PlayerTouchesItem( &cg.predictedPlayerState, &cent->currentState, cg.time ) ) {
return;
}
// never pick an item up twice in a prediction
if ( cent->miscTime == cg.time ) {
return;
}
if ( !BG_CanItemBeGrabbed( cgs.gametype, &cent->currentState, &cg.predictedPlayerState ) ) {
return; // can't hold it
}
item = &bg_itemlist[ cent->currentState.modelindex ];
// Special case for flags.
// We don't predict touching our own flag
#ifdef MISSIONPACK
if( cgs.gametype == GT_1FCTF ) {
if( item->giTag != PW_NEUTRALFLAG ) {
return;
}
}
if( cgs.gametype == GT_CTF || cgs.gametype == GT_HARVESTER ) {
#else
if( cgs.gametype == GT_CTF ) {
#endif
if (cg.predictedPlayerState.persistant[PERS_TEAM] == TEAM_RED &&
item->giTag == PW_REDFLAG)
return;
if (cg.predictedPlayerState.persistant[PERS_TEAM] == TEAM_BLUE &&
item->giTag == PW_BLUEFLAG)
return;
}
// grab it
BG_AddPredictableEventToPlayerstate( EV_ITEM_PICKUP, cent->currentState.modelindex , &cg.predictedPlayerState);
// remove it from the frame so it won't be drawn
cent->currentState.eFlags |= EF_NODRAW;
// don't touch it again this prediction
cent->miscTime = cg.time;
// if its a weapon, give them some predicted ammo so the autoswitch will work
if ( item->giType == IT_WEAPON ) {
cg.predictedPlayerState.stats[ STAT_WEAPONS ] |= 1 << item->giTag;
if ( !cg.predictedPlayerState.ammo[ item->giTag ] ) {
cg.predictedPlayerState.ammo[ item->giTag ] = 1;
}
}
}
/*
=========================
CG_TouchTriggerPrediction
Predict push triggers and items
=========================
*/
static void CG_TouchTriggerPrediction( void ) {
int i;
trace_t trace;
entityState_t *ent;
clipHandle_t cmodel;
centity_t *cent;
qboolean spectator;
// dead clients don't activate triggers
if ( cg.predictedPlayerState.stats[STAT_HEALTH] <= 0 ) {
return;
}
spectator = ( cg.predictedPlayerState.pm_type == PM_SPECTATOR );
if ( cg.predictedPlayerState.pm_type != PM_NORMAL && !spectator ) {
return;
}
for ( i = 0 ; i < cg_numTriggerEntities ; i++ ) {
cent = cg_triggerEntities[ i ];
ent = &cent->currentState;
if ( ent->eType == ET_ITEM && !spectator ) {
CG_TouchItem( cent );
continue;
}
if ( ent->solid != SOLID_BMODEL ) {
continue;
}
cmodel = trap_CM_InlineModel( ent->modelindex );
if ( !cmodel ) {
continue;
}
trap_CM_BoxTrace( &trace, cg.predictedPlayerState.origin, cg.predictedPlayerState.origin,
cg_pmove.mins, cg_pmove.maxs, cmodel, -1 );
if ( !trace.startsolid ) {
continue;
}
if ( ent->eType == ET_TELEPORT_TRIGGER ) {
cg.hyperspace = qtrue;
} else if ( ent->eType == ET_PUSH_TRIGGER ) {
BG_TouchJumpPad( &cg.predictedPlayerState, ent );
}
}
// if we didn't touch a jump pad this pmove frame
if ( cg.predictedPlayerState.jumppad_frame != cg.predictedPlayerState.pmove_framecount ) {
cg.predictedPlayerState.jumppad_frame = 0;
cg.predictedPlayerState.jumppad_ent = 0;
}
}
/*
=================
CG_PredictPlayerState
Generates cg.predictedPlayerState for the current cg.time
cg.predictedPlayerState is guaranteed to be valid after exiting.
For demo playback, this will be an interpolation between two valid
playerState_t.
For normal gameplay, it will be the result of predicted usercmd_t on
top of the most recent playerState_t received from the server.
Each new snapshot will usually have one or more new usercmd over the last,
but we simulate all unacknowledged commands each time, not just the new ones.
This means that on an internet connection, quite a few pmoves may be issued
each frame.
OPTIMIZE: don't re-simulate unless the newly arrived snapshot playerState_t
differs from the predicted one. Would require saving all intermediate
playerState_t during prediction.
We detect prediction errors and allow them to be decayed off over several frames
to ease the jerk.
=================
*/
void CG_PredictPlayerState( void ) {
int cmdNum, current;
playerState_t oldPlayerState;
qboolean moved;
usercmd_t oldestCmd;
usercmd_t latestCmd;
cg.hyperspace = qfalse; // will be set if touching a trigger_teleport
// if this is the first frame we must guarantee
// predictedPlayerState is valid even if there is some
// other error condition
if ( !cg.validPPS ) {
cg.validPPS = qtrue;
cg.predictedPlayerState = cg.snap->ps;
}
// demo playback just copies the moves
if ( cg.demoPlayback || (cg.snap->ps.pm_flags & PMF_FOLLOW) ) {
CG_InterpolatePlayerState( qfalse );
return;
}
// non-predicting local movement will grab the latest angles
if ( cg_nopredict.integer || cg_synchronousClients.integer ) {
CG_InterpolatePlayerState( qtrue );
return;
}
// prepare for pmove
cg_pmove.ps = &cg.predictedPlayerState;
cg_pmove.trace = CG_Trace;
cg_pmove.pointcontents = CG_PointContents;
if ( cg_pmove.ps->pm_type == PM_DEAD ) {
cg_pmove.tracemask = MASK_PLAYERSOLID & ~CONTENTS_BODY;
}
else {
cg_pmove.tracemask = MASK_PLAYERSOLID;
}
if ( cg.snap->ps.persistant[PERS_TEAM] == TEAM_SPECTATOR ) {
cg_pmove.tracemask &= ~CONTENTS_BODY; // spectators can fly through bodies
}
cg_pmove.noFootsteps = ( cgs.dmflags & DF_NO_FOOTSTEPS ) > 0;
// save the state before the pmove so we can detect transitions
oldPlayerState = cg.predictedPlayerState;
current = trap_GetCurrentCmdNumber();
// if we don't have the commands right after the snapshot, we
// can't accurately predict a current position, so just freeze at
// the last good position we had
cmdNum = current - CMD_BACKUP + 1;
trap_GetUserCmd( cmdNum, &oldestCmd );
if ( oldestCmd.serverTime > cg.snap->ps.commandTime
&& oldestCmd.serverTime < cg.time ) { // special check for map_restart
if ( cg_showmiss.integer ) {
CG_Printf ("exceeded PACKET_BACKUP on commands\n");
}
return;
}
// get the latest command so we can know which commands are from previous map_restarts
trap_GetUserCmd( current, &latestCmd );
// get the most recent information we have, even if
// the server time is beyond our current cg.time,
// because predicted player positions are going to
// be ahead of everything else anyway
if ( cg.nextSnap && !cg.nextFrameTeleport && !cg.thisFrameTeleport ) {
cg.predictedPlayerState = cg.nextSnap->ps;
cg.physicsTime = cg.nextSnap->serverTime;
} else {
cg.predictedPlayerState = cg.snap->ps;
cg.physicsTime = cg.snap->serverTime;
}
if ( pmove_msec.integer < 8 ) {
trap_Cvar_Set("pmove_msec", "8");
}
else if (pmove_msec.integer > 33) {
trap_Cvar_Set("pmove_msec", "33");
}
cg_pmove.pmove_fixed = pmove_fixed.integer;// | cg_pmove_fixed.integer;
cg_pmove.pmove_msec = pmove_msec.integer;
// run cmds
moved = qfalse;
for ( cmdNum = current - CMD_BACKUP + 1 ; cmdNum <= current ; cmdNum++ ) {
// get the command
trap_GetUserCmd( cmdNum, &cg_pmove.cmd );
if ( cg_pmove.pmove_fixed ) {
PM_UpdateViewAngles( cg_pmove.ps, &cg_pmove.cmd );
}
// don't do anything if the time is before the snapshot player time
if ( cg_pmove.cmd.serverTime <= cg.predictedPlayerState.commandTime ) {
continue;
}
// don't do anything if the command was from a previous map_restart
if ( cg_pmove.cmd.serverTime > latestCmd.serverTime ) {
continue;
}
// check for a prediction error from last frame
// on a lan, this will often be the exact value
// from the snapshot, but on a wan we will have
// to predict several commands to get to the point
// we want to compare
if ( cg.predictedPlayerState.commandTime == oldPlayerState.commandTime ) {
vec3_t delta;
float len;
if ( cg.thisFrameTeleport ) {
// a teleport will not cause an error decay
VectorClear( cg.predictedError );
if ( cg_showmiss.integer ) {
CG_Printf( "PredictionTeleport\n" );
}
cg.thisFrameTeleport = qfalse;
} else {
vec3_t adjusted;
CG_AdjustPositionForMover( cg.predictedPlayerState.origin,
cg.predictedPlayerState.groundEntityNum, cg.physicsTime, cg.oldTime, adjusted );
if ( cg_showmiss.integer ) {
if (!VectorCompare( oldPlayerState.origin, adjusted )) {
CG_Printf("prediction error\n");
}
}
VectorSubtract( oldPlayerState.origin, adjusted, delta );
len = VectorLength( delta );
if ( len > 0.1 ) {
if ( cg_showmiss.integer ) {
CG_Printf("Prediction miss: %f\n", len);
}
if ( cg_errorDecay.integer ) {
int t;
float f;
t = cg.time - cg.predictedErrorTime;
f = ( cg_errorDecay.value - t ) / cg_errorDecay.value;
if ( f < 0 ) {
f = 0;
}
if ( f > 0 && cg_showmiss.integer ) {
CG_Printf("Double prediction decay: %f\n", f);
}
VectorScale( cg.predictedError, f, cg.predictedError );
} else {
VectorClear( cg.predictedError );
}
VectorAdd( delta, cg.predictedError, cg.predictedError );
cg.predictedErrorTime = cg.oldTime;
}
}
}
// don't predict gauntlet firing, which is only supposed to happen
// when it actually inflicts damage
cg_pmove.gauntletHit = qfalse;
if ( cg_pmove.pmove_fixed ) {
cg_pmove.cmd.serverTime = ((cg_pmove.cmd.serverTime + pmove_msec.integer-1) / pmove_msec.integer) * pmove_msec.integer;
}
Pmove (&cg_pmove);
moved = qtrue;
// add push trigger movement effects
CG_TouchTriggerPrediction();
// check for predictable events that changed from previous predictions
//CG_CheckChangedPredictableEvents(&cg.predictedPlayerState);
}
if ( cg_showmiss.integer > 1 ) {
CG_Printf( "[%i : %i] ", cg_pmove.cmd.serverTime, cg.time );
}
if ( !moved ) {
if ( cg_showmiss.integer ) {
CG_Printf( "not moved\n" );
}
return;
}
// adjust for the movement of the groundentity
CG_AdjustPositionForMover( cg.predictedPlayerState.origin,
cg.predictedPlayerState.groundEntityNum,
cg.physicsTime, cg.time, cg.predictedPlayerState.origin );
if ( cg_showmiss.integer ) {
if (cg.predictedPlayerState.eventSequence > oldPlayerState.eventSequence + MAX_PS_EVENTS) {
CG_Printf("WARNING: dropped event\n");
}
}
// fire events and other transition triggered things
CG_TransitionPlayerState( &cg.predictedPlayerState, &oldPlayerState );
if ( cg_showmiss.integer ) {
if (cg.eventSequence > cg.predictedPlayerState.eventSequence) {
CG_Printf("WARNING: double event\n");
cg.eventSequence = cg.predictedPlayerState.eventSequence;
}
}
}

View File

@@ -0,0 +1,218 @@
// Copyright (C) 1999-2000 Id Software, Inc.
//
#define CMD_BACKUP 64
#define CMD_MASK (CMD_BACKUP - 1)
// allow a lot of command backups for very fast systems
// multiple commands may be combined into a single packet, so this
// needs to be larger than PACKET_BACKUP
#define MAX_ENTITIES_IN_SNAPSHOT 256
// snapshots are a view of the server at a given time
// Snapshots are generated at regular time intervals by the server,
// but they may not be sent if a client's rate level is exceeded, or
// they may be dropped by the network.
typedef struct {
int snapFlags; // SNAPFLAG_RATE_DELAYED, etc
int ping;
int serverTime; // server time the message is valid for (in msec)
byte areamask[MAX_MAP_AREA_BYTES]; // portalarea visibility bits
playerState_t ps; // complete information about the current player at this time
int numEntities; // all of the entities that need to be presented
entityState_t entities[MAX_ENTITIES_IN_SNAPSHOT]; // at the time of this snapshot
int numServerCommands; // text based server commands to execute when this
int serverCommandSequence; // snapshot becomes current
} snapshot_t;
enum {
CGAME_EVENT_NONE,
CGAME_EVENT_TEAMMENU,
CGAME_EVENT_SCOREBOARD,
CGAME_EVENT_EDITHUD
};
/*
==================================================================
functions imported from the main executable
==================================================================
*/
#define CGAME_IMPORT_API_VERSION 4
typedef enum {
CG_PRINT,
CG_ERROR,
CG_MILLISECONDS,
CG_CVAR_REGISTER,
CG_CVAR_UPDATE,
CG_CVAR_SET,
CG_CVAR_VARIABLESTRINGBUFFER,
CG_ARGC,
CG_ARGV,
CG_ARGS,
CG_FS_FOPENFILE,
CG_FS_READ,
CG_FS_WRITE,
CG_FS_FCLOSEFILE,
CG_SENDCONSOLECOMMAND,
CG_ADDCOMMAND,
CG_SENDCLIENTCOMMAND,
CG_UPDATESCREEN,
CG_CM_LOADMAP,
CG_CM_NUMINLINEMODELS,
CG_CM_INLINEMODEL,
CG_CM_LOADMODEL,
CG_CM_TEMPBOXMODEL,
CG_CM_POINTCONTENTS,
CG_CM_TRANSFORMEDPOINTCONTENTS,
CG_CM_BOXTRACE,
CG_CM_TRANSFORMEDBOXTRACE,
CG_CM_MARKFRAGMENTS,
CG_S_STARTSOUND,
CG_S_STARTLOCALSOUND,
CG_S_CLEARLOOPINGSOUNDS,
CG_S_ADDLOOPINGSOUND,
CG_S_UPDATEENTITYPOSITION,
CG_S_RESPATIALIZE,
CG_S_REGISTERSOUND,
CG_S_STARTBACKGROUNDTRACK,
CG_R_LOADWORLDMAP,
CG_R_REGISTERMODEL,
CG_R_REGISTERSKIN,
CG_R_REGISTERSHADER,
CG_R_CLEARSCENE,
CG_R_ADDREFENTITYTOSCENE,
CG_R_ADDPOLYTOSCENE,
CG_R_ADDLIGHTTOSCENE,
CG_R_RENDERSCENE,
CG_R_SETCOLOR,
CG_R_DRAWSTRETCHPIC,
CG_R_MODELBOUNDS,
CG_R_LERPTAG,
CG_GETGLCONFIG,
CG_GETGAMESTATE,
CG_GETCURRENTSNAPSHOTNUMBER,
CG_GETSNAPSHOT,
CG_GETSERVERCOMMAND,
CG_GETCURRENTCMDNUMBER,
CG_GETUSERCMD,
CG_SETUSERCMDVALUE,
CG_R_REGISTERSHADERNOMIP,
CG_MEMORY_REMAINING,
CG_R_REGISTERFONT,
CG_KEY_ISDOWN,
CG_KEY_GETCATCHER,
CG_KEY_SETCATCHER,
CG_KEY_GETKEY,
CG_PC_ADD_GLOBAL_DEFINE,
CG_PC_LOAD_SOURCE,
CG_PC_FREE_SOURCE,
CG_PC_READ_TOKEN,
CG_PC_SOURCE_FILE_AND_LINE,
CG_S_STOPBACKGROUNDTRACK,
CG_REAL_TIME,
CG_SNAPVECTOR,
CG_REMOVECOMMAND,
CG_R_LIGHTFORPOINT,
CG_CIN_PLAYCINEMATIC,
CG_CIN_STOPCINEMATIC,
CG_CIN_RUNCINEMATIC,
CG_CIN_DRAWCINEMATIC,
CG_CIN_SETEXTENTS,
CG_R_REMAP_SHADER,
CG_S_ADDREALLOOPINGSOUND,
CG_S_STOPLOOPINGSOUND,
CG_CM_TEMPCAPSULEMODEL,
CG_CM_CAPSULETRACE,
CG_CM_TRANSFORMEDCAPSULETRACE,
CG_R_ADDADDITIVELIGHTTOSCENE,
CG_GET_ENTITY_TOKEN,
CG_R_ADDPOLYSTOSCENE,
CG_R_INPVS,
// 1.32
CG_FS_SEEK,
/*
CG_LOADCAMERA,
CG_STARTCAMERA,
CG_GETCAMERAINFO,
*/
CG_MEMSET = 100,
CG_MEMCPY,
CG_STRNCPY,
CG_SIN,
CG_COS,
CG_ATAN2,
CG_SQRT,
CG_FLOOR,
CG_CEIL,
CG_TESTPRINTINT,
CG_TESTPRINTFLOAT,
CG_ACOS
} cgameImport_t;
/*
==================================================================
functions exported to the main executable
==================================================================
*/
typedef enum {
CG_INIT,
// void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum )
// called when the level loads or when the renderer is restarted
// all media should be registered at this time
// cgame will display loading status by calling SCR_Update, which
// will call CG_DrawInformation during the loading process
// reliableCommandSequence will be 0 on fresh loads, but higher for
// demos, tourney restarts, or vid_restarts
CG_SHUTDOWN,
// void (*CG_Shutdown)( void );
// oportunity to flush and close any open files
CG_CONSOLE_COMMAND,
// qboolean (*CG_ConsoleCommand)( void );
// a console command has been issued locally that is not recognized by the
// main game system.
// use Cmd_Argc() / Cmd_Argv() to read the command, return qfalse if the
// command is not known to the game
CG_DRAW_ACTIVE_FRAME,
// void (*CG_DrawActiveFrame)( int serverTime, stereoFrame_t stereoView, qboolean demoPlayback );
// Generates and draws a game scene and status information at the given time.
// If demoPlayback is set, local movement prediction will not be enabled
CG_CROSSHAIR_PLAYER,
// int (*CG_CrosshairPlayer)( void );
CG_LAST_ATTACKER,
// int (*CG_LastAttacker)( void );
CG_KEY_EVENT,
// void (*CG_KeyEvent)( int key, qboolean down );
CG_MOUSE_EVENT,
// void (*CG_MouseEvent)( int dx, int dy );
CG_EVENT_HANDLING
// void (*CG_EventHandling)(int type);
} cgameExport_t;
//----------------------------------------------

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,514 @@
// Copyright (C) 1999-2000 Id Software, Inc.
//
// cg_scoreboard -- draw the scoreboard on top of the game screen
#include "cg_local.h"
#define SCOREBOARD_X (0)
#define SB_HEADER 86
#define SB_TOP (SB_HEADER+32)
// Where the status bar starts, so we don't overwrite it
#define SB_STATUSBAR 420
#define SB_NORMAL_HEIGHT 40
#define SB_INTER_HEIGHT 16 // interleaved height
#define SB_MAXCLIENTS_NORMAL ((SB_STATUSBAR - SB_TOP) / SB_NORMAL_HEIGHT)
#define SB_MAXCLIENTS_INTER ((SB_STATUSBAR - SB_TOP) / SB_INTER_HEIGHT - 1)
// Used when interleaved
#define SB_LEFT_BOTICON_X (SCOREBOARD_X+0)
#define SB_LEFT_HEAD_X (SCOREBOARD_X+32)
#define SB_RIGHT_BOTICON_X (SCOREBOARD_X+64)
#define SB_RIGHT_HEAD_X (SCOREBOARD_X+96)
// Normal
#define SB_BOTICON_X (SCOREBOARD_X+32)
#define SB_HEAD_X (SCOREBOARD_X+64)
#define SB_SCORELINE_X 112
#define SB_RATING_WIDTH (6 * BIGCHAR_WIDTH) // width 6
#define SB_SCORE_X (SB_SCORELINE_X + BIGCHAR_WIDTH) // width 6
#define SB_RATING_X (SB_SCORELINE_X + 6 * BIGCHAR_WIDTH) // width 6
#define SB_PING_X (SB_SCORELINE_X + 12 * BIGCHAR_WIDTH + 8) // width 5
#define SB_TIME_X (SB_SCORELINE_X + 17 * BIGCHAR_WIDTH + 8) // width 5
#define SB_NAME_X (SB_SCORELINE_X + 22 * BIGCHAR_WIDTH) // width 15
// The new and improved score board
//
// In cases where the number of clients is high, the score board heads are interleaved
// here's the layout
//
// 0 32 80 112 144 240 320 400 <-- pixel position
// bot head bot head score ping time name
//
// wins/losses are drawn on bot icon now
static qboolean localClient; // true if local client has been displayed
/*
=================
CG_DrawScoreboard
=================
*/
static void CG_DrawClientScore( int y, score_t *score, float *color, float fade, qboolean largeFormat ) {
char string[1024];
vec3_t headAngles;
clientInfo_t *ci;
int iconx, headx;
if ( score->client < 0 || score->client >= cgs.maxclients ) {
Com_Printf( "Bad score->client: %i\n", score->client );
return;
}
ci = &cgs.clientinfo[score->client];
iconx = SB_BOTICON_X + (SB_RATING_WIDTH / 2);
headx = SB_HEAD_X + (SB_RATING_WIDTH / 2);
// draw the handicap or bot skill marker (unless player has flag)
if ( ci->powerups & ( 1 << PW_NEUTRALFLAG ) ) {
if( largeFormat ) {
CG_DrawFlagModel( iconx, y - ( 32 - BIGCHAR_HEIGHT ) / 2, 32, 32, TEAM_FREE, qfalse );
}
else {
CG_DrawFlagModel( iconx, y, 16, 16, TEAM_FREE, qfalse );
}
} else if ( ci->powerups & ( 1 << PW_REDFLAG ) ) {
if( largeFormat ) {
CG_DrawFlagModel( iconx, y - ( 32 - BIGCHAR_HEIGHT ) / 2, 32, 32, TEAM_RED, qfalse );
}
else {
CG_DrawFlagModel( iconx, y, 16, 16, TEAM_RED, qfalse );
}
} else if ( ci->powerups & ( 1 << PW_BLUEFLAG ) ) {
if( largeFormat ) {
CG_DrawFlagModel( iconx, y - ( 32 - BIGCHAR_HEIGHT ) / 2, 32, 32, TEAM_BLUE, qfalse );
}
else {
CG_DrawFlagModel( iconx, y, 16, 16, TEAM_BLUE, qfalse );
}
} else {
if ( ci->botSkill > 0 && ci->botSkill <= 5 ) {
if ( cg_drawIcons.integer ) {
if( largeFormat ) {
CG_DrawPic( iconx, y - ( 32 - BIGCHAR_HEIGHT ) / 2, 32, 32, cgs.media.botSkillShaders[ ci->botSkill - 1 ] );
}
else {
CG_DrawPic( iconx, y, 16, 16, cgs.media.botSkillShaders[ ci->botSkill - 1 ] );
}
}
} else if ( ci->handicap < 100 ) {
Com_sprintf( string, sizeof( string ), "%i", ci->handicap );
if ( cgs.gametype == GT_TOURNAMENT )
CG_DrawSmallStringColor( iconx, y - SMALLCHAR_HEIGHT/2, string, color );
else
CG_DrawSmallStringColor( iconx, y, string, color );
}
// draw the wins / losses
if ( cgs.gametype == GT_TOURNAMENT ) {
Com_sprintf( string, sizeof( string ), "%i/%i", ci->wins, ci->losses );
if( ci->handicap < 100 && !ci->botSkill ) {
CG_DrawSmallStringColor( iconx, y + SMALLCHAR_HEIGHT/2, string, color );
}
else {
CG_DrawSmallStringColor( iconx, y, string, color );
}
}
}
// draw the face
VectorClear( headAngles );
headAngles[YAW] = 180;
if( largeFormat ) {
CG_DrawHead( headx, y - ( ICON_SIZE - BIGCHAR_HEIGHT ) / 2, ICON_SIZE, ICON_SIZE,
score->client, headAngles );
}
else {
CG_DrawHead( headx, y, 16, 16, score->client, headAngles );
}
#ifdef MISSIONPACK
// draw the team task
if ( ci->teamTask != TEAMTASK_NONE ) {
if ( ci->teamTask == TEAMTASK_OFFENSE ) {
CG_DrawPic( headx + 48, y, 16, 16, cgs.media.assaultShader );
}
else if ( ci->teamTask == TEAMTASK_DEFENSE ) {
CG_DrawPic( headx + 48, y, 16, 16, cgs.media.defendShader );
}
}
#endif
// draw the score line
if ( score->ping == -1 ) {
Com_sprintf(string, sizeof(string),
" connecting %s", ci->name);
} else if ( ci->team == TEAM_SPECTATOR ) {
Com_sprintf(string, sizeof(string),
" SPECT %3i %4i %s", score->ping, score->time, ci->name);
} else {
Com_sprintf(string, sizeof(string),
"%5i %4i %4i %s", score->score, score->ping, score->time, ci->name);
}
// highlight your position
if ( score->client == cg.snap->ps.clientNum ) {
float hcolor[4];
int rank;
localClient = qtrue;
if ( cg.snap->ps.persistant[PERS_TEAM] == TEAM_SPECTATOR
|| cgs.gametype >= GT_TEAM ) {
rank = -1;
} else {
rank = cg.snap->ps.persistant[PERS_RANK] & ~RANK_TIED_FLAG;
}
if ( rank == 0 ) {
hcolor[0] = 0;
hcolor[1] = 0;
hcolor[2] = 0.7f;
} else if ( rank == 1 ) {
hcolor[0] = 0.7f;
hcolor[1] = 0;
hcolor[2] = 0;
} else if ( rank == 2 ) {
hcolor[0] = 0.7f;
hcolor[1] = 0.7f;
hcolor[2] = 0;
} else {
hcolor[0] = 0.7f;
hcolor[1] = 0.7f;
hcolor[2] = 0.7f;
}
hcolor[3] = fade * 0.7;
CG_FillRect( SB_SCORELINE_X + BIGCHAR_WIDTH + (SB_RATING_WIDTH / 2), y,
640 - SB_SCORELINE_X - BIGCHAR_WIDTH, BIGCHAR_HEIGHT+1, hcolor );
}
CG_DrawBigString( SB_SCORELINE_X + (SB_RATING_WIDTH / 2), y, string, fade );
// add the "ready" marker for intermission exiting
if ( cg.snap->ps.stats[ STAT_CLIENTS_READY ] & ( 1 << score->client ) ) {
CG_DrawBigStringColor( iconx, y, "READY", color );
}
}
/*
=================
CG_TeamScoreboard
=================
*/
static int CG_TeamScoreboard( int y, team_t team, float fade, int maxClients, int lineHeight ) {
int i;
score_t *score;
float color[4];
int count;
clientInfo_t *ci;
color[0] = color[1] = color[2] = 1.0;
color[3] = fade;
count = 0;
for ( i = 0 ; i < cg.numScores && count < maxClients ; i++ ) {
score = &cg.scores[i];
ci = &cgs.clientinfo[ score->client ];
if ( team != ci->team ) {
continue;
}
CG_DrawClientScore( y + lineHeight * count, score, color, fade, lineHeight == SB_NORMAL_HEIGHT );
count++;
}
return count;
}
/*
=================
CG_DrawScoreboard
Draw the normal in-game scoreboard
=================
*/
qboolean CG_DrawOldScoreboard( void ) {
int x, y, w, i, n1, n2;
float fade;
float *fadeColor;
char *s;
int maxClients;
int lineHeight;
int topBorderSize, bottomBorderSize;
// don't draw amuthing if the menu or console is up
if ( cg_paused.integer ) {
cg.deferredPlayerLoading = 0;
return qfalse;
}
if ( cgs.gametype == GT_SINGLE_PLAYER && cg.predictedPlayerState.pm_type == PM_INTERMISSION ) {
cg.deferredPlayerLoading = 0;
return qfalse;
}
// don't draw scoreboard during death while warmup up
if ( cg.warmup && !cg.showScores ) {
return qfalse;
}
if ( cg.showScores || cg.predictedPlayerState.pm_type == PM_DEAD ||
cg.predictedPlayerState.pm_type == PM_INTERMISSION ) {
fade = 1.0;
fadeColor = colorWhite;
} else {
fadeColor = CG_FadeColor( cg.scoreFadeTime, FADE_TIME );
if ( !fadeColor ) {
// next time scoreboard comes up, don't print killer
cg.deferredPlayerLoading = 0;
cg.killerName[0] = 0;
return qfalse;
}
fade = *fadeColor;
}
// fragged by ... line
if ( cg.killerName[0] ) {
s = va("Fragged by %s", cg.killerName );
w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH;
x = ( SCREEN_WIDTH - w ) / 2;
y = 40;
CG_DrawBigString( x, y, s, fade );
}
// current rank
if ( cgs.gametype < GT_TEAM) {
if (cg.snap->ps.persistant[PERS_TEAM] != TEAM_SPECTATOR ) {
s = va("%s place with %i",
CG_PlaceString( cg.snap->ps.persistant[PERS_RANK] + 1 ),
cg.snap->ps.persistant[PERS_SCORE] );
w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH;
x = ( SCREEN_WIDTH - w ) / 2;
y = 60;
CG_DrawBigString( x, y, s, fade );
}
} else {
if ( cg.teamScores[0] == cg.teamScores[1] ) {
s = va("Teams are tied at %i", cg.teamScores[0] );
} else if ( cg.teamScores[0] >= cg.teamScores[1] ) {
s = va("Red leads %i to %i",cg.teamScores[0], cg.teamScores[1] );
} else {
s = va("Blue leads %i to %i",cg.teamScores[1], cg.teamScores[0] );
}
w = CG_DrawStrlen( s ) * BIGCHAR_WIDTH;
x = ( SCREEN_WIDTH - w ) / 2;
y = 60;
CG_DrawBigString( x, y, s, fade );
}
// scoreboard
y = SB_HEADER;
CG_DrawPic( SB_SCORE_X + (SB_RATING_WIDTH / 2), y, 64, 32, cgs.media.scoreboardScore );
CG_DrawPic( SB_PING_X - (SB_RATING_WIDTH / 2), y, 64, 32, cgs.media.scoreboardPing );
CG_DrawPic( SB_TIME_X - (SB_RATING_WIDTH / 2), y, 64, 32, cgs.media.scoreboardTime );
CG_DrawPic( SB_NAME_X - (SB_RATING_WIDTH / 2), y, 64, 32, cgs.media.scoreboardName );
y = SB_TOP;
// If there are more than SB_MAXCLIENTS_NORMAL, use the interleaved scores
if ( cg.numScores > SB_MAXCLIENTS_NORMAL ) {
maxClients = SB_MAXCLIENTS_INTER;
lineHeight = SB_INTER_HEIGHT;
topBorderSize = 8;
bottomBorderSize = 16;
} else {
maxClients = SB_MAXCLIENTS_NORMAL;
lineHeight = SB_NORMAL_HEIGHT;
topBorderSize = 16;
bottomBorderSize = 16;
}
localClient = qfalse;
if ( cgs.gametype >= GT_TEAM ) {
//
// teamplay scoreboard
//
y += lineHeight/2;
if ( cg.teamScores[0] >= cg.teamScores[1] ) {
n1 = CG_TeamScoreboard( y, TEAM_RED, fade, maxClients, lineHeight );
CG_DrawTeamBackground( 0, y - topBorderSize, 640, n1 * lineHeight + bottomBorderSize, 0.33f, TEAM_RED );
y += (n1 * lineHeight) + BIGCHAR_HEIGHT;
maxClients -= n1;
n2 = CG_TeamScoreboard( y, TEAM_BLUE, fade, maxClients, lineHeight );
CG_DrawTeamBackground( 0, y - topBorderSize, 640, n2 * lineHeight + bottomBorderSize, 0.33f, TEAM_BLUE );
y += (n2 * lineHeight) + BIGCHAR_HEIGHT;
maxClients -= n2;
} else {
n1 = CG_TeamScoreboard( y, TEAM_BLUE, fade, maxClients, lineHeight );
CG_DrawTeamBackground( 0, y - topBorderSize, 640, n1 * lineHeight + bottomBorderSize, 0.33f, TEAM_BLUE );
y += (n1 * lineHeight) + BIGCHAR_HEIGHT;
maxClients -= n1;
n2 = CG_TeamScoreboard( y, TEAM_RED, fade, maxClients, lineHeight );
CG_DrawTeamBackground( 0, y - topBorderSize, 640, n2 * lineHeight + bottomBorderSize, 0.33f, TEAM_RED );
y += (n2 * lineHeight) + BIGCHAR_HEIGHT;
maxClients -= n2;
}
n1 = CG_TeamScoreboard( y, TEAM_SPECTATOR, fade, maxClients, lineHeight );
y += (n1 * lineHeight) + BIGCHAR_HEIGHT;
} else {
//
// free for all scoreboard
//
n1 = CG_TeamScoreboard( y, TEAM_FREE, fade, maxClients, lineHeight );
y += (n1 * lineHeight) + BIGCHAR_HEIGHT;
n2 = CG_TeamScoreboard( y, TEAM_SPECTATOR, fade, maxClients - n1, lineHeight );
y += (n2 * lineHeight) + BIGCHAR_HEIGHT;
}
if (!localClient) {
// draw local client at the bottom
for ( i = 0 ; i < cg.numScores ; i++ ) {
if ( cg.scores[i].client == cg.snap->ps.clientNum ) {
CG_DrawClientScore( y, &cg.scores[i], fadeColor, fade, lineHeight == SB_NORMAL_HEIGHT );
break;
}
}
}
// load any models that have been deferred
if ( ++cg.deferredPlayerLoading > 10 ) {
CG_LoadDeferredPlayers();
}
return qtrue;
}
//================================================================================
/*
================
CG_CenterGiantLine
================
*/
static void CG_CenterGiantLine( float y, const char *string ) {
float x;
vec4_t color;
color[0] = 1;
color[1] = 1;
color[2] = 1;
color[3] = 1;
x = 0.5 * ( 640 - GIANT_WIDTH * CG_DrawStrlen( string ) );
CG_DrawStringExt( x, y, string, color, qtrue, qtrue, GIANT_WIDTH, GIANT_HEIGHT, 0 );
}
/*
=================
CG_DrawTourneyScoreboard
Draw the oversize scoreboard for tournements
=================
*/
void CG_DrawOldTourneyScoreboard( void ) {
const char *s;
vec4_t color;
int min, tens, ones;
clientInfo_t *ci;
int y;
int i;
// request more scores regularly
if ( cg.scoresRequestTime + 2000 < cg.time ) {
cg.scoresRequestTime = cg.time;
trap_SendClientCommand( "score" );
}
color[0] = 1;
color[1] = 1;
color[2] = 1;
color[3] = 1;
// draw the dialog background
color[0] = color[1] = color[2] = 0;
color[3] = 1;
CG_FillRect( 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, color );
// print the mesage of the day
s = CG_ConfigString( CS_MOTD );
if ( !s[0] ) {
s = "Scoreboard";
}
// print optional title
CG_CenterGiantLine( 8, s );
// print server time
ones = cg.time / 1000;
min = ones / 60;
ones %= 60;
tens = ones / 10;
ones %= 10;
s = va("%i:%i%i", min, tens, ones );
CG_CenterGiantLine( 64, s );
// print the two scores
y = 160;
if ( cgs.gametype >= GT_TEAM ) {
//
// teamplay scoreboard
//
CG_DrawStringExt( 8, y, "Red Team", color, qtrue, qtrue, GIANT_WIDTH, GIANT_HEIGHT, 0 );
s = va("%i", cg.teamScores[0] );
CG_DrawStringExt( 632 - GIANT_WIDTH * strlen(s), y, s, color, qtrue, qtrue, GIANT_WIDTH, GIANT_HEIGHT, 0 );
y += 64;
CG_DrawStringExt( 8, y, "Blue Team", color, qtrue, qtrue, GIANT_WIDTH, GIANT_HEIGHT, 0 );
s = va("%i", cg.teamScores[1] );
CG_DrawStringExt( 632 - GIANT_WIDTH * strlen(s), y, s, color, qtrue, qtrue, GIANT_WIDTH, GIANT_HEIGHT, 0 );
} else {
//
// free for all scoreboard
//
for ( i = 0 ; i < MAX_CLIENTS ; i++ ) {
ci = &cgs.clientinfo[i];
if ( !ci->infoValid ) {
continue;
}
if ( ci->team != TEAM_FREE ) {
continue;
}
CG_DrawStringExt( 8, y, ci->name, color, qtrue, qtrue, GIANT_WIDTH, GIANT_HEIGHT, 0 );
s = va("%i", ci->score );
CG_DrawStringExt( 632 - GIANT_WIDTH * strlen(s), y, s, color, qtrue, qtrue, GIANT_WIDTH, GIANT_HEIGHT, 0 );
y += 64;
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,383 @@
// Copyright (C) 1999-2000 Id Software, Inc.
//
// cg_snapshot.c -- things that happen on snapshot transition,
// not necessarily every single rendered frame
#include "cg_local.h"
/*
==================
CG_ResetEntity
==================
*/
static void CG_ResetEntity( centity_t *cent ) {
// if the previous snapshot this entity was updated in is at least
// an event window back in time then we can reset the previous event
if ( cent->snapShotTime < cg.time - EVENT_VALID_MSEC ) {
cent->previousEvent = 0;
}
cent->trailTime = cg.snap->serverTime;
VectorCopy (cent->currentState.origin, cent->lerpOrigin);
VectorCopy (cent->currentState.angles, cent->lerpAngles);
if ( cent->currentState.eType == ET_PLAYER ) {
CG_ResetPlayerEntity( cent );
}
}
/*
===============
CG_TransitionEntity
cent->nextState is moved to cent->currentState and events are fired
===============
*/
static void CG_TransitionEntity( centity_t *cent ) {
cent->currentState = cent->nextState;
cent->currentValid = qtrue;
// reset if the entity wasn't in the last frame or was teleported
if ( !cent->interpolate ) {
CG_ResetEntity( cent );
}
// clear the next state. if will be set by the next CG_SetNextSnap
cent->interpolate = qfalse;
// check for events
CG_CheckEvents( cent );
}
/*
==================
CG_SetInitialSnapshot
This will only happen on the very first snapshot, or
on tourney restarts. All other times will use
CG_TransitionSnapshot instead.
FIXME: Also called by map_restart?
==================
*/
void CG_SetInitialSnapshot( snapshot_t *snap ) {
int i;
centity_t *cent;
entityState_t *state;
cg.snap = snap;
BG_PlayerStateToEntityState( &snap->ps, &cg_entities[ snap->ps.clientNum ].currentState, qfalse );
// sort out solid entities
CG_BuildSolidList();
CG_ExecuteNewServerCommands( snap->serverCommandSequence );
// set our local weapon selection pointer to
// what the server has indicated the current weapon is
CG_Respawn();
for ( i = 0 ; i < cg.snap->numEntities ; i++ ) {
state = &cg.snap->entities[ i ];
cent = &cg_entities[ state->number ];
memcpy(&cent->currentState, state, sizeof(entityState_t));
//cent->currentState = *state;
cent->interpolate = qfalse;
cent->currentValid = qtrue;
CG_ResetEntity( cent );
// check for events
CG_CheckEvents( cent );
}
}
/*
===================
CG_TransitionSnapshot
The transition point from snap to nextSnap has passed
===================
*/
static void CG_TransitionSnapshot( void ) {
centity_t *cent;
snapshot_t *oldFrame;
int i;
if ( !cg.snap ) {
CG_Error( "CG_TransitionSnapshot: NULL cg.snap" );
}
if ( !cg.nextSnap ) {
CG_Error( "CG_TransitionSnapshot: NULL cg.nextSnap" );
}
// execute any server string commands before transitioning entities
CG_ExecuteNewServerCommands( cg.nextSnap->serverCommandSequence );
// if we had a map_restart, set everthing with initial
if ( !cg.snap ) {
}
// clear the currentValid flag for all entities in the existing snapshot
for ( i = 0 ; i < cg.snap->numEntities ; i++ ) {
cent = &cg_entities[ cg.snap->entities[ i ].number ];
cent->currentValid = qfalse;
}
// move nextSnap to snap and do the transitions
oldFrame = cg.snap;
cg.snap = cg.nextSnap;
BG_PlayerStateToEntityState( &cg.snap->ps, &cg_entities[ cg.snap->ps.clientNum ].currentState, qfalse );
cg_entities[ cg.snap->ps.clientNum ].interpolate = qfalse;
for ( i = 0 ; i < cg.snap->numEntities ; i++ ) {
cent = &cg_entities[ cg.snap->entities[ i ].number ];
CG_TransitionEntity( cent );
// remember time of snapshot this entity was last updated in
cent->snapShotTime = cg.snap->serverTime;
}
cg.nextSnap = NULL;
// check for playerstate transition events
if ( oldFrame ) {
playerState_t *ops, *ps;
ops = &oldFrame->ps;
ps = &cg.snap->ps;
// teleporting checks are irrespective of prediction
if ( ( ps->eFlags ^ ops->eFlags ) & EF_TELEPORT_BIT ) {
cg.thisFrameTeleport = qtrue; // will be cleared by prediction code
}
// if we are not doing client side movement prediction for any
// reason, then the client events and view changes will be issued now
if ( cg.demoPlayback || (cg.snap->ps.pm_flags & PMF_FOLLOW)
|| cg_nopredict.integer || cg_synchronousClients.integer ) {
CG_TransitionPlayerState( ps, ops );
}
}
}
/*
===================
CG_SetNextSnap
A new snapshot has just been read in from the client system.
===================
*/
static void CG_SetNextSnap( snapshot_t *snap ) {
int num;
entityState_t *es;
centity_t *cent;
cg.nextSnap = snap;
BG_PlayerStateToEntityState( &snap->ps, &cg_entities[ snap->ps.clientNum ].nextState, qfalse );
cg_entities[ cg.snap->ps.clientNum ].interpolate = qtrue;
// check for extrapolation errors
for ( num = 0 ; num < snap->numEntities ; num++ ) {
es = &snap->entities[num];
cent = &cg_entities[ es->number ];
memcpy(&cent->nextState, es, sizeof(entityState_t));
//cent->nextState = *es;
// if this frame is a teleport, or the entity wasn't in the
// previous frame, don't interpolate
if ( !cent->currentValid || ( ( cent->currentState.eFlags ^ es->eFlags ) & EF_TELEPORT_BIT ) ) {
cent->interpolate = qfalse;
} else {
cent->interpolate = qtrue;
}
}
// if the next frame is a teleport for the playerstate, we
// can't interpolate during demos
if ( cg.snap && ( ( snap->ps.eFlags ^ cg.snap->ps.eFlags ) & EF_TELEPORT_BIT ) ) {
cg.nextFrameTeleport = qtrue;
} else {
cg.nextFrameTeleport = qfalse;
}
// if changing follow mode, don't interpolate
if ( cg.nextSnap->ps.clientNum != cg.snap->ps.clientNum ) {
cg.nextFrameTeleport = qtrue;
}
// if changing server restarts, don't interpolate
if ( ( cg.nextSnap->snapFlags ^ cg.snap->snapFlags ) & SNAPFLAG_SERVERCOUNT ) {
cg.nextFrameTeleport = qtrue;
}
// sort out solid entities
CG_BuildSolidList();
}
/*
========================
CG_ReadNextSnapshot
This is the only place new snapshots are requested
This may increment cgs.processedSnapshotNum multiple
times if the client system fails to return a
valid snapshot.
========================
*/
static snapshot_t *CG_ReadNextSnapshot( void ) {
qboolean r;
snapshot_t *dest;
if ( cg.latestSnapshotNum > cgs.processedSnapshotNum + 1000 ) {
CG_Printf( "WARNING: CG_ReadNextSnapshot: way out of range, %i > %i",
cg.latestSnapshotNum, cgs.processedSnapshotNum );
}
while ( cgs.processedSnapshotNum < cg.latestSnapshotNum ) {
// decide which of the two slots to load it into
if ( cg.snap == &cg.activeSnapshots[0] ) {
dest = &cg.activeSnapshots[1];
} else {
dest = &cg.activeSnapshots[0];
}
// try to read the snapshot from the client system
cgs.processedSnapshotNum++;
r = trap_GetSnapshot( cgs.processedSnapshotNum, dest );
// FIXME: why would trap_GetSnapshot return a snapshot with the same server time
if ( cg.snap && r && dest->serverTime == cg.snap->serverTime ) {
//continue;
}
// if it succeeded, return
if ( r ) {
CG_AddLagometerSnapshotInfo( dest );
return dest;
}
// a GetSnapshot will return failure if the snapshot
// never arrived, or is so old that its entities
// have been shoved off the end of the circular
// buffer in the client system.
// record as a dropped packet
CG_AddLagometerSnapshotInfo( NULL );
// If there are additional snapshots, continue trying to
// read them.
}
// nothing left to read
return NULL;
}
/*
============
CG_ProcessSnapshots
We are trying to set up a renderable view, so determine
what the simulated time is, and try to get snapshots
both before and after that time if available.
If we don't have a valid cg.snap after exiting this function,
then a 3D game view cannot be rendered. This should only happen
right after the initial connection. After cg.snap has been valid
once, it will never turn invalid.
Even if cg.snap is valid, cg.nextSnap may not be, if the snapshot
hasn't arrived yet (it becomes an extrapolating situation instead
of an interpolating one)
============
*/
void CG_ProcessSnapshots( void ) {
snapshot_t *snap;
int n;
// see what the latest snapshot the client system has is
trap_GetCurrentSnapshotNumber( &n, &cg.latestSnapshotTime );
if ( n != cg.latestSnapshotNum ) {
if ( n < cg.latestSnapshotNum ) {
// this should never happen
CG_Error( "CG_ProcessSnapshots: n < cg.latestSnapshotNum" );
}
cg.latestSnapshotNum = n;
}
// If we have yet to receive a snapshot, check for it.
// Once we have gotten the first snapshot, cg.snap will
// always have valid data for the rest of the game
while ( !cg.snap ) {
snap = CG_ReadNextSnapshot();
if ( !snap ) {
// we can't continue until we get a snapshot
return;
}
// set our weapon selection to what
// the playerstate is currently using
if ( !( snap->snapFlags & SNAPFLAG_NOT_ACTIVE ) ) {
CG_SetInitialSnapshot( snap );
}
}
// loop until we either have a valid nextSnap with a serverTime
// greater than cg.time to interpolate towards, or we run
// out of available snapshots
do {
// if we don't have a nextframe, try and read a new one in
if ( !cg.nextSnap ) {
snap = CG_ReadNextSnapshot();
// if we still don't have a nextframe, we will just have to
// extrapolate
if ( !snap ) {
break;
}
CG_SetNextSnap( snap );
// if time went backwards, we have a level restart
if ( cg.nextSnap->serverTime < cg.snap->serverTime ) {
CG_Error( "CG_ProcessSnapshots: Server time went backwards" );
}
}
// if our time is < nextFrame's, we have a nice interpolating state
if ( cg.time >= cg.snap->serverTime && cg.time < cg.nextSnap->serverTime ) {
break;
}
// we have passed the transition from nextFrame to frame
CG_TransitionSnapshot();
} while ( 1 );
// assert our valid conditions upon exiting
if ( cg.snap == NULL ) {
CG_Error( "CG_ProcessSnapshots: cg.snap == NULL" );
}
if ( cg.time < cg.snap->serverTime ) {
// this can happen right after a vid_restart
cg.time = cg.snap->serverTime;
}
if ( cg.nextSnap != NULL && cg.nextSnap->serverTime <= cg.time ) {
CG_Error( "CG_ProcessSnapshots: cg.nextSnap->serverTime <= cg.time" );
}
}

View File

@@ -0,0 +1,106 @@
code
equ trap_Print -1
equ trap_Error -2
equ trap_Milliseconds -3
equ trap_Cvar_Register -4
equ trap_Cvar_Update -5
equ trap_Cvar_Set -6
equ trap_Cvar_VariableStringBuffer -7
equ trap_Argc -8
equ trap_Argv -9
equ trap_Args -10
equ trap_FS_FOpenFile -11
equ trap_FS_Read -12
equ trap_FS_Write -13
equ trap_FS_FCloseFile -14
equ trap_SendConsoleCommand -15
equ trap_AddCommand -16
equ trap_SendClientCommand -17
equ trap_UpdateScreen -18
equ trap_CM_LoadMap -19
equ trap_CM_NumInlineModels -20
equ trap_CM_InlineModel -21
equ trap_CM_LoadModel -22
equ trap_CM_TempBoxModel -23
equ trap_CM_PointContents -24
equ trap_CM_TransformedPointContents -25
equ trap_CM_BoxTrace -26
equ trap_CM_TransformedBoxTrace -27
equ trap_CM_MarkFragments -28
equ trap_S_StartSound -29
equ trap_S_StartLocalSound -30
equ trap_S_ClearLoopingSounds -31
equ trap_S_AddLoopingSound -32
equ trap_S_UpdateEntityPosition -33
equ trap_S_Respatialize -34
equ trap_S_RegisterSound -35
equ trap_S_StartBackgroundTrack -36
equ trap_R_LoadWorldMap -37
equ trap_R_RegisterModel -38
equ trap_R_RegisterSkin -39
equ trap_R_RegisterShader -40
equ trap_R_ClearScene -41
equ trap_R_AddRefEntityToScene -42
equ trap_R_AddPolyToScene -43
equ trap_R_AddLightToScene -44
equ trap_R_RenderScene -45
equ trap_R_SetColor -46
equ trap_R_DrawStretchPic -47
equ trap_R_ModelBounds -48
equ trap_R_LerpTag -49
equ trap_GetGlconfig -50
equ trap_GetGameState -51
equ trap_GetCurrentSnapshotNumber -52
equ trap_GetSnapshot -53
equ trap_GetServerCommand -54
equ trap_GetCurrentCmdNumber -55
equ trap_GetUserCmd -56
equ trap_SetUserCmdValue -57
equ trap_R_RegisterShaderNoMip -58
equ trap_MemoryRemaining -59
equ trap_R_RegisterFont -60
equ trap_Key_IsDown -61
equ trap_Key_GetCatcher -62
equ trap_Key_SetCatcher -63
equ trap_Key_GetKey -64
equ trap_PC_AddGlobalDefine -65
equ trap_PC_LoadSource -66
equ trap_PC_FreeSource -67
equ trap_PC_ReadToken -68
equ trap_PC_SourceFileAndLine -69
equ trap_S_StopBackgroundTrack -70
equ trap_RealTime -71
equ trap_SnapVector -72
equ trap_RemoveCommand -73
equ trap_R_LightForPoint -74
equ trap_CIN_PlayCinematic -75
equ trap_CIN_StopCinematic -76
equ trap_CIN_RunCinematic -77
equ trap_CIN_DrawCinematic -78
equ trap_CIN_SetExtents -79
equ trap_R_RemapShader -80
equ trap_S_AddRealLoopingSound -81
equ trap_S_StopLoopingSound -82
equ trap_CM_TempCapsuleModel -83
equ trap_CM_CapsuleTrace -84
equ trap_CM_TransformedCapsuleTrace -85
equ trap_R_AddAdditiveLightToScene -86
equ trap_GetEntityToken -87
equ trap_R_AddPolysToScene -88
equ trap_R_inPVS -89
equ trap_FS_Seek -90
equ memset -101
equ memcpy -102
equ strncpy -103
equ sin -104
equ cos -105
equ atan2 -106
equ sqrt -107
equ floor -108
equ ceil -109
equ testPrintInt -110
equ testPrintFloat -111
equ acos -112

View File

@@ -0,0 +1,421 @@
// Copyright (C) 1999-2000 Id Software, Inc.
//
// cg_syscalls.c -- this file is only included when building a dll
// cg_syscalls.asm is included instead when building a qvm
#include "cg_local.h"
static int (QDECL *syscall)( int arg, ... ) = (int (QDECL *)( int, ...))-1;
void dllEntry( int (QDECL *syscallptr)( int arg,... ) ) {
syscall = syscallptr;
}
int PASSFLOAT( float x ) {
float floatTemp;
floatTemp = x;
return *(int *)&floatTemp;
}
void trap_Print( const char *fmt ) {
syscall( CG_PRINT, fmt );
}
void trap_Error( const char *fmt ) {
syscall( CG_ERROR, fmt );
}
int trap_Milliseconds( void ) {
return syscall( CG_MILLISECONDS );
}
void trap_Cvar_Register( vmCvar_t *vmCvar, const char *varName, const char *defaultValue, int flags ) {
syscall( CG_CVAR_REGISTER, vmCvar, varName, defaultValue, flags );
}
void trap_Cvar_Update( vmCvar_t *vmCvar ) {
syscall( CG_CVAR_UPDATE, vmCvar );
}
void trap_Cvar_Set( const char *var_name, const char *value ) {
syscall( CG_CVAR_SET, var_name, value );
}
void trap_Cvar_VariableStringBuffer( const char *var_name, char *buffer, int bufsize ) {
syscall( CG_CVAR_VARIABLESTRINGBUFFER, var_name, buffer, bufsize );
}
int trap_Argc( void ) {
return syscall( CG_ARGC );
}
void trap_Argv( int n, char *buffer, int bufferLength ) {
syscall( CG_ARGV, n, buffer, bufferLength );
}
void trap_Args( char *buffer, int bufferLength ) {
syscall( CG_ARGS, buffer, bufferLength );
}
int trap_FS_FOpenFile( const char *qpath, fileHandle_t *f, fsMode_t mode ) {
return syscall( CG_FS_FOPENFILE, qpath, f, mode );
}
void trap_FS_Read( void *buffer, int len, fileHandle_t f ) {
syscall( CG_FS_READ, buffer, len, f );
}
void trap_FS_Write( const void *buffer, int len, fileHandle_t f ) {
syscall( CG_FS_WRITE, buffer, len, f );
}
void trap_FS_FCloseFile( fileHandle_t f ) {
syscall( CG_FS_FCLOSEFILE, f );
}
int trap_FS_Seek( fileHandle_t f, long offset, int origin ) {
return syscall( CG_FS_SEEK, f, offset, origin );
}
void trap_SendConsoleCommand( const char *text ) {
syscall( CG_SENDCONSOLECOMMAND, text );
}
void trap_AddCommand( const char *cmdName ) {
syscall( CG_ADDCOMMAND, cmdName );
}
void trap_RemoveCommand( const char *cmdName ) {
syscall( CG_REMOVECOMMAND, cmdName );
}
void trap_SendClientCommand( const char *s ) {
syscall( CG_SENDCLIENTCOMMAND, s );
}
void trap_UpdateScreen( void ) {
syscall( CG_UPDATESCREEN );
}
void trap_CM_LoadMap( const char *mapname ) {
syscall( CG_CM_LOADMAP, mapname );
}
int trap_CM_NumInlineModels( void ) {
return syscall( CG_CM_NUMINLINEMODELS );
}
clipHandle_t trap_CM_InlineModel( int index ) {
return syscall( CG_CM_INLINEMODEL, index );
}
clipHandle_t trap_CM_TempBoxModel( const vec3_t mins, const vec3_t maxs ) {
return syscall( CG_CM_TEMPBOXMODEL, mins, maxs );
}
clipHandle_t trap_CM_TempCapsuleModel( const vec3_t mins, const vec3_t maxs ) {
return syscall( CG_CM_TEMPCAPSULEMODEL, mins, maxs );
}
int trap_CM_PointContents( const vec3_t p, clipHandle_t model ) {
return syscall( CG_CM_POINTCONTENTS, p, model );
}
int trap_CM_TransformedPointContents( const vec3_t p, clipHandle_t model, const vec3_t origin, const vec3_t angles ) {
return syscall( CG_CM_TRANSFORMEDPOINTCONTENTS, p, model, origin, angles );
}
void trap_CM_BoxTrace( trace_t *results, const vec3_t start, const vec3_t end,
const vec3_t mins, const vec3_t maxs,
clipHandle_t model, int brushmask ) {
syscall( CG_CM_BOXTRACE, results, start, end, mins, maxs, model, brushmask );
}
void trap_CM_CapsuleTrace( trace_t *results, const vec3_t start, const vec3_t end,
const vec3_t mins, const vec3_t maxs,
clipHandle_t model, int brushmask ) {
syscall( CG_CM_CAPSULETRACE, results, start, end, mins, maxs, model, brushmask );
}
void trap_CM_TransformedBoxTrace( trace_t *results, const vec3_t start, const vec3_t end,
const vec3_t mins, const vec3_t maxs,
clipHandle_t model, int brushmask,
const vec3_t origin, const vec3_t angles ) {
syscall( CG_CM_TRANSFORMEDBOXTRACE, results, start, end, mins, maxs, model, brushmask, origin, angles );
}
void trap_CM_TransformedCapsuleTrace( trace_t *results, const vec3_t start, const vec3_t end,
const vec3_t mins, const vec3_t maxs,
clipHandle_t model, int brushmask,
const vec3_t origin, const vec3_t angles ) {
syscall( CG_CM_TRANSFORMEDCAPSULETRACE, results, start, end, mins, maxs, model, brushmask, origin, angles );
}
int trap_CM_MarkFragments( int numPoints, const vec3_t *points,
const vec3_t projection,
int maxPoints, vec3_t pointBuffer,
int maxFragments, markFragment_t *fragmentBuffer ) {
return syscall( CG_CM_MARKFRAGMENTS, numPoints, points, projection, maxPoints, pointBuffer, maxFragments, fragmentBuffer );
}
void trap_S_StartSound( vec3_t origin, int entityNum, int entchannel, sfxHandle_t sfx ) {
syscall( CG_S_STARTSOUND, origin, entityNum, entchannel, sfx );
}
void trap_S_StartLocalSound( sfxHandle_t sfx, int channelNum ) {
syscall( CG_S_STARTLOCALSOUND, sfx, channelNum );
}
void trap_S_ClearLoopingSounds( qboolean killall ) {
syscall( CG_S_CLEARLOOPINGSOUNDS, killall );
}
void trap_S_AddLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx ) {
syscall( CG_S_ADDLOOPINGSOUND, entityNum, origin, velocity, sfx );
}
void trap_S_AddRealLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx ) {
syscall( CG_S_ADDREALLOOPINGSOUND, entityNum, origin, velocity, sfx );
}
void trap_S_StopLoopingSound( int entityNum ) {
syscall( CG_S_STOPLOOPINGSOUND, entityNum );
}
void trap_S_UpdateEntityPosition( int entityNum, const vec3_t origin ) {
syscall( CG_S_UPDATEENTITYPOSITION, entityNum, origin );
}
void trap_S_Respatialize( int entityNum, const vec3_t origin, vec3_t axis[3], int inwater ) {
syscall( CG_S_RESPATIALIZE, entityNum, origin, axis, inwater );
}
sfxHandle_t trap_S_RegisterSound( const char *sample, qboolean compressed ) {
return syscall( CG_S_REGISTERSOUND, sample, compressed );
}
void trap_S_StartBackgroundTrack( const char *intro, const char *loop ) {
syscall( CG_S_STARTBACKGROUNDTRACK, intro, loop );
}
void trap_R_LoadWorldMap( const char *mapname ) {
syscall( CG_R_LOADWORLDMAP, mapname );
}
qhandle_t trap_R_RegisterModel( const char *name ) {
return syscall( CG_R_REGISTERMODEL, name );
}
qhandle_t trap_R_RegisterSkin( const char *name ) {
return syscall( CG_R_REGISTERSKIN, name );
}
qhandle_t trap_R_RegisterShader( const char *name ) {
return syscall( CG_R_REGISTERSHADER, name );
}
qhandle_t trap_R_RegisterShaderNoMip( const char *name ) {
return syscall( CG_R_REGISTERSHADERNOMIP, name );
}
void trap_R_RegisterFont(const char *fontName, int pointSize, fontInfo_t *font) {
syscall(CG_R_REGISTERFONT, fontName, pointSize, font );
}
void trap_R_ClearScene( void ) {
syscall( CG_R_CLEARSCENE );
}
void trap_R_AddRefEntityToScene( const refEntity_t *re ) {
syscall( CG_R_ADDREFENTITYTOSCENE, re );
}
void trap_R_AddPolyToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts ) {
syscall( CG_R_ADDPOLYTOSCENE, hShader, numVerts, verts );
}
void trap_R_AddPolysToScene( qhandle_t hShader , int numVerts, const polyVert_t *verts, int num ) {
syscall( CG_R_ADDPOLYSTOSCENE, hShader, numVerts, verts, num );
}
int trap_R_LightForPoint( vec3_t point, vec3_t ambientLight, vec3_t directedLight, vec3_t lightDir ) {
return syscall( CG_R_LIGHTFORPOINT, point, ambientLight, directedLight, lightDir );
}
void trap_R_AddLightToScene( const vec3_t org, float intensity, float r, float g, float b ) {
syscall( CG_R_ADDLIGHTTOSCENE, org, PASSFLOAT(intensity), PASSFLOAT(r), PASSFLOAT(g), PASSFLOAT(b) );
}
void trap_R_AddAdditiveLightToScene( const vec3_t org, float intensity, float r, float g, float b ) {
syscall( CG_R_ADDADDITIVELIGHTTOSCENE, org, PASSFLOAT(intensity), PASSFLOAT(r), PASSFLOAT(g), PASSFLOAT(b) );
}
void trap_R_RenderScene( const refdef_t *fd ) {
syscall( CG_R_RENDERSCENE, fd );
}
void trap_R_SetColor( const float *rgba ) {
syscall( CG_R_SETCOLOR, rgba );
}
void trap_R_DrawStretchPic( float x, float y, float w, float h,
float s1, float t1, float s2, float t2, qhandle_t hShader ) {
syscall( CG_R_DRAWSTRETCHPIC, PASSFLOAT(x), PASSFLOAT(y), PASSFLOAT(w), PASSFLOAT(h), PASSFLOAT(s1), PASSFLOAT(t1), PASSFLOAT(s2), PASSFLOAT(t2), hShader );
}
void trap_R_ModelBounds( clipHandle_t model, vec3_t mins, vec3_t maxs ) {
syscall( CG_R_MODELBOUNDS, model, mins, maxs );
}
int trap_R_LerpTag( orientation_t *tag, clipHandle_t mod, int startFrame, int endFrame,
float frac, const char *tagName ) {
return syscall( CG_R_LERPTAG, tag, mod, startFrame, endFrame, PASSFLOAT(frac), tagName );
}
void trap_R_RemapShader( const char *oldShader, const char *newShader, const char *timeOffset ) {
syscall( CG_R_REMAP_SHADER, oldShader, newShader, timeOffset );
}
void trap_GetGlconfig( glconfig_t *glconfig ) {
syscall( CG_GETGLCONFIG, glconfig );
}
void trap_GetGameState( gameState_t *gamestate ) {
syscall( CG_GETGAMESTATE, gamestate );
}
void trap_GetCurrentSnapshotNumber( int *snapshotNumber, int *serverTime ) {
syscall( CG_GETCURRENTSNAPSHOTNUMBER, snapshotNumber, serverTime );
}
qboolean trap_GetSnapshot( int snapshotNumber, snapshot_t *snapshot ) {
return syscall( CG_GETSNAPSHOT, snapshotNumber, snapshot );
}
qboolean trap_GetServerCommand( int serverCommandNumber ) {
return syscall( CG_GETSERVERCOMMAND, serverCommandNumber );
}
int trap_GetCurrentCmdNumber( void ) {
return syscall( CG_GETCURRENTCMDNUMBER );
}
qboolean trap_GetUserCmd( int cmdNumber, usercmd_t *ucmd ) {
return syscall( CG_GETUSERCMD, cmdNumber, ucmd );
}
void trap_SetUserCmdValue( int stateValue, float sensitivityScale ) {
syscall( CG_SETUSERCMDVALUE, stateValue, PASSFLOAT(sensitivityScale) );
}
void testPrintInt( char *string, int i ) {
syscall( CG_TESTPRINTINT, string, i );
}
void testPrintFloat( char *string, float f ) {
syscall( CG_TESTPRINTFLOAT, string, PASSFLOAT(f) );
}
int trap_MemoryRemaining( void ) {
return syscall( CG_MEMORY_REMAINING );
}
qboolean trap_Key_IsDown( int keynum ) {
return syscall( CG_KEY_ISDOWN, keynum );
}
int trap_Key_GetCatcher( void ) {
return syscall( CG_KEY_GETCATCHER );
}
void trap_Key_SetCatcher( int catcher ) {
syscall( CG_KEY_SETCATCHER, catcher );
}
int trap_Key_GetKey( const char *binding ) {
return syscall( CG_KEY_GETKEY, binding );
}
int trap_PC_AddGlobalDefine( char *define ) {
return syscall( CG_PC_ADD_GLOBAL_DEFINE, define );
}
int trap_PC_LoadSource( const char *filename ) {
return syscall( CG_PC_LOAD_SOURCE, filename );
}
int trap_PC_FreeSource( int handle ) {
return syscall( CG_PC_FREE_SOURCE, handle );
}
int trap_PC_ReadToken( int handle, pc_token_t *pc_token ) {
return syscall( CG_PC_READ_TOKEN, handle, pc_token );
}
int trap_PC_SourceFileAndLine( int handle, char *filename, int *line ) {
return syscall( CG_PC_SOURCE_FILE_AND_LINE, handle, filename, line );
}
void trap_S_StopBackgroundTrack( void ) {
syscall( CG_S_STOPBACKGROUNDTRACK );
}
int trap_RealTime(qtime_t *qtime) {
return syscall( CG_REAL_TIME, qtime );
}
void trap_SnapVector( float *v ) {
syscall( CG_SNAPVECTOR, v );
}
// this returns a handle. arg0 is the name in the format "idlogo.roq", set arg1 to NULL, alteredstates to qfalse (do not alter gamestate)
int trap_CIN_PlayCinematic( const char *arg0, int xpos, int ypos, int width, int height, int bits) {
return syscall(CG_CIN_PLAYCINEMATIC, arg0, xpos, ypos, width, height, bits);
}
// stops playing the cinematic and ends it. should always return FMV_EOF
// cinematics must be stopped in reverse order of when they are started
e_status trap_CIN_StopCinematic(int handle) {
return syscall(CG_CIN_STOPCINEMATIC, handle);
}
// will run a frame of the cinematic but will not draw it. Will return FMV_EOF if the end of the cinematic has been reached.
e_status trap_CIN_RunCinematic (int handle) {
return syscall(CG_CIN_RUNCINEMATIC, handle);
}
// draws the current frame
void trap_CIN_DrawCinematic (int handle) {
syscall(CG_CIN_DRAWCINEMATIC, handle);
}
// allows you to resize the animation dynamically
void trap_CIN_SetExtents (int handle, int x, int y, int w, int h) {
syscall(CG_CIN_SETEXTENTS, handle, x, y, w, h);
}
/*
qboolean trap_loadCamera( const char *name ) {
return syscall( CG_LOADCAMERA, name );
}
void trap_startCamera(int time) {
syscall(CG_STARTCAMERA, time);
}
qboolean trap_getCameraInfo( int time, vec3_t *origin, vec3_t *angles) {
return syscall( CG_GETCAMERAINFO, time, origin, angles );
}
*/
qboolean trap_GetEntityToken( char *buffer, int bufferSize ) {
return syscall( CG_GET_ENTITY_TOKEN, buffer, bufferSize );
}
qboolean trap_R_inPVS( const vec3_t p1, const vec3_t p2 ) {
return syscall( CG_R_INPVS, p1, p2 );
}

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More