Compare commits

..
172 Commits
Author SHA1 Message Date
OM 312332ac5e Fixed weapon commands not working as intended 2023-05-23 01:57:18 +02:00
OM 27dcbdb49a Removed **HOLSTERWEAPON** state condition (useless) 2023-05-23 01:56:19 +02:00
OM 96ecb4535a **CG_WeaponCommandButtonBits** get iWeaponCommand before setting it to 0 2023-05-23 01:55:54 +02:00
OM f1f1f6e073 Fixed stackoverflow issues 2023-05-23 00:17:03 +02:00
OM 55dc84d932 Fixed CGM values for AA and SH/BT 2023-05-23 00:08:12 +02:00
OM 6c874641d7 Increased **MAX_RELIABLE_COMMANDS** to 512 2023-05-22 23:28:30 +02:00
OM fe01523cb1 Using viewmodel constants from bg_public.h 2023-05-22 23:28:18 +02:00
OM 827bd38603 Fixed bits value on spearhead/breakthrough 2023-05-22 23:28:01 +02:00
OM 862142b6c4 Added farplane stuff from spearhead/breakthrough (this fixes client version >=2.0 rendering maps incorrectly) 2023-05-22 23:27:40 +02:00
OM 014e86747f Added a new screenshot 2023-05-22 18:01:11 +02:00
OM 08057f52bc Fixed bad morph/weight index on ARM 2023-05-22 18:00:58 +02:00
OM d3870ccf45 Compilation fixes for ARM 2023-05-22 17:33:26 +02:00
OM e54f4a65f9 altname fix 2023-05-22 13:44:37 +02:00
OM a69aa0830a Removed **Com_Error** assertion on debug builds 2023-05-22 13:37:07 +02:00
OM fe8170e102 Added MESSAGE_CHAT_GREEN (Spearhead and Breakthrough) 2023-05-22 13:07:37 +02:00
OM c660e0162f Added compressed textures support 2023-05-22 13:02:14 +02:00
OM 55ad4dacdd Added DDS support 2023-05-22 13:01:52 +02:00
OM dd0799b52f Implemented printdeathmsg 2023-05-22 13:01:38 +02:00
OM d546dd9895 Incremented patch number 2023-05-22 12:31:50 +02:00
OM 389da58ec5 Fixed the scoreboard still showing after the intermission 2023-05-22 12:31:38 +02:00
OM 4e3eb02915 Call **ForceHide** instead of **ShowMenu** in **UI_RemoveHud_f** (this fixes hud elements like stopwatch not hidding) 2023-05-22 12:31:21 +02:00
OM 756198a02c **CG_Stopwatch_f** behavior is different on Spearhead and Breakthrough servers 2023-05-22 12:30:42 +02:00
OM 9a6e7f23f9 **CG_DrawStopwatch** Refactor 2023-05-22 12:30:20 +02:00
OM c4aca55b1a Minor fixes 2023-05-22 02:38:43 +02:00
OM 96bf729c54 (reverted to previous version number) 2023-05-22 02:20:33 +02:00
OM edcf521506 Patch number incremented 2023-05-22 02:16:56 +02:00
OM 9e7991f4b1 Load JPEG before TGA 2023-05-22 02:16:21 +02:00
OM 86e7a24b38 Fixed a nasty bug that can freeze/crash the game 2023-05-22 01:59:06 +02:00
OM ff587a8444 Health draw fix 2023-05-22 01:58:51 +02:00
OM c3e98ed681 Fixed **CG_DrawSpectatorView** for Spearhead and Breakthrough 2023-05-22 01:50:53 +02:00
OM cc2d698fe2 Scoreboard fix for Spearhead and Breakthrough 2023-05-22 01:45:09 +02:00
OM 420161095f Parse **CS_PLAYERS** 2023-05-22 01:44:59 +02:00
OM 58b0d335e7 Implemented **CG_PlayerTeamUpdate** 2023-05-22 01:44:35 +02:00
OM ce336e8962 Userinfo was never updating 2023-05-22 01:44:19 +02:00
OM 5b72eb189a pm_flags fix on SH/BT 2023-05-22 01:44:01 +02:00
OM 7600d3ca02 Fixed localization returning the same buffer 2023-05-22 01:43:52 +02:00
OM 8c3be9d549 Changed version number to reflect the fix 2023-05-21 22:55:38 +02:00
OM 2ddb534321 Updated LAYOUT.md 2023-05-21 22:55:13 +02:00
OM 21a1f61b04 small fix 2023-05-21 22:39:26 +02:00
OM 7219848655 Increased **MAX_GAMESTATE_CHARS** (41952 on Breakthrough) 2023-05-21 22:31:19 +02:00
OM 4695449fc7 Added a documentation on compiling for Spearhead or Breakthrough 2023-05-21 22:30:51 +02:00
OM af3dd2602b Compilation warnings fixes 2023-05-21 22:30:35 +02:00
OM 5bba5abece Added README note 2023-05-21 22:10:27 +02:00
OM bdcb6c42b6 Parse includes, depending on the server type 2023-05-21 22:07:42 +02:00
OM 0fe01d23d6 Fixed tag_num being -1 and *MSG_ReadPackedAngle* setting the wrong angle value 2023-05-21 22:07:09 +02:00
OM fc675e4064 Fixed authorization stuck 2023-05-21 22:06:42 +02:00
OM a29af7c3f6 Added Screenshot (Spearhead expansion) 2023-05-21 21:22:51 +02:00
OM 732872f433 Updated README 2023-05-21 21:22:02 +02:00
OM 04b5fdb934 Added Spearhead/Breakthrough client support 2023-05-21 21:21:20 +02:00
OM e23ce01d19 Added getKey/authorizeThis 2023-05-21 21:21:07 +02:00
OM 648dc395e7 Fixed compilation errors 2023-05-21 20:07:28 +02:00
OM ab2a26a14e Added support for *Team Assault* and *Team Tactics* 2023-05-21 19:59:36 +02:00
OM 238e94b4d5 Don't assert if *cls* is NULL 2023-05-21 19:59:12 +02:00
OM 0c18e0e26c Exports *UI_UpdateCenterPrint* and *UI_UpdateLocationPrint* 2023-05-21 19:58:59 +02:00
OM 7085d60d02 Added Team Tactics features 2023-05-21 19:58:43 +02:00
OM 3933e63044 Fixed crash in LoopSound when tiki's alias list is NULL 2023-05-21 19:57:45 +02:00
OM 342552c349 Process lightmap coord array on static models 2023-05-21 02:48:57 +02:00
OM 9addff08ce Bind if the texture is a lightmap 2023-05-21 02:48:41 +02:00
OM 2ff1071115 Export *R_PrintInfoWorldtris* 2023-05-21 02:43:07 +02:00
OM 49f4ac66ab Added *R_DrawLensFlares* 2023-05-21 02:40:50 +02:00
OM 7761cbd74c Implemented *RB_SetupStaticModelGridLighting* and *RB_Static_BuildDLights* 2023-05-21 02:40:44 +02:00
OM 103debcf6b Key bind string was not working as intended 2023-05-21 02:11:02 +02:00
OM 526ab8071c Changed version patch number 2023-05-21 02:10:20 +02:00
OM ac45f20fa6 Added *UploadCompressed* (although useless) + *force32bit* support in *Upload32* 2023-05-21 02:05:48 +02:00
OM a45b36f2f3 *RB_BeginSurface*: Don't set the shadertime here 2023-05-21 02:05:22 +02:00
OM bea35d28fc Added RefreshShaderNoMip 2023-05-21 02:05:06 +02:00
OM bb71f84985 Fixed sky seams 2023-05-21 02:04:47 +02:00
OM 2f62e61dc8 Using 1.875 instead of 1.0 2023-05-21 02:04:09 +02:00
OM dceceb976d Added qglCompressedTexImage 2023-05-21 02:03:38 +02:00
OM 59bf9fbd54 Fix CL_Vid_Restart_f for UI 2023-05-21 02:03:18 +02:00
OM a1cd6f2746 Fixed wrong VSS source allocation 2023-05-21 00:29:37 +02:00
OM 76178064a0 Drastically reduced compiler warnings on clang 2023-05-21 00:29:26 +02:00
OM 31ac3f7096 Using the standard version semantic 2023-05-21 00:01:27 +02:00
OM 545dc19811 Set console font to verdana-12 2023-05-21 00:01:04 +02:00
OM 5f598cf1f9 Fixed the buttons not drawing as intended 2023-05-21 00:00:46 +02:00
OM 4e66f2482f Fixed minimize / maximize buttons not working/showing as intended 2023-05-21 00:00:27 +02:00
OM f873fd447f Fixed vertical scrolling color 2023-05-20 23:59:54 +02:00
OM a4123f65b3 Implemented UIStatus 2023-05-20 23:59:44 +02:00
OM 93e56d968e Added clampmapx / clampmapy support
Don't determine sort order / fog color adjustment
2023-05-20 21:14:17 +02:00
OM b4e22d3040 set *r_ignoreFastPath* to 0 by default 2023-05-20 21:12:00 +02:00
OM 351f601986 Implemented *bLoadForMap* and fixed subtitle/maps parsing with *alias / aliascache* 2023-05-20 20:40:44 +02:00
OM 41fdd28d8b Refactored *Alias_ListAddParms* 2023-05-20 20:40:14 +02:00
OM d7c6cc0157 Removed scratchimage array 2023-05-20 19:33:16 +02:00
OM f1b83f1dab Added more rgbgen support 2023-05-20 19:33:00 +02:00
OM bb401d8d3c now sets tr.needsLightScale 2023-05-20 19:32:47 +02:00
OM 8bb9cd46f8 RB_SurfaceFace renders with dlight 2023-05-20 19:32:29 +02:00
OM c27695247e drawSurf sprite check fix 2023-05-20 19:32:09 +02:00
OM 7b9835a118 Corrected terrain lightmap 2023-05-20 19:31:51 +02:00
OM 2dc75b7527 Added lightmap grid data support 2023-05-20 19:30:12 +02:00
OM 6c577a7251 Fixed angle values 2023-05-20 19:29:38 +02:00
OM 5031402c2c CL_Vid_Restart_f: check if allowed, and call UI resolution change 2023-05-20 19:29:26 +02:00
OM a4bd37af8c Fixed buttons 2023-05-20 19:29:02 +02:00
OM 4dc60b9aa4 Added lighting-grid / sphere light basic implementation 2023-05-20 17:02:01 +02:00
OM ce89399824 Fixed unix compilation errors 2023-05-20 16:14:53 +02:00
OM b92d2972f6 Added RDF_FULLBRIGHT 2023-05-20 16:14:12 +02:00
OM f53680983b Spelling fix 2023-05-20 15:09:43 +02:00
OM d6fd337a07 Terrain crash fix 2023-05-20 14:57:14 +02:00
OM 95230a8d0a Added list destructor 2023-05-20 14:57:06 +02:00
OM 04524e9de9 Fixed huddraw_alpha and huddraw_color not working 2023-05-20 14:39:15 +02:00
OM df4f6f9515 Fixed crash due to null m_spawnthing 2023-05-20 14:38:54 +02:00
OM e9c7a1f959 Changed version number to 0.51 2023-05-20 02:19:35 +02:00
OM c4502469f4 Partially implemented UIListBox and UIList 2023-05-20 02:15:52 +02:00
OM c2cb15a1d1 Implemented UIListCtrl 2023-05-20 01:52:31 +02:00
OM 4d108a272f The scoreboard is now properly working 2023-05-20 01:20:20 +02:00
OM f523c32044 Partial implementation of UIList 2023-05-20 01:19:17 +02:00
OM 5ac5632e59 Export *CL_FinishedIntro* and *UI_StartStageKeyEvent* 2023-05-20 01:02:14 +02:00
OM 80f3296854 *CL_GetSnapshot* will take parent entities into account 2023-05-20 01:01:54 +02:00
OM 1b1433dd1b Removed useless cgame fields 2023-05-20 01:00:08 +02:00
OM 7647bbaf36 *CL_KeyEvent*: call *UI_StartStageKeyEvent* if intro hasn't finished 2023-05-20 00:59:48 +02:00
OM f00fd281b3 Added *TIKI_CG_Command_ProcessFile* 2023-05-20 00:59:21 +02:00
OM b5ea1ddb53 Added weapon command button bits from cgame module 2023-05-19 23:15:45 +02:00
OM b16ce90be3 Added *UI_LoadResource* calls 2023-05-19 23:15:24 +02:00
OM 4c0f7a34de Updated BUTTON ucmd flags 2023-05-19 23:15:06 +02:00
OM 2e11cd4ea2 *CG_Command_ProcessFile*: call *cgi.LoadResource* to update the UI while loading 2023-05-19 21:34:59 +02:00
OM c2ad608508 Fixed parameters of *CG_PermanentMark* 2023-05-19 21:34:36 +02:00
OM 5ec8c901e2 Using float instead of long double in *CG_RegisterSounds* 2023-05-19 21:34:18 +02:00
OM e6bbbdb79e Updated URLs in the README file 2023-05-19 21:33:58 +02:00
OM f5fa8d15d1 Made loading screens work 2023-05-19 21:33:02 +02:00
OM 7aee02ba8d Implemented *Sys_PumpMessageLoop* 2023-05-19 21:32:51 +02:00
OM cf51e14cf5 Added FPS counter 2023-05-19 20:52:10 +02:00
OM 7fb383c810 Updated README with new screenshot 2023-05-19 20:51:51 +02:00
OM 34f66963e3 Implemented DrawStatCompass 2023-05-19 19:26:46 +02:00
OM 6059063b67 Added "constant" parameter for "rgbGen" 2023-05-19 17:48:24 +02:00
OM 8bf57017ac Proper implementation of *RE_AddPolyToScene*
+ Increased *MAX_POLYS* and *MAX_POLYVERTS*
2023-05-19 17:48:09 +02:00
OM 9f1d35a11b Statbar fix
Implemented *UIFakkLabel::DrawStatbar*
2023-05-19 17:34:01 +02:00
OM aa51987077 Moved *BG_EvaluateTrajectory* from *game/bg_misc.cpp* to *cgame/cg_ents.c* 2023-05-19 17:27:38 +02:00
OM 64055d2580 Using RT_MODEL instead of ET_MODELANIM_SKEL 2023-05-19 16:59:44 +02:00
OM 45e82c590e Set numSpheresUsed to 0 2023-05-19 16:59:20 +02:00
OM 0c92890ef2 Implemented CGEN_STATIC 2023-05-19 16:59:08 +02:00
OM 03e8a64283 Added parent support in *RE_AddRefEntityToScene* 2023-05-19 16:58:46 +02:00
OM 4e14535f08 Fixed stats not drawing properly 2023-05-19 15:44:42 +02:00
OM 356e7c51fc Fixed widget alignment problem 2023-05-19 15:44:31 +02:00
OM 52a146d664 Updated README (added screenshot) 2023-05-19 14:09:03 +02:00
OM 76f107230c Exchanged SURF_NOLIGHTMAP and SURF_HINT 2023-05-19 13:57:35 +02:00
OM 4a49b15649 Removed CONTENTS_FOG
Added more surface params
2023-05-19 13:56:07 +02:00
OM 6c448694b6 Fixed static models color rendering 2023-05-19 13:40:29 +02:00
OM 34a1cee89b Made sure to unpack static models correctly 2023-05-19 13:40:18 +02:00
OM 29239dadfa Don't call ri.Hunk_Alloc when there are no texmods 2023-05-19 13:40:03 +02:00
OM e5a4574f92 Added *R_DistanceCullPointAndRadius* 2023-05-19 13:39:31 +02:00
OM 2d70547f9d Cleanup 2023-05-19 03:21:04 +02:00
OM f6279e8c17 *R_RecursiveWorldNode* now take the fog frustum into account, it also calls *R_AddPermanentMarkFragmentSurfaces* and set the vis static models 2023-05-19 03:20:50 +02:00
OM 18ade839c6 Added more shader commands
More fox support
2023-05-19 03:19:56 +02:00
OM b72eb8c6cc Using PLANE_NON_AXIAL instead of 3 2023-05-19 03:13:37 +02:00
OM e0446db81d Added one more mark function 2023-05-19 03:13:23 +02:00
OM a8bb9aaa77 Using qglFogi instead 2023-05-19 03:12:55 +02:00
OM 6595c3c673 Added sprites and ter marks to the render scene 2023-05-19 02:12:03 +02:00
OM 4ecf3195a5 Added *R_CullLocalBoxOffset* 2023-05-19 02:11:45 +02:00
OM 02f0e309e3 Implemented *R_ClearRealDlights*, *R_UploadDlights* and *R_AllocLMBlock* 2023-05-19 02:11:28 +02:00
OM 0fdfcf48f9 Added *RB_ComputeShadowVolume* (not implemented) 2023-05-19 02:10:56 +02:00
OM e9b5c7efd5 Initialize extension and level marks
Initialize the font debug string
2023-05-19 02:10:38 +02:00
OM 2a32b75815 Added GL flags 2023-05-19 02:10:19 +02:00
OM d966afe4ef Added *g_bInfoworldtris* 2023-05-19 02:10:03 +02:00
OM 92e2d42e19 Pre-added marks functions 2023-05-19 02:09:28 +02:00
OM 58e5e3fd63 Added multi-texture GL values
Don't iterate the stage if it has a skyAlpha gen near invisibility
2023-05-19 02:09:13 +02:00
OM b61c7b3988 Fog fixes 2023-05-19 02:08:32 +02:00
OM ee030f27e2 Early implementation of fog and sky portal 2023-05-19 00:29:13 +02:00
OM 02df95fc21 Updated the README file 2023-05-18 20:54:12 +02:00
OM 03100b47c1 Set the project name to openmohaa 2023-05-18 20:24:09 +02:00
OM 67444b0f15 Fixed sound being muted on startup 2023-05-18 20:21:38 +02:00
OM f6ae9a2b43 Incremented the version number 2023-05-18 20:16:19 +02:00
OM 98cd85bc9a Fixed compilation under Linux 2023-05-18 20:07:54 +02:00
OM 83a83b08f6 Export PDB of app & modules 2023-05-18 19:56:46 +02:00
OM 448e9010dc Fixed alias random indexes being wrong 2023-05-18 19:47:50 +02:00
OM ce69ed75f7 Reverted to Quake 3 sound system 2023-05-18 19:47:37 +02:00
OM 6ac70d6b7c Fixed terrain patch not drawing properly 2023-05-18 18:51:45 +02:00
OM 4f588d939d Prevent spawning a tempmodel that has the world as a tempmodel 2023-05-18 18:45:25 +02:00
OM f6ebdd1998 Better multitexture / bundle support 2023-05-18 18:17:32 +02:00
OM 7438dd709c Fixed terrain unpacking 2023-05-18 18:17:18 +02:00
OM 1207b46937 Fixed terrains vertices being wrongly rendered 2023-05-18 17:15:52 +02:00
OM 497f853171 Fixed terrain varnodes being badly loaded 2023-05-18 17:14:00 +02:00
OM 4984f8b925 nextBundle fix 2023-05-18 16:40:17 +02:00
OM a1d581df39 Introducing full LOD terrain support 2023-05-18 14:41:37 +02:00
162 changed files with 11580 additions and 9400 deletions

No files matched your search

+2
View File
@@ -1,4 +1,6 @@
build
mohaa-re
out
Makefile.local
*.swp
*tags
+6 -2
View File
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.5)
project(omohaaded)
project(openmohaa)
include(TargetArch.cmake)
@@ -205,7 +205,8 @@ if(WIN32)
endif()
target_link_libraries(omohaaded PRIVATE wsock32 ws2_32)
target_link_libraries(omohaaded PRIVATE winmm)
INSTALL(FILES $<TARGET_PDB_FILE:fgame> DESTINATION "${TARGET_BASE_GAME}" OPTIONAL)
INSTALL(FILES $<TARGET_PDB_FILE:omohaaded> DESTINATION "./" OPTIONAL)
elseif(UNIX)
find_package(Threads)
@@ -280,6 +281,9 @@ if (WITH_CLIENT)
target_link_libraries(openmohaa PRIVATE wsock32 ws2_32)
target_link_libraries(openmohaa PRIVATE winmm)
INSTALL(FILES $<TARGET_PDB_FILE:cgame> DESTINATION "${TARGET_BASE_GAME}" OPTIONAL)
INSTALL(FILES $<TARGET_PDB_FILE:openmohaa> DESTINATION "./" OPTIONAL)
elseif(UNIX)
find_package(OpenGL REQUIRED)
find_package(GLUT REQUIRED)
+4 -3
View File
@@ -2,22 +2,23 @@
| Path | Description |
| ---------------------|-------------------------------------------------------------------
| build/ | Output files |
| code/ | OpenMoHAA source code |
| code/cgame | Client game code |
| code/client | Client (network stuff, snapshots, etc) |
| code/game | Server game code (game logic stuff, etc) |
| code/gamespy | Gamespy SDK |
| code/mohui | MoHAA User Interface |
| code/null | Null redirector (used by the OpenMoHAA Dedicated Server) |
| code/parser | Flex/Bison parser |
| code/qcommon | Global shared stuff such as maths |
| code/renderer | OpenMoHAA renderer |
| code/sdl(12) | SDL code |
| code/script | Script engine |
| code/server | Server code (networkn snapshots, handling clients etc) |
| code/server | Server code (network, snapshots, handling clients etc) |
| code/skeletor | Skeleton model engine |
| code/sys | Main application system |
| code/tiki | Complete TIKI engine |
| code/uilib | UI library (Ubertools stuff) |
| code/{win32,unix} | Platform-specific code |
| docker | Docker files, for compiling on various linux versions |
| docs | Documentation stuff |
| misc/ | Project stuff, definition files and various resources stuff. |
+37 -13
View File
@@ -14,28 +14,38 @@
## Current State
OpenMoHAA is still in its early days.
### Server
The server version can successfully be built. There are few unimplemented stuff from the game library :
The server version can successfully be built.
Some stuff are not working as intended, such as Actor or Vehicle. These systems are both almost fully implemented, but not really in stable state.
- Actor
- Vehicle
Overall the server part and the game module are almost fully implemented, but the stability may vary, there may be some minor bugs and crashes.
### Client
There is currently no client build because the UI code is currently unimplemented. Here is what's missing or unimplemented :
The client version of OpenMoHAA is partially implemented and not stable currently. The cgame module is partially implemented as well, but is compatible with the original MOH:AA game. Credits to **Heavy Metal: F.A.K.K. 2**'s SDK for the cgame module.
- rendering (mostly advanced)
- sound (must be reworked)
- UI
Here is the current working state for each part of the engine:
Using CMake, the client build and successfully be built by adding `-DWITH_CLIENT=1`
| Part name | Full | Almost | Half | Early | Bad | Not working | Comment |
|-------------------------|------|--------|------|-------|-----|-------------|-------------------------------------------------------------------|
| Audio | | | | | x | | Very basic implementation from Quake III |
| CG Module | | x | | | | | Missing FX, Marks and decals |
| Client | | | x | | | | Missing GameSpy, server list, binds, map picker, ... |
| Collision | x | | | | | | |
| Model/TIKI/Skeletor | x | | | | | | |
| Renderer | | | | x | | | Missing ghost, marks, sphere lights, sky portal, sun flare, swipe |
| Server | | x | | | | | Probably a few bugs remaining |
| Server module (fgame) | | x | | | | | Actor, vehicle, and few gameplay bugs |
| UI | | | | x | | | Has core features only (menu, widgets, console, hud, urc loading) |
The client game module (cgame) is partially implemented, and is compatible with the original MOH:AA module.
NOTE: Both client and server version can be compiled to target **Medal of Honor: Spearhead** and **Medal of Honor: Breakthrough**.
## Running
Backup the existing **gamex86.dll** (rename it to **gamex86.bak**).
Backup existing mohaa files, **cgamex86.dll** and **gamex86.dll** (set their extension to **.bak**)
a) extract archive to your MOHAA installation directory.
@@ -53,6 +63,8 @@ You can now start a local OpenMOHAA server or play on a server.
## Compiling
OpenMoHAA supports both x86 and x64 architectures, and although the target platform is Windows, it still can be compiled for other platforms, and even other architectures.
These are the tools required for all platforms :
- CMake >= 3.5
- Flex and Bison (currently not used)
@@ -60,6 +72,10 @@ These are the tools required for all platforms :
The installation directory can be set to MOHAA directory.
The client build can be built by adding `-DWITH_CLIENT=1` to the CMake command line. This will compile the cgame module and the full app with rendering, ui and sound suppport, alongside the dedicated server version.
To compile for either Spearhead or Breakthrough, append `-DTARGET_GAME_TYPE=x` where x can be 1 for Team Assault (Spearhead), and 2 for Team Tactics (Breakthrough). 2 is recommended because Team Tactics can connect to both Spearhead and Breakthrough servers.
### Linux
These are the tools required on Unix :
@@ -73,6 +89,14 @@ These are the tools required on Unix :
Visual Studio (2019 or 2022) is generally preferred.
## Screenshots
| | |
|---------------------------------------------------------------------|---------------------------------------------------------------------------|
| ![](docs/images/opm_53_tt_1.png "Playing on a Breakthrough server") | ![](docs/images/opm_50b_1.png) |
| ![](docs/images/opm_50b_2.png) | ![](docs/images/opm-arm_53_tt_1.png "OpenMoHAA on Raspberry") |
## Third party
### SDL
@@ -109,8 +133,8 @@ https://xiph.org/vorbis/
https://opus-codec.org/
## URL
## URLs and communities
- https://openmohaa.sourceforge.net/
- https://github.com/openmoh/openmohaa/
- https://mohaaaa.co.uk/AAAAMOHAA/index.php
- https://x-null.net/
+188 -36
View File
@@ -1795,6 +1795,10 @@ void ClientGameCommandManager::SetAlignStretch(Event* ev)
void ClientGameCommandManager::SetDecalRadius(Event* ev)
{
if (!m_spawnthing) {
return;
}
m_spawnthing->cgd.decal_radius = ev->GetFloat(1);
}
@@ -1806,6 +1810,10 @@ void ClientGameCommandManager::SetDecalOrientation(Event* ev)
{
str deg;
if (!m_spawnthing) {
return;
}
deg = ev->GetString(1);
if (!deg.icmp("random")) {
@@ -1820,6 +1828,10 @@ void ClientGameCommandManager::SetDecalOrientation(Event* ev)
//===============
void ClientGameCommandManager::SetBounceDecal(Event* ev)
{
if (!m_spawnthing) {
return;
}
m_spawnthing->cgd.flags2 |= T2_BOUNCE_DECAL;
if (ev->NumArgs() > 1) {
m_spawnthing->cgd.maxbouncecount = ev->GetInteger(1);
@@ -1837,8 +1849,11 @@ void ClientGameCommandManager::SetBounceDecal(Event* ev)
// SetParallel
//===============
void ClientGameCommandManager::SetParallel(Event* ev)
{
if (!m_spawnthing) {
return;
}
m_spawnthing->cgd.flags2 |= T2_PARALLEL;
}
@@ -1846,10 +1861,13 @@ void ClientGameCommandManager::SetParallel(Event* ev)
// PhysicsRate
//===============
void ClientGameCommandManager::SetPhysicsRate(Event* ev)
{
str rate;
if (!m_spawnthing) {
return;
}
rate = ev->GetString(1);
if (!rate.icmp(rate, "every")) {
@@ -1863,8 +1881,11 @@ void ClientGameCommandManager::SetPhysicsRate(Event* ev)
// SetLightstyle
//===============
void ClientGameCommandManager::SetLightstyle(Event* ev)
{
if (!m_spawnthing) {
return;
}
m_spawnthing->cgd.lightstyle = CG_RegisterLightStyle(ev->GetString(1));
}
@@ -1872,8 +1893,11 @@ void ClientGameCommandManager::SetLightstyle(Event* ev)
// SetBeamSphere
//===============
void ClientGameCommandManager::SetBeamSphere(Event* ev)
{
if (!m_spawnthing) {
return;
}
m_spawnthing->numspherebeams = ev->GetInteger(1);
m_spawnthing->beamflags = BEAM_SPHERE_EFFECT;
}
@@ -1882,8 +1906,11 @@ void ClientGameCommandManager::SetBeamSphere(Event* ev)
// SetBeamSpread
//===============
void ClientGameCommandManager::SetSpread(Event* ev)
{
if (!m_spawnthing) {
return;
}
m_spawnthing->spreadx = ev->GetFloat(1);
m_spawnthing->spready = ev->GetFloat(2);
}
@@ -1892,8 +1919,11 @@ void ClientGameCommandManager::SetSpread(Event* ev)
// SetUseLastTraceEnd
//===============
void ClientGameCommandManager::SetUseLastTraceEnd(Event* ev)
{
if (!m_spawnthing) {
return;
}
m_spawnthing->use_last_trace_end = qtrue;
}
@@ -1901,8 +1931,11 @@ void ClientGameCommandManager::SetUseLastTraceEnd(Event* ev)
// SetSubdivisions
//===============
void ClientGameCommandManager::SetSubdivisions(Event* ev)
{
if (!m_spawnthing) {
return;
}
m_spawnthing->numSubdivisions = ev->GetInteger(1);
}
@@ -1910,8 +1943,11 @@ void ClientGameCommandManager::SetSubdivisions(Event* ev)
// SetBeamPersist
//===============
void ClientGameCommandManager::SetBeamPersist(Event* ev)
{
if (!m_spawnthing) {
return;
}
m_spawnthing->beamflags |= BEAM_PERSIST_EFFECT;
}
@@ -1919,8 +1955,11 @@ void ClientGameCommandManager::SetBeamPersist(Event* ev)
// SetBeamOffsetEndponts
//===============
void ClientGameCommandManager::SetBeamOffsetEndpoints(Event* ev)
{
if (!m_spawnthing) {
return;
}
m_spawnthing->beamflags |= BEAM_OFFSET_ENDPOINTS;
}
@@ -1928,8 +1967,11 @@ void ClientGameCommandManager::SetBeamOffsetEndpoints(Event* ev)
// SetBeamDelay
//===============
void ClientGameCommandManager::SetBeamDelay(Event* ev)
{
if (!m_spawnthing) {
return;
}
if (ev->NumArgs() > 1) {
str r = ev->GetString(1);
if (r.icmp("random")) {
@@ -1945,8 +1987,11 @@ void ClientGameCommandManager::SetBeamDelay(Event* ev)
// SetBeamToggleDelay
//===============
void ClientGameCommandManager::SetBeamToggleDelay(Event* ev)
{
if (!m_spawnthing) {
return;
}
m_spawnthing->beamflags |= BEAM_TOGGLE;
if (ev->NumArgs() > 1) {
str r = ev->GetString(1);
@@ -1964,8 +2009,11 @@ void ClientGameCommandManager::SetBeamToggleDelay(Event* ev)
// SetBeamLength
//===============
void ClientGameCommandManager::SetLength(Event* ev)
{
if (!m_spawnthing) {
return;
}
m_spawnthing->length = ev->GetFloat(1);
}
@@ -1973,8 +2021,11 @@ void ClientGameCommandManager::SetLength(Event* ev)
// SetShader
//===============
void ClientGameCommandManager::SetShader(Event* ev)
{
if (!m_spawnthing) {
return;
}
m_spawnthing->cgd.shadername = ev->GetString(1);
}
@@ -1982,8 +2033,11 @@ void ClientGameCommandManager::SetShader(Event* ev)
// SetMinOffset
//===============
void ClientGameCommandManager::SetMinOffset(Event* ev)
{
if (!m_spawnthing) {
return;
}
m_spawnthing->min_offset = ev->GetInteger(1);
}
@@ -1991,8 +2045,11 @@ void ClientGameCommandManager::SetMinOffset(Event* ev)
// SetSubdivisions
//===============
void ClientGameCommandManager::SetMaxOffset(Event* ev)
{
if (!m_spawnthing) {
return;
}
m_spawnthing->max_offset = ev->GetInteger(1);
}
@@ -2000,8 +2057,11 @@ void ClientGameCommandManager::SetMaxOffset(Event* ev)
// SetAnim
//===============
void ClientGameCommandManager::SetAnim(Event* ev)
{
if (!m_spawnthing) {
return;
}
m_spawnthing->animName = ev->GetString(1);
}
@@ -2009,8 +2069,11 @@ void ClientGameCommandManager::SetAnim(Event* ev)
// AnimateOnce
//===============
void ClientGameCommandManager::AnimateOnce(Event* ev)
{
if (!m_spawnthing) {
return;
}
m_spawnthing->cgd.flags |= T_ANIMATEONCE;
}
@@ -2018,8 +2081,11 @@ void ClientGameCommandManager::AnimateOnce(Event* ev)
// EmitterStartOff
//===============
void ClientGameCommandManager::EmitterStartOff(Event* ev)
{
if (!m_spawnthing) {
return;
}
m_spawnthing->startoff = qtrue;
}
@@ -4732,6 +4798,15 @@ void ClientGameCommandManager::SpawnTempModel(int mcount, int timeAlive)
}
}
}
// Make sure to not spawn the world model as a tempmodel
// Of course it would become extremely confusing...
if (!(p->cgd.flags & T_DLIGHT) && p->ent.reType == RT_MODEL && !p->ent.hModel)
{
Com_Printf("^~^~^ not spawning tempmodel because it is using the world as a brush model\n");
FreeTempModel(p);
break;
}
}
}
@@ -5064,7 +5139,7 @@ void ClientGameCommandManager::LoopSound(Event* ev)
// Get the real sound to play
if (current_tiki) {
if (current_tiki && current_tiki->a->alias_list) {
name = cgi.Alias_ListFindRandom((AliasList_t*)current_tiki->a->alias_list,
sound_name.c_str(), &soundAlias);
}
@@ -5093,7 +5168,7 @@ void CacheResource(const char* stuff)
{
str real_stuff;
if (!stuff) {
if (!stuff || !stuff[0]) {
return;
}
@@ -5151,10 +5226,37 @@ void AliasResource(dtiki_t* pmdl, const char* alias, const char* realname,
}
}
int bLoadForMap__FPCcT0(char* psMapsBuffer, char* name)
qboolean bLoadForMap(const char* psMapsBuffer, const char* name)
{
// FIXME: stub
return 0;
const char* token;
const char* mapname;
const char* override;
mapname = cgs.mapname;
if (!strncmp("test", mapname, strlen("test"))) {
return qtrue;
}
token = COM_GetToken((char**)&psMapsBuffer, qtrue);
override = token;
if (token && *token)
{
while (1)
{
if (!Q_stricmpn(token, mapname, strlen(token)))
{
return true;
}
token = COM_GetToken((char**)&psMapsBuffer, qtrue);
if (!token || !token[0]) {
return false;
}
}
}
Com_Printf("ERROR bLoadForMap: %s alias with empty maps specification.\n", name);
return false;
}
//===============
@@ -5164,8 +5266,9 @@ void ClientGameCommandManager::AliasCache(Event* ev)
{
int i;
char parmbuffer[512]; // this holds the parameters to be passed into the
char parmbuffer[2048]; // this holds the parameters to be passed into the
// alias command
const char* psMapsBuffer;
if (ev->NumArgs() < 2) {
return;
@@ -5176,14 +5279,23 @@ void ClientGameCommandManager::AliasCache(Event* ev)
// any additional parameters are in arguments 3-n
parmbuffer[0] = 0;
psMapsBuffer = NULL;
for (i = 3; i <= ev->NumArgs(); i++) {
strcat(parmbuffer, ev->GetToken(i));
strcat(parmbuffer, " ");
if (strcmp(ev->GetToken(i).c_str(), "maps")) {
strcat(parmbuffer, ev->GetToken(i));
strcat(parmbuffer, " ");
}
else {
psMapsBuffer = ev->GetToken(i++);
}
}
AliasResource(current_tiki, ev->GetString(1), ev->GetString(2), parmbuffer);
CacheResource(ev->GetString(2));
if (bLoadForMap(psMapsBuffer, ev->GetString(1)))
{
AliasResource(current_tiki, ev->GetString(1), ev->GetString(2), parmbuffer);
CacheResource(ev->GetString(2));
}
}
//===============
@@ -5193,8 +5305,10 @@ void ClientGameCommandManager::Alias(Event* ev)
{
int i;
char parmbuffer[512]; // this holds the parameters to be passed into the
char parmbuffer[2048]; // this holds the parameters to be passed into the
// alias command
qboolean subtitle;
const char* psMapsBuffer;
if (ev->NumArgs() < 2) {
return;
@@ -5204,14 +5318,43 @@ void ClientGameCommandManager::Alias(Event* ev)
// real path is argument 2
// any additional parameters are in arguments 3-n
parmbuffer[0] = 0;
parmbuffer[0] = 0;
subtitle = qfalse;
psMapsBuffer = NULL;
for (i = 3; i <= ev->NumArgs(); i++) {
strcat(parmbuffer, ev->GetToken(i));
strcat(parmbuffer, " ");
}
for (i = 3; i <= ev->NumArgs(); i++)
{
if (strcmp(ev->GetToken(i).c_str(), "maps"))
{
if (!subtitle)
{
if (!Q_stricmp(ev->GetToken(i), "subtitle")) {
subtitle = qtrue;
strcat(parmbuffer, ev->GetToken(i));
}
else {
strcat(parmbuffer, ev->GetToken(i));
}
}
else
{
strcat(parmbuffer, "\"");
strcat(parmbuffer, ev->GetToken(i));
strcat(parmbuffer, "\"");
subtitle = qfalse;
}
AliasResource(current_tiki, ev->GetString(1), ev->GetString(2), parmbuffer);
strcat(parmbuffer, " ");
}
else {
psMapsBuffer = ev->GetToken(i++);
}
}
if (bLoadForMap(psMapsBuffer, ev->GetString(1)))
{
AliasResource(current_tiki, ev->GetString(1), ev->GetString(2), parmbuffer);
}
}
void CacheAliasList(AliasList_t* alias_list, str& name)
@@ -6354,6 +6497,7 @@ qboolean CG_Command_ProcessFile(const char* filename, qboolean quiet, dtiki_t *c
char* buffer;
const char* bufstart;
char com_token[MAX_STRING_CHARS];
char tempName[MAX_QPATH + 1];
if (cgi.FS_ReadFile(filename, (void**)&buffer, quiet) == -1) {
return qfalse;
@@ -6366,6 +6510,10 @@ qboolean CG_Command_ProcessFile(const char* filename, qboolean quiet, dtiki_t *c
// we are not setting up for a tiki
current_tiki = NULL;
// Update the loading screen
sprintf(tempName, "m%s", filename);
cgi.LoadResource(tempName);
bufstart = buffer;
while (1) {
@@ -6400,10 +6548,14 @@ qboolean CG_Command_ProcessFile(const char* filename, qboolean quiet, dtiki_t *c
ev->AddToken(com_token);
}
commandManager.ProcessEvent(ev);
commandManager.SelectProcessEvent(ev);
}
cgi.FS_FreeFile((void*)bufstart);
// Update the loading screen
sprintf(tempName, "o%s", filename);
cgi.LoadResource(tempName);
return qtrue;
}
+2 -2
View File
@@ -273,7 +273,7 @@ enum class vsstypes_t : unsigned char {
NUM_VSS_TYPES
};
class cvssource_t : public Class
class cvssource_t
{
public:
cvssource_t* next;
@@ -309,7 +309,7 @@ public:
qboolean lastValid;
};
class cvssourcestate_t : public Class
class cvssourcestate_t
{
public:
Vector origin;
+5 -4
View File
@@ -123,7 +123,7 @@ void CG_ScoresUp_f( void )
}
cg.showScores = qfalse;
cgi.UI_HideScoreBoard(cg.scoresMenuName);
cgi.UI_HideScoreBoard();
}
baseshader_t* CG_GetShaderUnderCrosshair(qboolean bVerbose, trace_t* pRetTrace)
@@ -558,15 +558,16 @@ int CG_WeaponCommandButtonBits(void)
{
int iShiftedWeaponCommand;
iShiftedWeaponCommand = cg.iWeaponCommand;
if (!iShiftedWeaponCommand) {
if (!cg.iWeaponCommand) {
return 0;
}
iShiftedWeaponCommand = cg.iWeaponCommand << 7;
cg.iWeaponCommandSend++;
if (cg.iWeaponCommandSend > 2) {
cg.iWeaponCommand = 0;
}
return (iShiftedWeaponCommand << 7) & WEAPON_COMMAND_MASK;
return iShiftedWeaponCommand & WEAPON_COMMAND_MASK;
}
+142 -10
View File
@@ -816,7 +816,7 @@ void CG_DrawPlayerTeam()
return;
}
handle = NULL;
handle = 0;
if (cg.snap->ps.stats[STAT_TEAM] == 3)
{
handle = cgi.R_RegisterShader("textures/hud/allies");
@@ -851,7 +851,7 @@ void CG_DrawPlayerEntInfo()
}
iClientNum = cg.snap->ps.stats[STAT_INFOCLIENT];
handle = NULL;
handle = 0;
pszClientInfo = CG_ConfigString(iClientNum + CS_PLAYERS);
pszName = Info_ValueForKey(pszClientInfo, "name");
@@ -982,14 +982,32 @@ void CG_DrawStopwatch()
{
int iFraction;
if (!cg_hud->integer || !cgi.stopWatch->iStartTime
|| cgi.stopWatch->iStartTime >= cgi.stopWatch->iEndTime
|| cgi.stopWatch->iEndTime <= cg.time
// don't draw the stopwatch with the objective menu
|| cg.ObjectivesCurrentAlpha >= 0.02
// the player isn't alive
|| cg.snap && cg.snap->ps.stats[STAT_HEALTH] <= 0)
{
if (!cg_hud->integer) {
cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_stopwatch\n");
return;
}
if (!cgi.stopWatch->iStartTime) {
cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_stopwatch\n");
return;
}
if (cgi.stopWatch->iStartTime >= cgi.stopWatch->iEndTime) {
cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_stopwatch\n");
return;
}
if (cgi.stopWatch->iEndTime <= cg.time) {
cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_stopwatch\n");
return;
}
if (cg.ObjectivesCurrentAlpha >= 0.02) {
cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_stopwatch\n");
return;
}
if (cg.snap && cg.snap->ps.stats[STAT_HEALTH] <= 0) {
cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_stopwatch\n");
return;
}
@@ -1023,6 +1041,118 @@ void CG_DrawInstantMessageMenu()
cgi.R_DrawStretchPic(x, y, w, h, 0.0, 0.0, 1.0, 1.0, handle);
}
#if TARGET_GAME_PROTOCOL >= 15
void CG_DrawSpectatorView()
{
const char* pszString;
int iKey1, iKey2;
int iKey1b, iKey2b;
float fX, fY;
qboolean bOnTeam;
if (!(cg.predicted_player_state.pm_flags & PMF_SPECTATING)) {
return;
}
bOnTeam = qfalse;
if (cg.snap->ps.stats[STAT_TEAM] == TEAM_ALLIES || cg.snap->ps.stats[STAT_TEAM] == TEAM_AXIS) {
bOnTeam = 1;
}
if (!bOnTeam)
{
cgi.Key_GetKeysForCommand("+attackprimary", &iKey1, &iKey2);
pszString = cgi.LV_ConvertString(va("Press Fire(%s) to join the battle!", cgi.Key_KeynumToBindString(iKey1)));
fX = (float)(cgs.glconfig.vidWidth - cgi.UI_FontStringWidth(cgs.media.attackerFont, pszString, -1)) * 0.5;
fY = cgs.glconfig.vidHeight - 64.0;
cgi.R_SetColor(NULL);
cgi.R_DrawString(cgs.media.attackerFont, pszString, fX, fY, -1, qfalse);
}
if (cg.predicted_player_state.pm_flags & PMF_CAMERA_VIEW)
{
cgi.Key_GetKeysForCommand("+moveup", &iKey1, &iKey2);
cgi.Key_GetKeysForCommand("+movedown", &iKey1b, &iKey2b);
pszString = cgi.LV_ConvertString(
va(
"Press Jump(%s) or Duck(%s) to follow a different player.",
cgi.Key_KeynumToBindString(iKey1),
cgi.Key_KeynumToBindString(iKey1b)
)
);
fX = (float)(cgs.glconfig.vidWidth - cgi.UI_FontStringWidth(cgs.media.attackerFont, pszString, -1)) * 0.5;
fY = (float)cgs.glconfig.vidHeight - 40.0;
cgi.R_SetColor(0);
cgi.R_DrawString(cgs.media.attackerFont, pszString, fX, fY, -1, 0);
}
if (!bOnTeam && (cg.predicted_player_state.pm_flags & PMF_CAMERA_VIEW))
{
cgi.Key_GetKeysForCommand("+use", &iKey1, &iKey2);
pszString = cgi.LV_ConvertString(va("Press Use(%s) to enter free spectate mode.", cgi.Key_KeynumToBindString(iKey1)));
fX = (float)(cgs.glconfig.vidWidth - cgi.UI_FontStringWidth(cgs.media.attackerFont, pszString, -1)) * 0.5;
fY = (float)cgs.glconfig.vidHeight - 24.0;
cgi.R_SetColor(0);
cgi.R_DrawString(cgs.media.attackerFont, pszString, fX, fY, -1, 0);
}
if (!(cg.predicted_player_state.pm_flags & PMF_CAMERA_VIEW)) {
cgi.Key_GetKeysForCommand("+use", &iKey1, &iKey2);
pszString = cgi.LV_ConvertString(
va(
"Press Use(%s) to enter player following spectate mode.",
cgi.Key_KeynumToBindString(iKey1)
)
);
fX = (float)(cgs.glconfig.vidWidth - cgi.UI_FontStringWidth(cgs.media.attackerFont, pszString, -1)) * 0.5;
fY = (float)cgs.glconfig.vidHeight - 24.0;
cgi.R_SetColor(0);
cgi.R_DrawString(cgs.media.attackerFont, pszString, fX, fY, -1, 0);
}
if ((cg.predicted_player_state.pm_flags & 0x80) != 0 && cg.snap && cg.snap->ps.stats[STAT_INFOCLIENT] != -1)
{
int iClientNum;
qhandle_t hShader;
vec4_t color;
char buf[128];
iClientNum = cg.snap->ps.stats[STAT_INFOCLIENT];
sprintf(buf, "%s : %i", cg.clientinfo[iClientNum].name, cg.snap->ps.stats[STAT_INFOCLIENT_HEALTH]);
color[0] = 0.5;
color[1] = 1.0;
color[2] = 0.5;
color[3] = 1.0;
fX = (float)(cgs.glconfig.vidWidth - cgi.UI_FontStringWidth(cgs.media.attackerFont, pszString, -1) - 16) * 0.5;
fY = (float)cgs.glconfig.vidHeight - 80.0;
cgi.R_SetColor(color);
cgi.R_DrawString(cgs.media.attackerFont, buf, fX, fY, -1, 0);
if (cg.clientinfo[iClientNum].team == TEAM_ALLIES) {
hShader = cgi.R_RegisterShader("textures/hud/allies");
} else if (cg.clientinfo[iClientNum].team == TEAM_AXIS) {
hShader = cgi.R_RegisterShader("textures/hud/axis");
}
if (hShader)
{
fX -= 20.0;
cgi.R_SetColor(NULL);
cgi.R_DrawStretchPic(fX, fY, 16.0, 16.0, 0.0, 0.0, 1.0, 1.0, hShader);
}
}
}
#else
void CG_DrawSpectatorView()
{
const char* pszString;
@@ -1083,6 +1213,8 @@ void CG_DrawSpectatorView()
}
}
#endif
/*
==============
CG_Draw2D
+30 -14
View File
@@ -414,6 +414,25 @@ void CG_Portal(centity_t* cent)
{
}
/*
================
BG_EvaluateTrajectory
================
*/
void BG_EvaluateTrajectory(const trajectory_t* tr, int atTime, const vec3_t base, vec3_t result) {
float deltaTime;
if (atTime > cg_smoothClientsTime->integer + tr->trTime) {
atTime = cg_smoothClientsTime->integer + tr->trTime;
}
deltaTime = (float)(atTime - tr->trTime) / 1000.0;
result[0] = tr->trDelta[0] * deltaTime + base[0];
result[1] = tr->trDelta[1] * deltaTime + base[1];
result[2] = tr->trDelta[2] * deltaTime + base[2];
}
/*
===============
CG_CalcEntityLerpPositions
@@ -477,8 +496,8 @@ void CG_CalcEntityLerpPositions( centity_t *cent )
// this will linearize a sine or parabolic curve, but it is important
// to not extrapolate player positions if more recent data is available
BG_EvaluateTrajectory(&cent->currentState.pos, cg.snap->serverTime, current);
BG_EvaluateTrajectory(&cent->nextState.pos, cg.nextSnap->serverTime, next);
BG_EvaluateTrajectory(&cent->currentState.pos, cg.snap->serverTime, cent->currentState.origin, current);
BG_EvaluateTrajectory(&cent->nextState.pos, cg.nextSnap->serverTime, cent->nextState.origin, next);
cent->lerpOrigin[0] = current[0] + f * (next[0] - current[0]);
cent->lerpOrigin[1] = current[1] + f * (next[1] - current[1]);
@@ -494,17 +513,11 @@ void CG_CalcEntityLerpPositions( centity_t *cent )
QuatToMat(quat, mat);
MatrixToEulerAngles(mat, cent->lerpAngles);
}
// Lerp legs, torso, and head angles
for (i = 0; i < 3; i++) {
cent->lerpAngles[i] = LerpAngle(current[i], next[i], f);
}
}
else {
// just use the current frame and evaluate as best we can
BG_EvaluateTrajectory(&cent->currentState.pos, cg.time, cent->lerpOrigin);
BG_EvaluateTrajectory(&cent->currentState.pos, cg.time, cent->currentState.origin, cent->lerpOrigin);
VectorCopy(cent->currentState.angles, cent->lerpAngles);
//BG_EvaluateTrajectory(&cent->currentState.apos, cg.time, cent->lerpAngles);
}
}
@@ -545,10 +558,10 @@ void CG_AddCEntity(centity_t* cent)
CG_ModelAnim(cent, qtrue);
break;
case ET_PLAYER:
CG_Player(cent);
case ET_ITEM:
case ET_EXEC_COMMANDS:
CG_ModelAnim(cent, qfalse);
CG_Player(cent);
CG_Splash(cent);
case ET_ITEM:
CG_ModelAnim(cent, qfalse);
break;
case ET_GENERAL:
CG_General(cent);
@@ -575,7 +588,10 @@ void CG_AddCEntity(centity_t* cent)
break;
case ET_ROPE: // skip
CG_Rope(cent);
break;
break;
case ET_EXEC_COMMANDS:
CG_ModelAnim(cent, qfalse);
break;
}
}
+4 -4
View File
@@ -51,7 +51,7 @@ clightstyle_t cg_lightstyle[ MAX_LIGHTSTYLES * 2 ];
CG_LightStyleColor
================
*/
qboolean CG_LightStyleColor( int style, int realtime, float color[4], qboolean clamp )
qboolean CG_LightStyleColor( int style, int realtime, vec4_t color, qboolean clamp )
{
clightstyle_t *ls;
int i, time;
@@ -495,7 +495,7 @@ void CG_SetLightStyle( int num, const char *s )
cg_lightstyle[ num ].map[ k ][ 1 ] = t / 255.0f;
k++;
}
n = max( n, k );
n = Q_max( n, k );
}
while( k < MAX_LIGHTSTYLE_LENGTH )
{
@@ -518,7 +518,7 @@ void CG_SetLightStyle( int num, const char *s )
cg_lightstyle[ num ].map[ k ][ 2 ] = t / 255.0f;
k++;
}
n = max( n, k );
n = Q_max( n, k );
}
while( k < MAX_LIGHTSTYLE_LENGTH )
{
@@ -541,7 +541,7 @@ void CG_SetLightStyle( int num, const char *s )
cg_lightstyle[ num ].map[ k ][ 3 ] = t / 255.0f;
k++;
}
n = max( n, k );
n = Q_max( n, k );
}
while( k < MAX_LIGHTSTYLE_LENGTH )
{
+19 -9
View File
@@ -160,6 +160,7 @@ typedef struct markPoly_s
#define MAX_CUSTOM_SOUNDS 32
typedef struct {
int team;
char name[64];
} clientInfo_t;
typedef struct cobjective_s {
@@ -297,15 +298,21 @@ typedef struct {
qboolean testGun;
// farplane parameters
float farplane_distance;
float farplane_distance;
float farplane_bias;
vec3_t farplane_color;
qboolean farplane_cull;
qboolean farplane_cull;
float skyboxFarplane;
qboolean renderTerrain;
float farclipOverride;
vec3_t farplaneColorOverride;
// portal sky parameters
qboolean sky_portal;
float sky_alpha;
vec3_t sky_origin;
vec3_t sky_axis[3]; // rotation vectors
vec3_t sky_axis[3]; // rotation vectors
float skyboxSpeed;
// weapon viewkick recoil
float viewkick[2];
@@ -371,8 +378,9 @@ typedef struct {
int fraglimit;
int timelimit;
int maxclients;
int cinematic;
char mapname[MAX_QPATH];
int cinematic;
int mapChecksum;
char mapname[MAX_QPATH];
//
// locally derived information from gamestate
@@ -475,6 +483,7 @@ int CG_LastAttacker( void );
void CG_Init( clientGameImport_t *imported, int serverMessageNum, int serverCommandSequence, int clientNum );
void CG_Shutdown( void );
void CG_ServerRestarted( void );
void CG_ParseFogInfo(const char* str);
//
// cg_modelanim.cpp
@@ -590,6 +599,7 @@ void CG_PredictPlayerState( void );
//
// cg_ents.c
//
void BG_EvaluateTrajectory(const trajectory_t* tr, int atTime, const vec3_t base, vec3_t result);
void CG_SetEntitySoundPosition( centity_t *cent );
void CG_AddPacketEntities( void );
void CG_Beam( centity_t *cent );
@@ -632,8 +642,8 @@ void CG_ImpactMarkSimple(
);
void CG_InitTestTreadMark();
int CG_PermanentMark(
vec_t* origin,
vec_t* dir,
const vec3_t origin,
const vec3_t dir,
float orientation,
float fSScale,
float fTScale,
@@ -800,9 +810,9 @@ void CG_MultiBeam( centity_t *cent );
// cg_lightstyles.cpp
void CG_SetLightStyle( int num, const char *s );
#ifdef __cplusplus
qboolean CG_LightStyleColor( int style, int realtime, float color[4], qboolean clamp = qfalse );
qboolean CG_LightStyleColor( int style, int realtime, vec4_t color, qboolean clamp = qfalse );
#else
qboolean CG_LightStyleColor( int style, int realtime, float color[4], qboolean clamp );
qboolean CG_LightStyleColor( int style, int realtime, vec4_t color, qboolean clamp );
#endif
void CG_ClearLightStyles( void );
int CG_RegisterLightStyle( const char * name );
+69 -20
View File
@@ -194,23 +194,22 @@ called during a precache command
*/
void CG_RegisterSounds( void )
{
int startTime; // esi MAPDST
int endTime; // eax MAPDST
char filename[64]; // [esp+28h] [ebp-40h] BYREF
int startTime;
int endTime;
char filename[MAX_QPATH];
Com_Printf("\n\n-----------PARSING UBERSOUND------------\n");
Com_Printf(
"Any SetCurrentTiki errors means that tiki wasn't prefetched and "
"tiki-specific sounds for it won't work. To fix prefe"
"tch the tiki. Ignore if you don't use that tiki on this level.\n");
Com_sprintf(filename, 64, "ubersound/ubersound.scr");
Com_sprintf(filename, sizeof(filename), "ubersound/ubersound.scr");
startTime = cgi.Milliseconds();
CG_Command_ProcessFile(filename, 0, 0);
endTime = cgi.Milliseconds();
Com_Printf("Parse/Load time: %f seconds.\n",
(double)((long double)(endTime - startTime) / 1000.0));
Com_Printf("Parse/Load time: %f seconds.\n", (endTime - startTime) / 1000.0f);
Com_Printf("-------------UBERSOUND DONE---------------\n\n");
Com_Printf("\n\n-----------PARSING UBERDIALOG------------\n");
@@ -218,14 +217,13 @@ void CG_RegisterSounds( void )
"Any SetCurrentTiki errors means that tiki wasn't prefetched and "
"tiki-specific sounds for it won't work. To fix prefe"
"tch the tiki. Ignore if you don't use that tiki on this level.\n");
Com_sprintf(filename, 64, "ubersound/uberdialog.scr");
Com_sprintf(filename, sizeof(filename), "ubersound/uberdialog.scr");
startTime = cgi.Milliseconds();
CG_Command_ProcessFile(filename, 0, 0);
endTime = cgi.Milliseconds() - startTime;
Com_Printf("Parse/Load time: %f seconds.\n",
(double)((long double)endTime / 1000.0));
Com_Printf("Parse/Load time: %f seconds.\n", endTime / 1000.0f);
Com_Printf("-------------UBERDIALOG DONE---------------\n\n");
}
@@ -302,16 +300,7 @@ void CG_ProcessConfigString(int num)
cg.matchStartTime = atoi(str);
return;
case CS_FOGINFO:
sscanf
(
str,
"%d %f %f %f %f",
&cg.farplane_cull,
&cg.farplane_distance,
&cg.farplane_color[0],
&cg.farplane_color[1],
&cg.farplane_color[2]
);
CG_ParseFogInfo(str);
return;
case CS_SKYINFO:
sscanf
@@ -366,7 +355,7 @@ void CG_ProcessConfigString(int num)
}
else if (num >= CS_SOUNDS && num < CS_SOUNDS + MAX_SOUNDS)
{
int len = strlen(str);
size_t len = strlen(str);
if (len)
{
qboolean streamed;
@@ -384,6 +373,25 @@ void CG_ProcessConfigString(int num)
{
CG_SetLightStyle(num - CS_LIGHTSTYLES, str);
}
else if (num >= CS_PLAYERS && num < CS_PLAYERS + MAX_CLIENTS)
{
const char* value;
value = Info_ValueForKey(str, "name");
if (value) {
strncpy(cg.clientinfo[num - CS_PLAYERS].name, value, sizeof(cg.clientinfo[num - CS_PLAYERS].name));
}
else {
strncpy(cg.clientinfo[num - CS_PLAYERS].name, "UnnamedSoldier", sizeof(cg.clientinfo[num - CS_PLAYERS].name));
}
value = Info_ValueForKey(str, "team");
if (value) {
cg.clientinfo[num - CS_PLAYERS].team = atoi(value);
} else {
cg.clientinfo[num - CS_PLAYERS].team = TEAM_NONE;
}
}
}
//===================================================================================
@@ -778,4 +786,45 @@ void Com_Printf( const char *msg, ... ) {
#endif
#if TARGET_GAME_PROTOCOL >= 15
void CG_ParseFogInfo(const char* str) {
sscanf(
str,
"%d %f %f %f %f %f %f %f %d %f %f %f %f",
&cg.farplane_cull,
&cg.farplane_distance,
&cg.farplane_bias,
&cg.skyboxFarplane,
&cg.skyboxSpeed,
&cg.farplane_color[0],
&cg.farplane_color[1],
&cg.farplane_color[2],
&cg.renderTerrain,
&cg.farclipOverride,
&cg.farplaneColorOverride[0],
&cg.farplaneColorOverride[1],
&cg.farplaneColorOverride[2]
);
}
#else
void CG_ParseFogInfo(const char* str) {
cg.farclipOverride = 0.0;
cg.farplaneColorOverride[0] = -1.0;
cg.farplaneColorOverride[1] = -1.0;
cg.farplaneColorOverride[2] = -1.0;
sscanf
(
str,
"%d %f %f %f %f",
&cg.farplane_cull,
&cg.farplane_distance,
&cg.farplane_color[0],
&cg.farplane_color[1],
&cg.farplane_color[2]
);
}
#endif
+2 -2
View File
@@ -444,8 +444,8 @@ void CG_AddTreadMarks()
}
int CG_PermanentMark(
vec_t* origin,
vec_t* dir,
const vec3_t origin,
const vec3_t dir,
float orientation,
float fSScale,
float fTScale,
+178 -1
View File
@@ -28,6 +28,183 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
void CG_PlayerTeamUpdate(refEntity_t* pModel, entityState_t* pPlayerState)
{
qboolean bInArtillery, bInTeam, bSpecialIcon;
#if TARGET_GAME_PROTOCOL < 15
if (pPlayerState->eFlags & EF_ALLIES)
{
cg.clientinfo[pPlayerState->number].team = TEAM_ALLIES;
} else if (pPlayerState->eFlags & EF_AXIS) {
cg.clientinfo[pPlayerState->number].team = TEAM_AXIS;
} else {
cg.clientinfo[pPlayerState->number].team = TEAM_NONE;
}
#endif
if (pPlayerState->number == cg.snap->ps.clientNum) {
return;
}
bInTeam = qfalse;
bSpecialIcon = qfalse;
if (cgs.gametype > GT_FFA
&& (cg.snap->ps.stats[STAT_TEAM] == TEAM_ALLIES && (pPlayerState->eFlags & EF_ALLIES)
|| cg.snap->ps.stats[STAT_TEAM] == TEAM_AXIS && (pPlayerState->eFlags & EF_AXIS)
|| cg.snap->ps.stats[STAT_TEAM] != TEAM_AXIS && cg.snap->ps.stats[STAT_TEAM] != TEAM_ALLIES && (pPlayerState->eFlags & EF_ANY_TEAM) != 0))
{
bInTeam = qtrue;
}
if (cgs.gametype <= GT_FFA) {
return;
}
bInArtillery = qfalse;
if (pPlayerState->eFlags & EF_PLAYER_ARTILLERY) {
bInArtillery = qtrue;
}
if (bInTeam || (pPlayerState->eFlags & (EF_PLAYER_IN_MENU | EF_PLAYER_TALKING)) || bInArtillery)
{
int i;
int iTag;
float fAlpha;
float fDist;
vec3_t vTmp;
refEntity_t iconEnt;
memset(&iconEnt, 0, sizeof(iconEnt));
if ((pPlayerState->eFlags & EF_PLAYER_TALKING) != 0 && ((cg.time >> 8) & 1) != 0)
{
iconEnt.hModel = cgi.R_RegisterModel("textures/hud/talking_headicon.spr");
bSpecialIcon = 1;
}
else if ((pPlayerState->eFlags & EF_PLAYER_IN_MENU) != 0)
{
iconEnt.hModel = cgi.R_RegisterModel("textures/hud/inmenu_headicon.spr");
bSpecialIcon = 1;
}
else
{
if (!bInTeam) {
return;
}
if (bInArtillery)
{
iconEnt.hModel = cgi.R_RegisterModel("textures/hud/inmenu_artilleryicon.spr");
bSpecialIcon = qtrue;
}
else if ((pPlayerState->eFlags & 0x80) != 0)
{
iconEnt.hModel = cgi.R_RegisterModel("textures/hud/allies_headicon.spr");
}
else
{
iconEnt.hModel = cgi.R_RegisterModel("textures/hud/axis_headicon.spr");
}
}
memset(vTmp, 0, sizeof(vTmp));
AnglesToAxis(vTmp, iconEnt.axis);
iconEnt.scale = 0.5;
iconEnt.renderfx = 0;
iconEnt.reType = RT_SPRITE;
iconEnt.shaderTime = 0.0;
iconEnt.frameInfo[0].index = 0;
iconEnt.shaderRGBA[0] = -1;
iconEnt.shaderRGBA[1] = -1;
iconEnt.shaderRGBA[2] = -1;
VectorCopy(pModel->origin, iconEnt.origin);
iTag = cgi.Tag_NumForName(pModel->tiki, "eyes bone");
if (iTag == -1)
{
iconEnt.origin[2] = iconEnt.origin[2] + 96.0;
}
else
{
orientation_t oEyes = cgi.TIKI_Orientation(pModel, iTag);
for (i = 0; i < 3; ++i) {
VectorMA(iconEnt.origin, oEyes.origin[i], pModel->axis[i], iconEnt.origin);
}
iconEnt.origin[2] = iconEnt.origin[2] + 20.0;
}
VectorSubtract(iconEnt.origin, cg.refdef.vieworg, vTmp);
fDist = VectorLength(vTmp);
if (fDist >= 256)
{
if (fDist > 512.0) {
iconEnt.scale = (fDist - 512.0) / 2560.0 + 0.5;
}
}
else
{
iconEnt.scale = fDist / 853.0 + 0.2;
}
if (iconEnt.scale > 1.0) {
iconEnt.scale = 1.0;
}
if (fDist > 256.0) {
fAlpha = 1.0;
}
else if (fDist >= 72.0) {
fAlpha = (fDist - 72.0) / 184.0;
}
else {
fAlpha = 0.0;
}
if (cg.snap->ps.stats[STAT_TEAM] == 4 || cg.snap->ps.stats[STAT_TEAM] == 3) {
fAlpha = fAlpha * 0.65;
}
else {
fAlpha = fAlpha * 0.4;
}
if (bSpecialIcon)
{
int value = (int)((fAlpha + 0.60000002) * 255.0);
if (value > 255) value = 255;
iconEnt.shaderRGBA[3] = value;
}
else
{
iconEnt.shaderRGBA[3] = (int)(fAlpha * 255.0);
}
if (fAlpha > 0.0 || bSpecialIcon)
{
if (bSpecialIcon)
{
VectorMA(iconEnt.origin, -2.0, cg.refdef.viewaxis[0], iconEnt.origin);
iconEnt.scale = iconEnt.scale + 0.05;
}
cgi.R_AddRefSpriteToScene(&iconEnt);
if (bSpecialIcon && bInTeam && fAlpha > 0.0)
{
if (pPlayerState->eFlags & EF_ALLIES) {
iconEnt.hModel = cgi.R_RegisterModel("textures/hud/allies_headicon.spr");
}
else {
iconEnt.hModel = cgi.R_RegisterModel("textures/hud/axis_headicon.spr");
}
VectorMA(iconEnt.origin, 4.0, cg.refdef.viewaxis[0], iconEnt.origin);
iconEnt.scale = iconEnt.scale - 0.1;
iconEnt.shaderRGBA[3] = (int)(fAlpha * 255.0);
cgi.R_AddRefSpriteToScene(&iconEnt);
}
}
}
// FIXME: unimplemented
}
@@ -956,7 +1133,7 @@ void CG_ModelAnim(centity_t* cent, qboolean bDoShaderTime)
VectorCopy(model.origin, cg.sky_origin);
}
model.reType = ET_MODELANIM_SKEL;
model.reType = RT_MODEL;
if (!(s1->renderfx & RF_DONTDRAW))
{
cgi.R_Model_GetHandle(model.hModel);
+467 -6
View File
@@ -64,7 +64,7 @@ static void CG_MakeBulletHole(vec3_t i_vPos, vec3_t i_vNorm, int iLarge, trace_t
// FIXME: unimplemented
}
static void CG_MakeBubbleTrail(vec3_t i_vStart, vec3_t i_vEnd, int iLarge)
static void CG_MakeBubbleTrail(vec3_t i_vStart, vec3_t i_vEnd, int iLarge, float alpha = 1.0f)
{
// FIXME: unimplemented
}
@@ -79,7 +79,7 @@ static void CG_MakeBulletTracerInternal(vec3_t i_vBarrel, vec3_t i_vStart, vec3_
// FIXME: unimplemented
}
static void CG_MakeBulletTracer(vec3_t i_vBarrel, vec3_t i_vStart, vec3_t* i_vEnd, int i_iNumBullets, qboolean iLarge, int iTracerVisible, qboolean bIgnoreEntities) {
static void CG_MakeBulletTracer(vec3_t i_vBarrel, vec3_t i_vStart, vec3_t* i_vEnd, int i_iNumBullets, qboolean iLarge, int iTracerVisible, qboolean bIgnoreEntities, float alpha = 1.0f) {
bullet_tracer_t* bullet_tracer;
int i;
@@ -306,6 +306,463 @@ void CG_MakeVehicleEffect(vec3_t i_vStart, vec3_t i_vEnd , vec3_t i_vDir) {
cgi.R_DebugLine(vFrom, trace.endpos, 1.0, 1.0, 1.0, 1.0);
}
#if TARGET_GAME_PROTOCOL >= 15
void CG_ParseCGMessage()
{
int i;
int iType;
int iLarge;
int iInfo;
int iCount;
char* szTmp;
vec3_t vStart, vEnd, vTmp;
vec3_t vEndArray[MAX_IMPACTS];
float alpha;
int value;
qboolean bMoreCGameMessages = qtrue;
while (bMoreCGameMessages) {
iType = cgi.MSG_ReadBits(6);
switch (iType)
{
case 1:
case 2:
case 5:
if (iType == 1)
{
vTmp[0] = cgi.MSG_ReadCoord();
vTmp[1] = cgi.MSG_ReadCoord();
vTmp[2] = cgi.MSG_ReadCoord();
}
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
if (iType != 1)
{
vTmp[0] = vStart[0];
vTmp[1] = vStart[1];
vTmp[2] = vStart[2];
}
vEndArray[0][0] = cgi.MSG_ReadCoord();
vEndArray[0][1] = cgi.MSG_ReadCoord();
vEndArray[0][2] = cgi.MSG_ReadCoord();
iLarge = cgi.MSG_ReadBits(2);
if (cgi.MSG_ReadBits(1)) {
int iAlpha = cgi.MSG_ReadBits(10);
alpha = (float)iAlpha / 512.0;
if (alpha < 0.002) {
alpha = 0.002;
}
} else {
alpha = 1.0f;
}
if (iType == 1) {
CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qfalse, qtrue, alpha);
}
else if (iType == 2) {
CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qfalse, qtrue, alpha);
}
else {
CG_MakeBubbleTrail(vStart, vEndArray[0], iLarge, alpha);
}
break;
case 3:
case 4:
if (iType == 3)
{
vTmp[0] = cgi.MSG_ReadCoord();
vTmp[1] = cgi.MSG_ReadCoord();
vTmp[2] = cgi.MSG_ReadCoord();
iInfo = cgi.MSG_ReadBits(6);
}
else
{
iInfo = 0;
}
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
iLarge = cgi.MSG_ReadBits(2);
if (cgi.MSG_ReadBits(1)) {
int iAlpha = cgi.MSG_ReadBits(10);
alpha = (float)iAlpha / 512.0;
if (alpha < 0.002) {
alpha = 0.002;
}
} else {
alpha = 1.0f;
}
iCount = cgi.MSG_ReadBits(6);
for (i = 0; i < iCount; ++i)
{
vEndArray[i][0] = cgi.MSG_ReadCoord();
vEndArray[i][1] = cgi.MSG_ReadCoord();
vEndArray[i][2] = cgi.MSG_ReadCoord();
}
if (iCount) {
CG_MakeBulletTracer(vTmp, vStart, vEndArray, iCount, iLarge, iInfo, qtrue, alpha);
}
break;
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
cgi.MSG_ReadDir(vEnd);
iLarge = cgi.MSG_ReadBits(2);
switch (iType)
{
case 6:
if (wall_impact_count < MAX_IMPACTS)
{
VectorCopy(vStart, wall_impact_pos[wall_impact_count]);
VectorCopy(vEnd, wall_impact_norm[wall_impact_count]);
wall_impact_large[wall_impact_count] = iLarge;
wall_impact_type[wall_impact_count] = -1;
wall_impact_count++;
}
break;
case 7:
if (wall_impact_count < MAX_IMPACTS)
{
VectorCopy(vStart, wall_impact_pos[wall_impact_count]);
VectorCopy(vEnd, wall_impact_norm[wall_impact_count]);
wall_impact_large[wall_impact_count] = iLarge;
wall_impact_type[wall_impact_count] = 6;
wall_impact_count++;
}
break;
case 8:
if (flesh_impact_count < MAX_IMPACTS)
{
// negative
VectorNegate(vEnd, vEnd);
VectorCopy(vStart, flesh_impact_pos[flesh_impact_count]);
VectorCopy(vEnd, flesh_impact_norm[flesh_impact_count]);
flesh_impact_large[flesh_impact_count] = iLarge;
flesh_impact_count++;
}
break;
case 9:
if (flesh_impact_count < MAX_IMPACTS)
{
// negative
VectorNegate(vEnd, vEnd);
VectorCopy(vStart, flesh_impact_pos[flesh_impact_count]);
VectorCopy(vEnd, flesh_impact_norm[flesh_impact_count]);
flesh_impact_large[flesh_impact_count] = iLarge;
flesh_impact_count++;
}
break;
case 10:
if (wall_impact_count < MAX_IMPACTS)
{
VectorCopy(vStart, wall_impact_pos[wall_impact_count]);
VectorCopy(vEnd, wall_impact_norm[wall_impact_count]);
wall_impact_large[wall_impact_count] = iLarge;
wall_impact_type[wall_impact_count] = 2;
wall_impact_count++;
}
break;
case 11:
if (wall_impact_count < MAX_IMPACTS)
{
VectorCopy(vStart, wall_impact_pos[wall_impact_count]);
VectorCopy(vEnd, wall_impact_norm[wall_impact_count]);
wall_impact_large[wall_impact_count] = iLarge;
wall_impact_type[wall_impact_count] = 4;
wall_impact_count++;
}
break;
default:
continue;
}
break;
case 12:
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
vEnd[0] = cgi.MSG_ReadCoord();
vEnd[1] = cgi.MSG_ReadCoord();
vEnd[2] = cgi.MSG_ReadCoord();
CG_MeleeImpact(vStart, vEnd);
break;
case 13:
case 14:
case 15:
case 16:
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
CG_MakeExplosionEffect(vStart, iType);
break;
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
cgi.MSG_ReadDir(vEnd);
sfxManager.MakeEffect_Normal(iType + 67, vStart, vEnd);
break;
case 26:
case 27:
{
str sEffect;
char cTmp[8];
vec3_t axis[3];
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
iLarge = cgi.MSG_ReadByte();
// get the integer as string
snprintf(cTmp, sizeof(cTmp), "%d", iLarge);
if (iType == 26) {
sEffect = "models/fx/crates/debris_";
}
else {
sEffect = "models/fx/windows/debris_";
}
sEffect += cTmp;
sEffect += ".tik";
VectorSet(axis[0], 0, 0, 1);
VectorSet(axis[1], 0, 1, 0);
VectorSet(axis[2], 1, 0, 0);
cgi.R_SpawnEffectModel(sEffect.c_str(), vStart, axis);
}
break;
case 28:
vTmp[0] = cgi.MSG_ReadCoord();
vTmp[1] = cgi.MSG_ReadCoord();
vTmp[2] = cgi.MSG_ReadCoord();
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
vEndArray[0][0] = cgi.MSG_ReadCoord();
vEndArray[0][1] = cgi.MSG_ReadCoord();
vEndArray[0][2] = cgi.MSG_ReadCoord();
iLarge = cgi.MSG_ReadBits(2);
if (cgi.MSG_ReadBits(1)) {
int iAlpha = cgi.MSG_ReadBits(10);
alpha = (float)iAlpha / 512.0;
if (alpha < 0.002) {
alpha = 0.002;
}
} else {
alpha = 1.0f;
}
CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qtrue, qtrue, alpha);
break;
case 29:
memset(vTmp, 0, sizeof(vTmp));
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
vEndArray[0][0] = cgi.MSG_ReadCoord();
vEndArray[0][1] = cgi.MSG_ReadCoord();
vEndArray[0][2] = cgi.MSG_ReadCoord();
iLarge = cgi.MSG_ReadBits(1);
if (cgi.MSG_ReadBits(1)) {
int iAlpha = cgi.MSG_ReadBits(10);
alpha = (float)iAlpha / 512.0;
if (alpha < 0.002) {
alpha = 0.002;
}
} else {
alpha = 1.0f;
}
CG_MakeBulletTracer(vTmp, vStart, vEndArray, 1, iLarge, qfalse, qtrue, alpha);
break;
case 30:
iInfo = cgi.MSG_ReadByte();
strcpy(cgi.HudDrawElements[iInfo].shaderName, cgi.MSG_ReadString());
cgi.HudDrawElements[iInfo].string[0] = 0;
cgi.HudDrawElements[iInfo].pFont = NULL;
cgi.HudDrawElements[iInfo].fontName[0] = 0;
// set the shader
CG_HudDrawShader(iInfo);
break;
case 31:
iInfo = cgi.MSG_ReadByte();
cgi.HudDrawElements[iInfo].iHorizontalAlign = cgi.MSG_ReadBits(2);
cgi.HudDrawElements[iInfo].iVerticalAlign = cgi.MSG_ReadBits(2);
break;
case 32:
iInfo = cgi.MSG_ReadByte();
cgi.HudDrawElements[iInfo].iX = cgi.MSG_ReadShort();
cgi.HudDrawElements[iInfo].iY = cgi.MSG_ReadShort();
cgi.HudDrawElements[iInfo].iWidth = cgi.MSG_ReadShort();
cgi.HudDrawElements[iInfo].iHeight = cgi.MSG_ReadShort();
break;
case 33:
iInfo = cgi.MSG_ReadByte();
cgi.HudDrawElements[iInfo].bVirtualScreen = cgi.MSG_ReadBits(1);
break;
case 34:
iInfo = cgi.MSG_ReadByte();
cgi.HudDrawElements[iInfo].vColor[0] = cgi.MSG_ReadByte() / 255.0;
cgi.HudDrawElements[iInfo].vColor[1] = cgi.MSG_ReadByte() / 255.0;
cgi.HudDrawElements[iInfo].vColor[2] = cgi.MSG_ReadByte() / 255.0;
break;
case 35:
iInfo = cgi.MSG_ReadByte();
cgi.HudDrawElements[iInfo].vColor[3] = cgi.MSG_ReadByte() / 255.0;
break;
case 36:
iInfo = cgi.MSG_ReadByte();
cgi.HudDrawElements[iInfo].hShader = 0;
strcpy(cgi.HudDrawElements[iInfo].string, cgi.MSG_ReadString());
break;
case 37:
iInfo = cgi.MSG_ReadByte();
strcpy(cgi.HudDrawElements[iInfo].fontName, cgi.MSG_ReadString());
cgi.HudDrawElements[iInfo].hShader = 0;
cgi.HudDrawElements[iInfo].shaderName[0] = 0;
// load the font
CG_HudDrawFont(iInfo);
break;
case 38:
case 39:
{
int iOldEnt;
iOldEnt = current_entity_number;
current_entity_number = cg.snap->ps.clientNum;
if (iType == 36) {
commandManager.PlaySound(
"dm_kill_notify",
NULL,
CHAN_LOCAL,
2.0,
-1,
-1,
1
);
}
else {
commandManager.PlaySound(
"dm_hit_notify",
NULL,
CHAN_LOCAL,
2.0,
-1,
-1,
1
);
}
current_entity_number = iOldEnt;
}
break;
case 40:
{
int iOldEnt;
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
iLarge = cgi.MSG_ReadBits(1);
iInfo = cgi.MSG_ReadBits(6);
szTmp = cgi.MSG_ReadString();
iOldEnt = current_entity_number;
if (iLarge) {
current_entity_number = iInfo;
commandManager.PlaySound(
szTmp,
vStart,
CHAN_LOCAL,
-1,
-1,
-1,
0
);
}
else {
current_entity_number = cg.snap->ps.clientNum;
commandManager.PlaySound(
szTmp,
vStart,
CHAN_AUTO,
-1,
-1,
-1,
1
);
}
current_entity_number = iOldEnt;
}
break;
case 41:
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
vEnd[0] = cgi.MSG_ReadCoord();
vEnd[1] = cgi.MSG_ReadCoord();
vEnd[2] = cgi.MSG_ReadCoord();
cgi.MSG_ReadByte();
cgi.MSG_ReadByte();
VectorSubtract(vEnd, vStart, vTmp);
// FIXME: unimplemented
// ?? can't figure out what is this
break;
default:
cgi.Error(ERR_DROP, "CG_ParseCGMessage: Unknown CGM message type");
break;
}
bMoreCGameMessages = cgi.MSG_ReadBits(1);
}
}
#else
void CG_ParseCGMessage()
{
int i;
@@ -580,13 +1037,15 @@ void CG_ParseCGMessage()
cgi.HudDrawElements[iInfo].bVirtualScreen = cgi.MSG_ReadBits(1);
break;
case 31:
case 31:
iInfo = cgi.MSG_ReadByte();
cgi.HudDrawElements[iInfo].vColor[0] = cgi.MSG_ReadByte() / 255.0;
cgi.HudDrawElements[iInfo].vColor[1] = cgi.MSG_ReadByte() / 255.0;
cgi.HudDrawElements[iInfo].vColor[2] = cgi.MSG_ReadByte() / 255.0;
break;
case 32:
case 32:
iInfo = cgi.MSG_ReadByte();
cgi.HudDrawElements[iInfo].vColor[3] = cgi.MSG_ReadByte() / 255.0;
break;
@@ -682,10 +1141,12 @@ void CG_ParseCGMessage()
current_entity_number = iOldEnt;
}
break;
default:
cgi.Error(ERR_DROP, "CG_ParseCGMessage: Unknown CGM message type");
break;
}
bMoreCGameMessages = cgi.MSG_ReadBits(1);
}
// FIXME: unimplemented
}
#endif
+1 -1
View File
@@ -404,7 +404,7 @@ typedef struct {
// FIXME
//prof_cgame_t* profStruct;
qboolean (*CG_Command_ProcessFile)(char* name, qboolean quiet, dtiki_t* curTiki);
qboolean (*CG_Command_ProcessFile)(const char* name, qboolean quiet, dtiki_t* curTiki);
} clientGameExport_t;
+428 -72
View File
@@ -54,63 +54,419 @@ int CG_GetScoreBoardDrawHeader()
return 0;
}
const char* CG_GetColumnName(int iColumnNum, int* iColumnWidth)
{
int iReturnWidth;
const char* pszReturnString;
switch (iColumnNum) {
case 0:
iReturnWidth = 128;
pszReturnString = "Name";
break;
case 1:
iReturnWidth = 64;
pszReturnString = "Kills";
break;
case 2:
iReturnWidth = 64;
pszReturnString = "Deaths";
if (cgs.gametype > GT_TEAM) {
pszReturnString = "Total";
}
break;
case 3:
iReturnWidth = 64;
pszReturnString = "Time";
break;
case 4:
iReturnWidth = 64;
pszReturnString = "Ping";
break;
default:
iReturnWidth = 0;
pszReturnString = 0;
break;
}
if (iColumnWidth) {
*iColumnWidth = iReturnWidth;
}
return pszReturnString;
}
void CG_PrepScoreBoardInfo()
{
switch (cgs.gametype) {
switch (cgs.gametype) {
case GT_TEAM_ROUNDS:
strcpy(cg.scoresMenuName, "DM_Round_Scoreboard");
break;
case GT_OBJECTIVE:
strcpy(cg.scoresMenuName, "Obj_Scoreboard");
break;
case GT_TEAM_ROUNDS:
strcpy(cg.scoresMenuName, "DM_Round_Scoreboard");
break;
break;
case GT_TOW:
strcpy(cg.scoresMenuName, "Tow_Scoreboard");
break;
case GT_LIBERATION:
strcpy(cg.scoresMenuName, "Lib_Scoreboard");
break;
default:
strcpy(cg.scoresMenuName, "DM_Scoreboard");
break;
}
}
#if TARGET_GAME_PROTOCOL >= 15
const char* CG_GetColumnName(int iColumnNum, int* iColumnWidth)
{
int iReturnWidth;
const char* pszReturnString;
switch (iColumnNum) {
case 0:
iReturnWidth = 24;
pszReturnString = "#";
break;
case 1:
iReturnWidth = 128;
pszReturnString = "Name";
break;
case 2:
iReturnWidth = 64;
pszReturnString = "Kills";
break;
case 3:
iReturnWidth = 64;
pszReturnString = "Deaths";
if (cgs.gametype > GT_TEAM) {
pszReturnString = "Total";
}
break;
case 4:
iReturnWidth = 64;
pszReturnString = "Time";
break;
case 5:
iReturnWidth = 64;
pszReturnString = "Ping";
break;
default:
iReturnWidth = 0;
pszReturnString = 0;
break;
}
if (iColumnWidth) {
*iColumnWidth = iReturnWidth;
}
return pszReturnString;
}
void CG_ParseScores()
{
int i;
int iEntryCount;
int iClientTeam, iClientNum;
int iDatumCount;
int iMatchTeam;
int iCurrentEntry;
qboolean bIsDead, bIsHeader;
char szString2[MAX_STRING_TOKENS];
char szString3[MAX_STRING_TOKENS];
char szString4[MAX_STRING_TOKENS];
char szString5[MAX_STRING_TOKENS];
char szString6[MAX_STRING_TOKENS];
char szString7[MAX_STRING_TOKENS];
float vSameTeamTextColor[4];
float vSameTeamBackColor[4];
float vOtherTeamTextColor[4];
float vOtherTeamBackColor[4];
float vNoTeamTextColor[4];
float vNoTeamBackColor[4];
float vThisClientTextColor[4];
float vThisClientBackColor[4];
float vDeadTextColorDead[4];
float* pItemTextColor;
float* pItemBackColor;
iMatchTeam = -1;
vSameTeamTextColor[0] = 1.0f;
vSameTeamTextColor[1] = 1.0f;
vSameTeamTextColor[2] = 1.0f;
vSameTeamTextColor[3] = 1.0f;
vSameTeamBackColor[0] = 0.1f;
vSameTeamBackColor[1] = 0.5f;
vSameTeamBackColor[2] = 0.1f;
vSameTeamBackColor[3] = 0.4f;
vOtherTeamTextColor[0] = 1.0f;
vOtherTeamTextColor[1] = 1.0f;
vOtherTeamTextColor[2] = 1.0f;
vOtherTeamTextColor[3] = 1.0f;
vOtherTeamBackColor[0] = 0.5f;
vOtherTeamBackColor[1] = 0.1f;
vOtherTeamBackColor[2] = 0.1f;
vOtherTeamBackColor[3] = 0.4f;
vNoTeamTextColor[0] = 1.0f;
vNoTeamTextColor[1] = 1.0f;
vNoTeamTextColor[2] = 1.0f;
vNoTeamTextColor[3] = 1.0f;
vNoTeamBackColor[0] = 0.1f;
vNoTeamBackColor[1] = 0.1f;
vNoTeamBackColor[2] = 0.1f;
vNoTeamBackColor[3] = 0.4f;
vDeadTextColorDead[0] = 1.0f;
vDeadTextColorDead[1] = 0.1f;
vDeadTextColorDead[2] = 0.1f;
vDeadTextColorDead[3] = 1.0f;
vThisClientTextColor[0] = 0.0f;
vThisClientTextColor[1] = 0.0f;
vThisClientTextColor[2] = 0.0f;
vThisClientTextColor[3] = 1.0f;
if (cgs.gametype > GT_FFA)
{
vThisClientBackColor[0] = 0.5f;
vThisClientBackColor[1] = 0.75f;
vThisClientBackColor[2] = 0.5f;
}
else
{
vThisClientBackColor[0] = 0.75f;
vThisClientBackColor[1] = 0.75f;
vThisClientBackColor[2] = 0.75f;
}
vThisClientBackColor[3] = 0.8f;
iCurrentEntry = 1;
if (cgs.gametype > GT_FFA)
{
iDatumCount = 6;
iMatchTeam = cg.snap->ps.stats[STAT_TEAM];
if (iMatchTeam != TEAM_ALLIES && iMatchTeam != TEAM_AXIS)
{
iMatchTeam = TEAM_ALLIES;
vThisClientTextColor[0] = 0.0f;
vThisClientTextColor[1] = 0.0f;
vThisClientTextColor[2] = 0.0f;
vThisClientBackColor[0] = 0.75f;
vThisClientBackColor[1] = 0.75f;
vThisClientBackColor[2] = 0.75f;
}
}
else
{
// free-for-all
iDatumCount = 5;
}
iEntryCount = atoi(cgi.Argv(iCurrentEntry++));
if (iEntryCount > MAX_CLIENTS) {
iEntryCount = MAX_CLIENTS;
}
if (cgs.gametype == GT_TOW)
{
cgi.Cvar_Set("tow_allied_obj1", va("%i", (int)atof(cgi.Argv(iCurrentEntry++))));
cgi.Cvar_Set("tow_allied_obj2", va("%i", (int)atof(cgi.Argv(iCurrentEntry++))));
cgi.Cvar_Set("tow_allied_obj3", va("%i", (int)atof(cgi.Argv(iCurrentEntry++))));
cgi.Cvar_Set("tow_allied_obj4", va("%i", (int)atof(cgi.Argv(iCurrentEntry++))));
cgi.Cvar_Set("tow_allied_obj5", va("%i", (int)atof(cgi.Argv(iCurrentEntry++))));
cgi.Cvar_Set("tow_axis_obj1", va("%i", (int)atof(cgi.Argv(iCurrentEntry++))));
cgi.Cvar_Set("tow_axis_obj2", va("%i", (int)atof(cgi.Argv(iCurrentEntry++))));
cgi.Cvar_Set("tow_axis_obj3", va("%i", (int)atof(cgi.Argv(iCurrentEntry++))));
cgi.Cvar_Set("tow_axis_obj4", va("%i", (int)atof(cgi.Argv(iCurrentEntry++))));
cgi.Cvar_Set("tow_axis_obj5", va("%i", (int)atof(cgi.Argv(iCurrentEntry++))));
}
if (cgs.gametype == GT_LIBERATION)
{
cgi.Cvar_Set("scoreboard_toggle1", va("%i", (int)atof(cgi.Argv(iCurrentEntry++))));
cgi.Cvar_Set("scoreboard_toggle2", va("%i", (int)atof(cgi.Argv(iCurrentEntry++))));
}
for (i = 0; i < iEntryCount; ++i)
{
bIsHeader = qfalse;
if (cgs.gametype > GT_FFA)
{
iClientNum = atoi(cgi.Argv(iCurrentEntry + iDatumCount * i));
iClientTeam = atoi(cgi.Argv(1 + iCurrentEntry + iDatumCount * i));
if (iClientTeam >= 0) {
bIsDead = qfalse;
}
else {
bIsDead = qtrue;
iClientTeam = -iClientTeam;
}
if (iClientNum == -1)
{
szString2[0] = 0;
bIsHeader = qtrue;
switch (iClientTeam)
{
case 1:
strcpy(szString3, cgi.LV_ConvertString("Spectators"));
break;
case 2:
strcpy(szString3, cgi.LV_ConvertString("Free-For-Allers"));
break;
case 3:
sprintf(
szString3,
"%s - %d %s",
cgi.LV_ConvertString("Allies"),
atoi(cgi.Argv(2 + iCurrentEntry + iDatumCount * i)),
cgi.LV_ConvertString("Players")
);
iCurrentEntry++;
break;
case 4:
sprintf(
szString3,
"%s - %d %s",
cgi.LV_ConvertString("Axis"),
atoi(cgi.Argv(2 + iCurrentEntry + iDatumCount * i)),
cgi.LV_ConvertString("Players")
);
iCurrentEntry++;
break;
default:
strcpy(szString3, cgi.LV_ConvertString("No Team"));
break;
}
}
else if (iClientNum == -2)
{
// spectating
szString2[0] = 0;
szString3[0] = 0;
}
else
{
strcpy(szString2, va("%i", iClientNum));
strcpy(szString3, cg.clientinfo[iClientNum].name);
}
strcpy(szString4, cgi.Argv(2 + iCurrentEntry + iDatumCount * i));
strcpy(szString5, cgi.Argv(3 + iCurrentEntry + iDatumCount * i));
strcpy(szString6, cgi.Argv(4 + iCurrentEntry + iDatumCount * i));
strcpy(szString7, cgi.Argv(5 + iCurrentEntry + iDatumCount * i));
if (cgs.gametype >= GT_TEAM_ROUNDS && iClientNum == -1 && iClientTeam == TEAM_ALLIES || iClientTeam == TEAM_AXIS)
{
strcat(szString4, va(" %s", cgi.LV_ConvertString("Wins")));
szString5[0] = 0;
}
if (iClientNum == cg.snap->ps.clientNum)
{
pItemTextColor = vThisClientTextColor;
pItemBackColor = vThisClientBackColor;
}
else if (iClientNum == -2)
{
pItemTextColor = vNoTeamTextColor;
pItemBackColor = vNoTeamBackColor;
}
else if (iClientTeam == TEAM_ALLIES || iClientTeam == TEAM_AXIS)
{
if (iClientTeam == iMatchTeam)
{
pItemTextColor = vSameTeamTextColor;
pItemBackColor = vSameTeamBackColor;
}
else
{
pItemTextColor = vOtherTeamTextColor;
pItemBackColor = vOtherTeamBackColor;
}
}
else
{
pItemTextColor = vNoTeamTextColor;
pItemBackColor = vNoTeamBackColor;
}
if (bIsDead) {
pItemTextColor = vDeadTextColorDead;
}
}
else
{
iClientNum = atoi(cgi.Argv(iDatumCount * i));
if (iClientNum >= 0)
{
strcpy(szString2, va("%i", iClientNum));
strcpy(szString3, cg.clientinfo[iClientNum].name);
strcpy(szString4, cgi.Argv(1 + iCurrentEntry + iDatumCount * i));
strcpy(szString5, cgi.Argv(2 + iCurrentEntry + iDatumCount * i));
strcpy(szString6, cgi.Argv(3 + iCurrentEntry + iDatumCount * i));
strcpy(szString7, cgi.Argv(4 + iCurrentEntry + iDatumCount * i));
}
else
{
szString2[0] = 0;
if (iClientNum == -3)
{
strcpy(szString2, cgi.LV_ConvertString("Players"));
bIsHeader = qtrue;
}
else if (iClientNum == -2)
{
strcpy(szString2, cgi.LV_ConvertString("Spectators"));
bIsHeader = qtrue;
}
else
{
// unknown
szString3[0] = 0;
}
szString4[0] = 0;
szString5[0] = 0;
szString6[0] = 0;
szString7[0] = 0;
}
if (iClientNum == cg.snap->ps.clientNum)
{
pItemTextColor = vThisClientTextColor;
pItemBackColor = vThisClientBackColor;
}
else
{
pItemTextColor = vNoTeamTextColor;
pItemBackColor = vNoTeamBackColor;
}
}
cgi.UI_SetScoreBoardItem(
i,
szString2,
szString3,
szString4,
szString5,
szString6,
szString7,
NULL,
NULL,
pItemTextColor,
pItemBackColor,
bIsHeader
);
}
cgi.UI_DeleteScoreBoardItems(iEntryCount);
}
#else
const char* CG_GetColumnName(int iColumnNum, int* iColumnWidth)
{
int iReturnWidth;
const char* pszReturnString;
switch (iColumnNum) {
case 0:
iReturnWidth = 128;
pszReturnString = "Name";
break;
case 1:
iReturnWidth = 64;
pszReturnString = "Kills";
break;
case 2:
iReturnWidth = 64;
pszReturnString = "Deaths";
if (cgs.gametype > GT_TEAM) {
pszReturnString = "Total";
}
break;
case 3:
iReturnWidth = 64;
pszReturnString = "Time";
break;
case 4:
iReturnWidth = 64;
pszReturnString = "Ping";
break;
default:
iReturnWidth = 0;
pszReturnString = 0;
break;
}
if (iColumnWidth) {
*iColumnWidth = iReturnWidth;
}
return pszReturnString;
}
void CG_ParseScores()
{
int i;
@@ -118,13 +474,13 @@ void CG_ParseScores()
int iClientTeam, iClientNum;
int iDatumCount;
int iMatchTeam;
int iCurrentEntry;
qboolean bIsDead, bIsHeader;
char szString2[MAX_STRING_TOKENS];
char szString3[MAX_STRING_TOKENS];
char szString4[MAX_STRING_TOKENS];
char szString5[MAX_STRING_TOKENS];
char szString6[MAX_STRING_TOKENS];
const char* pszClientInfo;
float vSameTeamTextColor[4];
float vSameTeamBackColor[4];
float vOtherTeamTextColor[4];
@@ -187,6 +543,7 @@ void CG_ParseScores()
vThisClientBackColor[3] = 0.8f;
iCurrentEntry = 1;
if (cgs.gametype > GT_FFA)
{
iDatumCount = 6;
@@ -208,7 +565,7 @@ void CG_ParseScores()
iDatumCount = 5;
}
iEntryCount = atoi(cgi.Argv(1));
iEntryCount = atoi(cgi.Argv(iCurrentEntry++));
if (iEntryCount > MAX_CLIENTS) {
iEntryCount = MAX_CLIENTS;
}
@@ -218,8 +575,8 @@ void CG_ParseScores()
bIsHeader = qfalse;
if (cgs.gametype > GT_FFA)
{
iClientNum = atoi(cgi.Argv(2 + iDatumCount * i));
iClientTeam = atoi(cgi.Argv(3 + iDatumCount * i));
iClientNum = atoi(cgi.Argv(iCurrentEntry + iDatumCount * i));
iClientTeam = atoi(cgi.Argv(1 + iCurrentEntry + iDatumCount * i));
if (iClientTeam >= 0) {
bIsDead = qfalse;
}
@@ -235,19 +592,19 @@ void CG_ParseScores()
switch (iClientTeam)
{
case 1:
strcpy(szString2, "Spectators");
strcpy(szString2, cgi.LV_ConvertString("Spectators"));
break;
case 2:
strcpy(szString2, "Free-For-Allers");
strcpy(szString2, cgi.LV_ConvertString("Free-For-Allers"));
break;
case 3:
strcpy(szString2, "Allies");
strcpy(szString2, cgi.LV_ConvertString("Allies"));
break;
case 4:
strcpy(szString2, "Axis");
strcpy(szString2, cgi.LV_ConvertString("Axis"));
break;
default:
strcpy(szString2, "No Team");
strcpy(szString2, cgi.LV_ConvertString("No Team"));
break;
}
}
@@ -257,15 +614,14 @@ void CG_ParseScores()
szString2[0] = 0;
}
else
{
pszClientInfo = CG_ConfigString(CS_PLAYERS + iClientNum);
strcpy(szString2, Info_ValueForKey(pszClientInfo, "name"));
{
strcpy(szString2, cg.clientinfo[iClientNum].name);
}
strcpy(szString3, cgi.Argv(4 + iDatumCount * i));
strcpy(szString4, cgi.Argv(5 + iDatumCount * i));
strcpy(szString5, cgi.Argv(6 + iDatumCount * i));
strcpy(szString6, cgi.Argv(7 + iDatumCount * i));
strcpy(szString3, cgi.Argv(2 + iCurrentEntry + iDatumCount * i));
strcpy(szString4, cgi.Argv(3 + iCurrentEntry + iDatumCount * i));
strcpy(szString5, cgi.Argv(4 + iCurrentEntry + iDatumCount * i));
strcpy(szString6, cgi.Argv(5 + iCurrentEntry + iDatumCount * i));
if (iClientNum == cg.snap->ps.clientNum)
{
@@ -302,26 +658,25 @@ void CG_ParseScores()
}
else
{
iClientNum = atoi(cgi.Argv(2 + iDatumCount * i));
iClientNum = atoi(cgi.Argv(iCurrentEntry + iDatumCount * i));
if (iClientNum >= 0)
{
pszClientInfo = CG_ConfigString(CS_PLAYERS + iClientNum);
strcpy(szString2, Info_ValueForKey(pszClientInfo, "name"));
strcpy(szString3, cgi.Argv(3 + iDatumCount * i));
strcpy(szString4, cgi.Argv(4 + iDatumCount * i));
strcpy(szString5, cgi.Argv(5 + iDatumCount * i));
strcpy(szString6, cgi.Argv(6 + iDatumCount * i));
strcpy(szString2, cg.clientinfo[iClientNum].name);
strcpy(szString3, cgi.Argv(1 + iCurrentEntry + iDatumCount * i));
strcpy(szString4, cgi.Argv(2 + iCurrentEntry + iDatumCount * i));
strcpy(szString5, cgi.Argv(3 + iCurrentEntry + iDatumCount * i));
strcpy(szString6, cgi.Argv(4 + iCurrentEntry + iDatumCount * i));
}
else
{
if (iClientNum == -3)
{
strcpy(szString2, "Players");
strcpy(szString2, cgi.LV_ConvertString("Players"));
bIsHeader = qtrue;
}
else if (iClientNum == -2)
{
strcpy(szString2, "Spectators");
strcpy(szString2, cgi.LV_ConvertString("Spectators"));
bIsHeader = qtrue;
}
else
@@ -365,3 +720,4 @@ void CG_ParseScores()
cgi.UI_DeleteScoreBoardItems(iEntryCount);
}
#endif
+134 -5
View File
@@ -25,6 +25,58 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cg_local.h"
static const char* IsWeaponAllowed(int dmFlags, int flags) {
return (dmFlags & flags) ? "0" : "1";
}
static qboolean QueryLandminesAllowed2(const char* mapname, int dmflags) {
if (dmflags & DF_WEAPON_NO_LANDMINE) {
return qfalse;
}
if (dmflags & DF_WEAPON_LANDMINE_ALWAYS) {
return qtrue;
}
if (!Q_stricmpn(mapname, "obj/obj_", 8u))
return qfalse;
if (!Q_stricmpn(mapname, "dm/mohdm", 8u))
return qfalse;
if (!Q_stricmp(mapname, "DM/MP_Bahnhof_DM"))
return qfalse;
if (!Q_stricmp(mapname, "obj/MP_Ardennes_TOW"))
return qfalse;
if (!Q_stricmp(mapname, "DM/MP_Bazaar_DM"))
return qfalse;
if (!Q_stricmp(mapname, "obj/MP_Berlin_TOW"))
return qfalse;
if (!Q_stricmp(mapname, "DM/MP_Brest_DM"))
return qfalse;
if (!Q_stricmp(mapname, "obj/MP_Druckkammern_TOW"))
return qfalse;
if (!Q_stricmp(mapname, "DM/MP_Gewitter_DM"))
return qfalse;
if (!Q_stricmp(mapname, "obj/MP_Flughafen_TOW"))
return qfalse;
if (!Q_stricmp(mapname, "DM/MP_Holland_DM"))
return qfalse;
if (!Q_stricmp(mapname, "DM/MP_Malta_DM"))
return qfalse;
if (!Q_stricmp(mapname, "DM/MP_Stadt_DM"))
return qfalse;
if (!Q_stricmp(mapname, "DM/MP_Unterseite_DM"))
return qfalse;
if (!Q_stricmp(mapname, "DM/MP_Verschneit_DM"))
return qfalse;
if (!Q_stricmp(mapname, "lib/mp_ship_lib"))
return qfalse;
if (!Q_stricmp(mapname, "DM/MP_Verschneit_DM"))
return qfalse;
if (!Q_stricmp(mapname, "lib/mp_ship_lib"))
return qfalse;
return qtrue;
}
/*
================
CG_ParseServerinfo
@@ -39,6 +91,7 @@ void CG_ParseServerinfo(void)
const char* mapname;
char map[MAX_QPATH];
char* spawnpos;
const char* version;
info = CG_ConfigString(CS_SERVERINFO);
cgs.gametype = atoi(Info_ValueForKey(info, "g_gametype"));
@@ -48,6 +101,13 @@ void CG_ParseServerinfo(void)
cgs.timelimit = atoi(Info_ValueForKey(info, "timelimit"));
cgs.maxclients = atoi(Info_ValueForKey(info, "sv_maxclients"));
version = Info_ValueForKey(info, "version");
if (strstr(version, "Spearhead")) {
cgi.Cvar_Set("g_servertype", "1");
} else {
cgi.Cvar_Set("g_servertype", "2");
}
cgi.Cvar_Set("cg_gametype", Info_ValueForKey(info, "g_gametype"));
cgi.Cvar_Set("cg_fraglimit", Info_ValueForKey(info, "fraglimit"));
cgi.Cvar_Set("cg_timelimit", Info_ValueForKey(info, "timelimit"));
@@ -60,9 +120,18 @@ void CG_ParseServerinfo(void)
cgi.Cvar_Set("cg_obj_axistext3", Info_ValueForKey(info, "cg_obj_axistext3"));
cgi.Cvar_Set("cg_scoreboardpic", Info_ValueForKey(info, "g_scoreboardpic"));
cgi.Cvar_Set("cg_scoreboardpicover", Info_ValueForKey(info, "g_scoreboardpicover"));
cgs.mapChecksum = atoi(Info_ValueForKey(info, "sv_mapChecksum"));
mapname = Info_ValueForKey(info, "mapname");
cgi.Cvar_Set("cg_weapon_rifle", IsWeaponAllowed(cgs.dmflags, DF_WEAPON_NO_RIFLE));
cgi.Cvar_Set("cg_weapon_sniper", IsWeaponAllowed(cgs.dmflags, DF_WEAPON_NO_SNIPER));
cgi.Cvar_Set("cg_weapon_mg", IsWeaponAllowed(cgs.dmflags, DF_WEAPON_NO_MG));
cgi.Cvar_Set("cg_weapon_smg", IsWeaponAllowed(cgs.dmflags, DF_WEAPON_NO_SMG));
cgi.Cvar_Set("cg_weapon_rocket", IsWeaponAllowed(cgs.dmflags, DF_WEAPON_NO_ROCKET));
cgi.Cvar_Set("cg_weapon_shotgun", IsWeaponAllowed(cgs.dmflags, DF_WEAPON_NO_SHOTGUN));
cgi.Cvar_Set("cg_weapon_landmine", QueryLandminesAllowed2(mapname, cgs.dmflags) ? "1" : "0");
spawnpos = strchr(mapname, '$');
if (spawnpos) {
Q_strncpyz(map, mapname, spawnpos - mapname + 1);
@@ -150,16 +219,32 @@ CG_Stopwatch_f
================
*/
#if TARGET_GAME_PROTOCOL >= 15
static void CG_Stopwatch_f()
{
if (cgi.Argc() != 3) {
Com_Error(1, "stopwatch didn't have 2 parameters");
}
if (cgi.Argc() < 3) {
Com_Error(ERR_DROP, "stopwatch didn't have 2 parameters");
}
cgi.stopWatch->iStartTime = 1000 * atoi(cgi.Argv(1));
cgi.stopWatch->iEndTime = cgi.stopWatch->iStartTime + 1000 * atoi(cgi.Argv(2));
cgi.stopWatch->iStartTime = atoi(cgi.Argv(1));
cgi.stopWatch->iEndTime = cgi.stopWatch->iStartTime + 1000 * atoi(cgi.Argv(2));
}
#else
static void CG_Stopwatch_f()
{
if (cgi.Argc() < 3) {
Com_Error(ERR_DROP, "stopwatch didn't have 2 parameters");
}
cgi.stopWatch->iStartTime = 1000 * atoi(cgi.Argv(1));
cgi.stopWatch->iEndTime = cgi.stopWatch->iStartTime + 1000 * atoi(cgi.Argv(2));
}
#endif
/*
================
CG_ServerLag_f
@@ -202,6 +287,50 @@ static void CG_ServerCommand(void)
}
return;
}
else if (!strcmp(cmd, "printdeathmsg")) {
const char* s1, * s2, * s3, * s4, * s5;
const char* result1, * result2;
int hudColor;
result1 = NULL;
result2 = NULL;
s1 = cgi.Argv(1);
s2 = cgi.Argv(2);
s3 = cgi.Argv(3);
s4 = cgi.Argv(4);
s5 = cgi.Argv(5);
if (*s5 == tolower(*s5)) {
hudColor = 4;
} else {
hudColor = 5;
}
if (*s1 != 'x')
result1 = cgi.LV_ConvertString(s1);
if (*s2 != 'x')
result2 = cgi.LV_ConvertString(s2);
if (tolower(*s5) == 's')
{
cgi.Printf("%c%s %s\n", hudColor, s4, result1);
}
else if (tolower(*s5) == 'p')
{
if (*s2 == 'x')
cgi.Printf("%c%s %s %s\n", hudColor, s4, result1, s3);
else
cgi.Printf("%c%s %s %s%s\n", hudColor, s4, result1, s3, result2);
}
else if (tolower(*s5) == 'w')
{
cgi.Printf("%c%s %s\n", hudColor, s4, result1);
}
else
{
cgi.Printf("%s", cgi.Argv(1));
}
return;
}
if (!strcmp(cmd, "stufftext")) {
cgi.Cmd_Stuff(cgi.Argv(1));
+1 -1
View File
@@ -799,7 +799,7 @@ void CG_DrawActiveFrame( int serverTime, int frameTime, stereoFrame_t stereoView
cgi.SendClientCommand("stats");
}
cg.bIntermissionDisplay = qfalse;
cg.bIntermissionDisplay = qtrue;
}
else if (cg.bIntermissionDisplay)
{
+179 -12
View File
@@ -46,7 +46,40 @@ static const char* AnimPrefixList[] =
"bazooka",
"panzerschreck",
"shotgun",
"unarmed"
"unarmed",
//
// Team Assault and Team Tactics weapons
"mg42portable",
"webley",
"nagantrev",
"beretta",
"enfield",
"svt",
"mosin",
"g43",
"enfieldl42a1",
"carcano",
"delisle",
"thompson",
"sten",
"ppsh",
"moschetto",
"fg42",
"vickers",
"breda",
"f1grenade",
"millsgrenade",
"nebelhandgranate",
"m18smokegrenade",
"rdg1smokegrenade",
"bomba",
"bombabreda",
"mine",
"minedetector",
"minedetectoraxis",
"detonator",
"kar98mortar",
"PIAT"
};
enum animPrefix_e
@@ -69,7 +102,39 @@ enum animPrefix_e
WPREFIX_BAZOOKA,
WPREFIX_PANZERSCHRECK,
WPREFIX_SHOTGUN,
WPREFIX_UNARMED
WPREFIX_UNARMED,
//
// Team Assault and Team Tactics weapons
WPREFIX_MG42_PORTABLE,
WPREFIX_WEBLEY,
WPREFIX_NAGANTREV,
WPREFIX_BERETTA,
WPREFIX_ENFIELD,
WPREFIX_SVT,
WPREFIX_MOSIN,
WPREFIX_G43,
WPREFIX_ENFIELDL42A,
WPREFIX_CARCANO,
WPREFIX_DELISLE,
WPREFIX_STEN,
WPREFIX_PPSH,
WPREFIX_MOSCHETTO,
WPREFIX_FG42,
WPREFIX_VICKERS,
WPREFIX_BREDA,
WPREFIX_F1_GRENADE,
WPREFIX_MILLS_GRENADE,
WPREFIX_NEBELHANDGRANATE,
WPREFIX_M18_SMOKE_GRENADE,
WPREFIX_RDG1_SMOKE_GRENADE,
WPREFIX_BOMBA,
WPREFIX_BOMBA_BREDA,
WPREFIX_MINE,
WPREFIX_MINE_DETECTOR,
WPREFIX_MINE_DETECTOR_AXIS,
WPREFIX_DETONATOR,
WPREFIX_KAR98_MORTAR,
WPREFIX_PIAT
};
int CG_GetVMAnimPrefixIndex()
@@ -83,7 +148,9 @@ int CG_GetVMAnimPrefixIndex()
if (iWeaponClass & WEAPON_CLASS_ANY_ITEM)
{
if (!Q_stricmp(szWeaponName, "Papers"))
return WPREFIX_PAPERS;
return WPREFIX_PAPERS;
if (!Q_stricmp(szWeaponName, "Packed MG42 Turret"))
return WPREFIX_MG42_PORTABLE;
}
else if (iWeaponClass & WEAPON_CLASS_PISTOL)
{
@@ -92,7 +159,19 @@ int CG_GetVMAnimPrefixIndex()
if (!Q_stricmp(szWeaponName, "Walther P38"))
return WPREFIX_P38;
if (!Q_stricmp(szWeaponName, "Hi-Standard Silenced"))
return WPREFIX_HISTANDARD;
return WPREFIX_HISTANDARD;
//
// Team Assault and Team Tactics
//
if (!Q_stricmp(szWeaponName, "Webley Revolver"))
return WPREFIX_WEBLEY;
if (!Q_stricmp(szWeaponName, "Nagant Revolver"))
return WPREFIX_NAGANTREV;
if (!Q_stricmp(szWeaponName, "Beretta"))
return WPREFIX_BERETTA;
return WPREFIX_COLT45;
}
else if (iWeaponClass & WEAPON_CLASS_RIFLE)
{
@@ -103,28 +182,97 @@ int CG_GetVMAnimPrefixIndex()
if (!Q_stricmp(szWeaponName, "KAR98 - Sniper"))
return WPREFIX_KAR98SNIPER;
if (!Q_stricmp(szWeaponName, "Springfield '03 Sniper"))
return WPREFIX_SPRINGFIELD;
return WPREFIX_SPRINGFIELD;
//
// Team Assault and Team Tactics
//
if (!Q_stricmp(szWeaponName, "Lee-Enfield"))
return WPREFIX_SPRINGFIELD;
if (!Q_stricmp(szWeaponName, "SVT 40"))
return WPREFIX_SVT;
if (!Q_stricmp(szWeaponName, "Mosin Nagant Rifle"))
return WPREFIX_MOSIN;
if (!Q_stricmp(szWeaponName, "G 43"))
return WPREFIX_G43;
if (!Q_stricmp(szWeaponName, "Enfield L42A1"))
return WPREFIX_ENFIELD;
if (!Q_stricmp(szWeaponName, "Carcano"))
return WPREFIX_CARCANO;
if (!Q_stricmp(szWeaponName, "DeLisle"))
return WPREFIX_DELISLE;
return WPREFIX_GARAND;
}
else if (iWeaponClass & WEAPON_CLASS_SMG)
{
if (!Q_stricmp(szWeaponName, "Thompson"))
return WPREFIX_THOMPSON;
if (!Q_stricmp(szWeaponName, "MP40"))
return WPREFIX_MP40;
return WPREFIX_MP40;
//
// Team Assault and Team Tactics
//
if (!Q_stricmp(szWeaponName, "Sten Mark II"))
return WPREFIX_STEN;
if (!Q_stricmp(szWeaponName, "PPSH SMG"))
return WPREFIX_PPSH;
if (!Q_stricmp(szWeaponName, "Moschetto"))
return WPREFIX_MOSCHETTO;
return WPREFIX_THOMPSON;
}
else if (iWeaponClass & WEAPON_CLASS_MG)
{
if (!Q_stricmp(szWeaponName, "BAR"))
return WPREFIX_BAR;
if (!Q_stricmp(szWeaponName, "StG 44"))
return WPREFIX_MP44;
return WPREFIX_MP44;
//
// Team Assault and Team Tactics
//
if (!Q_stricmp(szWeaponName, "FG 42"))
return WPREFIX_MP44;
if (!Q_stricmp(szWeaponName, "Vickers-Berthier"))
return WPREFIX_MP44;
if (!Q_stricmp(szWeaponName, "Breda"))
return WPREFIX_MP44;
return WPREFIX_BAR;
}
else if (iWeaponClass & WEAPON_CLASS_GRENADE)
{
if (!Q_stricmp(szWeaponName, "Frag Grenade"))
return WPREFIX_FRAGGRENADE;
if (!Q_stricmp(szWeaponName, "Stielhandgranate"))
return WPREFIX_STIELHANDGRANATE;
return WPREFIX_STIELHANDGRANATE;
//
// Team Assault and Team Tactics
//
if (!Q_stricmp(szWeaponName, "F1 Grenade"))
return WPREFIX_F1_GRENADE;
if (!Q_stricmp(szWeaponName, "Mills Grenade"))
return WPREFIX_MILLS_GRENADE;
if (!Q_stricmp(szWeaponName, "Nebelhandgranate"))
return WPREFIX_NEBELHANDGRANATE;
if (!Q_stricmp(szWeaponName, "M18 Smoke Grenade"))
return WPREFIX_M18_SMOKE_GRENADE;
if (!Q_stricmp(szWeaponName, "RDG-1 Smoke Grenade"))
return WPREFIX_RDG1_SMOKE_GRENADE;
if (!Q_stricmp(szWeaponName, "Bomba A Mano"))
return WPREFIX_BOMBA;
if (!Q_stricmp(szWeaponName, "Bomba A Mano Breda"))
return WPREFIX_BOMBA_BREDA;
if (!Q_stricmp(szWeaponName, "LandmineAllies"))
return WPREFIX_MINE;
if (!Q_stricmp(szWeaponName, "LandmineAxis"))
return WPREFIX_MINE;
if (!Q_stricmp(szWeaponName, "Minensuchgerat"))
return WPREFIX_MINE_DETECTOR_AXIS;
if (!Q_stricmp(szWeaponName, "Minedetector"))
return WPREFIX_MINE_DETECTOR;
return WPREFIX_FRAGGRENADE;
}
else if (iWeaponClass & WEAPON_CLASS_HEAVY)
{
@@ -133,7 +281,14 @@ int CG_GetVMAnimPrefixIndex()
if (!Q_stricmp(szWeaponName, "Panzerschreck"))
return WPREFIX_PANZERSCHRECK;
if (!Q_stricmp(szWeaponName, "Shotgun"))
return WPREFIX_SHOTGUN;
return WPREFIX_SHOTGUN;
//
// Team Assault and Team Tactics
//
if (!Q_stricmp(szWeaponName, "PIAT"))
return WPREFIX_PIAT;
return WPREFIX_BAZOOKA;
}
return WPREFIX_UNARMED;
@@ -226,10 +381,22 @@ void CG_ViewModelAnimation(refEntity_t* pModel)
case VM_ANIM_LADDERSTEP:
pszAnimSuffix = "ladderstep";
break;
case VM_ANIM_IDLE:
case VM_ANIM_IDLE_0:
pszAnimSuffix = "idle0";
break;
case VM_ANIM_IDLE_1:
pszAnimSuffix = "idle1";
break;
case VM_ANIM_IDLE_2:
pszAnimSuffix = "idle2";
break;
case VM_ANIM_DISABLED:
pszAnimSuffix = "disabled";
break;
default:
pszAnimSuffix = "idle";
break;
case VM_ANIM_IDLE:
pszAnimSuffix = "idle";
break;
}
sprintf(szAnimName, "%s_%s", AnimPrefixList[iAnimPrefixIndex], pszAnimSuffix);
+13 -8
View File
@@ -145,18 +145,23 @@ void VSS_AddRepulsion(cvssource_t* pA, cvssource_t* pB)
cvssource_t* ClientGameCommandManager::AllocateVSSSource()
{
m_free_vsssources = m_free_vsssources;
cvssource_t* pNew;
if (!m_free_vsssources) {
FreeVSSSource(m_active_vsssources.prev);
}
pNew = m_free_vsssources;
m_free_vsssources = m_free_vsssources->next;
memset(m_free_vsssources, 0, sizeof(cvssource_t));
memset(pNew, 0, sizeof(cvssource_t));
m_free_vsssources->next = m_active_vsssources.next;
m_free_vsssources->prev = &m_active_vsssources;
pNew->next = m_active_vsssources.next;
pNew->prev = &m_active_vsssources;
m_active_vsssources.next->prev = m_free_vsssources;
m_active_vsssources.next = m_free_vsssources;
m_active_vsssources.next->prev = pNew;
m_active_vsssources.next = pNew;
return m_free_vsssources;
return pNew;
}
void ClientGameCommandManager::FreeVSSSource(cvssource_t* p)
@@ -201,7 +206,7 @@ void ClientGameCommandManager::ResetVSSSources()
}
m_vsssources = (cvssource_t*)cgi.Malloc(sizeof(cvssource_t) * m_iAllocatedvsssources);
memset(m_vsssources, 0, sizeof(sizeof(cvssource_t) * m_iAllocatedvsssources));
memset(m_vsssources, 0, sizeof(cvssource_t) * m_iAllocatedvsssources);
m_active_vsssources.next = &m_active_vsssources;
m_active_vsssources.prev = &m_active_vsssources;
+1
View File
@@ -34,6 +34,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// refdef flags
#define RDF_NOWORLDMODEL 1 // used for player configuration screen
#define RDF_FULLBRIGHT 2 // fullbright intensity
#define RDF_HYPERSPACE 4 // teleportation effect
typedef struct
+65 -21
View File
@@ -158,6 +158,10 @@ CL_GetSnapshot
qboolean CL_GetSnapshot( int snapshotNumber, snapshot_t *snapshot ) {
clSnapshot_t *clSnap;
int i, count;
int pnum;
int parents[MAX_ENTITIES_IN_SNAPSHOT];
entityState_t *s1;
int pcount = 0;
if ( snapshotNumber > cl.snap.messageNum ) {
Com_Error( ERR_DROP, "CL_GetSnapshot: snapshotNumber > cl.snapshot.messageNum" );
@@ -187,41 +191,81 @@ qboolean CL_GetSnapshot( int snapshotNumber, snapshot_t *snapshot ) {
snapshot->serverTime = clSnap->serverTime;
Com_Memcpy( snapshot->areamask, clSnap->areamask, sizeof( snapshot->areamask ) );
snapshot->ps = clSnap->ps;
// wombat: sounds
count = clSnap->number_of_sounds;
if (snapshot->number_of_sounds > MAX_SERVER_SOUNDS) {
Com_DPrintf("CL_GetSnapshot: truncated %i sounds to %i\n", count, MAX_SERVER_SOUNDS);
count = MAX_SERVER_SOUNDS;
}
snapshot->number_of_sounds = count;
Com_Memcpy(snapshot->sounds, clSnap->sounds, sizeof(snapshot->sounds[0])* count);
count = clSnap->numEntities;
if ( count > MAX_ENTITIES_IN_SNAPSHOT ) {
Com_DPrintf( "CL_GetSnapshot: truncated %i visible entities to %i\n", count, MAX_ENTITIES_IN_SNAPSHOT );
count = MAX_ENTITIES_IN_SNAPSHOT;
}
snapshot->numEntities = count;
snapshot->numEntities = 0;
for ( i = 0 ; i < count ; i++ ) {
snapshot->entities[i] =
cl.parseEntities[ ( clSnap->parseEntitiesNum + i ) & (MAX_PARSE_ENTITIES-1) ];
s1 = &cl.parseEntities[(clSnap->parseEntitiesNum + i) & (MAX_PARSE_ENTITIES - 1)];
pnum = s1->parent;
if (pnum == ENTITYNUM_NONE) {
parents[s1->number] = -2;
}
else
{
if (parents[pnum] == -2) {
parents[s1->number] = -2;
}
else
{
// add it later
parents[s1->number] = pnum;
continue;
}
}
snapshot->entities[snapshot->numEntities++] = *s1;
}
// wombat: sounds
count = clSnap->number_of_sounds;
if ( snapshot->number_of_sounds > MAX_SERVER_SOUNDS) {
Com_DPrintf( "CL_GetSnapshot: truncated %i sounds to %i\n", count, MAX_SERVER_SOUNDS);
count = MAX_SERVER_SOUNDS;
for(pcount = 0; pcount < 8 && snapshot->numEntities != count; pcount++)
{
for (i = 0; i < count; i++)
{
s1 = &cl.parseEntities[(clSnap->parseEntitiesNum + i) & (MAX_PARSE_ENTITIES - 1)];
pnum = parents[s1->number];
if (pnum >= 0 && parents[pnum] == -2) {
snapshot->entities[snapshot->numEntities++] = *s1;
}
}
}
snapshot->number_of_sounds = count;
Com_Memcpy( snapshot->sounds, clSnap->sounds, sizeof(snapshot->sounds[0])*count );
// FIXME: configstring changes and server commands!!!
if (pcount >= 8)
{
for (i = count; i < snapshot->numEntities; i++)
{
s1 = &cl.parseEntities[(clSnap->parseEntitiesNum + i) & (MAX_PARSE_ENTITIES - 1)];
if (parents[s1->number] >= 0) {
Com_DPrintf(
"CL_GetSnapshot: entity %d with parent %d and model '%s' at %.2f %.2f %.2f, could not find parent.\n",
s1->number,
s1->parent,
CL_ConfigString(CS_MODELS + s1->modelindex),
s1->origin[0],
s1->origin[1],
s1->origin[2]
);
}
}
}
return qtrue;
}
/*
=====================
CL_SetUserCmdValue
=====================
*/
void CL_SetUserCmdValue( int userCmdValue, float sensitivityScale ) {
cl.cgameUserCmdValue = userCmdValue;
cl.cgameSensitivity = sensitivityScale;
}
/*
=====================
CL_AddCgameCommand
+4 -4
View File
@@ -1142,17 +1142,17 @@ redump:
case ZA_SOUND_MONO:
if (!cinTable[currentHandle].silent) {
ssize = RllDecodeMonoToStereo( framedata, sbuf, cinTable[currentHandle].RoQFrameSize, 0, (unsigned short)cinTable[currentHandle].roq_flags);
S_RawSamples(0, ssize, 22050, 2, 1, (byte *)sbuf, 1.0f, -1);
S_RawSamples(0, 22050, 2, 1, (byte *)sbuf, 1.0f);
}
break;
case ZA_SOUND_STEREO:
if (!cinTable[currentHandle].silent) {
if (cinTable[currentHandle].numQuads == -1) {
S_Update();
s_rawend[0] = s_soundtime;
s_rawend = s_soundtime;
}
ssize = RllDecodeStereoToStereo( framedata, sbuf, cinTable[currentHandle].RoQFrameSize, 0, (unsigned short)cinTable[currentHandle].roq_flags);
S_RawSamples(0, ssize, 22050, 2, 2, (byte *)sbuf, 1.0f, -1);
S_RawSamples(0, 22050, 2, 2, (byte *)sbuf, 1.0f);
}
break;
case ROQ_QUAD_INFO:
@@ -1469,7 +1469,7 @@ int CIN_PlayCinematic( const char *arg, int x, int y, int w, int h, int systemBi
}
if (!cinTable[currentHandle].silent) {
s_rawend[0] = s_soundtime;
s_rawend = s_soundtime;
}
return currentHandle;
+100 -88
View File
@@ -242,6 +242,16 @@ void IN_MoveleftDown(void) {IN_KeyDown(&in_moveleft);}
void IN_MoveleftUp(void) {IN_KeyUp(&in_moveleft);}
void IN_MoverightDown(void) {IN_KeyDown(&in_moveright);}
void IN_MoverightUp(void) {IN_KeyUp(&in_moveright);}
void IN_AttackPrimaryDown(void) { IN_KeyDown(&in_buttons[0]);}
void IN_AttackPrimaryUp(void) { IN_KeyUp(&in_buttons[0]); }
void IN_AttackSecondaryDown(void) { IN_KeyDown(&in_buttons[1]); }
void IN_AttackSecondaryUp(void) { IN_KeyUp(&in_buttons[1]); }
void IN_UseDown(void) { IN_KeyDown(&in_buttons[3]); }
void IN_UseUp(void) { IN_KeyUp(&in_buttons[3]); }
void IN_LeanLeftDown(void) { IN_KeyDown(&in_buttons[4]); }
void IN_LeanLeftUp(void) { IN_KeyUp(&in_buttons[4]); }
void IN_LeanRightDown(void) { IN_KeyDown(&in_buttons[5]); }
void IN_LeanRightUp(void) { IN_KeyUp(&in_buttons[5]); }
void IN_SpeedDown(void) {IN_KeyDown(&in_speed);}
void IN_SpeedUp(void) {IN_KeyUp(&in_speed);}
@@ -341,22 +351,10 @@ void CL_KeyMove( usercmd_t *cmd ) {
int movespeed;
int forward, side, up;
//
// adjust for speed key / running
// the walking flag is to keep animations consistant
// even during acceleration and develeration
//
if ( in_speed.active ^ cl_run->integer ) {
movespeed = 127;
cmd->buttons |= BUTTON_RUN;
} else {
cmd->buttons &= ~BUTTON_RUN;
movespeed = 64;
}
forward = 0;
side = 0;
up = 0;
movespeed = 127;
if ( in_strafe.active ) {
side += movespeed * CL_KeyState (&in_right);
side -= movespeed * CL_KeyState (&in_left);
@@ -461,16 +459,8 @@ CL_JoystickMove
=================
*/
void CL_JoystickMove( usercmd_t *cmd ) {
int movespeed;
float anglespeed;
if ( in_speed.active ^ cl_run->integer ) {
movespeed = 2;
} else {
movespeed = 1;
cmd->buttons |= BUTTON_RUN;
}
if ( in_speed.active ) {
anglespeed = 0.001 * cls.frametime * cl_anglespeedkey->value;
} else {
@@ -566,7 +556,7 @@ CL_CmdButtons
*/
void CL_CmdButtons( usercmd_t *cmd ) {
int i;
//
// figure button bits
// send a button bit even if the key was pressed and released in
@@ -579,18 +569,28 @@ void CL_CmdButtons( usercmd_t *cmd ) {
in_buttons[i].wasPressed = qfalse;
}
// if ( Key_GetCatcher( ) ) {
// cmd->buttons |= BUTTON_TALK; // su44: is there a TALK button in MoHAA?
// }
if (UI_MenuActive() || UI_ConsoleIsOpen()) {
cmd->buttons |= BUTTON_TALK;
}
if (in_speed.active == !cl_run->integer) {
cmd->buttons |= BUTTON_RUN;
}
if (cge) {
// send weapon commands from cg
cmd->buttons |= cge->CG_WeaponCommandButtonBits();
}
// allow the game to know if any key at all is
// currently pressed, even if it isn't bound to anything
if ( anykeydown && Key_GetCatcher( ) == 0 ) {
cmd->buttons |= BUTTON_ANY;
if ( anykeydown && Key_GetCatcher() == 0) {
cmd->buttons |= BUTTON_MOUSE;
}
// su44: add weapon command bits
cmd->buttons |= cl.cgameUserCmdValue;
if (anykeydown) {
cmd->buttons |= BUTTON_ANY;
}
}
@@ -855,7 +855,7 @@ void CL_WritePacket( void ) {
for ( i = clc.reliableAcknowledge + 1 ; i <= clc.reliableSequence ; i++ ) {
MSG_WriteByte( &buf, clc_clientCommand );
MSG_WriteLong( &buf, i );
MSG_WriteString( &buf, clc.reliableCommands[ i & (MAX_RELIABLE_COMMANDS-1) ] );
MSG_WriteScrambledString( &buf, clc.reliableCommands[ i & (MAX_RELIABLE_COMMANDS-1) ] );
}
// we want to send all the usercmds that were generated in the last
@@ -924,7 +924,7 @@ void CL_WritePacket( void ) {
clc.lastPacketSentTime = cls.realtime;
if ( cl_showSend->integer ) {
Com_Printf( "%i ", buf.cursize );
Com_Printf( "%zu ", buf.cursize );
}
CL_Netchan_Transmit (&clc.netchan, &buf);
@@ -978,64 +978,76 @@ CL_InitInput
============
*/
void CL_InitInput( void ) {
Cmd_AddCommand ("centerview",IN_CenterView);
Cmd_AddCommand("centerview", IN_CenterView);
Cmd_AddCommand ("+moveup",IN_UpDown);
Cmd_AddCommand ("-moveup",IN_UpUp);
Cmd_AddCommand ("+movedown",IN_DownDown);
Cmd_AddCommand ("-movedown",IN_DownUp);
Cmd_AddCommand ("+left",IN_LeftDown);
Cmd_AddCommand ("-left",IN_LeftUp);
Cmd_AddCommand ("+right",IN_RightDown);
Cmd_AddCommand ("-right",IN_RightUp);
Cmd_AddCommand ("+forward",IN_ForwardDown);
Cmd_AddCommand ("-forward",IN_ForwardUp);
Cmd_AddCommand ("+back",IN_BackDown);
Cmd_AddCommand ("-back",IN_BackUp);
Cmd_AddCommand ("+lookup", IN_LookupDown);
Cmd_AddCommand ("-lookup", IN_LookupUp);
Cmd_AddCommand ("+lookdown", IN_LookdownDown);
Cmd_AddCommand ("-lookdown", IN_LookdownUp);
Cmd_AddCommand ("+strafe", IN_StrafeDown);
Cmd_AddCommand ("-strafe", IN_StrafeUp);
Cmd_AddCommand ("+moveleft", IN_MoveleftDown);
Cmd_AddCommand ("-moveleft", IN_MoveleftUp);
Cmd_AddCommand ("+moveright", IN_MoverightDown);
Cmd_AddCommand ("-moveright", IN_MoverightUp);
Cmd_AddCommand ("+speed", IN_SpeedDown);
Cmd_AddCommand ("-speed", IN_SpeedUp);
Cmd_AddCommand ("+attackprimary", IN_Button0Down);
Cmd_AddCommand ("-attackprimary", IN_Button0Up);
Cmd_AddCommand ("+attacksecondary", IN_Button1Down);
Cmd_AddCommand ("-attacksecondary", IN_Button1Up);
// Cmd_AddCommand ("+speed", IN_Button2Down);
// Cmd_AddCommand ("-speed", IN_Button2Up);
Cmd_AddCommand ("+use", IN_Button3Down);
Cmd_AddCommand ("-use", IN_Button3Up);
Cmd_AddCommand ("+leanleft", IN_Button4Down);
Cmd_AddCommand ("-leanleft", IN_Button4Up);
Cmd_AddCommand ("+leanright", IN_Button5Down);
Cmd_AddCommand ("-leanright", IN_Button5Up);
Cmd_AddCommand ("+button6", IN_Button6Down);
Cmd_AddCommand ("-button6", IN_Button6Up);
Cmd_AddCommand ("+button7", IN_Button7Down);
Cmd_AddCommand ("-button7", IN_Button7Up);
Cmd_AddCommand ("+button8", IN_Button8Down);
Cmd_AddCommand ("-button8", IN_Button8Up);
Cmd_AddCommand ("+button9", IN_Button9Down);
Cmd_AddCommand ("-button9", IN_Button9Up);
Cmd_AddCommand ("+button10", IN_Button10Down);
Cmd_AddCommand ("-button10", IN_Button10Up);
Cmd_AddCommand ("+button11", IN_Button11Down);
Cmd_AddCommand ("-button11", IN_Button11Up);
Cmd_AddCommand ("+button12", IN_Button12Down);
Cmd_AddCommand ("-button12", IN_Button12Up);
Cmd_AddCommand ("+button13", IN_Button13Down);
Cmd_AddCommand ("-button13", IN_Button13Up);
Cmd_AddCommand ("+button14", IN_Button14Down);
Cmd_AddCommand ("-button14", IN_Button14Up);
Cmd_AddCommand ("+mlook", IN_MLookDown);
Cmd_AddCommand ("-mlook", IN_MLookUp);
Cmd_AddCommand("+moveup", IN_UpDown);
Cmd_AddCommand("-moveup", IN_UpUp);
Cmd_AddCommand("+movedown", IN_DownDown);
Cmd_AddCommand("-movedown", IN_DownUp);
Cmd_AddCommand("+left", IN_LeftDown);
Cmd_AddCommand("-left", IN_LeftUp);
Cmd_AddCommand("+right", IN_RightDown);
Cmd_AddCommand("-right", IN_RightUp);
Cmd_AddCommand("+forward", IN_ForwardDown);
Cmd_AddCommand("-forward", IN_ForwardUp);
Cmd_AddCommand("+back", IN_BackDown);
Cmd_AddCommand("-back", IN_BackUp);
Cmd_AddCommand("+lookup", IN_LookupDown);
Cmd_AddCommand("-lookup", IN_LookupUp);
Cmd_AddCommand("+lookdown", IN_LookdownDown);
Cmd_AddCommand("-lookdown", IN_LookdownUp);
Cmd_AddCommand("+strafe", IN_StrafeDown);
Cmd_AddCommand("-strafe", IN_StrafeUp);
Cmd_AddCommand("+moveleft", IN_MoveleftDown);
Cmd_AddCommand("-moveleft", IN_MoveleftUp);
Cmd_AddCommand("+moveright", IN_MoverightDown);
Cmd_AddCommand("-moveright", IN_MoverightUp);
Cmd_AddCommand("+attack", IN_AttackPrimaryDown);
Cmd_AddCommand("-attack", IN_AttackPrimaryUp);
Cmd_AddCommand("+attackprimary", IN_AttackPrimaryDown);
Cmd_AddCommand("-attackprimary", IN_AttackPrimaryUp);
Cmd_AddCommand("+attacksecondary", IN_AttackSecondaryDown);
Cmd_AddCommand("-attacksecondary", IN_AttackSecondaryUp);
Cmd_AddCommand("+use", IN_Button3Down);
Cmd_AddCommand("-use", IN_Button3Up);
Cmd_AddCommand("+leanleft", IN_LeanLeftDown);
Cmd_AddCommand("-leanleft", IN_LeanLeftUp);
Cmd_AddCommand("+leanright", IN_LeanRightDown);
Cmd_AddCommand("-leanright", IN_LeanRightUp);
Cmd_AddCommand("+speed", IN_SpeedUp);
Cmd_AddCommand("-speed", IN_SpeedDown);
Cmd_AddCommand("+button0", IN_Button0Down);
Cmd_AddCommand("-button0", IN_Button0Up);
Cmd_AddCommand("+button1", IN_Button1Down);
Cmd_AddCommand("-button1", IN_Button1Up);
Cmd_AddCommand("+button2", IN_Button2Down);
Cmd_AddCommand("-button2", IN_Button2Up);
Cmd_AddCommand("+button3", IN_Button3Down);
Cmd_AddCommand("-button3", IN_Button3Up);
Cmd_AddCommand("+button4", IN_Button4Down);
Cmd_AddCommand("-button4", IN_Button4Up);
Cmd_AddCommand("+button5", IN_Button5Down);
Cmd_AddCommand("-button5", IN_Button5Up);
Cmd_AddCommand("+button6", IN_Button6Down);
Cmd_AddCommand("-button6", IN_Button6Up);
Cmd_AddCommand("+button7", IN_Button7Down);
Cmd_AddCommand("-button7", IN_Button7Up);
Cmd_AddCommand("+button8", IN_Button8Down);
Cmd_AddCommand("-button8", IN_Button8Up);
Cmd_AddCommand("+button9", IN_Button9Down);
Cmd_AddCommand("-button9", IN_Button9Up);
Cmd_AddCommand("+button10", IN_Button10Down);
Cmd_AddCommand("-button10", IN_Button10Up);
Cmd_AddCommand("+button11", IN_Button11Down);
Cmd_AddCommand("-button11", IN_Button11Up);
Cmd_AddCommand("+button12", IN_Button12Down);
Cmd_AddCommand("-button12", IN_Button12Up);
Cmd_AddCommand("+button13", IN_Button13Down);
Cmd_AddCommand("-button13", IN_Button13Up);
Cmd_AddCommand("+button14", IN_Button14Down);
Cmd_AddCommand("-button14", IN_Button14Up);
Cmd_AddCommand("+mlook", IN_MLookDown);
Cmd_AddCommand("-mlook", IN_MLookUp);
cl_nodelta = Cvar_Get ("cl_nodelta", "0", 0);
cl_debugMove = Cvar_Get ("cl_debugMove", "0", 0);
+15 -145
View File
@@ -29,14 +29,10 @@ key up events are sent even if in console mode
*/
field_t historyEditLines[COMMAND_HISTORY];
int nextHistoryLine; // the last line in the history buffer, not masked
int historyLine; // the line being displayed from history buffer
// will be <= nextHistoryLine
field_t g_consoleField;
field_t chatField;
qboolean chat_team;
int chat_playerNum;
@@ -55,8 +51,8 @@ qboolean alt_down;
qboolean ctrl_down;
typedef struct {
char *name;
int keynum;
const char *name;
int keynum;
} keyname_t;
@@ -470,7 +466,7 @@ void Key_SetCtrlBinding( int keynum, const char *binding ) {
Key_GetBinding
===================
*/
char *Key_GetBinding( int keynum ) {
const char *Key_GetBinding( int keynum ) {
if ( keynum < 0 || keynum >= K_LASTKEY ) {
return "";
}
@@ -525,7 +521,7 @@ Key_GetKeysForCommand
void Key_GetKeysForCommand( const char *command, int *key1, int *key2 ) {
int i;
*key1 = *key2 = 0;
*key1 = *key2 = -1;
for( i = 0; i < K_LASTKEY; i++ ) {
if( !keys[ i ].binding ) {
@@ -951,7 +947,13 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
ctrl_down = down;
}
if( cls.state > CA_DISCONNECTED && cge && !cls.keyCatchers && cge->CG_CheckCaptureKey( key, down, time ) && key != K_ESCAPE )
if (down && !CL_FinishedIntro())
{
UI_StartStageKeyEvent();
return;
}
if( cls.state > CA_DISCONNECTED && cge && !Key_GetCatcher() && cge->CG_CheckCaptureKey( key, down, time ) && key != K_ESCAPE )
{
if( key != '`' && key != '~' )
return;
@@ -962,6 +964,7 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
if( !down ) {
return;
}
if( Cvar_VariableIntegerValue( "ui_console" ) )
{
UI_ToggleConsole();
@@ -1015,10 +1018,10 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
}
}
if( in_guimouse || key <= K_MOUSE3 || key > K_JOY1 )
if (!in_guimouse || key <= K_MOUSE3 || key > K_JOY1)
{
// keys can still be used for bound actions
if( down && ( key < 128 || key == K_MOUSE4 ) &&
if (down && (key <= K_BACKSPACE || key == K_MOUSE4) &&
( clc.demoplaying || cls.state == CA_CINEMATIC ) && Key_GetCatcher() == 0 ) {
Cvar_Set( "nextdemo", "" );
key = K_ESCAPE;
@@ -1061,7 +1064,7 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
UI_KeyEvent( key, time );
} else if( cls.loading & KEYCATCH_MESSAGE ) {
Message_Key( key );
} else if( cls.state != CA_DISCONNECTED ) {
} else if( cls.state != CA_DISCONNECTED || menubound[key]) {
// send the bound action
kb = altkeys[ key ].binding;
if( !kb || !altkeys[ key ].down ) {
@@ -1198,136 +1201,3 @@ Key_SetCatcher
void Key_SetCatcher( int catcher ) {
keyCatchers = catcher;
}
// This must not exceed MAX_CMD_LINE
#define MAX_CONSOLE_SAVE_BUFFER 1024
#define CONSOLE_HISTORY_FILE "omhistory"
static char consoleSaveBuffer[ MAX_CONSOLE_SAVE_BUFFER ];
static int consoleSaveBufferSize = 0;
/*
================
CL_LoadConsoleHistory
Load the console history from cl_consoleHistory
================
*/
void CL_LoadConsoleHistory( void )
{
const char *token;
char *text_p;
int i, numChars, numLines = 0;
fileHandle_t f;
consoleSaveBufferSize = FS_FOpenFileRead( CONSOLE_HISTORY_FILE, &f, qfalse, qtrue );
if( !f )
{
Com_Printf( "Couldn't read %s.\n", CONSOLE_HISTORY_FILE );
return;
}
if( consoleSaveBufferSize <= MAX_CONSOLE_SAVE_BUFFER &&
FS_Read( consoleSaveBuffer, consoleSaveBufferSize, f ) == consoleSaveBufferSize )
{
text_p = consoleSaveBuffer;
for( i = COMMAND_HISTORY - 1; i >= 0; i-- )
{
if( !*( token = COM_Parse( &text_p ) ) )
break;
historyEditLines[ i ].cursor = atoi( token );
if( !*( token = COM_Parse( &text_p ) ) )
break;
historyEditLines[ i ].scroll = atoi( token );
if( !*( token = COM_Parse( &text_p ) ) )
break;
numChars = atoi( token );
text_p++;
if( numChars > ( strlen( consoleSaveBuffer ) - ( text_p - consoleSaveBuffer ) ) )
{
Com_DPrintf( S_COLOR_YELLOW "WARNING: probable corrupt history\n" );
break;
}
Com_Memcpy( historyEditLines[ i ].buffer,
text_p, numChars );
historyEditLines[ i ].buffer[ numChars ] = '\0';
text_p += numChars;
numLines++;
}
memmove( &historyEditLines[ 0 ], &historyEditLines[ i + 1 ],
numLines * sizeof( field_t ) );
for( i = numLines; i < COMMAND_HISTORY; i++ )
Field_Clear( &historyEditLines[ i ] );
historyLine = nextHistoryLine = numLines;
}
else
Com_Printf( "Couldn't read %s.\n", CONSOLE_HISTORY_FILE );
FS_FCloseFile( f );
}
/*
================
CL_SaveConsoleHistory
Save the console history into the cvar cl_consoleHistory
so that it persists across invocations of q3
================
*/
void CL_SaveConsoleHistory( void )
{
int i;
int lineLength, saveBufferLength, additionalLength;
fileHandle_t f;
consoleSaveBuffer[ 0 ] = '\0';
i = ( nextHistoryLine - 1 ) % COMMAND_HISTORY;
do
{
if( historyEditLines[ i ].buffer[ 0 ] )
{
lineLength = strlen( historyEditLines[ i ].buffer );
saveBufferLength = strlen( consoleSaveBuffer );
//ICK
additionalLength = lineLength + strlen( "999 999 999 " );
if( saveBufferLength + additionalLength < MAX_CONSOLE_SAVE_BUFFER )
{
Q_strcat( consoleSaveBuffer, MAX_CONSOLE_SAVE_BUFFER,
va( "%d %d %d %s ",
historyEditLines[ i ].cursor,
historyEditLines[ i ].scroll,
lineLength,
historyEditLines[ i ].buffer ) );
}
else
break;
}
i = ( i - 1 + COMMAND_HISTORY ) % COMMAND_HISTORY;
}
while( i != ( nextHistoryLine - 1 ) % COMMAND_HISTORY );
consoleSaveBufferSize = strlen( consoleSaveBuffer );
f = FS_FOpenFileWrite( CONSOLE_HISTORY_FILE );
if( !f )
{
Com_Printf( "Couldn't write %s.\n", CONSOLE_HISTORY_FILE );
return;
}
if( FS_Write( consoleSaveBuffer, consoleSaveBufferSize, f ) < consoleSaveBufferSize )
Com_Printf( "Couldn't write %s.\n", CONSOLE_HISTORY_FILE );
FS_FCloseFile( f );
}
+64 -32
View File
@@ -32,6 +32,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "../sys/sys_loadlib.h"
#endif
#include "gcdkeyc.h"
cvar_t *cl_nodelta;
cvar_t *cl_debugMove;
@@ -97,6 +99,7 @@ cvar_t *wombat;
cvar_t *cl_r_fullscreen;
cvar_t *cl_consoleKeys;
cvar_t *name;
cvar_t* j_pitch;
cvar_t* j_yaw;
@@ -218,7 +221,7 @@ CL_ChangeReliableCommand
======================
*/
void CL_ChangeReliableCommand( void ) {
int r, index, l;
size_t r, index, l;
r = clc.reliableSequence - (random() * 5);
index = clc.reliableSequence & ( MAX_RELIABLE_COMMANDS - 1 );
@@ -246,7 +249,7 @@ Dumps the current net message, prefixed by the length
====================
*/
void CL_WriteDemoMessage ( msg_t *msg, int headerBytes ) {
int len, swlen;
size_t len, swlen;
// write the packet sequence
len = clc.serverMessageSequence;
@@ -325,7 +328,7 @@ void CL_Record_f( void ) {
byte bufData[MAX_MSGLEN];
msg_t buf;
int i;
int len;
size_t len;
entityState_t *ent;
entityState_t nullstate;
char *s;
@@ -557,7 +560,7 @@ CL_ReadDemoMessage
=================
*/
void CL_ReadDemoMessage( void ) {
int r;
size_t r;
msg_t buf;
byte bufData[ MAX_MSGLEN ];
int s;
@@ -1058,7 +1061,8 @@ in anyway.
*/
void CL_RequestAuthorization( void ) {
char nums[64];
int i, j, l;
int i, j;
size_t l;
cvar_t *fs;
if ( !cls.authorizeServer.port ) {
@@ -1421,6 +1425,10 @@ void CL_ResetPureClientAtServer( void ) {
CL_AddReliableCommand( va("vdr") );
}
qboolean CL_Allowed_Vid_Restart() {
return cls.state == CA_DISCONNECTED || cls.state == CA_ACTIVE;
}
/*
=================
CL_Vid_Restart_f
@@ -1432,33 +1440,30 @@ because the renderer doesn't know what graphics to reload
=================
*/
void CL_Vid_Restart_f( void ) {
// Settings may have changed so stop recording now
if( CL_VideoRecording( ) ) {
CL_CloseAVI( );
if (!CL_Allowed_Vid_Restart()) {
return;
}
if(clc.demorecording)
CL_StopRecord_f();
Com_Printf("-------- CL_Vid_Restart_f --------\n");
cls.vid_restart = qtrue;
// don't let them loop during the restart
S_StopAllSounds( qtrue );
S_StopAllSounds(qtrue);
SV_ClearSvsTimeFixups();
S_BeginRegistration();
// shutdown the renderer and clear the renderer interface
CL_ShutdownRef();
// shutdown the CGame
CL_ShutdownCGame();
// initialize the renderer interface
CL_InitRef();
// client is no longer pure untill new checksums are sent
CL_ResetPureClientAtServer();
// clear pak references
FS_ClearPakReferences( FS_UI_REF | FS_CGAME_REF );
// reinitialize the filesystem if the game directory or checksum has changed
FS_ConditionalRestart( clc.checksumFeed );
// initialize the ui library
UI_ResolutionChange();
cls.rendererRegistered = qfalse;
cls.uiStarted = qfalse;
cls.cgameStarted = qfalse;
// unpause so the cgame definately gets a snapshot and renders a frame
Com_Unpause();
@@ -1469,6 +1474,8 @@ void CL_Vid_Restart_f( void ) {
S_Init();
cls.vid_restart = qfalse;
Com_Printf("----- finished CL_Vid_Restart_f ----\n");
}
/*
@@ -1804,7 +1811,11 @@ void CL_CheckForResend( void ) {
// }
NET_OutOfBandPrint(NS_CLIENT, clc.serverAddress, "getchallenge");
break;
case CA_AUTHORIZING:
// resend the cd key authorization
gcd_compute_response(cl_cdkey, Cmd_Argv(1), cls.gcdResponse, CDResponseMethod_REAUTH);
NET_OutOfBandPrint(NS_CLIENT, clc.serverAddress, "authorizeThis %s", cls.gcdResponse);
break;
case CA_CHALLENGING:
/*
wombat: sending conect here: an example connect string from MOHAA looks like this:
@@ -1817,7 +1828,11 @@ wombat: sending conect here: an example connect string from MOHAA looks like thi
Q_strncpyz( info, Cvar_InfoString( CVAR_USERINFO ), sizeof( info ) );
Info_SetValueForKey( info, "protocol", va("%i", PROTOCOL_VERSION ) );
Info_SetValueForKey( info, "qport", va("%i", port ) );
Info_SetValueForKey( info, "challenge", va("%i", clc.challenge ) );
Info_SetValueForKey(info, "challenge", va("%i", clc.challenge));
Info_SetValueForKey(info, "version", TARGET_GAME_VERSION);
#if TARGET_GAME_PROTOCOL >= 15
Info_SetValueForKey(info, "clientType", "Breakthrough");
#endif
strcpy(data, "connect ");
// TTimo adding " " around the userinfo string to avoid truncated userinfo on the server
@@ -2076,7 +2091,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
// challenge from the server we are connecting to
if ( !Q_stricmp(c, "challengeResponse") ) {
if ( cls.state != CA_CONNECTING ) {
if ( cls.state != CA_CONNECTING && cls.state != CA_AUTHORIZING ) {
Com_Printf( "Unwanted challenge response received. Ignored.\n" );
} else {
// start sending challenge repsonse instead of challenge request packets
@@ -2141,8 +2156,10 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
}
// cd check
if ( !Q_stricmp(c, "keyAuthorize") ) {
// we don't use these now, so dump them on the floor
if ( !Q_stricmp(c, "getKey") ) {
cls.state = CA_AUTHORIZING;
gcd_compute_response(cl_cdkey, Cmd_Argv(1), cls.gcdResponse, CDResponseMethod_NEWAUTH);
NET_OutOfBandPrint(NS_CLIENT, from, "authorizeThis %s", cls.gcdResponse);
return;
}
@@ -2274,7 +2291,7 @@ qboolean CL_CheckPaused(void)
// if paused->modified is set, the cvar has only been changed in
// this frame. Keep paused in this frame to ensure the server doesn't
// lag behind.
if(paused->integer || paused->modified)
if(paused->integer)
return qtrue;
return qfalse;
@@ -2289,6 +2306,8 @@ CL_CheckUserinfo
==================
*/
void CL_CheckUserinfo( void ) {
char szSanitizedName[MAX_NAME_LENGTH];
// don't add reliable commands when not yet connected
if(cls.state < CA_CHALLENGING)
return;
@@ -2300,6 +2319,10 @@ void CL_CheckUserinfo( void ) {
// send a reliable userinfo update if needed
if(cvar_modifiedFlags & CVAR_USERINFO)
{
if (Com_SanitizeName(name->string, szSanitizedName)) {
Cvar_Set("name", szSanitizedName);
}
cvar_modifiedFlags &= ~CVAR_USERINFO;
CL_AddReliableCommand( va("userinfo \"%s\"", Cvar_InfoString( CVAR_USERINFO ) ) );
}
@@ -3101,7 +3124,7 @@ void CL_Init( void ) {
cl_consoleKeys = Cvar_Get( "cl_consoleKeys", "~ ` 0x7e 0x60", CVAR_ARCHIVE );
// userinfo
Cvar_Get ("name", "UnnamedSoldier", CVAR_USERINFO | CVAR_ARCHIVE );
name = Cvar_Get ("name", "UnnamedSoldier", CVAR_USERINFO | CVAR_ARCHIVE );
Cvar_Get ("rate", "5000", CVAR_USERINFO | CVAR_ARCHIVE );
Cvar_Get ("snaps", "20", CVAR_USERINFO | CVAR_ARCHIVE );
Cvar_Get ("password", "", CVAR_USERINFO);
@@ -3294,7 +3317,7 @@ CL_ServerInfoPacket
void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) {
int i, type;
char info[MAX_INFO_STRING];
char* str;
const char* str;
char *infoString;
int prot;
@@ -3490,10 +3513,10 @@ CL_ServerStatusResponse
===================
*/
void CL_ServerStatusResponse( netadr_t from, msg_t *msg ) {
char *s;
const char *s;
char info[MAX_INFO_STRING];
int i, l, score, ping;
int len;
size_t len;
serverStatus_t *serverStatus;
serverStatus = NULL;
@@ -3583,7 +3606,7 @@ CL_LocalServers_f
==================
*/
void CL_LocalServers_f( void ) {
char *message;
const char *message;
int i, j;
netadr_t to;
@@ -4252,7 +4275,8 @@ qboolean CL_CDKeyValidate( const char *key, const char *checksum ) {
char ch;
byte sum;
char chs[3];
int i, len;
int i;
size_t len;
len = strlen(key);
if( len != CDKEY_LEN ) {
@@ -4307,4 +4331,12 @@ qboolean CL_CDKeyValidate( const char *key, const char *checksum ) {
return qfalse;
}
void TIKI_CG_Command_ProcessFile(char* filename, qboolean quiet, dtiki_t* curTiki)
{
if (cge) {
cge->CG_Command_ProcessFile(filename, quiet, curTiki);
return;
}
Com_Printf("NO CGE \n");
}
+38 -17
View File
@@ -24,7 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "client.h"
#include "cl_ui.h"
char *svc_strings[256] = {
const char *svc_strings[256] = {
"svc_bad",
"svc_nop",
@@ -41,7 +41,7 @@ char *svc_strings[256] = {
msg_t *cl_currentMSG;
void SHOWNET( msg_t *msg, char *s) {
void SHOWNET( msg_t *msg, const char *s) {
if ( cl_shownet->integer >= 2) {
Com_Printf ("%3i:%s\n", msg->readcount-1, s);
}
@@ -75,8 +75,7 @@ void CL_DeltaEntity (msg_t *msg, clSnapshot_t *frame, int newnum, entityState_t
if ( unchanged ) {
*state = *old;
} else {
// FIXME: frametime
MSG_ReadDeltaEntity( msg, old, state, newnum, 0.0);
MSG_ReadDeltaEntity( msg, old, state, newnum, cls.serverFrameTime);
}
if ( state->number == (MAX_GENTITIES-1) ) {
@@ -117,7 +116,7 @@ void CL_ParsePacketEntities( msg_t *msg, clSnapshot_t *oldframe, clSnapshot_t *n
while ( 1 ) {
// read the entity index number
newnum = MSG_ReadBits( msg, GENTITYNUM_BITS );
newnum = MSG_ReadEntityNum(msg);
if ( newnum == (MAX_GENTITIES-1) ) {
break;
@@ -274,11 +273,10 @@ void CL_ParseSnapshot( msg_t *msg ) {
// read playerinfo
SHOWNET(msg, "playerstate");
// FIXME: frametime
if ( old ) {
MSG_ReadDeltaPlayerstate( msg, &old->ps, &newSnap.ps, 0.0 );
MSG_ReadDeltaPlayerstate( msg, &old->ps, &newSnap.ps, cls.serverFrameTime );
} else {
MSG_ReadDeltaPlayerstate( msg, NULL, &newSnap.ps, 0.0);
MSG_ReadDeltaPlayerstate( msg, NULL, &newSnap.ps, cls.serverFrameTime);
}
// read packet entities
@@ -446,6 +444,28 @@ static void CL_ParseServerInfo(void)
sizeof(clc.sv_dlURL));
}
#if TARGET_GAME_PROTOCOL >= 15
char* MSG_ReadGameStateChar(msg_t* msg) {
return MSG_ReadScrambledBigString(msg);
}
float MSG_ReadServerFrameTime(msg_t* msg) {
return MSG_ReadFloat(msg);
}
#else
char* MSG_ReadGameStateChar(msg_t* msg) {
return MSG_ReadString(msg);
}
float MSG_ReadServerFrameTime(msg_t* msg) {
return 1.f / atof(Info_ValueForKey(cl.gameState.stringData + cl.gameState.stringOffsets[CS_SYSTEMINFO], "sv_fps"));
}
#endif
/*
==================
CL_ParseGamestate
@@ -488,7 +508,7 @@ void CL_ParseGamestate( msg_t *msg ) {
if ( i < 0 || i >= MAX_CONFIGSTRINGS ) {
Com_Error( ERR_DROP, "configstring > MAX_CONFIGSTRINGS" );
}
s = MSG_ReadString( msg );
s = MSG_ReadGameStateChar( msg );
len = strlen( s );
if ( len + 1 + cl.gameState.dataCount > MAX_GAMESTATE_CHARS ) {
@@ -499,7 +519,7 @@ void CL_ParseGamestate( msg_t *msg ) {
Com_Memcpy( cl.gameState.stringData + cl.gameState.dataCount, s, len + 1 );
cl.gameState.dataCount += len + 1;
} else if ( cmd == svc_baseline ) {
newnum = MSG_ReadBits( msg, GENTITYNUM_BITS );
newnum = MSG_ReadEntityNum(msg);
if ( newnum < 0 || newnum >= MAX_GENTITIES ) {
Com_Error( ERR_DROP, "Baseline number out of range: %i", newnum );
}
@@ -516,6 +536,7 @@ void CL_ParseGamestate( msg_t *msg ) {
clc.clientNum = MSG_ReadLong(msg);
// read the checksum feed
clc.checksumFeed = MSG_ReadLong( msg );
cls.serverFrameTime = MSG_ReadServerFrameTime(msg);
// parse serverId and other cvars
CL_SystemInfoChanged();
@@ -527,6 +548,7 @@ void CL_ParseGamestate( msg_t *msg ) {
// reinitialize the filesystem if the game directory has changed
FS_ConditionalRestart( clc.checksumFeed );
cls.state = CA_LOADING;
if (!com_sv_running->integer)
{
const char *info = cl.gameState.stringData + cl.gameState.stringOffsets[CS_SERVERINFO];
@@ -726,7 +748,7 @@ void CL_ParseCommandString( msg_t *msg ) {
int index;
seq = MSG_ReadLong( msg );
s = MSG_ReadString( msg );
s = MSG_ReadScrambledString( msg );
// see if we have already executed stored it off
if ( clc.serverCommandSequence >= seq ) {
@@ -763,10 +785,9 @@ void CL_ParseLocationprint( msg_t *msg ) {
x = MSG_ReadShort( msg );
y = MSG_ReadShort( msg );
string = MSG_ReadString(msg);
string = MSG_ReadScrambledString(msg);
// FIXME
//UI_UpdateLocationPrint( x, y, string, 1.0 );
UI_UpdateLocationPrint( x, y, string, 1.0 );
}
/*
@@ -777,10 +798,10 @@ CL_ParseCenterprint
void CL_ParseCenterprint( msg_t *msg ) {
char *string;
string = MSG_ReadString( msg );
string = MSG_ReadScrambledString( msg );
// FIXME
//UI_UpdateCenterPrintf( string, 1.0 );
UI_UpdateCenterPrint( string, 1.0 );
}
/*
@@ -792,7 +813,7 @@ void CL_ParseServerMessage( msg_t *msg ) {
int cmd;
//Com_Printf( "ParseServerMessage: %i\n", msg->cursize );
if ( cl_shownet->integer == 1 ) {
Com_Printf ("%i ",msg->cursize);
Com_Printf ("%zu ",msg->cursize);
} else if ( cl_shownet->integer >= 2 ) {
Com_Printf ("------------------\n");
}
+99 -78
View File
@@ -29,9 +29,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cl_ui.h"
#if _MSC_VER
#include <intrin.h>
#endif
#include <ctime>
typedef struct {
float fadetime;
@@ -877,7 +875,7 @@ Key_GetBindingBuf
====================
*/
static void Key_GetBindingBuf( int keynum, char *buf, int buflen ) {
char *value;
const char *value;
value = Key_GetBinding( keynum );
if ( value ) {
@@ -1119,7 +1117,7 @@ getNewConsole
====================
*/
UIFloatingConsole* getNewConsole() {
static constexpr char CONSOLE_NAME[] = PRODUCT_NAME_FULL " - " PRODUCT_VERSION_FULL;
static constexpr char CONSOLE_NAME[] = PRODUCT_NAME " console version " PRODUCT_VERSION;
UIFloatingConsole* console = new UIFloatingConsole;
console->Create(NULL, getDefaultConsoleRectangle(), CONSOLE_NAME, UWindowColor, UHudColor);
@@ -1256,6 +1254,10 @@ void UI_PrintConsole( const char *msg )
bDeathMessage = qtrue;
pColor = &ULightRed;
break;
case MESSAGE_CHAT_GREEN:
bDeathMessage = qtrue;
pColor = &UGreen;
break;
}
msg++;
@@ -1881,7 +1883,7 @@ void UI_Update(void) {
{
UI_ForceMenuOff(true);
UI_DeactiveFloatingWindows();
UI_ForceMenu("");
UI_ForceMenu(ui_sCurrentLoadingMenu);
uWinMan.showCursor(false);
}
@@ -3638,8 +3640,8 @@ void UI_WantsKeyboard() {
}
struct widgettrans_s {
char *src;
char *dst;
const char *src;
const char *dst;
};
static widgettrans_s s_widgettrans[ 2 ] =
@@ -4485,8 +4487,14 @@ ScoreboardListItem::ScoreboardListItem()
void ScoreboardListItem::DrawListItem( int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont )
{
DrawBox( drawRect, backColor, 1.0 );
pFont->setColor( textColor );
pFont->Print( drawRect.pos.x + 1, drawRect.pos.y, Sys_LV_CL_ConvertString( getListItemString( iColumn ) ), iColumn, -1 );
pFont->setColor(textColor);
pFont->Print(
drawRect.pos.x + 1,
drawRect.pos.y,
Sys_LV_CL_ConvertString(getListItemString(iColumn)),
-1,
qfalse
);
if( bTitleItem )
{
@@ -4588,10 +4596,11 @@ void UI_SetScoreBoardItem( int iItemNumber,
{
cge->CG_GetScoreBoardPosition( &x, &y, &w, &h );
if( scoreboard_x == x
|| scoreboard_y == y
|| scoreboard_w == w
|| scoreboard_h == h
// Recreate the scoreboard if it has different rect
if( scoreboard_x != x
|| scoreboard_y != y
|| scoreboard_w != w
|| scoreboard_h != h
|| scoreboard_header != cge->CG_GetScoreBoardDrawHeader() )
{
delete scoreboardlist;
@@ -4606,11 +4615,12 @@ void UI_SetScoreBoardItem( int iItemNumber,
if( scoreboardlist )
{
if( iItemNumber + 1 > scoreboardlist->getNumItems() ) {
if (iItemNumber + 1 > scoreboardlist->getNumItems()) {
pItem = new ScoreboardListItem;
scoreboardlist->AddItem( pItem );
} else {
pItem = ( ScoreboardListItem * )scoreboardlist->GetItem( iItemNumber );
scoreboardlist->AddItem(pItem);
}
else {
pItem = (ScoreboardListItem*)scoreboardlist->GetItem(iItemNumber + 1);
}
if( pItem )
@@ -4877,7 +4887,7 @@ static void SaveConsoleRectangle( void ) {
if( !fakk_console->IsMinimized() ) {
r = fakk_console->getFrame();
Cvar_Set( "ui_consoleposition", va( "%d %d %d %d", r.pos.x, r.pos.y, r.size.width, r.size.height ) );
Cvar_Set( "ui_consoleposition", va( "%d %d %d %d", (int)r.pos.x, (int)r.pos.y, (int)r.size.width, (int)r.size.height ) );
if( wasMinimized ) {
fakk_console->ProcessEvent( UIFloatingWindow::W_MinimizePressed );
@@ -4940,7 +4950,7 @@ void UI_RemoveHud_f( void ) {
if( hud && hudList.ObjectInList( hud ) )
{
hud->ShowMenu( NULL );
hud->ForceHide();
hudList.RemoveObject( hud );
}
}
@@ -5431,7 +5441,7 @@ UI_BeginLoadResource
====================
*/
void UI_BeginLoadResource( void ) {
uint64_t time = __rdtsc();
clock_t time = clock();
startCountHigh = time >> 32;
startCountLow = time;
@@ -5484,7 +5494,7 @@ qboolean UI_IsResourceLoaded( const char *name ) {
case 104:
return TIKI_FindTikiAnim( name + 1 ) != NULL;
case 103:
return SkeletorCacheFindFilename( name + 1, NULL ) != NULL;
return SkeletorCacheFindFilename( name + 1, NULL );
case 107:
return S_IsSoundRegistered( name + 1 );
case 110:
@@ -5565,23 +5575,23 @@ UI_LoadResource
====================
*/
void UI_LoadResource( const char *name ) {
if( cls.loading == SS_DEAD ) {
if (cls.loading == SS_DEAD) {
return;
}
if( cls.loading == 3 )
if (cls.loading == SS_GAME)
{
UI_EndLoadResource();
UI_EndLoadResource( name );
UI_EndLoadResource(name);
UI_BeginLoadResource();
}
else if( cls.loading == 2 )
else if (cls.loading == SS_LOADING2)
{
UI_RegisterLoadResource( name );
Cvar_SetValue( "loadingbar", currentLoadTime / totalLoadTime );
UI_RegisterLoadResource(name);
Cvar_SetValue("loadingbar", (float)currentLoadTime / (float)totalLoadTime);
}
UI_TestUpdateScreen( 333u );
UI_TestUpdateScreen(333u);
}
/*
@@ -5746,7 +5756,65 @@ void UI_BeginLoad( const char *pszMapName ) {
UI_ForceMenuOff( true );
UI_DeactiveFloatingWindows();
if( !ui_pLoadingMenu )
if (ui_pLoadingMenu)
{
if (!developer->integer && UI_ConsoleIsVisible()) {
UI_CloseConsole();
}
ui_pLoadingMenu->PassEventToWidget("continuebutton", new Event(EV_Widget_Disable));
loadName = "maps/";
loadName += pszMapName;
loadName += ".min";
mapfile = loadName + ".bsp";
if (UI_ArchiveLoadMapinfo(mapfile)) {
cls.loading = SS_LOADING2;
}
else {
cls.loading = SS_GAME;
}
if (cls.loading == SS_LOADING2)
{
ui_pLoadingMenu->PassEventToWidget("loadingflasher", new Event(EV_Widget_Disable));
ui_pLoadingMenu->PassEventToWidget("loadingbar", new Event(EV_Widget_Enable));
ui_pLoadingMenu->PassEventToWidget("loadingbar_border", new Event(EV_Widget_Enable));
currentLoadTime = 0;
Cvar_SetValue("loadingbar", 0);
L_ProcessPendingEvents();
lastTime = Sys_Milliseconds();
if (com_sv_running->integer) {
SCR_UpdateScreen();
}
}
else
{
ui_pLoadingMenu->PassEventToWidget("loadingflasher", new Event(EV_Widget_Enable));
ui_pLoadingMenu->PassEventToWidget("loadingbar", new Event(EV_Widget_Disable));
ui_pLoadingMenu->PassEventToWidget("loadingbar_border", new Event(EV_Widget_Disable));
UI_BeginLoadResource();
loadCountLow = 0;
loadCountHigh = 0;
loadHead = NULL;
loadNumber = 0;
cls.loading = SS_LOADING;
L_ProcessPendingEvents();
lastTime = Sys_Milliseconds();
if (com_sv_running->integer) {
SCR_UpdateScreen();
}
}
}
else
{
cls.loading = SS_LOADING;
@@ -5755,56 +5823,9 @@ void UI_BeginLoad( const char *pszMapName ) {
lastTime = Sys_Milliseconds();
if( com_sv_running->integer ) {
if (com_sv_running->integer) {
SCR_UpdateScreen();
}
return;
}
if( !developer->integer && UI_ConsoleIsVisible() ) {
UI_CloseConsole();
}
ui_pLoadingMenu->PassEventToWidget( "continuebutton", new Event( EV_Widget_Disable ) );
loadName = "maps/";
loadName += pszMapName;
loadName += ".min";
mapfile = loadName + ".bsp";
if( UI_ArchiveLoadMapinfo( mapfile ) ) {
cls.loading = SS_LOADING2;
} else {
cls.loading = SS_GAME;
}
if( cls.loading != SS_LOADING2 )
{
ui_pLoadingMenu->PassEventToWidget( "loadingflasher", new Event( EV_Widget_Enable ) );
ui_pLoadingMenu->PassEventToWidget( "loadingbar", new Event( EV_Widget_Disable ) );
ui_pLoadingMenu->PassEventToWidget( "loadingbar_border", new Event( EV_Widget_Disable ) );
UI_BeginLoadResource();
loadCountLow = 0;
loadCountHigh = 0;
loadHead = NULL;
loadNumber = 0;
}
else
{
ui_pLoadingMenu->PassEventToWidget( "loadingflasher", new Event( EV_Widget_Disable ) );
ui_pLoadingMenu->PassEventToWidget( "loadingbar", new Event( EV_Widget_Enable ) );
ui_pLoadingMenu->PassEventToWidget( "loadingbar_border", new Event( EV_Widget_Enable ) );
currentLoadTime = 0;
Cvar_SetValue( "loadingbar", 0 );
}
L_ProcessPendingEvents();
lastTime = Sys_Milliseconds();
if( com_sv_running->integer ) {
SCR_UpdateScreen();
}
}
+1
View File
@@ -42,6 +42,7 @@ void CL_ShutdownUI( void );
//
extern inventory_t client_inv;
extern bind_t client_bind;
extern cvar_t* cl_greenfps;
const char *CvarGetForUI( const char *name, const char *defval );
void UI_ClearState( void );
+18 -8
View File
@@ -189,11 +189,13 @@ void UIDMBox::RemoveTopItem( void )
{
int i;
for (i = 0; i < m_numitems - 1; i++) {
m_items[i] = m_items[i + 1];
}
if (m_numitems > 0) {
for (i = 0; i < m_numitems - 1; i++) {
m_items[i] = m_items[i + 1];
}
m_numitems--;
m_numitems--;
}
}
str UIDMBox::CalculateBreaks( UIFont *font, str text, float max_width )
@@ -291,19 +293,27 @@ void UIDMBox::Print( const char *text )
m_items[m_numitems].flags = 0;
if (*text == 2)
if (*text == MESSAGE_CHAT_WHITE)
{
m_items[m_numitems].color = UGrey;
m_items[m_numitems].font = m_fontbold;
m_items[m_numitems].flags |= GMBOX_ITEM_FLAG_BOLD;
m_items[m_numitems].flags |= DMBOX_ITEM_FLAG_BOLD;
text1 = text + 1;
}
else if (*text == 4)
else if (*text == MESSAGE_CHAT_RED)
{
m_items[m_numitems].color = ULightRed;
m_items[m_numitems].font = m_fontbold;
m_items[m_numitems].flags |= GMBOX_ITEM_FLAG_BOLD;
m_items[m_numitems].flags |= DMBOX_ITEM_FLAG_BOLD;
text1 = text + 1;
}
else if (*text == MESSAGE_CHAT_GREEN)
{
m_items[m_numitems].color = UGreen;
m_items[m_numitems].font = m_fontbold;
m_items[m_numitems].flags |= DMBOX_ITEM_FLAG_BOLD;
text1 = text + 1;
}
+6 -4
View File
@@ -186,11 +186,13 @@ void UIGMBox::RemoveTopItem( void )
{
int i;
for (i = 0; i < m_numitems - 1; i++) {
m_items[i] = m_items[i + 1];
}
if (m_numitems > 0) {
for (i = 0; i < m_numitems - 1; i++) {
m_items[i] = m_items[i + 1];
}
m_numitems--;
m_numitems--;
}
}
str UIGMBox::CalculateBreaks( UIFont *font, str text, float max_width )
+2 -2
View File
@@ -29,8 +29,8 @@ public:
SoundPickerClass();
void FileSelected( str &currentDirectory, str &partialName, str &fullname );
void FileChosen( str &currentDirectory, str &partialName, str &fullname );
void FileSelected( str &currentDirectory, str &partialName, str &fullname ) override;
void FileChosen( str &currentDirectory, str &partialName, str &fullname ) override;
};
#endif /* __CL_UISOUNDPICKER_H__ */
+385 -12
View File
@@ -438,7 +438,178 @@ void UIFakkLabel::LayoutRenderModelAnim( Event *ev )
void UIFakkLabel::DrawStatbar( float frac )
{
// FIXME: stub
vec4_t col;
float alpha;
col[0] = col[1] = col[2] = col[3] = 1.0;
switch (m_statbar_or)
{
case L_STATBAR_CIRCULAR:
DrawStatCircle(frac);
return;
case L_STATBAR_NEEDLE:
DrawStatNeedle(frac);
return;
case L_STATBAR_ROTATOR:
DrawStatRotator(frac);
return;
case L_STATBAR_COMPASS:
DrawStatCompass(frac);
return;
case L_STATBAR_SPINNER:
case L_STATBAR_HEADING_SPINNER:
DrawStatSpinner(frac);
return;
default:
break;
}
if (!frac) {
return;
}
if (frac != m_lastfrac) {
m_flashtime = uid.time;
}
m_lastfrac = frac;
alpha = 1.0 - ((float)uid.time - m_flashtime) / 1500.0;
if (alpha < 0.0) alpha = 0.0;
else if (alpha > 1.0) alpha = 1.0;
col[3] = alpha;
if (m_statbar_material)
{
if (m_flags & WF_TILESHADER)
{
switch (m_statbar_or)
{
case L_STATBAR_HORIZONTAL:
{
float width = frac * m_frame.size.width;
m_statbar_material->ReregisterMaterial();
re.DrawTilePic(0.0, 0.0, width, m_frame.size.height, m_statbar_material->GetMaterial());
if (alpha != 0.0 && m_statbar_material_flash)
{
re.SetColor(col);
m_statbar_material_flash->ReregisterMaterial();
re.DrawTilePic(0.0, 0.0, width, m_frame.size.height, m_statbar_material_flash->GetMaterial());
}
break;
}
case L_STATBAR_VERTICAL:
case L_STATBAR_VERTICAL_REVERSE:
case L_STATBAR_VERTICAL_STAGGER_EVEN:
case L_STATBAR_VERTICAL_STAGGER_ODD:
{
float y = m_frame.size.height * (1.0 - frac);
m_statbar_material->ReregisterMaterial();
re.DrawTilePic(0.0, y, m_frame.size.width, m_frame.size.height, m_statbar_material->GetMaterial());
if (alpha != 0.0 && m_statbar_material_flash)
{
re.SetColor(col);
m_statbar_material_flash->ReregisterMaterial();
re.DrawTilePic(0.0, y, m_frame.size.width, m_frame.size.height, m_statbar_material_flash->GetMaterial());
}
break;
}
default:
break;
}
}
else
{
switch (m_statbar_or)
{
case L_STATBAR_HORIZONTAL:
{
float width = frac * m_frame.size.width;
m_statbar_material->ReregisterMaterial();
re.DrawStretchPic(0.0, 0.0, width, m_frame.size.height, 0.0, 0.0, 1.0, 1.0, m_statbar_material->GetMaterial());
if(alpha != 0.0 && m_statbar_material_flash)
{
re.SetColor(col);
m_statbar_material_flash->ReregisterMaterial();
re.DrawStretchPic(0.0, 0.0, width, m_frame.size.height, 0.0, 0.0, 1.0, 1.0, m_statbar_material_flash->GetMaterial());
}
break;
}
case L_STATBAR_VERTICAL:
case L_STATBAR_VERTICAL_STAGGER_EVEN:
case L_STATBAR_VERTICAL_STAGGER_ODD:
{
float y = m_frame.size.height * (1.0 - frac);
float height = m_frame.size.height * frac;
m_statbar_material->ReregisterMaterial();
re.DrawStretchPic(0.0, y, m_frame.size.width, height, 0.0, 1.0 - frac, 1.0, 1.0, m_statbar_material->GetMaterial());
if (alpha != 0.0 && m_statbar_material_flash)
{
re.SetColor(col);
m_statbar_material_flash->ReregisterMaterial();
re.DrawStretchPic(0.0, y, m_frame.size.width, height, 0.0, 1.0 - frac, 1.0, 1.0, m_statbar_material_flash->GetMaterial());
}
break;
}
case L_STATBAR_VERTICAL_REVERSE:
{
float height = m_frame.size.height * frac;
m_statbar_material->ReregisterMaterial();
re.DrawStretchPic(0.0, 0.0, m_frame.size.width, height, 0.0, 0.0, 1.0, frac, m_statbar_material->GetMaterial());
if (alpha != 0.0 && m_statbar_material_flash)
{
re.SetColor(col);
m_statbar_material_flash->ReregisterMaterial();
re.DrawStretchPic(0.0, 0.0, m_frame.size.width, height, 0.0, 0.0, 1.0, frac, m_statbar_material_flash->GetMaterial());
}
break;
}
default:
break;
}
}
}
else
{
switch (m_statbar_or)
{
case L_STATBAR_VERTICAL:
case L_STATBAR_VERTICAL_STAGGER_EVEN:
case L_STATBAR_VERTICAL_STAGGER_ODD:
DrawBox(
0.0,
m_frame.size.height * (1.0 - frac),
m_frame.size.width,
m_frame.size.height,
m_foreground_color,
1.0
);
break;
case L_STATBAR_HORIZONTAL:
DrawBox(
0.0,
0.0,
frac * m_frame.size.width,
m_frame.size.height,
m_foreground_color,
1.0
);
break;
default:
break;
}
}
}
void UIFakkLabel::DrawStatCircle( float frac )
@@ -458,7 +629,212 @@ void UIFakkLabel::DrawStatRotator( float frac )
void UIFakkLabel::DrawStatCompass( float frac )
{
// FIXME: stub
vec4_t col;
float fTargAng;
float fSinVal, fCosVal;
vec2_t vCenter;
vec2_t vVerts[3];
vec2_t vTexCoords[3];
vec2_t vCompassDir;
vec2_t vSideDir;
col[0] = col[1] = col[2] = col[3] = 1.0;
if (!cge) {
return;
}
static int iLastCompassTime = -9999, iLastTimeDelta = 0;
static float fLastPitch = 0, fLastYaw = 0, fLastYawDelta = 0;
static float fYawOffset = 0, fYawSpeed = 0;
static float fNeedleOffset = 0, fNeedleSpeed = 0;
int iTimeCount, iTimeDelta;
float fYawDelta, fYawDeltaDiff;
vec3_t vViewAngles;
cge->CG_EyeAngles(&vViewAngles);
vViewAngles[1] -= cl.snap.ps.stats[STAT_COMPASSNORTH] / 182.0f;
iTimeCount = uid.time - iLastCompassTime;
if (iTimeCount <= 1000)
{
fYawDelta = AngleSubtract(vViewAngles[1], fLastYaw);
if (fYawDelta > 0.1)
{
if ((fYawDelta > 0.0 && fLastYawDelta < fYawDelta)
|| (fYawDelta < 0.0 && fLastYawDelta > fYawDelta))
{
fYawSpeed += (fYawDelta - fLastYawDelta) * 0.75;
fYawOffset += (fYawDelta - fLastYawDelta) * 0.75;
}
if (fYawSpeed > 90.0) {
fYawSpeed = 90.0;
}
else if (fYawSpeed < 0.05) {
fYawSpeed = 0.05;
}
}
while (iTimeCount > 0)
{
iTimeDelta = iTimeCount;
if (iTimeCount > 15) {
iTimeDelta = 15;
}
iTimeCount -= iTimeDelta;
if (fabs(fYawOffset) >= 0.1 || fabs(fYawSpeed) >= 0.01)
{
fYawOffset += fYawSpeed * iTimeDelta;
if (fYawOffset > 0.0) {
fYawSpeed -= iTimeDelta * 0.00175;
}
else if (fYawOffset < 0.0) {
fYawSpeed += iTimeDelta * 0.00175;
}
if (fYawOffset > 40.0) {
fYawOffset = 40.0;
fYawSpeed = 0.0;
}
else if (fYawOffset < -40.0) {
fYawOffset = -40.0;
fYawSpeed = 0.0;
}
fYawSpeed -= iTimeDelta * 0.003;
if (fYawSpeed > 0.0) {
fYawSpeed -= iTimeDelta * 0.0004;
}
else {
fYawSpeed += iTimeDelta * 0.0004;
if (fYawSpeed > 0.0) {
fYawSpeed = 0.0;
}
}
}
else
{
iTimeCount = 0;
fYawOffset = 0.0;
fYawSpeed = 0.0;
}
}
fLastYawDelta = fYawDelta;
iLastTimeDelta = uid.time - iLastCompassTime;
}
else
{
fLastYawDelta = 0;
fYawOffset = 0;
fYawSpeed = 0;
iLastTimeDelta = 0;
}
fLastPitch = vViewAngles[0];
fLastYaw = vViewAngles[1];
iLastCompassTime = uid.time;
if (iLastTimeDelta)
{
if (fabs(fLastYawDelta) > 0.1) {
fNeedleOffset -= fLastYawDelta;
}
iTimeCount = iLastTimeDelta;
while (iTimeCount > 0)
{
iTimeDelta = iTimeCount;
if (iTimeCount > 15) {
iTimeDelta = 15;
}
iTimeCount -= iTimeDelta;
if (fabs(fNeedleOffset) >= 0.1 || fabs(fNeedleSpeed) >= 0.01) {
fNeedleOffset += iTimeDelta * fNeedleSpeed;
if (fNeedleOffset > 180.0) {
fNeedleOffset -= 360.0;
}
else if (fNeedleOffset < -180.0) {
fNeedleOffset += 360.0;
}
if (fNeedleOffset > 0.0) {
fNeedleSpeed -= iTimeDelta * 0.00175;
}
else if (fNeedleOffset < 0.0) {
fNeedleSpeed += iTimeDelta * 0.00175;
}
fNeedleSpeed -= fNeedleSpeed * 0.0025 * iTimeDelta;
if (fNeedleSpeed > 0.0) {
fNeedleSpeed -= iTimeDelta * 0.00035;
if (fNeedleSpeed < 0.0) {
fNeedleSpeed = 0.0;
}
}
else {
fNeedleSpeed += iTimeDelta * 0.00035;
if (fNeedleSpeed > 0.0) {
fNeedleSpeed = 0.0;
}
}
} else {
iTimeCount = 0;
fNeedleOffset = 0.0;
fNeedleSpeed = 0.0;
}
}
}
else
{
fNeedleOffset = 0.0;
fNeedleSpeed = 0.0;
}
fSinVal = sin(anglemod(fNeedleOffset + fLastYaw) / (180 / M_PI));
fCosVal = cos(anglemod(fNeedleOffset + fLastYaw) / (180 / M_PI));
vCompassDir[0] = fSinVal;
vCompassDir[1] = -fCosVal;
vCenter[0] = m_frame.size.width * 0.5;
vCenter[1] = m_frame.size.height * 0.5;
vTexCoords[0][0] = 0.0;
vTexCoords[0][1] = 0.0;
vTexCoords[1][0] = 1.0;
vTexCoords[1][1] = 0.0;
vTexCoords[2][0] = 0.0;
vTexCoords[2][1] = 1.0;
vVerts[0][0] = vCenter[0] + vCompassDir[0] * vCenter[0] - fCosVal * vCenter[1];
vVerts[1][0] = vCenter[0] + vCompassDir[0] * vCenter[0] + fCosVal * vCenter[1];
vVerts[2][0] = vCenter[0] - vCompassDir[0] * vCenter[0] - fCosVal * vCenter[1];
vVerts[0][1] = vCenter[1] + vCompassDir[1] * vCenter[1] - fSinVal * vCenter[0];
vVerts[1][1] = vCenter[1] + vCompassDir[1] * vCenter[1] + fSinVal * vCenter[0];
vVerts[2][1] = vCenter[1] - vCompassDir[1] * vCenter[1] - fSinVal * vCenter[0];
m_statbar_material->ReregisterMaterial();
re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial());
vVerts[0][0] = vVerts[2][0];
vVerts[0][1] = vVerts[2][1];
vTexCoords[0][0] = vTexCoords[2][0];
vTexCoords[0][1] = vTexCoords[2][1];
vTexCoords[2][0] = 1.0;
vTexCoords[2][1] = 1.0;
vVerts[2][0] = vCenter[0] + fCosVal * vCenter[1] - vCompassDir[0] * vCenter[0];
vVerts[2][1] = vCenter[1] * fSinVal + vCenter[0] - vCompassDir[1] * vCenter[1];
m_statbar_material->ReregisterMaterial();
re.DrawTrianglePic(vVerts, vTexCoords, m_statbar_material->GetMaterial());
}
void UIFakkLabel::DrawStatSpinner( float frac )
@@ -506,7 +882,7 @@ void UIFakkLabel::Draw( void )
return;
}
if( m_stat != -1 )
if( m_stat == -1 )
{
float scale;
qhandle_t handle;
@@ -516,7 +892,7 @@ void UIFakkLabel::Draw( void )
vec3_t angles;
vec3_t offset;
vec3_t rotateoffset;
vec3_t color;
vec4_t color;
str sAnimName;
float height;
@@ -686,23 +1062,20 @@ _shitlabel01:
float frac;
if( m_maxstat )
if( m_maxstat >= 0 )
{
frac = delta / ( m_statbar_max - m_statbar_min );
frac = (float)delta / (float)cl.snap.ps.stats[m_maxstat];
}
else
{
frac = delta / cl.snap.ps.stats[ m_maxstat ];
frac = (float)delta / (float)(m_statbar_max - m_statbar_min);
}
if( frac > 1.0 )
frac = 1.0;
if( frac < 0.0 )
frac = 0.0;
if( frac > 1.0 ) frac = 1.0;
else if( frac < 0.0 ) frac = 0.0;
DrawStatbar( frac );
return;
}
+66 -1
View File
@@ -126,7 +126,72 @@ void View3D::DrawFPS
)
{
// FIXME: stub
char string[128];
setFont("verdana-14");
if (fps->integer == 2)
{
re.SetColor(UBlack);
re.DrawBox(
0.0,
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 4.0,
m_frame.pos.x + m_frame.size.width,
m_font->getHeight(qfalse) * 4.0
);
}
sprintf(string, "FPS %4.1f", currentfps);
if (currentfps > 23.94) {
if (cl_greenfps->integer) {
m_font->setColor(UGreen);
} else {
m_font->setColor(UWhite);
}
} else if (currentfps > 18.0) {
m_font->setColor(UYellow);
} else {
// low fps
m_font->setColor(URed);
}
m_font->Print(
m_font->getHeight(qfalse) * 10.0,
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 3.0,
string,
-1,
qfalse
);
// Draw elements count
if (cl_greenfps->integer) {
m_font->setColor(UGreen);
}
else {
m_font->setColor(UWhite);
}
sprintf(string, "wt%5d wv%5d cl%d", cls.world_tris, cls.world_verts, cls.character_lights);
m_font->Print(
m_font->getHeight(qfalse) * 10.0,
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 2.0,
string,
-1,
qfalse
);
sprintf(string, "t%5d v%5d Mtex%5.2f", cls.total_tris, cls.total_verts, (float)cls.total_texels * 0.00000095367432);
m_font->Print(
m_font->getHeight(qfalse) * 10.0,
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse),
string,
-1,
qfalse
);
m_font->setColor(UBlack);
}
void View3D::DrawProf
+1 -1
View File
@@ -59,7 +59,7 @@ public:
void UpdateLocationPrint( int x, int y, const char *s, float alpha );
qboolean LetterboxActive( void );
void InitSubtitle( void );
void FrameInitialized( void );
void FrameInitialized( void ) override;
virtual void Pressed( Event *ev );
};
+6 -10
View File
@@ -126,10 +126,6 @@ typedef struct {
int joystickAxis[MAX_JOYSTICK_AXIS]; // set by joystick events
// cgame communicates a few values to the client system
int cgameUserCmdValue; // current weapon to add to usercmd_t
float cgameSensitivity;
// cmds[cmdNumber] is the predicted command, [cmdNumber-1] is the last
// properly generated command
usercmd_t cmds[CMD_BACKUP]; // each mesage will send several old cmds
@@ -145,9 +141,6 @@ typedef struct {
// and teleport direction changes
vec3_t viewangles;
vec3_t eyeAngles;
vec3_t eyeOrigin;
int serverId; // included in each client message so the server
// can tell if it is for a prior map_restart
// big stuff at end of structure so most offsets are 15 bits or less
@@ -310,6 +303,7 @@ typedef struct {
int framecount;
int frametime; // msec since last frame
float serverFrameTime;
int realtime; // ignores pause
int realFrametime; // ignoring pause, so console always works
@@ -352,6 +346,11 @@ typedef struct {
hdelement_t HudDrawElements[ MAX_HUDDRAW_ELEMENTS ];
clientAnim_t anim;
stopWatch_t stopwatch;
void* savedCgameState;
int savedCgameStateSize;
char gcdResponse[73];
int unknown3_0;
int currentRate;
qhandle_t charSetShader;
qhandle_t whiteShader;
qhandle_t consoleShader;
@@ -578,9 +577,6 @@ void Con_PageDown( void );
void Con_Top( void );
void Con_Bottom( void );
void CL_LoadConsoleHistory( void );
void CL_SaveConsoleHistory( void );
//
// cl_scrn.c
//
+1 -12
View File
@@ -34,17 +34,6 @@ typedef struct {
extern qboolean key_overstrikeMode;
extern qkey_t keys[K_LASTKEY];
// NOTE TTimo the declaration of field_t and Field_Clear is now in qcommon/qcommon.h
void Field_KeyDownEvent( field_t *edit, int key );
void Field_CharEvent( field_t *edit, int ch );
void Field_Draw(fontInfo_t *font, field_t *edit, int x, int y, int width, qboolean showCursor, qboolean noColorEscape );
void Field_BigDraw(fontInfo_t *font, field_t *edit, int x, int y, int width, qboolean showCursor, qboolean noColorEscape );
#define COMMAND_HISTORY 32
extern field_t historyEditLines[COMMAND_HISTORY];
extern field_t g_consoleField;
extern field_t chatField;
extern int anykeydown;
extern qboolean chat_team;
extern int chat_playerNum;
@@ -53,7 +42,7 @@ extern int chat_playerNum;
int Key_StringToKeynum( const char *str );
void Key_WriteBindings( fileHandle_t f );
void Key_SetBinding( int keynum, const char *binding );
char *Key_GetBinding( int keynum );
const char *Key_GetBinding( int keynum );
qboolean Key_IsDown( int keynum );
qboolean Key_GetOverstrikeMode( void );
void Key_SetOverstrikeMode( qboolean state );
+4 -4
View File
@@ -25,7 +25,7 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
/*
** Intel/DVI ADPCM coder/decoder.
**
** The algorithm for this coder was taken from the IMA Compatibility Project
** The algorithm for this coder was taken from the IMA Compatability Project
** proceedings, Vol 2, Number 2; May 1992.
**
** Version 1.2, 18-Dec-92.
@@ -278,7 +278,7 @@ void S_AdpcmGetSamples(sndBuffer *chunk, short *to) {
out = (byte *)chunk->sndChunk;
// get samples
S_AdpcmDecode((char *) out, to, SND_CHUNK_SIZE_BYTE*2, &state );
S_AdpcmDecode( out, to, SND_CHUNK_SIZE_BYTE*2, &state );
}
@@ -310,7 +310,7 @@ void S_AdpcmEncodeSound( sfx_t *sfx, short *samples ) {
newchunk = SND_malloc();
if (sfx->soundData == NULL) {
sfx->soundData = newchunk;
} else if (chunk != NULL) {
} else {
chunk->next = newchunk;
}
chunk = newchunk;
@@ -322,7 +322,7 @@ void S_AdpcmEncodeSound( sfx_t *sfx, short *samples ) {
out = (byte *)chunk->sndChunk;
// encode the samples
S_AdpcmEncode( samples + inOffset, (char *) out, n, &state );
S_AdpcmEncode( samples + inOffset, out, n, &state );
inOffset += n;
count -= n;
-229
View File
@@ -1,229 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
/* This file is only compiled for PowerPC builds with Altivec support.
Altivec intrinsics need to be in a separate file, so GCC's -maltivec
command line can enable them, but give us the option to _not_ use that
on other files, where the compiler might then generate Altivec
instructions for normal floating point, crashing on G3 (etc) processors. */
#include "client.h"
#include "snd_local.h"
#if idppc_altivec
#if !defined(__APPLE__)
#include <altivec.h>
#endif
void S_PaintChannelFrom16_altivec( portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE], int snd_vol, channel_t *ch, const sfx_t *sc, int count, int sampleOffset, int bufferOffset ) {
int data, aoff, boff;
int leftvol, rightvol;
int i, j;
portable_samplepair_t *samp;
sndBuffer *chunk;
short *samples;
float ooff, fdata[2], fdiv, fleftvol, frightvol;
if (sc->soundChannels <= 0) {
return;
}
samp = &paintbuffer[ bufferOffset ];
if (ch->doppler) {
sampleOffset = sampleOffset*ch->oldDopplerScale;
}
if ( sc->soundChannels == 2 ) {
sampleOffset *= sc->soundChannels;
if ( sampleOffset & 1 ) {
sampleOffset &= ~1;
}
}
chunk = sc->soundData;
while (sampleOffset>=SND_CHUNK_SIZE) {
chunk = chunk->next;
sampleOffset -= SND_CHUNK_SIZE;
if (!chunk) {
chunk = sc->soundData;
}
}
if (!ch->doppler || ch->dopplerScale==1.0f) {
vector signed short volume_vec;
vector unsigned int volume_shift;
int vectorCount, samplesLeft, chunkSamplesLeft;
leftvol = ch->leftvol*snd_vol;
rightvol = ch->rightvol*snd_vol;
samples = chunk->sndChunk;
((short *)&volume_vec)[0] = leftvol;
((short *)&volume_vec)[1] = leftvol;
((short *)&volume_vec)[4] = leftvol;
((short *)&volume_vec)[5] = leftvol;
((short *)&volume_vec)[2] = rightvol;
((short *)&volume_vec)[3] = rightvol;
((short *)&volume_vec)[6] = rightvol;
((short *)&volume_vec)[7] = rightvol;
volume_shift = vec_splat_u32(8);
i = 0;
while(i < count) {
/* Try to align destination to 16-byte boundary */
while(i < count && (((unsigned long)&samp[i] & 0x1f) || ((count-i) < 8) || ((SND_CHUNK_SIZE - sampleOffset) < 8))) {
data = samples[sampleOffset++];
samp[i].left += (data * leftvol)>>8;
if ( sc->soundChannels == 2 ) {
data = samples[sampleOffset++];
}
samp[i].right += (data * rightvol)>>8;
if (sampleOffset == SND_CHUNK_SIZE) {
chunk = chunk->next;
samples = chunk->sndChunk;
sampleOffset = 0;
}
i++;
}
/* Destination is now aligned. Process as many 8-sample
chunks as we can before we run out of room from the current
sound chunk. We do 8 per loop to avoid extra source data reads. */
samplesLeft = count - i;
chunkSamplesLeft = SND_CHUNK_SIZE - sampleOffset;
if(samplesLeft > chunkSamplesLeft)
samplesLeft = chunkSamplesLeft;
vectorCount = samplesLeft / 8;
if(vectorCount)
{
vector unsigned char tmp;
vector short s0, s1, sampleData0, sampleData1;
vector signed int merge0, merge1;
vector signed int d0, d1, d2, d3;
vector unsigned char samplePermute0 =
VECCONST_UINT8(0, 1, 4, 5, 0, 1, 4, 5, 2, 3, 6, 7, 2, 3, 6, 7);
vector unsigned char samplePermute1 =
VECCONST_UINT8(8, 9, 12, 13, 8, 9, 12, 13, 10, 11, 14, 15, 10, 11, 14, 15);
vector unsigned char loadPermute0, loadPermute1;
// Rather than permute the vectors after we load them to do the sample
// replication and rearrangement, we permute the alignment vector so
// we do everything in one step below and avoid data shuffling.
tmp = vec_lvsl(0,&samples[sampleOffset]);
loadPermute0 = vec_perm(tmp,tmp,samplePermute0);
loadPermute1 = vec_perm(tmp,tmp,samplePermute1);
s0 = *(vector short *)&samples[sampleOffset];
while(vectorCount)
{
/* Load up source (16-bit) sample data */
s1 = *(vector short *)&samples[sampleOffset+7];
/* Load up destination sample data */
d0 = *(vector signed int *)&samp[i];
d1 = *(vector signed int *)&samp[i+2];
d2 = *(vector signed int *)&samp[i+4];
d3 = *(vector signed int *)&samp[i+6];
sampleData0 = vec_perm(s0,s1,loadPermute0);
sampleData1 = vec_perm(s0,s1,loadPermute1);
merge0 = vec_mule(sampleData0,volume_vec);
merge0 = vec_sra(merge0,volume_shift); /* Shift down to proper range */
merge1 = vec_mulo(sampleData0,volume_vec);
merge1 = vec_sra(merge1,volume_shift);
d0 = vec_add(merge0,d0);
d1 = vec_add(merge1,d1);
merge0 = vec_mule(sampleData1,volume_vec);
merge0 = vec_sra(merge0,volume_shift); /* Shift down to proper range */
merge1 = vec_mulo(sampleData1,volume_vec);
merge1 = vec_sra(merge1,volume_shift);
d2 = vec_add(merge0,d2);
d3 = vec_add(merge1,d3);
/* Store destination sample data */
*(vector signed int *)&samp[i] = d0;
*(vector signed int *)&samp[i+2] = d1;
*(vector signed int *)&samp[i+4] = d2;
*(vector signed int *)&samp[i+6] = d3;
i += 8;
vectorCount--;
s0 = s1;
sampleOffset += 8;
}
if (sampleOffset == SND_CHUNK_SIZE) {
chunk = chunk->next;
samples = chunk->sndChunk;
sampleOffset = 0;
}
}
}
} else {
fleftvol = ch->leftvol*snd_vol;
frightvol = ch->rightvol*snd_vol;
ooff = sampleOffset;
samples = chunk->sndChunk;
for ( i=0 ; i<count ; i++ ) {
aoff = ooff;
ooff = ooff + ch->dopplerScale * sc->soundChannels;
boff = ooff;
fdata[0] = fdata[1] = 0;
for (j=aoff; j<boff; j += sc->soundChannels) {
if (j == SND_CHUNK_SIZE) {
chunk = chunk->next;
if (!chunk) {
chunk = sc->soundData;
}
samples = chunk->sndChunk;
ooff -= SND_CHUNK_SIZE;
}
if ( sc->soundChannels == 2 ) {
fdata[0] += samples[j&(SND_CHUNK_SIZE-1)];
fdata[1] += samples[(j+1)&(SND_CHUNK_SIZE-1)];
} else {
fdata[0] += samples[j&(SND_CHUNK_SIZE-1)];
fdata[1] += samples[j&(SND_CHUNK_SIZE-1)];
}
}
fdiv = 256 * (boff-aoff) / sc->soundChannels;
samp[i].left += (fdata[0] * fleftvol)/fdiv;
samp[i].right += (fdata[1] * frightvol)/fdiv;
}
}
}
#endif
-237
View File
@@ -1,237 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "client.h"
#include "snd_codec.h"
static snd_codec_t *codecs;
/*
=================
S_CodecGetSound
Opens/loads a sound, tries codec based on the sound's file extension
then tries all supported codecs.
=================
*/
static void *S_CodecGetSound(const char *filename, snd_info_t *info)
{
snd_codec_t *codec;
snd_codec_t *orgCodec = NULL;
qboolean orgNameFailed = qfalse;
char localName[ MAX_QPATH ];
const char *ext;
char altName[ MAX_QPATH ];
void *rtn = NULL;
Q_strncpyz(localName, filename, MAX_QPATH);
ext = COM_GetExtension(localName);
if( *ext )
{
// Look for the correct loader and use it
for( codec = codecs; codec; codec = codec->next )
{
if( !Q_stricmp( ext, codec->ext ) )
{
// Load
if( info )
rtn = codec->load(localName, info);
else
rtn = codec->open(localName);
break;
}
}
// A loader was found
if( codec )
{
if( !rtn )
{
// Loader failed, most likely because the file isn't there;
// try again without the extension
orgNameFailed = qtrue;
orgCodec = codec;
COM_StripExtension( filename, localName, MAX_QPATH );
}
else
{
// Something loaded
return rtn;
}
}
}
// Try and find a suitable match using all
// the sound codecs supported
for( codec = codecs; codec; codec = codec->next )
{
if( codec == orgCodec )
continue;
Com_sprintf( altName, sizeof (altName), "%s.%s", localName, codec->ext );
// Load
if( info )
rtn = codec->load(altName, info);
else
rtn = codec->open(altName);
if( rtn )
{
if( orgNameFailed )
{
Com_DPrintf(S_COLOR_YELLOW "WARNING: %s not present, using %s instead\n",
filename, altName );
}
return rtn;
}
}
Com_Printf(S_COLOR_YELLOW "WARNING: Failed to %s sound %s!\n", info ? "load" : "open", filename);
return NULL;
}
/*
=================
S_CodecInit
=================
*/
void S_CodecInit()
{
codecs = NULL;
#ifdef USE_CODEC_OPUS
S_CodecRegister(&opus_codec);
#endif
#ifdef USE_CODEC_VORBIS
S_CodecRegister(&ogg_codec);
#endif
// Register wav codec last so that it is always tried first when a file extension was not found
S_CodecRegister(&wav_codec);
}
/*
=================
S_CodecShutdown
=================
*/
void S_CodecShutdown()
{
codecs = NULL;
}
/*
=================
S_CodecRegister
=================
*/
void S_CodecRegister(snd_codec_t *codec)
{
codec->next = codecs;
codecs = codec;
}
/*
=================
S_CodecLoad
=================
*/
void *S_CodecLoad(const char *filename, snd_info_t *info)
{
return S_CodecGetSound(filename, info);
}
/*
=================
S_CodecOpenStream
=================
*/
snd_stream_t *S_CodecOpenStream(const char *filename)
{
return S_CodecGetSound(filename, NULL);
}
void S_CodecCloseStream(snd_stream_t *stream)
{
stream->codec->close(stream);
}
int S_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer)
{
return stream->codec->read(stream, bytes, buffer);
}
//=======================================================================
// Util functions (used by codecs)
/*
=================
S_CodecUtilOpen
=================
*/
snd_stream_t *S_CodecUtilOpen(const char *filename, snd_codec_t *codec)
{
snd_stream_t *stream;
fileHandle_t hnd;
int length;
// Try to open the file
length = FS_FOpenFileRead(filename, &hnd, qtrue, qtrue);
if(!hnd)
{
Com_DPrintf("Can't read sound file %s\n", filename);
return NULL;
}
// Allocate a stream
stream = Z_Malloc(sizeof(snd_stream_t));
if(!stream)
{
FS_FCloseFile(hnd);
return NULL;
}
// Copy over, return
stream->codec = codec;
stream->file = hnd;
stream->length = length;
return stream;
}
/*
=================
S_CodecUtilClose
=================
*/
void S_CodecUtilClose(snd_stream_t **stream)
{
FS_FCloseFile((*stream)->file);
Z_Free(*stream);
*stream = NULL;
}
-107
View File
@@ -1,107 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef _SND_CODEC_H_
#define _SND_CODEC_H_
#include "../qcommon/q_shared.h"
#include "../qcommon/qcommon.h"
typedef struct snd_info_s
{
int rate;
int width;
int channels;
int samples;
int size;
int dataofs;
} snd_info_t;
typedef struct snd_codec_s snd_codec_t;
typedef struct snd_stream_s
{
snd_codec_t *codec;
fileHandle_t file;
snd_info_t info;
int length;
int pos;
void *ptr;
} snd_stream_t;
// Codec functions
typedef void *(*CODEC_LOAD)(const char *filename, snd_info_t *info);
typedef snd_stream_t *(*CODEC_OPEN)(const char *filename);
typedef int (*CODEC_READ)(snd_stream_t *stream, int bytes, void *buffer);
typedef void (*CODEC_CLOSE)(snd_stream_t *stream);
// Codec data structure
struct snd_codec_s
{
char *ext;
CODEC_LOAD load;
CODEC_OPEN open;
CODEC_READ read;
CODEC_CLOSE close;
snd_codec_t *next;
};
// Codec management
void S_CodecInit( void );
void S_CodecShutdown( void );
void S_CodecRegister(snd_codec_t *codec);
void *S_CodecLoad(const char *filename, snd_info_t *info);
snd_stream_t *S_CodecOpenStream(const char *filename);
void S_CodecCloseStream(snd_stream_t *stream);
int S_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer);
// Util functions (used by codecs)
snd_stream_t *S_CodecUtilOpen(const char *filename, snd_codec_t *codec);
void S_CodecUtilClose(snd_stream_t **stream);
// WAV Codec
extern snd_codec_t wav_codec;
void *S_WAV_CodecLoad(const char *filename, snd_info_t *info);
snd_stream_t *S_WAV_CodecOpenStream(const char *filename);
void S_WAV_CodecCloseStream(snd_stream_t *stream);
int S_WAV_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer);
// Ogg Vorbis codec
#ifdef USE_CODEC_VORBIS
extern snd_codec_t ogg_codec;
void *S_OGG_CodecLoad(const char *filename, snd_info_t *info);
snd_stream_t *S_OGG_CodecOpenStream(const char *filename);
void S_OGG_CodecCloseStream(snd_stream_t *stream);
int S_OGG_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer);
#endif // USE_CODEC_VORBIS
// Ogg Opus codec
#ifdef USE_CODEC_OPUS
extern snd_codec_t opus_codec;
void *S_OggOpus_CodecLoad(const char *filename, snd_info_t *info);
snd_stream_t *S_OggOpus_CodecOpenStream(const char *filename);
void S_OggOpus_CodecCloseStream(snd_stream_t *stream);
int S_OggOpus_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer);
#endif // USE_CODEC_OPUS
#endif // !_SND_CODEC_H_
-717
View File
@@ -1,717 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
Copyright (C) 2005-2006 Joerg Dietrich <dietrich_joerg@gmx.de>
Copyright (C) 2006 Thilo Schulz <arny@ats.s.bawue.de>
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#if USE_CODEC_MP3
// includes for the Q3 sound system
#include "client.h"
#include "snd_codec.h"
// includes for the MP3 codec
#include <mad.h>
#define MP3_SAMPLE_WIDTH 2
#define MP3_PCMSAMPLES_PERSLICE 32
// buffer size used when reading through the mp3
#define MP3_DATA_BUFSIZ 128*1024
// undefine this if you don't want any dithering.
#define MP3_DITHERING
// Q3 MP3 codec
snd_codec_t mp3_codec =
{
".mp3",
S_MP3_CodecLoad,
S_MP3_CodecOpenStream,
S_MP3_CodecReadStream,
S_MP3_CodecCloseStream,
NULL
};
// structure used for info purposes
struct snd_codec_mp3_info
{
byte encbuf[MP3_DATA_BUFSIZ]; // left over bytes not consumed
// by the decoder.
struct mad_stream madstream; // uses encbuf as buffer.
struct mad_frame madframe; // control structures for libmad.
struct mad_synth madsynth;
byte *pcmbuf; // buffer for not-used samples.
int buflen; // length of buffer data.
int pcmbufsize; // amount of allocated memory for
// pcmbuf. This should have at least
// the size of a decoded mp3 frame.
byte *dest; // copy decoded data here.
int destlen; // amount of already copied data.
int destsize; // amount of bytes we must decode.
};
/*************** MP3 utility functions ***************/
/*
=================
S_MP3_ReadData
=================
*/
// feed libmad with data
int S_MP3_ReadData(snd_stream_t *stream, struct mad_stream *madstream, byte *encbuf, int encbufsize)
{
int retval;
int leftover;
if(!stream)
return -1;
leftover = madstream->bufend - madstream->next_frame;
if(leftover > 0)
memmove(encbuf, madstream->this_frame, leftover);
// Fill the buffer right to the end
retval = FS_Read(&encbuf[leftover], encbufsize - leftover, stream->file);
if(retval <= 0)
{
// EOF reached, that's ok.
return 0;
}
mad_stream_buffer(madstream, encbuf, retval + leftover);
return retval;
}
/*
=================
S_MP3_Scanfile
to determine the samplecount, we apparently must get *all* headers :(
I basically used the xmms-mad plugin source to see how this stuff works.
returns a value < 0 on error.
=================
*/
int S_MP3_Scanfile(snd_stream_t *stream)
{
struct mad_stream madstream;
struct mad_header madheader;
int retval;
int samplecount;
byte encbuf[MP3_DATA_BUFSIZ];
// error out on invalid input.
if(!stream)
return -1;
mad_stream_init(&madstream);
mad_header_init(&madheader);
while(1)
{
retval = S_MP3_ReadData(stream, &madstream, encbuf, sizeof(encbuf));
if(retval < 0)
return -1;
else if(retval == 0)
break;
// Start decoding the headers.
while(1)
{
if((retval = mad_header_decode(&madheader, &madstream)) < 0)
{
if(madstream.error == MAD_ERROR_BUFLEN)
{
// We need to read more data
break;
}
if(!MAD_RECOVERABLE (madstream.error))
{
// unrecoverable error... we must bail out.
return retval;
}
mad_stream_skip(&madstream, madstream.skiplen);
continue;
}
// we got a valid header.
if(madheader.layer != MAD_LAYER_III)
{
// we don't support non-mp3s
return -1;
}
if(!stream->info.samples)
{
// This here is the very first frame. Set initial values now,
// that we expect to stay constant throughout the whole mp3.
stream->info.rate = madheader.samplerate;
stream->info.width = MP3_SAMPLE_WIDTH;
stream->info.channels = MAD_NCHANNELS(&madheader);
stream->info.samples = 0;
stream->info.size = 0; // same here.
stream->info.dataofs = 0;
}
else
{
// Check whether something changed that shouldn't.
if(stream->info.rate != madheader.samplerate ||
stream->info.channels != MAD_NCHANNELS(&madheader))
return -1;
}
// Update the counters
samplecount = MAD_NSBSAMPLES(&madheader) * MP3_PCMSAMPLES_PERSLICE;
stream->info.samples += samplecount;
stream->info.size += samplecount * stream->info.channels * stream->info.width;
}
}
// Reset the file pointer so we can do the real decoding.
FS_Seek(stream->file, 0, FS_SEEK_SET);
return 0;
}
/************************ dithering functions ***************************/
#ifdef MP3_DITHERING
// All dithering done here is taken from the GPL'ed xmms-mad plugin.
/* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. */
/* Any feedback is very welcome. For any question, comments, */
/* see http://www.math.keio.ac.jp/matumoto/emt.html or email */
/* matumoto@math.keio.ac.jp */
/* Period parameters */
#define MP3_DITH_N 624
#define MP3_DITH_M 397
#define MATRIX_A 0x9908b0df /* constant vector a */
#define UPPER_MASK 0x80000000 /* most significant w-r bits */
#define LOWER_MASK 0x7fffffff /* least significant r bits */
/* Tempering parameters */
#define TEMPERING_MASK_B 0x9d2c5680
#define TEMPERING_MASK_C 0xefc60000
#define TEMPERING_SHIFT_U(y) (y >> 11)
#define TEMPERING_SHIFT_S(y) (y << 7)
#define TEMPERING_SHIFT_T(y) (y << 15)
#define TEMPERING_SHIFT_L(y) (y >> 18)
static unsigned long mt[MP3_DITH_N]; /* the array for the state vector */
static int mti=MP3_DITH_N+1; /* mti==MP3_DITH_N+1 means mt[MP3_DITH_N] is not initialized */
/* initializing the array with a NONZERO seed */
void sgenrand(unsigned long seed)
{
/* setting initial seeds to mt[MP3_DITH_N] using */
/* the generator Line 25 of Table 1 in */
/* [KNUTH 1981, The Art of Computer Programming */
/* Vol. 2 (2nd Ed.), pp102] */
mt[0]= seed & 0xffffffff;
for (mti=1; mti<MP3_DITH_N; mti++)
mt[mti] = (69069 * mt[mti-1]) & 0xffffffff;
}
unsigned long genrand(void)
{
unsigned long y;
static unsigned long mag01[2]={0x0, MATRIX_A};
/* mag01[x] = x * MATRIX_A for x=0,1 */
if (mti >= MP3_DITH_N) { /* generate MP3_DITH_N words at one time */
int kk;
if (mti == MP3_DITH_N+1) /* if sgenrand() has not been called, */
sgenrand(4357); /* a default initial seed is used */
for (kk=0;kk<MP3_DITH_N-MP3_DITH_M;kk++) {
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
mt[kk] = mt[kk+MP3_DITH_M] ^ (y >> 1) ^ mag01[y & 0x1];
}
for (;kk<MP3_DITH_N-1;kk++) {
y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
mt[kk] = mt[kk+(MP3_DITH_M-MP3_DITH_N)] ^ (y >> 1) ^ mag01[y & 0x1];
}
y = (mt[MP3_DITH_N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
mt[MP3_DITH_N-1] = mt[MP3_DITH_M-1] ^ (y >> 1) ^ mag01[y & 0x1];
mti = 0;
}
y = mt[mti++];
y ^= TEMPERING_SHIFT_U(y);
y ^= TEMPERING_SHIFT_S(y) & TEMPERING_MASK_B;
y ^= TEMPERING_SHIFT_T(y) & TEMPERING_MASK_C;
y ^= TEMPERING_SHIFT_L(y);
return y;
}
long triangular_dither_noise(int nbits) {
// parameter nbits : the peak-to-peak amplitude desired (in bits)
// use with nbits set to 2 + nber of bits to be trimmed.
// (because triangular is made from two uniformly distributed processes,
// it starts at 2 bits peak-to-peak amplitude)
// see The Theory of Dithered Quantization by Robert Alexander Wannamaker
// for complete proof of why that's optimal
long v = (genrand()/2 - genrand()/2); // in ]-2^31, 2^31[
//int signe = (v>0) ? 1 : -1;
long P = 1 << (32 - nbits); // the power of 2
v /= P;
// now v in ]-2^(nbits-1), 2^(nbits-1) [
return v;
}
#endif // MP3_DITHERING
/************************ decoder functions ***************************/
/*
=================
S_MP3_Scale
Converts the signal to 16 bit LE-PCM data and does dithering.
- borrowed from xmms-mad plugin source.
=================
*/
/*
* xmms-mad - mp3 plugin for xmms
* Copyright (C) 2001-2002 Sam Clegg
*/
signed int S_MP3_Scale(mad_fixed_t sample)
{
int n_bits_to_loose = MAD_F_FRACBITS + 1 - 16;
#ifdef MP3_DITHERING
int dither;
#endif
// round
sample += (1L << (n_bits_to_loose - 1));
#ifdef MP3_DITHERING
dither = triangular_dither_noise(n_bits_to_loose + 1);
sample += dither;
#endif
/* clip */
if (sample >= MAD_F_ONE)
sample = MAD_F_ONE - 1;
else if (sample < -MAD_F_ONE)
sample = -MAD_F_ONE;
/* quantize */
return sample >> n_bits_to_loose;
}
/*
=================
S_MP3_PCMCopy
Copy and convert pcm data until bytecount bytes have been written.
return the position in pcm->samples.
indicate the amount of actually written bytes in wrotecnt.
=================
*/
int S_MP3_PCMCopy(byte *buf, struct mad_pcm *pcm, int bufofs,
int sampleofs, int bytecount, int *wrotecnt)
{
int written = 0;
signed int sample;
int framesize = pcm->channels * MP3_SAMPLE_WIDTH;
// add new pcm data.
while(written < bytecount && sampleofs < pcm->length)
{
sample = S_MP3_Scale(pcm->samples[0][sampleofs]);
#ifdef Q3_BIG_ENDIAN
// output to 16 bit big endian PCM
buf[bufofs++] = (sample >> 8) & 0xff;
buf[bufofs++] = sample & 0xff;
#else
// output to 16 bit little endian PCM
buf[bufofs++] = sample & 0xff;
buf[bufofs++] = (sample >> 8) & 0xff;
#endif
if(pcm->channels == 2)
{
sample = S_MP3_Scale(pcm->samples[1][sampleofs]);
#ifdef Q3_BIG_ENDIAN
buf[bufofs++] = (sample >> 8) & 0xff;
buf[bufofs++] = sample & 0xff;
#else
buf[bufofs++] = sample & 0xff;
buf[bufofs++] = (sample >> 8) & 0xff;
#endif
}
sampleofs++;
written += framesize;
}
if(wrotecnt)
*wrotecnt = written;
return sampleofs;
}
/*
=================
S_MP3_Decode
=================
*/
// gets executed for every decoded frame.
int S_MP3_Decode(snd_stream_t *stream)
{
struct snd_codec_mp3_info *mp3info;
struct mad_stream *madstream;
struct mad_frame *madframe;
struct mad_synth *madsynth;
struct mad_pcm *pcm;
int cursize;
int samplecount;
int needcount;
int wrote;
int retval;
if(!stream)
return -1;
mp3info = stream->ptr;
madstream = &mp3info->madstream;
madframe = &mp3info->madframe;
if(mad_frame_decode(madframe, madstream))
{
if(madstream->error == MAD_ERROR_BUFLEN)
{
// we need more data. Read another chunk.
retval = S_MP3_ReadData(stream, madstream, mp3info->encbuf, sizeof(mp3info->encbuf));
// call myself again now that buffer is full.
if(retval > 0)
retval = S_MP3_Decode(stream);
}
else if(MAD_RECOVERABLE(madstream->error))
{
mad_stream_skip(madstream, madstream->skiplen);
return S_MP3_Decode(stream);
}
else
retval = -1;
return retval;
}
// check whether this really is an mp3
if(madframe->header.layer != MAD_LAYER_III)
return -1;
// generate pcm data
madsynth = &mp3info->madsynth;
mad_synth_frame(madsynth, madframe);
pcm = &madsynth->pcm;
// perform a few checks to see whether something changed that shouldn't.
if(stream->info.rate != pcm->samplerate ||
stream->info.channels != pcm->channels)
{
return -1;
}
// see whether we have got enough data now.
cursize = pcm->length * pcm->channels * stream->info.width;
needcount = mp3info->destsize - mp3info->destlen;
// Copy exactly as many samples as required.
samplecount = S_MP3_PCMCopy(mp3info->dest, pcm,
mp3info->destlen, 0, needcount, &wrote);
mp3info->destlen += wrote;
if(samplecount < pcm->length)
{
// Not all samples got copied. Copy the rest into the pcm buffer.
samplecount = S_MP3_PCMCopy(mp3info->pcmbuf, pcm,
mp3info->buflen,
samplecount,
mp3info->pcmbufsize - mp3info->buflen,
&wrote);
mp3info->buflen += wrote;
if(samplecount < pcm->length)
{
// The pcm buffer was not large enough. Make it bigger.
byte *newbuf = Z_Malloc(cursize);
if(mp3info->pcmbuf)
{
memcpy(newbuf, mp3info->pcmbuf, mp3info->buflen);
Z_Free(mp3info->pcmbuf);
}
mp3info->pcmbuf = newbuf;
mp3info->pcmbufsize = cursize;
samplecount = S_MP3_PCMCopy(mp3info->pcmbuf, pcm,
mp3info->buflen,
samplecount,
mp3info->pcmbufsize - mp3info->buflen,
&wrote);
mp3info->buflen += wrote;
}
// we're definitely done.
retval = 0;
}
else if(mp3info->destlen >= mp3info->destsize)
retval = 0;
else
retval = 1;
return retval;
}
/*************** Callback functions for quake3 ***************/
/*
=================
S_MP3_CodecOpenStream
=================
*/
snd_stream_t *S_MP3_CodecOpenStream(const char *filename)
{
snd_stream_t *stream;
struct snd_codec_mp3_info *mp3info;
// Open the stream
stream = S_CodecUtilOpen(filename, &mp3_codec);
if(!stream || stream->length <= 0)
return NULL;
// We have to scan through the MP3 to determine the important mp3 info.
if(S_MP3_Scanfile(stream) < 0)
{
// scanning didn't work out...
S_CodecUtilClose(&stream);
return NULL;
}
// Initialize the mp3 info structure we need for streaming
mp3info = Z_Malloc(sizeof(*mp3info));
if(!mp3info)
{
S_CodecUtilClose(&stream);
return NULL;
}
stream->ptr = mp3info;
// initialize the libmad control structures.
mad_stream_init(&mp3info->madstream);
mad_frame_init(&mp3info->madframe);
mad_synth_init(&mp3info->madsynth);
if(S_MP3_ReadData(stream, &mp3info->madstream, mp3info->encbuf, sizeof(mp3info->encbuf)) <= 0)
{
// we didnt read anything, that's bad.
S_MP3_CodecCloseStream(stream);
return NULL;
}
return stream;
}
/*
=================
S_MP3_CodecCloseStream
=================
*/
// free all memory we allocated.
void S_MP3_CodecCloseStream(snd_stream_t *stream)
{
struct snd_codec_mp3_info *mp3info;
if(!stream)
return;
// free all data in our mp3info tree
if(stream->ptr)
{
mp3info = stream->ptr;
if(mp3info->pcmbuf)
Z_Free(mp3info->pcmbuf);
mad_synth_finish(&mp3info->madsynth);
mad_frame_finish(&mp3info->madframe);
mad_stream_finish(&mp3info->madstream);
Z_Free(stream->ptr);
}
S_CodecUtilClose(&stream);
}
/*
=================
S_MP3_CodecReadStream
=================
*/
int S_MP3_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer)
{
struct snd_codec_mp3_info *mp3info;
int retval;
if(!stream)
return -1;
mp3info = stream->ptr;
// Make sure we get complete frames all the way through.
bytes -= bytes % (stream->info.channels * stream->info.width);
if(mp3info->buflen)
{
if(bytes < mp3info->buflen)
{
// we still have enough bytes in our decoded pcm buffer
memcpy(buffer, mp3info->pcmbuf, bytes);
// remove the portion from our buffer.
mp3info->buflen -= bytes;
memmove(mp3info->pcmbuf, &mp3info->pcmbuf[bytes], mp3info->buflen);
return bytes;
}
else
{
// copy over the samples we already have.
memcpy(buffer, mp3info->pcmbuf, mp3info->buflen);
mp3info->destlen = mp3info->buflen;
mp3info->buflen = 0;
}
}
else
mp3info->destlen = 0;
mp3info->dest = buffer;
mp3info->destsize = bytes;
do
{
retval = S_MP3_Decode(stream);
} while(retval > 0);
// if there was an error return nothing.
if(retval < 0)
return 0;
return mp3info->destlen;
}
/*
=====================================================================
S_MP3_CodecLoad
We handle S_MP3_CodecLoad as a special case of the streaming functions
where we read the whole stream at once.
======================================================================
*/
void *S_MP3_CodecLoad(const char *filename, snd_info_t *info)
{
snd_stream_t *stream;
byte *pcmbuffer;
// check if input is valid
if(!filename)
return NULL;
stream = S_MP3_CodecOpenStream(filename);
if(!stream)
return NULL;
// copy over the info
info->rate = stream->info.rate;
info->width = stream->info.width;
info->channels = stream->info.channels;
info->samples = stream->info.samples;
info->dataofs = stream->info.dataofs;
// allocate enough buffer for all pcm data
// pcmbuffer = Z_Malloc(stream->info.size);
pcmbuffer = Hunk_AllocateTempMemory(stream->info.size);
if(!pcmbuffer)
{
S_MP3_CodecCloseStream(stream);
return NULL;
}
info->size = S_MP3_CodecReadStream(stream, stream->info.size, pcmbuffer);
if(info->size <= 0)
{
// we didn't read anything at all. darn.
// Z_Free(pcmbuffer);
Hunk_FreeTempMemory(pcmbuffer);
pcmbuffer = NULL;
}
S_MP3_CodecCloseStream(stream);
return pcmbuffer;
}
#endif
-475
View File
@@ -1,475 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
Copyright (C) 2005-2006 Joerg Dietrich <dietrich_joerg@gmx.de>
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// OGG support is enabled by this define
#ifdef USE_CODEC_VORBIS
// includes for the Q3 sound system
#include "client.h"
#include "snd_codec.h"
// includes for the OGG codec
#include <errno.h>
#define OV_EXCLUDE_STATIC_CALLBACKS
#include <vorbis/vorbisfile.h>
// The OGG codec can return the samples in a number of different formats,
// we use the standard signed short format.
#define OGG_SAMPLEWIDTH 2
// Q3 OGG codec
snd_codec_t ogg_codec =
{
"ogg",
S_OGG_CodecLoad,
S_OGG_CodecOpenStream,
S_OGG_CodecReadStream,
S_OGG_CodecCloseStream,
NULL
};
// callbacks for vobisfile
// fread() replacement
size_t S_OGG_Callback_read(void *ptr, size_t size, size_t nmemb, void *datasource)
{
snd_stream_t *stream;
int byteSize = 0;
int bytesRead = 0;
size_t nMembRead = 0;
// check if input is valid
if(!ptr)
{
errno = EFAULT;
return 0;
}
if(!(size && nmemb))
{
// It's not an error, caller just wants zero bytes!
errno = 0;
return 0;
}
if(!datasource)
{
errno = EBADF;
return 0;
}
// we use a snd_stream_t in the generic pointer to pass around
stream = (snd_stream_t *) datasource;
// FS_Read does not support multi-byte elements
byteSize = nmemb * size;
// read it with the Q3 function FS_Read()
bytesRead = FS_Read(ptr, byteSize, stream->file);
// update the file position
stream->pos += bytesRead;
// this function returns the number of elements read not the number of bytes
nMembRead = bytesRead / size;
// even if the last member is only read partially
// it is counted as a whole in the return value
if(bytesRead % size)
{
nMembRead++;
}
return nMembRead;
}
// fseek() replacement
int S_OGG_Callback_seek(void *datasource, ogg_int64_t offset, int whence)
{
snd_stream_t *stream;
int retVal = 0;
// check if input is valid
if(!datasource)
{
errno = EBADF;
return -1;
}
// snd_stream_t in the generic pointer
stream = (snd_stream_t *) datasource;
// we must map the whence to its Q3 counterpart
switch(whence)
{
case SEEK_SET :
{
// set the file position in the actual file with the Q3 function
retVal = FS_Seek(stream->file, (long) offset, FS_SEEK_SET);
// something has gone wrong, so we return here
if(retVal < 0)
{
return retVal;
}
// keep track of file position
stream->pos = (int) offset;
break;
}
case SEEK_CUR :
{
// set the file position in the actual file with the Q3 function
retVal = FS_Seek(stream->file, (long) offset, FS_SEEK_CUR);
// something has gone wrong, so we return here
if(retVal < 0)
{
return retVal;
}
// keep track of file position
stream->pos += (int) offset;
break;
}
case SEEK_END :
{
// set the file position in the actual file with the Q3 function
retVal = FS_Seek(stream->file, (long) offset, FS_SEEK_END);
// something has gone wrong, so we return here
if(retVal < 0)
{
return retVal;
}
// keep track of file position
stream->pos = stream->length + (int) offset;
break;
}
default :
{
// unknown whence, so we return an error
errno = EINVAL;
return -1;
}
}
// stream->pos shouldn't be smaller than zero or bigger than the filesize
stream->pos = (stream->pos < 0) ? 0 : stream->pos;
stream->pos = (stream->pos > stream->length) ? stream->length : stream->pos;
return 0;
}
// fclose() replacement
int S_OGG_Callback_close(void *datasource)
{
// we do nothing here and close all things manually in S_OGG_CodecCloseStream()
return 0;
}
// ftell() replacement
long S_OGG_Callback_tell(void *datasource)
{
snd_stream_t *stream;
// check if input is valid
if(!datasource)
{
errno = EBADF;
return -1;
}
// snd_stream_t in the generic pointer
stream = (snd_stream_t *) datasource;
return (long) FS_FTell(stream->file);
}
// the callback structure
const ov_callbacks S_OGG_Callbacks =
{
&S_OGG_Callback_read,
&S_OGG_Callback_seek,
&S_OGG_Callback_close,
&S_OGG_Callback_tell
};
/*
=================
S_OGG_CodecOpenStream
=================
*/
snd_stream_t *S_OGG_CodecOpenStream(const char *filename)
{
snd_stream_t *stream;
// OGG codec control structure
OggVorbis_File *vf;
// some variables used to get informations about the OGG
vorbis_info *OGGInfo;
ogg_int64_t numSamples;
// check if input is valid
if(!filename)
{
return NULL;
}
// Open the stream
stream = S_CodecUtilOpen(filename, &ogg_codec);
if(!stream)
{
return NULL;
}
// alloctate the OggVorbis_File
vf = Z_Malloc(sizeof(OggVorbis_File));
if(!vf)
{
S_CodecUtilClose(&stream);
return NULL;
}
// open the codec with our callbacks and stream as the generic pointer
if(ov_open_callbacks(stream, vf, NULL, 0, S_OGG_Callbacks) != 0)
{
Z_Free(vf);
S_CodecUtilClose(&stream);
return NULL;
}
// the stream must be seekable
if(!ov_seekable(vf))
{
ov_clear(vf);
Z_Free(vf);
S_CodecUtilClose(&stream);
return NULL;
}
// we only support OGGs with one substream
if(ov_streams(vf) != 1)
{
ov_clear(vf);
Z_Free(vf);
S_CodecUtilClose(&stream);
return NULL;
}
// get the info about channels and rate
OGGInfo = ov_info(vf, 0);
if(!OGGInfo)
{
ov_clear(vf);
Z_Free(vf);
S_CodecUtilClose(&stream);
return NULL;
}
// get the number of sample-frames in the OGG
numSamples = ov_pcm_total(vf, 0);
// fill in the info-structure in the stream
stream->info.rate = OGGInfo->rate;
stream->info.width = OGG_SAMPLEWIDTH;
stream->info.channels = OGGInfo->channels;
stream->info.samples = numSamples;
stream->info.size = stream->info.samples * stream->info.channels * stream->info.width;
stream->info.dataofs = 0;
// We use stream->pos for the file pointer in the compressed ogg file
stream->pos = 0;
// We use the generic pointer in stream for the OGG codec control structure
stream->ptr = vf;
return stream;
}
/*
=================
S_OGG_CodecCloseStream
=================
*/
void S_OGG_CodecCloseStream(snd_stream_t *stream)
{
// check if input is valid
if(!stream)
{
return;
}
// let the OGG codec cleanup its stuff
ov_clear((OggVorbis_File *) stream->ptr);
// free the OGG codec control struct
Z_Free(stream->ptr);
// close the stream
S_CodecUtilClose(&stream);
}
/*
=================
S_OGG_CodecReadStream
=================
*/
int S_OGG_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer)
{
// buffer handling
int bytesRead, bytesLeft, c;
char *bufPtr;
// Bitstream for the decoder
int BS = 0;
// big endian machines want their samples in big endian order
int IsBigEndian = 0;
# ifdef Q3_BIG_ENDIAN
IsBigEndian = 1;
# endif // Q3_BIG_ENDIAN
// check if input is valid
if(!(stream && buffer))
{
return 0;
}
if(bytes <= 0)
{
return 0;
}
bytesRead = 0;
bytesLeft = bytes;
bufPtr = buffer;
// cycle until we have the requested or all available bytes read
while(-1)
{
// read some bytes from the OGG codec
c = ov_read((OggVorbis_File *) stream->ptr, bufPtr, bytesLeft, IsBigEndian, OGG_SAMPLEWIDTH, 1, &BS);
// no more bytes are left
if(c <= 0)
{
break;
}
bytesRead += c;
bytesLeft -= c;
bufPtr += c;
// we have enough bytes
if(bytesLeft <= 0)
{
break;
}
}
return bytesRead;
}
/*
=====================================================================
S_OGG_CodecLoad
We handle S_OGG_CodecLoad as a special case of the streaming functions
where we read the whole stream at once.
======================================================================
*/
void *S_OGG_CodecLoad(const char *filename, snd_info_t *info)
{
snd_stream_t *stream;
byte *buffer;
int bytesRead;
// check if input is valid
if(!(filename && info))
{
return NULL;
}
// open the file as a stream
stream = S_OGG_CodecOpenStream(filename);
if(!stream)
{
return NULL;
}
// copy over the info
info->rate = stream->info.rate;
info->width = stream->info.width;
info->channels = stream->info.channels;
info->samples = stream->info.samples;
info->size = stream->info.size;
info->dataofs = stream->info.dataofs;
// allocate a buffer
// this buffer must be free-ed by the caller of this function
buffer = Hunk_AllocateTempMemory(info->size);
if(!buffer)
{
S_OGG_CodecCloseStream(stream);
return NULL;
}
// fill the buffer
bytesRead = S_OGG_CodecReadStream(stream, info->size, buffer);
// we don't even have read a single byte
if(bytesRead <= 0)
{
Hunk_FreeTempMemory(buffer);
S_OGG_CodecCloseStream(stream);
return NULL;
}
S_OGG_CodecCloseStream(stream);
return buffer;
}
#endif // USE_CODEC_VORBIS
-449
View File
@@ -1,449 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
Copyright (C) 2005-2006 Joerg Dietrich <dietrich_joerg@gmx.de>
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// Ogg Opus support is enabled by this define
#ifdef USE_CODEC_OPUS
// includes for the Q3 sound system
#include "client.h"
#include "snd_codec.h"
// includes for the Ogg Opus codec
#include <errno.h>
#include <opusfile.h>
// samples are 16 bit
#define OPUS_SAMPLEWIDTH 2
// Q3 Ogg Opus codec
snd_codec_t opus_codec =
{
"opus",
S_OggOpus_CodecLoad,
S_OggOpus_CodecOpenStream,
S_OggOpus_CodecReadStream,
S_OggOpus_CodecCloseStream,
NULL
};
// callbacks for opusfile
// fread() replacement
int S_OggOpus_Callback_read(void *datasource, unsigned char *ptr, int size )
{
snd_stream_t *stream;
int bytesRead = 0;
// check if input is valid
if(!ptr)
{
errno = EFAULT;
return -1;
}
if(!size)
{
// It's not an error, caller just wants zero bytes!
errno = 0;
return 0;
}
if (size < 0)
{
errno = EINVAL;
return -1;
}
if(!datasource)
{
errno = EBADF;
return -1;
}
// we use a snd_stream_t in the generic pointer to pass around
stream = (snd_stream_t *) datasource;
// read it with the Q3 function FS_Read()
bytesRead = FS_Read(ptr, size, stream->file);
// update the file position
stream->pos += bytesRead;
return bytesRead;
}
// fseek() replacement
int S_OggOpus_Callback_seek(void *datasource, opus_int64 offset, int whence)
{
snd_stream_t *stream;
int retVal = 0;
// check if input is valid
if(!datasource)
{
errno = EBADF;
return -1;
}
// snd_stream_t in the generic pointer
stream = (snd_stream_t *) datasource;
// we must map the whence to its Q3 counterpart
switch(whence)
{
case SEEK_SET :
{
// set the file position in the actual file with the Q3 function
retVal = FS_Seek(stream->file, (long) offset, FS_SEEK_SET);
// something has gone wrong, so we return here
if(retVal < 0)
{
return retVal;
}
// keep track of file position
stream->pos = (int) offset;
break;
}
case SEEK_CUR :
{
// set the file position in the actual file with the Q3 function
retVal = FS_Seek(stream->file, (long) offset, FS_SEEK_CUR);
// something has gone wrong, so we return here
if(retVal < 0)
{
return retVal;
}
// keep track of file position
stream->pos += (int) offset;
break;
}
case SEEK_END :
{
// set the file position in the actual file with the Q3 function
retVal = FS_Seek(stream->file, (long) offset, FS_SEEK_END);
// something has gone wrong, so we return here
if(retVal < 0)
{
return retVal;
}
// keep track of file position
stream->pos = stream->length + (int) offset;
break;
}
default :
{
// unknown whence, so we return an error
errno = EINVAL;
return -1;
}
}
// stream->pos shouldn't be smaller than zero or bigger than the filesize
stream->pos = (stream->pos < 0) ? 0 : stream->pos;
stream->pos = (stream->pos > stream->length) ? stream->length : stream->pos;
return 0;
}
// fclose() replacement
int S_OggOpus_Callback_close(void *datasource)
{
// we do nothing here and close all things manually in S_OggOpus_CodecCloseStream()
return 0;
}
// ftell() replacement
opus_int64 S_OggOpus_Callback_tell(void *datasource)
{
snd_stream_t *stream;
// check if input is valid
if(!datasource)
{
errno = EBADF;
return -1;
}
// snd_stream_t in the generic pointer
stream = (snd_stream_t *) datasource;
return (opus_int64) FS_FTell(stream->file);
}
// the callback structure
const OpusFileCallbacks S_OggOpus_Callbacks =
{
&S_OggOpus_Callback_read,
&S_OggOpus_Callback_seek,
&S_OggOpus_Callback_tell,
&S_OggOpus_Callback_close
};
/*
=================
S_OggOpus_CodecOpenStream
=================
*/
snd_stream_t *S_OggOpus_CodecOpenStream(const char *filename)
{
snd_stream_t *stream;
// Opus codec control structure
OggOpusFile *of;
// some variables used to get informations about the file
const OpusHead *opusInfo;
ogg_int64_t numSamples;
// check if input is valid
if(!filename)
{
return NULL;
}
// Open the stream
stream = S_CodecUtilOpen(filename, &opus_codec);
if(!stream)
{
return NULL;
}
// open the codec with our callbacks and stream as the generic pointer
of = op_open_callbacks(stream, &S_OggOpus_Callbacks, NULL, 0, NULL );
if (!of)
{
S_CodecUtilClose(&stream);
return NULL;
}
// the stream must be seekable
if(!op_seekable(of))
{
op_free(of);
S_CodecUtilClose(&stream);
return NULL;
}
// get the info about channels and rate
opusInfo = op_head(of, -1);
if(!opusInfo)
{
op_free(of);
S_CodecUtilClose(&stream);
return NULL;
}
if(opusInfo->stream_count != 1)
{
op_free(of);
S_CodecUtilClose(&stream);
Com_Printf("Only Ogg Opus files with one stream are support\n");
return NULL;
}
if(opusInfo->channel_count != 1 && opusInfo->channel_count != 2)
{
op_free(of);
S_CodecUtilClose(&stream);
Com_Printf("Only mono and stereo Ogg Opus files are supported\n");
return NULL;
}
// get the number of sample-frames in the file
numSamples = op_pcm_total(of, -1);
// fill in the info-structure in the stream
stream->info.rate = 48000;
stream->info.width = OPUS_SAMPLEWIDTH;
stream->info.channels = opusInfo->channel_count;
stream->info.samples = numSamples;
stream->info.size = stream->info.samples * stream->info.channels * stream->info.width;
stream->info.dataofs = 0;
// We use stream->pos for the file pointer in the compressed ogg file
stream->pos = 0;
// We use the generic pointer in stream for the opus codec control structure
stream->ptr = of;
return stream;
}
/*
=================
S_OggOpus_CodecCloseStream
=================
*/
void S_OggOpus_CodecCloseStream(snd_stream_t *stream)
{
// check if input is valid
if(!stream)
{
return;
}
// let the opus codec cleanup its stuff
op_free((OggOpusFile *) stream->ptr);
// close the stream
S_CodecUtilClose(&stream);
}
/*
=================
S_OggOpus_CodecReadStream
=================
*/
int S_OggOpus_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer)
{
// buffer handling
int samplesRead, samplesLeft, c;
opus_int16 *bufPtr;
// check if input is valid
if(!(stream && buffer))
{
return 0;
}
if(bytes <= 0)
{
return 0;
}
samplesRead = 0;
samplesLeft = bytes / stream->info.channels / stream->info.width;
bufPtr = buffer;
if(samplesLeft <= 0)
{
return 0;
}
// cycle until we have the requested or all available bytes read
while(-1)
{
// read some samples from the opus codec
c = op_read((OggOpusFile *) stream->ptr, bufPtr + samplesRead * stream->info.channels, samplesLeft * stream->info.channels, NULL);
// no more samples are left
if(c <= 0)
{
break;
}
samplesRead += c;
samplesLeft -= c;
// we have enough samples
if(samplesLeft <= 0)
{
break;
}
}
return samplesRead * stream->info.channels * stream->info.width;
}
/*
=====================================================================
S_OggOpus_CodecLoad
We handle S_OggOpus_CodecLoad as a special case of the streaming functions
where we read the whole stream at once.
======================================================================
*/
void *S_OggOpus_CodecLoad(const char *filename, snd_info_t *info)
{
snd_stream_t *stream;
byte *buffer;
int bytesRead;
// check if input is valid
if(!(filename && info))
{
return NULL;
}
// open the file as a stream
stream = S_OggOpus_CodecOpenStream(filename);
if(!stream)
{
return NULL;
}
// copy over the info
info->rate = stream->info.rate;
info->width = stream->info.width;
info->channels = stream->info.channels;
info->samples = stream->info.samples;
info->size = stream->info.size;
info->dataofs = stream->info.dataofs;
// allocate a buffer
// this buffer must be free-ed by the caller of this function
buffer = Hunk_AllocateTempMemory(info->size);
if(!buffer)
{
S_OggOpus_CodecCloseStream(stream);
return NULL;
}
// fill the buffer
bytesRead = S_OggOpus_CodecReadStream(stream, info->size, buffer);
// we don't even have read a single byte
if(bytesRead <= 0)
{
Hunk_FreeTempMemory(buffer);
S_OggOpus_CodecCloseStream(stream);
return NULL;
}
S_OggOpus_CodecCloseStream(stream);
return buffer;
}
#endif // USE_CODEC_OPUS
-291
View File
@@ -1,291 +0,0 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2005 Stuart Dalton (badcdev@gmail.com)
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "client.h"
#include "snd_codec.h"
/*
=================
FGetLittleLong
=================
*/
static int FGetLittleLong( fileHandle_t f ) {
int v;
FS_Read( &v, sizeof(v), f );
return LittleLong( v);
}
/*
=================
FGetLittleShort
=================
*/
static short FGetLittleShort( fileHandle_t f ) {
short v;
FS_Read( &v, sizeof(v), f );
return LittleShort( v);
}
/*
=================
S_ReadChunkInfo
=================
*/
static int S_ReadChunkInfo(fileHandle_t f, char *name)
{
int len, r;
name[4] = 0;
r = FS_Read(name, 4, f);
if(r != 4)
return -1;
len = FGetLittleLong(f);
if( len < 0 ) {
Com_Printf( S_COLOR_YELLOW "WARNING: Negative chunk length\n" );
return -1;
}
return len;
}
/*
=================
S_FindRIFFChunk
Returns the length of the data in the chunk, or -1 if not found
=================
*/
static int S_FindRIFFChunk( fileHandle_t f, char *chunk ) {
char name[5];
int len;
while( ( len = S_ReadChunkInfo(f, name) ) >= 0 )
{
// If this is the right chunk, return
if( !Q_strncmp( name, chunk, 4 ) )
return len;
len = PAD( len, 2 );
// Not the right chunk - skip it
FS_Seek( f, len, FS_SEEK_CUR );
}
return -1;
}
/*
=================
S_ByteSwapRawSamples
=================
*/
static void S_ByteSwapRawSamples( int samples, int width, int s_channels, const byte *data ) {
int i;
if ( width != 2 ) {
return;
}
if ( LittleShort( 256 ) == 256 ) {
return;
}
if ( s_channels == 2 ) {
samples <<= 1;
}
for ( i = 0 ; i < samples ; i++ ) {
((short *)data)[i] = LittleShort( ((short *)data)[i] );
}
}
/*
=================
S_ReadRIFFHeader
=================
*/
static qboolean S_ReadRIFFHeader(fileHandle_t file, snd_info_t *info)
{
char dump[16];
int bits;
int fmtlen = 0;
// skip the riff wav header
FS_Read(dump, 12, file);
// Scan for the format chunk
if((fmtlen = S_FindRIFFChunk(file, "fmt ")) < 0)
{
Com_Printf( S_COLOR_RED "ERROR: Couldn't find \"fmt\" chunk\n");
return qfalse;
}
// Save the parameters
FGetLittleShort(file); // wav_format
info->channels = FGetLittleShort(file);
info->rate = FGetLittleLong(file);
FGetLittleLong(file);
FGetLittleShort(file);
bits = FGetLittleShort(file);
if( bits < 8 )
{
Com_Printf( S_COLOR_RED "ERROR: Less than 8 bit sound is not supported\n");
return qfalse;
}
info->width = bits / 8;
info->dataofs = 0;
// Skip the rest of the format chunk if required
if(fmtlen > 16)
{
fmtlen -= 16;
FS_Seek( file, fmtlen, FS_SEEK_CUR );
}
// Scan for the data chunk
if( (info->size = S_FindRIFFChunk(file, "data")) < 0)
{
Com_Printf( S_COLOR_RED "ERROR: Couldn't find \"data\" chunk\n");
return qfalse;
}
info->samples = (info->size / info->width) / info->channels;
return qtrue;
}
// WAV codec
snd_codec_t wav_codec =
{
"wav",
S_WAV_CodecLoad,
S_WAV_CodecOpenStream,
S_WAV_CodecReadStream,
S_WAV_CodecCloseStream,
NULL
};
/*
=================
S_WAV_CodecLoad
=================
*/
void *S_WAV_CodecLoad(const char *filename, snd_info_t *info)
{
fileHandle_t file;
void *buffer;
// Try to open the file
FS_FOpenFileRead(filename, &file, qtrue, qtrue);
if(!file)
{
return NULL;
}
// Read the RIFF header
if(!S_ReadRIFFHeader(file, info))
{
FS_FCloseFile(file);
Com_Printf( S_COLOR_RED "ERROR: Incorrect/unsupported format in \"%s\"\n",
filename);
return NULL;
}
// Allocate some memory
buffer = Hunk_AllocateTempMemory(info->size);
if(!buffer)
{
FS_FCloseFile(file);
Com_Printf( S_COLOR_RED "ERROR: Out of memory reading \"%s\"\n",
filename);
return NULL;
}
// Read, byteswap
FS_Read(buffer, info->size, file);
S_ByteSwapRawSamples(info->samples, info->width, info->channels, (byte *)buffer);
// Close and return
FS_FCloseFile(file);
return buffer;
}
/*
=================
S_WAV_CodecOpenStream
=================
*/
snd_stream_t *S_WAV_CodecOpenStream(const char *filename)
{
snd_stream_t *rv;
// Open
rv = S_CodecUtilOpen(filename, &wav_codec);
if(!rv)
return NULL;
// Read the RIFF header
if(!S_ReadRIFFHeader(rv->file, &rv->info))
{
S_CodecUtilClose(&rv);
return NULL;
}
return rv;
}
/*
=================
S_WAV_CodecCloseStream
=================
*/
void S_WAV_CodecCloseStream(snd_stream_t *stream)
{
S_CodecUtilClose(&stream);
}
/*
=================
S_WAV_CodecReadStream
=================
*/
int S_WAV_CodecReadStream(snd_stream_t *stream, int bytes, void *buffer)
{
int remaining = stream->info.size - stream->pos;
int samples;
if(remaining <= 0)
return 0;
if(bytes > remaining)
bytes = remaining;
stream->pos += bytes;
samples = (bytes / stream->info.width) / stream->info.channels;
FS_Read(buffer, bytes, stream->file);
S_ByteSwapRawSamples(samples, stream->info.width, stream->info.channels, buffer);
return bytes;
}
+789 -438
View File
File diff suppressed because it is too large. Load diff
+24 -87
View File
@@ -15,14 +15,14 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// snd_local.h -- private sound definations
#include "../qcommon/q_shared.h"
#include "q_shared.h"
#include "../qcommon/qcommon.h"
#include "snd_public.h"
@@ -30,9 +30,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
extern "C" {
#endif
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define PAINTBUFFER_SIZE 4096 // this is in samples
#define SND_CHUNK_SIZE 1024 // samples
@@ -63,7 +60,6 @@ typedef struct sfx_s {
qboolean soundCompressed; // not in Memory
int soundCompressionMethod;
int soundLength;
int soundChannels;
char soundName[MAX_QPATH];
int lastTimeUsed;
struct sfx_s *next;
@@ -72,20 +68,14 @@ typedef struct sfx_s {
typedef struct {
int channels;
int samples; // mono samples in buffer
int fullsamples; // samples with all channels in buffer (samples divided by channels)
int submission_chunk; // don't mix less than this #
int samplebits;
int isfloat;
int speed;
byte *buffer;
} dma_t;
#define START_SAMPLE_IMMEDIATE 0x7fffffff
#define MAX_DOPPLER_SCALE 50.0f //arbitrary
#define THIRD_PERSON_THRESHOLD_SQ (48.0f*48.0f)
typedef struct loopSound_s {
vec3_t origin;
vec3_t velocity;
@@ -114,7 +104,6 @@ typedef struct
qboolean fixed_origin; // use origin instead of fetching entnum's origin
sfx_t *thesfx; // sfx structure
qboolean doppler;
qboolean fullVolume;
} channel_t;
@@ -130,38 +119,6 @@ typedef struct {
int dataofs; // chunk starts this many bytes from file start
} wavinfo_t;
// Interface between Q3 sound "api" and the sound backend
typedef struct
{
void (*Shutdown)(void);
void (*StartSound)(const vec3_t origin, int entnum, int entchannel, sfxHandle_t sfx );
void (*StartLocalSound)( sfxHandle_t sfx, int channelNum );
void (*StartBackgroundTrack)( const char *intro, const char *loop );
void (*StopBackgroundTrack)( void );
void (*RawSamples)(int stream, int samples, int rate, int width, int channels, const byte *data, float volume, int entityNum);
void (*StopAllSounds)( void );
void (*ClearLoopingSounds)( qboolean killall );
void (*AddLoopingSound)( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx );
void (*AddRealLoopingSound)( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx );
void (*StopLoopingSound)(int entityNum );
void (*Respatialize)( int entityNum, const vec3_t origin, vec3_t axis[3], int inwater );
void (*UpdateEntityPosition)( int entityNum, const vec3_t origin );
void (*Update)( void );
void (*DisableSounds)( void );
void (*BeginRegistration)( void );
sfxHandle_t (*RegisterSound)( const char *sample, qboolean compressed );
void (*ClearSoundBuffer)( void );
void (*SoundInfo)( void );
void (*SoundList)( void );
#ifdef USE_VOIP
void (*StartCapture)( void );
int (*AvailableCaptureSamples)( void );
void (*Capture)( int samples, byte *data );
void (*StopCapture)( void );
void (*MasterGain)( float gain );
#endif
} soundInterface_t;
/*
====================================================================
@@ -184,51 +141,43 @@ void SNDDMA_BeginPainting (void);
void SNDDMA_Submit(void);
#ifdef USE_VOIP
void SNDDMA_StartCapture(void);
int SNDDMA_AvailableCaptureSamples(void);
void SNDDMA_Capture(int samples, byte *data);
void SNDDMA_StopCapture(void);
void SNDDMA_MasterGain(float val);
#endif
//====================================================================
#define MAX_SOUNDCHANNELS 96
#define MAX_CHANNELS 96
extern channel_t s_channels[MAX_SOUNDCHANNELS];
extern channel_t loop_channels[MAX_SOUNDCHANNELS];
extern channel_t s_channels[MAX_CHANNELS];
extern channel_t loop_channels[MAX_CHANNELS];
extern int numLoopChannels;
extern int s_paintedtime;
extern int s_rawend;
extern vec3_t listener_forward;
extern vec3_t listener_right;
extern vec3_t listener_up;
extern dma_t dma;
#define MAX_RAW_SAMPLES 16384
#define MAX_RAW_STREAMS (MAX_CLIENTS * 2 + 1)
extern portable_samplepair_t s_rawsamples[MAX_RAW_STREAMS][MAX_RAW_SAMPLES];
extern int s_rawend[MAX_RAW_STREAMS];
extern portable_samplepair_t s_rawsamples[MAX_RAW_SAMPLES];
extern cvar_t *s_volume;
extern cvar_t *s_musicVolume;
extern cvar_t *s_muted;
extern cvar_t *s_doppler;
extern cvar_t *s_volume;
extern cvar_t *s_nosound;
extern cvar_t *s_khz;
extern cvar_t *s_show;
extern cvar_t *s_mixahead;
extern cvar_t *s_testsound;
extern cvar_t *s_testsound;
extern cvar_t *s_separation;
qboolean S_LoadSound( sfx_t *sfx );
void SND_free(sndBuffer *v);
sndBuffer* SND_malloc( void );
void SND_setup( void );
void SND_shutdown(void);
sndBuffer* SND_malloc();
void SND_setup();
void S_PaintChannels(int endtime);
void S_memoryLoad(sfx_t *sfx);
portable_samplepair_t *S_GetRawSamplePointer();
// spatializes a channel
void S_Spatialize(channel_t *ch);
@@ -243,7 +192,7 @@ void S_AdpcmGetSamples(sndBuffer *chunk, short *to);
#define SENTINEL_MULAW_ZERO_RUN 127
#define SENTINEL_MULAW_FOUR_BIT_RUN 126
void S_FreeOldestSound( void );
void S_FreeOldestSound();
#define NXStream byte
@@ -257,24 +206,12 @@ extern short *sfxScratchBuffer;
extern sfx_t *sfxScratchPointer;
extern int sfxScratchIndex;
qboolean S_Base_Init( soundInterface_t *si );
// OpenAL stuff
typedef enum
{
SRCPRI_AMBIENT = 0, // Ambient sound effects
SRCPRI_ENTITY, // Entity sound effects
SRCPRI_ONESHOT, // One-shot sounds
SRCPRI_LOCAL, // Local sounds
SRCPRI_STREAM // Streams (music, cutscenes)
} alSrcPriority_t;
typedef int srcHandle_t;
qboolean S_AL_Init( soundInterface_t *si );
#ifdef idppc_altivec
void S_PaintChannelFrom16_altivec( portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE], int snd_vol, channel_t *ch, const sfx_t *sc, int count, int sampleOffset, int bufferOffset );
#ifdef __linux__
// https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=371
// custom Snd_Memset implementation for glibc memset bug workaround
void Snd_Memset(void* dest, const int val, const size_t count);
#else
#define Snd_Memset Com_Memset
#endif
#ifdef __cplusplus
+6 -6
View File
@@ -22,18 +22,19 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "client.h"
#include "snd_codec.h"
#include "snd_local.h"
#include "snd_public.h"
cvar_t *s_volume;
cvar_t *s_muted;
cvar_t *s_musicVolume;
cvar_t *s_doppler;
cvar_t *s_backend;
cvar_t *s_muteWhenMinimized;
cvar_t *s_muteWhenUnfocused;
#if 0
cvar_t* s_volume;
cvar_t* s_musicVolume;
cvar_t* s_doppler;
static soundInterface_t si;
/*
@@ -332,13 +333,11 @@ S_RegisterSound
*/
sfxHandle_t S_RegisterSound(const char *sample, qboolean compressed, qboolean streamed)
{
/*
if( si.RegisterSound ) {
return si.RegisterSound( sample, compressed );
} else {
return 0;
}
*/
// FIXME: infinite loop
}
@@ -889,3 +888,4 @@ void S_FadeSound(float fTime)
{
// FIXME: stub
}
#endif
+196 -66
View File
@@ -15,7 +15,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
@@ -30,7 +30,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*****************************************************************************/
#include "snd_local.h"
#include "snd_codec.h"
#define DEF_COMSOUNDMEGS "8"
@@ -57,7 +56,7 @@ void SND_free(sndBuffer *v) {
inUse += sizeof(sndBuffer);
}
sndBuffer* SND_malloc(void) {
sndBuffer* SND_malloc() {
sndBuffer *v;
redo:
if (freelist == NULL) {
@@ -74,7 +73,7 @@ redo:
return v;
}
void SND_setup(void) {
void SND_setup() {
sndBuffer *p, *q;
cvar_t *cv;
int scs;
@@ -100,12 +99,137 @@ void SND_setup(void) {
Com_Printf("Sound memory manager started\n");
}
void SND_shutdown(void)
/*
===============================================================================
WAV loading
===============================================================================
*/
static byte *data_p;
static byte *iff_end;
static byte *last_chunk;
static byte *iff_data;
static int iff_chunk_len;
static short GetLittleShort(void)
{
free(sfxScratchBuffer);
free(buffer);
short val = 0;
val = *data_p;
val = val + (*(data_p+1)<<8);
data_p += 2;
return val;
}
static int GetLittleLong(void)
{
int val = 0;
val = *data_p;
val = val + (*(data_p+1)<<8);
val = val + (*(data_p+2)<<16);
val = val + (*(data_p+3)<<24);
data_p += 4;
return val;
}
static void FindNextChunk(char *name)
{
while (1)
{
data_p=last_chunk;
if (data_p >= iff_end)
{ // didn't find the chunk
data_p = NULL;
return;
}
data_p += 4;
iff_chunk_len = GetLittleLong();
if (iff_chunk_len < 0)
{
data_p = NULL;
return;
}
data_p -= 8;
last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 );
if (!strncmp((char *)data_p, name, 4))
return;
}
}
static void FindChunk(char *name)
{
last_chunk = iff_data;
FindNextChunk (name);
}
/*
============
GetWavinfo
============
*/
static wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
{
wavinfo_t info;
Com_Memset (&info, 0, sizeof(info));
if (!wav)
return info;
iff_data = wav;
iff_end = wav + wavlength;
// find "RIFF" chunk
FindChunk("RIFF");
if (!(data_p && !strncmp((char *)data_p+8, "WAVE", 4)))
{
Com_Printf("Missing RIFF/WAVE chunks\n");
return info;
}
// get "fmt " chunk
iff_data = data_p + 12;
// DumpChunks ();
FindChunk("fmt ");
if (!data_p)
{
Com_Printf("Missing fmt chunk\n");
return info;
}
data_p += 8;
info.format = GetLittleShort();
info.channels = GetLittleShort();
info.rate = GetLittleLong();
data_p += 4+2;
info.width = GetLittleShort() / 8;
if (info.format != 1)
{
Com_Printf("Microsoft PCM format only\n");
return info;
}
// find data chunk
FindChunk("data");
if (!data_p)
{
Com_Printf("Missing data chunk\n");
return info;
}
data_p += 4;
info.samples = GetLittleLong () / info.width;
info.dataofs = data_p - wav;
return info;
}
/*
================
ResampleSfx
@@ -113,53 +237,47 @@ ResampleSfx
resample / decimate to the current source rate
================
*/
static int ResampleSfx( sfx_t *sfx, int channels, int inrate, int inwidth, int samples, byte *data, qboolean compressed ) {
static void ResampleSfx( sfx_t *sfx, int inrate, int inwidth, byte *data, qboolean compressed ) {
int outcount;
int srcsample;
float stepscale;
int i, j;
int i;
int sample, samplefrac, fracstep;
int part;
sndBuffer *chunk;
stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2
outcount = samples / stepscale;
outcount = sfx->soundLength / stepscale;
sfx->soundLength = outcount;
srcsample = 0;
samplefrac = 0;
fracstep = stepscale * 256 * channels;
fracstep = stepscale * 256;
chunk = sfx->soundData;
for (i=0 ; i<outcount ; i++)
{
srcsample += samplefrac >> 8;
samplefrac &= 255;
srcsample = samplefrac >> 8;
samplefrac += fracstep;
for (j=0 ; j<channels ; j++)
{
if( inwidth == 2 ) {
sample = ( ((short *)data)[srcsample+j] );
if( inwidth == 2 ) {
sample = LittleShort ( ((short *)data)[srcsample] );
} else {
sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8;
}
part = (i&(SND_CHUNK_SIZE-1));
if (part == 0) {
sndBuffer *newchunk;
newchunk = SND_malloc();
if (chunk == NULL) {
sfx->soundData = newchunk;
} else {
sample = (unsigned int)( (unsigned char)(data[srcsample+j]) - 128) << 8;
chunk->next = newchunk;
}
part = (i*channels+j)&(SND_CHUNK_SIZE-1);
if (part == 0) {
sndBuffer *newchunk;
newchunk = SND_malloc();
if (chunk == NULL) {
sfx->soundData = newchunk;
} else {
chunk->next = newchunk;
}
chunk = newchunk;
}
chunk->sndChunk[part] = sample;
chunk = newchunk;
}
}
return outcount;
chunk->sndChunk[part] = sample;
}
}
/*
@@ -169,39 +287,35 @@ ResampleSfx
resample / decimate to the current source rate
================
*/
static int ResampleSfxRaw( short *sfx, int channels, int inrate, int inwidth, int samples, byte *data ) {
static int ResampleSfxRaw( short *sfx, int inrate, int inwidth, int samples, byte *data ) {
int outcount;
int srcsample;
float stepscale;
int i, j;
int i;
int sample, samplefrac, fracstep;
stepscale = (float)inrate / dma.speed; // this is usually 0.5, 1, or 2
outcount = samples / stepscale;
srcsample = 0;
samplefrac = 0;
fracstep = stepscale * 256 * channels;
fracstep = stepscale * 256;
for (i=0 ; i<outcount ; i++)
{
srcsample += samplefrac >> 8;
samplefrac &= 255;
srcsample = samplefrac >> 8;
samplefrac += fracstep;
for (j=0 ; j<channels ; j++)
{
if( inwidth == 2 ) {
sample = LittleShort ( ((short *)data)[srcsample+j] );
} else {
sample = (int)( (unsigned char)(data[srcsample+j]) - 128) << 8;
}
sfx[i*channels+j] = sample;
if( inwidth == 2 ) {
sample = LittleShort ( ((short *)data)[srcsample] );
} else {
sample = (int)( (unsigned char)(data[srcsample]) - 128) << 8;
}
sfx[i] = sample;
}
return outcount;
}
//=============================================================================
/*
@@ -216,23 +330,40 @@ qboolean S_LoadSound( sfx_t *sfx )
{
byte *data;
short *samples;
snd_info_t info;
// int size;
wavinfo_t info;
int size;
// player specific sounds are never directly loaded
if ( sfx->soundName[0] == '*') {
return qfalse;
}
// load it in
data = S_CodecLoad(sfx->soundName, &info);
if(!data)
size = FS_ReadFile( sfx->soundName, (void **)&data );
if ( !data ) {
return qfalse;
}
info = GetWavinfo( sfx->soundName, data, size );
if ( info.channels != 1 ) {
Com_Printf ("%s is a stereo wav file\n", sfx->soundName);
FS_FreeFile (data);
return qfalse;
}
if ( info.width == 1 ) {
Com_DPrintf(S_COLOR_YELLOW "WARNING: %s is a 8 bit audio file\n", sfx->soundName);
Com_DPrintf(S_COLOR_YELLOW "WARNING: %s is a 8 bit wav file\n", sfx->soundName);
}
if ( info.rate != 22050 ) {
Com_DPrintf(S_COLOR_YELLOW "WARNING: %s is not a 22kHz audio file\n", sfx->soundName);
Com_DPrintf(S_COLOR_YELLOW "WARNING: %s is not a 22kHz wav file\n", sfx->soundName);
}
samples = Hunk_AllocateTempMemory(info.channels * info.samples * sizeof(short) * 2);
if (!info.samples) {
return qfalse;
}
samples = Hunk_AllocateTempMemory(info.samples * sizeof(short) * 2);
sfx->lastTimeUsed = Com_Milliseconds()+1;
@@ -242,37 +373,36 @@ qboolean S_LoadSound( sfx_t *sfx )
// manager to do the right thing for us and page
// sound in as needed
if( info.channels == 1 && sfx->soundCompressed == qtrue) {
if( sfx->soundCompressed == qtrue) {
sfx->soundCompressionMethod = 1;
sfx->soundData = NULL;
sfx->soundLength = ResampleSfxRaw( samples, info.channels, info.rate, info.width, info.samples, data + info.dataofs );
sfx->soundLength = ResampleSfxRaw( samples, info.rate, info.width, info.samples, (data + info.dataofs) );
S_AdpcmEncodeSound(sfx, samples);
#if 0
} else if (info.channels == 1 && info.samples>(SND_CHUNK_SIZE*16) && info.width >1) {
} else if (info.samples>(SND_CHUNK_SIZE*16) && info.width >1) {
sfx->soundCompressionMethod = 3;
sfx->soundData = NULL;
sfx->soundLength = ResampleSfxRaw( samples, info.channels, info.rate, info.width, info.samples, (data + info.dataofs) );
sfx->soundLength = ResampleSfxRaw( samples, info.rate, info.width, info.samples, (data + info.dataofs) );
encodeMuLaw( sfx, samples);
} else if (info.channels == 1 && info.samples>(SND_CHUNK_SIZE*6400) && info.width >1) {
} else if (info.samples>(SND_CHUNK_SIZE*6400) && info.width >1) {
sfx->soundCompressionMethod = 2;
sfx->soundData = NULL;
sfx->soundLength = ResampleSfxRaw( samples, info.channels, info.rate, info.width, info.samples, (data + info.dataofs) );
sfx->soundLength = ResampleSfxRaw( samples, info.rate, info.width, info.samples, (data + info.dataofs) );
encodeWavelet( sfx, samples);
#endif
} else {
sfx->soundCompressionMethod = 0;
sfx->soundLength = info.samples;
sfx->soundData = NULL;
sfx->soundLength = ResampleSfx( sfx, info.channels, info.rate, info.width, info.samples, data + info.dataofs, qfalse );
ResampleSfx( sfx, info.rate, info.width, data + info.dataofs, qfalse );
}
sfx->soundChannels = info.channels;
Hunk_FreeTempMemory(samples);
Hunk_FreeTempMemory(data);
FS_FreeFile( data );
return qtrue;
}
void S_DisplayFreeMemory(void) {
void S_DisplayFreeMemory() {
Com_Printf("%d bytes free sound buffer memory, %d total used\n", inUse, totalInUse);
}
+182 -128
View File
@@ -15,23 +15,24 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// snd_mix.c -- portable code to mix sounds for snd_dma.c
#include "client.h"
#include "snd_local.h"
static portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE];
static int snd_vol;
// bk001119 - these not static, required by unix/snd_mixa.s
int* snd_p;
int snd_linear_count;
short* snd_out;
#if !id386 // if configured not to use asm
#if !( (defined __linux__ || defined __FreeBSD__ ) && (defined __i386__) ) // rb010123
#if !id386
void S_WriteLinearBlastStereo16 (void)
{
@@ -57,9 +58,6 @@ void S_WriteLinearBlastStereo16 (void)
snd_out[i+1] = val;
}
}
#elif defined(__GNUC__)
// uses snd_mixa.s
void S_WriteLinearBlastStereo16 (void);
#else
__declspec( naked ) void S_WriteLinearBlastStereo16 (void)
@@ -106,6 +104,10 @@ LClampDone2:
}
}
#endif
#else
// forward declare, implementation somewhere else
void S_WriteLinearBlastStereo16 (void);
#endif
void S_TransferStereo16 (unsigned long *pbuf, int endtime)
@@ -119,24 +121,21 @@ void S_TransferStereo16 (unsigned long *pbuf, int endtime)
while (ls_paintedtime < endtime)
{
// handle recirculating buffer issues
lpos = ls_paintedtime % dma.fullsamples;
lpos = ls_paintedtime & ((dma.samples>>1)-1);
snd_out = (short *) pbuf + (lpos<<1); // lpos * dma.channels
snd_out = (short *) pbuf + (lpos<<1);
snd_linear_count = dma.fullsamples - lpos;
snd_linear_count = (dma.samples>>1) - lpos;
if (ls_paintedtime + snd_linear_count > endtime)
snd_linear_count = endtime - ls_paintedtime;
snd_linear_count <<= 1; // snd_linear_count *= dma.channels
snd_linear_count <<= 1;
// write a linear blast of samples
S_WriteLinearBlastStereo16 ();
snd_p += snd_linear_count;
ls_paintedtime += (snd_linear_count>>1); // snd_linear_count / dma.channels
if( CL_VideoRecording( ) )
CL_WriteAVIAudioFrame( (byte *)snd_out, snd_linear_count << 1 ); // snd_linear_count * (dma.samplebits/8)
ls_paintedtime += (snd_linear_count>>1);
}
}
@@ -150,16 +149,19 @@ void S_TransferPaintBuffer(int endtime)
{
int out_idx;
int count;
int out_mask;
int *p;
int step;
int val;
int i;
unsigned long *pbuf;
pbuf = (unsigned long *)dma.buffer;
if ( s_testsound->integer ) {
int i;
int count;
// write a fixed sine wave
count = (endtime - s_paintedtime);
for (i=0 ; i<count ; i++)
@@ -175,73 +177,38 @@ void S_TransferPaintBuffer(int endtime)
{ // general case
p = (int *) paintbuffer;
count = (endtime - s_paintedtime) * dma.channels;
out_idx = ((unsigned int)s_paintedtime * dma.channels) % dma.samples;
step = 3 - MIN(dma.channels, 2);
out_mask = dma.samples - 1;
out_idx = s_paintedtime * dma.channels & out_mask;
step = 3 - dma.channels;
if ((dma.isfloat) && (dma.samplebits == 32))
{
float *out = (float *) pbuf;
for (i=0 ; i<count ; i++)
{
if ((i % dma.channels) >= 2)
{
val = 0;
}
else
{
val = *p >> 8;
p+= step;
}
if (val > 0x7fff)
val = 0x7fff;
else if (val < -32767) /* clamp to one less than max to make division max out at -1.0f. */
val = -32767;
out[out_idx] = ((float) val) / 32767.0f;
out_idx = (out_idx + 1) % dma.samples;
}
}
else if (dma.samplebits == 16)
if (dma.samplebits == 16)
{
short *out = (short *) pbuf;
for (i=0 ; i<count ; i++)
while (count--)
{
if ((i % dma.channels) >= 2)
{
val = 0;
}
else
{
val = *p >> 8;
p+= step;
}
val = *p >> 8;
p+= step;
if (val > 0x7fff)
val = 0x7fff;
else if (val < -32768)
val = -32768;
out[out_idx] = val;
out_idx = (out_idx + 1) % dma.samples;
out_idx = (out_idx + 1) & out_mask;
}
}
else if (dma.samplebits == 8)
{
unsigned char *out = (unsigned char *) pbuf;
for (i=0 ; i<count ; i++)
while (count--)
{
if ((i % dma.channels) >= 2)
{
val = 0;
}
else
{
val = *p >> 8;
p+= step;
}
val = *p >> 8;
p+= step;
if (val > 0x7fff)
val = 0x7fff;
else if (val < -32768)
val = -32768;
out[out_idx] = (val>>8) + 128;
out_idx = (out_idx + 1) % dma.samples;
out_idx = (out_idx + 1) & out_mask;
}
}
}
@@ -256,18 +223,14 @@ CHANNEL MIXING
===============================================================================
*/
static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int count, int sampleOffset, int bufferOffset ) {
static void S_PaintChannelFrom16( channel_t *ch, const sfx_t *sc, int count, int sampleOffset, int bufferOffset ) {
int data, aoff, boff;
int leftvol, rightvol;
int i, j;
portable_samplepair_t *samp;
sndBuffer *chunk;
short *samples;
float ooff, fdata[2], fdiv, fleftvol, frightvol;
if (sc->soundChannels <= 0) {
return;
}
float ooff, fdata, fdiv, fleftvol, frightvol;
samp = &paintbuffer[ bufferOffset ];
@@ -275,14 +238,6 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou
sampleOffset = sampleOffset*ch->oldDopplerScale;
}
if ( sc->soundChannels == 2 ) {
sampleOffset *= sc->soundChannels;
if ( sampleOffset & 1 ) {
sampleOffset &= ~1;
}
}
chunk = sc->soundData;
while (sampleOffset>=SND_CHUNK_SIZE) {
chunk = chunk->next;
@@ -293,16 +248,126 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou
}
if (!ch->doppler || ch->dopplerScale==1.0f) {
#if idppc_altivec
vector signed short volume_vec;
vector unsigned int volume_shift;
int vectorCount, samplesLeft, chunkSamplesLeft;
#endif
leftvol = ch->leftvol*snd_vol;
rightvol = ch->rightvol*snd_vol;
samples = chunk->sndChunk;
#if idppc_altivec
((short *)&volume_vec)[0] = leftvol;
((short *)&volume_vec)[1] = leftvol;
((short *)&volume_vec)[4] = leftvol;
((short *)&volume_vec)[5] = leftvol;
((short *)&volume_vec)[2] = rightvol;
((short *)&volume_vec)[3] = rightvol;
((short *)&volume_vec)[6] = rightvol;
((short *)&volume_vec)[7] = rightvol;
volume_shift = vec_splat_u32(8);
i = 0;
while(i < count) {
/* Try to align destination to 16-byte boundary */
while(i < count && (((unsigned long)&samp[i] & 0x1f) || ((count-i) < 8) || ((SND_CHUNK_SIZE - sampleOffset) < 8))) {
data = samples[sampleOffset++];
samp[i].left += (data * leftvol)>>8;
samp[i].right += (data * rightvol)>>8;
if (sampleOffset == SND_CHUNK_SIZE) {
chunk = chunk->next;
samples = chunk->sndChunk;
sampleOffset = 0;
}
i++;
}
/* Destination is now aligned. Process as many 8-sample
chunks as we can before we run out of room from the current
sound chunk. We do 8 per loop to avoid extra source data reads. */
samplesLeft = count - i;
chunkSamplesLeft = SND_CHUNK_SIZE - sampleOffset;
if(samplesLeft > chunkSamplesLeft)
samplesLeft = chunkSamplesLeft;
vectorCount = samplesLeft / 8;
if(vectorCount)
{
vector unsigned char tmp;
vector short s0, s1, sampleData0, sampleData1;
vector short samples0, samples1;
vector signed int left0, right0;
vector signed int merge0, merge1;
vector signed int d0, d1, d2, d3;
vector unsigned char samplePermute0 =
(vector unsigned char)(0, 1, 4, 5, 0, 1, 4, 5, 2, 3, 6, 7, 2, 3, 6, 7);
vector unsigned char samplePermute1 =
(vector unsigned char)(8, 9, 12, 13, 8, 9, 12, 13, 10, 11, 14, 15, 10, 11, 14, 15);
vector unsigned char loadPermute0, loadPermute1;
// Rather than permute the vectors after we load them to do the sample
// replication and rearrangement, we permute the alignment vector so
// we do everything in one step below and avoid data shuffling.
tmp = vec_lvsl(0,&samples[sampleOffset]);
loadPermute0 = vec_perm(tmp,tmp,samplePermute0);
loadPermute1 = vec_perm(tmp,tmp,samplePermute1);
s0 = *(vector short *)&samples[sampleOffset];
while(vectorCount)
{
/* Load up source (16-bit) sample data */
s1 = *(vector short *)&samples[sampleOffset+7];
/* Load up destination sample data */
d0 = *(vector signed int *)&samp[i];
d1 = *(vector signed int *)&samp[i+2];
d2 = *(vector signed int *)&samp[i+4];
d3 = *(vector signed int *)&samp[i+6];
sampleData0 = vec_perm(s0,s1,loadPermute0);
sampleData1 = vec_perm(s0,s1,loadPermute1);
merge0 = vec_mule(sampleData0,volume_vec);
merge0 = vec_sra(merge0,volume_shift); /* Shift down to proper range */
merge1 = vec_mulo(sampleData0,volume_vec);
merge1 = vec_sra(merge1,volume_shift);
d0 = vec_add(merge0,d0);
d1 = vec_add(merge1,d1);
merge0 = vec_mule(sampleData1,volume_vec);
merge0 = vec_sra(merge0,volume_shift); /* Shift down to proper range */
merge1 = vec_mulo(sampleData1,volume_vec);
merge1 = vec_sra(merge1,volume_shift);
d2 = vec_add(merge0,d2);
d3 = vec_add(merge1,d3);
/* Store destination sample data */
*(vector signed int *)&samp[i] = d0;
*(vector signed int *)&samp[i+2] = d1;
*(vector signed int *)&samp[i+4] = d2;
*(vector signed int *)&samp[i+6] = d3;
i += 8;
vectorCount--;
s0 = s1;
sampleOffset += 8;
}
if (sampleOffset == SND_CHUNK_SIZE) {
chunk = chunk->next;
samples = chunk->sndChunk;
sampleOffset = 0;
}
}
}
#else
for ( i=0 ; i<count ; i++ ) {
data = samples[sampleOffset++];
samp[i].left += (data * leftvol)>>8;
if ( sc->soundChannels == 2 ) {
data = samples[sampleOffset++];
}
samp[i].right += (data * rightvol)>>8;
if (sampleOffset == SND_CHUNK_SIZE) {
@@ -311,6 +376,7 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou
sampleOffset = 0;
}
}
#endif
} else {
fleftvol = ch->leftvol*snd_vol;
frightvol = ch->rightvol*snd_vol;
@@ -324,10 +390,10 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou
for ( i=0 ; i<count ; i++ ) {
aoff = ooff;
ooff = ooff + ch->dopplerScale * sc->soundChannels;
ooff = ooff + ch->dopplerScale;
boff = ooff;
fdata[0] = fdata[1] = 0;
for (j=aoff; j<boff; j += sc->soundChannels) {
fdata = 0;
for (j=aoff; j<boff; j++) {
if (j == SND_CHUNK_SIZE) {
chunk = chunk->next;
if (!chunk) {
@@ -336,32 +402,15 @@ static void S_PaintChannelFrom16_scalar( channel_t *ch, const sfx_t *sc, int cou
samples = chunk->sndChunk;
ooff -= SND_CHUNK_SIZE;
}
if ( sc->soundChannels == 2 ) {
fdata[0] += samples[j&(SND_CHUNK_SIZE-1)];
fdata[1] += samples[(j+1)&(SND_CHUNK_SIZE-1)];
} else {
fdata[0] += samples[j&(SND_CHUNK_SIZE-1)];
fdata[1] += samples[j&(SND_CHUNK_SIZE-1)];
}
fdata += samples[j&(SND_CHUNK_SIZE-1)];
}
fdiv = 256 * (boff-aoff) / sc->soundChannels;
samp[i].left += (fdata[0] * fleftvol)/fdiv;
samp[i].right += (fdata[1] * frightvol)/fdiv;
fdiv = 256 * (boff-aoff);
samp[i].left += (fdata * fleftvol)/fdiv;
samp[i].right += (fdata * frightvol)/fdiv;
}
}
}
static void S_PaintChannelFrom16( channel_t *ch, const sfx_t *sc, int count, int sampleOffset, int bufferOffset ) {
#if idppc_altivec
if (com_altivec->integer) {
// must be in a separate translation unit or G3 systems will crash.
S_PaintChannelFrom16_altivec( paintbuffer, snd_vol, ch, sc, count, sampleOffset, bufferOffset );
return;
}
#endif
S_PaintChannelFrom16_scalar( ch, sc, count, sampleOffset, bufferOffset );
}
void S_PaintChannelFromWavelet( channel_t *ch, sfx_t *sc, int count, int sampleOffset, int bufferOffset ) {
int data;
int leftvol, rightvol;
@@ -383,7 +432,7 @@ void S_PaintChannelFromWavelet( channel_t *ch, sfx_t *sc, int count, int sampleO
}
if (i!=sfxScratchIndex || sfxScratchPointer != sc) {
decodeWavelet(chunk, sfxScratchBuffer);
S_AdpcmGetSamples( chunk, sfxScratchBuffer );
sfxScratchIndex = i;
sfxScratchPointer = sc;
}
@@ -480,7 +529,7 @@ void S_PaintChannelFromMuLaw( channel_t *ch, sfx_t *sc, int count, int sampleOff
samp[i].left += (data * leftvol)>>8;
samp[i].right += (data * rightvol)>>8;
samples++;
if (chunk != NULL && samples == (byte *)chunk->sndChunk+(SND_CHUNK_SIZE*2)) {
if (samples == (byte *)chunk->sndChunk+(SND_CHUNK_SIZE*2)) {
chunk = chunk->next;
samples = (byte *)chunk->sndChunk;
}
@@ -513,16 +562,13 @@ S_PaintChannels
void S_PaintChannels( int endtime ) {
int i;
int end;
int stream;
channel_t *ch;
sfx_t *sc;
int ltime, count;
int sampleOffset;
if(s_muted->integer)
snd_vol = 0;
else
snd_vol = s_volume->value*255;
snd_vol = s_volume->value*255;
//Com_Printf ("%i to %i\n", s_paintedtime, endtime);
while ( s_paintedtime < endtime ) {
@@ -533,24 +579,36 @@ void S_PaintChannels( int endtime ) {
end = s_paintedtime + PAINTBUFFER_SIZE;
}
// clear the paint buffer and mix any raw samples...
Com_Memset(paintbuffer, 0, sizeof (paintbuffer));
for (stream = 0; stream < MAX_RAW_STREAMS; stream++) {
if ( s_rawend[stream] >= s_paintedtime ) {
// copy from the streaming sound source
const portable_samplepair_t *rawsamples = s_rawsamples[stream];
const int stop = (end < s_rawend[stream]) ? end : s_rawend[stream];
for ( i = s_paintedtime ; i < stop ; i++ ) {
const int s = i&(MAX_RAW_SAMPLES-1);
paintbuffer[i-s_paintedtime].left += rawsamples[s].left;
paintbuffer[i-s_paintedtime].right += rawsamples[s].right;
}
// clear the paint buffer to either music or zeros
if ( s_rawend < s_paintedtime ) {
if ( s_rawend ) {
//Com_DPrintf ("background sound underrun\n");
}
Com_Memset(paintbuffer, 0, (end - s_paintedtime) * sizeof(portable_samplepair_t));
} else {
// copy from the streaming sound source
int s;
int stop;
stop = (end < s_rawend) ? end : s_rawend;
for ( i = s_paintedtime ; i < stop ; i++ ) {
s = i&(MAX_RAW_SAMPLES-1);
paintbuffer[i-s_paintedtime] = s_rawsamples[s];
}
// if (i != end)
// Com_Printf ("partial stream\n");
// else
// Com_Printf ("full stream\n");
for ( ; i < end ; i++ ) {
paintbuffer[i-s_paintedtime].left =
paintbuffer[i-s_paintedtime].right = 0;
}
}
// paint in the channels.
ch = s_channels;
for ( i = 0; i < MAX_SOUNDCHANNELS ; i++, ch++ ) {
for ( i = 0; i < MAX_CHANNELS ; i++, ch++ ) {
if ( !ch->thesfx || (ch->leftvol<0.25 && ch->rightvol<0.25 )) {
continue;
}
@@ -558,10 +616,6 @@ void S_PaintChannels( int endtime ) {
ltime = s_paintedtime;
sc = ch->thesfx;
if (sc->soundData==NULL || sc->soundLength==0) {
continue;
}
sampleOffset = ltime - ch->startSample;
count = end - ltime;
if ( sampleOffset + count > sc->soundLength ) {
File diff suppressed because it is too large. Load diff
+8 -18
View File
@@ -15,7 +15,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
@@ -38,8 +38,8 @@ void S_StopBackgroundTrack( void );
// cinematics and voice-over-network will send raw samples
// 1.0 volume will be direct output of source samples
void S_RawSamples(int stream, int samples, int rate, int width, int channels,
const byte *data, float volume, int entityNum);
void S_RawSamples (int samples, int rate, int width, int channels,
const byte *data, float volume);
// stop all sounds and the background track
void S_StopAllSounds(qboolean stop_music);
@@ -51,21 +51,20 @@ void S_AddLoopingSound(const vec3_t origin, const vec3_t velocity, sfxHandle_t s
void S_AddRealLoopingSound( int entityNum, const vec3_t origin, const vec3_t velocity, sfxHandle_t sfx );
void S_StopLoopingSound(int entityNum );
// recompute the relative volumes for all running sounds
// relative to the given entityNum / orientation
void S_Respatialize(int entityNum, const vec3_t origin, vec3_t axis[3], int inwater);
// recompute the reletive volumes for all running sounds
// reletive to the given entityNum / orientation
void S_Respatialize( int entityNum, const vec3_t origin, vec3_t axis[3], int inwater );
// let the sound system know where an entity currently is
void S_UpdateEntityPosition(int entityNum, const vec3_t origin);
void S_UpdateEntityPosition( int entityNum, const vec3_t origin );
void S_Update( void );
void S_DisableSounds( void );
void S_BeginRegistration(void);
void S_BeginRegistration( void );
void S_EndRegistration(void);
qboolean S_IsSoundRegistered(const char* name);
// RegisterSound will allways return a valid sample, even if it
// has to create a placeholder. This prevents continuous filesystem
// checks for missing files
@@ -110,15 +109,6 @@ void S_RespatializeOld(int entityNum, const vec3_t origin, vec3_t axis[3]);
void S_UpdateEntity(int entityNum, const vec3_t origin, const vec3_t velocity, qboolean use_listener);
void S_FadeSound(float fTime);
#ifdef USE_VOIP
void S_StartCapture( void );
int S_AvailableCaptureSamples( void );
void S_Capture( int samples, byte *data );
void S_StopCapture( void );
void S_MasterGain( float gain );
#endif
#ifdef __cplusplus
}
#endif
+18 -17
View File
@@ -15,13 +15,15 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Quake III Arena source code; if not, write to the Free Software
along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "snd_local.h"
long myftol( float f );
#define C0 0.4829629131445341
#define C1 0.8365163037378079
#define C2 0.2241438680420134
@@ -29,8 +31,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
void daub4(float b[], unsigned long n, int isign)
{
float wksp[4097] = { 0.0f };
#define a(x) b[(x)-1] // numerical recipies so a[1] = b[0]
float wksp[4097];
float *a=b-1; // numerical recipies so a[1] = b[0]
unsigned long nh,nh1,i,j;
@@ -39,23 +41,22 @@ void daub4(float b[], unsigned long n, int isign)
nh1=(nh=n >> 1)+1;
if (isign >= 0) {
for (i=1,j=1;j<=n-3;j+=2,i++) {
wksp[i] = C0*a(j)+C1*a(j+1)+C2*a(j+2)+C3*a(j+3);
wksp[i+nh] = C3*a(j)-C2*a(j+1)+C1*a(j+2)-C0*a(j+3);
wksp[i] = C0*a[j]+C1*a[j+1]+C2*a[j+2]+C3*a[j+3];
wksp[i+nh] = C3*a[j]-C2*a[j+1]+C1*a[j+2]-C0*a[j+3];
}
wksp[i ] = C0*a(n-1)+C1*a(n)+C2*a(1)+C3*a(2);
wksp[i+nh] = C3*a(n-1)-C2*a(n)+C1*a(1)-C0*a(2);
wksp[i ] = C0*a[n-1]+C1*a[n]+C2*a[1]+C3*a[2];
wksp[i+nh] = C3*a[n-1]-C2*a[n]+C1*a[1]-C0*a[2];
} else {
wksp[1] = C2*a(nh)+C1*a(n)+C0*a(1)+C3*a(nh1);
wksp[2] = C3*a(nh)-C0*a(n)+C1*a(1)-C2*a(nh1);
wksp[1] = C2*a[nh]+C1*a[n]+C0*a[1]+C3*a[nh1];
wksp[2] = C3*a[nh]-C0*a[n]+C1*a[1]-C2*a[nh1];
for (i=1,j=3;i<nh;i++) {
wksp[j++] = C2*a(i)+C1*a(i+nh)+C0*a(i+1)+C3*a(i+nh1);
wksp[j++] = C3*a(i)-C0*a(i+nh)+C1*a(i+1)-C2*a(i+nh1);
wksp[j++] = C2*a[i]+C1*a[i+nh]+C0*a[i+1]+C3*a[i+nh1];
wksp[j++] = C3*a[i]-C0*a[i+nh]+C1*a[i+1]-C2*a[i+nh1];
}
}
for (i=1;i<=n;i++) {
a(i)=wksp[i];
a[i]=wksp[i];
}
#undef a
}
void wt1(float a[], unsigned long n, int isign)
@@ -120,7 +121,7 @@ void NXPutc(NXStream *stream, char out) {
void encodeWavelet( sfx_t *sfx, short *packets) {
float wksp[4097] = {0}, temp;
float wksp[4097], temp;
int i, samples, size;
sndBuffer *newchunk, *chunk;
byte *out;
@@ -147,7 +148,7 @@ void encodeWavelet( sfx_t *sfx, short *packets) {
newchunk = SND_malloc();
if (sfx->soundData == NULL) {
sfx->soundData = newchunk;
} else if (chunk != NULL) {
} else {
chunk->next = newchunk;
}
chunk = newchunk;
@@ -170,7 +171,7 @@ void encodeWavelet( sfx_t *sfx, short *packets) {
}
void decodeWavelet(sndBuffer *chunk, short *to) {
float wksp[4097] = {0};
float wksp[4097];
int i;
byte *out;
@@ -216,7 +217,7 @@ void encodeMuLaw( sfx_t *sfx, short *packets) {
newchunk = SND_malloc();
if (sfx->soundData == NULL) {
sfx->soundData = newchunk;
} else if (chunk != NULL) {
} else {
chunk->next = newchunk;
}
chunk = newchunk;
+12 -12
View File
@@ -238,11 +238,11 @@ void BarrelObject::BarrelThink
if( m_iBarrelType == BARREL_OIL )
{
gi.MSG_StartCGM( 15 );
gi.MSG_StartCGM(CGM_MAKE_EFFECT_1);
}
else
{
gi.MSG_StartCGM( 19 );
gi.MSG_StartCGM(CGM_MAKE_EFFECT_5);
}
m_fFluidAmount -= 1.0f;
@@ -254,11 +254,11 @@ void BarrelObject::BarrelThink
if( m_iBarrelType == BARREL_OIL )
{
gi.MSG_StartCGM( 16 );
gi.MSG_StartCGM(CGM_MAKE_EFFECT_2);
}
else
{
gi.MSG_StartCGM( 20 );
gi.MSG_StartCGM(CGM_MAKE_EFFECT_6);
}
m_fFluidAmount -= 0.75f;
@@ -271,11 +271,11 @@ void BarrelObject::BarrelThink
if( m_iBarrelType == BARREL_OIL )
{
gi.MSG_StartCGM( 17 );
gi.MSG_StartCGM(CGM_MAKE_EFFECT_3);
}
else
{
gi.MSG_StartCGM( 21 );
gi.MSG_StartCGM(CGM_MAKE_EFFECT_7);
}
m_fFluidAmount -= 0.5f;
@@ -294,11 +294,11 @@ void BarrelObject::BarrelThink
if( m_iBarrelType == BARREL_OIL )
{
gi.MSG_StartCGM( 17 );
gi.MSG_StartCGM(CGM_MAKE_EFFECT_3);
}
else
{
gi.MSG_StartCGM( 21 );
gi.MSG_StartCGM(CGM_MAKE_EFFECT_7);
}
gi.MSG_WriteCoord( m_vLeaks[ i ][ 0 ] );
@@ -506,18 +506,18 @@ void BarrelObject::BarrelDamaged
gi.SetBroadcastVisible( vHitPos, vHitPos );
if( m_iBarrelType == BARREL_OIL )
gi.MSG_StartCGM( 18 );
gi.MSG_StartCGM(CGM_MAKE_EFFECT_4);
else
gi.MSG_StartCGM( 22 );
gi.MSG_StartCGM(CGM_MAKE_EFFECT_8);
}
else
{
gi.SetBroadcastVisible( vHitPos, vHitPos );
if( m_iBarrelType == BARREL_OIL )
gi.MSG_StartCGM( 17 );
gi.MSG_StartCGM(CGM_MAKE_EFFECT_3);
else
gi.MSG_StartCGM( 21 );
gi.MSG_StartCGM(CGM_MAKE_EFFECT_7);
}
gi.MSG_WriteCoord( vHitPos[ 0 ] );
-9
View File
@@ -25,15 +25,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "../qcommon/q_shared.h"
#include "bg_public.h"
/*
================
BG_EvaluateTrajectory
================
*/
void BG_EvaluateTrajectory( const trajectory_t *tr, int atTime, vec3_t result ) {
}
/*
================
BG_EvaluateTrajectoryDelta
+4 -4
View File
@@ -1423,7 +1423,7 @@ void PmoveSingle( pmove_t *pmove )
if( pm->ps->pm_type == PM_CLIMBWALL )
{
pm->ps->fLeanAngle = 0.0f;
pm->cmd.buttons &= ~( BUTTON_LEANLEFT | BUTTON_LEANRIGHT );
pm->cmd.buttons &= ~( BUTTON_LEAN_LEFT | BUTTON_LEAN_RIGHT );
}
// clear all pmove local vars
@@ -1447,10 +1447,10 @@ void PmoveSingle( pmove_t *pmove )
pml.frametime = pml.msec * 0.001;
if( ( pm->cmd.buttons & ( BUTTON_LEANLEFT | BUTTON_LEANRIGHT ) &&
( pm->cmd.buttons & ( BUTTON_LEANLEFT | BUTTON_LEANRIGHT ) ) != ( BUTTON_LEANLEFT | BUTTON_LEANRIGHT ) ) )
if( ( pm->cmd.buttons & ( BUTTON_LEAN_LEFT | BUTTON_LEAN_RIGHT ) &&
( pm->cmd.buttons & ( BUTTON_LEAN_LEFT | BUTTON_LEAN_RIGHT ) ) != ( BUTTON_LEAN_LEFT | BUTTON_LEAN_RIGHT ) ) )
{
if( pm->cmd.buttons & BUTTON_LEANLEFT )
if( pm->cmd.buttons & BUTTON_LEAN_LEFT )
{
if( pm->ps->fLeanAngle <= -40.0f )
{
+237 -9
View File
@@ -66,6 +66,34 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define CS_MOTD 4 // g_motd string for server message of the day
#define CS_WARMUP 5 // server time when the match will be restarted
#if TARGET_GAME_PROTOCOL >= 15
#define CS_MUSIC 6 // MUSIC_NewSoundtrack(cs)
#define CS_FOGINFO 7 // cg.farplane_cull cg.farplane_distance cg.farplane_color[3]
#define CS_SKYINFO 8 // cg.sky_alpha cg.sky_portal
#define CS_GAME_VERSION 9
#define CS_LEVEL_START_TIME 10 // so the timer only shows the current level cgs.levelStartTime
#define CS_CURRENT_OBJECTIVE 11
#define CS_RAIN_DENSITY 12 // cg.rain
#define CS_RAIN_SPEED 13
#define CS_RAIN_SPEEDVARY 14
#define CS_RAIN_SLANT 15
#define CS_RAIN_LENGTH 16
#define CS_RAIN_MINDIST 17
#define CS_RAIN_WIDTH 18
#define CS_RAIN_SHADER 19
#define CS_RAIN_NUMSHADERS 20
#define CS_VOTE_TIME 21
#define CS_VOTE_STRING 22
#define CS_VOTE_YES 23
#define CS_VOTE_NO 24
#define CS_VOTE_UNDECIDED 25
#else
#define CS_MUSIC 8 // MUSIC_NewSoundtrack(cs)
#define CS_FOGINFO 9 // cg.farplane_cull cg.farplane_distance cg.farplane_color[3]
#define CS_SKYINFO 10 // cg.sky_alpha cg.sky_portal
@@ -85,6 +113,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define CS_RAIN_SHADER 21
#define CS_RAIN_NUMSHADERS 22
#endif
#define CS_MATCHEND 26 // cgs.matchEndTime
#define CS_MODELS 32
@@ -98,11 +128,11 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define CS_PLAYERS (CS_LIGHTSTYLES+MAX_LIGHTSTYLES) // 1684
#define CS_WEAPONS (CS_PLAYERS+MAX_CLIENTS) // su44 was here
#define CS_TEAMS 1876
#define CS_GENERAL_STRINGS 1877
#define CS_SPECTATORS 1878
#define CS_ALLIES 1879
#define CS_AXIS 1880
#define CS_TEAMS 1892
#define CS_GENERAL_STRINGS 1893
#define CS_SPECTATORS 1894
#define CS_ALLIES 1895
#define CS_AXIS 1896
#define CS_SOUNDTRACK 1881
#define CS_TEAMINFO 1
@@ -122,6 +152,10 @@ typedef enum {
GT_TEAM, // team deathmatch
GT_TEAM_ROUNDS,
GT_OBJECTIVE,
// Team Assault game mode
GT_TOW,
// Team Tactics game mode
GT_LIBERATION,
GT_MAX_GAME_TYPE
} gametype_t;
@@ -231,6 +265,28 @@ typedef enum {
#define PMF_LEVELEXIT (1<<20) // use camera view instead of ps view
#endif
#if TARGET_GAME_PROTOCOL >= 15
// moh pm_flags
#define PMF_DUCKED (1<<0)
#define PMF_VIEW_PRONE (1<<1)
#define PMF_SPECTATING (1<<2)
#define PMF_RESPAWNED (1<<3)
#define PMF_NO_PREDICTION (1<<4)
#define PMF_FROZEN (1<<5)
#define PMF_INTERMISSION (1<<6)
#define PMF_SPECTATE_FOLLOW (1<<7)
#define PMF_CAMERA_VIEW (1<<7) // use camera view instead of ps view
#define PMF_NO_MOVE (1<<8)
#define PMF_VIEW_DUCK_RUN (1<<9)
#define PMF_VIEW_JUMP_START (1<<10)
#define PMF_LEVELEXIT (1<<11)
#define PMF_NO_GRAVITY (1<<12)
#define PMF_NO_HUD (1<<13)
#define PMF_UNKNOWN (1<<14)
#else
// moh pm_flags
#define PMF_DUCKED (1<<0)
#define PMF_VIEW_PRONE (1<<1)
@@ -249,6 +305,8 @@ typedef enum {
#define PMF_NO_HUD (1<<15)
#define PMF_UNKNOWN (1<<16)
#endif
// moveposflags
#define MPF_POSITION_STANDING (1<<0)
#define MPF_POSITION_CROUCHING (1<<1)
@@ -395,6 +453,12 @@ typedef enum {
#define EF_AXIS 0x00000100 // su44: this player is in axis team
#define EF_ANY_TEAM (EF_ALLIES | EF_AXIS)
#define EF_DEAD 0x00000200 // don't draw a foe marker over players with EF_DEAD
//
// Team assault flags
//
#define EF_PLAYER_IN_MENU 0x00000400 // Player is in menu
#define EF_PLAYER_TALKING 0x00000800 // Player is talking
#define EF_PLAYER_ARTILLERY 0x00002000 // Player is using an artillery
// su44: q3 remnants
@@ -528,6 +592,15 @@ extern const char *means_of_death_strings[];
#define DF_NO_DROP_WEAPONS (1<<16)
#define DF_NO_FOOTSTEPS (1<<17)
#define DF_WEAPON_LANDMINE_ALWAYS (1<<21)
#define DF_WEAPON_NO_RIFLE (1<<22)
#define DF_WEAPON_NO_SNIPER (1<<23)
#define DF_WEAPON_NO_SMG (1<<24)
#define DF_WEAPON_NO_MG (1<<25)
#define DF_WEAPON_NO_ROCKET (1<<26)
#define DF_WEAPON_NO_SHOTGUN (1<<27)
#define DF_WEAPON_NO_LANDMINE (1<<28)
#define DM_FLAG( flag ) ( g_gametype->integer && ( ( int )dmflags->integer & ( flag ) ) )
// content masks
@@ -609,13 +682,168 @@ typedef enum {
ET_EXEC_COMMANDS
} entityType_t;
// su44; yes, I know there is no q3 trajectory_t in MoHAA,
// but I need it for fgame rotating doors code.
void BG_EvaluateTrajectory( const trajectory_t *tr, int atTime, vec3_t result );
void BG_EvaluateTrajectoryDelta( const trajectory_t *tr, int atTime, vec3_t result );
void BG_PlayerStateToEntityState( playerState_t *ps, entityState_t *s, qboolean snap );
void BG_PlayerStateToEntityStateExtraPolate( playerState_t *ps, entityState_t *s, int time, qboolean snap );
void BG_PlayerStateToEntityStateExtraPolate(playerState_t* ps, entityState_t* s, int time, qboolean snap);
#if TARGET_GAME_PROTOCOL >= 15
enum vmAnim_e {
VM_ANIM_DISABLED,
VM_ANIM_IDLE,
VM_ANIM_CHARGE,
VM_ANIM_FIRE,
VM_ANIM_FIRE_SECONDARY,
VM_ANIM_RECHAMBER,
VM_ANIM_RELOAD,
VM_ANIM_RELOAD_SINGLE,
VM_ANIM_RELOAD_END,
VM_ANIM_PULLOUT,
VM_ANIM_PUTAWAY,
VM_ANIM_LADDERSTEP,
VM_ANIM_IDLE_0,
VM_ANIM_IDLE_1,
VM_ANIM_IDLE_2,
};
enum cg_message_e {
CGM_NONE,
CGM_BULLET_1,
CGM_BULLET_2,
CGM_BULLET_3,
CGM_BULLET_4,
CGM_BULLET_5,
CGM_BULLET_6,
CGM_BULLET_7,
CGM_BULLET_8,
CGM_BULLET_9,
CGM_BULLET_10,
CGM_BULLET_11,
CGM_MELEE_IMPACT,
CGM_EXPLOSION_EFFECT_1,
CGM_EXPLOSION_EFFECT_2,
CGM_EXPLOSION_EFFECT_3,
CGM_EXPLOSION_EFFECT_4,
CGM_PADDING_1,
CGM_MAKE_EFFECT_1,
CGM_MAKE_EFFECT_2,
CGM_MAKE_EFFECT_3,
CGM_MAKE_EFFECT_4,
CGM_MAKE_EFFECT_5,
CGM_MAKE_EFFECT_6,
CGM_MAKE_EFFECT_7,
CGM_MAKE_EFFECT_8,
CGM_MAKE_CRATE_DEBRIS,
CGM_MAKE_WINDOW_DEBRIS,
CGM_BULLET_NO_BARREL_1,
CGM_BULLET_NO_BARREL_2,
CGM_HUDDRAW_SHADER,
CGM_HUDDRAW_ALIGN,
CGM_HUDDRAW_RECT,
CGM_HUDDRAW_VIRTUALSIZE,
CGM_HUDDRAW_COLOR,
CGM_HUDDRAW_ALPHA,
CGM_HUDDRAW_STRING,
CGM_HUDDRAW_FONT,
CGM_NOTIFY_KILL,
CGM_NOTIFY_HIT,
CGM_VOICE_CHAT,
CGM_UNKNOWN_1,
};
#else
enum vmAnim_e {
VM_ANIM_IDLE,
VM_ANIM_CHARGE,
VM_ANIM_FIRE,
VM_ANIM_FIRE_SECONDARY,
VM_ANIM_RECHAMBER,
VM_ANIM_RELOAD,
VM_ANIM_RELOAD_SINGLE,
VM_ANIM_RELOAD_END,
VM_ANIM_PULLOUT,
VM_ANIM_PUTAWAY,
VM_ANIM_LADDERSTEP,
VM_ANIM_IDLE_0,
VM_ANIM_IDLE_1,
VM_ANIM_IDLE_2,
VM_ANIM_DISABLED,
};
enum cg_message_e {
CGM_NONE,
CGM_BULLET_1,
CGM_BULLET_2,
CGM_BULLET_3,
CGM_BULLET_4,
CGM_BULLET_5,
CGM_BULLET_6,
CGM_BULLET_7,
CGM_BULLET_8,
CGM_BULLET_9,
CGM_BULLET_10,
CGM_MELEE_IMPACT,
CGM_EXPLOSION_EFFECT_1,
CGM_EXPLOSION_EFFECT_2,
CGM_PADDING_1,
CGM_MAKE_EFFECT_1,
CGM_MAKE_EFFECT_2,
CGM_MAKE_EFFECT_3,
CGM_MAKE_EFFECT_4,
CGM_MAKE_EFFECT_5,
CGM_MAKE_EFFECT_6,
CGM_MAKE_EFFECT_7,
CGM_MAKE_EFFECT_8,
CGM_MAKE_CRATE_DEBRIS,
CGM_MAKE_WINDOW_DEBRIS,
CGM_BULLET_NO_BARREL_1,
CGM_BULLET_NO_BARREL_2,
CGM_HUDDRAW_SHADER,
CGM_HUDDRAW_ALIGN,
CGM_HUDDRAW_RECT,
CGM_HUDDRAW_VIRTUALSIZE,
CGM_HUDDRAW_COLOR,
CGM_HUDDRAW_ALPHA,
CGM_HUDDRAW_STRING,
CGM_HUDDRAW_FONT,
CGM_NOTIFY_KILL,
CGM_NOTIFY_HIT,
CGM_VOICE_CHAT,
};
#endif
/*
#define CGM_HUDDRAW_SHADER 27
#define CGM_HUDDRAW_ALIGN 28
#define CGM_HUDDRAW_RECT 29
#define CGM_HUDDRAW_VIRTUALSIZE 30
#define CGM_HUDDRAW_COLOR 31
#define CGM_HUDDRAW_ALPHA 32
#define CGM_HUDDRAW_STRING 33
#define CGM_HUDDRAW_FONT 34
#define CGM_HUDDRAW_TIMER 38
#define CGM_HUDDRAW_3D 39
#define CGM_HUDDRAW_BREAK3D 40
#define CGM_HUDDRAW_FADE 41
#define CGM_HUDDRAW_MOVE 42
#define CGM_HUDDRAW_SCALE 43
#define CGM_VIEWMODELANIM 44
#define CGM_VIEWMODELPREFIX 45
#define CGM_MODHEIGHTFLOAT 46
#define CGM_SETVMASPEED 47
#define CGM_HINTSTRING 48
#define CGM_PLAYLOCALSOUND 49
#define CGM_SETLOCALSOUNDRATE 50
#define CGM_STOPLOCALSOUND 51
#define CGM_HUDDRAW_RECTX 52
#define CGM_HUDDRAW_RECTY 53
#define CGM_HUDDRAW_RECTWH 54
#define CGM_REPLICATION 55
#define CGM_HUDDRAW_DELETE 56
*/
#ifdef __cplusplus
}
+1 -1
View File
@@ -422,7 +422,7 @@ void State::ParseAndProcessCommand
{
int argc;
const char *argv[ MAX_COMMANDS ];
char args[ MAX_COMMANDS ][ MAXTOKEN ];
char args[ MAX_COMMANDS ][ SCRIPT_MAXTOKEN ];
Script script;
Event *event;
+1 -1
View File
@@ -465,7 +465,7 @@ void CrateObject::CrateKilled
// Tell clients around that a crate is destroyed
gi.SetBroadcastVisible( origin, origin );
gi.MSG_StartCGM( 23 );
gi.MSG_StartCGM(CGM_MAKE_CRATE_DEBRIS);
gi.MSG_WriteCoord( vCenter[ 0 ] );
gi.MSG_WriteCoord( vCenter[ 1 ] );
gi.MSG_WriteCoord( vCenter[ 2 ] );
+3
View File
@@ -6912,12 +6912,15 @@ void Entity::ProcessHint(gentity_t* client, bool bShow)
{
if (sv_reborn->integer)
{
// FIXME: delete
/*
gi.MSG_SetClient(client - g_entities);
// Send the hint string once
gi.MSG_StartCGM(CGM_HINTSTRING);
gi.MSG_WriteString(m_HintString);
gi.MSG_EndCGM();
*/
}
}
else
+1 -1
View File
@@ -241,7 +241,7 @@ typedef struct gameImport_s
void ( *AddCommand )( const char *cmdName, xcommand_t cmdFunction );
int ( *FS_ReadFile )( const char *qpath, void **buffer, qboolean quiet );
void ( *FS_FreeFile )( void *buffer );
size_t( *FS_WriteFile )( const char *qpath, const void *buffer, size_t size );
int ( *FS_WriteFile )( const char *qpath, const void *buffer, int size );
fileHandle_t ( *FS_FOpenFileWrite )( const char *fileName );
fileHandle_t ( *FS_FOpenFileAppend )( const char *fileName );
const char *( *FS_PrepFileWrite )( const char *fileName );
+50 -64
View File
@@ -503,6 +503,7 @@ Hud::~Hud()
SetNon3D();
}
/*
#ifdef GAME_DLL
SetBroadcast();
@@ -510,6 +511,7 @@ Hud::~Hud()
WriteNumber();
gi.MSG_EndCGM();
#endif
*/
hudElements.RemoveObject( this );
}
@@ -952,7 +954,9 @@ void Hud::FadeOverTime( float time )
fade_alpha_start = alpha;
fade_alpha_target = alpha;
// FIXME: delete
/*
#ifdef GAME_DLL
SetBroadcast();
@@ -961,6 +965,7 @@ void Hud::FadeOverTime( float time )
gi.MSG_WriteFloat( time );
gi.MSG_EndCGM();
#endif
*/
}
void Hud::MoveOverTime( float time )
@@ -982,6 +987,7 @@ void Hud::MoveOverTime( float time )
fade_move_x_target = x;
fade_move_y_target = y;
/*
#ifdef GAME_DLL
SetBroadcast();
@@ -990,6 +996,7 @@ void Hud::MoveOverTime( float time )
gi.MSG_WriteFloat( time );
gi.MSG_EndCGM();
#endif
*/
}
void Hud::Refresh( int clientNumber )
@@ -1092,6 +1099,7 @@ void Hud::Refresh( int clientNumber )
{
SetBroadcast();
/*
gi.MSG_StartCGM( CGM_HUDDRAW_3D );
WriteNumber();
gi.MSG_WriteCoord( org[ 0 ] );
@@ -1103,16 +1111,19 @@ void Hud::Refresh( int clientNumber )
gi.MSG_WriteBits( !!always_show, 1 );
gi.MSG_WriteBits( !!depth, 1 );
gi.MSG_EndCGM();
*/
}
if( fade_alpha )
{
SetBroadcast();
/*
gi.MSG_StartCGM( CGM_HUDDRAW_FADE );
WriteNumber();
gi.MSG_WriteFloat( fade_alpha_current );
gi.MSG_EndCGM();
*/
SetBroadcast();
@@ -1126,6 +1137,7 @@ void Hud::Refresh( int clientNumber )
{
SetBroadcast();
/*
gi.MSG_StartCGM( CGM_HUDDRAW_MOVE );
WriteNumber();
gi.MSG_WriteFloat( fade_move_current );
@@ -1138,10 +1150,12 @@ void Hud::Refresh( int clientNumber )
gi.MSG_WriteShort( ( short )fade_move_x_target );
gi.MSG_WriteShort( ( short )fade_move_y_target );
gi.MSG_EndCGM();
*/
}
if( fade_timer_flags & TIMER_ACTIVE )
{
/*
SetBroadcast();
gi.MSG_StartCGM( CGM_HUDDRAW_TIMER );
@@ -1156,6 +1170,7 @@ void Hud::Refresh( int clientNumber )
}
gi.MSG_EndCGM();
*/
}
}
#endif
@@ -1182,7 +1197,8 @@ void Hud::ScaleOverTime( float time, short w, short h )
fade_scale_w_target = w;
fade_scale_h_target = h;
#ifdef GAME_DLL
// FIXME: delete
/*
width = w;
height = h;
@@ -1194,7 +1210,7 @@ void Hud::ScaleOverTime( float time, short w, short h )
gi.MSG_WriteShort( w );
gi.MSG_WriteShort( h );
gi.MSG_EndCGM();
#endif
*/
}
#ifdef GAME_DLL
@@ -1235,6 +1251,7 @@ void Hud::Set3D( Vector vector_or_offset, qboolean alwaysOnScreen, qboolean hasD
isDimensional = true;
/*
#ifdef GAME_DLL
SetBroadcast();
@@ -1250,19 +1267,20 @@ void Hud::Set3D( Vector vector_or_offset, qboolean alwaysOnScreen, qboolean hasD
gi.MSG_WriteBits( !!hasDepth, 1 );
gi.MSG_EndCGM();
#endif
*/
}
void Hud::SetNon3D()
{
isDimensional = false;
#ifdef GAME_DLL
// FIXME?
/*
SetBroadcast();
gi.MSG_StartCGM( CGM_HUDDRAW_BREAK3D );
WriteNumber();
gi.MSG_EndCGM();
#endif
*/
}
void Hud::SetAlignX( hudAlign_t align )
@@ -1418,29 +1436,18 @@ void Hud::SetRectX( short value )
#ifdef GAME_DLL
SetBroadcast();
if( sv_reborn->integer )
{
gi.MSG_StartCGM( CGM_HUDDRAW_RECTX );
WriteNumber();
gi.MSG_WriteShort( ( short )value );
gi.MSG_EndCGM();
}
else
{
gi.MSG_StartCGM( CGM_HUDDRAW_RECT );
WriteNumber();
gi.MSG_WriteShort( ( short )fade_move_x_target );
gi.MSG_WriteShort( ( short )fade_move_y_target );
gi.MSG_WriteShort( ( short )width );
gi.MSG_WriteShort( ( short )height );
gi.MSG_EndCGM();
}
gi.MSG_StartCGM(CGM_HUDDRAW_RECT);
WriteNumber();
gi.MSG_WriteShort((short)fade_move_x_target);
gi.MSG_WriteShort((short)fade_move_y_target);
gi.MSG_WriteShort((short)width);
gi.MSG_WriteShort((short)height);
gi.MSG_EndCGM();
#endif
}
void Hud::SetRectY( short value )
{
//#ifdef CGAME_DLL
if( fade_move_y_first )
{
fade_move_y_target = value;
@@ -1451,30 +1458,17 @@ void Hud::SetRectY( short value )
y = value;
fade_move = false;
}
//#else
// y = value;
//#endif
#ifdef GAME_DLL
SetBroadcast();
if( sv_reborn->integer )
{
gi.MSG_StartCGM( CGM_HUDDRAW_RECTY );
WriteNumber();
gi.MSG_WriteShort( ( short )value );
gi.MSG_EndCGM();
}
else
{
gi.MSG_StartCGM( CGM_HUDDRAW_RECT );
WriteNumber();
gi.MSG_WriteShort( ( short )fade_move_x_target );
gi.MSG_WriteShort( ( short )fade_move_y_target );
gi.MSG_WriteShort( ( short )width );
gi.MSG_WriteShort( ( short )height );
gi.MSG_EndCGM();
}
gi.MSG_StartCGM(CGM_HUDDRAW_RECT);
WriteNumber();
gi.MSG_WriteShort((short)fade_move_x_target);
gi.MSG_WriteShort((short)fade_move_y_target);
gi.MSG_WriteShort((short)width);
gi.MSG_WriteShort((short)height);
gi.MSG_EndCGM();
#endif
}
@@ -1519,24 +1513,13 @@ void Hud::SetShader( const char * s, float w, float h )
#ifdef GAME_DLL
SetBroadcast();
if( sv_reborn->integer )
{
gi.MSG_StartCGM( CGM_HUDDRAW_RECTWH );
WriteNumber();
gi.MSG_WriteShort( ( short )width );
gi.MSG_WriteShort( ( short )height );
gi.MSG_EndCGM();
}
else
{
gi.MSG_StartCGM( CGM_HUDDRAW_RECT );
WriteNumber();
gi.MSG_WriteShort( ( short )x );
gi.MSG_WriteShort( ( short )y );
gi.MSG_WriteShort( ( short )width );
gi.MSG_WriteShort( ( short )height );
gi.MSG_EndCGM();
}
gi.MSG_StartCGM(CGM_HUDDRAW_RECT);
WriteNumber();
gi.MSG_WriteShort((short)x);
gi.MSG_WriteShort((short)y);
gi.MSG_WriteShort((short)width);
gi.MSG_WriteShort((short)height);
gi.MSG_EndCGM();
SetBroadcast();
@@ -1586,7 +1569,8 @@ void Hud::SetTimer( float time, float fade_at_time )
fade_timer_flags = TIMER_ACTIVE;
#ifdef GAME_DLL
// FIXME...
/*
SetBroadcast();
gi.MSG_StartCGM( CGM_HUDDRAW_TIMER );
@@ -1595,7 +1579,7 @@ void Hud::SetTimer( float time, float fade_at_time )
gi.MSG_WriteFloat( fade_at_time );
gi.MSG_WriteBits( 0, 1 );
gi.MSG_EndCGM();
#endif
*/
}
void Hud::SetTimerUp( float time, float fade_at_time )
@@ -1612,6 +1596,7 @@ void Hud::SetTimerUp( float time, float fade_at_time )
fade_timer_flags = TIMER_ACTIVE | TIMER_UP;
/*
#ifdef GAME_DLL
SetBroadcast();
@@ -1622,6 +1607,7 @@ void Hud::SetTimerUp( float time, float fade_at_time )
gi.MSG_WriteBits( 1, 1 );
gi.MSG_EndCGM();
#endif
*/
}
void Hud::SetVirtualSize( qboolean v )
+25 -16
View File
@@ -38,7 +38,7 @@ void HudWriteNumber( int num )
void HudDrawShader( int info, const char *name )
{
gi.SetBroadcastAll();
gi.MSG_StartCGM(0x1B);
gi.MSG_StartCGM(CGM_HUDDRAW_SHADER);
HudWriteNumber( info ); // c = info
gi.MSG_WriteString(name); // s = name (shader_name)
gi.MSG_EndCGM();
@@ -47,7 +47,7 @@ void HudDrawShader( int info, const char *name )
void HudDrawAlign( int info, int horizontalAlign, int verticalAlign )
{
gi.SetBroadcastAll();
gi.MSG_StartCGM(0x1C);
gi.MSG_StartCGM(CGM_HUDDRAW_ALIGN);
HudWriteNumber( info ); // c = probably "info"
gi.MSG_WriteBits(horizontalAlign, 2); // value = 0,1,2 bits = 2
// 0 - left \
@@ -66,7 +66,7 @@ void HudDrawAlign( int info, int horizontalAlign, int verticalAlign )
void HudDrawRect(int info, int x, int y, int width, int height)
{
gi.SetBroadcastAll();
gi.MSG_StartCGM(0x1D);
gi.MSG_StartCGM(CGM_HUDDRAW_RECT);
HudWriteNumber( info ); // c = probably "info"
gi.MSG_WriteShort(x); // c = probably "x"
gi.MSG_WriteShort(y); // c = probably "y"
@@ -79,7 +79,7 @@ void HudDrawRect(int info, int x, int y, int width, int height)
void HudDrawVirtualSize(int info, int virtualScreen)
{
gi.SetBroadcastAll();
gi.MSG_StartCGM(0x1E);
gi.MSG_StartCGM(CGM_HUDDRAW_VIRTUALSIZE);
HudWriteNumber( info ); // c = info
/*__asm
@@ -116,7 +116,7 @@ void HudDrawColor(int info, float *color)
gi.SetBroadcastAll();
gi.MSG_StartCGM(0x1F);
gi.MSG_StartCGM(CGM_HUDDRAW_COLOR);
HudWriteNumber( info ); // c = info
gi.MSG_WriteByte(temp[0]); // c = color[2]
gi.MSG_WriteByte(temp[1]); // c = color[1] - Values can be messed up. To be tested.
@@ -132,7 +132,7 @@ void HudDrawAlpha(int info, float alpha)
temp = (long int)(alpha*255.0f);
gi.SetBroadcastAll();
gi.MSG_StartCGM(0x20);
gi.MSG_StartCGM(CGM_HUDDRAW_ALPHA);
HudWriteNumber( info ); // c = info
gi.MSG_WriteByte(temp); // c = alpha
gi.MSG_EndCGM();
@@ -144,7 +144,7 @@ void HudDrawAlpha(int info, float alpha)
void HudDrawString(int info, const char *string)
{
gi.SetBroadcastAll();
gi.MSG_StartCGM(0x21);
gi.MSG_StartCGM(CGM_HUDDRAW_STRING);
HudWriteNumber( info ); // c = info
gi.MSG_WriteString(string); // s = string (to show)
gi.MSG_EndCGM();
@@ -154,7 +154,7 @@ void HudDrawString(int info, const char *string)
void HudDrawFont(int info, const char *fontName)
{
gi.SetBroadcastAll();
gi.MSG_StartCGM(0x22);
gi.MSG_StartCGM(CGM_HUDDRAW_FONT);
HudWriteNumber( info ); // c = info
gi.MSG_WriteString(fontName); // s = fontName (to use)
gi.MSG_EndCGM();
@@ -163,6 +163,8 @@ void HudDrawFont(int info, const char *fontName)
void HudDraw3d( int index, vec3_t vector, int ent_num, qboolean bAlwaysShow, qboolean depth )
{
// FIXME...
/*
gi.SetBroadcastAll();
gi.MSG_StartCGM( CGM_HUDDRAW_3D );
@@ -176,10 +178,12 @@ void HudDraw3d( int index, vec3_t vector, int ent_num, qboolean bAlwaysShow, qbo
gi.MSG_WriteByte( bAlwaysShow );
gi.MSG_WriteByte( depth );
gi.MSG_EndCGM();
*/
}
void HudDrawTimer( int index, float duration, float fade_out_time )
{
/*
gi.SetBroadcastAll();
gi.MSG_StartCGM( CGM_HUDDRAW_TIMER );
@@ -187,12 +191,13 @@ void HudDrawTimer( int index, float duration, float fade_out_time )
gi.MSG_WriteFloat( duration );
gi.MSG_WriteFloat( fade_out_time );
gi.MSG_EndCGM();
*/
}
void iHudDrawShader( int cl_num, int info, const char *name )
{
gi.MSG_SetClient(cl_num);
gi.MSG_StartCGM(0x1B);
gi.MSG_StartCGM(CGM_HUDDRAW_SHADER);
HudWriteNumber( info ); // c = info
gi.MSG_WriteString(name); // s = name (shader_name)
gi.MSG_EndCGM();
@@ -202,7 +207,7 @@ void iHudDrawShader( int cl_num, int info, const char *name )
void iHudDrawAlign(int cl_num, int info, int horizontalAlign, int verticalAlign )
{
gi.MSG_SetClient(cl_num);
gi.MSG_StartCGM(0x1C);
gi.MSG_StartCGM(CGM_HUDDRAW_ALIGN);
HudWriteNumber( info ); // c = probably "info"
gi.MSG_WriteBits(horizontalAlign, 2); // value = 0,1,2 bits = 2
// 0 - left \
@@ -221,7 +226,7 @@ void iHudDrawAlign(int cl_num, int info, int horizontalAlign, int verticalAlign
void iHudDrawRect(int cl_num, int info, int x, int y, int width, int height)
{
gi.MSG_SetClient(cl_num);
gi.MSG_StartCGM(0x1D);
gi.MSG_StartCGM(CGM_HUDDRAW_RECT);
HudWriteNumber( info ); // c = probably "info"
gi.MSG_WriteShort(x); // c = probably "x"
gi.MSG_WriteShort(y); // c = probably "y"
@@ -232,6 +237,7 @@ void iHudDrawRect(int cl_num, int info, int x, int y, int width, int height)
void iHudDraw3d( int cl_num, int index, vec3_t vector, int ent_num, qboolean bAlwaysShow, qboolean depth )
{
/*
gi.MSG_SetClient( cl_num );
gi.MSG_StartCGM( CGM_HUDDRAW_3D );
@@ -245,10 +251,12 @@ void iHudDraw3d( int cl_num, int index, vec3_t vector, int ent_num, qboolean bAl
gi.MSG_WriteByte( bAlwaysShow );
gi.MSG_WriteByte( depth );
gi.MSG_EndCGM();
*/
}
void iHudDrawTimer( int cl_num, int index, float duration, float fade_out_time )
{
/*
gi.MSG_SetClient( cl_num );
gi.MSG_StartCGM( CGM_HUDDRAW_TIMER );
@@ -256,12 +264,13 @@ void iHudDrawTimer( int cl_num, int index, float duration, float fade_out_time )
gi.MSG_WriteFloat( duration );
gi.MSG_WriteFloat( fade_out_time );
gi.MSG_EndCGM();
*/
}
void iHudDrawVirtualSize(int cl_num, int info, int virtualScreen)
{
gi.MSG_SetClient(cl_num);
gi.MSG_StartCGM(0x1E);
gi.MSG_StartCGM(CGM_HUDDRAW_VIRTUALSIZE);
HudWriteNumber( info ); // c = info
gi.MSG_WriteBits(!!virtualScreen, 1); // value = ? bits = 1
@@ -285,7 +294,7 @@ void iHudDrawColor(int cl_num, int info, float *color)
temp[2] = (long int)(color[2]*255.0f);
gi.MSG_SetClient(cl_num);
gi.MSG_StartCGM(0x1F);
gi.MSG_StartCGM(CGM_HUDDRAW_COLOR);
HudWriteNumber( info ); // c = info
gi.MSG_WriteByte(temp[0]); // c = color[2]
gi.MSG_WriteByte(temp[1]); // c = color[1] - Values can be messed up. To be tested.
@@ -301,7 +310,7 @@ void iHudDrawAlpha(int cl_num, int info, float alpha)
temp = (long int)(alpha*255.0f);
gi.MSG_SetClient(cl_num);
gi.MSG_StartCGM(0x20);
gi.MSG_StartCGM(CGM_HUDDRAW_ALPHA);
HudWriteNumber( info ); // c = info
gi.MSG_WriteByte(temp); // c = alpha
gi.MSG_EndCGM();
@@ -313,7 +322,7 @@ void iHudDrawAlpha(int cl_num, int info, float alpha)
void iHudDrawString( int cl_num, int info, const char *string )
{
gi.MSG_SetClient(cl_num);
gi.MSG_StartCGM(0x21);
gi.MSG_StartCGM(CGM_HUDDRAW_STRING);
HudWriteNumber( info ); // c = info
gi.MSG_WriteString(string); // s = string (to show)
gi.MSG_EndCGM();
@@ -323,7 +332,7 @@ void iHudDrawString( int cl_num, int info, const char *string )
void iHudDrawFont( int cl_num, int info, const char *fontName )
{
gi.MSG_SetClient(cl_num);
gi.MSG_StartCGM(0x22);
gi.MSG_StartCGM(CGM_HUDDRAW_FONT);
HudWriteNumber( info ); // c = info
gi.MSG_WriteString(fontName); // s = fontName (to use)
gi.MSG_EndCGM();
+3
View File
@@ -1149,6 +1149,8 @@ void Item::updatePrefix
return;
}
// FIXME: delete
/*
Entity *ent = ev->GetEntity( 1 );
gi.MSG_SetClient( ent->edict - g_entities );
@@ -1157,6 +1159,7 @@ void Item::updatePrefix
gi.MSG_WriteString( item_name.c_str() );
gi.MSG_WriteString( m_sVMprefix.c_str() );
gi.MSG_EndCGM();
*/
}
qboolean Item::IsItemCool
+102 -83
View File
@@ -1907,11 +1907,11 @@ qboolean Player::checkattackleft
return false;
}
if( last_ucmd.buttons & BUTTON_ATTACK )
if( last_ucmd.buttons & BUTTON_ATTACKLEFT )
{
Weapon *weapon;
last_attack_button = BUTTON_ATTACK;
last_attack_button = BUTTON_ATTACKLEFT;
weapon = GetActiveWeapon( WEAPON_MAIN );
if( weapon )
@@ -1939,7 +1939,7 @@ qboolean Player::checkattackbuttonleft
return false;
}
return ( last_ucmd.buttons & BUTTON_ATTACK );
return ( last_ucmd.buttons & BUTTON_ATTACKLEFT );
}
@@ -1954,11 +1954,11 @@ qboolean Player::checkattackright
return false;
}
if( last_ucmd.buttons & BUTTON_ATTACK2 )
if( last_ucmd.buttons & BUTTON_ATTACKRIGHT )
{
Weapon *weapon;
last_attack_button = BUTTON_ATTACK2;
last_attack_button = BUTTON_ATTACKRIGHT;
weapon = GetActiveWeapon( WEAPON_MAIN );
if( weapon )
@@ -1986,7 +1986,7 @@ qboolean Player::checkattackbuttonright
return false;
}
return ( last_ucmd.buttons & BUTTON_ATTACK2 );
return ( last_ucmd.buttons & BUTTON_ATTACKRIGHT );
}
qboolean Player::checksneak
@@ -2007,15 +2007,6 @@ qboolean Player::checkrun
return ( last_ucmd.buttons & BUTTON_RUN ) != 0;
}
qboolean Player::checkholsterweapon
(
Conditional &condition
)
{
return ( last_ucmd.buttons & BUTTON_HOLSTER ) != 0;
}
qboolean Player::checkuse
(
Conditional &condition
@@ -3666,6 +3657,49 @@ qboolean Player::checkimmediateswitch( Conditional &condition )
return ( g_gametype->integer && g_immediateswitch->integer );
}
qboolean Player::checkmovementspeed(Conditional& condition)
{
int speed = atoi(condition.getParm(1));
return client->ps.speed >= speed;
}
qboolean Player::checkabletodefuse(Conditional& condition)
{
// FIXME: unimplemented
return true;
}
qboolean Player::checkonlandmine(Conditional& condition)
{
// FIXME: unimplemented
return false;
}
qboolean Player::checknearlandmine(Conditional& condition)
{
// FIXME: unimplemented
return false;
}
qboolean Player::CondCanPlaceLandmine(Conditional& condition)
{
// FIXME: unimplemented
return false;
}
qboolean Player::CondWeaponCurrentFireAnim(Conditional& condition)
{
// FIXME: unimplemented
return false;
}
qboolean Player::CondVehicleType(Conditional& condition)
{
// FIXME: unimplemented
return false;
}
qboolean Player::CondAnimDoneVM( Conditional &condition )
{
return animDoneVM;
@@ -3921,7 +3955,6 @@ Condition<Player> Player::Conditions[] =
{ "default", &Player::returntrue },
{ "SNEAK", &Player::checksneak },
{ "RUN", &Player::checkrun },
{ "HOLSTERWEAPON", &Player::checkholsterweapon },
{ "USE", &Player::checkuse },
{ "LEFT", &Player::checkturnleft },
{ "RIGHT", &Player::checkturnright },
@@ -4024,6 +4057,13 @@ Condition<Player> Player::Conditions[] =
{ "MIN_CHARGE_TIME_MET", &Player::checkminchargetimemet },
{ "MAX_CHARGE_TIME_MET", &Player::checkmaxchargetimemet },
{ "IMMEDIATE_SWITCH", &Player::checkimmediateswitch },
{ "CHECK_MOVEMENT_SPEED", &Player::checkmovementspeed },
{ "ABLE_TO_DEFUSE", &Player::checkabletodefuse },
{ "ON_LANDMINE", &Player::checkonlandmine },
{ "NEAR_LANDMINE", &Player::checknearlandmine },
{ "CAN_PLACE_LANDMINE", &Player::CondCanPlaceLandmine },
{ "WEAPON_CURRENT_FIRE_ANIM", &Player::CondWeaponCurrentFireAnim },
{ "VEHICLE_TYPE", &Player::CondVehicleType },
{ "ANIMDONE_VM", &Player::CondAnimDoneVM },
{ "CLIENT_COMMAND", &Player::CondClientCommand },
{ "IS_VM_ANIM", &Player::CondVMAnim },
@@ -5740,9 +5780,9 @@ void Player::Pain
{
gi.MSG_SetClient( attacker->edict - g_entities );
if( IsDead() )
gi.MSG_StartCGM( 36 );
gi.MSG_StartCGM(CGM_NOTIFY_KILL);
else
gi.MSG_StartCGM( 35 );
gi.MSG_StartCGM(CGM_NOTIFY_HIT);
gi.MSG_EndCGM();
}
@@ -6478,6 +6518,8 @@ void Player::ClientMove
{
m_bShowingHint = false;
// FIXME: delete
/*
if (sv_reborn->integer)
{
gi.MSG_SetClient(edict - g_entities);
@@ -6487,6 +6529,7 @@ void Player::ClientMove
gi.MSG_WriteString("");
gi.MSG_EndCGM();
}
*/
}
oldorigin = origin;
@@ -6957,7 +7000,7 @@ void Player::ClientThink
client->ps.pm_flags |= PMF_FROZEN;
client->ps.pm_flags |= PMF_INTERMISSION;
if( level.time - level.intermissiontime > 5.0f && ( new_buttons & ( BUTTON_ATTACK | BUTTON_ATTACK2 ) ) )
if( level.time - level.intermissiontime > 5.0f && ( new_buttons & ( BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT ) ) )
{
level.exitintermission = true;
}
@@ -6998,7 +7041,7 @@ void Player::ClientThink
{
if( level.intermissiontype )
{
if( ( new_buttons & BUTTON_ATTACK ) || ( new_buttons & BUTTON_ATTACK2 ) )
if( ( new_buttons & BUTTON_ATTACKLEFT ) || ( new_buttons & BUTTON_ATTACKRIGHT ) )
{
if( level.intermissiontype == TRANS_MISSION_FAILED )
{
@@ -7044,7 +7087,7 @@ void Player::ClientThink
return;
}
if( new_buttons & BUTTON_ATTACK2 )
if( new_buttons & BUTTON_ATTACKRIGHT )
{
Weapon *weapon = GetActiveWeapon( WEAPON_MAIN );
@@ -7252,7 +7295,7 @@ void Player::Think
if (g_gametype->integer == GT_SINGLE_PLAYER)
{
if (((server_new_buttons & BUTTON_ATTACK) || (server_new_buttons & BUTTON_ATTACK2)) &&
if (((server_new_buttons & BUTTON_ATTACKLEFT) || (server_new_buttons & BUTTON_ATTACKRIGHT)) &&
(!GetActiveWeapon(WEAPON_MAIN)) &&
(!IsDead()) &&
(!IsNewActiveWeapon()) &&
@@ -7270,7 +7313,7 @@ void Player::Think
{
if (dmManager.AllowRespawn())
{
if (((server_new_buttons & BUTTON_ATTACK) || (server_new_buttons & BUTTON_ATTACK2)) ||
if (((server_new_buttons & BUTTON_ATTACKLEFT) || (server_new_buttons & BUTTON_ATTACKRIGHT)) ||
(g_forcerespawn->integer > 0 && level.time > g_forcerespawn->integer + respawn_time))
{
m_bSpectator = false;
@@ -7288,7 +7331,7 @@ void Player::Think
if (IsSpectator() && !m_bTempSpectator)
{
if (level.time <= respawn_time || !((server_new_buttons & BUTTON_ATTACK) || (server_new_buttons & BUTTON_ATTACK2)))
if (level.time <= respawn_time || !((server_new_buttons & BUTTON_ATTACKLEFT) || (server_new_buttons & BUTTON_ATTACKRIGHT)))
{
if (level.time - 10.0f > m_fWeapSelectTime)
{
@@ -11544,7 +11587,7 @@ void Player::EventGetFireHeld
)
{
ev->AddInteger( buttons & ( BUTTON_ATTACK | BUTTON_ATTACK2 ) ? qtrue : qfalse );
ev->AddInteger( buttons & ( BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT ) ? qtrue : qfalse );
}
void Player::Score
@@ -13171,7 +13214,7 @@ void Player::EventDMMessage
if( bInstaMessage )
{
gi.MSG_SetClient( i );
gi.MSG_StartCGM( 37 );
gi.MSG_StartCGM(CGM_VOICE_CHAT);
gi.MSG_WriteCoord( m_vViewPos[ 0 ] );
gi.MSG_WriteCoord( m_vViewPos[ 1 ] );
gi.MSG_WriteCoord( m_vViewPos[ 2 ] );
@@ -13263,35 +13306,27 @@ qboolean Player::ViewModelAnim( str anim, qboolean force_restart, qboolean bFull
}
if ( Q_stricmp( anim, "charge" ) == 0 ) {
viewModelAnim = VMA_CHARGE;
viewModelAnim = VM_ANIM_CHARGE;
} else if ( Q_stricmp( anim, "fire" ) == 0 ) {
viewModelAnim = VMA_FIRE;
viewModelAnim = VM_ANIM_FIRE;
} else if ( Q_stricmp( anim, "fire_secondary" ) == 0 ) {
viewModelAnim = VMA_FIRE_SECONDARY;
viewModelAnim = VM_ANIM_FIRE_SECONDARY;
} else if ( Q_stricmp( anim, "rechamber" ) == 0 ) {
viewModelAnim = VMA_RECHAMBER;
viewModelAnim = VM_ANIM_RECHAMBER;
} else if ( Q_stricmp( anim, "reload" ) == 0 ) {
viewModelAnim = VMA_RELOAD;
viewModelAnim = VM_ANIM_RELOAD;
} else if ( Q_stricmp( anim, "reload_single" ) == 0 ) {
viewModelAnim = VMA_RELOAD_SINGLE;
viewModelAnim = VM_ANIM_RELOAD_SINGLE;
} else if ( Q_stricmp( anim, "reload_end" ) == 0 ) {
viewModelAnim = VMA_RELOAD_END;
viewModelAnim = VM_ANIM_RELOAD_END;
} else if ( Q_stricmp( anim, "pullout" ) == 0 ) {
viewModelAnim = VMA_PULLOUT;
viewModelAnim = VM_ANIM_PULLOUT;
} else if ( Q_stricmp( anim, "putaway" ) == 0 ) {
viewModelAnim = VMA_PUTAWAY;
viewModelAnim = VM_ANIM_PUTAWAY;
} else if ( Q_stricmp( anim, "ladderstep" ) == 0 ) {
viewModelAnim = VMA_LADDERSTEP;
viewModelAnim = VM_ANIM_LADDERSTEP;
} else if ( Q_stricmp( anim, "idle" ) == 0 ) {
viewModelAnim = VMA_IDLE;
}
else if ( level.reborn )
{
if ( !anim.icmp( "enable" ) ) {
viewModelAnim = VMA_ENABLE;
} else {
viewModelAnim = VMA_CUSTOMANIMATION;
}
viewModelAnim = VM_ANIM_IDLE;
}
else
{
@@ -13319,16 +13354,6 @@ qboolean Player::ViewModelAnim( str anim, qboolean force_restart, qboolean bFull
m_sVMcurrent = anim;
if ( level.reborn && viewModelAnim == VMA_CUSTOMANIMATION )
{
gi.MSG_SetClient( edict - g_entities );
gi.MSG_StartCGM( CGM_VIEWMODELANIM );
gi.MSG_WriteString( anim.c_str() );
gi.MSG_WriteByte( bFullAnim );
gi.MSG_EndCGM();
}
if ( viewModelAnim != playerState->iViewModelAnim || force_restart ) {
playerState->iViewModelAnimChanged = ( playerState->iViewModelAnimChanged + 1 ) & 3;
}
@@ -14202,7 +14227,7 @@ void Player::LeanLeftHeld
player = ( Player * )this;
buttonheld = !!( player->buttons & BUTTON_LEANLEFT );
buttonheld = !!( player->buttons & BUTTON_LEAN_LEFT );
ev->AddInteger( buttonheld );
}
@@ -14218,7 +14243,7 @@ void Player::LeanRightHeld
player = ( Player * )this;
buttonheld = !!( player->buttons & BUTTON_LEANRIGHT );
buttonheld = !!( player->buttons & BUTTON_LEAN_RIGHT );
ev->AddInteger( buttonheld );
}
@@ -14256,15 +14281,15 @@ void Player::ModifyHeightFloat
client->ps.pm_flags &= ~( PMF_DUCKED | PMF_VIEW_PRONE | PMF_VIEW_DUCK_RUN | PMF_VIEW_JUMP_START );
if( sv_reborn->integer )
{
gi.MSG_SetClient( edict - g_entities);
// FIXME...
/*
gi.MSG_SetClient(edict - g_entities);
gi.MSG_StartCGM( CGM_MODHEIGHTFLOAT );
gi.MSG_WriteLong( height );
gi.MSG_WriteFloat( max_z );
gi.MSG_EndCGM();
}
gi.MSG_StartCGM(CGM_MODHEIGHTFLOAT);
gi.MSG_WriteLong(height);
gi.MSG_WriteFloat(max_z);
gi.MSG_EndCGM();
*/
}
void Player::PlayLocalSound
@@ -14298,8 +14323,8 @@ void Player::PlayLocalSound
return;
}
if( sv_reborn->integer )
{
// FIXME...
/*
gi.MSG_SetClient( client->ps.clientNum );
gi.MSG_StartCGM( CGM_PLAYLOCALSOUND );
@@ -14310,7 +14335,7 @@ void Player::PlayLocalSound
gi.MSG_EndCGM();
return;
}
*/
if( loop )
{
@@ -14362,7 +14387,7 @@ void Player::SecFireHeld
player = ( Player * )this;
buttonheld = !!( player->buttons & BUTTON_ATTACK2 );
buttonheld = !!( player->buttons & BUTTON_ATTACKRIGHT );
ev->AddInteger( buttonheld );
}
@@ -14467,11 +14492,14 @@ void Player::SetLocalSoundRate
gi.MSG_SetClient( client->ps.clientNum );
// FIXME...
/*
gi.MSG_StartCGM( CGM_SETLOCALSOUNDRATE );
gi.MSG_WriteString( found );
gi.MSG_WriteFloat( rate );
gi.MSG_WriteFloat( time );
gi.MSG_EndCGM();
*/
}
void Player::SetSpeed
@@ -14556,12 +14584,15 @@ void Player::SetVMASpeed
vma->name = name;
vma->speed = speed;
// FIXME...
/*
gi.MSG_SetClient( edict - g_entities );
gi.MSG_StartCGM( CGM_SETVMASPEED );
gi.MSG_WriteString( name );
gi.MSG_WriteFloat( speed );
gi.MSG_EndCGM();
*/
}
void Player::StopLocalSound
@@ -14589,20 +14620,8 @@ void Player::StopLocalSound
return;
}
if( level.reborn )
{
gi.MSG_SetClient( client->ps.clientNum );
gi.MSG_StartCGM( CGM_STOPLOCALSOUND );
gi.MSG_WriteString( found );
gi.MSG_WriteFloat( time );
gi.MSG_EndCGM();
}
else
{
edict->s.loopSound = 0;
gi.StopSound( entnum, CHAN_LOCAL );
}
edict->s.loopSound = 0;
gi.StopSound(entnum, CHAN_LOCAL);
}
void Player::UseHeld
+7 -1
View File
@@ -354,7 +354,6 @@ public:
qboolean checkattackbuttonright( Conditional &condition );
qboolean checksneak( Conditional &condition );
qboolean checkrun( Conditional &condition );
qboolean checkholsterweapon( Conditional &condition );
qboolean checkuse( Conditional &condition );
qboolean checkcanturn( Conditional &condition );
qboolean checkcanmoveright( Conditional &condition );
@@ -443,6 +442,13 @@ public:
qboolean checkminchargetimemet( Conditional &condition );
qboolean checkmaxchargetimemet( Conditional &condition );
qboolean checkimmediateswitch( Conditional &condition );
qboolean checkmovementspeed( Conditional &condition );
qboolean checkabletodefuse( Conditional &condition );
qboolean checkonlandmine( Conditional &condition );
qboolean checknearlandmine( Conditional &condition );
qboolean CondCanPlaceLandmine( Conditional &condition );
qboolean CondWeaponCurrentFireAnim( Conditional &condition );
qboolean CondVehicleType( Conditional &condition );
qboolean CondAnimDoneVM( Conditional &condition );
qboolean CondClientCommand( Conditional &condition );
qboolean CondVMAnim( Conditional &condition );
+12 -12
View File
@@ -503,7 +503,7 @@ void PlayerBot::UpdateBotStates
if( IsDead() )
{
// The bot should respawn
m_botCmd.buttons ^= BUTTON_ATTACK;
m_botCmd.buttons ^= BUTTON_ATTACKLEFT;
return;
}
@@ -1419,7 +1419,7 @@ void PlayerBot::State_EndAttack
)
{
m_botCmd.buttons &= ~( BUTTON_ATTACK | BUTTON_ATTACK2 );
m_botCmd.buttons &= ~( BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT );
}
void PlayerBot::State_Attack
@@ -1470,16 +1470,16 @@ void PlayerBot::State_Attack
{
if( pWeap->IsSemiAuto() )
{
m_botCmd.buttons ^= BUTTON_ATTACK;
m_botCmd.buttons ^= BUTTON_ATTACKLEFT;
}
else
{
m_botCmd.buttons |= BUTTON_ATTACK;
m_botCmd.buttons |= BUTTON_ATTACKLEFT;
}
}
else
{
m_botCmd.buttons &= ~BUTTON_ATTACK;
m_botCmd.buttons &= ~BUTTON_ATTACKLEFT;
}
}
else if( pWeap->GetFireType( FIRE_SECONDARY ) == FT_MELEE )
@@ -1488,21 +1488,21 @@ void PlayerBot::State_Attack
if( fDistanceSquared <= fSecondaryBulletRangeSquared )
{
m_botCmd.buttons ^= BUTTON_ATTACK2;
m_botCmd.buttons ^= BUTTON_ATTACKRIGHT;
}
else
{
m_botCmd.buttons &= ~BUTTON_ATTACK2;
m_botCmd.buttons &= ~BUTTON_ATTACKRIGHT;
}
}
else
{
m_botCmd.buttons &= ~( BUTTON_ATTACK | BUTTON_ATTACK2 );
m_botCmd.buttons &= ~( BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT );
}
}
else
{
m_botCmd.buttons &= ~( BUTTON_ATTACK | BUTTON_ATTACK2 );
m_botCmd.buttons &= ~( BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT );
fMinDistanceSquared = 0;
}
@@ -1634,10 +1634,10 @@ void PlayerBot::Killed
Player::Killed( ev );
// send the respawn buttons
if( !( m_botCmd.buttons & BUTTON_ATTACK ) )
m_botCmd.buttons |= BUTTON_ATTACK;
if( !( m_botCmd.buttons & BUTTON_ATTACKLEFT ) )
m_botCmd.buttons |= BUTTON_ATTACKLEFT;
else
m_botCmd.buttons &= ~BUTTON_ATTACK;
m_botCmd.buttons &= ~BUTTON_ATTACKLEFT;
m_botEyes.ofs[ 0 ] = 0;
m_botEyes.ofs[ 1 ] = 0;
+1 -1
View File
@@ -772,7 +772,7 @@ qboolean TurretGun::UserAim
m_vUserLastCmdAng = vNewCmdAng;
if( ( ucmd->buttons & BUTTON_ATTACK ) || ( ucmd->buttons & BUTTON_ATTACK2 ) )
if( ( ucmd->buttons & BUTTON_ATTACKLEFT ) || ( ucmd->buttons & BUTTON_ATTACKRIGHT ) )
{
if( !m_iFiring ) {
m_iFiring = 1;
+12 -12
View File
@@ -1785,11 +1785,11 @@ void Explosion::MakeExplosionEffect
if( !sEffect.icmp( "grenade" ) )
{
gi.MSG_StartCGM( 12 );
gi.MSG_StartCGM(CGM_EXPLOSION_EFFECT_1);
}
else
{
gi.MSG_StartCGM( 13 );
gi.MSG_StartCGM(CGM_EXPLOSION_EFFECT_2);
}
gi.MSG_WriteCoord( origin[ 0 ] );
@@ -2034,7 +2034,7 @@ float BulletAttack
if( ent->edict->solid == 3 && trace.shaderNum >= 0 )
{
gi.SetBroadcastVisible( trace.endpos, 0 );
gi.MSG_StartCGM( 6 );
gi.MSG_StartCGM(CGM_BULLET_6);
gi.MSG_WriteCoord( trace.endpos[ 0 ] );
gi.MSG_WriteCoord( trace.endpos[ 1 ] );
gi.MSG_WriteCoord( trace.endpos[ 2 ] );
@@ -2192,7 +2192,7 @@ float BulletAttack
if( trace.contents > 0 && trace.surfaceFlags & 0xFFFE000 )
{
gi.SetBroadcastVisible( trace.endpos, NULL );
gi.MSG_StartCGM( 6 );
gi.MSG_StartCGM(CGM_BULLET_6);
gi.MSG_WriteCoord( trace.endpos[ 0 ] );
gi.MSG_WriteCoord( trace.endpos[ 1 ] );
gi.MSG_WriteCoord( trace.endpos[ 2 ] );
@@ -2203,7 +2203,7 @@ float BulletAttack
else if( trace.location >= 0 && ent->IsSubclassOfPlayer() )
{
gi.SetBroadcastVisible( trace.endpos, NULL );
gi.MSG_StartCGM( 7 );
gi.MSG_StartCGM(CGM_BULLET_7);
gi.MSG_WriteCoord( trace.endpos[ 0 ] );
gi.MSG_WriteCoord( trace.endpos[ 1 ] );
gi.MSG_WriteCoord( trace.endpos[ 2 ] );
@@ -2250,7 +2250,7 @@ float BulletAttack
{
if( iTracerCount )
{
gi.MSG_StartCGM( 1 );
gi.MSG_StartCGM(CGM_BULLET_1);
gi.MSG_WriteCoord( vBarrel[ 0 ] );
gi.MSG_WriteCoord( vBarrel[ 1 ] );
@@ -2258,7 +2258,7 @@ float BulletAttack
}
else
{
gi.MSG_StartCGM( 2 );
gi.MSG_StartCGM(CGM_BULLET_2);
}
gi.MSG_WriteCoord( start[ 0 ] );
@@ -2273,7 +2273,7 @@ float BulletAttack
{
if( iTracerCount )
{
gi.MSG_StartCGM( 3 );
gi.MSG_StartCGM(CGM_BULLET_3);
gi.MSG_WriteCoord( vBarrel[ 0 ] );
gi.MSG_WriteCoord( vBarrel[ 1 ] );
@@ -2286,7 +2286,7 @@ float BulletAttack
}
else
{
gi.MSG_StartCGM( 4 );
gi.MSG_StartCGM(CGM_BULLET_4);
}
gi.MSG_WriteCoord( start[ 0 ] );
@@ -2349,7 +2349,7 @@ void FakeBulletAttack
( *piTracerCount )++;
if( *piTracerCount == iTracerFrequency )
{
gi.MSG_StartCGM( 25 );
gi.MSG_StartCGM(CGM_BULLET_NO_BARREL_1);
gi.MSG_WriteCoord( vBarrel[ 0 ] );
gi.MSG_WriteCoord( vBarrel[ 1 ] );
gi.MSG_WriteCoord( vBarrel[ 2 ] );
@@ -2357,12 +2357,12 @@ void FakeBulletAttack
}
else
{
gi.MSG_StartCGM( 26 );
gi.MSG_StartCGM(CGM_BULLET_NO_BARREL_2);
}
}
else
{
gi.MSG_StartCGM( 26 );
gi.MSG_StartCGM(CGM_BULLET_NO_BARREL_2);
}
gi.MSG_WriteCoord( start[ 0 ] );
+1 -1
View File
@@ -151,7 +151,7 @@ void WindowObject::WindowKilled( Event *ev )
vCenter = origin + mins + maxs;
gi.SetBroadcastVisible( vCenter, vCenter );
gi.MSG_StartCGM( 24 );
gi.MSG_StartCGM(CGM_MAKE_WINDOW_DEBRIS);
gi.MSG_WriteCoord( vCenter[ 0 ] );
gi.MSG_WriteCoord( vCenter[ 1 ] );
gi.MSG_WriteCoord( vCenter[ 2 ] );
+55 -26
View File
@@ -391,9 +391,6 @@ ConSimple *World::GetTargetList( const_str targetname )
return &m_targetList.addKeyValue( targetname );
}
#ifdef GAME_DLL
World::World()
{
world = this;
@@ -424,11 +421,30 @@ World::World()
// set the default farplane parameters
farplane_distance = 0;
farplane_color = "0 0 0";
farplane_bias = 0.0;
farplane_color = vec_zero;
farplane_cull = qtrue;
skybox_farplane = 0.0;
render_terrain = qtrue;
skybox_speed = 0.0;
farclip_override = 0.f;
farplane_color_override = Vector(-1, -1, -1);
animated_farplane_start = 0.0;
animated_farplane_end = 0.0;
animated_farplane_start_z = 8192.0;
animated_farplane_end_z = 0.0;
animated_farplane_bias_start = 0.0;
animated_farplane_bias_end = 0.0;
animated_farplane_bias_start_z = 8192.0;
animated_farplane_bias_end_z = 0.0;
animated_farplane_color_start = vec_zero;
animated_farplane_color_end = vec_zero;
animated_farplane_color_start_z = 8192.0;
animated_farplane_color_end_z = 0.0;
UpdateFog();
sky_alpha = 1.0f;
sky_portal = qtrue;
UpdateSky();
@@ -472,19 +488,12 @@ void World::UpdateConfigStrings( void )
gi.SetConfigstring( CS_MESSAGE, level.level_name.c_str() );
};
void World::UpdateFog( void )
{
gi.SetFarPlane( farplane_distance );
gi.SetConfigstring( CS_FOGINFO, va( "%d %.0f %.4f %.4f %.4f", farplane_cull, farplane_distance, farplane_color.x, farplane_color.y, farplane_color.z ) );
}
void World::UpdateSky( void )
{
gi.SetSkyPortal( sky_portal );
gi.SetConfigstring( CS_SKYINFO, va( "%.4f %d", sky_alpha, sky_portal ) );
}
void World::SetSoundtrack( Event *ev )
{
const char *text;
@@ -566,6 +575,41 @@ void World::SetNorthYaw( Event *ev )
m_fNorth = anglemod( ev->GetFloat( 1 ) );
}
#if TARGET_GAME_PROTOCOL >= 15
void World::UpdateFog(void)
{
gi.SetFarPlane(farplane_distance);
gi.SetConfigstring(CS_FOGINFO, va(
"%d %.0f %.0f %.0f %.6f %.4f %.4f %.4f %d %.0f %.2f %.2f %.2f",
farplane_cull,
farplane_distance,
farplane_bias,
skybox_farplane,
skybox_speed,
farplane_color.x,
farplane_color.y,
farplane_color.z,
render_terrain,
farclip_override,
farplane_color_override.x,
farplane_color_override.y,
farplane_color_override.z
)
);
}
#else
void World::UpdateFog(void)
{
gi.SetFarPlane(farplane_distance);
gi.SetConfigstring(CS_FOGINFO, va("%d %.0f %.4f %.4f %.4f", farplane_cull, farplane_distance, farplane_color.x, farplane_color.y, farplane_color.z));
}
#endif
CLASS_DECLARATION( Entity, World, "worldspawn" )
{
{ &EV_World_SetSoundtrack, &World::SetSoundtrack },
@@ -594,18 +638,3 @@ CLASS_DECLARATION( Entity, World, "worldspawn" )
{ &EV_World_SetSunDiffuseColor, NULL },
{ NULL, NULL }
};
#else
World::World()
{
world = this;
world_dying = qfalse;
}
CLASS_DECLARATION( SimpleEntity, World, "worldspawn" )
{
{ NULL, NULL }
};
#endif
+18
View File
@@ -51,8 +51,26 @@ class World : public SimpleEntity {
public:
// farplane variables
float farplane_distance;
float farplane_bias;
Vector farplane_color;
qboolean farplane_cull;
float skybox_farplane;
qboolean render_terrain;
float skybox_speed;
float farclip_override;
Vector farplane_color_override;
float animated_farplane_start;
float animated_farplane_end;
float animated_farplane_start_z;
float animated_farplane_end_z;
float animated_farplane_bias_start;
float animated_farplane_bias_end;
float animated_farplane_bias_start_z;
float animated_farplane_bias_end_z;
Vector animated_farplane_color_start;
Vector animated_farplane_color_end;
float animated_farplane_color_start_z;
float animated_farplane_color_end_z;
// sky variables
float sky_alpha;
-2
View File
@@ -1,7 +1,5 @@
cmake_minimum_required(VERSION 3.5)
project(gcd)
set(CURRENT_DIR "code/gamespy")
include_directories("${CURRENT_DIR}/common")
+100 -162
View File
@@ -200,168 +200,109 @@ void Alias_ListAddParms(AliasListNode_t* node, const char* parameters)
return;
}
while (1)
for (;;)
{
while (1)
token = nptr = COM_GetToken((char**)&parameters, qtrue);
if (!token || !token[0])
{
while (1)
break;
}
if (!Q_stricmp(token, "stop"))
{
node->stop_flag = 1;
}
else if (!Q_stricmp(token, "soundparms"))
{
node->volume = getTokenFloat(&parameters, "volume", node);
node->volumeMod = getTokenFloat(&parameters, "volumeMod", node);
node->pitch = getTokenFloat(&parameters, "pitch", node);
node->pitchMod = getTokenFloat(&parameters, "pitchMod", node);
node->dist = getTokenFloat(&parameters, "dist", node);
node->maxDist = getTokenFloat(&parameters, "maxDist", node);
token = COM_GetToken((char**)&parameters, qtrue);
if (!token || !*token)
{
while (1)
{
while (1)
{
while (1)
{
while (1)
{
while (1)
{
token = nptr = COM_GetToken((char**)&parameters, qtrue);
if (!token || !*token)
{
return;
}
if (Q_stricmp(nptr, "weight"))
{
break;
}
node->stop_flag = 1;
}
if (Q_stricmp(nptr, "weight"))
{
break;
}
token = COM_GetToken((char**)&parameters, 1);
if (!token || !*token)
{
return;
}
temp_float = atof(token);
if (temp_float < 0.0f)
{
Com_Printf("Weight value out of range in %s alias\n", node->alias_name);
continue;
}
node->weight = temp_float;
}
if (Q_stricmp(nptr, "soundparms"))
{
break;
}
node->volume = getTokenFloat(&parameters, "volume", node);
node->volumeMod = getTokenFloat(&parameters, "volumeMod", node);
node->pitch = getTokenFloat(&parameters, "pitch", node);
node->pitchMod = getTokenFloat(&parameters, "pitchMod", node);
node->dist = getTokenFloat(&parameters, "dist", node);
node->maxDist = getTokenFloat(&parameters, "maxDist", node);
token = COM_GetToken((char**)&parameters, 1);
if (!token || !*token)
{
return;
}
node->channel = S_ChannelNameToNum(token);
if (node->channel == -1)
{
Com_Printf("%s is not avalid channel on %s alias.\n", token, node->alias_name);
node->channel = 0;
}
token = COM_GetToken((char**)&parameters, 1);
if (!token || !*token)
{
Com_Printf("ERROR: defaulting %s to not streamed - please setup alias properly.\n", node->alias_name);
return;
}
if (!Q_stricmp(token, "streamed"))
{
node->streamed = 1;
}
else if (!Q_stricmp(token, "loaded"))
{
node->streamed = 0;
}
else
{
Com_Printf("ERROR: Expecting streamed or loaded in ubersound and got %s on alias %s\n", token, node->alias_name);
continue;
}
}
if (Q_stricmp(nptr, "subtitle"))
{
break;
}
token = COM_GetToken((char**)&parameters, qtrue);
if (!token || !*token)
{
Com_Printf("NULL subtitle on %s alias.\n", node->alias_name);
return;
}
node->subtitle = Z_TagMalloc(strlen(token) + 1, TAG_TIKI);
strcpy(node->subtitle, token);
}
if (Q_stricmp(nptr, "pitch"))
{
break;
}
token = COM_GetToken((char**)&parameters, qtrue);
if (!token || !*token)
{
return;
}
temp_float = atof(token);
if (temp_float < 0.0f)
{
Com_Printf("Pitch value out of range in %s alias\n", node->alias_name);
continue;
}
node->pitch = temp_float;
}
if (Q_stricmp(nptr, "pitchmod"))
{
break;
}
token = COM_GetToken((char**)&parameters, qtrue);
if (!token || !*token)
{
return;
}
temp_float = atof(token);
if (temp_float < 0.0f)
{
Com_Printf("PitchMod value out of range in %s alias\n", node->alias_name);
continue;
}
node->pitchMod = temp_float;
return;
}
if (Q_stricmp(nptr, "volumemod"))
node->channel = S_ChannelNameToNum(token);
if (node->channel == -1)
{
break;
Com_Printf("%s is not avalid channel on %s alias.\n", token, node->alias_name);
node->channel = 0;
}
token = COM_GetToken((char**)&parameters, qtrue);
if (!token || !*token)
{
Com_Printf("ERROR: defaulting %s to not streamed - please setup alias properly.\n", node->alias_name);
return;
}
if (!Q_stricmp(token, "streamed"))
{
node->streamed = qtrue;
}
else if (!Q_stricmp(token, "loaded"))
{
node->streamed = qfalse;
}
else
{
Com_Printf("ERROR: Expecting streamed or loaded in ubersound and got %s on alias %s\n", token, node->alias_name);
continue;
}
}
else if (!Q_stricmp(token, "subtitle"))
{
token = COM_GetToken((char**)&parameters, qtrue);
if (!token || !*token)
{
Com_Printf("NULL subtitle on %s alias.\n", node->alias_name);
return;
}
node->subtitle = Z_TagMalloc(strlen(token) + 1, TAG_TIKI);
strcpy(node->subtitle, token);
}
else if (!Q_stricmp(token, "pitch"))
{
token = COM_GetToken((char**)&parameters, qtrue);
if (!token || !*token)
{
return;
}
temp_float = atof(token);
if (temp_float < 0.0f)
{
Com_Printf("Pitch value out of range in %s alias\n", node->alias_name);
continue;
}
node->pitch = temp_float;
}
else if (!Q_stricmp(token, "pitchmod"))
{
token = COM_GetToken((char**)&parameters, qtrue);
if (!token || !*token)
{
return;
}
temp_float = atof(token);
if (temp_float < 0.0f)
{
Com_Printf("PitchMod value out of range in %s alias\n", node->alias_name);
continue;
}
node->pitchMod = temp_float;
}
else if (!Q_stricmp(token, "volumemod"))
{
token = COM_GetToken((char**)&parameters, qtrue);
if (!token || !*token)
{
@@ -377,8 +318,7 @@ void Alias_ListAddParms(AliasListNode_t* node, const char* parameters)
node->volumeMod = temp_float;
}
if (!Q_stricmp(nptr, "dist"))
else if (!Q_stricmp(token, "dist"))
{
token = COM_GetToken((char**)&parameters, qtrue);
if (!token || !*token)
@@ -396,7 +336,7 @@ void Alias_ListAddParms(AliasListNode_t* node, const char* parameters)
node->dist = temp_float;
}
else if (!Q_stricmp(nptr, "channel"))
else if (!Q_stricmp(token, "channel"))
{
token = COM_GetToken((char**)&parameters, qtrue);
if (!token || !*token)
@@ -418,8 +358,6 @@ void Alias_ListAddParms(AliasListNode_t* node, const char* parameters)
continue;
}
}
// FIXME: stub
}
qboolean Alias_ListAdd(AliasList_t* list, const char* alias, const char* name, const char* parameters)
@@ -728,7 +666,7 @@ void Alias_ListFindRandomRange(AliasList_t* list, const char* alias, int* min_in
}
} while (r >= l);
if (l >= r)
if (r >= l)
{
numfound = 0;
*min_index = index;
@@ -736,7 +674,7 @@ void Alias_ListFindRandomRange(AliasList_t* list, const char* alias, int* min_in
totalfoundweight = 0.f;
ptr = &list->sorted_list[index];
for (i = 0; i < index; i++, ptr--)
for (i = index + 1; i > 0; i--, ptr--)
{
if (strncmp(convalias, (*ptr)->alias_name, length)) {
break;
@@ -746,7 +684,7 @@ void Alias_ListFindRandomRange(AliasList_t* list, const char* alias, int* min_in
{
foundlist[numfound++] = *ptr;
totalfoundweight += (*ptr)->weight;
*min_index = i;
*min_index = i - 1;
}
}
+7 -3
View File
@@ -609,6 +609,7 @@ void CMod_LoadPatches( gamelump_t *surfs, gamelump_t *verts, int *shaderSubdivis
vec3_t points[MAX_PATCH_VERTS];
int width, height;
int shaderNum;
char tempName[MAX_QPATH + 1];
in = ( dsurface_t * )surfs->buffer;
if( surfs->length % sizeof( *in ) )
@@ -668,6 +669,9 @@ void CMod_LoadPatches( gamelump_t *surfs, gamelump_t *verts, int *shaderSubdivis
// create the internal facet structure
patch->pc = CM_GeneratePatchCollide( width, height, points, patch->subdivisions );
sprintf(tempName, "s%d", i);
UI_LoadResource(tempName);
}
Hunk_FreeTempMemory( shaderSubdivisions );
@@ -878,9 +882,9 @@ void CM_LoadMap( const char *name, qboolean clientload, int *checksum ) {
((int *)&header)[i] = LittleLong ( ((int *)&header)[i]);
}
if ( header.version != BSP_VERSION ) {
Com_Error (ERR_DROP, "CM_LoadMap: %s has wrong version number (%i should be %i)"
, name, header.version, BSP_VERSION );
if ( header.version < BSP_MIN_VERSION || header.version > BSP_MAX_VERSION ) {
Com_Error (ERR_DROP, "CM_LoadMap: %s has wrong version number (%i should be between %i and %i)"
, name, header.version, BSP_MIN_VERSION, BSP_MAX_VERSION );
}
cmod_base = ( byte * )&header;
+32 -211
View File
@@ -31,6 +31,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <winsock.h>
#endif
// FPS
#include <chrono>
#include <tiki.h>
qboolean CL_FinishedIntro(void);
@@ -72,7 +75,6 @@ fileHandle_t com_journalDataFile; // config files are written here
cvar_t *paused;
cvar_t *config;
cvar_t *fps;
float currentfps;
cvar_t *com_speeds;
cvar_t *developer;
cvar_t *com_dedicated;
@@ -126,6 +128,18 @@ static char *rd_buffer;
static int rd_buffersize;
static void (*rd_flush)( char *buffer );
#define MAX_FPS_TIMES 16
using fps_clock_t = std::chrono::high_resolution_clock;
using fps_time_t = fps_clock_t::time_point;
using fps_delta_t = fps_clock_t::duration;
static int fpsindex;
static fps_delta_t fpstimes[MAX_FPS_TIMES];
static fps_delta_t fpstotal;
static fps_time_t fpslasttime;
float currentfps;
void Com_BeginRedirect (char *buffer, int buffersize, void (*flush)( char *) )
{
if (!buffer || !buffersize || !flush)
@@ -270,7 +284,7 @@ void QDECL Com_Error( int code, const char *fmt, ... ) {
static int errorCount;
int currentTime;
#ifdef _DEBUG
#ifdef COM_ERROR_ASSERT
*( int * )0 = 0;
assert( 0 );
#endif
@@ -1752,6 +1766,22 @@ void Com_Frame( void ) {
com_frameNumber, all, sv, ev, cl, time_game, time_frontend, time_backend );
}
if (fps->integer) {
fps_time_t fpstime = fps_clock_t::now();
fps_delta_t delta = fpstime - fpslasttime;
fpstotal = (fpstime - fpslasttime) + (fpstotal - fpstimes[fpsindex]);
fpstimes[fpsindex] = fpstime - fpslasttime;
fpsindex = (fpsindex + 1) % MAX_FPS_TIMES;
fpslasttime = fpstime;
if (fpstotal.count()) {
currentfps = 16.0 / std::chrono::duration<long double>(fpstotal).count();
} else {
currentfps = 0.0;
}
}
//
// trace optimization tracking
//
@@ -1893,23 +1923,10 @@ command line completion
===========================================
*/
/*
==================
Field_Clear
==================
*/
void Field_Clear( field_t *edit ) {
memset(edit->buffer, 0, MAX_EDIT_LINE);
edit->cursor = 0;
edit->scroll = 0;
}
static const char *completionString;
static char shortestMatch[MAX_TOKEN_CHARS];
static int matchCount;
// field we are working on, passed to Field_AutoComplete(&g_consoleCommand for instance)
static field_t *completionField;
/*
===============
FindMatches
@@ -1968,200 +1985,4 @@ static void PrintCvarMatches( const char *s ) {
}
}
/*
===============
Field_FindFirstSeparator
===============
*/
static char *Field_FindFirstSeparator( char *s )
{
int i;
for( i = 0; i < strlen( s ); i++ )
{
if( s[ i ] == ';' )
return &s[ i ];
}
return NULL;
}
#ifndef DEDICATED
/*
===============
Field_CompleteKeyname
===============
*/
static void Field_CompleteKeyname( void )
{
matchCount = 0;
shortestMatch[ 0 ] = 0;
Key_KeynameCompletion( FindMatches );
if( matchCount == 0 )
return;
Q_strncpyz( &completionField->buffer[ strlen( completionField->buffer ) -
strlen( completionString ) ], shortestMatch,
sizeof( completionField->buffer ) );
completionField->cursor = ( int )strlen( completionField->buffer );
if( matchCount == 1 )
{
Q_strcat( completionField->buffer, sizeof( completionField->buffer ), " " );
completionField->cursor++;
return;
}
Com_Printf( "]%s\n", completionField->buffer );
Key_KeynameCompletion( PrintMatches );
}
#endif
/*
===============
Field_CompleteFilename
===============
*/
static void Field_CompleteFilename( const char *dir,
const char *ext, qboolean stripExt )
{
size_t pos;
matchCount = 0;
shortestMatch[ 0 ] = 0;
FS_FilenameCompletion( dir, ext, stripExt, FindMatches );
if( matchCount == 0 )
return;
pos = strlen( completionField->buffer ) - strlen( completionString );
Q_strncpyz( &completionField->buffer[ pos ], shortestMatch,
sizeof( completionField->buffer ) - pos );
completionField->cursor = ( int )strlen( completionField->buffer );
if( matchCount == 1 )
{
Q_strcat( completionField->buffer, sizeof( completionField->buffer ), " " );
completionField->cursor++;
return;
}
Com_Printf( "]%s\n", completionField->buffer );
FS_FilenameCompletion( dir, ext, stripExt, PrintMatches );
}
static void keyConcatArgs(void) {
int i;
char* arg;
for (i = 1; i < Cmd_Argc(); i++) {
Q_strcat(completionField->buffer, sizeof(completionField->buffer), " ");
arg = Cmd_Argv(i);
while (*arg) {
if (*arg == ' ') {
Q_strcat(completionField->buffer, sizeof(completionField->buffer), "\"");
break;
}
arg++;
}
Q_strcat(completionField->buffer, sizeof(completionField->buffer), Cmd_Argv(i));
if (*arg == ' ') {
Q_strcat(completionField->buffer, sizeof(completionField->buffer), "\"");
}
}
}
static void ConcatRemaining(const char* src, const char* start) {
const char* str;
str = strstr(src, start);
if (!str) {
keyConcatArgs();
return;
}
str += strlen(start);
Q_strcat(completionField->buffer, sizeof(completionField->buffer), str);
}
/*
===============
Field_CompleteCommand
perform Tab expansion
NOTE TTimo this was originally client code only
moved to common code when writing tty console for *nix dedicated server
===============
*/
void Field_CompleteCommand(field_t* field) {
field_t temp;
completionField = field;
// only look at the first token for completion purposes
Cmd_TokenizeString(completionField->buffer);
completionString = Cmd_Argv(0);
if (completionString[0] == '\\' || completionString[0] == '/') {
completionString++;
}
matchCount = 0;
shortestMatch[0] = 0;
if (strlen(completionString) == 0) {
return;
}
Cmd_CommandCompletion(FindMatches);
Cvar_CommandCompletion(FindMatches);
if (matchCount == 0) {
return; // no matches
}
Com_Memcpy(&temp, completionField, sizeof(field_t));
if (matchCount == 1) {
Com_sprintf(completionField->buffer, sizeof(completionField->buffer), "\\%s", shortestMatch);
if (Cmd_Argc() == 1) {
Q_strcat(completionField->buffer, sizeof(completionField->buffer), " ");
}
else {
ConcatRemaining(temp.buffer, completionString);
}
completionField->cursor = strlen(completionField->buffer);
return;
}
// multiple matches, complete to shortest
Com_sprintf(completionField->buffer, sizeof(completionField->buffer), "\\%s", shortestMatch);
completionField->cursor = strlen(completionField->buffer);
ConcatRemaining(temp.buffer, completionString);
Com_Printf("]%s\n", completionField->buffer);
// run through again, printing matches
Cmd_CommandCompletion(PrintMatches);
Cvar_CommandCompletion(PrintMatches);
}
/*
===============
Field_AutoComplete
Perform Tab expansion
===============
*/
void Field_AutoComplete( field_t *field )
{
completionField = field;
Field_CompleteCommand(field);
}
}
+12 -6
View File
@@ -3068,7 +3068,7 @@ static void FS_ReorderPurePaks( void )
FS_Startup
================
*/
static void FS_Startup( const char *gameName )
static void FS_Startup(const char* gameName, const char* extensionName)
{
const char* homePath;
@@ -3087,10 +3087,16 @@ static void FS_Startup( const char *gameName )
fs_gamedirvar = Cvar_Get( "fs_game", "", CVAR_INIT | CVAR_SYSTEMINFO );
fs_restrict = Cvar_Get( "fs_restrict", "", CVAR_INIT );
FS_AddGameDirectory( fs_basepath->string, gameName );
if (gameName) {
FS_AddGameDirectory(fs_basepath->string, gameName);
}
if( *fs_gamedirvar->string && !Q_stricmp( gameName, "main" ) && Q_stricmp( fs_gamedirvar->string, gameName ) ) {
FS_AddGameDirectory( fs_basepath->string, fs_gamedirvar->string );
if (Q_stricmp(gameName, extensionName)) {
FS_AddGameDirectory(fs_basepath->string, extensionName);
}
if (*fs_gamedirvar->string && !Q_stricmp(gameName, GAME_EXTENSION_BASE) && Q_stricmp(fs_gamedirvar->string, gameName)) {
FS_AddGameDirectory(fs_basepath->string, fs_gamedirvar->string);
}
fs_mapdir = Cvar_Get( "mapdir", "", 0 );
@@ -3594,7 +3600,7 @@ void FS_InitFilesystem( void ) {
Com_StartupVariable( "fs_homepath" );
// try to start up normally
FS_Startup( BASEGAME );
FS_Startup( BASEGAME, GAME_EXTENSION_BASE);
FS_SetRestrictions();
if( !silentStart ) {
@@ -3640,7 +3646,7 @@ void FS_Restart( int checksumFeed ) {
FS_ClearPakReferences(0);
// try to start up normally
FS_Startup( BASEGAME );
FS_Startup(BASEGAME, GAME_EXTENSION_BASE);
FS_CheckPak0( );
+1 -1
View File
@@ -108,7 +108,7 @@ void* MEM_TempAlloc::CreateBlock(size_t len)
// allocate a new block
tempBlock_t* prev_block = m_CurrentMemoryBlock;
m_CurrentMemoryBlock = (tempBlock_t*)MEM_TempAllocate(
sizeof(tempBlock_t) + max(m_BlockSize, len));
sizeof(tempBlock_t) + Q_max(m_BlockSize, len));
m_CurrentMemoryBlock->prev = prev_block;
return m_CurrentMemoryBlock->GetData();
}
+2 -2
View File
@@ -114,7 +114,7 @@ void Z_Free( void *ptr )
block->prev = block;
block->next = block;
#if !defined(_DEBUG) && !defined(WIN32)
#if !defined(_DEBUG) || !defined(WIN32)
// free the block
free( block );
#else
@@ -172,7 +172,7 @@ void *Z_TagMalloc( size_t size, int tag )
#endif
size = PAD( size, sizeof( intptr_t ) ); // align to 32/64 bit boundary
#if !defined(_DEBUG) && !defined(WIN32)
#if !defined(_DEBUG) || !defined(WIN32)
block = ( memblock_t * )malloc( size );
#else
block = HeapAlloc(GetProcessHeap(), 0, size);
+560 -190
View File
@@ -32,10 +32,10 @@ int oldsize = 0;
// TA stuff
//===================
static constexpr unsigned int MAX_PACKED_COORD = 65536;
static constexpr unsigned int MAX_PACKED_COORD_HALF = MAX_PACKED_COORD / 2;
static constexpr unsigned int MAX_PACKED_COORD_EXTRA = 262144;
static constexpr unsigned int MAX_PACKED_COORD_EXTRA_HALF = MAX_PACKED_COORD_EXTRA / 2;
static constexpr int MAX_PACKED_COORD = 65536;
static constexpr int MAX_PACKED_COORD_HALF = MAX_PACKED_COORD / 2;
static constexpr int MAX_PACKED_COORD_EXTRA = 262144;
static constexpr int MAX_PACKED_COORD_EXTRA_HALF = MAX_PACKED_COORD_EXTRA / 2;
//===
// Statistics for changes reporting
@@ -161,7 +161,7 @@ int overflows;
#if TARGET_GAME_PROTOCOL >= 15
int MSG_NegateValue(int value)
int MSG_WriteNegateValue(int value, int bits)
{
if (value >= 0) {
value <<= 1;
@@ -173,13 +173,34 @@ int MSG_NegateValue(int value)
return value;
}
int MSG_ReadNegateValue(int value, int bits)
{
if (value & 1) {
value = ~(value >> 1);
}
else {
value >>= 1;
}
return value;
}
#else
int MSG_NegateValue(int value)
int MSG_WriteNegateValue(int value, int bits)
{
return value;
}
int MSG_ReadNegateValue(int value, int bits)
{
if (value & (1 << (bits - 1))) {
value |= -1 ^ ((1 << bits) - 1);
}
return value;
}
#endif
// negative bit values include signs
@@ -216,8 +237,9 @@ void MSG_WriteBits( msg_t *msg, int value, int bits ) {
}
if ( bits < 0 ) {
bits = -bits;
value = MSG_NegateValue(value);
value = MSG_WriteNegateValue(value, bits);
}
if (msg->oob) {
if (msg->cursize + (bits >> 3) > msg->maxsize) {
msg->overflowed = qtrue;
@@ -326,10 +348,9 @@ int MSG_ReadBits( msg_t *msg, int bits ) {
}
msg->readcount = (msg->bit>>3)+1;
}
if (sgn) {
if (value & (1 << (bits - 1))) {
value |= -1 ^ ((1 << bits) - 1);
}
value = MSG_ReadNegateValue(value, bits);
}
return value;
@@ -417,6 +438,32 @@ void MSG_WriteString( msg_t *sb, const char *s ) {
}
}
void MSG_WriteBigString( msg_t *sb, const char *s ) {
if ( !s ) {
MSG_WriteByte(sb, 0);
} else {
size_t l;
int i;
char string[BIG_INFO_STRING];
l = strlen( s );
if ( l >= BIG_INFO_STRING ) {
Com_Printf("MSG_WriteString: BIG_INFO_STRING");
MSG_WriteByte(sb, 0);
return;
}
Q_strncpyz( string, s, sizeof( string ) );
for ( i = 0 ; i <= l ; i++ ) {
MSG_WriteByte(sb, string[i]);
}
}
}
#if TARGET_GAME_PROTOCOL >= 15
void MSG_WriteScrambledString(msg_t* sb, const char* s) {
if (!s) {
strstats[0]++;
@@ -444,28 +491,6 @@ void MSG_WriteScrambledString(msg_t* sb, const char* s) {
}
}
void MSG_WriteBigString( msg_t *sb, const char *s ) {
if ( !s ) {
MSG_WriteByte(sb, 0);
} else {
size_t l;
int i;
char string[BIG_INFO_STRING];
l = strlen( s );
if ( l >= BIG_INFO_STRING ) {
Com_Printf("MSG_WriteString: BIG_INFO_STRING");
MSG_WriteByte(sb, 0);
return;
}
Q_strncpyz( string, s, sizeof( string ) );
for ( i = 0 ; i <= l ; i++ ) {
MSG_WriteByte(sb, string[i]);
}
}
}
void MSG_WriteScrambledBigString(msg_t* sb, const char* s) {
if (!s) {
strstats[0]++;
@@ -493,6 +518,18 @@ void MSG_WriteScrambledBigString(msg_t* sb, const char* s) {
}
}
#else
void MSG_WriteScrambledString(msg_t* sb, const char* s) {
return MSG_WriteString(sb, s);
}
void MSG_WriteScrambledBigString(msg_t* sb, const char* s) {
return MSG_WriteBigString(sb, s);
}
#endif
void MSG_WriteAngle( msg_t *sb, float f ) {
MSG_WriteByte (sb, (int)(f*256/360) & 255);
}
@@ -598,6 +635,8 @@ float MSG_ReadFloat( msg_t *msg ) {
return dat.f;
}
#if TARGET_GAME_PROTOCOL >= 15
char* MSG_ReadScrambledString(msg_t* msg) {
static char string[MAX_STRING_CHARS];
int l, c;
@@ -610,6 +649,9 @@ char* MSG_ReadScrambledString(msg_t* msg) {
}
c = NetByteToStrChar[c];
if (!c) {
break;
}
// translate all fmt spec to avoid crash bugs
if (c == '%') {
c = '.';
@@ -629,6 +671,52 @@ char* MSG_ReadScrambledString(msg_t* msg) {
return string;
}
char* MSG_ReadScrambledBigString(msg_t* msg) {
static char string[BIG_INFO_STRING];
int l, c;
l = 0;
do {
c = MSG_ReadByte(msg); // use ReadByte so -1 is out of bounds
if (c == -1) {
break;
}
c = NetByteToStrChar[c];
if (!c) {
break;
}
// translate all fmt spec to avoid crash bugs
if (c == '%') {
c = '.';
}
// don't allow higher ascii values
// (su44: this check is missing in MoHAA)
if (c > 127) {
c = '.';
}
string[l] = c;
l++;
} while (l < sizeof(string) - 1);
string[l] = 0;
return string;
}
#else
char* MSG_ReadScrambledString(msg_t* msg) {
return MSG_ReadString(msg);
}
char* MSG_ReadScrambledBigString(msg_t* msg) {
return MSG_ReadBigString(msg);
}
#endif
char *MSG_ReadString( msg_t *msg ) {
static char string[MAX_STRING_CHARS];
int l,c;
@@ -721,7 +809,6 @@ void MSG_GetNullEntityState(entityState_t *nullState) {
nullState->alpha = 1.0f;
nullState->scale = 1.0f;
nullState->parent = ENTITYNUM_NONE;
nullState->tag_num = -1; // su44
nullState->constantLight = 0xffffff;
nullState->renderfx = 16;
nullState->bone_tag[4] = -1;
@@ -1171,6 +1258,157 @@ typedef struct {
// using the stringizing operator to save typing...
#define NETF(x) #x,(size_t)&((entityState_t*)0)->x
#if TARGET_GAME_PROTOCOL >= 15
netField_t entityStateFields[] =
{
{ NETF(netorigin[0]), 0, netFieldType_t::coord },
{ NETF(netorigin[1]), 0, netFieldType_t::coord },
{ NETF(netangles[1]), 12, netFieldType_t::angle },
{ NETF(frameInfo[0].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[1].time), 15, netFieldType_t::animTime },
{ NETF(bone_angles[0][0]), -13, netFieldType_t::angle },
{ NETF(bone_angles[3][0]), -13, netFieldType_t::angle },
{ NETF(bone_angles[1][0]), -13, netFieldType_t::angle },
{ NETF(bone_angles[2][0]), -13, netFieldType_t::angle },
{ NETF(netorigin[2]), 0, netFieldType_t::coord },
{ NETF(frameInfo[0].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[1].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[2].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[3].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[0].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[1].index), 12, netFieldType_t::regular },
{ NETF(actionWeight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[2].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[3].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[2].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[3].index), 12, netFieldType_t::regular },
{ NETF(eType), 8, netFieldType_t::regular },
{ NETF(modelindex), 16, netFieldType_t::regular },
{ NETF(parent), 16, netFieldType_t::regular },
{ NETF(constantLight), 32, netFieldType_t::regular },
{ NETF(renderfx), 32, netFieldType_t::regular },
{ NETF(bone_tag[0]), -8, netFieldType_t::regular },
{ NETF(bone_tag[1]), -8, netFieldType_t::regular },
{ NETF(bone_tag[2]), -8, netFieldType_t::regular },
{ NETF(bone_tag[3]), -8, netFieldType_t::regular },
{ NETF(bone_tag[4]), -8, netFieldType_t::regular },
{ NETF(scale), 10, netFieldType_t::scale },
{ NETF(alpha), 8, netFieldType_t::alpha },
{ NETF(usageIndex), 16, netFieldType_t::regular },
{ NETF(eFlags), 16, netFieldType_t::regular },
{ NETF(solid), 32, netFieldType_t::regular },
{ NETF(netangles[2]), 12, netFieldType_t::angle },
{ NETF(netangles[0]), 12, netFieldType_t::angle },
{ NETF(tag_num), 10, netFieldType_t::regular },
{ NETF(bone_angles[1][2]), -13, netFieldType_t::angle },
{ NETF(attach_use_angles), 1, netFieldType_t::regular },
{ NETF(origin2[1]), 0, netFieldType_t::coord },
{ NETF(origin2[0]), 0, netFieldType_t::coord },
{ NETF(origin2[2]), 0, netFieldType_t::coord },
{ NETF(bone_angles[0][2]), -13, netFieldType_t::angle },
{ NETF(bone_angles[2][2]), -13, netFieldType_t::angle },
{ NETF(bone_angles[3][2]), -13, netFieldType_t::angle },
{ NETF(surfaces[0]), 8, netFieldType_t::regular },
{ NETF(surfaces[1]), 8, netFieldType_t::regular },
{ NETF(surfaces[2]), 8, netFieldType_t::regular },
{ NETF(surfaces[3]), 8, netFieldType_t::regular },
{ NETF(bone_angles[0][1]), -13, netFieldType_t::angle },
{ NETF(surfaces[4]), 8, netFieldType_t::regular },
{ NETF(surfaces[5]), 8, netFieldType_t::regular },
{ NETF(pos.trTime), 32, netFieldType_t::regular },
{ NETF(pos.trDelta[0]), 0, netFieldType_t::velocity },
{ NETF(pos.trDelta[1]), 0, netFieldType_t::velocity },
{ NETF(pos.trDelta[2]), 0, netFieldType_t::velocity },
{ NETF(loopSound), 16, netFieldType_t::regular },
{ NETF(loopSoundVolume), 0, netFieldType_t::regular },
{ NETF(loopSoundMinDist), 0, netFieldType_t::regular },
{ NETF(loopSoundMaxDist), 0, netFieldType_t::regular },
{ NETF(loopSoundPitch), 0, netFieldType_t::regular },
{ NETF(loopSoundFlags), 8, netFieldType_t::regular },
{ NETF(attach_offset[0]), 0, netFieldType_t::regular },
{ NETF(attach_offset[1]), 0, netFieldType_t::regular },
{ NETF(attach_offset[2]), 0, netFieldType_t::regular },
{ NETF(beam_entnum), 16, netFieldType_t::regular },
{ NETF(skinNum), 16, netFieldType_t::regular },
{ NETF(wasframe), 10, netFieldType_t::regular },
{ NETF(frameInfo[4].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[5].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[6].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[7].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[8].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[9].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[10].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[11].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[12].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[13].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[14].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[15].index), 12, netFieldType_t::regular },
{ NETF(frameInfo[4].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[5].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[6].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[7].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[8].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[9].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[10].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[11].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[12].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[13].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[14].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[15].time), 15, netFieldType_t::animTime },
{ NETF(frameInfo[4].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[5].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[6].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[7].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[8].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[9].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[10].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[11].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[12].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[13].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[14].weight), 8, netFieldType_t::animWeight },
{ NETF(frameInfo[15].weight), 8, netFieldType_t::animWeight },
{ NETF(bone_angles[1][1]), -13, netFieldType_t::angle },
{ NETF(bone_angles[2][1]), -13, netFieldType_t::angle },
{ NETF(bone_angles[3][1]), -13, netFieldType_t::angle },
{ NETF(bone_angles[4][0]), -13, netFieldType_t::angle },
{ NETF(bone_angles[4][1]), -13, netFieldType_t::angle },
{ NETF(bone_angles[4][2]), -13, netFieldType_t::angle },
{ NETF(clientNum), 8, netFieldType_t::regular },
{ NETF(groundEntityNum), GENTITYNUM_BITS, netFieldType_t::regular },
{ NETF(shader_data[0]), 0, netFieldType_t::regular },
{ NETF(shader_data[1]), 0, netFieldType_t::regular },
{ NETF(shader_time), 0, netFieldType_t::regular },
{ NETF(eyeVector[0]), 0, netFieldType_t::regular },
{ NETF(eyeVector[1]), 0, netFieldType_t::regular },
{ NETF(eyeVector[2]), 0, netFieldType_t::regular },
{ NETF(surfaces[6]), 8, netFieldType_t::regular },
{ NETF(surfaces[7]), 8, netFieldType_t::regular },
{ NETF(surfaces[8]), 8, netFieldType_t::regular },
{ NETF(surfaces[9]), 8, netFieldType_t::regular },
{ NETF(surfaces[10]), 8, netFieldType_t::regular },
{ NETF(surfaces[11]), 8, netFieldType_t::regular },
{ NETF(surfaces[12]), 8, netFieldType_t::regular },
{ NETF(surfaces[13]), 8, netFieldType_t::regular },
{ NETF(surfaces[14]), 8, netFieldType_t::regular },
{ NETF(surfaces[15]), 8, netFieldType_t::regular },
{ NETF(surfaces[16]), 8, netFieldType_t::regular },
{ NETF(surfaces[17]), 8, netFieldType_t::regular },
{ NETF(surfaces[18]), 8, netFieldType_t::regular },
{ NETF(surfaces[19]), 8, netFieldType_t::regular },
{ NETF(surfaces[20]), 8, netFieldType_t::regular },
{ NETF(surfaces[21]), 8, netFieldType_t::regular },
{ NETF(surfaces[22]), 8, netFieldType_t::regular },
{ NETF(surfaces[23]), 8, netFieldType_t::regular },
{ NETF(surfaces[24]), 8, netFieldType_t::regular },
{ NETF(surfaces[25]), 8, netFieldType_t::regular },
{ NETF(surfaces[26]), 8, netFieldType_t::regular },
{ NETF(surfaces[27]), 8, netFieldType_t::regular },
{ NETF(surfaces[28]), 8, netFieldType_t::regular },
{ NETF(surfaces[29]), 8, netFieldType_t::regular },
{ NETF(surfaces[30]), 8, netFieldType_t::regular },
{ NETF(surfaces[31]), 8, netFieldType_t::regular }
};
#else
netField_t entityStateFields[] =
{
{ NETF(netorigin[0]), 0, netFieldType_t::coord },
@@ -1320,6 +1558,7 @@ netField_t entityStateFields[] =
{ NETF(surfaces[30]), 8, netFieldType_t::regular },
{ NETF(surfaces[31]), 8, netFieldType_t::regular }
};
#endif
static constexpr unsigned long numEntityFields = sizeof(entityStateFields) / sizeof(entityStateFields[0]);
// if (int)f == f and (int)f + ( 1<<(FLOAT_INT_BITS-1) ) < ( 1 << FLOAT_INT_BITS )
@@ -1343,22 +1582,25 @@ void MSG_ReadRegular(msg_t* sb, int bits, void* toF)
if (!MSG_ReadBits(sb, 1))
{
// integral float
int32_t truncFloat = MSG_ReadBits(sb, -FLOAT_INT_BITS);
// bias to allow equal parts positive and negative
truncFloat -= FLOAT_INT_BIAS;
*(float*)toF = (float)truncFloat;
*(float*)toF = MSG_ReadBits(sb, -FLOAT_INT_BITS);
}
else
{
// full floating point value
*(float*)toF = MSG_ReadFloat(sb);
unsigned int v = MSG_ReadBits(sb, 32);
if (v & 1) {
*(int*)toF = ((v + 0x7A000000) >> 1) | 0x80000000;
}
else {
*(int*)toF = (v + 0x7A000000) >> 1;
}
}
}
}
else
{
if (MSG_ReadBits(msg, 1)) {
*(int*)toF = MSG_ReadBits(msg, bits);
if (MSG_ReadBits(sb, 1)) {
*(int*)toF = MSG_ReadBits(sb, bits);
}
else {
*(int*)toF = 0;
@@ -1366,6 +1608,11 @@ void MSG_ReadRegular(msg_t* sb, int bits, void* toF)
}
}
void MSG_ReadRegularSimple(msg_t* sb, int bits, void* toF)
{
MSG_ReadRegular(sb, bits, toF);
}
void MSG_WriteRegular(msg_t* sb, int bits, const void* toF)
{
float fullFloat;
@@ -1382,16 +1629,19 @@ void MSG_WriteRegular(msg_t* sb, int bits, const void* toF)
}
else {
MSG_WriteBits(sb, 1, 1);
if (trunc == fullFloat && trunc + FLOAT_INT_BIAS >= 0 &&
trunc + FLOAT_INT_BIAS < (1 << FLOAT_INT_BITS)) {
if (trunc == fullFloat && trunc >= -4096 && trunc < 4096) {
// send as small integer
MSG_WriteBits(sb, 0, 1);
MSG_WriteBits(sb, trunc + FLOAT_INT_BIAS, FLOAT_INT_BITS);
MSG_WriteBits(sb, trunc, -FLOAT_INT_BITS);
}
else {
// send as full floating point value
int newvalue = *(int*)toF * 2 - 0x7A000000;
if (*(int*)toF < 0) {
newvalue |= 1;
}
MSG_WriteBits(sb, 1, 1);
MSG_WriteBits(sb, *(int*)toF, 32);
// send as full floating point value
MSG_WriteBits(sb, newvalue, 32);
}
}
}
@@ -1418,9 +1668,9 @@ void MSG_WriteEntityNum(msg_t* sb, short number)
MSG_WriteBits(sb, (number + 1) % MAX_GENTITIES, GENTITYNUM_BITS);
}
short MSG_ReadEntityNum(msg_t* sb)
unsigned short MSG_ReadEntityNum(msg_t* sb)
{
return (MSG_ReadBits(sb, GENTITYNUM_BITS) - 1) % MAX_GENTITIES;
return (unsigned short)(MSG_ReadBits(sb, GENTITYNUM_BITS) - 1) % MAX_GENTITIES;
}
#else
@@ -1436,7 +1686,7 @@ void MSG_ReadRegular(msg_t* sb, int bits, void* toF)
else
{
if (!MSG_ReadBits(sb, 1)) {
*(float*)toF = (float)MSG_ReadBits(sb, FLOAT_INT_BITS);
*(float*)toF = (int)MSG_ReadBits(sb, FLOAT_INT_BITS) - FLOAT_INT_BIAS;
}
else
{
@@ -1456,6 +1706,28 @@ void MSG_ReadRegular(msg_t* sb, int bits, void* toF)
}
}
void MSG_ReadRegularSimple(msg_t* sb, int bits, void* toF)
{
if (bits == 0) {
// float
if (MSG_ReadBits(sb, 1) == 0) {
// integral float
int trunc = MSG_ReadBits(sb, FLOAT_INT_BITS);
// bias to allow equal parts positive and negative
trunc -= FLOAT_INT_BIAS;
*(float*)toF = trunc;
}
else {
// full floating point value
*(int*)toF = MSG_ReadBits(sb, 32);
}
}
else {
// integer
*(int*)toF = MSG_ReadBits(sb, bits);
}
}
void MSG_WriteRegular(msg_t* sb, int bits, const void* toF)
{
float fullFloat;
@@ -1530,7 +1802,7 @@ void MSG_WriteEntityNum(msg_t* sb, short number)
MSG_WriteBits(sb, number % MAX_GENTITIES, GENTITYNUM_BITS);
}
short MSG_ReadEntityNum(msg_t* sb)
unsigned short MSG_ReadEntityNum(msg_t* sb)
{
return MSG_ReadBits(sb, GENTITYNUM_BITS) % MAX_GENTITIES;
}
@@ -1568,7 +1840,7 @@ void MSG_WriteDeltaEntity( msg_t *msg, struct entityState_s *from, struct entity
if ( from == NULL ) {
return;
}
MSG_WriteBits( msg, from->number, GENTITYNUM_BITS );
MSG_WriteEntityNum(msg, from->number);
MSG_WriteBits( msg, 1, 1 );
return;
}
@@ -1813,19 +2085,69 @@ int MSG_PackCoordExtra(float coord)
#if TARGET_GAME_PROTOCOL >= 15
float MSG_ReadPackedAngle(msg_t* msg, int bits)
{
int packed = MSG_ReadBits(msg, abs(bits));
return MSG_UnpackAngle(packed, bits);
}
float MSG_ReadPackedAnimTime(msg_t* msg, int bits, float fromValue, float frameTime)
{
int packed;
if (!MSG_ReadBits(msg, 1)) {
return fromValue + frameTime;
}
packed = MSG_ReadBits(msg, bits);
return MSG_UnpackAnimTime(packed);
}
float MSG_ReadPackedAnimWeight(msg_t* msg, int bits)
{
int packed = MSG_ReadBits(msg, bits);
return MSG_UnpackAnimWeight(packed, bits);
}
float MSG_ReadPackedScale(msg_t* msg, int bits)
{
int packed = MSG_ReadBits(msg, bits);
return MSG_UnpackScale(packed);
}
float MSG_ReadPackedAlpha(msg_t* msg, int bits)
{
int packed = MSG_ReadBits(msg, bits);
return MSG_UnpackAlpha(packed, bits);
}
float MSG_ReadPackedCoord(msg_t* msg, float fromValue, int bits)
{
int packedFrom = MSG_PackCoord(fromValue);
int packedTo = MSG_ReadDeltaCoord(msg, packedFrom);
return MSG_UnpackCoord(packedTo, bits);
}
float MSG_ReadPackedCoordExtra(msg_t* msg, float fromValue, int bits)
{
int packedFrom = MSG_PackCoordExtra(fromValue);
int packedTo = MSG_ReadDeltaCoordExtra(msg, packedFrom);
return MSG_UnpackCoordExtra(packedTo, bits);
}
void MSG_WritePackedAngle(msg_t* msg, float value, int bits)
{
int packed = MSG_PackAngle(value, bits);
MSG_WriteBits(msg, packed, bits);
MSG_WriteBits(msg, packed, abs(bits));
}
void MSG_WritePackedAnimTime(msg_t* msg, float fromValue, float toValue, float frameTime, int bits)
{
int packed;
if (abs(fromValue - toValue) < frameTime) {
if (fabs(fromValue - toValue) < frameTime) {
// below the frame time, don't send
MSG_WriteBits(msg, 0, 1);
return;
}
MSG_WriteBits(msg, 1, 1);
@@ -1923,6 +2245,80 @@ qboolean MSG_DeltaNeeded(const void* fromField, const void* toField, int fieldTy
#else
float MSG_ReadPackedAngle(msg_t* msg, int bits)
{
int result;
float tmp = 1.0f;
if (bits < 0) {
if (MSG_ReadBits(msg, 1))
tmp = -1.0f;
bits = ~bits;
}
result = MSG_ReadBits(msg, bits);
switch (bits)
{
case 8:
return tmp * 360.f / 256.f;
case 12:
return tmp * result * 360.f / 4096.f;
case 16:
return tmp * result * 360.f / 65536.f;
default:
return tmp * 360.f / (1 << bits) * result;
}
}
float MSG_ReadPackedAnimTime(msg_t* msg, int bits, float fromValue, float frameTime)
{
return MSG_ReadBits(msg, 15) / 100.0f;
}
float MSG_ReadPackedAnimWeight(msg_t* msg, int bits)
{
float tmp = MSG_ReadBits(msg, 8) / 255.0f;
if (tmp < 0.0f)
return 0.0f;
else if (tmp > 1.0f)
return 1.0f;
else
return tmp;
}
float MSG_ReadPackedScale(msg_t* msg, int bits)
{
return MSG_ReadBits(msg, 10) / 100.0f;
}
float MSG_ReadPackedAlpha(msg_t* msg, int bits)
{
float tmp = MSG_ReadBits(msg, 8) / 255.0f;
if (tmp < 0.0f)
return 0.0f;
else if (tmp > 1.0f)
return 1.0f;
else
return tmp;
}
float MSG_ReadPackedCoord(msg_t* msg, float fromValue, int bits)
{
float tmp = 1.0f;
int value = MSG_ReadBits(msg, 19);
if (value & 262144) // test for 19th bit
tmp = -1.0f;
value &= ~262144; // remove that bit
return tmp * value / 16.0f;
}
float MSG_ReadPackedCoordExtra(msg_t* msg, float fromValue, int bits)
{
int packedFrom = MSG_PackCoordExtra(fromValue);
int packedTo = MSG_ReadDeltaCoordExtra(msg, packedFrom);
return MSG_UnpackCoordExtra(packedTo, bits);
}
void MSG_WritePackedAngle(msg_t* msg, float value, int bits)
{
// angles, what a mess! it wouldnt surprise me if something goes wrong here ;)
@@ -2044,6 +2440,25 @@ qboolean MSG_DeltaNeeded(const void* fromField, const void* toField, int fieldTy
#endif
float MSG_ReadPackedVelocity(msg_t* msg, int bits)
{
float tmp = 1.0f;
int value = MSG_ReadBits(msg, 17);
if (value & 65536) // test for 17th bit
tmp = -1.0f;
value &= ~65536; // remove that bit
return tmp * value / 8.0f;
}
int MSG_ReadPackedSimple(msg_t* msg, int fromValue, int bits)
{
if (!MSG_ReadBits(msg, 1)) {
return fromValue;
}
return MSG_ReadBits(msg, bits);
}
void MSG_WritePackedVelocity(msg_t* msg, float value, int bits)
{
int32_t packed = (uint32_t)(value * 8.0f);
@@ -2159,99 +2574,34 @@ void MSG_ReadDeltaEntity( msg_t *msg, entityState_t *from, entityState_t *to,
} else {
switch (field->type) {
case netFieldType_e::regular:
if ( field->bits == 0 ) {
// float
if ( MSG_ReadBits( msg, 1 ) == 0 ) {
*(float *)toF = 0.0f;
} else {
if ( MSG_ReadBits( msg, 1 ) == 0 ) {
// integral float
trunc = MSG_ReadBits( msg, FLOAT_INT_BITS );
// bias to allow equal parts positive and negative
trunc -= FLOAT_INT_BIAS;
*(float *)toF = trunc;
if ( print ) {
Com_Printf( "%s:%i ", field->name, trunc );
}
} else {
// full floating point value
*toF = MSG_ReadBits( msg, 32 );
if ( print ) {
Com_Printf( "%s:%f ", field->name, *(float *)toF );
}
}
}
} else {
if ( MSG_ReadBits( msg, 1 ) == 0 ) {
*toF = 0;
} else {
// integer
*toF = MSG_ReadBits( msg, field->bits );
if ( print ) {
Com_Printf( "%s:%i ", field->name, *toF );
}
}
}
MSG_ReadRegular(msg, field->bits, toF);
break;
case netFieldType_e::angle: // angles, what a mess! it wouldnt surprise me if something goes wrong here ;)
tmp = 1.0f;
if ( field->bits < 0 ) {
if ( MSG_ReadBits( msg, 1 ) )
tmp = -1.0f;
bits = ~field->bits;
}
else bits = field->bits;
result = MSG_ReadBits( msg, bits );
if ( bits == 12 )
*(float *)toF = result * 0.087890625f * tmp;
else if ( bits == 8 )
*(float *)toF = result * 1.411764705882353f * tmp;
else if ( bits == 16 )
*(float *)toF = result * 0.0054931640625f * tmp;
else
*(float *)toF = result * (1 << bits) * tmp / 360.0f;
*(float*)toF = MSG_ReadPackedAngle(msg, field->bits);
break;
case netFieldType_e::animTime: // time
*(float *)toF = MSG_ReadBits( msg, 15 ) * 0.0099999998f;
*(float*)toF = MSG_ReadPackedAnimTime(msg, field->bits, *(float*)fromF, frameTime);
break;
case netFieldType_e::animWeight: // nasty!
tmp = MSG_ReadBits( msg, 8 ) / 255.0f;
if ( tmp < 0.0f )
*(float *)toF = 0.0f;
else if ( tmp > 1.0f )
*(float *)toF = 1.0f;
else
*(float *)toF = tmp;
// FPU instructions yay
*(float*)toF = MSG_ReadPackedAnimWeight(msg, field->bits);
break;
case netFieldType_e::scale:
*(float *)toF = MSG_ReadBits( msg, 10 ) *0.0099999998f;
*(float*)toF = MSG_ReadPackedScale(msg, field->bits);
break;
case netFieldType_e::alpha:
tmp = MSG_ReadBits( msg, 8 ) / 255.0f;
if ( tmp < 0.0f )
*(float *)toF = 0.0f;
else if ( tmp > 1.0f )
*(float *)toF = 1.0f;
else
*(float *)toF = tmp;
*(float*)toF = MSG_ReadPackedAlpha(msg, field->bits);
break;
case netFieldType_e::coord:
tmp = 1.0f;
bits = MSG_ReadBits( msg, 19 );
if ( bits & 262144 ) // test for 19th bit
tmp = -1.0f;
bits &= ~262144; // remove that bit
*(float *)toF = tmp * bits / 16.0f;
*(float*)toF = MSG_ReadPackedCoord(msg, *(float*)fromF, field->bits);
break;
case netFieldType_e::coordExtra:
*(float*)toF = MSG_ReadPackedCoordExtra(msg, *(float*)fromF, field->bits);
break;
case netFieldType_e::velocity:
tmp = 1.0f;
bits = MSG_ReadBits( msg, 17 );
if ( bits & 65536 ) // test for 17th bit
tmp = -1.0f;
bits &= ~65536; // remove that bit
*(float *)toF = tmp * bits / 8.0f;
*(float*)toF = MSG_ReadPackedVelocity(msg, field->bits);
break;
case netFieldType_e::simple:
*(int*)toF = MSG_ReadPackedSimple(msg, *(int*)fromF, field->bits);
break;
default:
Com_Error( ERR_DROP, "MSG_ReadDeltaEntity: unrecognized entity field type %i for field\n", i );
@@ -2329,6 +2679,16 @@ float MSG_UnpackAnimTime(int packed)
return packed / 100.f;
}
float MSG_UnpackAnimWeight(int result, int bits)
{
const int32_t max = (1 << bits) - 1;
const float tmp = (float)result / (float)max;
if (tmp < 0.0f) return 0.f;
else if (tmp > 1.0f) return 1.f;
else return tmp;
}
float MSG_UnpackScale(int packed)
{
return packed / 100.f;
@@ -2501,6 +2861,66 @@ plyer_state_t communication
// using the stringizing operator to save typing...
#define PSF(x) #x,(size_t)&((playerState_t*)0)->x
#if TARGET_GAME_PROTOCOL >= 15
netField_t playerStateFields[] =
{
{ PSF(commandTime), 32, netFieldType_t::regular },
{ PSF(origin[0]), 0, netFieldType_t::coordExtra },
{ PSF(origin[1]), 0, netFieldType_t::coordExtra },
{ PSF(viewangles[1]), 0, netFieldType_t::regular },
{ PSF(velocity[1]), 0, netFieldType_t::velocity },
{ PSF(velocity[0]), 0, netFieldType_t::velocity },
{ PSF(viewangles[0]), 0, netFieldType_t::regular },
{ PSF(origin[2]), 0, netFieldType_t::coordExtra },
{ PSF(velocity[2]), 0, netFieldType_t::velocity },
{ PSF(iViewModelAnimChanged), 2, netFieldType_t::regular },
{ PSF(damage_angles[0]), -13, netFieldType_t::angle },
{ PSF(damage_angles[1]), -13, netFieldType_t::angle },
{ PSF(damage_angles[2]), -13, netFieldType_t::angle },
{ PSF(speed), 16, netFieldType_t::regular },
{ PSF(delta_angles[1]), 16, netFieldType_t::regular },
{ PSF(viewheight), -8, netFieldType_t::regular },
{ PSF(groundEntityNum), GENTITYNUM_BITS, netFieldType_t::regular },
{ PSF(delta_angles[0]), 16, netFieldType_t::regular },
{ PSF(iViewModelAnim), 4, netFieldType_t::regular },
{ PSF(fov), 0, netFieldType_t::regular },
{ PSF(current_music_mood), 8, netFieldType_t::regular },
{ PSF(gravity), 16, netFieldType_t::regular },
{ PSF(fallback_music_mood), 8, netFieldType_t::regular },
{ PSF(music_volume), 0, netFieldType_t::regular },
{ PSF(pm_flags), 16, netFieldType_t::regular },
{ PSF(clientNum), 8, netFieldType_t::regular },
{ PSF(fLeanAngle), 0, netFieldType_t::regular },
{ PSF(blend[3]), 0, netFieldType_t::regular },
{ PSF(blend[0]), 0, netFieldType_t::regular },
{ PSF(pm_type), 8, netFieldType_t::regular },
{ PSF(feetfalling), 8, netFieldType_t::regular },
{ PSF(radarInfo), 26, netFieldType_t::regular },
{ PSF(camera_angles[0]), 16, netFieldType_t::angle },
{ PSF(camera_angles[1]), 16, netFieldType_t::angle },
{ PSF(camera_angles[2]), 16, netFieldType_t::angle },
{ PSF(camera_origin[0]), 0, netFieldType_t::coordExtra },
{ PSF(camera_origin[1]), 0, netFieldType_t::coordExtra },
{ PSF(camera_origin[2]), 0, netFieldType_t::coordExtra },
{ PSF(camera_posofs[0]), 0, netFieldType_t::coordExtra },
{ PSF(camera_posofs[2]), 0, netFieldType_t::coordExtra },
{ PSF(camera_time), 0, netFieldType_t::regular },
{ PSF(voted), 1, netFieldType_t::regular },
{ PSF(bobCycle), 8, netFieldType_t::regular },
{ PSF(delta_angles[2]), 16, netFieldType_t::regular },
{ PSF(viewangles[2]), 0, netFieldType_t::regular },
{ PSF(music_volume_fade_time), 0, netFieldType_t::regular },
{ PSF(reverb_type), 6, netFieldType_t::regular },
{ PSF(reverb_level), 0, netFieldType_t::regular },
{ PSF(blend[1]), 0, netFieldType_t::regular },
{ PSF(blend[2]), 0, netFieldType_t::regular },
{ PSF(camera_offset[0]), 0, netFieldType_t::regular },
{ PSF(camera_offset[1]), 0, netFieldType_t::regular },
{ PSF(camera_offset[2]), 0, netFieldType_t::regular },
{ PSF(camera_posofs[1]), 0, netFieldType_t::coordExtra },
{ PSF(camera_flags), 16, netFieldType_t::regular }
};
#else
netField_t playerStateFields[] =
{
{ PSF(commandTime), 32, netFieldType_t::regular },
@@ -2559,6 +2979,7 @@ netField_t playerStateFields[] =
{ PSF(camera_posofs[1]), 0, netFieldType_t::coord },
{ PSF(camera_flags), 16, netFieldType_t::regular }
};
#endif
/*
=============
@@ -2793,80 +3214,29 @@ void MSG_ReadDeltaPlayerstate(msg_t *msg, playerState_t *from, playerState_t *to
numFields = sizeof( playerStateFields ) / sizeof( playerStateFields[0] );
lc = MSG_ReadByte(msg);
//Com_DPrintf( "===\nMSG_ReadDeltaPlayerstate: count %i\n===\n", lc );
assert(lc <= numFields);
for ( i = 0, field = playerStateFields ; i < lc ; i++, field++ ) {
fromF = (int *)( (byte *)from + field->offset );
toF = (int *)( (byte *)to + field->offset );
//Com_DPrintf( "field %s ", field->name );
if ( ! MSG_ReadBits( msg, 1 ) ) {
// no change
*toF = *fromF;
//Com_DPrintf( "NO CHANGE " );
//Com_DPrintf( "value int %i, float %f\n", *toF, *(float *)toF );
} else {
//Com_DPrintf( "type %i, ", field->type );
switch ( field->type ) {
case netFieldType_e::regular:
if ( field->bits == 0 ) {
// float
if ( MSG_ReadBits( msg, 1 ) == 0 ) {
// integral float
trunc = MSG_ReadBits( msg, FLOAT_INT_BITS );
// bias to allow equal parts positive and negative
trunc -= FLOAT_INT_BIAS;
*(float *)toF = trunc;
if ( print ) {
Com_Printf( "%s:%i ", field->name, trunc );
}
} else {
// full floating point value
*toF = MSG_ReadBits( msg, 32 );
if ( print ) {
Com_Printf( "%s:%f ", field->name, *(float *)toF );
}
}
} else {
// integer
*toF = MSG_ReadBits( msg, field->bits );
if ( print ) {
Com_Printf( "%s:%i ", field->name, *toF );
}
}
MSG_ReadRegularSimple(msg, field->bits, toF);
break;
case netFieldType_e::angle:
tmp = 1.0f;
if ( field->bits < 0 ) {
if ( MSG_ReadBits( msg, 1 ) )
tmp = -1.0f;
bits = - field->bits -1;
}
else bits = field->bits;
result = MSG_ReadBits( msg, bits );
if ( field->bits == 12 )
*(float *)toF = result * 0.087890625f * tmp;
else if ( field->bits == 8 )
*(float *)toF = result * 1.411764705882353f * tmp;
else if ( field->bits == 16 )
*(float *)toF = result * 0.0054931640625f * tmp;
else
*(float *)toF = result * (1 << bits) * tmp / 360.0f;
*(float*)toF = MSG_ReadPackedAngle(msg, field->bits);
break;
case netFieldType_e::coord:
tmp = 1.0f;
bits = MSG_ReadBits( msg, 19 );
if ( bits & 262144 ) // test for 19th bit
tmp = -1.0f;
bits &= ~262144; // 4294705151; // remove that bit
*(float *)toF = tmp * bits / 16.0f;
*(float*)toF = MSG_ReadPackedCoord(msg, *(float*)fromF, field->bits);
break;
case netFieldType_e::coordExtra:
*(float*)toF = MSG_ReadPackedCoordExtra(msg, *(float*)fromF, field->bits);
break;
case netFieldType_e::velocity:
tmp = 1.0f;
bits = MSG_ReadBits( msg, 17 );
if ( bits & 65536 ) // test for 17th bit
tmp = -1.0f;
bits &= ~65536; // 4294901759; // remove that bit
*(float *)toF = tmp * bits / 8.0f;
*(float*)toF = MSG_ReadPackedVelocity(msg, field->bits);
break;
default:
break;
+8
View File
@@ -346,6 +346,8 @@ short ShortSwapPtr(const void* l);
int LongSwapPtr(const void* l);
short ShortNoSwapPtr(const void* l);
int LongNoSwapPtr(const void* l);
float FloatSwapPtr(const void* l);
float FloatNoSwapPtr(const void* l);
#if defined( Q3_BIG_ENDIAN ) && defined( Q3_LITTLE_ENDIAN )
#error "Endianness defined as both big and little"
@@ -354,11 +356,16 @@ int LongNoSwapPtr(const void* l);
#define CopyLittleShort(dest, src) CopyShortSwap(dest, src)
#define CopyLittleLong(dest, src) CopyLongSwap(dest, src)
//
// Those Little*Ptr are used to avoid alignment problems
//
#define LittleShort(x) ShortSwap(x)
#define LittleLong(x) LongSwap(x)
#define LittleFloat(x) FloatSwap(&x)
#define LittleShortPtr(x) ShortSwapPtr(&x)
#define LittleLongPtr(x) LongSwapPtr(&x)
#define LittleFloatPtr(x) FloatSwapPtr(&x)
#define BigShort
#define BigLong
@@ -376,6 +383,7 @@ int LongNoSwapPtr(const void* l);
#define LittleFloat
#define LittleShortPtr(x) ShortNoSwapPtr(&x)
#define LittleLongPtr(x) LongNoSwapPtr(&x)
#define LittleFloatPtr(x) FloatNoSwapPtr(&x)
#define BigShort(x) ShortSwap(x)
#define BigLong(x) LongSwap(x)
+14
View File
@@ -1552,6 +1552,20 @@ int LongNoSwapPtr(const void* l)
return out;
}
float FloatSwapPtr(const void* l)
{
float out;
CopyLittleLong((int*)&out, l);
return out;
}
float FloatNoSwapPtr(const void* l)
{
float out;
Com_Memcpy(&out, l, sizeof(float));
return out;
}
void Swap_Init(void)
{
// Endianness is now computed at compile time
+83 -100
View File
@@ -29,14 +29,38 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
extern "C" {
#endif
#define PRODUCT_NAME "OpenMoHAA"
#define PRODUCT_VERSION "0.49-alpha"
#define PRODUCT_DATE __DATE__
#define PRODUCT_NAME "OpenMoHAA"
//
// Version
//
// These values are the only one that must be set for the version
#define PRODUCT_VERSION_MAJOR 0
#define PRODUCT_VERSION_MINOR 53
#define PRODUCT_VERSION_PATCH 2
#define PRODUCT_VERSION_STAGE "alpha"
//
// Version display
//
#define PRODUCT_VERSION_NUMBER_STRING XSTRING(PRODUCT_VERSION_MAJOR) "." XSTRING(PRODUCT_VERSION_MINOR) "." XSTRING(PRODUCT_VERSION_PATCH)
#define PRODUCT_VERSION PRODUCT_VERSION_NUMBER_STRING "-" PRODUCT_VERSION_STAGE
#define PRODUCT_DATE __DATE__
#define BASEGAME "main"
//
// The target type specifies which content pack the engine targets.
//
// Note: An universal client is not currently possible without refactoring the network and the file system.
// Pak files must be reloaded on-the-fly depending on the server the client is connecting to.
//
#if TARGET_GAME_TYPE == 1
//
// Team Assault
#define BASEGAME "mainta"
#define PRODUCT_EXTENSION "Spearhead"
//
#define GAME_EXTENSION_BASE "mainta"
#define PRODUCT_EXTENSION "spearhead"
// The version string must be equal or above 2.0 to be able to connect to spearhead servers
#define TARGET_GAME_VERSION "2.16"
#define TARGET_GAME_PROTOCOL 17
@@ -46,10 +70,12 @@ extern "C" {
#define HOMEPATH_NAME_WIN "mohta"
#define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN
#elif TARGET_GAME_TYPE == 2
//
// Team Tactics
#define BASEGAME "maintt"
#define PRODUCT_EXTENSION "Breakthrough"
// The version string must be equal or above 2.0 to be able to connect to breakthrough servers
//
#define GAME_EXTENSION_BASE "maintt"
#define PRODUCT_EXTENSION "breakthrough"
// The version string must be equal or above 2.0 to be able to connect to breakthrough servers
#define TARGET_GAME_VERSION "2.41"
#define TARGET_GAME_PROTOCOL 17
#define TARGET_GAME_NAME "mohaab"
@@ -58,11 +84,13 @@ extern "C" {
#define HOMEPATH_NAME_WIN "mohtt"
#define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN
#else
// The default: the base game (no expansion)
#define BASEGAME "main"
#define PRODUCT_EXTENSION "Base"
// The version string must be below 1.12, otherwise it's not possible to connect
//
// Base game
//
#define GAME_EXTENSION_BASE "main"
#define PRODUCT_EXTENSION "base"
// The version string must be 1.1x or below, otherwise it's not possible to connect
#define TARGET_GAME_VERSION "1.12"
#define TARGET_GAME_PROTOCOL 8
#define TARGET_GAME_NAME "mohaa"
@@ -72,11 +100,11 @@ extern "C" {
#define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN
#endif
#define PRODUCT_NAME_FULL PRODUCT_NAME ": " PRODUCT_EXTENSION
#define PRODUCT_VERSION_FULL PRODUCT_VERSION " (for " TARGET_GAME_VERSION ")"
#define PRODUCT_NAME_FULL PRODUCT_NAME " - v" PRODUCT_VERSION " - ext-" PRODUCT_EXTENSION
#define PRODUCT_VERSION_FULL PRODUCT_NAME_FULL
#define CLIENT_WINDOW_TITLE "OpenMoHAA"
#define CLIENT_WINDOW_MIN_TITLE "OpenMoHAA"
#define CLIENT_WINDOW_TITLE PRODUCT_NAME
#define CLIENT_WINDOW_MIN_TITLE PRODUCT_NAME
#define MAX_TEAMNAME 32
@@ -426,6 +454,7 @@ enum {
MESSAGE_CHAT_WHITE,
MESSAGE_WHITE,
MESSAGE_CHAT_RED,
MESSAGE_CHAT_GREEN,
MESSAGE_MAX
};
@@ -456,34 +485,6 @@ enum {
#define HUD_MESSAGE_CHAT_WHITE "\x02"
#define HUD_MESSAGE_CHAT_RED "\x04"
#define CGM_HUDDRAW_SHADER 27
#define CGM_HUDDRAW_ALIGN 28
#define CGM_HUDDRAW_RECT 29
#define CGM_HUDDRAW_VIRTUALSIZE 30
#define CGM_HUDDRAW_COLOR 31
#define CGM_HUDDRAW_ALPHA 32
#define CGM_HUDDRAW_STRING 33
#define CGM_HUDDRAW_FONT 34
#define CGM_HUDDRAW_TIMER 38
#define CGM_HUDDRAW_3D 39
#define CGM_HUDDRAW_BREAK3D 40
#define CGM_HUDDRAW_FADE 41
#define CGM_HUDDRAW_MOVE 42
#define CGM_HUDDRAW_SCALE 43
#define CGM_VIEWMODELANIM 44
#define CGM_VIEWMODELPREFIX 45
#define CGM_MODHEIGHTFLOAT 46
#define CGM_SETVMASPEED 47
#define CGM_HINTSTRING 48
#define CGM_PLAYLOCALSOUND 49
#define CGM_SETLOCALSOUNDRATE 50
#define CGM_STOPLOCALSOUND 51
#define CGM_HUDDRAW_RECTX 52
#define CGM_HUDDRAW_RECTY 53
#define CGM_HUDDRAW_RECTWH 54
#define CGM_REPLICATION 55
#define CGM_HUDDRAW_DELETE 56
extern vec4_t g_color_table[8];
#define MAKERGB( v, r, g, b ) v[0]=r;v[1]=g;v[2]=b
@@ -501,11 +502,11 @@ extern vec4_t g_color_table[8];
#define LERP( a, b, w ) ( ( a ) * ( 1.0f - ( w ) ) + ( b ) * ( w ) )
#define LUMA( red, green, blue ) ( 0.2126f * ( red ) + 0.7152f * ( green ) + 0.0722f * ( blue ) )
#ifndef min
#define min(a,b) (((a) < (b)) ? (a) : (b))
#ifndef Q_min
#define Q_min(a,b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef max
#define max(a,b) (((a) > (b)) ? (a) : (b))
#ifndef Q_max
#define Q_max(a,b) (((a) > (b)) ? (a) : (b))
#endif
#define bound(a,minval,maxval) ( ((a) > (minval)) ? ( ((a) < (maxval)) ? (a) : (maxval) ) : (minval) )
@@ -1597,7 +1598,7 @@ typedef enum
#define RESERVED_CONFIGSTRINGS 2 // game can't modify below this, only the system can
#define MAX_GAMESTATE_CHARS 32000
#define MAX_GAMESTATE_CHARS 41952
typedef struct {
int stringOffsets[MAX_CONFIGSTRINGS];
char stringData[MAX_GAMESTATE_CHARS];
@@ -1608,7 +1609,7 @@ typedef struct {
// maybe this is better put somewhere else...
typedef struct server_sound_s {
float origin[3];
vec3_t origin;
int entity_number;
int channel;
short int sound_index;
@@ -1703,6 +1704,11 @@ typedef struct playerState_s {
float camera_posofs[3];
int camera_flags;
float damage_angles[3];
// --
// Team Assault
int radarInfo;
qboolean voted;
// --
// not communicated over the net at all
int ping; // server to game info for scoreboard
@@ -1712,44 +1718,29 @@ typedef struct playerState_s {
//====================================================================
#define BUTTON_ATTACKRIGHT_BITINDEX 0
#define BUTTON_ATTACKLEFT_BITINDEX 1
#define BUTTON_SNEAK_BITINDEX 2
#define BUTTON_RUN_BITINDEX 3
#define BUTTON_HOLSTERWEAPON_BITINDEX 4
#define BUTTON_USE_BITINDEX 5
#define BUTTON_TALK_BITINDEX 6 // displays talk balloon and disables actions
#define BUTTON_ANY_BITINDEX 11 // any key whatsoever
#define BUTTON_MOUSE_BITINDEX 14 // mouse move
//
// usercmd_t->button bits, many of which are generated by the client system,
// so they aren't game/cgame only definitions
// so they aren't game-only definitions
//
#define BUTTON_ATTACK 1 // +/-attackprimary
#define BUTTON_ATTACK2 2 // +/-attacksecondary
#define BUTTON_RUN 4 // +/-speed
// walking can't just be infered from MOVE_RUN
// because a key pressed late in the frame will
// only generate a small move value for that frame
// walking will use different animations and
// won't generate footsteps
#define BUTTON_ATTACKLEFT_BITINDEX 0
#define BUTTON_ATTACKRIGHT_BITINDEX 1
#define BUTTON_RUN_BITINDEX 2
#define BUTTON_USE_BITINDEX 3
#define BUTTON_LEAN_LEFT_BITINDEX 4
#define BUTTON_LEAN_RIGHT_BITINDEX 5
#define BUTTON_TALK_BITINDEX 6 // displays talk balloon and disables actions
#define BUTTON_ANY_BITINDEX 14 // any key whatsoever
#define BUTTON_MOUSE_BITINDEX 15 // mouse move
#define BUTTON_USE 8
#define BUTTON_LEANLEFT 16 // +/-leanleft
#define BUTTON_LEANRIGHT 32 // +/-leanright
#define BUTTON_NEGATIVE 64
#define BUTTON_GETFLAG 128
#define BUTTON_GUARDBASE 256
#define BUTTON_PATROL 512
#define BUTTON_FOLLOWME 1024
#define BUTTON_HOLSTER 32768
#define BUTTON_TALK ( 1 << BUTTON_TALK_BITINDEX ) // displays talk balloon and disables actions
#define BUTTON_ANY ( 1 << BUTTON_ANY_BITINDEX ) // any key whatsoever
#define BUTTON_MOUSE ( 1 << BUTTON_MOUSE_BITINDEX )
#define BUTTON_ATTACKLEFT (1 << BUTTON_ATTACKLEFT_BITINDEX)
#define BUTTON_ATTACKRIGHT (1 << BUTTON_ATTACKRIGHT_BITINDEX)
#define BUTTON_RUN (1 << BUTTON_RUN_BITINDEX)
#define BUTTON_USE (1 << BUTTON_USE_BITINDEX)
#define BUTTON_LEAN_LEFT (1 << BUTTON_LEAN_LEFT_BITINDEX)
#define BUTTON_LEAN_RIGHT (1 << BUTTON_LEAN_RIGHT_BITINDEX)
#define BUTTON_TALK (1 << BUTTON_TALK_BITINDEX) // displays talk balloon and disables actions
#define BUTTON_ANY (1 << BUTTON_ANY_BITINDEX) // any key whatsoever
#define BUTTON_MOUSE (1 << BUTTON_MOUSE_BITINDEX)
#define WEAPON_COMMAND_USE_PISTOL 1
#define WEAPON_COMMAND_USE_RIFLE 2
@@ -1766,8 +1757,14 @@ typedef struct playerState_s {
#define WEAPON_COMMAND_USE_LAST_WEAPON 13
#define WEAPON_COMMAND_HOLSTER 14
#define WEAPON_COMMAND_DROP 15
#if TARGET_GAME_PROTOCOL >= 15
#define WEAPON_COMMAND_MAX 31
#else
#define WEAPON_COMMAND_MAX 15
#define WEAPON_COMMAND_MASK WEAPON_COMMAND_MAX << 7
#endif
#define WEAPON_COMMAND_MASK (WEAPON_COMMAND_MAX << 7)
#define MOVE_RUN 120 // if forwardmove or rightmove are >= MOVE_RUN,
@@ -2041,20 +2038,6 @@ typedef struct hdelement_s {
struct fontheader_s *pFont;
} hdelement_t;
enum vmAnim_e {
VM_ANIM_IDLE,
VM_ANIM_CHARGE,
VM_ANIM_FIRE,
VM_ANIM_FIRE_SECONDARY,
VM_ANIM_RECHAMBER,
VM_ANIM_RELOAD,
VM_ANIM_RELOAD_SINGLE,
VM_ANIM_RELOAD_END,
VM_ANIM_PULLOUT,
VM_ANIM_PUTAWAY,
VM_ANIM_LADDERSTEP
};
typedef struct {
frameInfo_t g_VMFrameInfo[MAX_FRAMEINFOS];
+16 -22
View File
@@ -83,7 +83,10 @@ void MSG_WriteLong (msg_t *sb, int c);
void MSG_WriteFloat (msg_t *sb, float f);
void MSG_WriteString (msg_t *sb, const char *s);
void MSG_WriteBigString (msg_t *sb, const char *s);
void MSG_WriteScrambledString(msg_t* sb, const char* s);
void MSG_WriteScrambledBigString(msg_t* sb, const char* s);
void MSG_WriteAngle16 (msg_t *sb, float f);
void MSG_WriteEntityNum(msg_t* sb, short number);
void MSG_BeginReading (msg_t *sb);
void MSG_BeginReadingOOB(msg_t *sb);
@@ -104,9 +107,12 @@ float MSG_ReadFloat (msg_t *sb);
char *MSG_ReadString (msg_t *sb);
char *MSG_ReadBigString (msg_t *sb);
char *MSG_ReadStringLine( msg_t *sb );
char* MSG_ReadScrambledString(msg_t* msg);
char* MSG_ReadScrambledBigString(msg_t* msg);
float MSG_ReadAngle8( msg_t *sb );
float MSG_ReadAngle16 (msg_t *sb);
void MSG_ReadData (msg_t *sb, void *buffer, int size);
unsigned short MSG_ReadEntityNum(msg_t* sb);
void MSG_WriteDeltaUsercmd( msg_t *msg, struct usercmd_s *from, struct usercmd_s *to );
@@ -158,6 +164,7 @@ void MSG_WritePackedSimple(msg_t* msg, int value, int bits);
float MSG_UnpackAngle(int value, int bits);
float MSG_UnpackAnimTime(int packed);
float MSG_UnpackAnimWeight(int result, int bits);
float MSG_UnpackScale(int packed);
float MSG_UnpackAlpha(int packed, int bits);
float MSG_UnpackCoord(int packed, int bits);
@@ -181,7 +188,7 @@ NET
#define PORT_ANY -1
#define MAX_RELIABLE_COMMANDS 64 // max string commands buffered for restransmit
#define MAX_RELIABLE_COMMANDS 512 // max string commands buffered for restransmit
typedef enum {
NA_BOT,
@@ -798,26 +805,6 @@ MISC
/*
==============================================================
Edit fields and command line history/completion
==============================================================
*/
#define MAX_EDIT_LINE 256
typedef struct {
int cursor;
int scroll;
int widthInChars;
char buffer[MAX_EDIT_LINE];
} field_t;
void Field_Clear( field_t *edit );
void Field_CompleteCommand( field_t *edit );
void Field_AutoComplete( field_t *edit );
/*
==============================================================
MISC
==============================================================
@@ -882,10 +869,10 @@ void Com_StartupVariable( const char *match );
// only a set with the exact name. Only used during startup.
extern float currentfps;
extern cvar_t *paused;
extern cvar_t *config;
extern cvar_t *fps;
extern float currentfps;
extern cvar_t *developer;
extern cvar_t *com_dedicated;
extern cvar_t *com_speeds;
@@ -1237,6 +1224,13 @@ char **Sys_ListFiles( const char *directory, const char *extension, const char *
void Sys_FreeFileList( char **list );
void Sys_Sleep(int msec);
void Sys_InitStreamThread(void);
void Sys_ShutdownStreamThread(void);
void Sys_BeginStreamedFile(fileHandle_t f, int readAhead);
void Sys_EndStreamedFile(fileHandle_t f);
int Sys_StreamedRead(void* buffer, int size, int count, fileHandle_t f);
void Sys_StreamSeek(fileHandle_t f, int offset, int origin);
qboolean Sys_LowPhysicalMemory( void );
void SetNormalThreadPriority( void );
+6 -6
View File
@@ -468,8 +468,8 @@ typedef struct {
// little-endian "2015"
#define BSP_BETA_VERSION 18 // Beta Allied Assault
#define BSP_BASE_VERSION 19 // vanilla Allied Assault
#define BSP_VERSION 19 // current Allied Assault
#define BSP_MIN_VERSION 18 // Beta Allied Assault
#define BSP_MAX_VERSION 21 // Breakthrough
// there shouldn't be any problem with increasing these values at the
@@ -535,7 +535,7 @@ typedef struct cTerraPatch_s {
byte s;
byte t;
float texCoord[ 2 ][ 2 ][ 2 ];
vec2_t texCoord[ 2 ][ 2 ];
char x;
char y;
@@ -555,9 +555,9 @@ typedef struct cTerraPatch_s {
} cTerraPatch_t;
typedef struct cStaticModel_s {
char model[ 128 ];
float origin[ 3 ];
float angles[ 3 ];
char model[128];
vec3_t origin;
vec3_t angles;
float scale;
int firstVertexData;
int numVertexData;
+5 -5
View File
@@ -582,7 +582,7 @@ const char* Script::GrabNextToken(qboolean crossline)
*token_p++ = *script_p++;
}
if (token_p == &token[MAXTOKEN]) {
if (token_p == &token[SCRIPT_MAXTOKEN]) {
FILE_Error(ERR_DROP, "Token too large on line %i in file %s\n",
line, filename.c_str());
}
@@ -824,7 +824,7 @@ const char* Script::GetLine(qboolean crossline)
start = script_p;
SkipToEOL();
size = script_p - start;
if (size < (MAXTOKEN - 1)) {
if (size < (SCRIPT_MAXTOKEN - 1)) {
memcpy(token, start, size);
token[size] = '\0';
} else {
@@ -859,7 +859,7 @@ const char* Script::GetRaw(void)
start = script_p;
SkipToEOL();
size = script_p - start;
if (size < (MAXTOKEN - 1)) {
if (size < (SCRIPT_MAXTOKEN - 1)) {
memset(token, 0, sizeof(token));
memcpy(token, start, size);
} else {
@@ -946,7 +946,7 @@ const char* Script::GetString(qboolean crossline)
startline, filename.c_str());
}
if (token_p == &token[MAXTOKEN]) {
if (token_p == &token[SCRIPT_MAXTOKEN]) {
FILE_Error(ERR_DROP, "String too large on line %i in file %s\n",
line, filename.c_str());
}
@@ -1075,7 +1075,7 @@ int Script::LinesInFile(void)
qboolean temp_tokenready;
const char* temp_script_p;
int temp_line;
char temp_token[MAXTOKEN];
char temp_token[SCRIPT_MAXTOKEN];
int numentries;
temp_tokenready = tokenready;
+3 -3
View File
@@ -40,13 +40,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define TOKENSPACE (' ')
#define TOKENSPECIAL ('$')
#define MAXTOKEN 512
#define SCRIPT_MAXTOKEN 512
typedef struct {
qboolean tokenready;
int offset;
int line;
char token[MAXTOKEN];
char token[SCRIPT_MAXTOKEN];
} scriptmarker_t;
typedef struct {
@@ -67,7 +67,7 @@ protected:
Container<macro*> macrolist;
int line;
char token[MAXTOKEN];
char token[SCRIPT_MAXTOKEN];
qboolean releaseBuffer;
qboolean hasError;
+2 -2
View File
@@ -87,7 +87,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define SURF_NOMARKS 0x20 // don't leave missile marks
#define SURF_CASTSHADOW 0x40
#define SURF_NODRAW 0x80 // don't generate a drawsurface at all
#define SURF_HINT 0x100 // make a primary bsp splitter
#define SURF_NOLIGHTMAP 0x100 // surface doesn't need a lightmap
#define SURF_ALPHASHADOW 0x200 // do per-pixel light shadow casting in q3map
#define SURF_NOSTEPS 0x400 // no footstep sounds
#define SURF_NONSOLID 0x800 // don't collide against curves with this set
@@ -109,7 +109,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define SURF_CARPET 0x8000000 // carpet effects
#define SURF_BACKSIDE 0x10000000 // su44: backside
#define SURF_NODLIGHT 0x20000000 // don't dlight even if solid (solid lava, skies)
#define SURF_NOLIGHTMAP 0x40000000 // surface doesn't need a lightmap
#define SURF_HINT 0x40000000 // make a primary bsp splitter
#define SURF_UNKNOWN3 0x80000000 // IneQuation: WTF?
#define SURF_FLESH 0x40 // make flesh sounds and effects
+9 -9
View File
@@ -388,7 +388,7 @@ void TikiScript::AddMacro( const char *name, const char *expansion )
return;
}
if( nummacros >= MAXMACROS )
if( nummacros >= TIKI_MAXMACROS )
{
TIKI_DPrintf( "Too many %cdefine in file %s\n", TOKENSPECIAL, Filename() );
}
@@ -420,7 +420,7 @@ qboolean TikiScript::ProcessCommand( qboolean crossline )
char argument1[ 256 ];
char argument2[ 256 ];
sscanf( script_p, "%c%s %s %s\n", &dummy, &command, &argument1, &argument2 );
sscanf( script_p, "%c%s %s %s\n", &dummy, command, argument1, argument2 );
if( !stricmp( command, "define" ) )
{
@@ -760,7 +760,7 @@ const char *TikiScript::GetToken( qboolean crossline )
*token_p++ = *i->script_p++;
}
if( token_p == &i->token[ MAXTOKEN ] )
if( token_p == &i->token[ TIKI_MAXTOKEN ] )
{
TIKI_DPrintf( "Token too large on line %i in file %s\n", i->line, i->Filename() );
break;
@@ -869,7 +869,7 @@ const char *TikiScript::GetLine( qboolean crossline )
start = i->script_p;
SkipToEOL();
size = i->script_p - start;
if( size < ( MAXTOKEN - 1 ) )
if( size < ( TIKI_MAXTOKEN - 1 ) )
{
memcpy( i->token, start, size );
i->token[ size ] = '\0';
@@ -928,7 +928,7 @@ const char *TikiScript::GetAndIgnoreLine( qboolean crossline )
start = script_p;
SkipToEOL();
size = script_p - start;
if( size < ( MAXTOKEN - 1 ) )
if( size < ( TIKI_MAXTOKEN - 1 ) )
{
memcpy( token, start, size );
token[ size ] = '\0';
@@ -981,7 +981,7 @@ const char *TikiScript::GetRaw( void )
start = script_p;
SkipToEOL();
size = script_p - start;
if( size < ( MAXTOKEN - 1 ) )
if( size < ( TIKI_MAXTOKEN - 1 ) )
{
memset( token, 0, sizeof( token ) );
memcpy( token, start, size );
@@ -1086,7 +1086,7 @@ const char *TikiScript::GetString( qboolean crossline )
"line %d in file %s\n", startline, i->filename );
}
if( token_p == &i->token[ MAXTOKEN ] )
if( token_p == &i->token[ TIKI_MAXTOKEN ] )
{
TIKI_DPrintf( "String too large on line %i in file %s\n", i->line, i->filename );
}
@@ -1192,7 +1192,7 @@ int TikiScript::LinesInFile( void )
qboolean temp_tokenready;
const char *temp_script_p;
int temp_line;
char temp_token[ MAXTOKEN ];
char temp_token[ TIKI_MAXTOKEN ];
int numentries;
temp_tokenready = tokenready;
@@ -1232,7 +1232,7 @@ void TikiScript::Parse( char *data, int length, const char *name )
Reset();
this->length = length;
end_p = script_p + length;
strncpy( filename, name, MAXTOKEN );
strncpy( filename, name, TIKI_MAXTOKEN );
}
/*
+8 -10
View File
@@ -32,21 +32,19 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define TOKENSPACE (' ')
#define TOKENSPECIAL ('$')
#ifndef MAXTOKEN
#define MAXTOKEN 256
#endif
#define TIKI_MAXTOKEN 256
#define MAXMACROS 48
#define TIKI_MAXMACROS 48
typedef struct {
char name[ MAXTOKEN ];
char macro[ MAXTOKEN ];
char name[TIKI_MAXTOKEN];
char macro[TIKI_MAXTOKEN];
} tiki_macro_t;
typedef struct {
const char *mark_script_p;
qboolean mark_tokenready;
char mark_token[ MAXTOKEN ];
char mark_token[TIKI_MAXTOKEN];
} tiki_mark_t;
#ifdef __cplusplus
@@ -57,13 +55,13 @@ protected:
qboolean tokenready;
class TikiScript *include;
class TikiScript *parent;
char filename[ MAXTOKEN ];
char filename[TIKI_MAXTOKEN];
const char *script_p;
const char *end_p;
tiki_macro_t macros[ MAXMACROS ];
tiki_macro_t macros[TIKI_MAXMACROS];
int nummacros;
int line;
char token[ MAXTOKEN ];
char token[TIKI_MAXTOKEN];
qboolean releaseBuffer;
tiki_mark_t mark[ 64 ];
int mark_pos;
+50
View File
@@ -90,6 +90,28 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define GL_TEXTURE2_ARB 0x84C2
#define GL_TEXTURE3_ARB 0x84C3
#define GL_COMBINE 0x8570
#define GL_COMBINE4_NV 0x8503
#define GL_COMBINE_RGB 0x8571
#define GL_COMBINE_ALPHA 0x8572
#define GL_SOURCE0_RGB 0x8580
#define GL_SOURCE1_RGB 0x8581
#define GL_SOURCE2_RGB 0x8582
#define GL_SOURCE3_RGB 0x8583
#define GL_SOURCE0_ALPHA 0x8588
#define GL_SOURCE1_ALPHA 0x8589
#define GL_SOURCE2_ALPHA 0x858A
#define GL_SOURCE3_ALPHA 0x858B
#define GL_OPERAND0_RGB 0x8590
#define GL_OPERAND1_RGB 0x8591
#define GL_OPERAND2_RGB 0x8592
#define GL_OPERAND3_RGB 0x8593
#define GL_OPERAND0_ALPHA 0x8598
#define GL_OPERAND1_ALPHA 0x8599
#define GL_OPERAND2_ALPHA 0x859A
#define GL_OPERAND3_ALPHA 0x859B
// NOTE: some Linux platforms would need those prototypes
#if defined(MACOS_X)
typedef void (APIENTRY * PFNGLMULTITEXCOORD1DARBPROC) (GLenum target, GLdouble s);
@@ -506,6 +528,34 @@ extern void ( APIENTRY * qglVertex4sv )(const GLshort *v);
extern void ( APIENTRY * qglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
extern void ( APIENTRY * qglViewport )(GLint x, GLint y, GLsizei width, GLsizei height);
// GL_ARB_texture_compression
extern void (APIENTRY* qglCompressedTexImage3DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void* data);
extern void (APIENTRY* qglCompressedTexImage2DARB)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
extern void (APIENTRY* qglCompressedTexSubImage3DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void* data);
extern void (APIENTRY* qglCompressedTexSubImage2DARB)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data);
extern void (APIENTRY* qglGetCompressedTexImageARB)(GLenum target, GLint lod, void* img);
#ifndef GL_COMPRESSED_RGB_ARB
#define GL_COMPRESSED_ALPHA_ARB 0x84E9
#define GL_COMPRESSED_LUMINANCE_ARB 0x84EA
#define GL_COMPRESSED_LUMINANCE_ALPHA_ARB 0x84EB
#define GL_COMPRESSED_INTENSITY_ARB 0x84EC
#define GL_COMPRESSED_RGB_ARB 0x84ED
#define GL_COMPRESSED_RGBA_ARB 0x84EE
#define GL_TEXTURE_COMPRESSION_HINT_ARB 0x84EF
#define GL_TEXTURE_COMPRESSED_IMAGE_SIZE_ARB 0x86A0
#define GL_TEXTURE_COMPRESSED_ARB 0x86A1
#define GL_NUM_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A2
#define GL_COMPRESSED_TEXTURE_FORMATS_ARB 0x86A3
#endif
// GL_EXT_texture_compression_s3tc
#ifndef GL_COMPRESSED_RGB_S3TC_DXT1_EXT
#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
#endif
#if defined( _WIN32 )
extern int ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *);
+5
View File
@@ -355,3 +355,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define qglVertexPointer glVertexPointer
#define qglViewport glViewport
#define qglCompressedTexImage3DARB glCompressedTexImage3D
#define qglCompressedTexImage2DARB glCompressedTexImage2D
#define qglCompressedTexSubImage3DARB glCompressedTexSubImage3D
#define qglCompressedTexSubImage2DARB glCompressedTexSubImage2D
#define qglGetCompressedTexImageARB glGetCompressedTexImage
+199 -41
View File
@@ -34,6 +34,16 @@ static float s_flipMatrix[16] = {
0, 0, 0, 1
};
void GL_SetFogColor(const vec4_t fColor) {
glState.fFogColor[0] = fColor[0];
glState.fFogColor[1] = fColor[1];
glState.fFogColor[2] = fColor[2];
glState.fFogColor[3] = fColor[3];
if (!(glState.glStateBits & GLS_FOG_COLOR)) {
qglFogfv(GL_FOG_COLOR, glState.fFogColor);
}
}
/*
** GL_Bind
@@ -188,6 +198,10 @@ void GL_TexEnv( int env )
case GL_ADD:
qglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_ADD );
break;
case GL_COMBINE4_NV:
case GL_COMBINE:
qglTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env);
break;
default:
ri.Error( ERR_DROP, "GL_TexEnv: invalid env '%d' passed\n", env );
break;
@@ -202,7 +216,7 @@ void GL_TexEnv( int env )
*/
void GL_State( unsigned long stateBits )
{
unsigned long diff = stateBits ^ glState.glStateBits;
unsigned long diff = glState.glStateBits ^ (glState.externalSetState | stateBits);
if ( !diff )
{
@@ -354,6 +368,35 @@ void GL_State( unsigned long stateBits )
}
}
if ((diff & GLS_MULTITEXTURE_ENV) || (diff & GLS_MULTITEXTURE))
{
if (stateBits & GLS_MULTITEXTURE_ENV)
{
GL_TexEnv(GL_COMBINE4_NV);
}
else if (stateBits & GLS_MULTITEXTURE)
{
if (glState.cntTexEnvExt != GLS_MULTITEXTURE)
{
qglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, 34165.0);
qglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, 8448.0);
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, 0x47057700);
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, 0x44400000);
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, 5890.0);
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB, 0x44400000);
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB, 0x47057700);
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB, 770.0);
glState.cntTexEnvExt = GLS_MULTITEXTURE;
}
GL_TexEnv(GL_COMBINE);
}
else
{
GL_TexEnv(GL_MODULATE);
}
}
//
// alpha test
//
@@ -382,7 +425,109 @@ void GL_State( unsigned long stateBits )
}
}
glState.glStateBits = stateBits;
if (diff & GLS_CLAMP_EDGE)
{
float clampValue;
if (r_forceClampToEdge->value)
{
if (stateBits & GLS_CLAMP_EDGE) {
clampValue = 33071.0;
}
else {
clampValue = 10497.0;
}
}
else
{
if (stateBits & GLS_CLAMP_EDGE) {
clampValue = 10496.0;
}
else {
clampValue = 10497.0;
}
}
if (qglActiveTextureARB)
{
int currenttmu = glState.currenttmu;
GL_SelectTexture(0);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clampValue);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clampValue);
GL_SelectTexture(1);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clampValue);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clampValue);
GL_SelectTexture(currenttmu);
}
else
{
GL_SelectTexture(0);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, clampValue);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, clampValue);
}
}
if (diff & GLS_FOG)
{
if (glState.externalSetState & GLS_FOG)
{
qglEnable(GL_FOG);
if (stateBits & GLS_FOG_BLACK)
{
vec4_t fBlackFogColor = { 0, 0, 0, 1 };
qglFogfv(GL_FOG_COLOR, fBlackFogColor);
}
else if (stateBits & GLS_FOG_WHITE)
{
vec4_t fWhiteFogColor = { 1, 1, 1, 1 };
qglFogfv(GL_FOG_COLOR, fWhiteFogColor);
}
else
{
//
// Use the global fog
qglFogfv(GL_FOG_COLOR, glState.fFogColor);
}
}
else
{
qglDisable(GL_FOG);
}
}
else if (glState.externalSetState & GLS_FOG)
{
if (diff & GLS_FOG_ENABLED)
{
if (stateBits & GLS_FOG_ENABLED) {
qglEnable(GL_FOG);
}
else {
qglDisable(GL_FOG);
}
}
if (diff & GLS_FOG_COLOR)
{
if (stateBits & GLS_FOG_BLACK)
{
vec4_t fBlackFogColor = { 0, 0, 0, 1 };
qglFogfv(GL_FOG_COLOR, fBlackFogColor);
}
else if (stateBits & GLS_FOG_WHITE)
{
vec4_t fWhiteFogColor = { 1, 1, 1, 1 };
qglFogfv(GL_FOG_COLOR, fWhiteFogColor);
}
}
}
glState.glStateBits = stateBits | glState.externalSetState;
}
@@ -450,23 +595,33 @@ void RB_BeginDrawingView (void) {
//
SetViewportAndScissor();
R_UploadDlights();
// ensures that depth writes are enabled for the depth clear
GL_State( GLS_DEFAULT );
// clear relevant buffers
clearBits = GL_DEPTH_BUFFER_BIT;
if ( r_measureOverdraw->integer || r_shadows->integer == 2 )
if ( r_measureOverdraw->integer || r_shadows->integer == 3 )
{
clearBits |= GL_STENCIL_BUFFER_BIT;
}
if ( r_fastsky->integer && !( backEnd.refdef.rdflags & RDF_NOWORLDMODEL ) )
if (!( backEnd.refdef.rdflags & RDF_NOWORLDMODEL))
{
clearBits |= GL_COLOR_BUFFER_BIT; // FIXME: only if sky shaders have been used
#ifdef _DEBUG
qglClearColor( 0.8f, 0.7f, 0.4f, 1.0f ); // FIXME: get color of sky
#else
qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); // FIXME: get color of sky
#endif
if (backEnd.viewParms.farplane_distance && tr.skyRendered && tr.portalRendered)
{
clearBits |= GL_COLOR_BUFFER_BIT;
qglClearColor(glState.fFogColor[0], glState.fFogColor[1], glState.fFogColor[2], glState.fFogColor[3]);
}
else
{
if (r_fastsky->integer)
{
clearBits |= GL_COLOR_BUFFER_BIT;
qglClearColor(0.5, 0.5, 1.0, 1.0);
}
}
}
qglClear( clearBits );
@@ -553,6 +708,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
depthRange = qfalse;
backEnd.pc.c_surfaces += numDrawSurfs;
backEnd.numSpheresUsed = 0;
for (i = 0, drawSurf = drawSurfs ; i < numDrawSurfs ; i++, drawSurf++) {
if ( drawSurf->sort == oldSort ) {
@@ -561,7 +717,14 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
continue;
}
oldSort = drawSurf->sort;
R_DecomposeSort( drawSurf->sort, &entityNum, &shader, &dlightMap, &bStaticModel );
if (*drawSurf->surface != SF_SPRITE) {
R_DecomposeSort(drawSurf->sort, &entityNum, &shader, &dlightMap, &bStaticModel);
} else {
shader = tr.sortedShaders[((refSprite_t*)drawSurf->surface)->shaderNum];
entityNum = ENTITYNUM_WORLD;
dlightMap = 0;
bStaticModel = qfalse;
}
//
// change the tess parameters if needed
@@ -587,6 +750,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
oldDlightMap = dlightMap;
}
backEnd.currentSphere = &backEnd.spareSphere;
//
// change the modelview matrix if needed
//
@@ -643,7 +807,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
if ( depthRange ) {
qglDepthRange (0, 0.3);
} else {
qglDepthRange (0, 1);
qglDepthRange (0, 1.875);
}
oldDepthRange = depthRange;
}
@@ -697,7 +861,7 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
}
else
{
backEnd.currentSphere = &backEnd.spheres[backEnd.currentEntity->lightingSphere];
backEnd.currentSphere = &backEnd.spheres[backEnd.numSpheresUsed];
backEnd.currentEntity->lightingSphere = backEnd.numSpheresUsed++;
backEnd.currentEntity->sphereCalculated = 1;
}
@@ -708,6 +872,10 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
}
}
if (*drawSurf->surface == SF_SPRITE) {
backEnd.shaderStartTime = ((refSprite_t*)drawSurf->surface)->shaderTime;
}
// add the triangles for this surface
rb_surfaceTable[ *drawSurf->surface ]( drawSurf->surface );
}
@@ -722,7 +890,16 @@ void RB_RenderDrawSurfList( drawSurf_t *drawSurfs, int numDrawSurfs ) {
// go back to the world modelview matrix
qglLoadMatrixf( backEnd.viewParms.world.modelMatrix );
if ( depthRange ) {
qglDepthRange (0, 1);
qglDepthRange (0, 1.875);
}
RB_ShadowFinish();
RB_RenderFlares();
R_DrawLensFlares();
if (g_bInfoworldtris)
{
g_bInfoworldtris = 0;
R_PrintInfoWorldtris();
}
#if 0
@@ -814,12 +991,12 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, int componen
ri.Error (ERR_DROP, "Draw_StretchRaw: size not a power of 2: %i by %i", cols, rows);
}
GL_Bind( tr.scratchImage[0] );
GL_Bind( tr.scratchImage );
// if the scratchImage isn't in the format we want, specify it as a new texture
if ( cols != tr.scratchImage[0]->width || rows != tr.scratchImage[0]->height ) {
tr.scratchImage[0]->width = tr.scratchImage[0]->uploadWidth = cols;
tr.scratchImage[0]->height = tr.scratchImage[0]->uploadHeight = rows;
if ( cols != tr.scratchImage->width || rows != tr.scratchImage->height ) {
tr.scratchImage->width = tr.scratchImage->uploadWidth = cols;
tr.scratchImage->height = tr.scratchImage->uploadHeight = rows;
qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
@@ -852,29 +1029,6 @@ void RE_StretchRaw (int x, int y, int w, int h, int cols, int rows, int componen
qglEnd ();
}
void RE_UploadCinematic (int w, int h, int cols, int rows, const byte *data, int client, qboolean dirty) {
GL_Bind( tr.scratchImage[client] );
// if the scratchImage isn't in the format we want, specify it as a new texture
if ( cols != tr.scratchImage[client]->width || rows != tr.scratchImage[client]->height ) {
tr.scratchImage[client]->width = tr.scratchImage[client]->uploadWidth = cols;
tr.scratchImage[client]->height = tr.scratchImage[client]->uploadHeight = rows;
qglTexImage2D( GL_TEXTURE_2D, 0, GL_RGB8, cols, rows, 0, GL_RGBA, GL_UNSIGNED_BYTE, data );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );
} else {
if (dirty) {
// otherwise, just subimage upload it so that drivers can tell we are going to be changing
// it and don't try and do a texture compression
qglTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, cols, rows, GL_RGBA, GL_UNSIGNED_BYTE, data );
}
}
}
/*
=============
RB_SetColor
@@ -969,6 +1123,10 @@ const void *RB_StretchPic ( const void *data ) {
return (const void *)(cmd + 1);
}
void RB_SetupFog() {
// FIXME: unimplemented
}
/*
=============
+153 -186
View File
@@ -261,6 +261,14 @@ static void R_LoadLightmaps(gamelump_t* l) {
if ( r_lightmap->integer == 2 ) {
ri.Printf( PRINT_ALL, "Brightest lightmap value: %d\n", ( int ) ( maxIntensity * 255 ) );
}
if (r_fastdlights->integer) {
s_worldData.lighting = NULL;
}
else {
s_worldData.lighting = ri.Hunk_Alloc(l->length);
Com_Memcpy(s_worldData.lighting, l->buffer, l->length);
}
}
@@ -457,7 +465,11 @@ R_UnpackTerraPatch
================
*/
void R_UnpackTerraPatch(cTerraPatch_t* pPacked, cTerraPatchUnpacked_t* pUnpacked) {
int i;
int i, j;
union {
int16_t v;
uint8_t b[2];
} flags;
pUnpacked->byDirty = qfalse;
pUnpacked->visCountCheck = 0;
@@ -468,41 +480,54 @@ void R_UnpackTerraPatch(cTerraPatch_t* pPacked, cTerraPatchUnpacked_t* pUnpacked
Com_Error(ERR_DROP, "invalid map: terrain has lmapScale <= 0");
}
pUnpacked->drawinfo.lmapStep = (pPacked->lmapScale / 64);
pUnpacked->drawinfo.lmapSize = (pPacked->lmapScale * 8) | 1;
pUnpacked->drawinfo.lmapStep = (float)(pPacked->lmapScale / 64);
pUnpacked->drawinfo.lmapSize = (float)((pPacked->lmapScale * 8) + 1);
pUnpacked->s = ((float)pPacked->s + 0.5) * 0.0078125;
pUnpacked->t = ((float)pPacked->t + 0.5) * 0.0078125;
//if( s_worldData.lighting ) {
// pUnpacked->drawinfo.lmData = &s_worldData.lighting[ 3 * ( ( pPacked->t << 7 ) + pPacked->s + ( pPacked->iLightMap << 14 ) ) ];
//} else {
// pUnpacked->drawinfo.lmData = NULL;
//}
// fixme: is it important to have a lightmap data?
pUnpacked->drawinfo.lmData = NULL;
memcpy(pUnpacked->texCoord, pPacked->texCoord, sizeof(pUnpacked->texCoord));
pUnpacked->x0 = ((int)pPacked->x << 6);
pUnpacked->y0 = ((int)pPacked->y << 6);
pUnpacked->z0 = pPacked->iBaseHeight;
pUnpacked->shader = ShaderForShaderNum(pPacked->iShader, pPacked->iLightMap);
pUnpacked->iNorth = pPacked->iNorth;
pUnpacked->iEast = pPacked->iEast;
pUnpacked->iSouth = pPacked->iSouth;
pUnpacked->iWest = pPacked->iWest;
for (i = 0; i < 63; i++)
{
pUnpacked->varTree[0][i / 4].fVariance = pPacked->varTree[0][i].flags >> 12;
pUnpacked->varTree[1][i / 4].fVariance = pPacked->varTree[1][i].flags >> 12;
if( s_worldData.lighting ) {
pUnpacked->drawinfo.lmData = &s_worldData.lighting[pPacked->iLightMap * (LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3) + 3 * pPacked->s + 3 * 128 * pPacked->t];
} else {
pUnpacked->drawinfo.lmData = NULL;
}
memcpy(pUnpacked->heightmap, pPacked->heightmap, sizeof(pUnpacked->heightmap));
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
pUnpacked->texCoord[i][j][0] = LittleFloat(pPacked->texCoord[i][j][0]);
pUnpacked->texCoord[i][j][1] = LittleFloat(pPacked->texCoord[i][j][1]);
}
}
pUnpacked->x0 = ((int)pPacked->x << 6);
pUnpacked->y0 = ((int)pPacked->y << 6);
pUnpacked->z0 = LittleShort(pPacked->iBaseHeight);
pUnpacked->shader = ShaderForShaderNum(LittleShort(pPacked->iShader), LittleShort(pPacked->iLightMap));
pUnpacked->iNorth = LittleShort(pPacked->iNorth);
pUnpacked->iEast = LittleShort(pPacked->iEast);
pUnpacked->iSouth = LittleShort(pPacked->iSouth);
pUnpacked->iWest = LittleShort(pPacked->iWest);
for (i = 0; i < 63; i++)
{
flags.v = pPacked->varTree[0][i].flags;
flags.b[1] &= 7;
pUnpacked->varTree[0][i].fVariance = LittleShort(flags.v);
pUnpacked->varTree[0][i].s.flags = LittleShort(pPacked->varTree[0][i].flags) >> 12;
flags.v = pPacked->varTree[1][i].flags;
flags.b[1] &= 7;
pUnpacked->varTree[1][i].fVariance = LittleShort(flags.v);
pUnpacked->varTree[1][i].s.flags = LittleShort(pPacked->varTree[1][i].flags) >> 12;
}
for (i = 0; i < sizeof(pUnpacked->heightmap) / sizeof(pUnpacked->heightmap[0]); i++) {
pUnpacked->heightmap[i] = pPacked->heightmap[i];
}
pUnpacked->zmax = 0;
pUnpacked->flags = pPacked->flags;
for (i = 0; i < sizeof(pUnpacked->heightmap); i++)
for (i = 0; i < sizeof(pUnpacked->heightmap) / sizeof(pUnpacked->heightmap[0]); i++)
{
if (pUnpacked->zmax < pUnpacked->heightmap[i]) {
pUnpacked->zmax = pUnpacked->heightmap[i];
@@ -590,9 +615,6 @@ static void ParseFace( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, int
lightmapNum = LittleLong( ds->lightmapNum );
// get fog volume
surf->fogIndex = LittleLong( ds->fogNum ) + 1;
// get shader value
surf->shader = ShaderForShaderNum( ds->shaderNum, lightmapNum );
if ( r_singleShader->integer && !surf->shader->isSky ) {
@@ -644,6 +666,42 @@ static void ParseFace( dsurface_t *ds, drawVert_t *verts, msurface_t *surf, int
SetPlaneSignbits( &cv->plane );
cv->plane.type = PlaneTypeForNormal( cv->plane.normal );
if (tr.numLightmaps && lightmapNum != -1 && surf->shader->lightmapIndex >= 0)
{
float inv;
cv->lmX = LittleLong(ds->lightmapX);
cv->lmY = LittleLong(ds->lightmapY);
cv->lmWidth = LittleLong(ds->lightmapWidth);
cv->lmHeight = LittleLong(ds->lightmapHeight);
if (s_worldData.lighting) {
cv->lmData = &s_worldData.lighting[lightmapNum * (LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3) + 3 * cv->lmX + 3 * 128 * cv->lmY];
} else {
cv->lmData = NULL;
}
for (i = 0; i < 3; i++)
{
cv->lmOrigin[j] = LittleFloat(ds->lightmapOrigin[j]);
cv->lmVecs[0][j] = LittleFloat(ds->lightmapVecs[0][j]);
cv->lmVecs[1][j] = LittleFloat(ds->lightmapVecs[1][j]);
}
inv = VectorNormalize2(cv->lmVecs[0], cv->lmInverseVecs[0]);
cv->lmInverseVecs[0][0] *= 1.0 / inv;
cv->lmInverseVecs[0][1] *= 1.0 / inv;
cv->lmInverseVecs[0][2] *= 1.0 / inv;
inv = VectorNormalize2(cv->lmVecs[1], cv->lmInverseVecs[1]);
cv->lmInverseVecs[1][0] *= 1.0 / inv;
cv->lmInverseVecs[1][1] *= 1.0 / inv;
cv->lmInverseVecs[1][2] *= 1.0 / inv;
}
else
{
cv->lmData = NULL;
}
surf->data = (surfaceType_t *)cv;
}
@@ -702,6 +760,19 @@ static void ParseMesh ( dsurface_t *ds, drawVert_t *verts, msurface_t *surf ) {
grid = R_SubdividePatchToGrid( width, height, points );
surf->data = (surfaceType_t *)grid;
if (tr.numLightmaps && lightmapNum != -1 && surf->shader->lightmapIndex >= 0)
{
grid->lmX = LittleLong(ds->lightmapX);
grid->lmY = LittleLong(ds->lightmapY);
grid->lmWidth = LittleLong(ds->lightmapWidth);
grid->lmHeight = LittleLong(ds->lightmapHeight);
if (s_worldData.lighting) {
grid->lmData = &s_worldData.lighting[lightmapNum * (LIGHTMAP_SIZE * LIGHTMAP_SIZE * 3) + 3 * grid->lmX + 3 * 128 * grid->lmY];
} else {
grid->lmData = NULL;
}
}
// copy the level of detail origin, which is the center
// of the group of all curves that must subdivide the same
// to avoid cracking
@@ -1886,129 +1957,13 @@ static void R_LoadPlanes(gamelump_t* l) {
}
}
/*
=================
R_LoadFogs
=================
*/
static void R_LoadFogs(gamelump_t* l, gamelump_t* brushesLump, gamelump_t* sidesLump) {
int i;
fog_t* out;
dfog_t* fogs;
dbrush_t* brushes, * brush;
dbrushside_t* sides;
int count, brushesCount, sidesCount;
int sideNum;
int planeNum;
shader_t* shader;
float d;
int firstSide;
fogs = l->buffer;
if (l->length % sizeof(*fogs)) {
ri.Error(ERR_DROP, "LoadMap: funny lump size in %s", s_worldData.name);
}
count = l->length / sizeof(*fogs);
// create fog strucutres for them
s_worldData.numfogs = count + 1;
s_worldData.fogs = ri.Hunk_Alloc(s_worldData.numfogs * sizeof(*out));
out = s_worldData.fogs + 1;
if (!count) {
return;
}
brushes = brushesLump->buffer;
if (brushesLump->length % sizeof(*brushes)) {
ri.Error(ERR_DROP, "LoadMap: funny lump size in %s", s_worldData.name);
}
brushesCount = brushesLump->length / sizeof(*brushes);
sides = sidesLump->buffer;
if (sidesLump->length % sizeof(*sides)) {
ri.Error(ERR_DROP, "LoadMap: funny lump size in %s", s_worldData.name);
}
sidesCount = sidesLump->length / sizeof(*sides);
for (i = 0; i < count; i++, fogs++) {
out->originalBrushNumber = LittleLong(fogs->brushNum);
if ((unsigned)out->originalBrushNumber >= brushesCount) {
ri.Error(ERR_DROP, "fog brushNumber out of range");
}
brush = brushes + out->originalBrushNumber;
firstSide = LittleLong(brush->firstSide);
if ((unsigned)firstSide > sidesCount - 6) {
ri.Error(ERR_DROP, "fog brush sideNumber out of range");
}
// brushes are always sorted with the axial sides first
sideNum = firstSide + 0;
planeNum = LittleLong(sides[sideNum].planeNum);
out->bounds[0][0] = -s_worldData.planes[planeNum].dist;
sideNum = firstSide + 1;
planeNum = LittleLong(sides[sideNum].planeNum);
out->bounds[1][0] = s_worldData.planes[planeNum].dist;
sideNum = firstSide + 2;
planeNum = LittleLong(sides[sideNum].planeNum);
out->bounds[0][1] = -s_worldData.planes[planeNum].dist;
sideNum = firstSide + 3;
planeNum = LittleLong(sides[sideNum].planeNum);
out->bounds[1][1] = s_worldData.planes[planeNum].dist;
sideNum = firstSide + 4;
planeNum = LittleLong(sides[sideNum].planeNum);
out->bounds[0][2] = -s_worldData.planes[planeNum].dist;
sideNum = firstSide + 5;
planeNum = LittleLong(sides[sideNum].planeNum);
out->bounds[1][2] = s_worldData.planes[planeNum].dist;
// get information from the shader for fog parameters
shader = R_FindShader(fogs->shader, LIGHTMAP_NONE, qtrue, qtrue, qtrue, qtrue);
out->parms = shader->fogParms;
out->colorInt = ColorBytes4(shader->fogParms.color[0] * tr.identityLight,
shader->fogParms.color[1] * tr.identityLight,
shader->fogParms.color[2] * tr.identityLight, 1.0);
d = shader->fogParms.depthForOpaque < 1 ? 1 : shader->fogParms.depthForOpaque;
out->tcScale = 1.0f / (d * 8);
// set the gradient vector
sideNum = LittleLong(fogs->visibleSide);
if (sideNum == -1) {
out->hasSurface = qfalse;
}
else {
out->hasSurface = qtrue;
planeNum = LittleLong(sides[firstSide + sideNum].planeNum);
VectorSubtract(vec3_origin, s_worldData.planes[planeNum].normal, out->surface);
out->surface[3] = -s_worldData.planes[planeNum].dist;
}
out++;
}
}
/*
================
R_LoadLightGrid
================
*/
void R_LoadLightGrid(gamelump_t* l) {
void R_LoadLightGrid(gamelump_t* plPal, gamelump_t* plOffsets, gamelump_t* plData) {
int i;
vec3_t maxs;
int numGridPoints;
@@ -2017,35 +1972,51 @@ void R_LoadLightGrid(gamelump_t* l) {
w = &s_worldData;
w->lightGridInverseSize[0] = 1.0f / w->lightGridSize[0];
w->lightGridInverseSize[1] = 1.0f / w->lightGridSize[1];
w->lightGridInverseSize[2] = 1.0f / w->lightGridSize[2];
if (!plPal->buffer || !plOffsets->buffer || !plData->buffer) {
ri.Printf(PRINT_WARNING, "WARNING: No light grid data present\n");
w->lightGridOffsets = 0;
w->lightGridData = 0;
return;
}
w->lightGridSize[0] = 32.0;
w->lightGridSize[1] = 32.0;
w->lightGridSize[2] = 32.0;
w->lightGridOOSize[0] = 1.0f / w->lightGridSize[0];
w->lightGridOOSize[1] = 1.0f / w->lightGridSize[1];
w->lightGridOOSize[2] = 1.0f / w->lightGridSize[2];
wMins = w->bmodels[0].bounds[0];
wMaxs = w->bmodels[0].bounds[1];
for ( i = 0 ; i < 3 ; i++ ) {
w->lightGridOrigin[i] = w->lightGridSize[i] * ceil( wMins[i] / w->lightGridSize[i] );
w->lightGridMins[i] = w->lightGridSize[i] * ceil( wMins[i] / w->lightGridSize[i] );
maxs[i] = w->lightGridSize[i] * floor( wMaxs[i] / w->lightGridSize[i] );
w->lightGridBounds[i] = (maxs[i] - w->lightGridOrigin[i])/w->lightGridSize[i] + 1;
w->lightGridBounds[i] = (maxs[i] - w->lightGridMins[i])/w->lightGridSize[i] + 1;
}
numGridPoints = w->lightGridBounds[0] * w->lightGridBounds[1] * w->lightGridBounds[2];
numGridPoints = w->lightGridBounds[0] * w->lightGridBounds[1] + w->lightGridBounds[0];
if (l->length != numGridPoints * 8) {
ri.Printf(PRINT_WARNING, "WARNING: light grid mismatch\n");
if (plOffsets->length != numGridPoints * 2) {
ri.Printf(PRINT_WARNING, "WARNING: light grid offset size mismatch\n");
w->lightGridOffsets = NULL;
w->lightGridData = NULL;
return;
}
w->lightGridData = ri.Hunk_Alloc(l->length);
Com_Memcpy(w->lightGridData, (void*)l->buffer, l->length);
// deal with overbright bits
for ( i = 0 ; i < numGridPoints ; i++ ) {
R_ColorShiftLightingBytesAlpha( &w->lightGridData[i*8], &w->lightGridData[i*8] );
R_ColorShiftLightingBytesAlpha( &w->lightGridData[i*8+3], &w->lightGridData[i*8+3] );
if (plPal->length != 768) {
ri.Printf(PRINT_WARNING, "WARNING: light grid palette size mismatch\n");
w->lightGridOffsets = NULL;
w->lightGridData = NULL;
return;
}
w->lightGridOffsets = ri.Hunk_Alloc(plOffsets->length);
Com_Memcpy(w->lightGridOffsets, plOffsets->buffer, plOffsets->length);
Com_Memcpy(w->lightGridPalette, plPal->buffer, sizeof(s_worldData.lightGridPalette));
w->lightGridData = ri.Hunk_Alloc(plData->length);
Com_Memcpy(w->lightGridData, plData->buffer, plData->length);
}
/*
@@ -2070,17 +2041,16 @@ void R_LoadStaticModelData(gamelump_t* lump) {
}
s_worldData.numStaticModelData = lump->length / (sizeof(byte) * 3);
s_worldData.staticModelData = ri.Hunk_Alloc(s_worldData.numStaticModelData * (sizeof(byte) * 4));
s_worldData.staticModelData = (byte*)ri.Hunk_Alloc(s_worldData.numStaticModelData * sizeof(color4ub_t));
pSrcColors = lump->buffer;
pDstColors = s_worldData.staticModelData;
for (i = 0; i < lump->length; i += 3)
{
pDstColors[0] = pSrcColors[0];
pDstColors[1] = pSrcColors[1];
pDstColors[2] = pSrcColors[2];
pDstColors[3] = -1;
for (i = 0; i < lump->length; i += sizeof(byte) * 3)
{
// Colors are stored as integers
*(unsigned int*)pDstColors = LittleLong(*(unsigned int*)pSrcColors);
pDstColors[3] = 0xFF;
pSrcColors += sizeof(byte) * 3;
pDstColors += sizeof(byte) * 4;
@@ -2094,11 +2064,15 @@ R_CopyStaticModel
*/
void R_CopyStaticModel(cStaticModel_t* pSM, cStaticModelUnpacked_t* pUnpackedSM) {
pUnpackedSM->visCount = 0;
VectorCopy(pSM->angles, pUnpackedSM->angles);
VectorCopy(pSM->origin, pUnpackedSM->origin);
pUnpackedSM->scale = pSM->scale;
pUnpackedSM->firstVertexData = pSM->firstVertexData * 4 / 3;
pUnpackedSM->numVertexData = pSM->numVertexData;
pUnpackedSM->angles[0] = LittleFloat(pSM->angles[0]);
pUnpackedSM->angles[1] = LittleFloat(pSM->angles[1]);
pUnpackedSM->angles[2] = LittleFloat(pSM->angles[2]);
pUnpackedSM->origin[0] = LittleFloat(pSM->origin[0]);
pUnpackedSM->origin[1] = LittleFloat(pSM->origin[1]);
pUnpackedSM->origin[2] = LittleFloat(pSM->origin[2]);
pUnpackedSM->scale = LittleFloat(pSM->scale);
pUnpackedSM->firstVertexData = LittleLong(pSM->firstVertexData) * sizeof(color4ub_t) / (sizeof(byte) * 3);
pUnpackedSM->numVertexData = LittleLong(pSM->numVertexData);
memcpy(pUnpackedSM->model, pSM->model, sizeof(pUnpackedSM->model));
}
@@ -2259,9 +2233,9 @@ void RE_LoadWorldMap( const char *name ) {
c_gridVerts = 0;
i = LittleLong(header.version);
if (i < BSP_BASE_VERSION || i > BSP_VERSION) {
if (i < BSP_MIN_VERSION || i > BSP_MAX_VERSION) {
ri.Error(ERR_DROP, "RE_LoadWorldMap: %s has wrong version number (%i should be between %i and %i)",
name, i, BSP_BASE_VERSION, BSP_VERSION);
name, i, BSP_MIN_VERSION, BSP_MAX_VERSION);
}
// load into heap
@@ -2319,13 +2293,7 @@ void RE_LoadWorldMap( const char *name ) {
_R(75);
R_FreeLump(&lump2);
_R(76);
numbrushsides = R_LoadLump(h, &header.lumps[LUMP_BRUSHSIDES], &lump2, sizeof(dbrushside_t));
numbrushes = R_LoadLump(h, &header.lumps[LUMP_BRUSHES], &lump, sizeof(dbrush_t));
numFogs = R_LoadLump(h, &header.lumps[LUMP_DUMMY10], &lump3, sizeof(dfog_t));
R_LoadFogs(&lump3, &lump, &lump2);
R_FreeLump(&lump);
R_FreeLump(&lump2);
R_FreeLump(&lump3);
numFogs = 0;
nummodels = R_LoadLump(h, &header.lumps[LUMP_MODELS], &lump, sizeof(bmodel_t));
_R(77);
R_LoadSubmodels(&lump);
@@ -2344,8 +2312,7 @@ void RE_LoadWorldMap( const char *name ) {
_R(84);
g_iGridDataSize = R_LoadLump(h, &header.lumps[LUMP_LIGHTGRIDDATA], &lump3, sizeof(byte));
_R(85);
//R_LoadLightGrid( &lump, &lump2, &lump3 );
R_LoadLightGrid(&lump3);
R_LoadLightGrid( &lump, &lump2, &lump3 );
_R(86);
R_FreeLump(&lump);
_R(87);
+10
View File
@@ -42,6 +42,16 @@ R_PerformanceCounters
=====================
*/
void R_PerformanceCounters( void ) {
if (fps->integer) {
ri.SetPerformanceCounters(
backEnd.pc.c_totalIndexes / 3,
backEnd.pc.c_vertexes,
R_SumOfUsedImages(),
pc_save.c_totalIndexes / 3,
pc_save.c_vertexes,
backEnd.pc.c_characterlights
);
}
if ( !r_speeds->integer ) {
// clear the counters even if we aren't printing
Com_Memset( &tr.pc, 0, sizeof( tr.pc ) );
+5 -5
View File
@@ -236,17 +236,17 @@ void RE_DrawBackground_TexSubImage(int cols, int rows, int bgr, byte* data) {
format = GL_RGB;
}
GL_Bind(tr.scratchImage[0]);
GL_Bind(tr.scratchImage);
if (cols == tr.scratchImage[0]->width && rows == tr.scratchImage[0]->height && format == tr.scratchImage[0]->internalFormat)
if (cols == tr.scratchImage->width && rows == tr.scratchImage->height && format == tr.scratchImage->internalFormat)
{
qglTexSubImage2D(3553, 0, 0, 0, cols, rows, format, 5121, data);
}
else
{
tr.scratchImage[0]->uploadWidth = cols;
tr.scratchImage[0]->uploadHeight = rows;
tr.scratchImage[0]->internalFormat = format;
tr.scratchImage->uploadWidth = cols;
tr.scratchImage->uploadHeight = rows;
tr.scratchImage->internalFormat = format;
qglTexImage2D(GL_TEXTURE_2D, 0, 3, cols, rows, 0, format, 5121, data);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 9729.0);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 9729.0);
-19
View File
@@ -197,32 +197,13 @@ RB_AddDlightFlares
void RB_AddDlightFlares( void ) {
dlight_t *l;
int i, j, k;
fog_t *fog;
if ( !r_flares->integer ) {
return;
}
l = backEnd.refdef.dlights;
fog = tr.world->fogs;
for (i=0 ; i<backEnd.refdef.num_dlights ; i++, l++) {
// find which fog volume the light is in
for ( j = 1 ; j < tr.world->numfogs ; j++ ) {
fog = &tr.world->fogs[j];
for ( k = 0 ; k < 3 ; k++ ) {
if ( l->origin[k] < fog->bounds[0][k] || l->origin[k] > fog->bounds[1][k] ) {
break;
}
}
if ( k == 3 ) {
break;
}
}
if ( j == tr.world->numfogs ) {
j = 0;
}
RB_AddFlare( (void *)l, j, l->origin, l->color, NULL );
}
}
+652 -119
View File
@@ -49,6 +49,8 @@ int gl_filter_max = GL_LINEAR;
#define FILE_HASH_SIZE 1024
static image_t* hashTable[FILE_HASH_SIZE];
extern qboolean scr_initialized;
/*
** R_GammaCorrect
*/
@@ -297,6 +299,10 @@ lighting range
*/
void R_LightScaleTexture (unsigned *in, int inwidth, int inheight, qboolean only_gamma )
{
if (!tr.needsLightScale) {
return;
}
if ( only_gamma )
{
if ( !glConfig.deviceSupportsGamma )
@@ -546,36 +552,62 @@ static void Upload32(
// select proper internal format
if ( samples == 3 )
{
if ( glConfig.textureCompression == TC_S3TC )
if (!force32bit)
{
internalFormat = GL_RGB4_S3TC;
}
else if ( r_texturebits->integer == 16 )
{
internalFormat = GL_RGB5;
}
else if ( r_texturebits->integer == 32 )
{
internalFormat = GL_RGB8;
if (r_texturebits->integer == 16)
{
internalFormat = GL_RGB5;
}
else if (r_texturebits->integer == 32)
{
internalFormat = GL_RGB8;
}
else if (r_colorbits->integer == 16)
{
internalFormat = GL_RGBA4;
}
else if (r_colorbits->integer == 32)
{
internalFormat = GL_RGBA8;
}
else
{
internalFormat = 3;
}
}
else
{
internalFormat = 3;
internalFormat = GL_RGB8;
}
}
else if ( samples == 4 )
{
if ( r_texturebits->integer == 16 )
if (!force32bit)
{
internalFormat = GL_RGBA4;
}
else if ( r_texturebits->integer == 32 )
{
internalFormat = GL_RGBA8;
if (r_texturebits->integer == 16)
{
internalFormat = GL_RGBA4;
}
else if (r_texturebits->integer == 32)
{
internalFormat = GL_RGBA8;
}
else if (r_colorbits->integer == 16)
{
internalFormat = GL_RGBA4;
}
else if (r_colorbits->integer == 32)
{
internalFormat = GL_RGBA8;
}
else
{
internalFormat = 4;
}
}
else
{
internalFormat = 4;
internalFormat = GL_RGB8;
}
}
} else {
@@ -664,6 +696,161 @@ done:
ri.Hunk_FreeTempMemory( resampledBuffer );
}
static void UploadCompressed(
byte* data,
int width,
int height,
int numMipmaps,
int iMipmapsAvailable,
qboolean picmip,
int glCompressMode,
int* format,
int* pUploadWidth,
int* pUploadHeight,
int* pBytesUsed
) {
byte* offset;
int i;
int iStartImage;
int size;
int blockSize;
int scaled_width, scaled_height;
offset = data;
iStartImage = 0;
if (picmip) {
iStartImage = r_picmip->integer;
}
if (iStartImage > 0 && iStartImage >= iMipmapsAvailable) {
iStartImage = iMipmapsAvailable - 1;
}
scaled_width = width;
scaled_height = height;
if (iStartImage)
{
scaled_width = width >> iStartImage;
scaled_height = height >> iStartImage;
}
while (scaled_width > glConfig.maxTextureSize || scaled_height > glConfig.maxTextureSize)
{
scaled_width >>= 1;
scaled_height >>= 1;
++iStartImage;
}
if (iStartImage > 0 && iStartImage >= iMipmapsAvailable)
{
iStartImage = iMipmapsAvailable - 1;
scaled_width = width >> (iMipmapsAvailable - 1);
scaled_height = height >> (iMipmapsAvailable - 1);
}
*pUploadWidth = scaled_width;
*pUploadHeight = scaled_height;
*format = glCompressMode;
blockSize = 16;
if (glCompressMode == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || glCompressMode == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) {
blockSize = 8;
}
scaled_width = width;
scaled_height = height;
for (i = iStartImage; i; i--) {
int w, h;
w = scaled_width + 3;
if (scaled_width + 3 < 0) {
w = scaled_width + 6;
}
w >>= 2;
if (w > 1) {
h = scaled_height + 3;
if (scaled_height + 3 < 0) {
h = scaled_height + 6;
}
h >>= 2;
if (h > 1) {
offset += blockSize * w * h;
}
}
scaled_width >>= 1;
scaled_height >>= 1;
if (!scaled_width) scaled_width = 1;
if (!scaled_height) scaled_height = 1;
}
*pBytesUsed = 0;
for (;;)
{
while (scaled_width)
{
int w, h;
if (!scaled_height) scaled_height = 1;
w = scaled_width + 3;
if (scaled_width + 3 < 0) w = scaled_width + 6;
w >>= 2;
h = scaled_height + 3;
if (scaled_height + 3 < 0) h = scaled_height + 6;
h >>= 2;
size = blockSize * w * h;
if (w > 1 && h > 1) *pBytesUsed += size;
qglCompressedTexImage2DARB(3553, i - iStartImage, glCompressMode, scaled_width, scaled_height, 0, size, data);
GL_CheckErrors();
if (i < iMipmapsAvailable)
{
w = scaled_width + 3;
if (scaled_width + 3 < 0) {
w = scaled_width + 6;
}
if (w >> 2 > 1)
{
h = scaled_height + 3;
if (scaled_height + 3 < 0) {
h = scaled_height + 6;
}
if (h >> 2 > 1)
data += size;
}
}
scaled_width >>= 1;
scaled_height >>= 1;
++i;
}
if (!scaled_height) {
break;
}
scaled_width = 1;
}
if (numMipmaps > 1) {
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
}
else
{
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
GL_CheckErrors();
}
/*
================
@@ -727,6 +914,7 @@ image_t* R_CreateImage(
image->allowPicmip = allowPicmip;
image->dynamicallyUpdated = dynamicallyUpdated;
image->force32bit = force32bit;
image->UseCount = 0;
strcpy (image->imgName, name);
@@ -748,21 +936,37 @@ image_t* R_CreateImage(
GL_Bind(image);
Upload32(
(unsigned*)pic,
image->width,
image->height,
image->numMipmaps,
allowPicmip,
image->dynamicallyUpdated,
force32bit,
hasAlpha,
&image->internalFormat,
&image->uploadWidth,
&image->uploadHeight,
&image->bytesUsed,
isLightmap
);
if (glCompressMode) {
UploadCompressed(
pic,
image->width,
image->height,
image->numMipmaps,
iMipmapsAvailable,
allowPicmip,
glCompressMode,
&image->internalFormat,
&image->uploadWidth,
&image->uploadHeight,
&image->bytesUsed
);
} else {
Upload32(
(unsigned*)pic,
image->width,
image->height,
image->numMipmaps,
allowPicmip,
image->dynamicallyUpdated,
force32bit,
hasAlpha,
&image->internalFormat,
&image->uploadWidth,
&image->uploadHeight,
&image->bytesUsed,
isLightmap
);
}
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glWrapClampModeX );
qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glWrapClampModeY );
@@ -777,6 +981,7 @@ image_t* R_CreateImage(
hash = generateHashValue(name);
image->next = hashTable[hash];
hashTable[hash] = image;
image->r_sequence = r_sequencenumber;
return image;
}
@@ -1095,6 +1300,342 @@ static void LoadPCX32 ( const char *filename, byte **pic, int *width, int *heigh
ri.Free (palette);
}
//==========================
//
// DDS Loading
//
//==========================
typedef unsigned int ui32_t;
typedef struct ddsHeader_s
{
ui32_t headerSize;
ui32_t flags;
ui32_t height;
ui32_t width;
ui32_t pitchOrFirstMipSize;
ui32_t volumeDepth;
ui32_t numMips;
ui32_t reserved1[11];
ui32_t always_0x00000020;
ui32_t pixelFormatFlags;
ui32_t fourCC;
ui32_t rgbBitCount;
ui32_t rBitMask;
ui32_t gBitMask;
ui32_t bBitMask;
ui32_t aBitMask;
ui32_t caps;
ui32_t caps2;
ui32_t caps3;
ui32_t caps4;
ui32_t reserved2;
}
ddsHeader_t;
// flags:
#define _DDSFLAGS_REQUIRED 0x001007
#define _DDSFLAGS_PITCH 0x8
#define _DDSFLAGS_MIPMAPCOUNT 0x20000
#define _DDSFLAGS_FIRSTMIPSIZE 0x80000
#define _DDSFLAGS_VOLUMEDEPTH 0x800000
// pixelFormatFlags:
#define DDSPF_ALPHAPIXELS 0x1
#define DDSPF_ALPHA 0x2
#define DDSPF_FOURCC 0x4
#define DDSPF_RGB 0x40
#define DDSPF_YUV 0x200
#define DDSPF_LUMINANCE 0x20000
// caps:
#define DDSCAPS_COMPLEX 0x8
#define DDSCAPS_MIPMAP 0x400000
#define DDSCAPS_REQUIRED 0x1000
// caps2:
#define DDSCAPS2_CUBEMAP 0xFE00
#define DDSCAPS2_VOLUME 0x200000
typedef struct ddsHeaderDxt10_s
{
ui32_t dxgiFormat;
ui32_t dimensions;
ui32_t miscFlags;
ui32_t arraySize;
ui32_t miscFlags2;
}
ddsHeaderDxt10_t;
// dxgiFormat
// from http://msdn.microsoft.com/en-us/library/windows/desktop/bb173059%28v=vs.85%29.aspx
typedef enum DXGI_FORMAT {
DXGI_FORMAT_UNKNOWN = 0,
DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
DXGI_FORMAT_R32G32B32A32_UINT = 3,
DXGI_FORMAT_R32G32B32A32_SINT = 4,
DXGI_FORMAT_R32G32B32_TYPELESS = 5,
DXGI_FORMAT_R32G32B32_FLOAT = 6,
DXGI_FORMAT_R32G32B32_UINT = 7,
DXGI_FORMAT_R32G32B32_SINT = 8,
DXGI_FORMAT_R16G16B16A16_TYPELESS = 9,
DXGI_FORMAT_R16G16B16A16_FLOAT = 10,
DXGI_FORMAT_R16G16B16A16_UNORM = 11,
DXGI_FORMAT_R16G16B16A16_UINT = 12,
DXGI_FORMAT_R16G16B16A16_SNORM = 13,
DXGI_FORMAT_R16G16B16A16_SINT = 14,
DXGI_FORMAT_R32G32_TYPELESS = 15,
DXGI_FORMAT_R32G32_FLOAT = 16,
DXGI_FORMAT_R32G32_UINT = 17,
DXGI_FORMAT_R32G32_SINT = 18,
DXGI_FORMAT_R32G8X24_TYPELESS = 19,
DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20,
DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21,
DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22,
DXGI_FORMAT_R10G10B10A2_TYPELESS = 23,
DXGI_FORMAT_R10G10B10A2_UNORM = 24,
DXGI_FORMAT_R10G10B10A2_UINT = 25,
DXGI_FORMAT_R11G11B10_FLOAT = 26,
DXGI_FORMAT_R8G8B8A8_TYPELESS = 27,
DXGI_FORMAT_R8G8B8A8_UNORM = 28,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29,
DXGI_FORMAT_R8G8B8A8_UINT = 30,
DXGI_FORMAT_R8G8B8A8_SNORM = 31,
DXGI_FORMAT_R8G8B8A8_SINT = 32,
DXGI_FORMAT_R16G16_TYPELESS = 33,
DXGI_FORMAT_R16G16_FLOAT = 34,
DXGI_FORMAT_R16G16_UNORM = 35,
DXGI_FORMAT_R16G16_UINT = 36,
DXGI_FORMAT_R16G16_SNORM = 37,
DXGI_FORMAT_R16G16_SINT = 38,
DXGI_FORMAT_R32_TYPELESS = 39,
DXGI_FORMAT_D32_FLOAT = 40,
DXGI_FORMAT_R32_FLOAT = 41,
DXGI_FORMAT_R32_UINT = 42,
DXGI_FORMAT_R32_SINT = 43,
DXGI_FORMAT_R24G8_TYPELESS = 44,
DXGI_FORMAT_D24_UNORM_S8_UINT = 45,
DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46,
DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47,
DXGI_FORMAT_R8G8_TYPELESS = 48,
DXGI_FORMAT_R8G8_UNORM = 49,
DXGI_FORMAT_R8G8_UINT = 50,
DXGI_FORMAT_R8G8_SNORM = 51,
DXGI_FORMAT_R8G8_SINT = 52,
DXGI_FORMAT_R16_TYPELESS = 53,
DXGI_FORMAT_R16_FLOAT = 54,
DXGI_FORMAT_D16_UNORM = 55,
DXGI_FORMAT_R16_UNORM = 56,
DXGI_FORMAT_R16_UINT = 57,
DXGI_FORMAT_R16_SNORM = 58,
DXGI_FORMAT_R16_SINT = 59,
DXGI_FORMAT_R8_TYPELESS = 60,
DXGI_FORMAT_R8_UNORM = 61,
DXGI_FORMAT_R8_UINT = 62,
DXGI_FORMAT_R8_SNORM = 63,
DXGI_FORMAT_R8_SINT = 64,
DXGI_FORMAT_A8_UNORM = 65,
DXGI_FORMAT_R1_UNORM = 66,
DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67,
DXGI_FORMAT_R8G8_B8G8_UNORM = 68,
DXGI_FORMAT_G8R8_G8B8_UNORM = 69,
DXGI_FORMAT_BC1_TYPELESS = 70,
DXGI_FORMAT_BC1_UNORM = 71,
DXGI_FORMAT_BC1_UNORM_SRGB = 72,
DXGI_FORMAT_BC2_TYPELESS = 73,
DXGI_FORMAT_BC2_UNORM = 74,
DXGI_FORMAT_BC2_UNORM_SRGB = 75,
DXGI_FORMAT_BC3_TYPELESS = 76,
DXGI_FORMAT_BC3_UNORM = 77,
DXGI_FORMAT_BC3_UNORM_SRGB = 78,
DXGI_FORMAT_BC4_TYPELESS = 79,
DXGI_FORMAT_BC4_UNORM = 80,
DXGI_FORMAT_BC4_SNORM = 81,
DXGI_FORMAT_BC5_TYPELESS = 82,
DXGI_FORMAT_BC5_UNORM = 83,
DXGI_FORMAT_BC5_SNORM = 84,
DXGI_FORMAT_B5G6R5_UNORM = 85,
DXGI_FORMAT_B5G5R5A1_UNORM = 86,
DXGI_FORMAT_B8G8R8A8_UNORM = 87,
DXGI_FORMAT_B8G8R8X8_UNORM = 88,
DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89,
DXGI_FORMAT_B8G8R8A8_TYPELESS = 90,
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91,
DXGI_FORMAT_B8G8R8X8_TYPELESS = 92,
DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93,
DXGI_FORMAT_BC6H_TYPELESS = 94,
DXGI_FORMAT_BC6H_UF16 = 95,
DXGI_FORMAT_BC6H_SF16 = 96,
DXGI_FORMAT_BC7_TYPELESS = 97,
DXGI_FORMAT_BC7_UNORM = 98,
DXGI_FORMAT_BC7_UNORM_SRGB = 99,
DXGI_FORMAT_AYUV = 100,
DXGI_FORMAT_Y410 = 101,
DXGI_FORMAT_Y416 = 102,
DXGI_FORMAT_NV12 = 103,
DXGI_FORMAT_P010 = 104,
DXGI_FORMAT_P016 = 105,
DXGI_FORMAT_420_OPAQUE = 106,
DXGI_FORMAT_YUY2 = 107,
DXGI_FORMAT_Y210 = 108,
DXGI_FORMAT_Y216 = 109,
DXGI_FORMAT_NV11 = 110,
DXGI_FORMAT_AI44 = 111,
DXGI_FORMAT_IA44 = 112,
DXGI_FORMAT_P8 = 113,
DXGI_FORMAT_A8P8 = 114,
DXGI_FORMAT_B4G4R4A4_UNORM = 115,
DXGI_FORMAT_FORCE_UINT = 0xffffffffUL
} DXGI_FORMAT;
#define EncodeFourCC(x) ((((ui32_t)((x)[0])) ) | \
(((ui32_t)((x)[1])) << 8 ) | \
(((ui32_t)((x)[2])) << 16) | \
(((ui32_t)((x)[3])) << 24) )
static void LoadDDS(const char* name, byte** pic, int* width, int* height, qboolean* hasAlpha, int* glCompressMode, int* numMipmaps, int* piMipmapsAvailable) {
union {
byte* b;
void* v;
} buffer;
int len;
ddsHeader_t* ddsHeader = NULL;
ddsHeaderDxt10_t* ddsHeaderDxt10 = NULL;
byte* data;
*pic = 0;
*piMipmapsAvailable = 0;
if (width)
*width = 0;
if (height)
*height = 0;
*pic = NULL;
//
// load the file
//
len = ri.FS_ReadFile((char*)name, &buffer.v);
if (!buffer.b || len < 0) {
return;
}
//
// reject files that are too small to hold even a header
//
if (len < 4 + sizeof(*ddsHeader))
{
ri.Printf(PRINT_ALL, "File %s is too small to be a DDS file.\n", name);
ri.FS_FreeFile(buffer.v);
return;
}
//
// reject files that don't start with "DDS "
//
if (*((ui32_t*)(buffer.b)) != EncodeFourCC("DDS "))
{
ri.Printf(PRINT_ALL, "File %s is not a DDS file.\n", name);
ri.FS_FreeFile(buffer.v);
return;
}
//
// parse header and dx10 header if available
//
ddsHeader = (ddsHeader_t*)(buffer.b + 4);
if ((ddsHeader->pixelFormatFlags & DDSPF_FOURCC) && ddsHeader->fourCC == EncodeFourCC("DX10"))
{
if (len < 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10))
{
ri.Printf(PRINT_ALL, "File %s indicates a DX10 header it is too small to contain.\n", name);
ri.FS_FreeFile(buffer.v);
return;
}
ddsHeaderDxt10 = (ddsHeaderDxt10_t*)(buffer.b + 4 + sizeof(ddsHeader_t));
data = buffer.b + 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10);
len -= 4 + sizeof(*ddsHeader) + sizeof(*ddsHeaderDxt10);
}
else
{
data = buffer.b + 4 + sizeof(*ddsHeader);
len -= 4 + sizeof(*ddsHeader);
}
if (width)
*width = ddsHeader->width;
if (height)
*height = ddsHeader->height;
if (piMipmapsAvailable)
{
if (ddsHeader->flags & _DDSFLAGS_MIPMAPCOUNT)
*piMipmapsAvailable = ddsHeader->numMips;
else
*piMipmapsAvailable = 1;
}
// FIXME: handle cube map
//if ((ddsHeader->caps2 & DDSCAPS2_CUBEMAP) == DDSCAPS2_CUBEMAP)
//
// Convert DXGI format/FourCC into OpenGL format
//
if (ddsHeaderDxt10)
{
ri.Printf(PRINT_ALL, "DDS File %s has unsupported DXGI format %d.", name, ddsHeaderDxt10->dxgiFormat);
ri.FS_FreeFile(buffer.v);
return;
}
else
{
if (ddsHeader->pixelFormatFlags & DDSPF_FOURCC)
{
if (ddsHeader->fourCC == EncodeFourCC("DXT1"))
*glCompressMode = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
else if (ddsHeader->fourCC == EncodeFourCC("DXT2"))
*glCompressMode = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
else if (ddsHeader->fourCC == EncodeFourCC("DXT3"))
*glCompressMode = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
else if (ddsHeader->fourCC == EncodeFourCC("DXT4"))
*glCompressMode = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
else if (ddsHeader->fourCC == EncodeFourCC("DXT5"))
*glCompressMode = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
else
{
ri.Printf(PRINT_ALL, "DDS File %s has unsupported FourCC.", name);
ri.FS_FreeFile(buffer.v);
return;
}
}
else if (ddsHeader->pixelFormatFlags == (DDSPF_RGB | DDSPF_ALPHAPIXELS)
&& ddsHeader->rgbBitCount == 32
&& ddsHeader->rBitMask == 0x000000ff
&& ddsHeader->gBitMask == 0x0000ff00
&& ddsHeader->bBitMask == 0x00ff0000
&& ddsHeader->aBitMask == 0xff000000)
{
*glCompressMode = GL_RGBA8;
}
else
{
ri.Printf(PRINT_ALL, "DDS File %s has unsupported RGBA format.", name);
ri.FS_FreeFile(buffer.v);
return;
}
}
*pic = ri.Malloc(len);
Com_Memcpy(*pic, data, len);
ri.FS_FreeFile(buffer.v);
}
/*
=========================================================
@@ -1880,7 +2421,10 @@ Loads any of the supported image types into a cannonical
=================
*/
static void R_LoadImage(const char* name, byte** pic, int* width, int* height, qboolean* hasAlpha, int* glCompressMode, int* numMipmaps, int* piMipmapsAvailable) {
int len;
size_t len;
char tempName[MAX_STRING_TOKENS + 1];
char altname[MAX_QPATH];
*hasAlpha = qfalse;
*glCompressMode = 0;
@@ -1893,30 +2437,54 @@ static void R_LoadImage(const char* name, byte** pic, int* width, int* height, q
return;
}
if (!Q_stricmp(name + len - 4, ".tga")) {
LoadTGA(name, pic, width, height); // try tga first
if (!*pic) { //
char altname[MAX_QPATH]; // try jpg in place of tga
strcpy(altname, name);
len = strlen(altname);
altname[len - 3] = 'j';
altname[len - 2] = 'p';
altname[len - 1] = 'g';
LoadJPG(altname, pic, width, height);
strcpy(altname, name);
len = strlen(altname);
if (glConfig.textureCompression == 1)
{
len = strlen(altname);
altname[len - 3] = 'd';
altname[len - 2] = 'd';
altname[len - 1] = 's';
LoadDDS(altname, pic, width, height, hasAlpha, glCompressMode, numMipmaps, piMipmapsAvailable);
}
if (!*pic)
{
if (!Q_stricmp(name + len - 4, ".tga") || !Q_stricmp(name + len - 4, ".jpg")) {
if (r_loadjpg->integer) {
len = strlen(altname);
altname[len - 3] = 'j';
altname[len - 2] = 'p';
altname[len - 1] = 'g';
// try jpg first
LoadJPG(altname, pic, width, height);
}
if (!*pic) {
altname[len - 3] = 't';
altname[len - 2] = 'g';
altname[len - 1] = 'a';
LoadTGA(altname, pic, width, height);
}
*piMipmapsAvailable = 1;
}
else if (!Q_stricmp(name + len - 4, ".pcx")) {
LoadPCX32(name, pic, width, height);
*piMipmapsAvailable = 1;
}
else if (!Q_stricmp(name + len - 4, ".bmp")) {
LoadBMP(name, pic, width, height);
*piMipmapsAvailable = 1;
}
else if (!Q_stricmp(name + len - 4, ".jpg")) {
LoadJPG(name, pic, width, height);
*piMipmapsAvailable = 1;
}
*piMipmapsAvailable = 1;
}
else if (!Q_stricmp(name + len - 4, ".pcx")) {
LoadPCX32(name, pic, width, height);
*piMipmapsAvailable = 1;
}
else if (!Q_stricmp(name + len - 4, ".bmp")) {
LoadBMP(name, pic, width, height);
*piMipmapsAvailable = 1;
}
else if (!Q_stricmp(name + len - 4, ".jpg")) {
LoadJPG(name, pic, width, height);
*piMipmapsAvailable = 1;
if (scr_initialized)
{
sprintf(tempName, "n%s", name);
UI_LoadResource(tempName);
}
}
@@ -1959,7 +2527,7 @@ image_t* R_FindImageFile(const char* name, qboolean mipmap, qboolean allowPicmip
if (image->allowPicmip != allowPicmip) {
ri.Printf(PRINT_DEVELOPER, "WARNING: reused image %s with mixed allowPicmip parm\n", name);
}
if (image->wrapClampModeX != glWrapClampModeX || image != glWrapClampModeY) {
if (image->wrapClampModeX != glWrapClampModeX || image->wrapClampModeY != glWrapClampModeY) {
ri.Printf(PRINT_ALL, "WARNING: reused image %s with mixed glWrapClampMode parm\n", name);
}
}
@@ -2057,61 +2625,6 @@ static void R_CreateDlightImage( void ) {
tr.dlightImage = R_CreateImage("*dlight", (byte *)data, DLIGHT_SIZE, DLIGHT_SIZE, 0, 1, qfalse, qfalse, qfalse, qfalse, GL_CLAMP, GL_CLAMP);
}
/*
=================
R_InitFogTable
=================
*/
void R_InitFogTable( void ) {
int i;
float d;
float exp;
exp = 0.5;
for ( i = 0 ; i < FOG_TABLE_SIZE ; i++ ) {
d = pow ( (float)i/(FOG_TABLE_SIZE-1), exp );
tr.fogTable[i] = d;
}
}
/*
================
R_FogFactor
Returns a 0.0 to 1.0 fog density value
This is called for each texel of the fog texture on startup
and for each vertex of transparent shaders in fog dynamically
================
*/
float R_FogFactor( float s, float t ) {
float d;
s -= 1.0/512;
if ( s < 0 ) {
return 0;
}
if ( t < 1.0/32 ) {
return 0;
}
if ( t < 31.0/32 ) {
s *= (t - 1.0f/32.0f) / (30.0f/32.0f);
}
// we need to leave a lot of clamp range
s *= 8;
if ( s > 1.0 ) {
s = 1.0;
}
d = tr.fogTable[ (int)(s * (FOG_TABLE_SIZE-1)) ];
return d;
}
/*
==================
R_CreateDefaultImage
@@ -2146,6 +2659,7 @@ static void R_CreateDefaultImage( void ) {
data[x][DEFAULT_SIZE-1][3] = 255;
}
tr.defaultImage = R_CreateImage("*default", (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, 1, 1, qfalse, qfalse, qfalse, qfalse, GL_REPEAT, GL_REPEAT);
tr.defaultImage->r_sequence = -1;
}
/*
@@ -2155,6 +2669,8 @@ R_CreateBuiltinImages
*/
void R_CreateBuiltinImages( void ) {
int x,y;
int i;
byte lightmap_buffer[128 * 128 * 4];
byte data[DEFAULT_SIZE][DEFAULT_SIZE][4];
R_CreateDefaultImage();
@@ -2162,6 +2678,7 @@ void R_CreateBuiltinImages( void ) {
// we use a solid white image instead of disabling texturing
Com_Memset( data, 255, sizeof( data ) );
tr.whiteImage = R_CreateImage("*white", (byte *)data, 8, 8, 0, 1, qfalse, qfalse, qfalse, qfalse, GL_REPEAT, GL_REPEAT);
tr.whiteImage->r_sequence = -1;
// with overbright bits active, we need an image which is some fraction of full color,
// for default lightmaps, etc
@@ -2174,14 +2691,18 @@ void R_CreateBuiltinImages( void ) {
}
}
tr.identityLightImage = R_CreateImage("*identityLight", (byte *)data, 8, 8, 0, 1, qfalse, qfalse, qfalse, qfalse, GL_REPEAT, GL_REPEAT);
for(x=0;x<32;x++) {
// scratchimage is usually used for cinematic drawing
tr.scratchImage[x] = R_CreateImage("*scratch", (byte *)data, DEFAULT_SIZE, DEFAULT_SIZE, 0, 1, qtrue, qfalse, qfalse, qfalse, GL_REPEAT, GL_REPEAT);
Com_Memset(lightmap_buffer, 0xFFFFFFFF, sizeof(lightmap_buffer));
for (i = 0; i < 15; i++) {
tr.dlightImages[i] = R_CreateImage("*lightmapD%i", lightmap_buffer, LIGHTMAP_SIZE, LIGHTMAP_SIZE, 0, 1, qfalse, qfalse, qfalse, 0, GL_CLAMP, GL_CLAMP);
tr.dlightImages[i]->r_sequence = -1;
}
tr.identityLightImage = R_CreateImage("*identityLight", (byte *)data, 8, 8, 0, 1, qfalse, qfalse, qfalse, qfalse, GL_REPEAT, GL_REPEAT);
tr.identityLightImage->r_sequence = -1;
tr.scratchImage = R_CreateImage("*scratch", (byte*)data, DEFAULT_SIZE, DEFAULT_SIZE, 0, 1, qtrue, qfalse, qfalse, qfalse, GL_CLAMP, GL_CLAMP);
tr.scratchImage->r_sequence = -1;
R_CreateDlightImage();
}
@@ -2228,7 +2749,6 @@ void R_SetColorMappings( void ) {
tr.identityLight = 1.0f / (1 << tr.overbrightBits);
tr.identityLightByte = 255 * tr.identityLight;
if ( r_intensity->value <= 1 ) {
ri.Cvar_Set( "r_intensity", "1" );
}
@@ -2240,6 +2760,15 @@ void R_SetColorMappings( void ) {
}
g = r_gamma->value;
if (!glConfig.deviceSupportsGamma && g != 1.0) {
tr.needsLightScale = qtrue;
}
else if (r_intensity->value != 1.0) {
tr.needsLightScale = qtrue;
}
else {
tr.needsLightScale = qfalse;
}
shift = tr.overbrightBits;
@@ -2280,6 +2809,10 @@ R_InitImages
*/
void R_InitImages( void ) {
Com_Memset(hashTable, 0, sizeof(hashTable));
// clear images
Com_Memset(tr.images, 0, sizeof(tr.images));
tr.numImages = 0;
// build brightness translation tables
R_SetColorMappings();
+43 -2
View File
@@ -841,6 +841,13 @@ void GL_SetDefaultState( void )
qglEnable( GL_SCISSOR_TEST );
qglDisable( GL_CULL_FACE );
qglDisable( GL_BLEND );
qglFogi(GL_FOG_MODE, GL_LINEAR);
glState.fFogColor[0] = 0.0;
glState.fFogColor[1] = 0.0;
glState.fFogColor[2] = 0.0;
glState.fFogColor[3] = 1.0;
}
const char* RE_GetGraphicsInfo() {
@@ -1009,7 +1016,7 @@ void R_Register( void )
#else
r_smp = ri.Cvar_Get( "r_smp", "0", CVAR_ARCHIVE | CVAR_LATCH);
#endif
r_ignoreFastPath = ri.Cvar_Get("r_ignoreFastPath", "1", CVAR_ARCHIVE | CVAR_LATCH);
r_ignoreFastPath = ri.Cvar_Get("r_ignoreFastPath", "0", CVAR_ARCHIVE | CVAR_LATCH);
r_subdivisions = ri.Cvar_Get("r_subdivisions", "4", CVAR_ARCHIVE | CVAR_LATCH);
//
@@ -1200,6 +1207,21 @@ void R_Register( void )
ri.Cmd_AddCommand( "gfxinfo", GfxInfo_f );
}
void R_InitExtensions() {
// FIXME: qglTextureEnvCombineExists
glState.cntTexEnvExt = 0;
glState.cntnvblendmode = 0;
qglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_RGB, 34165.0);
qglTexEnvf(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, 8448.0);
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE0_RGB, 0x47057700);
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND0_RGB, 0x44400000);
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE1_RGB, 5890.0);
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND1_RGB, 0x44400000);
qglTexEnvf(GL_TEXTURE_ENV, GL_SOURCE2_RGB, 0x47057700);
qglTexEnvf(GL_TEXTURE_ENV, GL_OPERAND2_RGB, 770.0);
}
/*
===============
R_Init
@@ -1224,6 +1246,11 @@ void R_Init( void ) {
}
Com_Memset( tess.constantColor255, 255, sizeof( tess.constantColor255 ) );
tr.worldEntity.e.shaderRGBA[0] = -1;
tr.worldEntity.e.shaderRGBA[1] = 0;
tr.worldEntity.e.shaderRGBA[2] = -1;
tr.worldEntity.e.shaderRGBA[3] = -1;
//
// init function tables
//
@@ -1251,10 +1278,16 @@ void R_Init( void ) {
}
}
R_InitFogTable();
tr.rendererhandle = ri.Milliseconds();
if (!tr.rendererhandle) {
tr.rendererhandle = -1;
}
R_NoiseInit();
R_Sky_Init();
R_Register();
max_polys = r_maxpolys->integer;
@@ -1292,12 +1325,19 @@ void R_Init( void ) {
InitOpenGL();
R_InitExtensions();
R_InitImages();
R_StartupShaders();
R_ModelInit();
R_LevelMarksInit();
tr.pFontDebugStrings = R_LoadFont("verdana-14");
g_bInfoworldtris = qfalse;
err = qglGetError();
if ( err != GL_NO_ERROR )
ri.Printf (PRINT_ALL, "glGetError() = 0x%x\n", err);
@@ -1422,6 +1462,7 @@ refexport_t *GetRefAPI ( int apiVersion, refimport_t *rimp ) {
re.UnregisterServerModel = RE_UnregisterServerModel;
re.RegisterShader = RE_RegisterShader;
re.RegisterShaderNoMip = RE_RegisterShaderNoMip;
re.RefreshShaderNoMip = RE_RefreshShaderNoMip;
re.LoadWorld = RE_LoadWorldMap;
re.PrintBSPFileSizes = RE_PrintBSPFileSizes;
re.MapVersion = RE_MapVersion;
Loaded 100 of 162 files, more files were not shown because too many files have changed in this diff. Show more