as released 2007-09-27
This commit is contained in:
commit
dd3484bb44
863 changed files with 446846 additions and 0 deletions
107
Readme Painkeep Arena Source Info.txt
Normal file
107
Readme Painkeep Arena Source Info.txt
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
PainKeep Arena 3.0n Source Release
|
||||||
|
Release Date: September 27,2007
|
||||||
|
|
||||||
|
Materials in this release are based on the
|
||||||
|
PainKeep Arena 3.0n Full Release - March 19, 2004
|
||||||
|
Copyright (c)2007-2008 Team Evolve.
|
||||||
|
All rights reserved.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Team Evolve:
|
||||||
|
Team Evolve Web Site - http://www.teamevolve.com
|
||||||
|
|
||||||
|
Community Information:
|
||||||
|
http://www.groundplan.com/gplan_forum
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Team Evolve welcomes you to the source files of PainKeep Arena! We release this information in the hopes that it will contribute to the gaming community with a jumpstart into the next generation of online games. Should you use any information within the source files toward your game then please give credit to Team Evolve in the form of a textual reference in the public readme file.
|
||||||
|
|
||||||
|
Team Evolve releases the source in an AS-IS form and will not support nor answer any questions into its workings. Team Evolve will not support nor be responsible in any way to extensions made to Painkeep Arena from third party modifications to source or content.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PainKeep Arena is based on the 1.32 version of Quake III Arena. IMPORTANT: In order to use any modification to the PainKeep Arena source code will require: 1) Quake III Arena 1.32 installed and 2) the Full Install of PainKeep Arena 3.0n.
|
||||||
|
|
||||||
|
This help document is based on Windows XP SP2. If you use another OS then you will need to adjust search PATH information accordingly.
|
||||||
|
|
||||||
|
The PainKeep Arena source code is based on the GAME Source released by id Software. PainKeep Arena source must be installed into the same place as the id software GAME Source, C:\QUAKE3, in order for the lcc and q3cpp compilation paths to be correct.
|
||||||
|
|
||||||
|
You must place the compilation executables in your system’s path. The lcc executable is located in c:\quake3\bin_nt directory. Add to your systems path using the Control Panel’s System tool, select the Advanced Tab and then click on the “Environment Variables” Button. Under the “Systems Variables”, select “Path” and Click the “Edit” button to add to the end of the existing path line - “;c:\quake3\bin_nt” - {without the quotes, of course}. Click OK a few time to save the new Path setting. You may need to reboot Windows for new Path setting to be recognized by the system.
|
||||||
|
|
||||||
|
The PainKeep Arena source code contains the procedures and logic that govern the User Interface, Game Logic, Client Presentation. Each section is primarily controlled by a specific directory within the source code…
|
||||||
|
User Interface - c:\quake3\source\code\ui\
|
||||||
|
Game Logic - c:\quake3\source\code\game\
|
||||||
|
Client Presentation - c:\quake3\source\code\cgame\
|
||||||
|
|
||||||
|
Please note that some modifications to the User Interface will require changes in Client Presentation area.
|
||||||
|
|
||||||
|
PainKeep Arena uses QVM files to hold the compiled game code. Each section (User Interface, Game Logic, Client Presentation) has an associated and separate QVM file. To create, (or compile), a new QVM, each section have a .BAT file that can be used to generate a new QVM.
|
||||||
|
|
||||||
|
To compile a new…
|
||||||
|
User Interface:
|
||||||
|
execute c:\quake3\source\code\ui\ui.bat
|
||||||
|
Game Logic:
|
||||||
|
execute c:\quake3\source\code\game\game.bat
|
||||||
|
Client Presentation:
|
||||||
|
execute c:\quake3\source\code\cgame\cgame.bat
|
||||||
|
|
||||||
|
The GAME and CLIENT QVM files will be generated in directory:
|
||||||
|
c:\quake3\baseq3\vm\
|
||||||
|
gagame.qvm
|
||||||
|
cgame.qvm
|
||||||
|
|
||||||
|
The USER INTERFACE QVM file will be generated in directory:
|
||||||
|
c:\quake3\missionpack\vm\
|
||||||
|
ui.qvm
|
||||||
|
|
||||||
|
After you make your QVM files you will need to make a .PK3 file that holds your newly generated QVMs and any other Modification materials. Please note that .PK3 files can be managed by ZIP tools.
|
||||||
|
|
||||||
|
Create a .PK3 file with the new QVM files in a \vm subdirectory.
|
||||||
|
|
||||||
|
Place the newly generated .PK3 file into your mod (or \PKARENA) directory under the Quake III Arena Execution directory. Reminder, Quake III Arena will use the .PK3 File’s material that comes last alphabetically. For example if you make a simple MOD for PainKeep Arena, place your materials in…
|
||||||
|
..\Quake III Arena\pkarena\zpktext.pk3
|
||||||
|
(in this example zpktest.pk3 will be loaded last and your updates will act as the effective .QVM files)
|
||||||
|
|
||||||
|
Good Luck!
|
||||||
|
Yours, Team Evolve and Ergodic
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
THE LEGAL CRAP
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
|
||||||
|
A. Copyright Notice
|
||||||
|
This production in its entirety and all derivative works are copyright (c)2007-2008 Team Evolve. All rights reserved.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Ownership of all new components, including, but not limited to; source code, compiled code, graphics, textures, sounds, models and maps, remain with Team Evolve and the individual authors respectively. Some components are the exclusive property of their authors and owners and are used with kind permission.
|
||||||
|
All original components are copyright (c)2001, iD Software.
|
||||||
|
Quake III Arena and the stylized 'Q' are trademarks of iD Software.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
All other trademarks are property of their respective owners and are hereby acknowledged.
|
||||||
|
|
||||||
|
|
||||||
|
B. Distribution and Usage Permissions
|
||||||
|
Team Evolve grants to the final end user an exclusive right to use this production for the purposes of personal entertainment only. Team Evolve grants to the final end user an exclusive right to freely distribute this production in its undisturbed and unaltered entirety provided no exchange, monetary or otherwise, is requested. All other media entities are expressly excluded from this right prior to acknowledge and consent from Team Evolve or one of Team Evolve's duly appointed representatives, agents or subsidiaries.
|
||||||
|
|
||||||
|
By using this product you agree to exempt, without reservation, the authors and
|
||||||
|
owners of this production or components thereof from any responsibility for liability, damage caused, or loss, directly or indirectly, by this software, including but not limited to, any interruptions of service, loss of business, or any other consequential damages resulting from the use of or operation of this product or components thereof.
|
||||||
|
|
||||||
|
No warranties are made, expressed or implied, regarding the usage, functionality, or implied operability of this product. All elements are available solely on an
|
||||||
|
"as-is" basis. Usage is subject to the user's own risk.
|
||||||
|
|
||||||
|
New or altered source code components are included with kind permission of the respective authors and owners and are provided with the only intention of facilitating in the integration of this production, or components thereof, with other such freely available and non-commercial productions. Authors are expressly forbidden to use these components, or any other component of this production, as a basis for other commercially available works or demonstration systems without prior acknowledge and consent from Team Evolve or one of Team Evolve's duly appointed representatives, agents or subsidiaries.
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PainKeep Arena is RATED M: Mature Audiences Only
|
||||||
|
|
62
quake3/Readme PainKeep Arena 3_1.txt
Normal file
62
quake3/Readme PainKeep Arena 3_1.txt
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
PainKeep Arena 3.0 Full Release is RATED M: Mature Audiences Only
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
PainKeep Arena 3.0 Full Release - March 19, 2004
|
||||||
|
Copyright (c)2004-2005 Team Evolve.
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
|
||||||
|
Team Evolve:
|
||||||
|
Team Evolve Web Site - http://www.team-evolve.com
|
||||||
|
|
||||||
|
Find help & Post Bug Comments at:
|
||||||
|
http://www.groundplan.com/gplan_forum
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
For information regarding PainKeep Arena please view the PKA Manual by opening the
|
||||||
|
file index.html in the /pkamanual directory. A typical installation will locate the
|
||||||
|
help manual in the following location:
|
||||||
|
|
||||||
|
/quake III arena/pkarena/pkamanual/index.html
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
VIII. THE LEGAL CRAP
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
|
||||||
|
A. Copyright Notice
|
||||||
|
This production in its entirety and all derivative works are copyright (c)2004-2005 Team Evolve. All rights reserved.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Ownership of all new components, including, but not limited to; source code, compiled code, graphics, textures, sounds, models and maps, remain with Team Evolve and the individual authors respectively. Some components are the exclusive property of their authors and owners and are used with kind permission.
|
||||||
|
All original components are copyright (c)2001, iD Software.
|
||||||
|
Quake III Arena and the stylized 'Q' are trademarks of iD Software.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
All other trademarks are property of their respective owners and are hereby acknowledged.
|
||||||
|
|
||||||
|
|
||||||
|
B. Distribution and Usage Permissions
|
||||||
|
Team Evolve grants to the final end user an exclusive right to use this production for the purposes of personal entertainment only. Team Evolve grants to the final end user an exclusive right to freely distribute this production in its undisturbed and unaltered entirety provided no exchange, monetary or otherwise, is requested. All other media entities are expressly excluded from this right prior to acknowledge and consent from Team Evolve or one of Team Evolve's duly appointed representatives, agents or subsidiaries.
|
||||||
|
|
||||||
|
By using this product you agree to exempt, without reservation, the authors and
|
||||||
|
owners of this production or components thereof from any responsibility for liability, damage caused, or loss, directly or indirectly, by this software, including but not limited to, any interruptions of service, loss of business, or any other consequential damages resulting from the use of or operation of this product or components thereof.
|
||||||
|
|
||||||
|
No warranties are made, expressed or implied, regarding the usage, functionality, or implied operability of this product. All elements are available solely on an
|
||||||
|
"as-is" basis. Usage is subject to the user's own risk.
|
||||||
|
|
||||||
|
New or altered source code components are included with kind permission of the respective authors and owners and are provided with the only intention of facilitating in the integration of this production, or components thereof, with other such freely available and non-commercial productions. Authors are expressly forbidden to use these components, or any other component of this production, as a basis for other commercially available works or demonstration systems without prior acknowledge and consent from Team Evolve or one of Team Evolve's duly appointed representatives, agents or subsidiaries.
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PainKeep Arena is RATED M: Mature Audiences Only
|
||||||
|
|
||||||
|
Now Bring on the killing!
|
107
quake3/Readme Painkeep Arena Source Info.txt
Normal file
107
quake3/Readme Painkeep Arena Source Info.txt
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
PainKeep Arena 3.0n Source Release
|
||||||
|
Release Date: September 27,2007
|
||||||
|
|
||||||
|
Materials in this release are based on the
|
||||||
|
PainKeep Arena 3.0n Full Release - March 19, 2004
|
||||||
|
Copyright (c)2007-2008 Team Evolve.
|
||||||
|
All rights reserved.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Team Evolve:
|
||||||
|
Team Evolve Web Site - http://www.teamevolve.com
|
||||||
|
|
||||||
|
Community Information:
|
||||||
|
http://www.groundplan.com/gplan_forum
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Team Evolve welcomes you to the source files of PainKeep Arena! We release this information in the hopes that it will contribute to the gaming community with a jumpstart into the next generation of online games. Should you use any information within the source files toward your game then please give credit to Team Evolve in the form of a textual reference in the public readme file.
|
||||||
|
|
||||||
|
Team Evolve releases the source in an AS-IS form and will not support nor answer any questions into its workings. Team Evolve will not support nor be responsible in any way to extensions made to Painkeep Arena from third party modifications to source or content.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PainKeep Arena is based on the 1.32 version of Quake III Arena. IMPORTANT: In order to use any modification to the PainKeep Arena source code will require: 1) Quake III Arena 1.32 installed and 2) the Full Install of PainKeep Arena 3.0n.
|
||||||
|
|
||||||
|
This help document is based on Windows XP SP2. If you use another OS then you will need to adjust search PATH information accordingly.
|
||||||
|
|
||||||
|
The PainKeep Arena source code is based on the GAME Source released by id Software. PainKeep Arena source must be installed into the same place as the id software GAME Source, C:\QUAKE3, in order for the lcc and q3cpp compilation paths to be correct.
|
||||||
|
|
||||||
|
You must place the compilation executables in your system’s path. The lcc executable is located in c:\quake3\bin_nt directory. Add to your systems path using the Control Panel’s System tool, select the Advanced Tab and then click on the “Environment Variables” Button. Under the “Systems Variables”, select “Path” and Click the “Edit” button to add to the end of the existing path line - “;c:\quake3\bin_nt” - {without the quotes, of course}. Click OK a few time to save the new Path setting. You may need to reboot Windows for new Path setting to be recognized by the system.
|
||||||
|
|
||||||
|
The PainKeep Arena source code contains the procedures and logic that govern the User Interface, Game Logic, Client Presentation. Each section is primarily controlled by a specific directory within the source code…
|
||||||
|
User Interface - c:\quake3\source\code\ui\
|
||||||
|
Game Logic - c:\quake3\source\code\game\
|
||||||
|
Client Presentation - c:\quake3\source\code\cgame\
|
||||||
|
|
||||||
|
Please note that some modifications to the User Interface will require changes in Client Presentation area.
|
||||||
|
|
||||||
|
PainKeep Arena uses QVM files to hold the compiled game code. Each section (User Interface, Game Logic, Client Presentation) has an associated and separate QVM file. To create, (or compile), a new QVM, each section have a .BAT file that can be used to generate a new QVM.
|
||||||
|
|
||||||
|
To compile a new…
|
||||||
|
User Interface:
|
||||||
|
execute c:\quake3\source\code\ui\ui.bat
|
||||||
|
Game Logic:
|
||||||
|
execute c:\quake3\source\code\game\game.bat
|
||||||
|
Client Presentation:
|
||||||
|
execute c:\quake3\source\code\cgame\cgame.bat
|
||||||
|
|
||||||
|
The GAME and CLIENT QVM files will be generated in directory:
|
||||||
|
c:\quake3\baseq3\vm\
|
||||||
|
gagame.qvm
|
||||||
|
cgame.qvm
|
||||||
|
|
||||||
|
The USER INTERFACE QVM file will be generated in directory:
|
||||||
|
c:\quake3\missionpack\vm\
|
||||||
|
ui.qvm
|
||||||
|
|
||||||
|
After you make your QVM files you will need to make a .PK3 file that holds your newly generated QVMs and any other Modification materials. Please note that .PK3 files can be managed by ZIP tools.
|
||||||
|
|
||||||
|
Create a .PK3 file with the new QVM files in a \vm subdirectory.
|
||||||
|
|
||||||
|
Place the newly generated .PK3 file into your mod (or \PKARENA) directory under the Quake III Arena Execution directory. Reminder, Quake III Arena will use the .PK3 File’s material that comes last alphabetically. For example if you make a simple MOD for PainKeep Arena, place your materials in…
|
||||||
|
..\Quake III Arena\pkarena\zpktext.pk3
|
||||||
|
(in this example zpktest.pk3 will be loaded last and your updates will act as the effective .QVM files)
|
||||||
|
|
||||||
|
Good Luck!
|
||||||
|
Yours, Team Evolve and Ergodic
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
THE LEGAL CRAP
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
|
||||||
|
A. Copyright Notice
|
||||||
|
This production in its entirety and all derivative works are copyright (c)2007-2008 Team Evolve. All rights reserved.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Ownership of all new components, including, but not limited to; source code, compiled code, graphics, textures, sounds, models and maps, remain with Team Evolve and the individual authors respectively. Some components are the exclusive property of their authors and owners and are used with kind permission.
|
||||||
|
All original components are copyright (c)2001, iD Software.
|
||||||
|
Quake III Arena and the stylized 'Q' are trademarks of iD Software.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
All other trademarks are property of their respective owners and are hereby acknowledged.
|
||||||
|
|
||||||
|
|
||||||
|
B. Distribution and Usage Permissions
|
||||||
|
Team Evolve grants to the final end user an exclusive right to use this production for the purposes of personal entertainment only. Team Evolve grants to the final end user an exclusive right to freely distribute this production in its undisturbed and unaltered entirety provided no exchange, monetary or otherwise, is requested. All other media entities are expressly excluded from this right prior to acknowledge and consent from Team Evolve or one of Team Evolve's duly appointed representatives, agents or subsidiaries.
|
||||||
|
|
||||||
|
By using this product you agree to exempt, without reservation, the authors and
|
||||||
|
owners of this production or components thereof from any responsibility for liability, damage caused, or loss, directly or indirectly, by this software, including but not limited to, any interruptions of service, loss of business, or any other consequential damages resulting from the use of or operation of this product or components thereof.
|
||||||
|
|
||||||
|
No warranties are made, expressed or implied, regarding the usage, functionality, or implied operability of this product. All elements are available solely on an
|
||||||
|
"as-is" basis. Usage is subject to the user's own risk.
|
||||||
|
|
||||||
|
New or altered source code components are included with kind permission of the respective authors and owners and are provided with the only intention of facilitating in the integration of this production, or components thereof, with other such freely available and non-commercial productions. Authors are expressly forbidden to use these components, or any other component of this production, as a basis for other commercially available works or demonstration systems without prior acknowledge and consent from Team Evolve or one of Team Evolve's duly appointed representatives, agents or subsidiaries.
|
||||||
|
-------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
PainKeep Arena is RATED M: Mature Audiences Only
|
||||||
|
|
BIN
quake3/bin_nt/lcc.exe
Normal file
BIN
quake3/bin_nt/lcc.exe
Normal file
Binary file not shown.
BIN
quake3/bin_nt/q3asm.exe
Normal file
BIN
quake3/bin_nt/q3asm.exe
Normal file
Binary file not shown.
BIN
quake3/bin_nt/q3cpp.exe
Normal file
BIN
quake3/bin_nt/q3cpp.exe
Normal file
Binary file not shown.
BIN
quake3/bin_nt/q3rcc.exe
Normal file
BIN
quake3/bin_nt/q3rcc.exe
Normal file
Binary file not shown.
BIN
quake3/source/QIIIA Game Source License.doc
Normal file
BIN
quake3/source/QIIIA Game Source License.doc
Normal file
Binary file not shown.
BIN
quake3/source/code/Debug_TA/qagamex86.dll
Normal file
BIN
quake3/source/code/Debug_TA/qagamex86.dll
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/bg_lib.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/bg_lib.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/bg_lib.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/bg_lib.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/bg_misc.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/bg_misc.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/bg_misc.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/bg_misc.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/bg_pmove.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/bg_pmove.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/bg_pmove.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/bg_pmove.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/bg_slidemove.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/bg_slidemove.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/bg_slidemove.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/bg_slidemove.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_consolecmds.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_consolecmds.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_consolecmds.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_consolecmds.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_draw.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_draw.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_draw.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_draw.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_drawtools.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_drawtools.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_drawtools.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_drawtools.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_effects.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_effects.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_effects.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_effects.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_ents.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_ents.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_event.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_event.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_event.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_event.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_info.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_info.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_info.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_info.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_localents.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_localents.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_localents.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_localents.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_main.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_main.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_main.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_main.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_marks.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_marks.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_marks.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_marks.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_newDraw.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_newDraw.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_newDraw.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_newDraw.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_players.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_players.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_players.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_players.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_playerstate.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_playerstate.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_playerstate.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_playerstate.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_predict.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_predict.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_predict.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_predict.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_scoreboard.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_scoreboard.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_scoreboard.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_scoreboard.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_servercmds.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_servercmds.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_servercmds.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_servercmds.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_snapshot.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_snapshot.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_snapshot.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_snapshot.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_syscalls.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_syscalls.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_syscalls.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_syscalls.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_view.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_view.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_view.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_view.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_weapons.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_weapons.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cg_weapons.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cg_weapons.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/cgame.pch
Normal file
BIN
quake3/source/code/cgame/Debug_TA/cgame.pch
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/q_math.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/q_math.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/q_math.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/q_math.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/q_shared.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/q_shared.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/q_shared.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/q_shared.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/ui_shared.obj
Normal file
BIN
quake3/source/code/cgame/Debug_TA/ui_shared.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/ui_shared.sbr
Normal file
BIN
quake3/source/code/cgame/Debug_TA/ui_shared.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/cgame/Debug_TA/vc50.idb
Normal file
BIN
quake3/source/code/cgame/Debug_TA/vc50.idb
Normal file
Binary file not shown.
611
quake3/source/code/cgame/cg_consolecmds.c
Normal file
611
quake3/source/code/cgame/cg_consolecmds.c
Normal file
|
@ -0,0 +1,611 @@
|
||||||
|
// 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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//PKMOD - Ergodic 12/09/03 - add command dynamic hub voting
|
||||||
|
static void CG_HubAlternates_f (void ) {
|
||||||
|
trap_SendConsoleCommand( "hubalternates\n" );
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//PKMOD - Ergodic 02/23/04 - include HUD commands
|
||||||
|
//#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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//PKMOD - Ergodic 02/23/04 - include HUD commands: move ifdef here
|
||||||
|
#ifdef MISSIONPACK
|
||||||
|
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
//PKMOD - Ergodic 02/23/04 - enable HUD functions
|
||||||
|
//#ifdef MISSIONPACK
|
||||||
|
static void CG_NextTeamMember_f( void ) {
|
||||||
|
CG_SelectNextPlayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CG_PrevTeamMember_f( void ) {
|
||||||
|
CG_SelectPrevPlayer();
|
||||||
|
}
|
||||||
|
|
||||||
|
//PKMOD - Ergodic 02/23/04 - enable HUD functions: move the ifdef statment here
|
||||||
|
#ifdef MISSIONPACK
|
||||||
|
|
||||||
|
|
||||||
|
// 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 },
|
||||||
|
//PKMOD - Ergodic 07/02/00 PKA weapon commands
|
||||||
|
{ "gravitywell", CG_Weapon_GravityWell },
|
||||||
|
{ "autosentry", CG_Weapon_Sentry },
|
||||||
|
{ "beartrap", CG_Weapon_BearTrap },
|
||||||
|
{ "beans", CG_Weapon_Beans },
|
||||||
|
//PKMOD - Ergodic 07/12/00 PKA weapon commands
|
||||||
|
{ "gauntlet", CG_Weapon_Gauntlet },
|
||||||
|
{ "machinegun", CG_Weapon_MachineGun },
|
||||||
|
//PKMOD - Ergodic 03/22/01 - change shotgun name to boomstick
|
||||||
|
{ "boomstick", CG_Weapon_ShotGun },
|
||||||
|
{ "airfist", CG_Weapon_AirFist },
|
||||||
|
{ "nailgun", CG_Weapon_NailGun },
|
||||||
|
{ "grenades", CG_Weapon_GrenadeLauncher },
|
||||||
|
{ "rockets", CG_Weapon_RocketLauncher },
|
||||||
|
{ "lightning", CG_Weapon_LightningGun },
|
||||||
|
//PKMOD - Ergodic 07/12/01 - change railgun name to magnum
|
||||||
|
{ "magnum", CG_Weapon_RailGun },
|
||||||
|
{ "dragon", CG_Weapon_Harpoon },
|
||||||
|
//PKMOD - Ergodic 03/01/01 - dragon deploy pka weapon
|
||||||
|
//PKMOD - Ergodic 03/27/01 - remove dragon deploy for beta 2 launch (sniff)
|
||||||
|
//PKMOD - Ergodic 05/08/01 - re-enable dragon deploy
|
||||||
|
{ "dragondeploy", CG_Weapon_DragonDeploy },
|
||||||
|
//PKMOD - Ergodic 04/04/01 - add last weapon command
|
||||||
|
{ "weaplast", CG_LastWeapon_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 },
|
||||||
|
//PKMOD - Ergodic 02/23/04 - include HUD commands
|
||||||
|
{ "loadhud", CG_LoadHud_f },
|
||||||
|
{ "nextTeamMember", CG_NextTeamMember_f },
|
||||||
|
{ "prevTeamMember", CG_PrevTeamMember_f },
|
||||||
|
{ "scoresDown", CG_scrollScoresDown_f },
|
||||||
|
{ "scoresUp", CG_scrollScoresUp_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 },
|
||||||
|
//PKMOD - Ergodic 12/09/03 - Add dynamic hub vote command
|
||||||
|
{ "cghubalternates", CG_HubAlternates_f }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
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
|
||||||
|
//PKMOD - Ergodic 03/04/01 - add dragondeploy command
|
||||||
|
//PKMOD - Ergodic 03/27/01 - remove dragon deploy for beta 2 launch (sniff)
|
||||||
|
//PKMOD - Ergodic 05/08/01 - re-enable dragon deploy
|
||||||
|
trap_AddCommand ("gdeploy");
|
||||||
|
//PKMOD - Ergodic 12/10/03 - add command for dynamic hub messaging
|
||||||
|
// trap_AddCommand ("cghubalternates");
|
||||||
|
}
|
2872
quake3/source/code/cgame/cg_draw.c
Normal file
2872
quake3/source/code/cgame/cg_draw.c
Normal file
File diff suppressed because it is too large
Load diff
944
quake3/source/code/cgame/cg_drawtools.c
Normal file
944
quake3/source/code/cgame/cg_drawtools.c
Normal file
|
@ -0,0 +1,944 @@
|
||||||
|
// 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
|
||||||
|
/* PKMOD - Ergodic 02/26/01 - original font locations
|
||||||
|
{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
|
||||||
|
*/
|
||||||
|
{35, 134, 6}, // ! (ck)
|
||||||
|
{193, 92, 10}, // " (ck)
|
||||||
|
{47, 135, 21}, // # (ck)
|
||||||
|
{27, 221, 10}, // $ (ck)
|
||||||
|
{90, 134, 29}, // % (ck)
|
||||||
|
{144, 135, 19}, // & (ck)
|
||||||
|
{80, 134, 4}, // ' (ck)
|
||||||
|
{195, 134, 8}, // ( (ck)
|
||||||
|
{182, 134, 8}, // ) (ck)
|
||||||
|
{167, 129, 11}, // * (ck)
|
||||||
|
{48, 177, 20}, // + (ck)
|
||||||
|
{156, 181, 6}, // , (ck)
|
||||||
|
{226, 93, 6}, // - (ck)
|
||||||
|
{165, 176, 6}, // . (ck) //06/11/01 was {165, 177, 6}
|
||||||
|
{117, 176, 11}, // / (ck)
|
||||||
|
{10, 92, 19}, // 0
|
||||||
|
{34, 92, 4}, // 1
|
||||||
|
{43, 92, 14}, // 2
|
||||||
|
{61, 92, 13}, // 3
|
||||||
|
{80, 92, 16}, // 4
|
||||||
|
{97, 92, 14}, // 5 (bump up 1 unit)
|
||||||
|
{113, 92, 14}, // 6
|
||||||
|
{132, 92, 12}, // 7
|
||||||
|
{148, 92, 14}, // 8
|
||||||
|
{168, 92, 14}, // 9 (bump up 1 unit)
|
||||||
|
{147, 181, 6}, // : (ck)
|
||||||
|
{138, 181, 6}, // ; (ck)
|
||||||
|
{117, 219, 18}, // < (ck)
|
||||||
|
{209, 134, 19}, // = (ck)
|
||||||
|
{140, 219, 18}, // > (ck)
|
||||||
|
{173, 177, 12}, // ? (ck)
|
||||||
|
{48, 224, 27}, // @ (ck)
|
||||||
|
{9, 8, 18}, // A
|
||||||
|
{34, 8, 12}, // B
|
||||||
|
{52, 8, 18}, // C
|
||||||
|
{75, 8, 16}, // D
|
||||||
|
{94, 8, 11}, // E
|
||||||
|
{108, 8, 11}, // F
|
||||||
|
{122, 8, 17}, // G
|
||||||
|
{143, 8, 13}, // H
|
||||||
|
{161, 8, 5}, // I
|
||||||
|
{169, 8, 13}, // J
|
||||||
|
{187, 8, 14}, // K
|
||||||
|
{206, 8, 12}, // L
|
||||||
|
{221, 8, 24}, // M
|
||||||
|
{11, 50, 15}, // N
|
||||||
|
{29, 50, 21}, // O
|
||||||
|
{57, 50, 13}, // P
|
||||||
|
{75, 50, 22}, // Q
|
||||||
|
{101, 50, 12}, // R (bump up 1 unit)
|
||||||
|
{119, 50, 13}, // S
|
||||||
|
{133, 50, 16}, // T
|
||||||
|
{151, 50, 14}, // U
|
||||||
|
{171, 50, 16}, // V
|
||||||
|
{190, 176, 21}, // W
|
||||||
|
{192, 50, 13}, // X
|
||||||
|
{209, 50, 17}, // Y
|
||||||
|
{229, 50, 11}, // Z
|
||||||
|
{82, 177, 7}, // [ (ck)
|
||||||
|
{98, 176, 10}, // '\' (ck)
|
||||||
|
{71, 177, 7}, // ] (ck)
|
||||||
|
{124, 134, 15}, // ^ (ck)
|
||||||
|
{27, 181, 19}, // _ (ck)
|
||||||
|
{80, 134, 4}, // ` (ck)
|
||||||
|
|
||||||
|
{9, 8, 18}, // A
|
||||||
|
{34, 8, 12}, // B
|
||||||
|
{52, 8, 18}, // C
|
||||||
|
{75, 8, 16}, // D
|
||||||
|
{94, 8, 11}, // E
|
||||||
|
{108, 8, 11}, // F
|
||||||
|
{122, 8, 17}, // G
|
||||||
|
{143, 8, 13}, // H
|
||||||
|
{161, 8, 5}, // I
|
||||||
|
{169, 8, 13}, // J
|
||||||
|
{187, 8, 14}, // K
|
||||||
|
{206, 8, 12}, // L
|
||||||
|
{221, 8, 24}, // M
|
||||||
|
{11, 50, 15}, // N
|
||||||
|
{29, 50, 21}, // O
|
||||||
|
{57, 50, 13}, // P
|
||||||
|
{75, 50, 22}, // Q
|
||||||
|
{101, 50, 12}, // R (bump up 1 unit)
|
||||||
|
{119, 50, 13}, // S
|
||||||
|
{133, 50, 16}, // T
|
||||||
|
{151, 50, 14}, // U
|
||||||
|
{171, 50, 16}, // V
|
||||||
|
{190, 176, 21}, // W
|
||||||
|
{192, 50, 13}, // X
|
||||||
|
{209, 50, 17}, // Y
|
||||||
|
{229, 50, 11}, // Z
|
||||||
|
{84, 224, 8}, // { (ck)
|
||||||
|
{17, 221, 2}, // | (ck)
|
||||||
|
{102, 224, 8}, // } (ck)
|
||||||
|
{12, 134, 19}, // ~ (ck)
|
||||||
|
{0, 0, -1} // DEL
|
||||||
|
};
|
||||||
|
|
||||||
|
static int propMapB[26][3] = {
|
||||||
|
/* PKMOD - Ergodic 02/26/01 - original font locations
|
||||||
|
{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},
|
||||||
|
*/
|
||||||
|
{25, 25, 31}, //A
|
||||||
|
{64, 25, 22}, //B
|
||||||
|
{93, 25, 30}, //C
|
||||||
|
{131, 25, 27}, //D
|
||||||
|
{164, 25, 18}, //E
|
||||||
|
{187, 25, 19}, //F
|
||||||
|
|
||||||
|
{27, 79, 28}, //G
|
||||||
|
{60, 79, 23}, //H
|
||||||
|
{91, 79, 8}, //I
|
||||||
|
{102, 79, 22}, //J
|
||||||
|
{133, 79, 23}, //K
|
||||||
|
{164, 79, 20}, //L
|
||||||
|
{197, 79, 40}, //M
|
||||||
|
|
||||||
|
{28, 133, 26}, //N
|
||||||
|
{59, 133, 36}, //O
|
||||||
|
{105, 133, 22}, //P
|
||||||
|
{134, 133, 37}, //Q
|
||||||
|
{177, 133, 21}, //R
|
||||||
|
{206, 133, 22}, //S
|
||||||
|
|
||||||
|
{25, 187, 28}, //T
|
||||||
|
{56, 187, 23}, //U
|
||||||
|
{87, 187, 27}, //V
|
||||||
|
{121, 187, 35}, //W
|
||||||
|
{163, 187, 22}, //X
|
||||||
|
{192, 187, 28}, //Y
|
||||||
|
{225, 187, 19}, //Z
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#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 ) {
|
||||||
|
//PKMOD - Ergodic 11/27/01 - add new font sizes "smaller" and "micro"
|
||||||
|
if( style & UI_SMALLFONT ) {
|
||||||
|
return 0.75;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( style & UI_PKA_SMALLERFONT ) {
|
||||||
|
return (float) PROP_PKA_SMALLER_SIZE_SCALE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( style & UI_PKA_MICROFONT ) {
|
||||||
|
return (float) PROP_PKA_MICRO_SIZE_SCALE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
1401
quake3/source/code/cgame/cg_effects.c
Normal file
1401
quake3/source/code/cgame/cg_effects.c
Normal file
File diff suppressed because it is too large
Load diff
3508
quake3/source/code/cgame/cg_ents.c
Normal file
3508
quake3/source/code/cgame/cg_ents.c
Normal file
File diff suppressed because it is too large
Load diff
2723
quake3/source/code/cgame/cg_event.c
Normal file
2723
quake3/source/code/cgame/cg_event.c
Normal file
File diff suppressed because it is too large
Load diff
315
quake3/source/code/cgame/cg_info.c
Normal file
315
quake3/source/code/cgame/cg_info.c
Normal file
|
@ -0,0 +1,315 @@
|
||||||
|
// 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
|
||||||
|
//PKMOD - Ergodic 02/04/01 - make 3 rows of registered icons
|
||||||
|
#define MAX_LOADING_ITEM_ICONS 39 //was 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] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PKMOD - Ergodic 02/04/01 - original code
|
||||||
|
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] );
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
//PKMOD - Ergodic 02/04/01 - make 3 row s of registered icons
|
||||||
|
for( n = 0; n < loadingItemIconCount; n++ ) {
|
||||||
|
y = 400-40;
|
||||||
|
if ( n >= 26 ) {
|
||||||
|
y += 80;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
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;
|
||||||
|
//PKMOD - Ergodic 11/07/00 - add logic to enable hub limits
|
||||||
|
int hold_hub_flag;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
//PKMOD - Ergodic 11/07/00 - add logic to enable hub limits
|
||||||
|
hold_hub_flag = atoi( Info_ValueForKey( info, "hub_flag" ) );
|
||||||
|
|
||||||
|
if ( hold_hub_flag ) {
|
||||||
|
value = atoi( Info_ValueForKey( info, "hub_timelimit" ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
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) {
|
||||||
|
//PKMOD - Ergodic 11/07/00 - add logic to enable hub limits
|
||||||
|
if ( hold_hub_flag ) {
|
||||||
|
value = atoi( Info_ValueForKey( info, "hub_fraglimit" ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
2194
quake3/source/code/cgame/cg_local.h
Normal file
2194
quake3/source/code/cgame/cg_local.h
Normal file
File diff suppressed because it is too large
Load diff
932
quake3/source/code/cgame/cg_localents.c
Normal file
932
quake3/source/code/cgame/cg_localents.c
Normal file
|
@ -0,0 +1,932 @@
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
//PKMOD - Ergodic 11/30/01 - debug radius (inactive)
|
||||||
|
// if ( (rand() % 101) > 95 )
|
||||||
|
// Com_Printf("CG_AddFallScaleFade - re->radius>%f<, le->radius>%f<\n", re->radius, le->radius );
|
||||||
|
|
||||||
|
// 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] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
PKMOD - Ergodic 01/12/04 - for quad beans blast
|
||||||
|
CG_AddScaledSpriteExplosion
|
||||||
|
|
||||||
|
scale explosion from 1 to 2 times the size
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
static void CG_AddScaledSpriteExplosion( localEntity_t *le ) {
|
||||||
|
refEntity_t re;
|
||||||
|
float c;
|
||||||
|
|
||||||
|
// vec3_t test, axis[3];
|
||||||
|
|
||||||
|
re = le->refEntity;
|
||||||
|
|
||||||
|
c = (float) (1 + 3*( cg.time - le->startTime ) / 1100);
|
||||||
|
|
||||||
|
if ( c > 4.0 ) {
|
||||||
|
c = 4.0; // can happen during connection problems
|
||||||
|
}
|
||||||
|
|
||||||
|
// VectorClear( test );
|
||||||
|
// AnglesToAxis( test, axis );
|
||||||
|
|
||||||
|
|
||||||
|
// VectorScale( axis[0], c, re.axis[0] );
|
||||||
|
// VectorScale( axis[1], c, re.axis[1] );
|
||||||
|
// VectorScale( axis[2], c, re.axis[2] );
|
||||||
|
// re.nonNormalizedAxes = qtrue;
|
||||||
|
|
||||||
|
|
||||||
|
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 = 40 * c;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
//PKMOD - Ergodic 01/12/04 - add LE for quad beans
|
||||||
|
case LE_SCALED_SPRITE_EXPLOSION:
|
||||||
|
CG_AddScaledSpriteExplosion( 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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
2545
quake3/source/code/cgame/cg_main.c
Normal file
2545
quake3/source/code/cgame/cg_main.c
Normal file
File diff suppressed because it is too large
Load diff
2381
quake3/source/code/cgame/cg_marks.c
Normal file
2381
quake3/source/code/cgame/cg_marks.c
Normal file
File diff suppressed because it is too large
Load diff
2236
quake3/source/code/cgame/cg_newdraw.c
Normal file
2236
quake3/source/code/cgame/cg_newdraw.c
Normal file
File diff suppressed because it is too large
Load diff
1997
quake3/source/code/cgame/cg_particles.c
Normal file
1997
quake3/source/code/cgame/cg_particles.c
Normal file
File diff suppressed because it is too large
Load diff
2772
quake3/source/code/cgame/cg_players.c
Normal file
2772
quake3/source/code/cgame/cg_players.c
Normal file
File diff suppressed because it is too large
Load diff
556
quake3/source/code/cgame/cg_playerstate.c
Normal file
556
quake3/source/code/cgame/cg_playerstate.c
Normal file
|
@ -0,0 +1,556 @@
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
//PKMOD - Ergodic 02/14/02 - optimize AngeVectors call when only "FORWARD" is needed
|
||||||
|
// AngleVectors( angles, dir, NULL, NULL );
|
||||||
|
AngleVectorsForward( angles, dir );
|
||||||
|
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;
|
||||||
|
|
||||||
|
//PKMOD - Ergodic 04/04/01, holds last weapon
|
||||||
|
// cg.weaponLast = cg.snap->ps.stats[ STAT_LAST_WEAPON ];
|
||||||
|
|
||||||
|
//PKMOD - Ergodic 04/04/01 - debug (inactive)
|
||||||
|
// Com_Printf( "CG_Respawn - current>%d<, last>%d<\n", cg.weaponSelect, cg.weaponLast );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
int hold_stat_bits; //PKMOD - Ergodic 02/05/02 - hold the ATTACK bits for the proper sounds
|
||||||
|
|
||||||
|
// 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
|
||||||
|
//PKMOD - Ergodic 02/05/02 - decode the ATTACK bits for the proper sounds
|
||||||
|
hold_stat_bits = ps->stats[STAT_PKA_BITS] & PKA_BITS_SENTRYATTACK;
|
||||||
|
switch ( hold_stat_bits ) {
|
||||||
|
case PKA_BITS_BEARTRAPATTACK:
|
||||||
|
trap_S_StartLocalSound( cgs.media.beartrap_attackSound, CHAN_LOCAL_SOUND );
|
||||||
|
break;
|
||||||
|
case PKA_BITS_SENTRYATTACK:
|
||||||
|
trap_S_StartLocalSound( cgs.media.autosentry_attackSound, CHAN_LOCAL_SOUND );
|
||||||
|
break;
|
||||||
|
case PKA_BITS_RADIATEATTACK:
|
||||||
|
trap_S_StartLocalSound( cgs.media.radiate_attackSound, CHAN_LOCAL_SOUND );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
trap_S_StartLocalSound( cgs.media.hitSound, CHAN_LOCAL_SOUND );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
#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");
|
||||||
|
}
|
||||||
|
//PKMOD - Ergodic 08/08/00 PAINKILLER awarded after every 10 PKitem kills
|
||||||
|
//PKMOD - Ergodic 12/16/00 - shift off add HUB_FLAG (first bit of PERS_PAINKILLER_COUNT)
|
||||||
|
if ( ( (ps->persistant[PERS_PAINKILLER_COUNT] >> 1) / 10 ) != ( (ops->persistant[PERS_PAINKILLER_COUNT] >> 1) / 10 )) {
|
||||||
|
//PKMOD - Ergodic 12/26/00 fixed typo on painkiller announcement sound
|
||||||
|
sfx = cgs.media.painkillerSound;
|
||||||
|
pushReward(sfx, cgs.media.medalPainKiller, (ps->persistant[PERS_PAINKILLER_COUNT] >> 1) / 10);
|
||||||
|
reward = qtrue;
|
||||||
|
//Com_Printf("painkiller\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
//PKMOD OLD 1.17 codebase
|
||||||
|
//PKMOD - Ergodic 08/08/00 PAINKILLER awarded after every 10 PKitem kills
|
||||||
|
// case REWARD_PAINKILLER:
|
||||||
|
// trap_S_StartLocalSound( cgs.media.painkillerSound, CHAN_ANNOUNCER );
|
||||||
|
// cg.rewardTime = cg.time;
|
||||||
|
// cg.rewardShader = cgs.media.medalPainKiller;
|
||||||
|
// cg.rewardCount = ps->persistant[PERS_PAINKILLER_COUNT] / 10;
|
||||||
|
// break;
|
||||||
|
|
||||||
|
|
||||||
|
// 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] ) {
|
||||||
|
//PKMOD - Ergodic 01/20/02 - don't play sounds when comparing with private bots
|
||||||
|
//PKMOD - Ergodic 02/05/02 - change STAT_PKA_BITS settings from enum type to definition
|
||||||
|
if ( !( ( ops->stats[STAT_PKA_BITS] & PKA_BITS_PRIVATEBOT ) || ( ps->stats[STAT_PKA_BITS] & PKA_BITS_PRIVATEBOT ) ) ) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
643
quake3/source/code/cgame/cg_predict.c
Normal file
643
quake3/source/code/cgame/cg_predict.c
Normal file
|
@ -0,0 +1,643 @@
|
||||||
|
// 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 = ¢->currentState;
|
||||||
|
|
||||||
|
//PKMOD Ergodic debug 07/04/01 (inactive)
|
||||||
|
// if ( ent->eType == ET_ZOMBIE ) {
|
||||||
|
// Com_Printf( "CG_BuildSolidList et_zombie found\n" );
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
//PKMOD Ergodic debug 09/30/01 (inactive)
|
||||||
|
// if ( ent->eType == ET_LIGHTNING_FX ) {
|
||||||
|
// Com_Printf( "CG_BuildSolidList ET_LIGHTNING_FX found\n" );
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
//PKMOD - Ergodic. 05/30/00 modify for beartrap
|
||||||
|
//PKMOD - Ergodic 11/15/00 add functionality to make trigger_push silent
|
||||||
|
if ( ent->eType == ET_BEARTRAP || ent->eType == ET_ITEM || ent->eType == ET_PUSH_TRIGGER || ent->eType == ET_TELEPORT_TRIGGER || ent->eType == ET_QUIET_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 = ¢->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( ¢->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 = ¢->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
|
||||||
|
//PKMOD - Ergodic 09/26/00 - don't register the touching of the voting_image entity.
|
||||||
|
// The voting_image is not a pickup item
|
||||||
|
===================
|
||||||
|
*/
|
||||||
|
static void CG_TouchItem( centity_t *cent ) {
|
||||||
|
gitem_t *item;
|
||||||
|
|
||||||
|
if ( !cg_predictItems.integer ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ( !BG_PlayerTouchesItem( &cg.predictedPlayerState, ¢->currentState, cg.time ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// never pick an item up twice in a prediction
|
||||||
|
if ( cent->miscTime == cg.time ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !BG_CanItemBeGrabbed( cgs.gametype, ¢->currentState, &cg.predictedPlayerState ) ) {
|
||||||
|
return; // can't hold it
|
||||||
|
}
|
||||||
|
|
||||||
|
item = &bg_itemlist[ cent->currentState.modelindex ];
|
||||||
|
|
||||||
|
//PKMOD - Ergodic 09/26/00 - don't pickup the voting_image
|
||||||
|
if ( item->giType == IT_VOTING ) {
|
||||||
|
//PKMOD - Ergodic 09/28/00 - debug inactive
|
||||||
|
// Com_Printf("CG_TouchItem - voting entity index >%d<\n", cent->currentState.otherEntityNum );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 = ¢->currentState;
|
||||||
|
|
||||||
|
if ( ent->eType == ET_ITEM && !spectator ) {
|
||||||
|
CG_TouchItem( cent );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//PKMOD - Ergodic. 05/30/00 modify for beartrap
|
||||||
|
if ( ent->eType == ET_BEARTRAP && !spectator ) {
|
||||||
|
//PKMOD - Ergodic 06/03/00 don't fire up cg_touchitem for launched beartraps
|
||||||
|
// 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 ) || ( ent->eType == ET_TELEPORT_TRIGGER ) || ( ent->eType == ET_QUIET_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//PKMOD - Ergodic 04/05/01 - debug (inactive)
|
||||||
|
// Com_Printf( "CG_PredictPlayerState - calling pmove\n" );
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
218
quake3/source/code/cgame/cg_public.h
Normal file
218
quake3/source/code/cgame/cg_public.h
Normal 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;
|
||||||
|
|
||||||
|
//----------------------------------------------
|
531
quake3/source/code/cgame/cg_scoreboard.c
Normal file
531
quake3/source/code/cgame/cg_scoreboard.c
Normal file
|
@ -0,0 +1,531 @@
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//PKMOD - Ergodic 01/09/02 - add info to structure so Private Bot will not appear in scoreboard
|
||||||
|
if ( ci->privateBot ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//PKMOD - Ergodic 01/09/02 - debug private bot on scoreboard (inactive)
|
||||||
|
// Com_Printf("CG_TeamScoreboard\n" );
|
||||||
|
|
||||||
|
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 ) {
|
||||||
|
|
||||||
|
//PKMOD - Ergodic 01/09/02 - add info to structure so Private Bot will not appear in scoreboard
|
||||||
|
if ( cgs.clientinfo[i].privateBot ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//PKMOD - Ergodic 01/09/02 - debug private bot on scoreboard (inactive)
|
||||||
|
// Com_Printf("CG_DrawOldScoreboard\n" );
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
1200
quake3/source/code/cgame/cg_servercmds.c
Normal file
1200
quake3/source/code/cgame/cg_servercmds.c
Normal file
File diff suppressed because it is too large
Load diff
402
quake3/source/code/cgame/cg_snapshot.c
Normal file
402
quake3/source/code/cgame/cg_snapshot.c
Normal file
|
@ -0,0 +1,402 @@
|
||||||
|
// 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 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//PKMOD - Ergodic 07/04/01 - debug position
|
||||||
|
extern char *CG_vtos( const vec3_t v );
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
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;
|
||||||
|
|
||||||
|
//PKMOD Ergodic debug 07/19/00 (inactive)
|
||||||
|
// if ( cent->currentState.eType == ET_LIGHTNING_FX ) {
|
||||||
|
// Com_Printf("CG_TransitionEntity - ET_LIGHTNING_FX found\n");
|
||||||
|
// }
|
||||||
|
|
||||||
|
//PKMOD Ergodic debug 07/04/01 (inactive)
|
||||||
|
// if ( cent->currentState.eType == ET_ZOMBIE ) {
|
||||||
|
// Com_Printf("CG_TransitionEntity - ET_ZOMBIE found at >%s<\n", CG_vtos(cent->lerpOrigin) ) ;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 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(¢->currentState, state, sizeof(entityState_t));
|
||||||
|
//cent->currentState = *state;
|
||||||
|
cent->interpolate = qfalse;
|
||||||
|
cent->currentValid = qtrue;
|
||||||
|
|
||||||
|
//PKMOD Ergodic debug 07/19/00 (inactive)
|
||||||
|
// if ( cent->currentState.eType == ET_LIGHTNING_FX ) {
|
||||||
|
// Com_Printf("CG_SetInitialSnapshot - ET_LIGHTNING_FX found\n");
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
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(¢->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" );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
106
quake3/source/code/cgame/cg_syscalls.asm
Normal file
106
quake3/source/code/cgame/cg_syscalls.asm
Normal 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
|
||||||
|
|
426
quake3/source/code/cgame/cg_syscalls.c
Normal file
426
quake3/source/code/cgame/cg_syscalls.c
Normal file
|
@ -0,0 +1,426 @@
|
||||||
|
// 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
|
||||||
|
#ifdef Q3_VM
|
||||||
|
#error "Do not use in VM build"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#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 );
|
||||||
|
}
|
863
quake3/source/code/cgame/cg_view.c
Normal file
863
quake3/source/code/cgame/cg_view.c
Normal file
|
@ -0,0 +1,863 @@
|
||||||
|
// Copyright (C) 1999-2000 Id Software, Inc.
|
||||||
|
//
|
||||||
|
// cg_view.c -- setup all the parameters (position, angle, etc)
|
||||||
|
// for a 3D rendering
|
||||||
|
#include "cg_local.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============================================================================
|
||||||
|
|
||||||
|
MODEL TESTING
|
||||||
|
|
||||||
|
The viewthing and gun positioning tools from Q2 have been integrated and
|
||||||
|
enhanced into a single model testing facility.
|
||||||
|
|
||||||
|
Model viewing can begin with either "testmodel <modelname>" or "testgun <modelname>".
|
||||||
|
|
||||||
|
The names must be the full pathname after the basedir, like
|
||||||
|
"models/weapons/v_launch/tris.md3" or "players/male/tris.md3"
|
||||||
|
|
||||||
|
Testmodel will create a fake entity 100 units in front of the current view
|
||||||
|
position, directly facing the viewer. It will remain immobile, so you can
|
||||||
|
move around it to view it from different angles.
|
||||||
|
|
||||||
|
Testgun will cause the model to follow the player around and supress the real
|
||||||
|
view weapon model. The default frame 0 of most guns is completely off screen,
|
||||||
|
so you will probably have to cycle a couple frames to see it.
|
||||||
|
|
||||||
|
"nextframe", "prevframe", "nextskin", and "prevskin" commands will change the
|
||||||
|
frame or skin of the testmodel. These are bound to F5, F6, F7, and F8 in
|
||||||
|
q3default.cfg.
|
||||||
|
|
||||||
|
If a gun is being tested, the "gun_x", "gun_y", and "gun_z" variables will let
|
||||||
|
you adjust the positioning.
|
||||||
|
|
||||||
|
Note that none of the model testing features update while the game is paused, so
|
||||||
|
it may be convenient to test with deathmatch set to 1 so that bringing down the
|
||||||
|
console doesn't pause the game.
|
||||||
|
|
||||||
|
=============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
CG_TestModel_f
|
||||||
|
|
||||||
|
Creates an entity in front of the current position, which
|
||||||
|
can then be moved around
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void CG_TestModel_f (void) {
|
||||||
|
vec3_t angles;
|
||||||
|
|
||||||
|
memset( &cg.testModelEntity, 0, sizeof(cg.testModelEntity) );
|
||||||
|
if ( trap_Argc() < 2 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_strncpyz (cg.testModelName, CG_Argv( 1 ), MAX_QPATH );
|
||||||
|
cg.testModelEntity.hModel = trap_R_RegisterModel( cg.testModelName );
|
||||||
|
|
||||||
|
if ( trap_Argc() == 3 ) {
|
||||||
|
cg.testModelEntity.backlerp = atof( CG_Argv( 2 ) );
|
||||||
|
cg.testModelEntity.frame = 1;
|
||||||
|
cg.testModelEntity.oldframe = 0;
|
||||||
|
}
|
||||||
|
if (! cg.testModelEntity.hModel ) {
|
||||||
|
CG_Printf( "Can't register model\n" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
VectorMA( cg.refdef.vieworg, 100, cg.refdef.viewaxis[0], cg.testModelEntity.origin );
|
||||||
|
|
||||||
|
angles[PITCH] = 0;
|
||||||
|
angles[YAW] = 180 + cg.refdefViewAngles[1];
|
||||||
|
angles[ROLL] = 0;
|
||||||
|
|
||||||
|
AnglesToAxis( angles, cg.testModelEntity.axis );
|
||||||
|
cg.testGun = qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
CG_TestGun_f
|
||||||
|
|
||||||
|
Replaces the current view weapon with the given model
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void CG_TestGun_f (void) {
|
||||||
|
CG_TestModel_f();
|
||||||
|
cg.testGun = qtrue;
|
||||||
|
cg.testModelEntity.renderfx = RF_MINLIGHT | RF_DEPTHHACK | RF_FIRST_PERSON;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CG_TestModelNextFrame_f (void) {
|
||||||
|
cg.testModelEntity.frame++;
|
||||||
|
CG_Printf( "frame %i\n", cg.testModelEntity.frame );
|
||||||
|
}
|
||||||
|
|
||||||
|
void CG_TestModelPrevFrame_f (void) {
|
||||||
|
cg.testModelEntity.frame--;
|
||||||
|
if ( cg.testModelEntity.frame < 0 ) {
|
||||||
|
cg.testModelEntity.frame = 0;
|
||||||
|
}
|
||||||
|
CG_Printf( "frame %i\n", cg.testModelEntity.frame );
|
||||||
|
}
|
||||||
|
|
||||||
|
void CG_TestModelNextSkin_f (void) {
|
||||||
|
cg.testModelEntity.skinNum++;
|
||||||
|
CG_Printf( "skin %i\n", cg.testModelEntity.skinNum );
|
||||||
|
}
|
||||||
|
|
||||||
|
void CG_TestModelPrevSkin_f (void) {
|
||||||
|
cg.testModelEntity.skinNum--;
|
||||||
|
if ( cg.testModelEntity.skinNum < 0 ) {
|
||||||
|
cg.testModelEntity.skinNum = 0;
|
||||||
|
}
|
||||||
|
CG_Printf( "skin %i\n", cg.testModelEntity.skinNum );
|
||||||
|
}
|
||||||
|
|
||||||
|
static void CG_AddTestModel (void) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// re-register the model, because the level may have changed
|
||||||
|
cg.testModelEntity.hModel = trap_R_RegisterModel( cg.testModelName );
|
||||||
|
if (! cg.testModelEntity.hModel ) {
|
||||||
|
CG_Printf ("Can't register model\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if testing a gun, set the origin reletive to the view origin
|
||||||
|
if ( cg.testGun ) {
|
||||||
|
VectorCopy( cg.refdef.vieworg, cg.testModelEntity.origin );
|
||||||
|
VectorCopy( cg.refdef.viewaxis[0], cg.testModelEntity.axis[0] );
|
||||||
|
VectorCopy( cg.refdef.viewaxis[1], cg.testModelEntity.axis[1] );
|
||||||
|
VectorCopy( cg.refdef.viewaxis[2], cg.testModelEntity.axis[2] );
|
||||||
|
|
||||||
|
// allow the position to be adjusted
|
||||||
|
for (i=0 ; i<3 ; i++) {
|
||||||
|
cg.testModelEntity.origin[i] += cg.refdef.viewaxis[0][i] * cg_gun_x.value;
|
||||||
|
cg.testModelEntity.origin[i] += cg.refdef.viewaxis[1][i] * cg_gun_y.value;
|
||||||
|
cg.testModelEntity.origin[i] += cg.refdef.viewaxis[2][i] * cg_gun_z.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trap_R_AddRefEntityToScene( &cg.testModelEntity );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
CG_CalcVrect
|
||||||
|
|
||||||
|
Sets the coordinates of the rendered window
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
static void CG_CalcVrect (void) {
|
||||||
|
int size;
|
||||||
|
|
||||||
|
// the intermission should allways be full screen
|
||||||
|
if ( cg.snap->ps.pm_type == PM_INTERMISSION ) {
|
||||||
|
size = 100;
|
||||||
|
} else {
|
||||||
|
// bound normal viewsize
|
||||||
|
if (cg_viewsize.integer < 30) {
|
||||||
|
trap_Cvar_Set ("cg_viewsize","30");
|
||||||
|
size = 30;
|
||||||
|
} else if (cg_viewsize.integer > 100) {
|
||||||
|
trap_Cvar_Set ("cg_viewsize","100");
|
||||||
|
size = 100;
|
||||||
|
} else {
|
||||||
|
size = cg_viewsize.integer;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
cg.refdef.width = cgs.glconfig.vidWidth*size/100;
|
||||||
|
cg.refdef.width &= ~1;
|
||||||
|
|
||||||
|
cg.refdef.height = cgs.glconfig.vidHeight*size/100;
|
||||||
|
cg.refdef.height &= ~1;
|
||||||
|
|
||||||
|
cg.refdef.x = (cgs.glconfig.vidWidth - cg.refdef.width)/2;
|
||||||
|
cg.refdef.y = (cgs.glconfig.vidHeight - cg.refdef.height)/2;
|
||||||
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
CG_OffsetThirdPersonView
|
||||||
|
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
#define FOCUS_DISTANCE 512
|
||||||
|
static void CG_OffsetThirdPersonView( void ) {
|
||||||
|
vec3_t forward, right, up;
|
||||||
|
vec3_t view;
|
||||||
|
vec3_t focusAngles;
|
||||||
|
trace_t trace;
|
||||||
|
static vec3_t mins = { -4, -4, -4 };
|
||||||
|
static vec3_t maxs = { 4, 4, 4 };
|
||||||
|
vec3_t focusPoint;
|
||||||
|
float focusDist;
|
||||||
|
float forwardScale, sideScale;
|
||||||
|
|
||||||
|
cg.refdef.vieworg[2] += cg.predictedPlayerState.viewheight;
|
||||||
|
|
||||||
|
VectorCopy( cg.refdefViewAngles, focusAngles );
|
||||||
|
|
||||||
|
// if dead, look at killer
|
||||||
|
if ( cg.predictedPlayerState.stats[STAT_HEALTH] <= 0 ) {
|
||||||
|
focusAngles[YAW] = cg.predictedPlayerState.stats[STAT_DEAD_YAW];
|
||||||
|
cg.refdefViewAngles[YAW] = cg.predictedPlayerState.stats[STAT_DEAD_YAW];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( focusAngles[PITCH] > 45 ) {
|
||||||
|
focusAngles[PITCH] = 45; // don't go too far overhead
|
||||||
|
}
|
||||||
|
//PKMOD - Ergodic 02/14/02 - optimize AngeVectors call when only "FORWARD" is needed
|
||||||
|
// AngleVectors( focusAngles, forward, NULL, NULL );
|
||||||
|
AngleVectorsForward( focusAngles, forward );
|
||||||
|
|
||||||
|
VectorMA( cg.refdef.vieworg, FOCUS_DISTANCE, forward, focusPoint );
|
||||||
|
|
||||||
|
VectorCopy( cg.refdef.vieworg, view );
|
||||||
|
|
||||||
|
view[2] += 8;
|
||||||
|
|
||||||
|
cg.refdefViewAngles[PITCH] *= 0.5;
|
||||||
|
|
||||||
|
AngleVectors( cg.refdefViewAngles, forward, right, up );
|
||||||
|
|
||||||
|
forwardScale = cos( cg_thirdPersonAngle.value / 180 * M_PI );
|
||||||
|
sideScale = sin( cg_thirdPersonAngle.value / 180 * M_PI );
|
||||||
|
VectorMA( view, -cg_thirdPersonRange.value * forwardScale, forward, view );
|
||||||
|
VectorMA( view, -cg_thirdPersonRange.value * sideScale, right, view );
|
||||||
|
|
||||||
|
// trace a ray from the origin to the viewpoint to make sure the view isn't
|
||||||
|
// in a solid block. Use an 8 by 8 block to prevent the view from near clipping anything
|
||||||
|
|
||||||
|
if (!cg_cameraMode.integer) {
|
||||||
|
CG_Trace( &trace, cg.refdef.vieworg, mins, maxs, view, cg.predictedPlayerState.clientNum, MASK_SOLID );
|
||||||
|
|
||||||
|
if ( trace.fraction != 1.0 ) {
|
||||||
|
VectorCopy( trace.endpos, view );
|
||||||
|
view[2] += (1.0 - trace.fraction) * 32;
|
||||||
|
// try another trace to this position, because a tunnel may have the ceiling
|
||||||
|
// close enogh that this is poking out
|
||||||
|
|
||||||
|
CG_Trace( &trace, cg.refdef.vieworg, mins, maxs, view, cg.predictedPlayerState.clientNum, MASK_SOLID );
|
||||||
|
VectorCopy( trace.endpos, view );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VectorCopy( view, cg.refdef.vieworg );
|
||||||
|
|
||||||
|
// select pitch to look at focus point from vieword
|
||||||
|
VectorSubtract( focusPoint, cg.refdef.vieworg, focusPoint );
|
||||||
|
focusDist = sqrt( focusPoint[0] * focusPoint[0] + focusPoint[1] * focusPoint[1] );
|
||||||
|
if ( focusDist < 1 ) {
|
||||||
|
focusDist = 1; // should never happen
|
||||||
|
}
|
||||||
|
cg.refdefViewAngles[PITCH] = -180 / M_PI * atan2( focusPoint[2], focusDist );
|
||||||
|
cg.refdefViewAngles[YAW] -= cg_thirdPersonAngle.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// this causes a compiler bug on mac MrC compiler
|
||||||
|
static void CG_StepOffset( void ) {
|
||||||
|
int timeDelta;
|
||||||
|
|
||||||
|
// smooth out stair climbing
|
||||||
|
timeDelta = cg.time - cg.stepTime;
|
||||||
|
if ( timeDelta < STEP_TIME ) {
|
||||||
|
cg.refdef.vieworg[2] -= cg.stepChange
|
||||||
|
* (STEP_TIME - timeDelta) / STEP_TIME;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
CG_OffsetFirstPersonView
|
||||||
|
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
static void CG_OffsetFirstPersonView( void ) {
|
||||||
|
float *origin;
|
||||||
|
float *angles;
|
||||||
|
float bob;
|
||||||
|
float ratio;
|
||||||
|
float delta;
|
||||||
|
float speed;
|
||||||
|
float f;
|
||||||
|
vec3_t predictedVelocity;
|
||||||
|
int timeDelta;
|
||||||
|
|
||||||
|
if ( cg.snap->ps.pm_type == PM_INTERMISSION ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
origin = cg.refdef.vieworg;
|
||||||
|
angles = cg.refdefViewAngles;
|
||||||
|
|
||||||
|
// if dead, fix the angle and don't add any kick
|
||||||
|
if ( cg.snap->ps.stats[STAT_HEALTH] <= 0 ) {
|
||||||
|
angles[ROLL] = 40;
|
||||||
|
angles[PITCH] = -15;
|
||||||
|
angles[YAW] = cg.snap->ps.stats[STAT_DEAD_YAW];
|
||||||
|
origin[2] += cg.predictedPlayerState.viewheight;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add angles based on weapon kick
|
||||||
|
VectorAdd (angles, cg.kick_angles, angles);
|
||||||
|
|
||||||
|
// add angles based on damage kick
|
||||||
|
if ( cg.damageTime ) {
|
||||||
|
ratio = cg.time - cg.damageTime;
|
||||||
|
if ( ratio < DAMAGE_DEFLECT_TIME ) {
|
||||||
|
ratio /= DAMAGE_DEFLECT_TIME;
|
||||||
|
angles[PITCH] += ratio * cg.v_dmg_pitch;
|
||||||
|
angles[ROLL] += ratio * cg.v_dmg_roll;
|
||||||
|
} else {
|
||||||
|
ratio = 1.0 - ( ratio - DAMAGE_DEFLECT_TIME ) / DAMAGE_RETURN_TIME;
|
||||||
|
if ( ratio > 0 ) {
|
||||||
|
angles[PITCH] += ratio * cg.v_dmg_pitch;
|
||||||
|
angles[ROLL] += ratio * cg.v_dmg_roll;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add pitch based on fall kick
|
||||||
|
#if 0
|
||||||
|
ratio = ( cg.time - cg.landTime) / FALL_TIME;
|
||||||
|
if (ratio < 0)
|
||||||
|
ratio = 0;
|
||||||
|
angles[PITCH] += ratio * cg.fall_value;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// add angles based on velocity
|
||||||
|
VectorCopy( cg.predictedPlayerState.velocity, predictedVelocity );
|
||||||
|
|
||||||
|
delta = DotProduct ( predictedVelocity, cg.refdef.viewaxis[0]);
|
||||||
|
angles[PITCH] += delta * cg_runpitch.value;
|
||||||
|
|
||||||
|
delta = DotProduct ( predictedVelocity, cg.refdef.viewaxis[1]);
|
||||||
|
angles[ROLL] -= delta * cg_runroll.value;
|
||||||
|
|
||||||
|
// add angles based on bob
|
||||||
|
|
||||||
|
// make sure the bob is visible even at low speeds
|
||||||
|
speed = cg.xyspeed > 200 ? cg.xyspeed : 200;
|
||||||
|
|
||||||
|
delta = cg.bobfracsin * cg_bobpitch.value * speed;
|
||||||
|
if (cg.predictedPlayerState.pm_flags & PMF_DUCKED)
|
||||||
|
delta *= 3; // crouching
|
||||||
|
angles[PITCH] += delta;
|
||||||
|
delta = cg.bobfracsin * cg_bobroll.value * speed;
|
||||||
|
if (cg.predictedPlayerState.pm_flags & PMF_DUCKED)
|
||||||
|
delta *= 3; // crouching accentuates roll
|
||||||
|
if (cg.bobcycle & 1)
|
||||||
|
delta = -delta;
|
||||||
|
angles[ROLL] += delta;
|
||||||
|
|
||||||
|
//===================================
|
||||||
|
|
||||||
|
// add view height
|
||||||
|
origin[2] += cg.predictedPlayerState.viewheight;
|
||||||
|
|
||||||
|
// smooth out duck height changes
|
||||||
|
timeDelta = cg.time - cg.duckTime;
|
||||||
|
if ( timeDelta < DUCK_TIME) {
|
||||||
|
cg.refdef.vieworg[2] -= cg.duckChange
|
||||||
|
* (DUCK_TIME - timeDelta) / DUCK_TIME;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add bob height
|
||||||
|
bob = cg.bobfracsin * cg.xyspeed * cg_bobup.value;
|
||||||
|
if (bob > 6) {
|
||||||
|
bob = 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
origin[2] += bob;
|
||||||
|
|
||||||
|
|
||||||
|
// add fall height
|
||||||
|
delta = cg.time - cg.landTime;
|
||||||
|
if ( delta < LAND_DEFLECT_TIME ) {
|
||||||
|
f = delta / LAND_DEFLECT_TIME;
|
||||||
|
cg.refdef.vieworg[2] += cg.landChange * f;
|
||||||
|
} else if ( delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME ) {
|
||||||
|
delta -= LAND_DEFLECT_TIME;
|
||||||
|
f = 1.0 - ( delta / LAND_RETURN_TIME );
|
||||||
|
cg.refdef.vieworg[2] += cg.landChange * f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add step offset
|
||||||
|
CG_StepOffset();
|
||||||
|
|
||||||
|
// add kick offset
|
||||||
|
|
||||||
|
VectorAdd (origin, cg.kick_origin, origin);
|
||||||
|
|
||||||
|
// pivot the eye based on a neck length
|
||||||
|
#if 0
|
||||||
|
{
|
||||||
|
#define NECK_LENGTH 8
|
||||||
|
vec3_t forward, up;
|
||||||
|
|
||||||
|
cg.refdef.vieworg[2] -= NECK_LENGTH;
|
||||||
|
AngleVectors( cg.refdefViewAngles, forward, NULL, up );
|
||||||
|
VectorMA( cg.refdef.vieworg, 3, forward, cg.refdef.vieworg );
|
||||||
|
VectorMA( cg.refdef.vieworg, NECK_LENGTH, up, cg.refdef.vieworg );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
|
||||||
|
void CG_ZoomDown_f( void ) {
|
||||||
|
if ( cg.zoomed ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cg.zoomed = qtrue;
|
||||||
|
cg.zoomTime = cg.time;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CG_ZoomUp_f( void ) {
|
||||||
|
if ( !cg.zoomed ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cg.zoomed = qfalse;
|
||||||
|
cg.zoomTime = cg.time;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
====================
|
||||||
|
CG_CalcFov
|
||||||
|
|
||||||
|
Fixed fov at intermissions, otherwise account for fov variable and zooms.
|
||||||
|
====================
|
||||||
|
*/
|
||||||
|
#define WAVE_AMPLITUDE 1
|
||||||
|
#define WAVE_FREQUENCY 0.4
|
||||||
|
|
||||||
|
static int CG_CalcFov( void ) {
|
||||||
|
float x;
|
||||||
|
float phase;
|
||||||
|
float v;
|
||||||
|
int contents;
|
||||||
|
float fov_x, fov_y;
|
||||||
|
float zoomFov;
|
||||||
|
float f;
|
||||||
|
int inwater;
|
||||||
|
|
||||||
|
if ( cg.predictedPlayerState.pm_type == PM_INTERMISSION ) {
|
||||||
|
// if in intermission, use a fixed value
|
||||||
|
fov_x = 90;
|
||||||
|
} else {
|
||||||
|
// user selectable
|
||||||
|
if ( cgs.dmflags & DF_FIXED_FOV ) {
|
||||||
|
// dmflag to prevent wide fov for all clients
|
||||||
|
fov_x = 90;
|
||||||
|
} else {
|
||||||
|
fov_x = cg_fov.value;
|
||||||
|
if ( fov_x < 1 ) {
|
||||||
|
fov_x = 1;
|
||||||
|
} else if ( fov_x > 160 ) {
|
||||||
|
fov_x = 160;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// account for zooms
|
||||||
|
zoomFov = cg_zoomFov.value;
|
||||||
|
if ( zoomFov < 1 ) {
|
||||||
|
zoomFov = 1;
|
||||||
|
} else if ( zoomFov > 160 ) {
|
||||||
|
zoomFov = 160;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( cg.zoomed ) {
|
||||||
|
f = ( cg.time - cg.zoomTime ) / (float)ZOOM_TIME;
|
||||||
|
if ( f > 1.0 ) {
|
||||||
|
fov_x = zoomFov;
|
||||||
|
} else {
|
||||||
|
fov_x = fov_x + f * ( zoomFov - fov_x );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
f = ( cg.time - cg.zoomTime ) / (float)ZOOM_TIME;
|
||||||
|
if ( f > 1.0 ) {
|
||||||
|
fov_x = fov_x;
|
||||||
|
} else {
|
||||||
|
fov_x = zoomFov + f * ( fov_x - zoomFov );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
x = cg.refdef.width / tan( fov_x / 360 * M_PI );
|
||||||
|
fov_y = atan2( cg.refdef.height, x );
|
||||||
|
fov_y = fov_y * 360 / M_PI;
|
||||||
|
|
||||||
|
// warp if underwater
|
||||||
|
contents = CG_PointContents( cg.refdef.vieworg, -1 );
|
||||||
|
if ( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ){
|
||||||
|
phase = cg.time / 1000.0 * WAVE_FREQUENCY * M_PI * 2;
|
||||||
|
v = WAVE_AMPLITUDE * sin( phase );
|
||||||
|
fov_x += v;
|
||||||
|
fov_y -= v;
|
||||||
|
inwater = qtrue;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
inwater = qfalse;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// set it
|
||||||
|
cg.refdef.fov_x = fov_x;
|
||||||
|
cg.refdef.fov_y = fov_y;
|
||||||
|
|
||||||
|
if ( !cg.zoomed ) {
|
||||||
|
cg.zoomSensitivity = 1;
|
||||||
|
} else {
|
||||||
|
cg.zoomSensitivity = cg.refdef.fov_y / 75.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return inwater;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
CG_DamageBlendBlob
|
||||||
|
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
static void CG_DamageBlendBlob( void ) {
|
||||||
|
int t;
|
||||||
|
int maxTime;
|
||||||
|
refEntity_t ent;
|
||||||
|
|
||||||
|
if ( !cg.damageValue ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (cg.cameraMode) {
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// ragePro systems can't fade blends, so don't obscure the screen
|
||||||
|
if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
maxTime = DAMAGE_TIME;
|
||||||
|
t = cg.time - cg.damageTime;
|
||||||
|
if ( t <= 0 || t >= maxTime ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
memset( &ent, 0, sizeof( ent ) );
|
||||||
|
ent.reType = RT_SPRITE;
|
||||||
|
ent.renderfx = RF_FIRST_PERSON;
|
||||||
|
|
||||||
|
VectorMA( cg.refdef.vieworg, 8, cg.refdef.viewaxis[0], ent.origin );
|
||||||
|
VectorMA( ent.origin, cg.damageX * -8, cg.refdef.viewaxis[1], ent.origin );
|
||||||
|
VectorMA( ent.origin, cg.damageY * 8, cg.refdef.viewaxis[2], ent.origin );
|
||||||
|
|
||||||
|
ent.radius = cg.damageValue * 3;
|
||||||
|
ent.customShader = cgs.media.viewBloodShader;
|
||||||
|
ent.shaderRGBA[0] = 255;
|
||||||
|
ent.shaderRGBA[1] = 255;
|
||||||
|
ent.shaderRGBA[2] = 255;
|
||||||
|
ent.shaderRGBA[3] = 200 * ( 1.0 - ((float)t / maxTime) );
|
||||||
|
trap_R_AddRefEntityToScene( &ent );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
===============
|
||||||
|
CG_CalcViewValues
|
||||||
|
|
||||||
|
Sets cg.refdef view values
|
||||||
|
===============
|
||||||
|
*/
|
||||||
|
static int CG_CalcViewValues( void ) {
|
||||||
|
playerState_t *ps;
|
||||||
|
|
||||||
|
memset( &cg.refdef, 0, sizeof( cg.refdef ) );
|
||||||
|
|
||||||
|
// strings for in game rendering
|
||||||
|
// Q_strncpyz( cg.refdef.text[0], "Park Ranger", sizeof(cg.refdef.text[0]) );
|
||||||
|
// Q_strncpyz( cg.refdef.text[1], "19", sizeof(cg.refdef.text[1]) );
|
||||||
|
|
||||||
|
// calculate size of 3D view
|
||||||
|
CG_CalcVrect();
|
||||||
|
|
||||||
|
ps = &cg.predictedPlayerState;
|
||||||
|
/*
|
||||||
|
if (cg.cameraMode) {
|
||||||
|
vec3_t origin, angles;
|
||||||
|
if (trap_getCameraInfo(cg.time, &origin, &angles)) {
|
||||||
|
VectorCopy(origin, cg.refdef.vieworg);
|
||||||
|
angles[ROLL] = 0;
|
||||||
|
VectorCopy(angles, cg.refdefViewAngles);
|
||||||
|
AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis );
|
||||||
|
return CG_CalcFov();
|
||||||
|
} else {
|
||||||
|
cg.cameraMode = qfalse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// intermission view
|
||||||
|
if ( ps->pm_type == PM_INTERMISSION ) {
|
||||||
|
VectorCopy( ps->origin, cg.refdef.vieworg );
|
||||||
|
VectorCopy( ps->viewangles, cg.refdefViewAngles );
|
||||||
|
AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis );
|
||||||
|
return CG_CalcFov();
|
||||||
|
}
|
||||||
|
|
||||||
|
cg.bobcycle = ( ps->bobCycle & 128 ) >> 7;
|
||||||
|
cg.bobfracsin = fabs( sin( ( ps->bobCycle & 127 ) / 127.0 * M_PI ) );
|
||||||
|
cg.xyspeed = sqrt( ps->velocity[0] * ps->velocity[0] +
|
||||||
|
ps->velocity[1] * ps->velocity[1] );
|
||||||
|
|
||||||
|
|
||||||
|
VectorCopy( ps->origin, cg.refdef.vieworg );
|
||||||
|
VectorCopy( ps->viewangles, cg.refdefViewAngles );
|
||||||
|
|
||||||
|
if (cg_cameraOrbit.integer) {
|
||||||
|
if (cg.time > cg.nextOrbitTime) {
|
||||||
|
cg.nextOrbitTime = cg.time + cg_cameraOrbitDelay.integer;
|
||||||
|
cg_thirdPersonAngle.value += cg_cameraOrbit.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// add error decay
|
||||||
|
if ( cg_errorDecay.value > 0 ) {
|
||||||
|
int t;
|
||||||
|
float f;
|
||||||
|
|
||||||
|
t = cg.time - cg.predictedErrorTime;
|
||||||
|
f = ( cg_errorDecay.value - t ) / cg_errorDecay.value;
|
||||||
|
if ( f > 0 && f < 1 ) {
|
||||||
|
VectorMA( cg.refdef.vieworg, f, cg.predictedError, cg.refdef.vieworg );
|
||||||
|
} else {
|
||||||
|
cg.predictedErrorTime = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( cg.renderingThirdPerson ) {
|
||||||
|
// back away from character
|
||||||
|
CG_OffsetThirdPersonView();
|
||||||
|
} else {
|
||||||
|
// offset for local bobbing and kicks
|
||||||
|
CG_OffsetFirstPersonView();
|
||||||
|
}
|
||||||
|
|
||||||
|
// position eye reletive to origin
|
||||||
|
AnglesToAxis( cg.refdefViewAngles, cg.refdef.viewaxis );
|
||||||
|
|
||||||
|
if ( cg.hyperspace ) {
|
||||||
|
cg.refdef.rdflags |= RDF_NOWORLDMODEL | RDF_HYPERSPACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// field of view
|
||||||
|
return CG_CalcFov();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
=====================
|
||||||
|
CG_PowerupTimerSounds
|
||||||
|
=====================
|
||||||
|
*/
|
||||||
|
static void CG_PowerupTimerSounds( void ) {
|
||||||
|
int i;
|
||||||
|
int t;
|
||||||
|
|
||||||
|
// powerup timers going away
|
||||||
|
for ( i = 0 ; i < MAX_POWERUPS ; i++ ) {
|
||||||
|
//PKMOD - Ergodic 06/03/01 - add bean powerup timer for armor countdown immunity,
|
||||||
|
// ignore the beans powerup
|
||||||
|
if ( i == PW_BEANS )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
t = cg.snap->ps.powerups[i];
|
||||||
|
if ( t <= cg.time ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( t - cg.time >= POWERUP_BLINKS * POWERUP_BLINK_TIME ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( ( t - cg.time ) / POWERUP_BLINK_TIME != ( t - cg.oldTime ) / POWERUP_BLINK_TIME ) {
|
||||||
|
trap_S_StartSound( NULL, cg.snap->ps.clientNum, CHAN_ITEM, cgs.media.wearOffSound );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=====================
|
||||||
|
CG_AddBufferedSound
|
||||||
|
=====================
|
||||||
|
*/
|
||||||
|
void CG_AddBufferedSound( sfxHandle_t sfx ) {
|
||||||
|
if ( !sfx )
|
||||||
|
return;
|
||||||
|
cg.soundBuffer[cg.soundBufferIn] = sfx;
|
||||||
|
cg.soundBufferIn = (cg.soundBufferIn + 1) % MAX_SOUNDBUFFER;
|
||||||
|
if (cg.soundBufferIn == cg.soundBufferOut) {
|
||||||
|
cg.soundBufferOut++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=====================
|
||||||
|
CG_PlayBufferedSounds
|
||||||
|
=====================
|
||||||
|
*/
|
||||||
|
static void CG_PlayBufferedSounds( void ) {
|
||||||
|
if ( cg.soundTime < cg.time ) {
|
||||||
|
if (cg.soundBufferOut != cg.soundBufferIn && cg.soundBuffer[cg.soundBufferOut]) {
|
||||||
|
trap_S_StartLocalSound(cg.soundBuffer[cg.soundBufferOut], CHAN_ANNOUNCER);
|
||||||
|
cg.soundBuffer[cg.soundBufferOut] = 0;
|
||||||
|
cg.soundBufferOut = (cg.soundBufferOut + 1) % MAX_SOUNDBUFFER;
|
||||||
|
cg.soundTime = cg.time + 750;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//=========================================================================
|
||||||
|
|
||||||
|
/*
|
||||||
|
=================
|
||||||
|
CG_DrawActiveFrame
|
||||||
|
|
||||||
|
Generates and draws a game scene and status information at the given time.
|
||||||
|
=================
|
||||||
|
*/
|
||||||
|
void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demoPlayback ) {
|
||||||
|
int inwater;
|
||||||
|
|
||||||
|
cg.time = serverTime;
|
||||||
|
cg.demoPlayback = demoPlayback;
|
||||||
|
|
||||||
|
// update cvars
|
||||||
|
CG_UpdateCvars();
|
||||||
|
|
||||||
|
// if we are only updating the screen as a loading
|
||||||
|
// pacifier, don't even try to read snapshots
|
||||||
|
if ( cg.infoScreenText[0] != 0 ) {
|
||||||
|
CG_DrawInformation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// any looped sounds will be respecified as entities
|
||||||
|
// are added to the render list
|
||||||
|
trap_S_ClearLoopingSounds(qfalse);
|
||||||
|
|
||||||
|
// clear all the render lists
|
||||||
|
trap_R_ClearScene();
|
||||||
|
|
||||||
|
// set up cg.snap and possibly cg.nextSnap
|
||||||
|
CG_ProcessSnapshots();
|
||||||
|
|
||||||
|
// if we haven't received any snapshots yet, all
|
||||||
|
// we can draw is the information screen
|
||||||
|
if ( !cg.snap || ( cg.snap->snapFlags & SNAPFLAG_NOT_ACTIVE ) ) {
|
||||||
|
CG_DrawInformation();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// let the client system know what our weapon and zoom settings are
|
||||||
|
trap_SetUserCmdValue( cg.weaponSelect, cg.zoomSensitivity );
|
||||||
|
|
||||||
|
// this counter will be bumped for every valid scene we generate
|
||||||
|
cg.clientFrame++;
|
||||||
|
|
||||||
|
// update cg.predictedPlayerState
|
||||||
|
CG_PredictPlayerState();
|
||||||
|
|
||||||
|
// decide on third person view
|
||||||
|
cg.renderingThirdPerson = cg_thirdPerson.integer || (cg.snap->ps.stats[STAT_HEALTH] <= 0);
|
||||||
|
|
||||||
|
// build cg.refdef
|
||||||
|
inwater = CG_CalcViewValues();
|
||||||
|
|
||||||
|
// first person blend blobs, done after AnglesToAxis
|
||||||
|
if ( !cg.renderingThirdPerson ) {
|
||||||
|
CG_DamageBlendBlob();
|
||||||
|
}
|
||||||
|
|
||||||
|
// build the render lists
|
||||||
|
if ( !cg.hyperspace ) {
|
||||||
|
CG_AddPacketEntities(); // adter calcViewValues, so predicted player state is correct
|
||||||
|
CG_AddMarks();
|
||||||
|
CG_AddParticles ();
|
||||||
|
CG_AddLocalEntities();
|
||||||
|
}
|
||||||
|
CG_AddViewWeapon( &cg.predictedPlayerState );
|
||||||
|
|
||||||
|
// add buffered sounds
|
||||||
|
CG_PlayBufferedSounds();
|
||||||
|
|
||||||
|
// play buffered voice chats
|
||||||
|
CG_PlayBufferedVoiceChats();
|
||||||
|
|
||||||
|
// finish up the rest of the refdef
|
||||||
|
if ( cg.testModelEntity.hModel ) {
|
||||||
|
CG_AddTestModel();
|
||||||
|
}
|
||||||
|
cg.refdef.time = cg.time;
|
||||||
|
memcpy( cg.refdef.areamask, cg.snap->areamask, sizeof( cg.refdef.areamask ) );
|
||||||
|
|
||||||
|
// warning sounds when powerup is wearing off
|
||||||
|
CG_PowerupTimerSounds();
|
||||||
|
|
||||||
|
// update audio positions
|
||||||
|
trap_S_Respatialize( cg.snap->ps.clientNum, cg.refdef.vieworg, cg.refdef.viewaxis, inwater );
|
||||||
|
|
||||||
|
// make sure the lagometerSample and frame timing isn't done twice when in stereo
|
||||||
|
if ( stereoView != STEREO_RIGHT ) {
|
||||||
|
cg.frametime = cg.time - cg.oldTime;
|
||||||
|
if ( cg.frametime < 0 ) {
|
||||||
|
cg.frametime = 0;
|
||||||
|
}
|
||||||
|
cg.oldTime = cg.time;
|
||||||
|
CG_AddLagometerFrameInfo();
|
||||||
|
}
|
||||||
|
if (cg_timescale.value != cg_timescaleFadeEnd.value) {
|
||||||
|
if (cg_timescale.value < cg_timescaleFadeEnd.value) {
|
||||||
|
cg_timescale.value += cg_timescaleFadeSpeed.value * ((float)cg.frametime) / 1000;
|
||||||
|
if (cg_timescale.value > cg_timescaleFadeEnd.value)
|
||||||
|
cg_timescale.value = cg_timescaleFadeEnd.value;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cg_timescale.value -= cg_timescaleFadeSpeed.value * ((float)cg.frametime) / 1000;
|
||||||
|
if (cg_timescale.value < cg_timescaleFadeEnd.value)
|
||||||
|
cg_timescale.value = cg_timescaleFadeEnd.value;
|
||||||
|
}
|
||||||
|
if (cg_timescaleFadeSpeed.value) {
|
||||||
|
trap_Cvar_Set("timescale", va("%f", cg_timescale.value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// actually issue the rendering calls
|
||||||
|
CG_DrawActive( stereoView );
|
||||||
|
|
||||||
|
if ( cg_stats.integer ) {
|
||||||
|
CG_Printf( "cg.clientFrame:%i\n", cg.clientFrame );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
3472
quake3/source/code/cgame/cg_weapons.c
Normal file
3472
quake3/source/code/cgame/cg_weapons.c
Normal file
File diff suppressed because it is too large
Load diff
68
quake3/source/code/cgame/cgame.bat
Normal file
68
quake3/source/code/cgame/cgame.bat
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
set LIBRARY=
|
||||||
|
set INCLUDE=
|
||||||
|
|
||||||
|
mkdir vm
|
||||||
|
cd vm
|
||||||
|
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../../game/bg_misc.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../../game/bg_pmove.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../../game/bg_slidemove.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../../game/bg_lib.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../../game/q_math.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../../game/q_shared.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../cg_consolecmds.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../cg_draw.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../cg_drawtools.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../cg_effects.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../cg_ents.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../cg_event.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../cg_info.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../cg_localents.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../cg_main.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../cg_marks.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../cg_players.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../cg_playerstate.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../cg_predict.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../cg_scoreboard.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../cg_servercmds.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../cg_snapshot.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../cg_view.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../cg_weapons.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../../ui/ui_shared.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
lcc -DQ3_VM -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui ../cg_newdraw.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
|
||||||
|
q3asm -f ../cgame
|
||||||
|
|
||||||
|
rem copy the qvm to a staging area...
|
||||||
|
rem copy \quake3\baseq3\vm\cgame.qvm c:\workmb\pkarena31\pkarena0\vm\cgame.qvm
|
||||||
|
|
||||||
|
echo "Compilation was successful!"
|
||||||
|
|
||||||
|
:quit
|
||||||
|
cd ..
|
3
quake3/source/code/cgame/cgame.def
Normal file
3
quake3/source/code/cgame/cgame.def
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
EXPORTS
|
||||||
|
vmMain
|
||||||
|
dllEntry
|
344
quake3/source/code/cgame/cgame.dsp
Normal file
344
quake3/source/code/cgame/cgame.dsp
Normal file
|
@ -0,0 +1,344 @@
|
||||||
|
# Microsoft Developer Studio Project File - Name="cgame" - Package Owner=<4>
|
||||||
|
# Microsoft Developer Studio Generated Build File, Format Version 5.00
|
||||||
|
# ** DO NOT EDIT **
|
||||||
|
|
||||||
|
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
||||||
|
|
||||||
|
CFG=cgame - Win32 Debug TA
|
||||||
|
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
||||||
|
!MESSAGE use the Export Makefile command and run
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "cgame.mak".
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE You can specify a configuration when running NMAKE
|
||||||
|
!MESSAGE by defining the macro CFG on the command line. For example:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE NMAKE /f "cgame.mak" CFG="cgame - Win32 Debug TA"
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE Possible choices for configuration are:
|
||||||
|
!MESSAGE
|
||||||
|
!MESSAGE "cgame - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "cgame - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "cgame - Win32 Release TA" (based on\
|
||||||
|
"Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE "cgame - Win32 Debug TA" (based on "Win32 (x86) Dynamic-Link Library")
|
||||||
|
!MESSAGE
|
||||||
|
|
||||||
|
# Begin Project
|
||||||
|
# PROP Scc_ProjName ""$/MissionPack/code/cgame", NPAAAAAA"
|
||||||
|
# PROP Scc_LocalPath "."
|
||||||
|
CPP=cl.exe
|
||||||
|
MTL=midl.exe
|
||||||
|
RSC=rc.exe
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "cgame - Win32 Release"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "Release"
|
||||||
|
# PROP BASE Intermediate_Dir "Release"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release"
|
||||||
|
# PROP Intermediate_Dir "Release"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /G6 /W4 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||||
|
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
|
||||||
|
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
|
||||||
|
# ADD LINK32 /nologo /base:"0x30000000" /subsystem:windows /dll /map /machine:I386 /out:"../Release/cgamex86.dll"
|
||||||
|
# SUBTRACT LINK32 /debug
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "cgame - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "Debug"
|
||||||
|
# PROP BASE Intermediate_Dir "Debug"
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug"
|
||||||
|
# PROP Intermediate_Dir "Debug"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /G5 /MTd /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /ZI /c
|
||||||
|
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
|
||||||
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
|
||||||
|
# ADD LINK32 /nologo /base:"0x30000000" /subsystem:windows /dll /map /debug /machine:I386 /out:"../Debug/cgamex86.dll"
|
||||||
|
# SUBTRACT LINK32 /profile /nodefaultlib
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "cgame - Win32 Release TA"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 0
|
||||||
|
# PROP BASE Output_Dir "cgame___Win32_Release_TA"
|
||||||
|
# PROP BASE Intermediate_Dir "cgame___Win32_Release_TA"
|
||||||
|
# PROP BASE Ignore_Export_Lib 0
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 0
|
||||||
|
# PROP Output_Dir "Release_TA"
|
||||||
|
# PROP Intermediate_Dir "Release_TA"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /G6 /W4 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /FD /c
|
||||||
|
# ADD CPP /nologo /G6 /W4 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "MISSIONPACK" /YX /FD /c
|
||||||
|
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
|
||||||
|
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL"
|
||||||
|
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "NDEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 /nologo /base:"0x30000000" /subsystem:windows /dll /map /machine:I386 /out:"../Release/cgamex86.dll"
|
||||||
|
# SUBTRACT BASE LINK32 /debug
|
||||||
|
# ADD LINK32 /nologo /base:"0x30000000" /subsystem:windows /dll /map /machine:I386 /out:"../Release_TA/cgamex86.dll"
|
||||||
|
# SUBTRACT LINK32 /debug
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "cgame - Win32 Debug TA"
|
||||||
|
|
||||||
|
# PROP BASE Use_MFC 0
|
||||||
|
# PROP BASE Use_Debug_Libraries 1
|
||||||
|
# PROP BASE Output_Dir "cgame___Win32_Debug_TA"
|
||||||
|
# PROP BASE Intermediate_Dir "cgame___Win32_Debug_TA"
|
||||||
|
# PROP BASE Ignore_Export_Lib 0
|
||||||
|
# PROP BASE Target_Dir ""
|
||||||
|
# PROP Use_MFC 0
|
||||||
|
# PROP Use_Debug_Libraries 1
|
||||||
|
# PROP Output_Dir "Debug_TA"
|
||||||
|
# PROP Intermediate_Dir "Debug_TA"
|
||||||
|
# PROP Ignore_Export_Lib 0
|
||||||
|
# PROP Target_Dir ""
|
||||||
|
# ADD BASE CPP /nologo /G5 /MTd /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /ZI /c
|
||||||
|
# ADD CPP /nologo /G5 /MTd /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR /YX /FD /ZI /c
|
||||||
|
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
|
||||||
|
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL"
|
||||||
|
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
||||||
|
# ADD RSC /l 0x409 /d "_DEBUG"
|
||||||
|
BSC32=bscmake.exe
|
||||||
|
# ADD BASE BSC32 /nologo
|
||||||
|
# ADD BSC32 /nologo
|
||||||
|
LINK32=link.exe
|
||||||
|
# ADD BASE LINK32 /nologo /base:"0x30000000" /subsystem:windows /dll /map /debug /machine:I386 /out:"..\Debug/cgamex86.dll"
|
||||||
|
# SUBTRACT BASE LINK32 /profile /nodefaultlib
|
||||||
|
# ADD LINK32 /nologo /base:"0x30000000" /subsystem:windows /dll /map /debug /machine:I386 /def:".\cgame.def" /out:"..\Debug_TA\cgamex86.dll"
|
||||||
|
# SUBTRACT LINK32 /pdb:none
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# Begin Target
|
||||||
|
|
||||||
|
# Name "cgame - Win32 Release"
|
||||||
|
# Name "cgame - Win32 Debug"
|
||||||
|
# Name "cgame - Win32 Release TA"
|
||||||
|
# Name "cgame - Win32 Debug TA"
|
||||||
|
# Begin Group "Source Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "c"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\game\bg_lib.c
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "cgame - Win32 Release"
|
||||||
|
|
||||||
|
# PROP Exclude_From_Build 1
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "cgame - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP Exclude_From_Build 1
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "cgame - Win32 Release TA"
|
||||||
|
|
||||||
|
# PROP BASE Exclude_From_Build 1
|
||||||
|
# PROP Exclude_From_Build 1
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "cgame - Win32 Debug TA"
|
||||||
|
|
||||||
|
# PROP BASE Exclude_From_Build 1
|
||||||
|
# PROP Exclude_From_Build 1
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\game\bg_misc.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\game\bg_pmove.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\game\bg_slidemove.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_consolecmds.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_draw.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_drawtools.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_effects.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_ents.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_event.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_info.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_localents.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_main.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_marks.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_newDraw.c
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "cgame - Win32 Release"
|
||||||
|
|
||||||
|
# PROP Exclude_From_Build 1
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "cgame - Win32 Debug"
|
||||||
|
|
||||||
|
# PROP Exclude_From_Build 1
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "cgame - Win32 Release TA"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "cgame - Win32 Debug TA"
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_players.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_playerstate.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_predict.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_scoreboard.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_servercmds.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_snapshot.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_syscalls.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_view.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_weapons.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\game\q_math.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\game\q_shared.c
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\ui\ui_shared.c
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Group "Header Files"
|
||||||
|
|
||||||
|
# PROP Default_Filter "h"
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\game\bg_public.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_local.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cg_public.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\game\q_shared.h
|
||||||
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\game\surfaceflags.h
|
||||||
|
# End Source File
|
||||||
|
# End Group
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=.\cgame.def
|
||||||
|
|
||||||
|
!IF "$(CFG)" == "cgame - Win32 Release"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "cgame - Win32 Debug"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "cgame - Win32 Release TA"
|
||||||
|
|
||||||
|
!ELSEIF "$(CFG)" == "cgame - Win32 Debug TA"
|
||||||
|
|
||||||
|
# PROP Exclude_From_Build 1
|
||||||
|
|
||||||
|
!ENDIF
|
||||||
|
|
||||||
|
# End Source File
|
||||||
|
# End Target
|
||||||
|
# End Project
|
16
quake3/source/code/cgame/cgame.plg
Normal file
16
quake3/source/code/cgame/cgame.plg
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
--------------------Configuration: cgame - Win32 Debug TA--------------------
|
||||||
|
Begining build with project "C:\quake3\source\code\cgame\cgame.dsp", with item "cg_servercmds.c"
|
||||||
|
Active configuration is Win32 (x86) Dynamic-Link Library (based on Win32 (x86) Dynamic-Link Library)
|
||||||
|
|
||||||
|
|
||||||
|
Creating temp file "C:\DOCUME~1\brights\LOCALS~1\Temp\RSP81.tmp" with contents </nologo /G5 /MTd /W3 /GX /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FR"Debug_TA/" /Fp"Debug_TA/cgame.pch" /YX /Fo"Debug_TA/" /Fd"Debug_TA/" /FD /ZI /c
|
||||||
|
"C:\quake3\source\code\cgame\cg_servercmds.c"
|
||||||
|
>
|
||||||
|
Creating command line "cl.exe @C:\DOCUME~1\brights\LOCALS~1\Temp\RSP81.tmp"
|
||||||
|
Compiling...
|
||||||
|
Command line warning D4002 : ignoring unknown option '/ZI'
|
||||||
|
cg_servercmds.c
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cg_servercmds.obj - 0 error(s), 1 warning(s)
|
28
quake3/source/code/cgame/cgame.q3asm
Normal file
28
quake3/source/code/cgame/cgame.q3asm
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
-o "\quake3\baseq3\vm\cgame"
|
||||||
|
cg_main
|
||||||
|
..\cg_syscalls
|
||||||
|
cg_consolecmds
|
||||||
|
cg_draw
|
||||||
|
cg_drawtools
|
||||||
|
cg_effects
|
||||||
|
cg_ents
|
||||||
|
cg_event
|
||||||
|
cg_info
|
||||||
|
cg_localents
|
||||||
|
cg_marks
|
||||||
|
cg_players
|
||||||
|
cg_playerstate
|
||||||
|
cg_predict
|
||||||
|
cg_scoreboard
|
||||||
|
cg_servercmds
|
||||||
|
cg_snapshot
|
||||||
|
cg_view
|
||||||
|
cg_weapons
|
||||||
|
bg_slidemove
|
||||||
|
bg_pmove
|
||||||
|
bg_lib
|
||||||
|
bg_misc
|
||||||
|
q_math
|
||||||
|
q_shared
|
||||||
|
ui_shared
|
||||||
|
cg_newdraw
|
65
quake3/source/code/cgame/cgame_ta.bat
Normal file
65
quake3/source/code/cgame/cgame_ta.bat
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
rem make sure we have a safe environement
|
||||||
|
set LIBRARY=
|
||||||
|
set INCLUDE=
|
||||||
|
|
||||||
|
mkdir vm
|
||||||
|
cd vm
|
||||||
|
set cc=lcc -DQ3_VM -DMISSIONPACK -DCGAME -S -Wf-target=bytecode -Wf-g -I..\..\cgame -I..\..\game -I..\..\ui %1
|
||||||
|
|
||||||
|
%cc% ../../game/bg_misc.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../../game/bg_pmove.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../../game/bg_slidemove.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../../game/bg_lib.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../../game/q_math.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../../game/q_shared.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../cg_consolecmds.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../cg_draw.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../cg_drawtools.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../cg_effects.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../cg_ents.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../cg_event.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../cg_info.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../cg_localents.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../cg_main.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../cg_marks.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../cg_players.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../cg_playerstate.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../cg_predict.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../cg_scoreboard.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../cg_servercmds.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../cg_snapshot.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../cg_view.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../cg_weapons.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../../ui/ui_shared.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
%cc% ../cg_newdraw.c
|
||||||
|
@if errorlevel 1 goto quit
|
||||||
|
|
||||||
|
|
||||||
|
q3asm -f ../cgame_ta
|
||||||
|
:quit
|
||||||
|
cd ..
|
28
quake3/source/code/cgame/cgame_ta.q3asm
Normal file
28
quake3/source/code/cgame/cgame_ta.q3asm
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
-o "\quake3\missionpack\vm\cgame"
|
||||||
|
cg_main
|
||||||
|
..\cg_syscalls
|
||||||
|
cg_consolecmds
|
||||||
|
cg_draw
|
||||||
|
cg_drawtools
|
||||||
|
cg_effects
|
||||||
|
cg_ents
|
||||||
|
cg_event
|
||||||
|
cg_info
|
||||||
|
cg_localents
|
||||||
|
cg_marks
|
||||||
|
cg_players
|
||||||
|
cg_playerstate
|
||||||
|
cg_predict
|
||||||
|
cg_scoreboard
|
||||||
|
cg_servercmds
|
||||||
|
cg_snapshot
|
||||||
|
cg_view
|
||||||
|
cg_weapons
|
||||||
|
bg_slidemove
|
||||||
|
bg_pmove
|
||||||
|
bg_lib
|
||||||
|
bg_misc
|
||||||
|
q_math
|
||||||
|
q_shared
|
||||||
|
ui_shared
|
||||||
|
cg_newdraw
|
209
quake3/source/code/cgame/tr_types.h
Normal file
209
quake3/source/code/cgame/tr_types.h
Normal file
|
@ -0,0 +1,209 @@
|
||||||
|
// Copyright (C) 1999-2000 Id Software, Inc.
|
||||||
|
//
|
||||||
|
#ifndef __TR_TYPES_H
|
||||||
|
#define __TR_TYPES_H
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_DLIGHTS 32 // can't be increased, because bit flags are used on surfaces
|
||||||
|
#define MAX_ENTITIES 1023 // can't be increased without changing drawsurf bit packing
|
||||||
|
|
||||||
|
// renderfx flags
|
||||||
|
#define RF_MINLIGHT 1 // allways have some light (viewmodel, some items)
|
||||||
|
#define RF_THIRD_PERSON 2 // don't draw through eyes, only mirrors (player bodies, chat sprites)
|
||||||
|
#define RF_FIRST_PERSON 4 // only draw through eyes (view weapon, damage blood blob)
|
||||||
|
#define RF_DEPTHHACK 8 // for view weapon Z crunching
|
||||||
|
#define RF_NOSHADOW 64 // don't add stencil shadows
|
||||||
|
|
||||||
|
#define RF_LIGHTING_ORIGIN 128 // use refEntity->lightingOrigin instead of refEntity->origin
|
||||||
|
// for lighting. This allows entities to sink into the floor
|
||||||
|
// with their origin going solid, and allows all parts of a
|
||||||
|
// player to get the same lighting
|
||||||
|
#define RF_SHADOW_PLANE 256 // use refEntity->shadowPlane
|
||||||
|
#define RF_WRAP_FRAMES 512 // mod the model frames by the maxframes to allow continuous
|
||||||
|
// animation without needing to know the frame count
|
||||||
|
|
||||||
|
// refdef flags
|
||||||
|
#define RDF_NOWORLDMODEL 1 // used for player configuration screen
|
||||||
|
#define RDF_HYPERSPACE 4 // teleportation effect
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
vec3_t xyz;
|
||||||
|
float st[2];
|
||||||
|
byte modulate[4];
|
||||||
|
} polyVert_t;
|
||||||
|
|
||||||
|
typedef struct poly_s {
|
||||||
|
qhandle_t hShader;
|
||||||
|
int numVerts;
|
||||||
|
polyVert_t *verts;
|
||||||
|
} poly_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RT_MODEL,
|
||||||
|
RT_POLY,
|
||||||
|
RT_SPRITE,
|
||||||
|
RT_BEAM,
|
||||||
|
RT_RAIL_CORE,
|
||||||
|
RT_RAIL_RINGS,
|
||||||
|
RT_LIGHTNING,
|
||||||
|
RT_PORTALSURFACE, // doesn't draw anything, just info for portals
|
||||||
|
|
||||||
|
RT_MAX_REF_ENTITY_TYPE
|
||||||
|
} refEntityType_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
refEntityType_t reType;
|
||||||
|
int renderfx;
|
||||||
|
|
||||||
|
qhandle_t hModel; // opaque type outside refresh
|
||||||
|
|
||||||
|
// most recent data
|
||||||
|
vec3_t lightingOrigin; // so multi-part models can be lit identically (RF_LIGHTING_ORIGIN)
|
||||||
|
float shadowPlane; // projection shadows go here, stencils go slightly lower
|
||||||
|
|
||||||
|
vec3_t axis[3]; // rotation vectors
|
||||||
|
qboolean nonNormalizedAxes; // axis are not normalized, i.e. they have scale
|
||||||
|
float origin[3]; // also used as MODEL_BEAM's "from"
|
||||||
|
int frame; // also used as MODEL_BEAM's diameter
|
||||||
|
|
||||||
|
// previous data for frame interpolation
|
||||||
|
float oldorigin[3]; // also used as MODEL_BEAM's "to"
|
||||||
|
int oldframe;
|
||||||
|
float backlerp; // 0.0 = current, 1.0 = old
|
||||||
|
|
||||||
|
// texturing
|
||||||
|
int skinNum; // inline skin index
|
||||||
|
qhandle_t customSkin; // NULL for default skin
|
||||||
|
qhandle_t customShader; // use one image for the entire thing
|
||||||
|
|
||||||
|
// misc
|
||||||
|
byte shaderRGBA[4]; // colors used by rgbgen entity shaders
|
||||||
|
float shaderTexCoord[2]; // texture coordinates used by tcMod entity modifiers
|
||||||
|
float shaderTime; // subtracted from refdef time to control effect start times
|
||||||
|
|
||||||
|
// extra sprite information
|
||||||
|
float radius;
|
||||||
|
float rotation;
|
||||||
|
} refEntity_t;
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_RENDER_STRINGS 8
|
||||||
|
#define MAX_RENDER_STRING_LENGTH 32
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int x, y, width, height;
|
||||||
|
float fov_x, fov_y;
|
||||||
|
vec3_t vieworg;
|
||||||
|
vec3_t viewaxis[3]; // transformation matrix
|
||||||
|
|
||||||
|
// time in milliseconds for shader effects and other time dependent rendering issues
|
||||||
|
int time;
|
||||||
|
|
||||||
|
int rdflags; // RDF_NOWORLDMODEL, etc
|
||||||
|
|
||||||
|
// 1 bits will prevent the associated area from rendering at all
|
||||||
|
byte areamask[MAX_MAP_AREA_BYTES];
|
||||||
|
|
||||||
|
// text messages for deform text shaders
|
||||||
|
char text[MAX_RENDER_STRINGS][MAX_RENDER_STRING_LENGTH];
|
||||||
|
} refdef_t;
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
STEREO_CENTER,
|
||||||
|
STEREO_LEFT,
|
||||||
|
STEREO_RIGHT
|
||||||
|
} stereoFrame_t;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** glconfig_t
|
||||||
|
**
|
||||||
|
** Contains variables specific to the OpenGL configuration
|
||||||
|
** being run right now. These are constant once the OpenGL
|
||||||
|
** subsystem is initialized.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
TC_NONE,
|
||||||
|
TC_S3TC
|
||||||
|
} textureCompression_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GLDRV_ICD, // driver is integrated with window system
|
||||||
|
// WARNING: there are tests that check for
|
||||||
|
// > GLDRV_ICD for minidriverness, so this
|
||||||
|
// should always be the lowest value in this
|
||||||
|
// enum set
|
||||||
|
GLDRV_STANDALONE, // driver is a non-3Dfx standalone driver
|
||||||
|
GLDRV_VOODOO // driver is a 3Dfx standalone driver
|
||||||
|
} glDriverType_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
GLHW_GENERIC, // where everthing works the way it should
|
||||||
|
GLHW_3DFX_2D3D, // Voodoo Banshee or Voodoo3, relevant since if this is
|
||||||
|
// the hardware type then there can NOT exist a secondary
|
||||||
|
// display adapter
|
||||||
|
GLHW_RIVA128, // where you can't interpolate alpha
|
||||||
|
GLHW_RAGEPRO, // where you can't modulate alpha on alpha textures
|
||||||
|
GLHW_PERMEDIA2 // where you don't have src*dst
|
||||||
|
} glHardwareType_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char renderer_string[MAX_STRING_CHARS];
|
||||||
|
char vendor_string[MAX_STRING_CHARS];
|
||||||
|
char version_string[MAX_STRING_CHARS];
|
||||||
|
char extensions_string[BIG_INFO_STRING];
|
||||||
|
|
||||||
|
int maxTextureSize; // queried from GL
|
||||||
|
int maxActiveTextures; // multitexture ability
|
||||||
|
|
||||||
|
int colorBits, depthBits, stencilBits;
|
||||||
|
|
||||||
|
glDriverType_t driverType;
|
||||||
|
glHardwareType_t hardwareType;
|
||||||
|
|
||||||
|
qboolean deviceSupportsGamma;
|
||||||
|
textureCompression_t textureCompression;
|
||||||
|
qboolean textureEnvAddAvailable;
|
||||||
|
|
||||||
|
int vidWidth, vidHeight;
|
||||||
|
// aspect is the screen's physical width / height, which may be different
|
||||||
|
// than scrWidth / scrHeight if the pixels are non-square
|
||||||
|
// normal screens should be 4/3, but wide aspect monitors may be 16/9
|
||||||
|
float windowAspect;
|
||||||
|
|
||||||
|
int displayFrequency;
|
||||||
|
|
||||||
|
// synonymous with "does rendering consume the entire screen?", therefore
|
||||||
|
// a Voodoo or Voodoo2 will have this set to TRUE, as will a Win32 ICD that
|
||||||
|
// used CDS.
|
||||||
|
qboolean isFullscreen;
|
||||||
|
qboolean stereoEnabled;
|
||||||
|
qboolean smpActive; // dual processor
|
||||||
|
} glconfig_t;
|
||||||
|
|
||||||
|
// FIXME: VM should be OS agnostic .. in theory
|
||||||
|
|
||||||
|
/*
|
||||||
|
#ifdef Q3_VM
|
||||||
|
|
||||||
|
#define _3DFX_DRIVER_NAME "Voodoo"
|
||||||
|
#define OPENGL_DRIVER_NAME "Default"
|
||||||
|
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(Q3_VM) || defined(_WIN32)
|
||||||
|
|
||||||
|
#define _3DFX_DRIVER_NAME "3dfxvgl"
|
||||||
|
#define OPENGL_DRIVER_NAME "opengl32"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define _3DFX_DRIVER_NAME "libMesaVoodooGL.so"
|
||||||
|
// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=524
|
||||||
|
#define OPENGL_DRIVER_NAME "libGL.so.1"
|
||||||
|
|
||||||
|
#endif // !defined _WIN32
|
||||||
|
|
||||||
|
#endif // __TR_TYPES_H
|
BIN
quake3/source/code/game/Debug_TA/ai_chat.obj
Normal file
BIN
quake3/source/code/game/Debug_TA/ai_chat.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/game/Debug_TA/ai_chat.sbr
Normal file
BIN
quake3/source/code/game/Debug_TA/ai_chat.sbr
Normal file
Binary file not shown.
BIN
quake3/source/code/game/Debug_TA/ai_cmd.obj
Normal file
BIN
quake3/source/code/game/Debug_TA/ai_cmd.obj
Normal file
Binary file not shown.
BIN
quake3/source/code/game/Debug_TA/ai_cmd.sbr
Normal file
BIN
quake3/source/code/game/Debug_TA/ai_cmd.sbr
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue