Compare commits

...
216 Commits
Author SHA1 Message Date
smallmodel efeda23627 Fix player losing part torso animation during pain 2025-01-02 18:04:32 +01:00
smallmodel 465d462756 Automatically adjust the FOV depending on the aspect ratio 2025-01-02 15:52:45 +01:00
smallmodel df22895b94 Fix compile error 2025-01-02 15:30:34 +01:00
smallmodel 6b2160c876 Add putaway getter for Weapon 2025-01-02 14:27:39 +01:00
smallmodel 088b44e2cc Don't use the same weapon and add getters for the newActiveWeapon 2025-01-02 14:27:31 +01:00
smallmodel 3f299610fc Also try to find weapon by name in useWeapon() 2025-01-02 13:33:04 +01:00
smallmodel 713e361d85 Fix DM box position with resolutions above 1920x1080 2025-01-02 01:46:34 +01:00
smallmodel 869075f47b Disable audio virtualization on special audio sources such as music and ambient sounds
This prevents the music from being muffled by HRTF virtualization
2025-01-01 23:58:48 +01:00
smallmodel a067c58b3d Add EV_ScriptThread_FileClose2 to call fclose() without getting the return value 2025-01-01 23:38:49 +01:00
smallmodel b16aaa5adc Use a scripted object to store the C file handle for file functions 2025-01-01 12:40:59 +01:00
smallmodel f4a412cc24 Fix reverb toggle at runtime even if reverb is unimplemented 2024-12-31 13:04:33 +01:00
smallmodel d83ad43b0b Fix FPS model not being set correctly to match the world model 2024-12-30 20:24:49 +01:00
smallmodel aa9847cf90 Use clean Radix sort code from ioquake3 to sort draw surfaces 2024-12-30 19:18:54 +01:00
smallmodel 18a3658935 Ignore fast path if the drawsurf is a sprite 2024-12-30 19:18:20 +01:00
smallmodel 716a574abe Clean up terrain when shutting the Ref down 2024-12-30 18:51:10 +01:00
smallmodel e0dee12578 Clamp LOD terrain values 2024-12-30 16:16:17 +01:00
smallmodel 04b1e88077 Clamp r_subdivisions value 2024-12-30 16:13:50 +01:00
smallmodel 51a2f7d479 Use an enumeration for weapon commands and a function to get the weapon command
This improves clarity for using weapon commands. Also the mask was incorrect for protocol above version 8 (mohaas and mohaab)
2024-12-30 00:55:29 +01:00
smallmodel 2656000ce4 Print chat message from the game module instead of the server 2024-12-29 18:46:40 +01:00
smallmodel 4ec10af1fd Fix private message not working 2024-12-29 15:43:41 +01:00
smallmodel 78cd0cf28b Prevent firing weapon if there is a weapon command
This prevent tricks like firing and dropping weapon to shoot silently
2024-12-29 13:45:18 +01:00
smallmodel 3e9d2bf89a Fix incompatible type being used for shadertext 2024-12-27 17:33:29 +01:00
smallmodel ebe9795bba Select a random player skin when the bot dies 2024-12-25 15:08:57 +01:00
smallmodel 3f2c2f7aa4 Spectate the next player in mohaa 1.0 (instead of random) when pressing use in spectator 2024-12-25 15:08:00 +01:00
smallmodel 583c2720e2 Fix Info_RemoveKey not correctly removing the key 2024-12-25 15:00:32 +01:00
smallmodel 47d6843b70 Fix player model list never initialized 2024-12-25 14:50:11 +01:00
smallmodel 25fd01c46b Automatically switch to another weapon when the current weapon has no ammo 2024-12-24 20:19:08 +01:00
smallmodel 963b2a2bbd Add getters for Sentient inventory and ammo inventory 2024-12-24 20:04:59 +01:00
smallmodel 7274ceb0ff Make the bot melee when it is near the player 2024-12-24 19:53:20 +01:00
smallmodel cb1c3c0b1c Remove call to SV_WriteDownloadToClient() when sending snapshots, as it's already called when sending download messages 2024-12-24 18:42:05 +01:00
smallmodel da5c35ec2b Prevent connecting clients from receiving snapshots and CG messages while connecting 2024-12-24 18:30:08 +01:00
smallmodel 515beeafa7 Fix wrong fov clamping 2024-12-23 22:57:26 +01:00
smallmodel 37f5f64ef3 Update features.md 2024-12-23 22:55:17 +01:00
smallmodel 85c401496a Add a client-game variable for customizing the FOV client-side 2024-12-23 22:53:31 +01:00
smallmodel 07f7c557ce Move TargetArch.cmake to misc/cmake 2024-12-23 22:34:50 +01:00
smallmodel 31278fba92 Make sure to bind to the renderer FBO when drawing 2024-12-22 22:41:54 +01:00
smallmodel a32a9e8ae8 Update documentation about bots 2024-12-22 22:07:24 +01:00
smallmodel 70dc1820db Update README 2024-12-22 21:53:19 +01:00
smallmodel a760cb75a3 Use RE_AddPolyToScene2 for poly like beams 2024-12-22 20:27:59 +01:00
smallmodel 1d0b912f75 Make sure to check if the sprite is valid 2024-12-22 19:57:14 +01:00
smallmodel 439e0718ce Fix sprite rendering causing crashes 2024-12-22 19:16:27 +01:00
smallmodel 4c57ba6ef3 Fix currentStaticModel assignment 2024-12-22 19:03:11 +01:00
smallmodel b4bae40da8 Fix BSP minimum and maximum version on GL2 2024-12-22 19:00:15 +01:00
smallmodel e04cbd57ea Fix most shader errors, light rendering 2024-12-21 22:49:38 +01:00
smallmodel 66664b7b46 Add tr_vis 2024-12-21 21:43:29 +01:00
smallmodel 546b90d75f Add basic 3D GL2 rendering with static models and terrain 2024-12-21 17:04:31 +01:00
smallmodel 14e83a52a4 Add terrain rendering 2024-12-21 14:01:11 +01:00
smallmodel dc9fec9d03 Load JPEG file first before TGA 2024-12-20 23:35:14 +01:00
smallmodel 6d21d52d3e Define USE_INTERNAL_JPEG macro for renderer when using the internal JPEG 2024-12-20 23:31:03 +01:00
smallmodel 3afb87486b Add basic support for mohaa shaders for GL2 2024-12-20 23:21:28 +01:00
smallmodel d0c0a55e6d Fix drawing elements with color 2024-12-20 23:20:30 +01:00
smallmodel 1919b0efcb Fix Cvar_SetValue not set for ref imports 2024-12-20 23:11:37 +01:00
smallmodel 954d096261 Fix font rendering 2024-12-20 21:53:33 +01:00
smallmodel 7e150c7a8a Implement used draw functions 2024-12-20 21:27:10 +01:00
smallmodel 77646bda78 Implement RB_Stream draw surfaces 2024-12-20 21:21:10 +01:00
smallmodel e6848a3ab0 Fix the window sizer losing focus when rapidly dragging the mouse
This would lead to annoyances when trying to resize the window as the window sizer would lose focus
2024-12-20 20:13:05 +01:00
smallmodel 011f49616b Fix the improper focus and activation of pulldown menus 2024-12-20 19:35:27 +01:00
smallmodel e1be3c0fd1 Call G_SetClientConfigString() instead to properly set the team configstring 2024-12-20 19:13:17 +01:00
smallmodel 3d950764a2 Add minimal renderergl2 implementation
This implementation should just let the game run without crashing, the renderer doesn't show anything yet
2024-12-20 01:23:00 +01:00
smallmodel fe16f999d8 Use ri.Printf to print instead of the Com_* functions 2024-12-19 22:40:38 +01:00
smallmodel 390c1d3f3d Move tiki_mesh inclusion to renderercommon CMakeLists 2024-12-19 21:18:54 +01:00
smallmodel 49b5c29c11 Format renderergl1 source files 2024-12-19 21:13:39 +01:00
smallmodel f86b495cc6 Set all common renderer imports and add openmohaa imports after ioquake3 imports for more clarity 2024-12-19 20:09:52 +01:00
smallmodel a4d0a96ce5 Clear the camera jitter when ending the remote control 2024-12-19 19:52:29 +01:00
smallmodel 9d4ea75a18 Increase the number of aliases that can be found
Previously, 64 aliases could be chosen for random search, it was incremented to 128 since 2.0, however it should have been increased in Breakthrough as well, because there are aliases with more than 128 elements
2024-12-19 19:19:12 +01:00
smallmodel 38427fa3c5 Add support for compiling both opengl1 and opengl2 when they're built as shared libraries
renderercommon is now used, which will appropriately use opengl1 when building static libraries, or compile both opengl1/opengl2 modules when building shared libraries
2024-12-18 23:24:04 +01:00
smallmodel 7d369dec74 Don't render static mesh if there is no static xyz 2024-12-18 19:44:48 +01:00
smallmodel 58bef33bc7 Don't check if the TIKI model exists when initializing a static model
In later version like 2.0 and above, the TIKI model can be registered before static models which would prevent static xyz to be initialized
2024-12-18 19:41:28 +01:00
smallmodel bd021b109c Fix a terrible mistake in TIKI_FindTiki with uninitialized variable
This was using an uninitialized buffer to find the cached TIKI, in most configurations it always returned false, but when compiled with GCC it would return true
2024-12-18 19:31:21 +01:00
smallmodel 7e15c2ac1b Update features.md 2024-12-17 23:03:58 +01:00
smallmodel 3b1b994152 Fix temporary spawn spots being incorrectly ignored 2024-12-17 22:54:46 +01:00
smallmodel 4e69d7a78a Remove redundant code 2024-12-17 22:50:25 +01:00
smallmodel 16166a36b5 Fix spawnpoint metric for objective-based matches 2024-12-17 22:48:10 +01:00
smallmodel bcbe7cd870 Fix spawn point metric functions not counting the last player 2024-12-17 22:45:43 +01:00
smallmodel 8dba91fbcc Reopen doors to the other side when blocked 2024-12-17 22:17:02 +01:00
smallmodel 29fe5780e9 Only post the EV_MoveDone event if it's not pending when done moving
There are some situations where EV_MoveDone is posted again through a call to G_PushMove(), this avoids the mover unexpectedly and immediately moving to the new location
2024-12-17 22:15:53 +01:00
smallmodel 12686c0ab1 Format mover source file 2024-12-17 22:02:35 +01:00
smallmodel a21d712f54 Reopen the door to the other side if it's blocked 2024-12-17 21:30:48 +01:00
smallmodel 2c7d18b331 Initialize client persistent in G_InitClientPersistant 2024-12-17 21:16:45 +01:00
smallmodel e353673005 Fix player deaths (or total kills) being added twice in round-based matches 2024-12-17 21:11:34 +01:00
smallmodel 6b36bec8e9 Allow custom game ports other than 12203 to be specified through GAME_PORT environment variable 2024-12-17 19:29:17 +01:00
smallmodel 1be50cdddf Clear the attack time during reaction time 2024-12-17 14:01:13 +01:00
smallmodel 869b257bf8 Add a slight random response time before attacking
It's a way to make the fight less difficult between bots and players
2024-12-16 23:05:35 +01:00
smallmodel f165ebf9a3 Refactor G_ExitLevel 2024-12-16 23:03:15 +01:00
smallmodel a6c168c289 Count from 0 instead of CS_OBJECTIVES for more clarity 2024-12-16 22:13:26 +01:00
smallmodel 0057a8273c Initialize the total map time 2024-12-16 21:17:36 +01:00
smallmodel 876829a742 Properly aim the enemy
The bot wasn't aiming properly at the enemy because the bot was aiming from the centroid. It also caused issues when the enemy was crouching
2024-12-16 19:45:42 +01:00
smallmodel f4519325ce Speed up bot rotation 2024-12-16 19:41:01 +01:00
smallmodel 932367d061 Append "demo" to the keywords if fs_restrict is enabled 2024-12-15 21:32:34 +01:00
smallmodel 79643d963e Correctly parse the name of the players returned by the serverstatus command 2024-12-15 21:32:23 +01:00
smallmodel 872b3f5d70 Improve bot movement when stuck 2024-12-15 21:10:48 +01:00
smallmodel ac4138a763 Declare PID functions 2024-12-15 00:20:31 +01:00
smallmodel 0765537d29 Improve bot attack state
This should stop bot aiming forever behind walls and getting stuck to a wall
2024-12-14 23:32:17 +01:00
smallmodel f2f9ba9f83 Fix emulated death message incorrectly having a '?' at the beginning of each message on base game 2024-12-14 22:14:55 +01:00
smallmodel 20c1fab815 Don't set the frame number if the renderer function doesn't exist 2024-12-14 22:13:11 +01:00
smallmodel d3fb1331f8 Fix NDEBUG check 2024-12-14 20:09:33 +01:00
smallmodel 13eafb9bf1 Update server doc 2024-12-14 19:53:28 +01:00
smallmodel 1ef61a6e3d Use the PID file in non-debug builds
The PID file is used to check if openmohaa cleanly exited, and in case it didn't, the user is prompted to start in safe mode
2024-12-14 19:40:49 +01:00
smallmodel 0fb80a4ab5 Use unnamedsoldier.cfg config file if the openmohaa config file doesn't exist 2024-12-14 19:38:52 +01:00
smallmodel 981b12b63d Return a rounded number in G_GetAngle
There are scripts that compare the returned angle with an exact value and sometimes G_GetAngle return a value with a tiny fraction difference
2024-12-13 23:55:34 +01:00
smallmodel 508ee871b9 Add a small offset for checking if the player can get off ladder
This compensates with the difference with floating-point precision between architectures
2024-12-13 23:30:01 +01:00
smallmodel c293a52f7a Fix MASK_LADDER mask 2024-12-13 22:54:00 +01:00
smallmodel acf2dd0ad1 Use an integer when waiting
Since the expected time is in milliseconds, it's best to use an integer instead. Floating-point numbers lose precision as they get larger, especially when the level's current time is long (e.g., over 24 hours). This loss of precision could cause scripts to wait unsuccessfully with small numbers, causing unexpected behaviors
2024-12-13 22:17:43 +01:00
smallmodel 32bee2602c Rename mods to home 2024-12-13 20:37:13 +01:00
smallmodel d5ec17ec26 Allow subtitles to be set from stufftext 2024-12-13 19:24:58 +01:00
Bulldozer e53c6b55bf Update getting_started_installation.md
Spearhead was mentioned instead of Breakthrough.
2024-12-13 18:55:17 +01:00
smallmodel 85da9fabdd Fix incorrect event/return value for ScriptOrigin::GetAngleEvent 2024-12-12 23:50:42 +01:00
smallmodel e15440af5e Clear the view velocity when PMF_NO_MOVE is set 2024-12-12 22:52:28 +01:00
smallmodel 26c2225a24 Remove rate assertion 2024-12-12 22:45:44 +01:00
smallmodel cd06dc0535 Don't validate facet if there is an invalid border plane
The check was missing, which would cause a crash during collision test
2024-12-12 22:37:09 +01:00
smallmodel 1b8ef411ee Increase the value of MAX_PATCH_PLANES 2024-12-11 23:20:27 +01:00
smallmodel 95466b810f Prevent an infinite loop in ProcessPendingEvents() when an entity is being deleted in thinks 2024-12-11 21:55:31 +01:00
smallmodel 0a41f3bb76 Indicate when processing events 2024-12-11 21:55:22 +01:00
smallmodel 9b247a746c Add health check script to check for the state of the mohaa server 2024-12-11 20:19:34 +01:00
smallmodel fcdde53774 Use home instead of mods 2024-12-11 00:57:31 +01:00
smallmodel 279cfb364b Change the homepath instead of the game directory
Otherwise, clients would look for cgamex86.dll module that is inside the fs_game directory
2024-12-11 00:42:54 +01:00
smallmodel 3dcb2cad64 Fix typo 2024-12-10 23:07:57 +01:00
smallmodel a199188ede Add more stuff to build dev/server containers 2024-12-10 22:54:32 +01:00
smallmodel 8a84436d1b Fix Cmd_TokenizeString2 incorrectly ignoring extended ascii characters 2024-12-09 22:33:36 +01:00
smallmodel 231553f574 Fix round not ending when the clock reached 0:00
The wrong variable was being checked to end the round
2024-12-09 22:14:57 +01:00
smallmodel 37466cdffb Fix wrong condition for checking entity 2024-12-09 22:02:48 +01:00
smallmodel 3cc417151d Fix newlines for G_PrintToAllClients 2024-12-09 21:42:45 +01:00
smallmodel d26718a711 Fix teamkill kick warning not working 2024-12-09 21:32:38 +01:00
smallmodel 0644bc2967 Don't execute old commands from previous map when initializing cgame 2024-12-09 21:27:08 +01:00
smallmodel a2e4f1dc25 Use the server frametime when parsing baseline entities from the game state 2024-12-09 19:34:19 +01:00
smallmodel 9c952ab49d Set the map name from the server 2024-12-09 19:33:05 +01:00
smallmodel aa52fe73a5 Restart the file system when connected and when the local server has no paks 2024-12-09 19:31:58 +01:00
smallmodel fee6390281 Update README 2024-12-09 18:55:36 +01:00
smallmodel 835ddb1de3 Set the compass scale to 0.55 by default on the base game 2024-12-09 18:08:00 +01:00
smallmodel b58f031bcc Remove unused cg variables 2024-12-08 20:09:23 +01:00
smallmodel 3897a44ce6 Bump the version number 2024-12-08 19:58:59 +01:00
smallmodel 1ec88142b9 Put the value of the working directory in quotes 2024-12-08 19:46:36 +01:00
smallmodel 70a5dde726 Correctly handle long strings in chat and game message box 2024-12-08 19:22:25 +01:00
smallmodel f684349c18 Make sure to pop the loading screen on error
This fixes the client getting stuck in the loading screen due to a drop error
2024-12-08 18:47:10 +01:00
smallmodel a08a9a4f10 Remove TOKEN_NUMBER (unused)
Some maps use #xx to indicate an identifier, so remove this token to avoid errors
2024-12-08 18:24:33 +01:00
smallmodel f719b87e69 Handle identifiers that are present after strings, by marking strings as identifier 2024-12-08 18:15:26 +01:00
smallmodel af1cbea966 Also make players non-solid in a vehicle slot 2024-12-08 17:19:39 +01:00
smallmodel f3f53947bc Call the switch label only is the primary turret is valid 2024-12-08 16:43:58 +01:00
smallmodel f0cc34cccf Correctly parse identifiers starting with a number and containing non-numeric characters 2024-12-08 16:19:57 +01:00
smallmodel c4a1175ad0 Clear the invulnerable override when loading 2024-12-08 15:53:37 +01:00
smallmodel 333c452f44 Sanitize the name with a maximum buffer size limit 2024-12-08 12:51:14 +01:00
smallmodel 5801af34bb Don't execute newconfig.cfg
This prevents graphic settings from being overridden by the configuration file previously generated by the original game
2024-12-08 12:43:05 +01:00
smallmodel da0c36cc88 Also show the port of clients in status 2024-12-08 12:40:21 +01:00
smallmodel d8d98ade6a Set the default sound quality to 44 Hz 2024-12-08 12:37:59 +01:00
smallmodel c3157ad4d7 Use DebugPrintf for errors that are relevant to developers 2024-12-06 20:36:12 +01:00
smallmodel 6f686cb7fa Check if the renderer is loaded instead of checking if it's registered 2024-12-06 00:45:18 +01:00
smallmodel 39981643a8 Fix incorrect count when unloading sgl fonts 2024-12-06 00:45:12 +01:00
smallmodel 28bdd1b2b3 Made the renderer modular and loadable
This removes coupling between the renderer and UI/client functions. An option USE_RENDERER_DLOPEN was added to specify whether a renderer module should be compiled and loaded, instead of integrating the renderer into the executable directly. This opens the door for a new renderer
2024-12-06 00:15:19 +01:00
smallmodel 35f40e949b Properly clear UI resources when shutting down the UI 2024-12-05 23:31:38 +01:00
smallmodel 115b7b82aa Correctly handle the scenario where multiple architectures are specified
Each target will produce a single binary having multiple architectures, instead of having a binary per architecture. The suffix for each binary will be `multiarch`. This makes it easier for the end-user to install and use. This also helps the transition between Intel and Apple Silicon hardware
2024-12-05 21:12:19 +01:00
smallmodel d7c0ee47fe Check if the skel is valid before freeing it 2024-12-05 00:42:50 +01:00
smallmodel 0559d643b7 Use TIKI_DPrintf instead of Skel_DPrintf 2024-12-05 00:42:31 +01:00
smallmodel 8446a655bb Print an error when the skel file extension is unknown 2024-12-04 22:33:42 +01:00
smallmodel 01d098dab5 Clear the number of uses of the skel cache when registering a new skeleton 2024-12-04 22:33:28 +01:00
smallmodel b6dd3914be Correctly free skels when freeing TIKIs
This fixes a potential memory leak that would occur when the first skelcache's skel is NULL
2024-12-04 22:30:26 +01:00
smallmodel c2e45710ad Improve code clarity 2024-12-04 22:15:01 +01:00
smallmodel 5da24a8ab5 Update mac runner OS to macos-15 2024-12-04 19:37:45 +01:00
smallmodel ac6b274a4f Use MAP_SIZE instead of MAX_MAP_BOUNDS
This fixes collision being incorrect on big maps
2024-12-04 19:22:56 +01:00
smallmodel f703ee2f26 Add a section about installing official patches and improve clarity 2024-12-03 23:09:43 +01:00
smallmodel 70b8f9868e Use GameFront for links to demos 2024-12-03 22:29:53 +01:00
smallmodel c69bafeb3f Add a section about cleaning up the game directory 2024-12-03 21:07:18 +01:00
smallmodel f7c8c745c4 Don't return a slash at the end for directory name 2024-12-02 21:08:42 +01:00
smallmodel 861338b0fc Add support for smaller lightmaps
Large lightmap can be disabled for very low-end hardware. A BSP file with a smaller lightmap (_sml.bsp) will be used instead of the standard one if the map supports it
2024-12-02 20:36:45 +01:00
smallmodel 499fe44bde Call R_RegisterShaderNoMip for the crosshair
This prevents the crosshair texture from being altered by the texture quality settings
2024-12-02 19:00:43 +01:00
smallmodel ba74943844 Fix picmip adjustment 2024-12-02 18:59:48 +01:00
smallmodel 21f631e733 Compile SDL input/client and SDL OpenGL independently
This decouple the renderer from the client part of SDL (input), and only uses SDL for OpenGL
2024-12-01 22:23:28 +01:00
smallmodel b5c32a41de Check for tabs alongside spaces in the lexer between expressions and variables
This fixes a compile error in some scripts that use tabs instead of spaces between expressions
2024-12-01 20:36:30 +01:00
smallmodel c9373cbc97 Comment out ABI compatibility checks 2024-12-01 20:34:38 +01:00
smallmodel b5a73384d3 Exclude the slash at the beginning of each file for FS_ListFilteredFiles 2024-12-01 20:33:51 +01:00
smallmodel 4f699f3b58 Add support to compile renderergl2 (currently unimplemented) 2024-12-01 19:21:07 +01:00
smallmodel 4ea598d76b Reimplement SkipBracedSection 2024-12-01 17:53:51 +01:00
smallmodel 7e6b0a1c2b Remove SMP and render thread code, as they're unused 2024-12-01 16:32:19 +01:00
smallmodel d884512a76 Update renderergl2 from upstream ioq3 2024-12-01 15:41:48 +01:00
smallmodel 71450fb36e Move renderer to renderergl1 2024-12-01 15:30:23 +01:00
smallmodel 4775f29194 Fix build warnings and errors 2024-11-30 23:36:37 +01:00
smallmodel d5d5c7a55d Use bits per sample rather than bytes as there are 4-bit sounds 2024-11-30 23:23:49 +01:00
smallmodel aa74934ae0 Fix huddraw scaling with high resolutions 2024-11-30 23:21:20 +01:00
smallmodel 0534482c22 Fix a small mistake where it uses vidWidth rather than vidHeight 2024-11-30 23:08:23 +01:00
smallmodel 6fe1e86b31 Automatically scale UI elements for high resolutions
This fixes UI elements being tiny on high resolutions like 4K. Now most UI elements will scale automatically with resolutions above 1920x1080.
2024-11-30 22:40:00 +01:00
smallmodel 47983481c9 Use UI definitions instead of cls.glconfig for UI code to get the resolution 2024-11-30 13:54:50 +01:00
smallmodel 383bc60ddb Update OpenAL to 1.24.1 2024-11-30 00:40:41 +01:00
smallmodel d834f08cad Update compiling.md with current version of tools to use 2024-11-30 00:40:35 +01:00
smallmodel 387ccd5cc3 Bump the minimum CMake version to 3.12 2024-11-30 00:36:33 +01:00
smallmodel 0fb775cd60 Only set the infoclient if it's a teammate player that can be sent to other clients 2024-11-29 23:45:52 +01:00
smallmodel f31ea39331 Add about tweaking the build 2024-11-29 23:00:57 +01:00
smallmodel 56cc3fff53 Use a single variable to disable modern DMA 2024-11-29 22:53:04 +01:00
smallmodel 5f33a617ab Allow linking directly against system OpenAL library 2024-11-29 22:03:39 +01:00
smallmodel b3da62f77e Don't use an offset for constArrayValue
This is risky and a bad practice to offset a pointer. This also fixes the compiler warning
2024-11-29 21:58:07 +01:00
smallmodel f1e5d02169 Fix insecure printf format 2024-11-29 21:48:56 +01:00
smallmodel 7cad7a4bd0 Fix printf format specifiers 2024-11-29 21:34:41 +01:00
smallmodel 83a874e4fd Add an option for CMake to specify when targeting the local system 2024-11-29 20:59:47 +01:00
Joey Riches 6eab2ddd57 CMake: Support lib extension on unix
Some distros install to lib64 instead of lib, respect the lib extension
otherwise some {f,c}game gets installed to lib64 and other libs get
installed to lib.
2024-11-28 00:49:00 +01:00
smallmodel d944b4a21e Fix wrong command name for ForceDropHealth 2024-11-27 22:40:40 +01:00
smallmodel 58f0245e83 Only add entries for servers that were queried successfully 2024-11-27 22:12:55 +01:00
smallmodel 2f8382f100 Initialize m_bMumble 2024-11-27 21:15:49 +01:00
smallmodel 167bd45a6a Make the AI rarely play the standidentify animation (pointing finger to the player) 2024-11-27 21:14:51 +01:00
smallmodel 1e9decf193 Add support for IMA-ADPCM sounds (4-bit)
Sounds such as sea waves (mohaa m3l1a) and subpen (mohaas flughafen) will be played accordingly. This uses OpenAL extensions such as AL_EXT_IMA4 and SOFT features such as AL_SOFT_block_alignment
2024-11-27 20:37:56 +01:00
smallmodel 459e13dc76 Allow pusher to teleport
This fixes an issue where teamslaves (bind elements) would not be in sync with the pusher
2024-11-27 14:36:16 +01:00
smallmodel 94e3d95d6c Update getting_started_installation.md 2024-11-27 14:35:07 +01:00
smallmodel eeb9139024 Fix incorrect delta for FaceEnemyOrMotion
The AI would not consistently aim at the enemy while covering
2024-11-27 11:57:05 +01:00
smallmodel 486b6f40e5 Don't play sound if the parameter is not specified 2024-11-26 22:47:55 +01:00
smallmodel d3fdaa060a Fix bad parameters passed to CG_AnimationDebugMessage 2024-11-26 19:21:18 +01:00
smallmodel 766258e84b Archive instances of SmokeGrenade
This was mistakenly missing and fixes smoke grenade explosions disappearing after loading from save
2024-11-26 18:38:34 +01:00
smallmodel 8213bf41a8 Fix player having no inventory or dying when respawning immediately after getting killed 2024-11-26 00:53:38 +01:00
smallmodel 8843a8ee15 Remove owner assert
The owner can be NULL so there is no reason to assert on this
2024-11-26 00:36:47 +01:00
smallmodel 6bb09256c5 Teleport the player back to (0,0,0) origin if out of map bounds 2024-11-25 22:32:08 +01:00
smallmodel b2e6e1b56f Comment out the Illegal XYZ coordinates message to avoid spamming the console 2024-11-25 22:30:44 +01:00
smallmodel 6b402e5215 Format g_phys source file 2024-11-25 22:21:51 +01:00
smallmodel 04baf673dc Set MAX_MAP_BOUNDS to 8192 2024-11-25 22:12:47 +01:00
smallmodel 10b7651eff Use getters for max fire movement and zoom movement 2024-11-25 22:12:29 +01:00
smallmodel 4f76d7291f Fix typo 2024-11-25 21:02:52 +01:00
smallmodel 1c2be68253 Update getting started (installation) 2024-11-25 20:36:42 +01:00
smallmodel 6c9d6940cc Disable sv_floodProtect by default 2024-11-25 19:35:37 +01:00
smallmodel b719455b78 Add the missing newline for iprintln functions 2024-11-25 19:18:15 +01:00
smallmodel db16c8bea4 Localize player IPrint string 2024-11-25 19:09:02 +01:00
smallmodel abdaecb28d Update README 2024-11-25 19:08:03 +01:00
315 changed files with 41561 additions and 49794 deletions

No files matched your search

+13 -16
View File
@@ -63,13 +63,6 @@ jobs:
echo "CXX=clang++" >> $GITHUB_ENV
echo "CFLAGS='--target=${{ matrix.architecture.triple }}'" >> $GITHUB_ENV
echo "CXXFLAGS='--target=${{ matrix.architecture.triple }}'" >> $GITHUB_ENV
# Temporary workaround for PowerPC as the 1.24.0 version doesn't check for altivec
# Will use older versions until a new tag is created with this issue resolved
if [ ${{ matrix.architecture.name }} != 'powerpc' ] && [ ${{ matrix.architecture.name }} != 'ppc64' ] && [ ${{ matrix.architecture.name }} != 'ppc64el' ]; then
echo "OPENAL_REF=1.24.0" >> $GITHUB_ENV
else
echo "OPENAL_REF=1.23.1" >> $GITHUB_ENV
fi
###
# SDL
@@ -95,7 +88,7 @@ jobs:
with:
repository: 'kcat/openal-soft'
path: 'thirdparties/soft-oal'
ref: ${{ env.OPENAL_REF }}
ref: '1.24.1'
- name: Configure and install soft-oal
working-directory: ${{github.workspace}}/thirdparties/soft-oal
@@ -249,7 +242,7 @@ jobs:
with:
repository: 'kcat/openal-soft'
path: 'thirdparties/soft-oal'
ref: '1.24.0'
ref: '1.24.1'
# soft-oal build
# Statically link the CRT runtime into OAL as a workaround to prevent crashes
@@ -352,12 +345,16 @@ jobs:
strategy:
matrix:
architecture: [
{name: 'x86_64', triple: 'x86_64-apple-macos10.8'},
{name: 'arm64', triple: 'arm64-apple-macos11'}
#{name: 'x86_64', triple: 'x86_64-apple-macos10.8'},
#{name: 'arm64', triple: 'arm64-apple-macos11'}
#{name: 'x86_64', build_name: 'x86_64'},
#{name: 'arm64', build_name: 'arm64'},
# Compile into an universal binary
{name: 'multiarch(arm64-x86_64)', build_name: 'arm64;x86_64' }
]
name: "Building for platform macos-${{matrix.architecture.name}}"
runs-on: "macos-14"
runs-on: "macos-15"
environment: ${{inputs.environment}}
steps:
@@ -390,7 +387,7 @@ jobs:
with:
version: 2-latest
build-type: Release
cmake-arguments: "-DCMAKE_OSX_ARCHITECTURES=${{ matrix.architecture.name }}
cmake-arguments: "-DCMAKE_OSX_ARCHITECTURES='${{ matrix.architecture.build_name }}'
-DCMAKE_VERBOSE_MAKEFILE=on"
###
# OpenAL
@@ -404,14 +401,14 @@ jobs:
with:
repository: 'kcat/openal-soft'
path: 'thirdparties/soft-oal'
ref: '1.24.0'
ref: '1.24.1'
- name: Configure and install soft-oal
working-directory: ${{github.workspace}}/thirdparties/soft-oal
run: |
cmake -B ./build \
-DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/soft-oal/install' \
-DCMAKE_OSX_ARCHITECTURES=${{ matrix.architecture.name }} \
-DCMAKE_OSX_ARCHITECTURES='${{ matrix.architecture.build_name }}' \
-DCMAKE_VERBOSE_MAKEFILE=on
cmake --build ./build --config Release --parallel
cmake --install ./build --config Release
@@ -429,7 +426,7 @@ jobs:
echo "CMAKE_PARAM=--log-level=VERBOSE \
-DCMAKE_INSTALL_PREFIX='${{github.workspace}}/install' \
-DCMAKE_VERBOSE_MAKEFILE=on \
-DCMAKE_OSX_ARCHITECTURES=${{ matrix.architecture.name }} \
-DCMAKE_OSX_ARCHITECTURES='${{ matrix.architecture.build_name }}' \
-DOPENAL_LIBRARY='${{github.workspace}}/thirdparties/soft-oal/install' \
-DOPENAL_INCLUDE_DIR='${{github.workspace}}/thirdparties/soft-oal/install/include/AL' \
-DGIT_REVISION_BUILD_NUMBER=${{ github.run_number }} \
+5 -4
View File
@@ -38,8 +38,9 @@ jobs:
'windows-x86-pdb',
'windows-arm64',
'windows-arm64-pdb',
'macos-x86_64',
'macos-arm64'
#'macos-x86_64',
#'macos-arm64',
'macos-multiarch(arm64-x86_64)',
]
runs-on: ubuntu-24.04
@@ -56,8 +57,8 @@ jobs:
path: ${{github.workspace}}/${{matrix.target_os}}
- name: Zip
working-directory: ${{github.workspace}}/${{matrix.target_os}}
run: zip -r ../${{ env.RELEASE_NAME }}.zip ./
working-directory: '${{github.workspace}}/${{matrix.target_os}}'
run: zip -r "../${{ env.RELEASE_NAME }}.zip" ./
- name: Release
uses: softprops/action-gh-release@v2
+34 -25
View File
@@ -1,9 +1,10 @@
cmake_minimum_required(VERSION 3.5)
cmake_minimum_required(VERSION 3.12)
project(openmohaa)
include(TargetArch.cmake)
include(misc/cmake/TargetArch.cmake)
target_architecture(TARGET_ARCH)
list(LENGTH TARGET_ARCH TARGET_ARCH_COUNT)
set(USE_INTERNAL_LIBS ON)
if(USE_SYSTEM_LIBS)
@@ -13,12 +14,13 @@ endif()
option(USE_INTERNAL_JPEG "If set, use bundled libjpeg." ${USE_INTERNAL_LIBS})
option(USE_INTERNAL_MAD "If set, use bundled libmad." ${USE_INTERNAL_LIBS})
option(USE_INTERNAL_ZLIB "If set, use bundled zlib." ${USE_INTERNAL_LIBS})
option(USE_RENDERER_DLOPEN "Whether to compile the renderer as separate pluggable modules" OFF)
option(TARGET_LOCAL_SYSTEM "Indicate that the project will be compiled and installed for the local system" OFF)
if(TARGET_GAME_TYPE)
message(SEND_ERROR "TARGET_GAME_TYPE is now unsupported, it is now done at runtime.")
endif()
set(TARGET_BASE_GAME "./")
set(CMAKE_DEBUG_POSTFIX "-dbg")
@@ -62,27 +64,39 @@ if(DEBUG_MEMORY)
add_definitions(-D_DEBUG_MEM)
endif()
IF("${TARGET_ARCH}" STREQUAL "i386")
if("${TARGET_ARCH}" STREQUAL "i386")
set(TARGET_ARCH_SUFFIX "x86")
ELSE()
else()
set(TARGET_ARCH_SUFFIX ${TARGET_ARCH})
ENDIF()
endif()
set(TARGET_BIN_SUFFIX ".${TARGET_ARCH}")
message(STATUS "Architecture detected: ${TARGET_ARCH}")
message(STATUS "Architecture detected: ${TARGET_ARCH}, suffix set to ${TARGET_ARCH_SUFFIX}.")
if(TARGET_LOCAL_SYSTEM)
add_definitions(-DTARGET_LOCAL_SYSTEM)
# As it targets the local system, no need to know about the architecture used
set(TARGET_BIN_SUFFIX "")
message(STATUS "Binary suffix will not be used as the local system is the target")
elseif(${TARGET_ARCH_COUNT} GREATER 1)
add_definitions(-DTARGET_MULTIPLE_ARCHITECTURES)
set(TARGET_BIN_SUFFIX ".multiarch")
message(STATUS "Multiple architectures were specified, suffix set to 'multiarch'.")
else()
set(TARGET_BIN_SUFFIX ".${TARGET_ARCH}")
message(STATUS "Binary suffix set to '${TARGET_ARCH_SUFFIX}'.")
endif()
IF(WIN32)
if(WIN32)
set(TARGET_PLATFORM_PREFIX "")
message(STATUS "Using Win32 naming convention")
ELSEIF(UNIX)
elseif(UNIX)
set(TARGET_PLATFORM_PREFIX "")
message(STATUS "Using Unix naming convention")
ELSE()
else()
set(TARGET_PLATFORM_PREFIX "")
ENDIF()
endif()
IF(CMAKE_BUILD_TYPE MATCHES Debug)
if(CMAKE_BUILD_TYPE MATCHES Debug)
add_compile_definitions(_DEBUG)
# NOTE: The following may mess up function importation
@@ -91,10 +105,10 @@ IF(CMAKE_BUILD_TYPE MATCHES Debug)
# set(CMAKE_ENABLE_EXPORTS ON)
# message(STATUS "Enabling exports on Unix for backtrace")
#endif()
ELSE()
else()
# Non-debug builds
add_compile_definitions(NDEBUG)
ENDIF()
endif()
if(APPLE)
# macOS doesn't search the executable path by default
@@ -120,7 +134,7 @@ if(WIN32)
set(LIB_INSTALL_SUBDIR ".")
else()
# Unix
set(CMAKE_DEFAULT_INSTALL_RUNTIME_DIR lib)
set(CMAKE_DEFAULT_INSTALL_RUNTIME_DIR lib${CMAKE_LIB_SUFFIX})
set(BIN_INSTALL_SUBDIR ${CMAKE_PROJECT_NAME})
set(LIB_INSTALL_SUBDIR ${CMAKE_PROJECT_NAME})
endif()
@@ -171,23 +185,19 @@ if (NOT BUILD_NO_CLIENT)
##
## Client app
##
option(NO_MODERN_DMA "Use older sound-system" FALSE)
add_subdirectory("code/client")
add_subdirectory("code/renderer")
add_subdirectory("code/renderercommon")
add_subdirectory("code/sdl")
#include("code/renderergl2/glsl/shaders.cmake")
#file(GLOB_RECURSE SOURCES_RENDERER "code/sdl/*.c" "code/renderercommon/*.c" "code/renderergl2/*.c" "code/renderergl2/*.cpp")
#list(FILTER SOURCES_RENDERER EXCLUDE REGEX "code/renderergl2/tr_subs.c")
#list(FILTER SOURCES_RENDERER EXCLUDE REGEX "code/renderergl2/tr_model.c")
add_executable(openmohaa "misc/dummy.c")
target_link_libraries(openmohaa PRIVATE syslib)
target_link_libraries(openmohaa PRIVATE omohserver)
target_link_libraries(openmohaa PRIVATE omohclient)
target_link_libraries(openmohaa PRIVATE omohrenderer omohsdl)
target_link_libraries(openmohaa PRIVATE omohrenderer)
target_link_libraries(openmohaa PRIVATE qcommon qcommon_standalone)
# Add the gamespy dependency
target_include_directories(openmohaa PUBLIC "code/qcommon" "code/script" "code/gamespy" "code/server" "code/client" "code/uilib")
set_target_properties(openmohaa PROPERTIES OUTPUT_NAME "openmohaa${TARGET_BIN_SUFFIX}")
@@ -260,4 +270,3 @@ if(NOT TARGET uninstall)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
endif()
+4 -4
View File
@@ -10,7 +10,7 @@
## Intro
The main goal of OpenMoHAA is to ensure the future and continuity of **Medal of Honor: Allied Assault** on all platforms/architectures by providing new patches/features. Thanks to the ioquake3 project and the F.A.K.K SDK, OpenMoHAA has already reached more than half of its goal: an open-source version of MoH:AA (based on version 2.40) that is fully compatible with the original game (in terms of protocol, assets, and scripts).
The main goal of OpenMoHAA is to ensure the future and continuity of **Medal of Honor: Allied Assault** (including Spearhead and Breakthrough expansions) on all platforms/architectures by providing new patches/features. Thanks to the ioquake3 project and the F.A.K.K SDK, OpenMoHAA has already reached more than half of its goal: an open-source version of MoH:AA (based on version 2.40) that is fully compatible with both the original game and expansions, in terms of network protocol, assets, and scripts. OpenMoHAA is compatible with both MOH:AA servers and clients (Spearhead and Breakthrough included).
## Getting started
@@ -26,11 +26,11 @@ The entire single-player campaign should work (Allied Assault, Spearhead and Bre
### Multiplayer
The Multiplayer part is almost fully stable.
The Multiplayer part is almost fully stable, all game modes including `Tug-of-War` from Medal of Honor: Spearhead, and `Liberation` from Medal of Honor: Breakthrough are implemented and are working as intended. Mods like `Freeze-Tag` are working as well.
Server admins can use OpenMoHAA to [host](docs/getting_started_installation.md#server) a mohaa/mohaas/mohaab server. Bugs must be reported by creating a new [issue](https://github.com/openmoh/openmohaa/issues) on the OpenMoHAA GitHub project. Players can use OpenMoHAA to [play](docs/getting_started_installation.md#client) on a mohaa/mohaas/mohaab server.
OpenMoHAA can be used to [host](docs/getting_started_installation.md#server) a mohaa/mohaas/mohaab server and players can use OpenMoHAA to [play](docs/getting_started_installation.md#client) on any server. If some bugs/strange behavior occurs, the best way to report them is by [creating a new issue](https://github.com/openmoh/openmohaa/issues) on the [OpenMoHAA GitHub](https://github.com/openmoh/openmohaa) project with the steps to reproduce (with eventually the problematic mods).
All game modes including `Tug-of-War` from Medal of Honor: Spearhead, and `Liberation` from Medal of Honor: Breakthrough are implemented and are working as intended. Mods like `Freeze-Tag` are working as well.
One of the big multiplayer features are bots. They were introduced for testing and for entertainment purposes so players can have fun alone. See [Configuring bots](docs/configuration/server.md#bots) in the dedicated server configuration documentation to set them up.
## Features
+2
View File
@@ -1,3 +1,5 @@
cmake_minimum_required(VERSION 3.12)
project(Launcher)
set(LAUNCHER_SOURCES "${CMAKE_SOURCE_DIR}/code/Launcher/launch_main.cpp")
+2 -2
View File
@@ -38,9 +38,9 @@ const char* targetGameList[] =
int main(int argc, const char* argv[]) {
std::vector<std::string> argumentList;
#if !defined(DEDICATED) || !DEDICATED
const char* programName = "openmohaa" "." ARCH_STRING DLL_SUFFIX EXE_EXT;
const char* programName = "openmohaa" ARCH_SUFFIX DLL_SUFFIX EXE_EXT;
#else
const char* programName = "omohaaded" "." ARCH_STRING DLL_SUFFIX EXE_EXT;
const char* programName = "omohaaded" ARCH_SUFFIX DLL_SUFFIX EXE_EXT;
#endif
argumentList.push_back("+set");
+1 -1
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.5)
cmake_minimum_required(VERSION 3.12)
project(cgame)
# Shared source files for modules
+9 -9
View File
@@ -3866,7 +3866,7 @@ void ClientGameCommandManager::PlaySound(
}
if (!name || !soundAlias) {
Com_Printf(
cgi.DPrintf(
"\nERROR PlaySound: %s needs an alias in ubersound.scr or uberdialog.scr - Please fix.\n",
sound_name.c_str()
);
@@ -4066,7 +4066,7 @@ void ClientGameCommandManager::StopAliasChannel(Event *ev)
}
if (!name || !soundAlias) {
Com_Printf("\nERROR stopaliaschannel: couldn't find alias %s\n", sound_name.c_str());
cgi.DPrintf("\nERROR stopaliaschannel: couldn't find alias %s\n", sound_name.c_str());
return;
}
@@ -4145,8 +4145,8 @@ void ClientGameCommandManager::StopLoopSound(Event* ev)
return;
}
Com_Printf("\n\nClientGameCommandManager::StopLoopSound\n\n");
current_centity->tikiLoopSound = NULL;
cgi.DPrintf("\n\nClientGameCommandManager::StopLoopSound\n\n");
current_centity->tikiLoopSound = (sfxHandle_t)0;
}
//===============
@@ -4265,7 +4265,7 @@ qboolean bLoadForMap(const char *psMapsBuffer, const char *name)
}
if (!token || !token[0]) {
Com_Printf("ERROR bLoadForMap: %s alias with empty maps specification.\n", name);
cgi.DPrintf("ERROR bLoadForMap: %s alias with empty maps specification.\n", name);
return false;
}
@@ -5179,7 +5179,7 @@ void CG_ProcessInitCommands(dtiki_t *tiki, refEntity_t *ent)
}
if (!commandManager.SelectProcessEvent(ev)) {
Com_Printf(
cgi.DPrintf(
"^~^~^ CG_ProcessInitCommands: Bad init client command '%s' in '%s'\n", pcmd->args[0], tiki->name
);
}
@@ -5225,7 +5225,7 @@ void CG_ProcessCacheInitCommands(dtiki_t *tiki)
}
if (!commandManager.SelectProcessEvent(ev)) {
Com_Printf(
cgi.DPrintf(
"^~^~^ CG_ProcessInitCommands: Bad init client command '%s' in '%s'\n", pcmd->args[0], tiki->name
);
}
@@ -5298,7 +5298,7 @@ qboolean CG_ProcessEntityCommands(int frame, int anim, int entnum, refEntity_t *
current_centity = cent;
current_entity_number = entnum;
current_tiki = ent->tiki;
CG_AnimationDebugMessage(entnum, "Processing Ent Commands: Entity: %3d Anim:#(%i) Frame:#(%i)\n", anim, frame);
CG_AnimationDebugMessage(entnum, "Processing Ent Commands: Entity: %3d Anim:#(%i) Frame:#(%i)\n", entnum, anim, frame);
for (i = 0; i < tikicmds.num_cmds; i++) {
Event *ev;
@@ -5840,7 +5840,7 @@ void ClientGameCommandManager::SetCurrentTiki(Event *ev)
str tikiName;
if (ev->NumArgs() != 1) {
Com_Printf("ERROR: settiki command takes 1 parameter.\n");
cgi.DPrintf("ERROR: settiki command takes 1 parameter.\n");
return;
}
+1 -1
View File
@@ -705,5 +705,5 @@ int CG_WeaponCommandButtonBits(void)
cg.iWeaponCommand = 0;
}
return iShiftedWeaponCommand & WEAPON_COMMAND_MASK;
return iShiftedWeaponCommand & GetWeaponCommandMask(cg_protocol >= PROTOCOL_MOHTA_MIN ? WEAPON_COMMAND_MAX_VER17 : WEAPON_COMMAND_MAX_VER6);
}
+121 -47
View File
@@ -191,8 +191,8 @@ void CG_DrawDisconnect(void)
}
handle = cgi.R_RegisterShader("gfx/2d/net.tga");
w = cgi.R_GetShaderWidth(handle);
h = cgi.R_GetShaderHeight(handle);
w = cgi.R_GetShaderWidth(handle) * cgs.uiHiResScale[0];
h = cgi.R_GetShaderHeight(handle) * cgs.uiHiResScale[1];
x = ((float)cgs.glconfig.vidWidth - w) * 0.5;
y = (float)cgs.glconfig.vidHeight - h;
@@ -331,7 +331,7 @@ static void CG_DrawPauseIcon()
x = (cgs.glconfig.vidWidth - w) / 2.f;
cgi.R_SetColor(colorWhite);
cgi.R_DrawStretchPic(x, y, w, h, 0, 0, 1, 1, handle);
cgi.R_DrawStretchPic(x, y, w * cgs.uiHiResScale[0], h * cgs.uiHiResScale[1], 0, 0, 1, 1, handle);
}
static void CG_DrawServerLag()
@@ -362,8 +362,8 @@ static void CG_DrawServerLag()
}
handle = cgi.R_RegisterShader("gfx/2d/slowserver");
w = (float)cgi.R_GetShaderWidth(handle) / 4;
h = (float)cgi.R_GetShaderHeight(handle) / 4;
w = (float)cgi.R_GetShaderWidth(handle) * cgs.uiHiResScale[0] / 4;
h = (float)cgi.R_GetShaderHeight(handle) * cgs.uiHiResScale[1] / 4;
x = ((float)cgs.glconfig.vidWidth - w) / 2;
y = (float)cgs.glconfig.vidHeight - h;
cgi.R_DrawStretchPic(x, y, w, h, 0.0, 0.0, 1.0, 1.0, handle);
@@ -580,11 +580,15 @@ void CG_HudDrawElements()
int i;
float fX, fY;
float fWidth, fHeight;
vec2_t virtualScale;
if (!cg_huddraw_force->integer && !cg_hud->integer) {
return;
}
virtualScale[0] = cgs.glconfig.vidWidth / 640.0;
virtualScale[1] = cgs.glconfig.vidHeight / 480.0;
for (i = 0; i < MAX_HUDDRAW_ELEMENTS; i++) {
if ((!cgi.HudDrawElements[i].hShader && !cgi.HudDrawElements[i].string[0])
|| !cgi.HudDrawElements[i].vColor[3]) {
@@ -597,6 +601,13 @@ void CG_HudDrawElements()
fWidth = cgi.HudDrawElements[i].iWidth;
fHeight = cgi.HudDrawElements[i].iHeight;
if (!cgi.HudDrawElements[i].bVirtualScreen) {
fWidth *= cgs.uiHiResScale[0];
fHeight *= cgs.uiHiResScale[1];
fX *= cgs.uiHiResScale[0];
fY *= cgs.uiHiResScale[1];
}
if (cgi.HudDrawElements[i].iHorizontalAlign == HUD_ALIGN_X_CENTER) {
if (cgi.HudDrawElements[i].bVirtualScreen) {
fX += 320.0 - fWidth * 0.5;
@@ -627,23 +638,28 @@ void CG_HudDrawElements()
cgi.R_SetColor(cgi.HudDrawElements[i].vColor);
if (cgi.HudDrawElements[i].string[0]) {
if (cgi.HudDrawElements[i].pFont) {
fontheader_t* pFont = cgi.HudDrawElements[i].pFont;
if (!pFont) {
pFont = cgs.media.hudDrawFont;
}
if (cgi.HudDrawElements[i].bVirtualScreen) {
cgi.R_DrawString(
cgi.HudDrawElements[i].pFont,
pFont,
cgi.LV_ConvertString(cgi.HudDrawElements[i].string),
fX,
fY,
-1,
cgi.HudDrawElements[i].bVirtualScreen
virtualScale
);
} else {
cgi.R_DrawString(
cgs.media.hudDrawFont,
pFont,
cgi.LV_ConvertString(cgi.HudDrawElements[i].string),
fX,
fY,
fX / cgs.uiHiResScale[0],
fY / cgs.uiHiResScale[1],
-1,
cgi.HudDrawElements[i].bVirtualScreen
cgs.uiHiResScale
);
}
} else {
@@ -734,7 +750,7 @@ void CG_DrawObjectives()
vColor[0] = 0.2f;
vColor[3] = cg.ObjectivesCurrentAlpha * 0.75;
cgi.R_SetColor(vColor);
cgi.R_DrawStretchPic(fX, fY, 450.0, fWidth, 0.0, 0.0, 1.0, 1.0, cgs.media.objectivesBackShader);
cgi.R_DrawStretchPic(fX, fY, 450.0 * cgs.uiHiResScale[0], fWidth * cgs.uiHiResScale[1], 0.0, 0.0, 1.0, 1.0, cgs.media.objectivesBackShader);
fX = 30.0;
fY = fObjectivesTop + 10;
@@ -743,11 +759,11 @@ void CG_DrawObjectives()
vColor[2] = 1.0;
vColor[3] = cg.ObjectivesCurrentAlpha;
cgi.R_SetColor(vColor);
cgi.R_DrawString(cgs.media.objectiveFont, cgi.LV_ConvertString("Mission Objectives:"), fX, fY, -1, 0);
cgi.R_DrawString(cgs.media.objectiveFont, cgi.LV_ConvertString("Mission Objectives:"), fX, fY / cgs.uiHiResScale[1], -1, cgs.uiHiResScale);
fY = fY + 5.0;
cgi.R_DrawString(cgs.media.objectiveFont, "_______________________________________________________", fX, fY, -1, 0);
fHeight = fObjectivesTop + 35;
cgi.R_DrawString(cgs.media.objectiveFont, "_______________________________________________________", fX, fY / cgs.uiHiResScale[1], -1, cgs.uiHiResScale);
fHeight = fObjectivesTop + 35 * cgs.uiHiResScale[1];
for (i = 0; i < MAX_OBJECTIVES; ++i) {
qhandle_t hBoxShader;
@@ -785,7 +801,14 @@ void CG_DrawObjectives()
cgi.R_SetColor(vColor);
fX = 55.0;
fY = fHeight;
cgi.R_DrawString(cgs.media.objectiveFont, cgi.LV_ConvertString(cg.Objectives[i].text), 55.0, fHeight, -1, 0);
cgi.R_DrawString(
cgs.media.objectiveFont,
cgi.LV_ConvertString(cg.Objectives[i].text),
55.0,
fY / cgs.uiHiResScale[1],
-1,
cgs.uiHiResScale
);
fX = 30.0;
fY = fHeight;
@@ -794,9 +817,19 @@ void CG_DrawObjectives()
vColor[2] = 1.0;
vColor[3] = cg.ObjectivesCurrentAlpha;
cgi.R_SetColor(vColor);
cgi.R_DrawStretchPic(fX, fY, 16.0, 16.0, 0.0, 0.0, 1.0, 1.0, hBoxShader);
cgi.R_DrawStretchPic(
fX * cgs.uiHiResScale[0],
fY,
16.0 * cgs.uiHiResScale[0],
16.0 * cgs.uiHiResScale[1],
0.0,
0.0,
1.0,
1.0,
hBoxShader
);
fHeight += iNumLines[i] * 12 + 25;
fHeight += iNumLines[i] * 12 + 25 * cgs.uiHiResScale[1];
}
}
@@ -820,7 +853,17 @@ void CG_DrawPlayerTeam()
if (handle) {
cgi.R_SetColor(NULL);
cgi.R_DrawStretchPic(96.0, cgs.glconfig.vidHeight - 46, 24.0, 24.0, 0.0, 0.0, 1.0, 1.0, handle);
cgi.R_DrawStretchPic(
96.0 * cgs.uiHiResScale[0],
cgs.glconfig.vidHeight - 46 * cgs.uiHiResScale[1],
24.0 * cgs.uiHiResScale[0],
24.0 * cgs.uiHiResScale[1],
0.0,
0.0,
1.0,
1.0,
handle
);
}
}
@@ -862,13 +905,12 @@ void CG_DrawPlayerEntInfo()
if (handle) {
cgi.R_SetColor(0);
cgi.R_DrawStretchPic(56.0, fY, 16.0, 16.0, 0.0, 0.0, 1.0, 1.0, handle);
fX = 56.0 + 24.0;
cgi.R_DrawStretchPic(fX, fY, 16.0 * cgs.uiHiResScale[0], 16.0 * cgs.uiHiResScale[1], 0.0, 0.0, 1.0, 1.0, handle);
}
cgi.R_SetColor(color);
cgi.R_DrawString(cgs.media.hudDrawFont, (char *)pszName, fX, fY, -1, 0);
cgi.R_DrawString(cgs.media.hudDrawFont, va("%i", cg.snap->ps.stats[STAT_INFOCLIENT_HEALTH]), fX, fY + 20.0, -1, 0);
cgi.R_DrawString(cgs.media.hudDrawFont, (char *)pszName, fX / cgs.uiHiResScale[0] + 24.0, fY / cgs.uiHiResScale[1], -1, cgs.uiHiResScale);
cgi.R_DrawString(cgs.media.hudDrawFont, va("%i", cg.snap->ps.stats[STAT_INFOCLIENT_HEALTH]), fX / cgs.uiHiResScale[0] + 24.0, fY / cgs.uiHiResScale[1] + 20.0, -1, cgs.uiHiResScale);
}
void CG_UpdateAttackerDisplay()
@@ -907,7 +949,17 @@ void CG_UpdateAttackerDisplay()
if (handle) {
cgi.R_SetColor(0);
cgi.R_DrawStretchPic(56.0, fY, 24.0, 24.0, 0.0, 0.0, 1.0, 1.0, handle);
cgi.R_DrawStretchPic(
56.0 * cgs.uiHiResScale[0],
fY,
24.0 * cgs.uiHiResScale[0],
24.0 * cgs.uiHiResScale[1],
0.0,
0.0,
1.0,
1.0,
handle
);
}
if ((cg.snap->ps.stats[STAT_TEAM] == TEAM_ALLIES || cg.snap->ps.stats[STAT_TEAM] == TEAM_AXIS)
@@ -921,7 +973,7 @@ void CG_UpdateAttackerDisplay()
color[2] = 0.5;
}
fX = 56.0 + 32.0;
fX = 56.0;
} else {
color[0] = 1.0;
color[1] = 0.5;
@@ -929,7 +981,7 @@ void CG_UpdateAttackerDisplay()
}
cgi.R_SetColor(color);
cgi.R_DrawString(cgs.media.attackerFont, pszName, fX, fY, -1, 0);
cgi.R_DrawString(cgs.media.attackerFont, pszName, fX / cgs.uiHiResScale[0] + 32.0, fY / cgs.uiHiResScale[1], -1, cgs.uiHiResScale);
}
void CG_UpdateCountdown()
@@ -1043,7 +1095,7 @@ void CG_DrawInstantMessageMenu()
x = 8.0;
y = ((float)cgs.glconfig.vidHeight - h) * 0.5;
cgi.R_SetColor(0);
cgi.R_DrawStretchPic(x, y, w, h, 0.0, 0.0, 1.0, 1.0, handle);
cgi.R_DrawStretchPic(x * cgs.uiHiResScale[0], y, w * cgs.uiHiResScale[0], h * cgs.uiHiResScale[1], 0.0, 0.0, 1.0, 1.0, handle);
}
void CG_DrawSpectatorView_ver_15()
@@ -1069,7 +1121,7 @@ void CG_DrawSpectatorView_ver_15()
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);
cgi.R_DrawString(cgs.media.attackerFont, pszString, fX / cgs.uiHiResScale[0], fY / cgs.uiHiResScale[1], -1, cgs.uiHiResScale);
}
if (cg.predicted_player_state.pm_flags & PMF_CAMERA_VIEW) {
@@ -1085,7 +1137,7 @@ void CG_DrawSpectatorView_ver_15()
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);
cgi.R_DrawString(cgs.media.attackerFont, pszString, fX / cgs.uiHiResScale[0], fY / cgs.uiHiResScale[1], -1, cgs.uiHiResScale);
}
if (!bOnTeam && (cg.predicted_player_state.pm_flags & PMF_CAMERA_VIEW)) {
@@ -1096,7 +1148,7 @@ void CG_DrawSpectatorView_ver_15()
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);
cgi.R_DrawString(cgs.media.attackerFont, pszString, fX / cgs.uiHiResScale[0], fY / cgs.uiHiResScale[1], -1, cgs.uiHiResScale);
}
if (!(cg.predicted_player_state.pm_flags & PMF_CAMERA_VIEW)) {
@@ -1109,10 +1161,10 @@ void CG_DrawSpectatorView_ver_15()
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);
cgi.R_DrawString(cgs.media.attackerFont, pszString, fX / cgs.uiHiResScale[0], fY / cgs.uiHiResScale[1], -1, cgs.uiHiResScale);
}
if ((cg.predicted_player_state.pm_flags & 0x80) != 0 && cg.snap && cg.snap->ps.stats[STAT_INFOCLIENT] != -1) {
if ((cg.predicted_player_state.pm_flags & PMF_CAMERA_VIEW) != 0 && cg.snap && cg.snap->ps.stats[STAT_INFOCLIENT] != -1) {
int iClientNum;
qhandle_t hShader;
vec4_t color;
@@ -1130,7 +1182,7 @@ void CG_DrawSpectatorView_ver_15()
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);
cgi.R_DrawString(cgs.media.attackerFont, buf, fX / cgs.uiHiResScale[0], fY / cgs.uiHiResScale[1], -1, cgs.uiHiResScale);
if (cg.clientinfo[iClientNum].team == TEAM_ALLIES) {
hShader = cgi.R_RegisterShader("textures/hud/allies");
@@ -1139,9 +1191,18 @@ void CG_DrawSpectatorView_ver_15()
}
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);
cgi.R_DrawStretchPic(
fX - 20.0 * cgs.uiHiResScale[0],
fY,
16.0 * cgs.uiHiResScale[0],
16.0 * cgs.uiHiResScale[1],
0.0,
0.0,
1.0,
1.0,
hShader
);
}
}
}
@@ -1176,7 +1237,7 @@ void CG_DrawSpectatorView_ver_6()
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);
cgi.R_DrawString(cgs.media.attackerFont, pszString, fX / cgs.uiHiResScale[0], fY / cgs.uiHiResScale[1], -1, cgs.uiHiResScale);
if (!bOnTeam && (cg.predicted_player_state.pm_flags & PMF_CAMERA_VIEW)) {
cgi.Key_GetKeysForCommand("+moveup", &iKey1, &iKey2);
@@ -1190,7 +1251,7 @@ void CG_DrawSpectatorView_ver_6()
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);
cgi.R_DrawString(cgs.media.attackerFont, pszString, fX / cgs.uiHiResScale[0], fY / cgs.uiHiResScale[1], -1, cgs.uiHiResScale);
}
}
@@ -1233,6 +1294,9 @@ void CG_DrawCrosshair()
return;
}
// Fixed in OPM: R_RegisterShaderNoMip
// Use R_RegisterShaderNoMip, as it's UI stuff
if (cgs.gametype != GT_FFA) {
AngleVectorsLeft(cg.refdefViewAngles, forward, NULL, NULL);
@@ -1260,23 +1324,23 @@ void CG_DrawCrosshair()
|| ((myFlags & EF_AXIS) && (friendEnt->currentState.eFlags & EF_AXIS))) {
// friend
if (cg.snap->ps.stats[STAT_CROSSHAIR]) {
shader = cgi.R_RegisterShader(cg_crosshair_friend->string);
shader = cgi.R_RegisterShaderNoMip(cg_crosshair_friend->string);
}
} else {
// enemy
if (cg.snap->ps.stats[STAT_CROSSHAIR]) {
shader = cgi.R_RegisterShader(cg_crosshair->string);
shader = cgi.R_RegisterShaderNoMip(cg_crosshair->string);
}
}
} else {
if (cg.snap->ps.stats[STAT_CROSSHAIR]) {
shader = cgi.R_RegisterShader(cg_crosshair->string);
shader = cgi.R_RegisterShaderNoMip(cg_crosshair->string);
}
}
} else {
// FFA
if (cg.snap->ps.stats[STAT_CROSSHAIR]) {
shader = cgi.R_RegisterShader(cg_crosshair->string);
shader = cgi.R_RegisterShaderNoMip(cg_crosshair->string);
}
}
@@ -1287,7 +1351,17 @@ void CG_DrawCrosshair()
y = (cgs.glconfig.vidHeight - height) * 0.5f;
cgi.R_SetColor(NULL);
cgi.R_DrawStretchPic(x, y, width, height, 0, 0, 1, 1, shader);
cgi.R_DrawStretchPic(
x,
y,
width * cgs.uiHiResScale[0],
height * cgs.uiHiResScale[1],
0,
0,
1,
1,
shader
);
}
}
@@ -1324,7 +1398,7 @@ void CG_DrawVote()
cgi.R_SetColor(NULL);
text = va("%s: %s", cgi.LV_ConvertString("Vote Running"), cgs.voteString);
cgi.R_DrawString(cgs.media.attackerFont, text, x, y, -1, qfalse);
cgi.R_DrawString(cgs.media.attackerFont, text, x, y, -1, cgs.uiHiResScale);
y += 12;
@@ -1338,7 +1412,7 @@ void CG_DrawVote()
percentNo,
cgi.LV_ConvertString("Undecided"),
percentUndecided);
cgi.R_DrawString(cgs.media.attackerFont, text, x, y, -1, qfalse);
cgi.R_DrawString(cgs.media.attackerFont, text, x, y, -1, cgs.uiHiResScale);
if (cg.snap && !cg.snap->ps.voted) {
col[0] = 0.5;
@@ -1350,12 +1424,12 @@ void CG_DrawVote()
y += 12;
text = cgi.LV_ConvertString("Vote now, it's your patriotic duty!");
cgi.R_DrawString(cgs.media.attackerFont, text, x, y, -1, qfalse);
cgi.R_DrawString(cgs.media.attackerFont, text, x, y, -1, cgs.uiHiResScale);
y += 12;
text = cgi.LV_ConvertString("To vote Yes, press F1. To vote No, press F2.");
cgi.R_DrawString(cgs.media.attackerFont, text, x, y, -1, qfalse);
cgi.R_DrawString(cgs.media.attackerFont, text, x, y, -1, cgs.uiHiResScale);
cgi.R_SetColor(NULL);
}
}
+7
View File
@@ -380,6 +380,7 @@ extern "C" {
float screenXScale; // derived from glconfig
float screenYScale;
float screenXBias;
vec2_t uiHiResScale;
int serverCommandSequence; // reliable command stream counter
int processedSnapshotNum; // the number of snapshots cgame has requested
@@ -505,9 +506,15 @@ extern "C" {
extern cvar_t *cg_shadowdebug;
extern cvar_t *ui_timemessage;
//
// Added in OPM
//
extern cvar_t *cg_fov;
//
// cg_main.c
//
qboolean CG_UseLargeLightmaps(const char* mapName);
void CG_ProcessConfigString(int num, qboolean modelOnly);
const char *CG_ConfigString(int index);
void CG_AddToTeamChat(const char *str);
+31
View File
@@ -112,6 +112,11 @@ cvar_t *cg_shadowscount;
cvar_t *cg_shadowdebug;
cvar_t *ui_timemessage;
//
// Added in OPM
//
cvar_t *cg_fov;
/*
=================
CG_RegisterCvars
@@ -203,6 +208,31 @@ void CG_RegisterCvars(void)
// see if we are also running the server on this machine
temp = cgi.Cvar_Get("sv_running", "0", 0);
cgs.localServer = temp->integer;
//
// Added in OPM
//
cg_fov = cgi.Cvar_Get("cg_fov", "80", CVAR_ARCHIVE);
}
/*
===============
CG_UseLargeLightmaps
Added in 2.0
Returns true if the standard BSP file should be used, false if the smaller lightmap BSP file should be used
===============
*/
qboolean CG_UseLargeLightmaps(const char* mapName) {
char buffer[MAX_QPATH];
Com_sprintf(buffer, sizeof(buffer), "maps/%s_sml.bsp", mapName);
if (cgi.FS_ReadFile(buffer, NULL, qtrue) == -1) {
return qtrue;
}
return cgi.Cvar_Get("r_largemap", "0", 0)->integer;
}
/*
@@ -570,6 +600,7 @@ void CG_GetRendererConfig(void)
cgi.GetGlconfig(&cgs.glconfig);
cgs.screenXScale = cgs.glconfig.vidWidth / 640.0;
cgs.screenYScale = cgs.glconfig.vidHeight / 480.0;
cgi.UI_GetHighResolutionScale(cgs.uiHiResScale);
}
/*
+2
View File
@@ -1200,7 +1200,9 @@ void CG_ModelAnim(centity_t *cent, qboolean bDoShaderTime)
if (!cg.pLastPlayerWorldModel || cg.pLastPlayerWorldModel != model.tiki) {
qhandle_t hModel;
char fpsname[128];
COM_StripExtension(model.tiki->a->name, fpsname, sizeof(fpsname));
Q_strcat(fpsname, sizeof(fpsname), "_fps.tik");
hModel = cgi.R_RegisterModel(fpsname);
if (hModel) {
+17 -3
View File
@@ -330,8 +330,18 @@ static void CG_InterpolatePlayerStateCamera(void)
//
VectorCopy(cg.predicted_player_state.camera_angles, cg.camera_angles);
VectorCopy(cg.predicted_player_state.camera_origin, cg.camera_origin);
cg.camera_fov = cg.predicted_player_state.fov;
//
// Added in OPM
// Use the specified fov specified by the server
// when zooming
//
if (cg.predicted_player_state.stats[STAT_INZOOM]) {
cg.camera_fov = cg.predicted_player_state.fov;
} else {
cg.camera_fov = cg_fov->value;
}
// if the next frame is a teleport, we can't lerp to it
if (cg.nextFrameCameraCut) {
return;
@@ -343,8 +353,12 @@ static void CG_InterpolatePlayerStateCamera(void)
f = (float)(cg.time - prev->serverTime) / (next->serverTime - prev->serverTime);
// interpolate fov
cg.camera_fov = prev->ps.fov + f * (next->ps.fov - prev->ps.fov);
if (cg.predicted_player_state.stats[STAT_INZOOM]) {
// interpolate fov
cg.camera_fov = prev->ps.fov + f * (next->ps.fov - prev->ps.fov);
} else {
cg.camera_fov = cg_fov->value;
}
if (!(cg.snap->ps.pm_flags & PMF_CAMERA_VIEW)) {
return;
+3 -2
View File
@@ -312,12 +312,12 @@ functions exported to the main executable
); // 0 = white
fontheader_t *(*R_LoadFont)(const char *name);
void (*R_DrawString)(
fontheader_t *font, const char *text, float x, float y, int maxLen, qboolean virtualScreen
fontheader_t *font, const char *text, float x, float y, int maxLen, const float *pvVirtualScreen
);
refEntity_t *(*R_GetRenderEntity)(int entityNumber);
void (*R_ModelBounds)(clipHandle_t model, vec3_t mins, vec3_t maxs);
float (*R_ModelRadius)(clipHandle_t model);
float (*R_Noise)(float x, float y, float z, float t);
float (*R_Noise)(float x, float y, float z, double t);
void (*R_DebugLine)(const vec3_t start, const vec3_t end, float r, float g, float b, float alpha);
baseshader_t *(*GetShader)(int shaderNum);
// =========== Swipes =============
@@ -363,6 +363,7 @@ functions exported to the main executable
int (*UI_FontStringWidth)(fontheader_t *font, const char *string, int maxLen);
// Added in 2.0
float (*UI_GetObjectivesTop)(void);
void (*UI_GetHighResolutionScale)(vec2_t scale);
int (*Key_StringToKeynum)(const char *str);
const char *(*Key_KeynumToBindString)(int keyNum);
+10 -2
View File
@@ -190,8 +190,12 @@ void CG_ParseServerinfo(void)
Q_strncpyz(map, mapname, sizeof(map));
}
Com_sprintf(cgs.mapname, sizeof(cgs.mapname), "maps/%s.bsp", map);
if (CG_UseLargeLightmaps(mapname)) {
Com_sprintf(cgs.mapname, sizeof(cgs.mapname), "maps/%s.bsp", map);
} else {
Com_sprintf(cgs.mapname, sizeof(cgs.mapname), "maps/%s_sml.bsp", map);
}
// hide/show huds
if (cgs.gametype) {
cgi.Cmd_Execute(EXEC_NOW, "ui_addhud hud_timelimit\n");
@@ -461,6 +465,10 @@ void CG_ExecuteNewServerCommands(int latestSequence, qboolean differentServer)
static const char *whiteListedVariables[] = {
"r_fastsky", // some mods set this variable to make the sky uniform
"ui_hud",
"subtitle0",
"subtitle1",
"subtitle2",
"subtitle3"
};
//
+1 -1
View File
@@ -120,7 +120,7 @@ void CG_MessageSingleClient_f(void)
// copy the rest
for (i = 2; i < cgi.Argc(); i++) {
sString += va("%s", cgi.Argv(i));
sString += va(" %s", cgi.Argv(i));
}
sString += "\n";
+19 -3
View File
@@ -298,7 +298,7 @@ void CG_OffsetFirstPersonView(refEntity_t *pREnt, qboolean bUseWorldPosition)
VectorCopy(origin, vOldOrigin);
if (!cg.predicted_player_state.walking || !(cg.predicted_player_state.pm_flags & PMF_FROZEN)) {
if (!cg.predicted_player_state.walking || (!(cg.predicted_player_state.pm_flags & PMF_FROZEN) && !(cg.predicted_player_state.pm_flags & PMF_NO_MOVE))) {
VectorCopy(cg.predicted_player_state.velocity, vVelocity);
} else {
//
@@ -485,9 +485,16 @@ static int CG_CalcFov(void)
int contents;
float fov_x, fov_y;
int inwater;
float fov_ratio;
fov_x = cg.camera_fov;
x = cg.refdef.width / tan(fov_x / 360 * M_PI);
fov_ratio = (float)cg.refdef.width / (float)cg.refdef.height * (3.0 / 4.0);
if (fov_ratio == 1) {
fov_x = cg.camera_fov;
} else {
fov_x = RAD2DEG(atan(tan(DEG2RAD(cg.camera_fov / 2.0)) * fov_ratio)) * 2.0;
}
x = cg.refdef.width / tan(fov_x / 360 * M_PI);
fov_y = atan2(cg.refdef.height, x);
fov_y = fov_y * 360 / M_PI;
@@ -840,6 +847,15 @@ void CG_DrawActiveFrame(int serverTime, int frameTime, stereoFrame_t stereoView,
// no entities should be marked as interpolating
}
//
// Added in OPM
// Clamp the fov to avoid artifacts
if (cg_fov->value < 65) {
cgi.Cvar_Set("cg_fov", "65");
} else if (cg_fov->value > 120) {
cgi.Cvar_Set("cg_fov", "120");
}
// update cg.predicted_player_state
CG_PredictPlayerState();
+11 -7
View File
@@ -1,7 +1,6 @@
cmake_minimum_required(VERSION 3.5)
project(omohclient)
cmake_minimum_required(VERSION 3.12)
option(NO_OPENAL "Use older sound-system" FALSE)
project(omohclient)
add_subdirectory("../cgame" "./cgame")
@@ -11,16 +10,15 @@ file(GLOB_RECURSE SOURCES_UILIB "../uilib/*.c*")
# Made as an interface and not static, as static only links used methods
add_library(omohclient INTERFACE)
target_compile_definitions(omohclient INTERFACE APP_MODULE)
target_compile_definitions(omohclient INTERFACE USE_OPENAL_DLOPEN=1)
target_compile_features(omohclient INTERFACE cxx_nullptr)
target_compile_features(omohclient INTERFACE c_variadic_macros)
target_link_libraries(omohclient INTERFACE omohsdl)
target_link_libraries(omohclient INTERFACE omohsdl_client)
target_link_libraries(omohclient INTERFACE gcd)
# Sound stuff
target_compile_definitions(omohclient INTERFACE USE_CODEC_MP3)
if (NOT NO_OPENAL)
if (NOT NO_MODERN_DMA)
# Use OpenAL
find_package(OpenAL REQUIRED)
@@ -31,7 +29,13 @@ if (NOT NO_OPENAL)
else()
target_include_directories(omohclient INTERFACE ${OPENAL_INCLUDE_DIR})
endif()
target_link_libraries(omohclient INTERFACE ${OPENAL_LIBRARY})
if(NOT USE_SYSTEM_LIBS)
target_compile_definitions(omohclient INTERFACE USE_OPENAL_DLOPEN=1)
else()
# Link against system OpenAL
target_link_libraries(omohclient INTERFACE OpenAL::OpenAL)
endif()
endif()
list(FILTER SOURCES_CLIENT EXCLUDE REGEX "./snd_([a-zA-Z0-9_]+)\.c$")
+19 -5
View File
@@ -774,6 +774,7 @@ void CL_InitCGameDLL( clientGameImport_t *cgi, clientGameExport_t **cge ) {
cgi->UI_HideMenu = UI_HideMenu;
cgi->UI_FontStringWidth = CL_FontStringWidth;
cgi->UI_GetObjectivesTop = UI_GetObjectivesTop;
cgi->UI_GetHighResolutionScale = UI_GetHighResolutionScale;
cgi->Key_StringToKeynum = Key_StringToKeynum;
cgi->Key_KeynumToBindString = Key_KeynumToBindString;
cgi->Key_GetKeysForCommand = Key_GetKeysForCommand;
@@ -922,7 +923,13 @@ void CL_InitCGame( void ) {
// find the current mapname
info = cl.gameState.stringData + cl.gameState.stringOffsets[ CS_SERVERINFO ];
mapname = Info_ValueForKey( info, "mapname" );
Com_sprintf( cl.mapname, sizeof( cl.mapname ), "maps/%s.bsp", mapname );
if (CL_UseLargeLightmap(mapname)) {
Com_sprintf(cl.mapname, sizeof(cl.mapname), "maps/%s.bsp", mapname);
} else {
// Added in 2.0
Com_sprintf(cl.mapname, sizeof(cl.mapname), "maps/%s_sml.bsp", mapname);
}
S_BeginRegistration();
CL_ShutdownCGame();
@@ -937,10 +944,17 @@ void CL_InitCGame( void ) {
CL_InitClientSavedData();
}
// init for this gamestate
// use the lastExecutedServerCommand instead of the serverCommandSequence
// otherwise server commands sent just before a gamestate are dropped
cge->CG_Init( &cgi, clc.serverMessageSequence, clc.lastExecutedServerCommand, clc.clientNum );
if (cl.snap.valid) {
// init for this gamestate
// use the lastExecutedServerCommand instead of the serverCommandSequence
// otherwise server commands sent just before a gamestate are dropped
cge->CG_Init(&cgi, clc.serverMessageSequence, clc.lastExecutedServerCommand, clc.clientNum);
} else {
// executing client commands from previous map/server might be an issue, some commands might be cs commands,
// like old CS_SYSTEMINFO configstrings which still contain the sv_serverId from previous map.
// It would cause the client to lose the game state number
cge->CG_Init(&cgi, clc.serverMessageSequence, clc.serverCommandSequence, clc.clientNum);
}
ClearNewConfigFlag();
TIKI_FinishLoad();
+1 -1
View File
@@ -295,7 +295,7 @@ void UI_DoInventory(qboolean activate_mouse)
if (client_inv.align == INV_ALIGN_RIGHT) {
s_main_inv->InitFrame(
NULL,
client_inv.horizoffset + cls.glconfig.vidWidth - client_inv.typewidth,
client_inv.horizoffset + uid.vidWidth - client_inv.typewidth,
client_inv.vertoffset,
client_inv.typewidth,
client_inv.typeheight * client_inv.types.NumObjects(),
+199 -72
View File
@@ -29,14 +29,19 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "../qcommon/localization.h"
#include "../qcommon/bg_compat.h"
#include "../sys/sys_local.h"
#ifdef USE_RENDERER_DLL
#include "../sys/sys_loadlib.h"
#endif
extern "C" {
#include "../sys/sys_loadlib.h"
}
#include "../gamespy/gcdkey/gcdkeyc.h"
#include <climits>
#ifdef USE_RENDERER_DLOPEN
cvar_t* cl_renderer;
#endif
cvar_t *cl_nodelta;
cvar_t *cl_debugMove;
@@ -130,19 +135,14 @@ clientGameExport_t *cge;
// Structure containing functions exported from refresh DLL
refexport_t re;
#ifdef USE_RENDERER_DLOPEN
static void *rendererLib = NULL;
#endif
qboolean camera_reset;
qboolean camera_active;
vec3_t camera_offset;
#ifdef USE_RENDERER_DLL
// su44: for plugable renderer system
refexport_t* (*DGetRefAPI)(int apiVersion, refimport_t * rimp) = NULL;
static cvar_t *cl_renderer = NULL;
static void *rendererLib = NULL;
#endif // USE_RENDERER_DLL
ping_t cl_pinglist[MAX_PINGREQUESTS];
typedef struct serverStatus_s
@@ -172,6 +172,26 @@ void CL_ServerStatusResponse( netadr_t from, msg_t *msg );
static qboolean cl_bCLSystemStarted = qfalse;
/*
===============
CL_UseLargeLightmap
Added in 2.0
Returns true if the standard BSP file should be used, false if the smaller lightmap BSP file should be used
===============
*/
qboolean CL_UseLargeLightmap(const char* mapName) {
char buffer[MAX_QPATH];
Com_sprintf(buffer, sizeof(buffer), "maps/%s_sml.bsp", mapName);
if (FS_ReadFileEx(buffer, NULL, qtrue) == -1) {
return qtrue;
}
return Cvar_Get("r_largemap", "0", 0)->integer;
}
/*
===============
CL_CDDialog
@@ -782,9 +802,10 @@ void CL_ShutdownAll(qboolean shutdownRef) {
TIKI_FreeAll();
// shutdown the renderer
if ( re.Shutdown ) {
re.Shutdown( qfalse ); // don't destroy window or context
}
if(shutdownRef)
CL_ShutdownRef();
else if(re.Shutdown)
re.Shutdown(qfalse); // don't destroy window or context
cls.uiStarted = qfalse;
cls.cgameStarted = qfalse;
@@ -1560,19 +1581,24 @@ void CL_Vid_Restart_f( void ) {
S_BeginRegistration();
// shutdown the UI
//CL_ShutdownUI();
// shutdown the renderer and clear the renderer interface
CL_ShutdownRef();
CL_ShutdownRef();
cls.rendererRegistered = qfalse;
// shutdown the CGame
CL_ShutdownCGame();
// initialize the renderer interface
CL_InitRef();
// initialize the UI
//CL_InitializeUI();
// initialize the ui library
UI_ResolutionChange();
// clear aliases
Alias_Clear();
cls.rendererRegistered = qfalse;
// unpause so the cgame definately gets a snapshot and renders a frame
Com_Unpause();
@@ -2554,7 +2580,7 @@ void CL_CheckUserinfo( void ) {
// send a reliable userinfo update if needed
if(cvar_modifiedFlags & CVAR_USERINFO)
{
if (Com_SanitizeName(name->string, szSanitizedName)) {
if (Com_SanitizeName(name->string, szSanitizedName, sizeof(szSanitizedName))) {
Cvar_Set("name", szSanitizedName);
}
@@ -2564,6 +2590,10 @@ void CL_CheckUserinfo( void ) {
}
void CL_SetFrameNumber(int frameNumber) {
if (!re.SetFrameNumber) {
return;
}
re.SetFrameNumber(frameNumber);
}
@@ -2789,15 +2819,15 @@ CL_ShutdownRef
============
*/
void CL_ShutdownRef( void ) {
if ( !re.Shutdown ) {
return;
if ( re.Shutdown ) {
re.Shutdown( qtrue );
}
re.Shutdown( qtrue );
Com_Memset( &re, 0, sizeof( re ) );
#ifdef USE_RENDERER_DLL
// su44: remember to unload renderer library
if(rendererLib) {
Sys_UnloadLibrary(rendererLib);
#ifdef USE_RENDERER_DLOPEN
if ( rendererLib ) {
Sys_UnloadLibrary( rendererLib );
rendererLib = NULL;
}
#endif
@@ -2974,22 +3004,105 @@ void CL_CG_EndTiki( dtiki_t *tiki ) {
}
}
/*
============
CL_CG_EndTiki
============
*/
extern "C"
int CL_ScaledMilliseconds(void) {
return Sys_Milliseconds()*com_timescale->value;
}
/*
============
CL_RefFS_WriteFile
============
*/
void CL_RefFS_WriteFile(const char* qpath, const void* buffer, int size) {
FS_WriteFile(qpath, buffer, size);
}
/*
============
CL_RefFS_ListFiles
============
*/
char** CL_RefFS_ListFiles(const char* name, const char* extension, int* numfilesfound) {
return FS_ListFiles(name, extension, qtrue, numfilesfound);
}
/*
============
CL_RefCIN_UploadCinematic
============
*/
void CL_RefCIN_UploadCinematic(int handle) {
}
/*
============
CL_RefTIKI_GetNumChannels
============
*/
int CL_RefTIKI_GetNumChannels(dtiki_t* tiki) {
return tiki->m_boneList.NumChannels();
}
/*
============
CL_RefTIKI_GetLocalChannel
============
*/
int CL_RefTIKI_GetLocalChannel(dtiki_t* tiki, int channel) {
return tiki->m_boneList.LocalChannel(channel);
}
/*
============
CL_RefTIKI_GetLocalFromGlobal
============
*/
int CL_RefTIKI_GetLocalFromGlobal(dtiki_t* tiki, int channel) {
return tiki->m_boneList.GetLocalFromGlobal(channel);
}
/*
============
CL_RefSKEL_GetMorphWeightFrame
============
*/
int CL_RefSKEL_GetMorphWeightFrame(void* skeletor, int index, float time, int* data) {
return ((skeletor_c*)skeletor)->GetMorphWeightFrame(index, time, data);
}
/*
============
CL_RefSKEL_GetBoneParent
============
*/
int CL_RefSKEL_GetBoneParent(void* skeletor, int boneIndex) {
return ((skeletor_c*)skeletor)->GetBoneParent(boneIndex);
}
/*
============
CL_GetRefSequence
============
*/
int CL_GetRefSequence(void) {
return cls.refSequence;
}
/*
============
CL_IsRendererLoaded
============
*/
qboolean CL_IsRendererLoaded(void) {
return re.Shutdown != NULL;
}
/*
============
CL_InitRef
@@ -2998,12 +3111,40 @@ CL_InitRef
void CL_InitRef( void ) {
refimport_t ri;
refexport_t *ret;
#ifdef USE_RENDERER_DLL
char dllName[256];
#ifdef USE_RENDERER_DLOPEN
GetRefAPI_t GetRefAPI;
char dllName[MAX_OSPATH];
#endif
Com_Printf( "----- Initializing Renderer ----\n" );
#ifdef USE_RENDERER_DLOPEN
cl_renderer = Cvar_Get("cl_renderer", "opengl1", CVAR_ARCHIVE | CVAR_LATCH);
Com_sprintf(dllName, sizeof(dllName), "renderer_%s" ARCH_SUFFIX DLL_SUFFIX DLL_EXT, cl_renderer->string);
if(!(rendererLib = Sys_LoadDll(dllName, qfalse)) && strcmp(cl_renderer->string, cl_renderer->resetString))
{
Com_Printf("failed:\n\"%s\"\n", Sys_LibraryError());
Cvar_ForceReset("cl_renderer");
Com_sprintf(dllName, sizeof(dllName), "renderer_opengl1" ARCH_SUFFIX DLL_SUFFIX DLL_EXT);
rendererLib = Sys_LoadDll(dllName, qfalse);
}
if(!rendererLib)
{
Com_Printf("failed:\n\"%s\"\n", Sys_LibraryError());
Com_Error(ERR_FATAL, "Failed to load renderer");
}
GetRefAPI = (GetRefAPI_t)Sys_LoadFunction(rendererLib, "GetRefAPI");
if(!GetRefAPI)
{
Com_Error(ERR_FATAL, "Can't load symbol GetRefAPI: '%s'", Sys_LibraryError());
}
#endif
ri.Cmd_AddCommand = Cmd_AddCommand;
ri.Cmd_RemoveCommand = Cmd_RemoveCommand;
ri.Cmd_Argc = Cmd_Argc;
@@ -3027,8 +3168,10 @@ void CL_InitRef( void ) {
ri.CM_DrawDebugSurface = CM_DrawDebugSurface;
ri.FS_OpenFile = FS_FOpenFileRead;
ri.FS_OpenFileWrite = FS_FOpenFileWrite;
ri.FS_CloseFile = FS_FCloseFile;
ri.FS_Read = FS_Read;
ri.FS_Write = FS_Write;
ri.FS_Seek = FS_Seek;
ri.FS_ReadFile = FS_ReadFile;
ri.FS_ReadFileEx = FS_ReadFileEx;
@@ -3038,8 +3181,10 @@ void CL_InitRef( void ) {
ri.FS_ListFiles = CL_RefFS_ListFiles;
ri.FS_FileIsInPAK = FS_FileIsInPAK;
ri.FS_FileExists = FS_FileExists;
ri.FS_CanonicalFilename = FS_CanonicalFilename;
ri.Cvar_Get = Cvar_Get;
ri.Cvar_Set = Cvar_Set;
ri.Cvar_SetValue = Cvar_SetValue;
ri.Cvar_SetDefault = Cvar_SetDefault;
ri.CM_EntityString = CM_EntityString;
@@ -3088,40 +3233,30 @@ void CL_InitRef( void ) {
ri.Sys_GLimpInit = Sys_GLimpInit;
ri.Sys_LowPhysicalMemory = Sys_LowPhysicalMemory;
#ifdef USE_RENDERER_DLL
// su44: load renderer dll
cl_renderer = Cvar_Get("cl_renderer", "glom", CVAR_ARCHIVE);
Q_snprintf(dllName, sizeof(dllName), "renderer_%s" ARCH_STRING DLL_EXT, cl_renderer->string);
Com_Printf("Loading \"%s\"...", dllName);
if((rendererLib = Sys_LoadLibrary(dllName)) == 0) {
#ifdef _WIN32
Com_Error(ERR_FATAL, "failed:\n\"%s\"\n", Sys_LibraryError());
#else
char fn[1024];
//
// Added in OPM
//
ri.UI_LoadResource = UI_LoadResource;
ri.CM_PointLeafnum = CM_PointLeafnum;
ri.CM_LeafCluster = CM_LeafCluster;
Q_strncpyz(fn, Sys_Cwd(), sizeof(fn));
strncat(fn, "/", sizeof(fn) - strlen(fn) - 1);
strncat(fn, dllName, sizeof(fn) - strlen(fn) - 1);
ri.TIKI_CalcLodConsts = TIKI_CalcLodConsts;
ri.TIKI_CalculateBounds = TIKI_CalculateBounds;
ri.TIKI_FindTiki = TIKI_FindTiki;
ri.TIKI_RegisterTikiFlags = TIKI_RegisterTikiFlags;
ri.TIKI_GetSkeletor = TIKI_GetSkeletor;
ri.TIKI_GetSkel = TIKI_GetSkel;
ri.TIKI_GetSkelAnimFrame = TIKI_GetSkelAnimFrame;
ri.TIKI_GlobalRadius = TIKI_GlobalRadius;
ri.TIKI_FindSkelByHeader = TIKI_FindSkelByHeader;
ri.TIKI_GetNumChannels = CL_RefTIKI_GetNumChannels;
ri.TIKI_GetLocalChannel = CL_RefTIKI_GetLocalChannel;
ri.TIKI_GetLocalFromGlobal = CL_RefTIKI_GetLocalFromGlobal;
Com_Printf("Loading \"%s\"...", fn);
if((rendererLib = Sys_LoadLibrary(fn)) == 0)
{
Com_Error(ERR_FATAL, "failed:\n\"%s\"", Sys_LibraryError());
}
#endif /* _WIN32 */
}
ri.SKEL_GetBoneParent = CL_RefSKEL_GetBoneParent;
ri.SKEL_GetMorphWeightFrame = CL_RefSKEL_GetMorphWeightFrame;
Com_Printf("done\n");
DGetRefAPI = Sys_LoadFunction(rendererLib, "GetRefAPI");
if(!DGetRefAPI)
{
Com_Error(ERR_FATAL, "Can't load symbol GetRefAPI: '%s'", Sys_LibraryError());
}
ret = DGetRefAPI( REF_API_VERSION, &ri );
#else
ret = GetRefAPI( REF_API_VERSION, &ri );
#endif
#if defined __USEA3D && defined __A3D_GEOM
hA3Dg_ExportRenderGeom (ret);
@@ -3137,6 +3272,8 @@ void CL_InitRef( void ) {
// unpause so the cgame definately gets a snapshot and renders a frame
Cvar_Set( "cl_paused", "0" );
cls.refSequence++;
}
@@ -3488,14 +3625,6 @@ void CL_Init( void ) {
Cvar_Get ("dm_playermodel", "american_army", CVAR_USERINFO | CVAR_ARCHIVE );
Cvar_Get ("dm_playergermanmodel", "german_wehrmacht_soldier", CVAR_USERINFO | CVAR_ARCHIVE );
Cvar_Get ("cg_predictItems", "1", CVAR_USERINFO | CVAR_ARCHIVE );
// cgame might not be initialized before menu is used
Cvar_Get ("cg_viewsize", "100", CVAR_ARCHIVE );
Cvar_Get ("cg_running", "0", CVAR_ROM );
//
// register our commands
//
@@ -3925,7 +4054,7 @@ CL_ServerStatusResponse
void CL_ServerStatusResponse( netadr_t from, msg_t *msg ) {
const char *s;
char info[MAX_INFO_STRING];
int i, l, score, ping;
int i, l, ping;
int len;
serverStatus_t *serverStatus;
@@ -3979,7 +4108,7 @@ void CL_ServerStatusResponse( netadr_t from, msg_t *msg ) {
if (serverStatus->print) {
Com_Printf("\nPlayers:\n");
Com_Printf("num: score: ping: name:\n");
Com_Printf("num: ping: name:\n");
}
for (i = 0, s = MSG_ReadStringLine( msg ); *s; s = MSG_ReadStringLine( msg ), i++) {
@@ -3987,16 +4116,14 @@ void CL_ServerStatusResponse( netadr_t from, msg_t *msg ) {
Com_sprintf(&serverStatus->string[len], sizeof(serverStatus->string)-len, "\\%s", s);
if (serverStatus->print) {
score = ping = 0;
sscanf(s, "%d %d", &score, &ping);
ping = 0;
sscanf(s, "%d", &ping);
s = strchr(s, ' ');
if (s)
s = strchr(s+1, ' ');
if (s)
s++;
else
s = "unknown";
Com_Printf("%-2d %-3d %-3d %s\n", i, score, ping, s );
Com_Printf("%-2d %-3d %s\n", i, ping, s );
}
}
len = strlen(serverStatus->string);
+16 -7
View File
@@ -568,6 +568,7 @@ void CL_ParseGamestate( msg_t *msg ) {
csNum = CPT_NormalizeConfigstring(i);
if (csNum < 0 || csNum >= MAX_CONFIGSTRINGS) {
Com_Error(ERR_DROP, "configstring > MAX_CONFIGSTRINGS");
return;
}
s = MSG_ReadScrambledBigString(msg);
len = strlen(s);
@@ -588,8 +589,7 @@ void CL_ParseGamestate( msg_t *msg ) {
//Com_Memset (&nullstate, 0, sizeof(nullstate));
MSG_GetNullEntityState(&nullstate);
es = &cl.entityBaselines[ newnum ];
// FIXME: frametime
MSG_ReadDeltaEntity( msg, &nullstate, es, newnum, 0.0);
MSG_ReadDeltaEntity( msg, &nullstate, es, newnum, cls.serverFrameTime);
} else {
Com_Error( ERR_DROP, "CL_ParseGamestate: bad command byte %i", cmd );
}
@@ -606,16 +606,25 @@ void CL_ParseGamestate( msg_t *msg ) {
// stop recording now so the demo won't have an unnecessary level load at the end.
if(cl_autoRecordDemo->integer && clc.demorecording)
CL_StopRecord_f();
// reinitialize the filesystem if the game directory has changed
FS_ConditionalRestart( clc.checksumFeed, qfalse );
if (clc.state == CA_CONNECTED && !Cvar_Get("sv_paks", "", 0)->string[0]) {
// Added in 2.30
FS_Restart(clc.checksumFeed);
} else {
// reinitialize the filesystem if the game directory has changed
FS_ConditionalRestart(clc.checksumFeed, qfalse);
}
clc.state = CA_LOADING;
if (!com_sv_running->integer)
{
const char *info = cl.gameState.stringData + cl.gameState.stringOffsets[CS_SERVERINFO];
UI_ClearState();
UI_BeginLoad(Info_ValueForKey(info, "mapname"));
const char *mapname = Info_ValueForKey(info, "mapname");
// Added in 2.0
Cvar_Set("mapname", mapname);
UI_ClearState();
UI_BeginLoad(mapname);
}
// This used to call CL_StartHunkUsers, but now we enter the download state before loading the
+94 -32
View File
@@ -143,6 +143,9 @@ static unsigned int totalLoadTime;
static unsigned int currentLoadTime;
unsigned char UIListCtrlItem[8];
static const float maxWidthRes = 1920;
static const float maxHeightRes = 1080;
inventory_t client_inv;
bind_t client_bind;
static str scoreboard_menuname;
@@ -212,15 +215,15 @@ static UIRect2D getDefaultConsoleRectangle(void)
f[i] = floor(f[i]);
}
rect.pos.x = f[0] - cls.glconfig.vidWidth;
rect.pos.y = f[1] - cls.glconfig.vidHeight;
rect.pos.x = f[0] - uid.vidWidth;
rect.pos.y = f[1] - uid.vidHeight;
rect.size.width = f[2] + 50.0;
rect.size.height = f[3] + 50.0;
} else {
rect.pos.x = 25.0;
rect.pos.y = 25.0;
rect.size.width = (cls.glconfig.vidWidth - 50);
rect.size.height = (cls.glconfig.vidHeight / 2);
rect.size.width = (uid.vidWidth - 50);
rect.size.height = (uid.vidHeight / 2);
}
return rect;
@@ -967,15 +970,15 @@ static UIRect2D getDefaultDMConsoleRectangle(void)
f[i] = floor(f[i]);
}
rect.pos.x = f[0] - cls.glconfig.vidWidth;
rect.pos.y = f[1] - cls.glconfig.vidHeight;
rect.pos.x = f[0] - uid.vidWidth;
rect.pos.y = f[1] - uid.vidHeight;
rect.size.width = f[2] + 50.0;
rect.size.height = f[3] + 50.0;
} else {
rect.pos.x = 0;
rect.pos.y = cls.glconfig.vidHeight * 0.58;
rect.size.width = cls.glconfig.vidWidth;
rect.size.height = cls.glconfig.vidHeight * 0.415;
rect.pos.y = uid.vidHeight * 0.58;
rect.size.width = uid.vidWidth;
rect.size.height = uid.vidHeight * 0.415;
}
return rect;
@@ -997,19 +1000,19 @@ static UIRect2D getQuickMessageDMConsoleRectangle(void)
f[i] = floor(f[i]);
}
rect.pos.x = f[0] - cls.glconfig.vidWidth;
rect.pos.y = f[1] - cls.glconfig.vidHeight;
rect.pos.x = f[0] - uid.vidWidth;
rect.pos.y = f[1] - uid.vidHeight;
rect.size.width = f[2] + 50.0;
rect.size.height = f[3] + 50.0;
} else {
rect.pos.x = 0;
rect.pos.y = cls.glconfig.vidHeight * 0.66;
rect.size.width = cls.glconfig.vidWidth;
rect.pos.y = uid.vidHeight * 0.66;
rect.size.width = uid.vidWidth;
// Fixed in 2.0
// Was 38.0 in 1.11 and below
// This prevents characters to be seen from the DM console
// in the quick message console
rect.size.height = 36.0;
rect.size.height = 36.0 * uid.scaleRes[1];
}
return rect;
@@ -1128,6 +1131,20 @@ static void DMConsoleCommandHandler(const char *txt)
CL_AddReliableCommand(szStringOut, qfalse);
}
/*
====================
getScreenWidth
====================
*/
static float getScreenWidth()
{
if (uid.bHighResScaling) {
return maxWidthRes;
} else {
return uid.vidWidth;
}
}
/*
====================
getNewConsole
@@ -1189,14 +1206,14 @@ getDefaultGMBoxRectangle
static UIRect2D getDefaultGMBoxRectangle(void)
{
UIRect2D dmRect = getDefaultDMBoxRectangle();
float height = cls.glconfig.vidHeight * ui_compass_scale->value * 0.25f;
float height = uid.vidHeight * ui_compass_scale->value * 0.25f;
float y = dmRect.size.height + dmRect.pos.y;
if (height < y) {
height = y;
}
return UIRect2D(20.0f, height, cls.glconfig.vidWidth - 20, 128.0f);
return UIRect2D(20.0f, height, (getScreenWidth() - 20) * uid.scaleRes[0], 128.0f * uid.scaleRes[1]);
}
/*
@@ -1206,9 +1223,12 @@ getDefaultDMBoxRectangle
*/
static UIRect2D getDefaultDMBoxRectangle(void)
{
float width = cls.glconfig.vidWidth * ui_compass_scale->value * 0.2f;
float width;
float screenWidth = getScreenWidth();
width = screenWidth * uid.scaleRes[0] * ui_compass_scale->value * 0.2f;
return UIRect2D(width, 0, cls.glconfig.vidWidth - (width + 192.0f), 120.0f);
return UIRect2D(width, 0, (screenWidth - (width + 192.0f)) * uid.scaleRes[0], 120.0f * uid.scaleRes[1]);
}
/*
@@ -1221,6 +1241,21 @@ float UI_GetObjectivesTop(void)
return getDefaultGMBoxRectangle().pos.y;
}
/*
====================
UI_GetObjectivesTop
====================
*/
void UI_GetHighResolutionScale(vec2_t scale)
{
if (uid.bHighResScaling) {
scale[0] = uid.scaleRes[0];
scale[1] = uid.scaleRes[1];
} else {
scale[0] = scale[1] = 1.0;
}
}
/*
====================
UI_ShowHudList
@@ -1681,11 +1716,11 @@ UI_ClearBackground
void UI_ClearBackground(void)
{
re.Set2DWindow(
0, 0, cls.glconfig.vidWidth, cls.glconfig.vidHeight, 0, cls.glconfig.vidWidth, cls.glconfig.vidHeight, 0, -1, 1
0, 0, uid.vidWidth, uid.vidHeight, 0, uid.vidWidth, uid.vidHeight, 0, -1, 1
);
re.Scissor(0, 0, cls.glconfig.vidWidth, cls.glconfig.vidHeight);
re.Scissor(0, 0, uid.vidWidth, uid.vidHeight);
re.SetColor(g_color_table[0]);
re.DrawBox(0, 0, cls.glconfig.vidWidth, cls.glconfig.vidHeight);
re.DrawBox(0, 0, uid.vidWidth, uid.vidHeight);
re.SetColor(NULL);
}
@@ -3098,7 +3133,7 @@ void UI_MapList_f(void)
MapRunnerClass *map = new MapRunnerClass;
map->Setup("maps", mappath, ".bsp", "_sml");
CL_SetMousePos(cls.glconfig.vidWidth / 2, cls.glconfig.vidHeight / 2);
CL_SetMousePos(uid.vidWidth / 2, uid.vidHeight / 2);
}
/*
@@ -3138,7 +3173,7 @@ void UI_DMMapSelect_f(void)
MpMapPickerClass *map = new MpMapPickerClass;
map->Setup(basepath, mappath, gametype);
CL_SetMousePos(cls.glconfig.vidWidth / 2, cls.glconfig.vidHeight / 2);
CL_SetMousePos(uid.vidWidth / 2, uid.vidHeight / 2);
}
/*
@@ -3322,7 +3357,7 @@ void UI_PlayerModel_f(void)
PlayerModelPickerClass *picker = new PlayerModelPickerClass;
picker->Setup("models/player", modelpath, bGermanModel);
CL_SetMousePos(cls.glconfig.vidWidth / 2, cls.glconfig.vidHeight / 2);
CL_SetMousePos(uid.vidWidth / 2, uid.vidHeight / 2);
}
/*
@@ -3712,6 +3747,7 @@ void CL_FillUIImports(void)
uii.Rend_Scissor = re.Scissor;
uii.Rend_Set2D = re.Set2DWindow;
uii.Rend_SetColor = re.SetColor;
uii.Rend_ImageExists = re.ImageExists;
uii.Cmd_Stuff = Cbuf_AddText;
uii.Cvar_GetString = CvarGetForUI;
@@ -3750,6 +3786,9 @@ void CL_FillUIImports(void)
uii.GetConfigstring = CL_ConfigString;
uii.UI_CloseDMConsole = UI_CloseDMConsole;
uii.GetRefSequence = CL_GetRefSequence;
uii.IsRendererLoaded = CL_IsRendererLoaded;
}
/*
@@ -3806,7 +3845,7 @@ void UI_CreateDialog(
{
UIDialog *dlg = new UIDialog;
UIRect2D rect =
UIRect2D((cls.glconfig.vidWidth - width) >> 1, (cls.glconfig.vidHeight - height) >> 1, width, height);
UIRect2D((uid.vidWidth - width) / 2, (uid.vidHeight - height) / 2, width, height);
UColor bgColor = UWindowColor;
dlg->Create(NULL, rect, title, bgColor, UHudColor);
@@ -3836,12 +3875,28 @@ void UI_ResolutionChange(void)
ui_compass_scale = Cvar_Get("ui_compass_scale", "0.75", CVAR_ARCHIVE | CVAR_LATCH);
} else {
// Older version doesn't have an adjustable compass, so assume 0.5 by default
ui_compass_scale = Cvar_Get("ui_compass_scale", "0.5", CVAR_ARCHIVE | CVAR_LATCH);
ui_compass_scale = Cvar_Get("ui_compass_scale", "0.55", CVAR_ARCHIVE | CVAR_LATCH);
}
CL_FillUIImports();
CL_FillUIDef();
// Added in OPM
// Scaling for high resolutions
if (uid.vidWidth > maxWidthRes && uid.vidHeight > maxHeightRes) {
const float vidRatio = (float)uid.vidWidth / (float)uid.vidHeight;
uid.scaleRes[0] = (float)uid.vidWidth / (maxHeightRes * vidRatio);
uid.scaleRes[1] = (float)uid.vidHeight / maxHeightRes;
//uid.scaleRes[0] = (float)uid.vidWidth / maxWidthRes;
//uid.scaleRes[1] = (float)uid.vidHeight / maxHeightRes;
uid.bHighResScaling = qtrue;
} else {
uid.scaleRes[0] = 1;
uid.scaleRes[1] = 1;
uid.bHighResScaling = qfalse;
}
if (!uie.ResolutionChange) {
return;
}
@@ -3876,7 +3931,7 @@ void UI_ResolutionChange(void)
menuManager.RealignMenus();
if (view3d) {
frame = UIRect2D(0, 0, cls.glconfig.vidWidth, cls.glconfig.vidHeight);
frame = UIRect2D(0, 0, uid.vidWidth, uid.vidHeight);
view3d->setFrame(frame);
}
@@ -4409,7 +4464,7 @@ void ScoreboardListItem::DrawListItem(int iColumn, const UIRect2D& drawRect, boo
{
DrawBox(drawRect, backColor, 1.0);
pFont->setColor(textColor);
pFont->Print(drawRect.pos.x + 1, drawRect.pos.y, Sys_LV_CL_ConvertString(getListItemString(iColumn)), -1, qfalse);
pFont->Print((drawRect.pos.x + 1) / uid.scaleRes[0], drawRect.pos.y / uid.scaleRes[1], Sys_LV_CL_ConvertString(getListItemString(iColumn)), -1, uid.scaleRes);
if (bTitleItem) {
UIRect2D lineRect;
@@ -4462,7 +4517,7 @@ void UI_CreateScoreboard(void)
scoreboard_h = h;
SCR_AdjustFrom640(&x, &y, &w, &h);
fColumnScale = cls.glconfig.vidWidth / 640.0;
fColumnScale = uid.vidWidth / 640.0;
cge->CG_GetScoreBoardColor(&fR, &fG, &fB, &fA);
cge->CG_GetScoreBoardFontColor(&fFontR, &fFontG, &fFontB, &fFontA);
@@ -5308,7 +5363,7 @@ void CL_InitializeUI(void)
// Create the 3D view
view3d = new View3D;
view3d->setAlwaysOnBottom(true);
view3d->InitFrame(NULL, 0, 0, cls.glconfig.vidWidth, cls.glconfig.vidHeight, -1, "facfont-20");
view3d->InitFrame(NULL, 0, 0, uid.vidWidth, uid.vidHeight, -1, "facfont-20");
view3d->setName("view3d");
view3d->InitSubtitle();
@@ -5504,7 +5559,7 @@ qboolean UI_IsResourceLoaded(const char *name)
case 107:
return S_IsSoundRegistered(name + 1);
case 110:
return R_ImageExists(name + 1);
return uii.Rend_ImageExists(name + 1);
default:
return qfalse;
}
@@ -5765,8 +5820,15 @@ void UI_BeginLoad(const char *pszMapName)
loadName = "maps/";
loadName += pszMapName;
mapfile = loadName;
loadName += ".min";
mapfile = loadName + ".bsp";
if (CL_UseLargeLightmap(pszMapName)) {
mapfile += ".bsp";
} else {
// Added in 2.0
mapfile += "_sml.bsp";
}
if (UI_ArchiveLoadMapinfo(mapfile)) {
cls.loading = SS_LOADING2;
+1
View File
@@ -57,6 +57,7 @@ void UI_ClearState(void);
void CL_BeginRegistration(void);
void CL_EndRegistration(void);
float UI_GetObjectivesTop(void);
void UI_GetHighResolutionScale(vec2_t scale);
//
// menu
+280 -310
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2024 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -40,127 +40,116 @@ Event EV_DMBox_Decay
"Event to make the dmbox console line decay"
);
static float s_dmboxWidth = 384.0;
static float s_dmboxWidth = 384.0;
static float s_dmboxOffsetX = 3.0f;
static float s_dmboxOffsetY = 8.0f;
CLASS_DECLARATION( UIWidget, UIDMBox, NULL )
{
{ &W_SizeChanged, &UIDMBox::OnSizeChanged },
{ &EV_DMBox_Goin, &UIDMBox::MoveInEvent },
{ &EV_DMBox_Decay, &UIDMBox::DecayEvent },
{ NULL, NULL }
CLASS_DECLARATION(UIWidget, UIDMBox, NULL) {
{&W_SizeChanged, &UIDMBox::OnSizeChanged},
{&EV_DMBox_Goin, &UIDMBox::MoveInEvent },
{&EV_DMBox_Decay, &UIDMBox::DecayEvent },
{NULL, NULL }
};
UIDMBox::UIDMBox()
{
m_numitems = 0;
m_reallyshown = true;
m_fontbold = NULL;
m_boxstate = boxstate_t::box_out;
m_iBeginDecay = 0;
m_boxtime = uid.time;
m_movespeed = 500;
m_drawoutline = com_target_game->integer >= target_game_e::TG_MOHTA;
m_numitems = 0;
m_reallyshown = true;
m_fontbold = NULL;
m_boxstate = boxstate_t::box_out;
m_iBeginDecay = 0;
m_boxtime = uid.time;
m_movespeed = 500;
m_drawoutline = com_target_game->integer >= target_game_e::TG_MOHTA;
}
void UIDMBox::VerifyBoxOut( void )
void UIDMBox::VerifyBoxOut(void)
{
PostMoveinEvent();
if (m_boxstate != boxstate_t::box_moving_out && m_boxstate != boxstate_t::box_out)
{
ChangeBoxState(boxstate_t::box_moving_out);
}
PostMoveinEvent();
if (m_boxstate != boxstate_t::box_moving_out && m_boxstate != boxstate_t::box_out) {
ChangeBoxState(boxstate_t::box_moving_out);
}
}
void UIDMBox::ChangeBoxState( boxstate_t state )
void UIDMBox::ChangeBoxState(boxstate_t state)
{
m_boxstate = state;
m_boxtime = uid.time;
setShowState();
m_boxstate = state;
m_boxtime = uid.time;
setShowState();
if (state == box_out) {
PostMoveinEvent();
}
if (state == box_out) {
PostMoveinEvent();
}
}
void UIDMBox::HandleBoxMoving( void )
void UIDMBox::HandleBoxMoving(void)
{
int delta;
UIRect2D newRect;
int delta;
UIRect2D newRect;
if (m_boxstate != boxstate_t::box_moving_out && m_boxstate != boxstate_t::box_moving_in) {
return;
}
if (m_boxstate != boxstate_t::box_moving_out && m_boxstate != boxstate_t::box_moving_in) {
return;
}
delta = m_movespeed * (uid.time - m_boxtime) / 1000;
m_boxtime = 1000 * delta / m_movespeed + m_boxtime;
if (m_boxstate == boxstate_t::box_moving_out)
{
newRect.size.width = m_frame.size.width;
newRect.size.height = m_frame.size.height;
newRect.pos.x = m_frame.pos.x;
newRect.pos.y = delta + m_frame.pos.y;
delta = m_movespeed * (uid.time - m_boxtime) / 1000;
m_boxtime = 1000 * delta / m_movespeed + m_boxtime;
if (m_boxstate == boxstate_t::box_moving_out) {
newRect.size.width = m_frame.size.width;
newRect.size.height = m_frame.size.height;
newRect.pos.x = m_frame.pos.x;
newRect.pos.y = delta + m_frame.pos.y;
if (newRect.pos.y <= 0.0)
{
newRect.pos.y = 0.0;
ChangeBoxState(boxstate_t::box_out);
}
}
else if (m_boxstate == boxstate_t::box_moving_in)
{
newRect.size.width = m_frame.size.width;
newRect.size.height = m_frame.size.height;
newRect.pos.x = m_frame.pos.x;
newRect.pos.y = delta - m_frame.pos.y;
if (newRect.pos.y <= 0.0) {
newRect.pos.y = 0.0;
ChangeBoxState(boxstate_t::box_out);
}
} else if (m_boxstate == boxstate_t::box_moving_in) {
newRect.size.width = m_frame.size.width;
newRect.size.height = m_frame.size.height;
newRect.pos.x = m_frame.pos.x;
newRect.pos.y = delta - m_frame.pos.y;
if (newRect.pos.y <= -newRect.size.height)
{
newRect.pos.y = -newRect.size.height;
ChangeBoxState(boxstate_t::box_in);
}
}
else {
newRect = m_frame;
}
if (newRect.pos.y <= -newRect.size.height) {
newRect.pos.y = -newRect.size.height;
ChangeBoxState(boxstate_t::box_in);
}
} else {
newRect = m_frame;
}
setFrame(newRect);
setFrame(newRect);
}
void UIDMBox::PostMoveinEvent( void )
void UIDMBox::PostMoveinEvent(void)
{
if (m_boxstate != boxstate_t::box_out) {
return;
}
if (m_boxstate != boxstate_t::box_out) {
return;
}
if (!EventPending(EV_DMBox_Goin)) {
PostEvent(EV_DMBox_Goin, 10.0);
}
else {
PostponeEvent(EV_DMBox_Goin, 10.0);
}
if (!EventPending(EV_DMBox_Goin)) {
PostEvent(EV_DMBox_Goin, 10.0);
} else {
PostponeEvent(EV_DMBox_Goin, 10.0);
}
}
void UIDMBox::PostDecayEvent( void )
void UIDMBox::PostDecayEvent(void)
{
if (!EventPending(EV_DMBox_Decay))
{
float fDelayTime;
int iNumLines;
int i;
const char* pszString = m_items[0].string.c_str();
if (!EventPending(EV_DMBox_Decay)) {
float fDelayTime;
int iNumLines;
int i;
const char *pszString = m_items[0].string.c_str();
//
// Calculate the number of lines
//
iNumLines = 1;
for (i = 0; pszString[i]; i++)
{
if (pszString[i] == '\n') {
iNumLines++;
}
}
//
// Calculate the number of lines
//
iNumLines = 1;
for (i = 0; pszString[i]; i++) {
if (pszString[i] == '\n') {
iNumLines++;
}
}
if (m_items[0].flags & DMBOX_ITEM_FLAG_BOLD) {
fDelayTime = iNumLines * 8.0;
@@ -168,291 +157,272 @@ void UIDMBox::PostDecayEvent( void )
//
// Bold as twice more decay
//
else if (m_items[0].flags & DMBOX_ITEM_FLAG_DEATH) {
fDelayTime = iNumLines * 6.0;
}
else {
fDelayTime = iNumLines * 5.0;
}
else if (m_items[0].flags & DMBOX_ITEM_FLAG_DEATH) {
fDelayTime = iNumLines * 6.0;
} else {
fDelayTime = iNumLines * 5.0;
}
m_iBeginDecay = cls.realtime;
m_iEndDecay = (int)(fDelayTime * 1000.0);
m_iBeginDecay = cls.realtime;
m_iEndDecay = (int)(fDelayTime * 1000.0);
PostEvent(EV_DMBox_Decay, fDelayTime);
}
PostEvent(EV_DMBox_Decay, fDelayTime);
}
}
void UIDMBox::setShowState( void )
void UIDMBox::setShowState(void)
{
if (m_reallyshown) {
setShow(m_boxstate != box_in);
} else {
setShow(false);
}
if (m_reallyshown) {
setShow(m_boxstate != box_in);
} else {
setShow(false);
}
}
void UIDMBox::RemoveTopItem( void )
void UIDMBox::RemoveTopItem(void)
{
int i;
int i;
if (m_numitems > 0) {
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 )
str UIDMBox::CalculateBreaks(UIFont *font, str text, float max_width)
{
str newText, sTmp;
int i;
float fX;
float fwX, fsX;
str newText;
float fX;
float fwX;
const char *current;
int count;
Cmd_TokenizeString(text.c_str());
if (Cmd_Argc())
{
fX = 0.0;
fsX = font->getCharWidth(' ');
current = text;
fX = 0.0;
for (i = 0; i < Cmd_Argc(); i++)
{
sTmp = Cmd_Argv(i);
for (count = font->DBCSGetWordBlockCount(current, -1); count;
current += count, count = font->DBCSGetWordBlockCount(current, -1)) {
fwX = font->getWidth(current, count);
fwX = font->getWidth(sTmp.c_str(), -1);
if (fwX + i <= max_width)
{
if (fwX + i + fX <= max_width)
{
newText += sTmp + " ";
} else {
newText += "\n" + sTmp + " ";
}
}
else
{
sTmp += "\n";
fX = 0.0;
}
}
} else {
newText = "";
}
if (fX + fwX > max_width) {
newText += "\n" + str(current, 0, count);
fX = 0;
} else {
newText += str(current, 0, count);
}
return newText;
fX += fwX;
}
return newText;
}
float UIDMBox::PrintWrap( UIFont *font, float x, float y, str text )
float UIDMBox::PrintWrap(UIFont *font, float x, float y, str text)
{
const char* p1, * p2;
size_t n, l;
float fY;
const char *p1, *p2;
size_t n, l;
float fY;
fY = y;
p1 = text.c_str();
l = text.length();
fY = y;
p1 = text.c_str();
l = text.length();
for (;;)
{
p2 = strchr(p1, '\n');
if (!p2) {
break;
}
for (;;) {
p2 = strchr(p1, '\n');
if (!p2) {
break;
}
n = p2 - p1;
if (n >= l) {
break;
}
n = p2 - p1;
if (n >= l) {
break;
}
font->Print(x, fY, p1, p2 - p1, qfalse);
p1 = p2 + 1;
l -= n;
fY += font->getHeight(qfalse);
}
font->Print(x, fY, p1, p2 - p1, getHighResScale());
p1 = p2 + 1;
l -= n;
fY += font->getHeight();
}
font->Print(x, fY, p1, l, qfalse);
if (*p1) {
font->Print(x, fY, p1, l, getHighResScale());
fY += font->getHeight();
}
return font->getHeight(qfalse) + (fY - y);
return fY - y;
}
float UIDMBox::DrawItem( item_t *in, float x, float y, float alpha )
float UIDMBox::DrawItem(item_t *in, float x, float y, float alpha)
{
if (m_drawoutline) {
//
// Draw an outline
//
if (m_drawoutline) {
//
// Draw an outline
//
in->font->setColor(UBlack);
in->font->setAlpha(alpha);
in->font->setColor(UBlack);
in->font->setAlpha(alpha);
PrintWrap(in->font, x + 1, y + 2, in->string);
PrintWrap(in->font, x + 2, y + 1, in->string);
PrintWrap(in->font, x - 1, y + 2, in->string);
PrintWrap(in->font, x - 2, y + 1, in->string);
PrintWrap(in->font, x - 1, y - 2, in->string);
PrintWrap(in->font, x - 2, y - 1, in->string);
PrintWrap(in->font, x + 1, y - 2, in->string);
PrintWrap(in->font, x + 2, y - 1, in->string);
PrintWrap(in->font, x + 2, y, in->string);
PrintWrap(in->font, x - 2, y, in->string);
PrintWrap(in->font, x, y + 2, in->string);
PrintWrap(in->font, x, y - 2, in->string);
}
PrintWrap(in->font, x + 1, y + 2, in->string);
PrintWrap(in->font, x + 2, y + 1, in->string);
PrintWrap(in->font, x - 1, y + 2, in->string);
PrintWrap(in->font, x - 2, y + 1, in->string);
PrintWrap(in->font, x - 1, y - 2, in->string);
PrintWrap(in->font, x - 2, y - 1, in->string);
PrintWrap(in->font, x + 1, y - 2, in->string);
PrintWrap(in->font, x + 2, y - 1, in->string);
PrintWrap(in->font, x + 2, y, in->string);
PrintWrap(in->font, x - 2, y, in->string);
PrintWrap(in->font, x, y + 2, in->string);
PrintWrap(in->font, x, y - 2, in->string);
}
in->font->setColor(in->color);
in->font->setAlpha(alpha);
in->font->setColor(in->color);
in->font->setAlpha(alpha);
return PrintWrap(in->font, x, y, in->string);
return PrintWrap(in->font, x, y, in->string);
}
void UIDMBox::Print( const char *text )
void UIDMBox::Print(const char *text)
{
const char* text1 = text;
const char *text1 = text;
if (m_numitems > 5)
{
//
// Overwrite an item
//
RemoveTopItem();
}
if (m_numitems > 5) {
//
// Overwrite an item
//
RemoveTopItem();
}
m_items[m_numitems].flags = 0;
m_items[m_numitems].flags = 0;
if (*text == MESSAGE_CHAT_WHITE)
{
m_items[m_numitems].color = UGrey;
m_items[m_numitems].font = m_fontbold;
m_items[m_numitems].flags |= DMBOX_ITEM_FLAG_BOLD;
if (*text == MESSAGE_CHAT_WHITE) {
m_items[m_numitems].color = UGrey;
m_items[m_numitems].font = m_fontbold;
m_items[m_numitems].flags |= DMBOX_ITEM_FLAG_BOLD;
text1 = text + 1;
}
else if (*text == MESSAGE_CHAT_RED)
{
m_items[m_numitems].color = ULightRed;
m_items[m_numitems].font = m_fontbold;
m_items[m_numitems].flags |= DMBOX_ITEM_FLAG_DEATH;
text1 = text + 1;
} else if (*text == MESSAGE_CHAT_RED) {
m_items[m_numitems].color = ULightRed;
m_items[m_numitems].font = m_fontbold;
m_items[m_numitems].flags |= DMBOX_ITEM_FLAG_DEATH;
text1 = text + 1;
}
else if (*text == MESSAGE_CHAT_GREEN)
{
if (com_target_game->integer >= TG_MOHTA) {
m_items[m_numitems].color = ULightGreen;
} else {
m_items[m_numitems].color = UGreen;
}
text1 = text + 1;
} else if (*text == MESSAGE_CHAT_GREEN) {
if (com_target_game->integer >= TG_MOHTA) {
m_items[m_numitems].color = ULightGreen;
} else {
m_items[m_numitems].color = UGreen;
}
m_items[m_numitems].font = m_fontbold;
m_items[m_numitems].flags |= DMBOX_ITEM_FLAG_DEATH;
text1 = text + 1;
}
else
{
m_items[m_numitems].color = m_foreground_color;
m_items[m_numitems].font = m_font;
}
text1 = text + 1;
} else {
m_items[m_numitems].color = m_foreground_color;
m_items[m_numitems].font = m_font;
}
m_items[m_numitems].string = CalculateBreaks(m_items[m_numitems].font, text1, s_dmboxWidth);
m_items[m_numitems].string = CalculateBreaks(m_items[m_numitems].font, text1, s_dmboxWidth);
m_numitems++;
VerifyBoxOut();
PostDecayEvent();
m_numitems++;
VerifyBoxOut();
PostDecayEvent();
}
void UIDMBox::OnSizeChanged( Event *ev )
void UIDMBox::OnSizeChanged(Event *ev)
{
s_dmboxWidth = m_frame.size.width;
s_dmboxWidth = m_frame.size.width;
}
void UIDMBox::Create( const UIRect2D& rect, const UColor& fore, const UColor& back, float alpha )
void UIDMBox::Create(const UIRect2D& rect, const UColor& fore, const UColor& back, float alpha)
{
InitFrame(NULL, rect, 0, "facfont-20");
InitFrame(NULL, rect, 0, "facfont-20");
if (!m_fontbold) {
m_fontbold = new UIFont("facfont-20");
}
if (!m_fontbold) {
m_fontbold = new UIFont("facfont-20");
}
m_fontbold->setColor(URed);
setBackgroundColor(back, true);
setForegroundColor(fore);
setBackgroundAlpha(alpha);
m_fontbold->setColor(URed);
setBackgroundColor(back, true);
setForegroundColor(fore);
setBackgroundAlpha(alpha);
Connect(this, W_SizeChanged, W_SizeChanged);
OnSizeChanged(NULL);
Connect(this, W_SizeChanged, W_SizeChanged);
OnSizeChanged(NULL);
m_movespeed = rect.size.height * 3.0;
m_movespeed = rect.size.height * 3.0;
setShowState();
setShowState();
}
void UIDMBox::MoveInEvent( Event *ev )
void UIDMBox::MoveInEvent(Event *ev) {}
void UIDMBox::DecayEvent(Event *ev)
{
RemoveTopItem();
if (m_numitems) {
PostDecayEvent();
}
}
void UIDMBox::DecayEvent( Event *ev )
void UIDMBox::Draw(void)
{
RemoveTopItem();
if (m_numitems) {
PostDecayEvent();
}
float fsY;
int i;
float alpha;
float alphaScale;
alphaScale = 0.8f;
HandleBoxMoving();
if (!m_numitems) {
//
// Nothing to show
//
return;
}
m_font->setColor(m_foreground_color);
alpha = (float)(cls.realtime - m_iBeginDecay) / (float)m_iEndDecay;
if (alpha > 1.0) {
alpha = 1.0;
}
alpha = (1.0 - alpha) * 4.0;
if (alpha > 1.0) {
alpha = 1.0;
}
if (cge) {
alphaScale = 1.0 - cge->CG_GetObjectiveAlpha();
}
fsY = DrawItem(m_items, s_dmboxOffsetX, s_dmboxOffsetY, alpha * alphaScale);
fsY = alpha <= 0.2 ? s_dmboxOffsetY : fsY + s_dmboxOffsetY;
for (i = 1; i < m_numitems; i++) {
fsY += DrawItem(&m_items[i], s_dmboxOffsetX, fsY, alphaScale);
if (fsY > m_frame.size.height) {
if (EventPending(EV_DMBox_Decay)) {
CancelEventsOfType(EV_DMBox_Decay);
}
PostEvent(EV_DMBox_Decay, 0.0);
break;
}
}
}
void UIDMBox::Draw( void )
void UIDMBox::setRealShow(bool b)
{
float fsY;
int i;
float alpha;
float alphaScale;
alphaScale = 0.8f;
HandleBoxMoving();
if (!m_numitems) {
//
// Nothing to show
//
return;
}
m_font->setColor(m_foreground_color);
alpha = (float)(cls.realtime - m_iBeginDecay) / (float)m_iEndDecay;
if (alpha > 1.0) alpha = 1.0;
alpha = (1.0 - alpha) * 4.0;
if (alpha > 1.0) alpha = 1.0;
if (cge) {
alphaScale = 1.0 - cge->CG_GetObjectiveAlpha();
}
fsY = DrawItem(m_items, s_dmboxOffsetX, s_dmboxOffsetY, alpha * alphaScale);
fsY = alpha <= 0.2 ? s_dmboxOffsetY : fsY + s_dmboxOffsetY;
for (i = 1; i < m_numitems; i++)
{
fsY += DrawItem(&m_items[i], s_dmboxOffsetX, fsY, alphaScale);
if (fsY > m_frame.size.height)
{
if (EventPending(EV_DMBox_Decay)) {
CancelEventsOfType(EV_DMBox_Decay);
}
PostEvent(EV_DMBox_Decay, 0.0);
break;
}
}
this->m_reallyshown = b;
setShowState();
}
void UIDMBox::setRealShow( bool b )
void UIDMBox::Clear(void)
{
this->m_reallyshown = b;
setShowState();
}
void UIDMBox::Clear( void )
{
m_numitems = 0;
m_numitems = 0;
}
+1 -1
View File
@@ -47,7 +47,7 @@ FilePickerClass::FilePickerClass()
window = new UIFloatingWindow();
window->Create(
NULL,
UIRect2D((cls.glconfig.vidWidth - 400) / 2, (cls.glconfig.vidHeight - 300) / 2, 400, 300),
UIRect2D((uid.vidWidth - 400) / 2, (uid.vidHeight - 300) / 2, 400, 300),
"File Picker",
UColor(0.15f, 0.195f, 0.278f),
UHudColor
+270 -294
View File
@@ -40,394 +40,370 @@ Event EV_GMBox_Decay
"Event to make the gmbox console line decay"
);
static float s_gmboxWidth = 640.0;
static float s_gmboxWidth = 640.0;
static float s_gmboxOffsetX = 3.0f;
static float s_gmboxOffsetY = 0.0f;
CLASS_DECLARATION( UIWidget, UIGMBox, NULL )
{
{ &W_SizeChanged, &UIGMBox::OnSizeChanged },
{ &EV_GMBox_Goin, &UIGMBox::MoveInEvent },
{ &EV_GMBox_Decay, &UIGMBox::DecayEvent },
{ NULL, NULL }
CLASS_DECLARATION(UIWidget, UIGMBox, NULL) {
{&W_SizeChanged, &UIGMBox::OnSizeChanged},
{&EV_GMBox_Goin, &UIGMBox::MoveInEvent },
{&EV_GMBox_Decay, &UIGMBox::DecayEvent },
{NULL, NULL }
};
UIGMBox::UIGMBox()
{
m_numitems = 0;
m_reallyshown = true;
m_fontbold = NULL;
m_boxstate = boxstate_t::box_out;
m_iBeginDecay = 0;
m_boxtime = uid.time;
m_movespeed = 500;
m_drawoutline = com_target_game->integer >= target_game_e::TG_MOHTA;
m_numitems = 0;
m_reallyshown = true;
m_fontbold = NULL;
m_boxstate = boxstate_t::box_out;
m_iBeginDecay = 0;
m_boxtime = uid.time;
m_movespeed = 500;
m_drawoutline = com_target_game->integer >= target_game_e::TG_MOHTA;
}
void UIGMBox::VerifyBoxOut( void )
void UIGMBox::VerifyBoxOut(void)
{
PostMoveinEvent();
if (m_boxstate != boxstate_t::box_moving_out && m_boxstate != boxstate_t::box_out)
{
ChangeBoxState(boxstate_t::box_moving_out);
}
PostMoveinEvent();
if (m_boxstate != boxstate_t::box_moving_out && m_boxstate != boxstate_t::box_out) {
ChangeBoxState(boxstate_t::box_moving_out);
}
}
void UIGMBox::ChangeBoxState( boxstate_t state )
void UIGMBox::ChangeBoxState(boxstate_t state)
{
m_boxstate = state;
m_boxtime = uid.time;
setShowState();
m_boxstate = state;
m_boxtime = uid.time;
setShowState();
if (state == box_out) {
PostMoveinEvent();
}
if (state == box_out) {
PostMoveinEvent();
}
}
void UIGMBox::HandleBoxMoving( void )
void UIGMBox::HandleBoxMoving(void)
{
int delta;
UIRect2D newRect;
int delta;
UIRect2D newRect;
if (m_boxstate != boxstate_t::box_moving_out && m_boxstate != boxstate_t::box_moving_in) {
return;
}
if (m_boxstate != boxstate_t::box_moving_out && m_boxstate != boxstate_t::box_moving_in) {
return;
}
delta = m_movespeed * (uid.time - m_boxtime) / 1000;
m_boxtime = 1000 * delta / m_movespeed + m_boxtime;
if (m_boxstate == boxstate_t::box_moving_out)
{
newRect.size.width = m_frame.size.width;
newRect.size.height = m_frame.size.height;
newRect.pos.x = m_frame.pos.x;
newRect.pos.y = delta + m_frame.pos.y;
delta = m_movespeed * (uid.time - m_boxtime) / 1000;
m_boxtime = 1000 * delta / m_movespeed + m_boxtime;
if (m_boxstate == boxstate_t::box_moving_out) {
newRect.size.width = m_frame.size.width;
newRect.size.height = m_frame.size.height;
newRect.pos.x = m_frame.pos.x;
newRect.pos.y = delta + m_frame.pos.y;
if (newRect.pos.y <= 0.0)
{
newRect.pos.y = 0.0;
ChangeBoxState(boxstate_t::box_out);
}
}
else if (m_boxstate == boxstate_t::box_moving_in)
{
newRect.size.width = m_frame.size.width;
newRect.size.height = m_frame.size.height;
newRect.pos.x = m_frame.pos.x;
newRect.pos.y = delta - m_frame.pos.y;
if (newRect.pos.y <= 0.0) {
newRect.pos.y = 0.0;
ChangeBoxState(boxstate_t::box_out);
}
} else if (m_boxstate == boxstate_t::box_moving_in) {
newRect.size.width = m_frame.size.width;
newRect.size.height = m_frame.size.height;
newRect.pos.x = m_frame.pos.x;
newRect.pos.y = delta - m_frame.pos.y;
if (newRect.pos.y <= -newRect.size.height)
{
newRect.pos.y = -newRect.size.height;
ChangeBoxState(boxstate_t::box_in);
}
} else {
newRect = m_frame;
}
if (newRect.pos.y <= -newRect.size.height) {
newRect.pos.y = -newRect.size.height;
ChangeBoxState(boxstate_t::box_in);
}
} else {
newRect = m_frame;
}
setFrame(newRect);
setFrame(newRect);
}
void UIGMBox::PostMoveinEvent( void )
void UIGMBox::PostMoveinEvent(void)
{
if (m_boxstate != boxstate_t::box_out) {
return;
}
if (m_boxstate != boxstate_t::box_out) {
return;
}
if (!EventPending(EV_GMBox_Goin)) {
PostEvent(EV_GMBox_Goin, 10.0);
} else {
PostponeEvent(EV_GMBox_Goin, 10.0);
}
if (!EventPending(EV_GMBox_Goin)) {
PostEvent(EV_GMBox_Goin, 10.0);
} else {
PostponeEvent(EV_GMBox_Goin, 10.0);
}
}
void UIGMBox::PostDecayEvent( void )
void UIGMBox::PostDecayEvent(void)
{
if (!EventPending(EV_GMBox_Decay))
{
float fDelayTime;
int iNumLines;
int i;
const char* pszString = m_items[0].string.c_str();
if (!EventPending(EV_GMBox_Decay)) {
float fDelayTime;
int iNumLines;
int i;
const char *pszString = m_items[0].string.c_str();
//
// Calculate the number of lines
//
iNumLines = 1;
for (i = 0; pszString[i]; i++)
{
if (pszString[i] == '\n') {
iNumLines++;
}
}
//
// Calculate the number of lines
//
iNumLines = 1;
for (i = 0; pszString[i]; i++) {
if (pszString[i] == '\n') {
iNumLines++;
}
}
//
// Bold as twice more decay
//
if (m_items[0].flags & GMBOX_ITEM_FLAG_BOLD) {
fDelayTime = iNumLines * 10.0;
} else {
fDelayTime = iNumLines * 5.0;
}
//
// Bold as twice more decay
//
if (m_items[0].flags & GMBOX_ITEM_FLAG_BOLD) {
fDelayTime = iNumLines * 10.0;
} else {
fDelayTime = iNumLines * 5.0;
}
m_iBeginDecay = cls.realtime;
m_iEndDecay = (int)(fDelayTime * 1000.0);
m_iBeginDecay = cls.realtime;
m_iEndDecay = (int)(fDelayTime * 1000.0);
PostEvent(EV_GMBox_Decay, fDelayTime);
}
PostEvent(EV_GMBox_Decay, fDelayTime);
}
}
void UIGMBox::setShowState( void )
void UIGMBox::setShowState(void)
{
if (m_reallyshown) {
setShow(m_boxstate != box_in);
} else {
setShow(false);
}
if (m_reallyshown) {
setShow(m_boxstate != box_in);
} else {
setShow(false);
}
}
void UIGMBox::RemoveTopItem( void )
void UIGMBox::RemoveTopItem(void)
{
int i;
int i;
if (m_numitems > 0) {
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 )
str UIGMBox::CalculateBreaks(UIFont *font, str text, float max_width)
{
str newText, sTmp;
int i;
float fX;
float fwX, fsX;
str newText;
float fX;
float fwX;
const char *current;
int count;
Cmd_TokenizeString(text.c_str());
if (Cmd_Argc())
{
fX = 0.0;
fsX = font->getCharWidth(' ');
current = text;
fX = 0.0;
for (i = 0; i < Cmd_Argc(); i++)
{
sTmp = Cmd_Argv(i);
for (count = font->DBCSGetWordBlockCount(current, -1); count;
current += count, count = font->DBCSGetWordBlockCount(current, -1)) {
fwX = font->getWidth(current, count);
fwX = font->getWidth(sTmp.c_str(), -1);
if (fwX + i <= max_width)
{
if (fwX + i + fX <= max_width)
{
newText += sTmp + " ";
} else {
newText += "\n" + sTmp + " ";
}
}
else
{
sTmp += "\n";
fX = 0.0;
}
}
} else {
newText = "";
}
if (fX + fwX > max_width) {
newText += "\n" + str(current, 0, count);
fX = 0;
} else {
newText += str(current, 0, count);
}
return newText;
fX += fwX;
}
return newText;
}
float UIGMBox::PrintWrap( UIFont *font, float x, float y, str text )
float UIGMBox::PrintWrap(UIFont *font, float x, float y, str text)
{
const char* p1, * p2;
size_t n, l;
float fY;
const char *p1, *p2;
size_t n, l;
float fY;
fY = y;
p1 = text.c_str();
l = text.length();
fY = y;
p1 = text.c_str();
l = text.length();
for (;;)
{
p2 = strchr(p1, '\n');
if (!p2) {
break;
}
for (;;) {
p2 = strchr(p1, '\n');
if (!p2) {
break;
}
n = p2 - p1;
if (n >= l) {
break;
}
n = p2 - p1;
if (n >= l) {
break;
}
font->Print(x, fY, p1, p2 - p1, qfalse);
p1 = p2 + 1;
l -= n;
fY += font->getHeight(qfalse);
}
font->Print(x, fY, p1, p2 - p1, getHighResScale());
p1 = p2 + 1;
l -= n;
fY += font->getHeight();
}
font->Print(x, fY, p1, l, qfalse);
if (*p1) {
font->Print(x, fY, p1, l, getHighResScale());
fY += font->getHeight();
}
return font->getHeight(qfalse) + (fY - y);
return fY - y;
}
float UIGMBox::DrawItem( item_t *in, float x, float y, float alpha )
float UIGMBox::DrawItem(item_t *in, float x, float y, float alpha)
{
if (m_drawoutline) {
//
// Draw an outline
//
if (m_drawoutline) {
//
// Draw an outline
//
in->font->setColor(UBlack);
in->font->setAlpha(alpha);
in->font->setColor(UBlack);
in->font->setAlpha(alpha);
PrintWrap(in->font, x + 1, y + 2, in->string);
PrintWrap(in->font, x + 2, y + 1, in->string);
PrintWrap(in->font, x - 1, y + 2, in->string);
PrintWrap(in->font, x - 2, y + 1, in->string);
PrintWrap(in->font, x - 1, y - 2, in->string);
PrintWrap(in->font, x - 2, y - 1, in->string);
PrintWrap(in->font, x + 1, y - 2, in->string);
PrintWrap(in->font, x + 2, y - 1, in->string);
PrintWrap(in->font, x + 2, y, in->string);
PrintWrap(in->font, x - 2, y, in->string);
PrintWrap(in->font, x, y + 2, in->string);
PrintWrap(in->font, x, y - 2, in->string);
}
PrintWrap(in->font, x + 1, y + 2, in->string);
PrintWrap(in->font, x + 2, y + 1, in->string);
PrintWrap(in->font, x - 1, y + 2, in->string);
PrintWrap(in->font, x - 2, y + 1, in->string);
PrintWrap(in->font, x - 1, y - 2, in->string);
PrintWrap(in->font, x - 2, y - 1, in->string);
PrintWrap(in->font, x + 1, y - 2, in->string);
PrintWrap(in->font, x + 2, y - 1, in->string);
PrintWrap(in->font, x + 2, y, in->string);
PrintWrap(in->font, x - 2, y, in->string);
PrintWrap(in->font, x, y + 2, in->string);
PrintWrap(in->font, x, y - 2, in->string);
}
in->font->setColor(in->color);
in->font->setAlpha(alpha);
in->font->setColor(in->color);
in->font->setAlpha(alpha);
return PrintWrap(in->font, x, y, in->string);
return PrintWrap(in->font, x, y, in->string);
}
void UIGMBox::Print( const char *text )
void UIGMBox::Print(const char *text)
{
const char* text1 = text;
const char *text1 = text;
if (m_numitems > 4)
{
//
// Overwrite an item
//
RemoveTopItem();
}
if (m_numitems > 4) {
//
// Overwrite an item
//
RemoveTopItem();
}
m_items[m_numitems].flags = 0;
m_items[m_numitems].flags = 0;
if (*text == 3)
{
m_items[m_numitems].color = UWhite;
m_items[m_numitems].font = m_fontbold;
m_items[m_numitems].flags |= GMBOX_ITEM_FLAG_BOLD;
if (*text == 3) {
m_items[m_numitems].color = UWhite;
m_items[m_numitems].font = m_fontbold;
m_items[m_numitems].flags |= GMBOX_ITEM_FLAG_BOLD;
text1 = text + 1;
}
else
{
m_items[m_numitems].color = m_foreground_color;
m_items[m_numitems].font = m_font;
}
text1 = text + 1;
} else {
m_items[m_numitems].color = m_foreground_color;
m_items[m_numitems].font = m_font;
}
m_items[m_numitems].string = CalculateBreaks(m_items[m_numitems].font, text1, s_gmboxWidth);
m_items[m_numitems].string = CalculateBreaks(m_items[m_numitems].font, text1, s_gmboxWidth);
m_numitems++;
VerifyBoxOut();
PostDecayEvent();
m_numitems++;
VerifyBoxOut();
PostDecayEvent();
}
void UIGMBox::OnSizeChanged( Event *ev )
void UIGMBox::OnSizeChanged(Event *ev)
{
s_gmboxWidth = m_frame.size.width;
s_gmboxWidth = m_frame.size.width;
}
void UIGMBox::Create( const UIRect2D& rect, const UColor& fore, const UColor& back, float alpha )
void UIGMBox::Create(const UIRect2D& rect, const UColor& fore, const UColor& back, float alpha)
{
InitFrame(NULL, rect, 0, "facfont-20");
InitFrame(NULL, rect, 0, "facfont-20");
if (!m_fontbold) {
m_fontbold = new UIFont("facfont-20");
}
if (!m_fontbold) {
m_fontbold = new UIFont("facfont-20");
}
m_fontbold->setColor(URed);
setBackgroundColor(back, true);
setForegroundColor(fore);
setBackgroundAlpha(alpha);
m_fontbold->setColor(URed);
setBackgroundColor(back, true);
setForegroundColor(fore);
setBackgroundAlpha(alpha);
Connect(this, W_SizeChanged, W_SizeChanged);
OnSizeChanged(NULL);
Connect(this, W_SizeChanged, W_SizeChanged);
OnSizeChanged(NULL);
m_movespeed = rect.size.height * 3.0;
m_movespeed = rect.size.height * 3.0;
setShowState();
setShowState();
}
void UIGMBox::MoveInEvent( Event *ev )
void UIGMBox::MoveInEvent(Event *ev) {}
void UIGMBox::DecayEvent(Event *ev)
{
RemoveTopItem();
if (m_numitems) {
PostDecayEvent();
}
}
void UIGMBox::DecayEvent( Event *ev )
void UIGMBox::Draw(void)
{
RemoveTopItem();
if (m_numitems) {
PostDecayEvent();
}
float fsY;
int i;
float alpha;
float alphaScale;
alphaScale = 1.0;
HandleBoxMoving();
if (!m_numitems) {
//
// Nothing to show
//
return;
}
m_font->setColor(m_foreground_color);
alpha = (float)(cls.realtime - m_iBeginDecay) / (float)m_iEndDecay;
if (alpha > 1.0) {
alpha = 1.0;
}
alpha = (1.0 - alpha) * 4.0;
if (alpha > 1.0) {
alpha = 1.0;
}
if (cge) {
alphaScale = 1.0 - cge->CG_GetObjectiveAlpha();
}
fsY = DrawItem(m_items, s_gmboxOffsetX, s_gmboxOffsetY, alpha * alphaScale);
fsY = alpha <= 0.2 ? s_gmboxOffsetY : fsY + s_gmboxOffsetY;
for (i = 1; i < m_numitems; i++) {
fsY += DrawItem(&m_items[i], s_gmboxOffsetX, fsY, alphaScale);
if (fsY > m_frame.size.height) {
if (EventPending(EV_GMBox_Decay)) {
CancelEventsOfType(EV_GMBox_Decay);
}
PostEvent(EV_GMBox_Decay, 0.0);
break;
}
}
}
void UIGMBox::Draw( void )
void UIGMBox::setRealShow(bool b)
{
float fsY;
int i;
float alpha;
float alphaScale;
alphaScale = 1.0;
HandleBoxMoving();
if (!m_numitems) {
//
// Nothing to show
//
return;
}
m_font->setColor(m_foreground_color);
alpha = (float)(cls.realtime - m_iBeginDecay) / (float)m_iEndDecay;
if (alpha > 1.0) alpha = 1.0;
alpha = (1.0 - alpha) * 4.0;
if (alpha > 1.0) alpha = 1.0;
if (cge) {
alphaScale = 1.0 - cge->CG_GetObjectiveAlpha();
}
fsY = DrawItem(m_items, s_gmboxOffsetX, s_gmboxOffsetY, alpha * alphaScale);
fsY = alpha <= 0.2 ? s_gmboxOffsetY : fsY + s_gmboxOffsetY;
for (i = 1; i < m_numitems; i++)
{
fsY += DrawItem(&m_items[i], s_gmboxOffsetX, fsY, alphaScale);
if (fsY > m_frame.size.height)
{
if (EventPending(EV_GMBox_Decay)) {
CancelEventsOfType(EV_GMBox_Decay);
}
PostEvent(EV_GMBox_Decay, 0.0);
break;
}
}
this->m_reallyshown = b;
setShowState();
}
void UIGMBox::setRealShow( bool b )
void UIGMBox::Clear(void)
{
this->m_reallyshown = b;
setShowState();
m_numitems = 0;
}
void UIGMBox::Clear( void )
{
m_numitems = 0;
}
+5 -5
View File
@@ -112,7 +112,7 @@ void FakkMiniconsole::PostMoveinEvent(void)
void FakkMiniconsole::OnSizeChanged(Event *ev)
{
m_maxlines = m_frame.size.height / m_font->getHeight(false);
m_maxlines = m_frame.size.height / m_font->getHeight(getHighResScale());
}
void FakkMiniconsole::MoveInEvent(Event *ev)
@@ -163,14 +163,14 @@ void FakkMiniconsole::Draw(void)
HandleBoxMoving();
m_font->setColor(m_foreground_color);
aty = m_frame.size.height - m_font->getHeight(false);
aty = m_frame.size.height - m_font->getHeight(getHighResScale());
for (i = m_lines.NumObjects(); i > 0; i--) {
if (-m_font->getHeight(false) >= aty) {
if (-m_font->getHeight(getHighResScale()) >= aty) {
break;
}
m_font->Print(0, aty, m_lines.ObjectAt(i), -1, false);
aty -= m_font->getHeight(false);
m_font->Print(0, aty / getHighResScale()[1], m_lines.ObjectAt(i), -1, getHighResScale());
aty -= m_font->getHeight(getHighResScale());
}
}
+1 -1
View File
@@ -51,7 +51,7 @@ MpMapPickerClass::MpMapPickerClass()
window = new UIFloatingWindow();
window->Create(
NULL,
UIRect2D((cls.glconfig.vidWidth - 300) / 2, (cls.glconfig.vidHeight - 200) / 2, 300, 200),
UIRect2D((uid.vidWidth - 300) / 2, (uid.vidHeight - 200) / 2, 300, 200),
"Select a Map",
UColor(0.15f, 0.195f, 0.278f),
UHudColor
+1 -1
View File
@@ -155,7 +155,7 @@ PlayerModelPickerClass::PlayerModelPickerClass()
window = new UIFloatingWindow();
window->Create(
NULL,
UIRect2D((cls.glconfig.vidWidth - 400) / 2, (cls.glconfig.vidHeight - 300) / 2, 400, 300),
UIRect2D((uid.vidWidth - 400) / 2, (uid.vidHeight - 300) / 2, 400, 300),
"Player Model Select...",
UColor(0.15f, 0.195f, 0.278f),
UHudColor
+11 -2
View File
@@ -177,6 +177,9 @@ void FAKKServerListItem::DrawListItem(int iColumn, const UIRect2D& drawRect, boo
newRect.size.height *= uid.vidHeight / 768;
}
*/
virtualScale[0] = m_parent->getHighResScale()[0];
virtualScale[1] = m_parent->getHighResScale()[1];
if (!pColoringType->integer) {
if (IfQueryFailed() || (IsDifferentVersion() && IsQueried())) {
@@ -210,7 +213,7 @@ void FAKKServerListItem::DrawListItem(int iColumn, const UIRect2D& drawRect, boo
newRect.pos.y / virtualScale[1],
getListItemString(iColumn).c_str(),
-1,
false //m_parent->isVirtual()
virtualScale
);
} else {
if (IsDifferentVersion()) {
@@ -266,7 +269,7 @@ void FAKKServerListItem::DrawListItem(int iColumn, const UIRect2D& drawRect, boo
newRect.pos.y / virtualScale[1],
getListItemString(iColumn).c_str(),
-1,
false //m_parent->isVirtual()
virtualScale
);
if (IsDifferentVersion()) {
@@ -1181,6 +1184,11 @@ void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, v
}
iServerTotalCount += ServerListCount(serverlist);
// Removed in 2.0
// Only add entries for servers that are queried successfully
// it avoids unnecessary entries
#if 0
for (j = 0; j < ServerListCount(serverlist); j++) {
GServer arrayServer = ServerListGetServer(serverlist, j);
@@ -1208,6 +1216,7 @@ void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, v
uiServerList->AddItem(pNewServerItem);
}
#endif
/*
for (i = 1; i <= uiServerList->getNumItems(); i++)
+33 -14
View File
@@ -443,6 +443,7 @@ void UIFakkLabel::DrawStatbar(float frac)
float alpha;
qhandle_t hMat;
float w, h;
float fvWidth, fvHeight;
col[0] = col[1] = col[2] = col[3] = 1.0;
@@ -488,11 +489,20 @@ void UIFakkLabel::DrawStatbar(float frac)
{
float width = frac * m_frame.size.width;
re.DrawTilePic(0.0, 0.0, width, m_frame.size.height, m_statbar_material->GetMaterial());
fvWidth = m_frame.size.width / m_vVirtualScale[0] / uii.Rend_GetShaderWidth(m_statbar_material->GetMaterial());
fvHeight = m_frame.size.height / m_vVirtualScale[1] / uii.Rend_GetShaderHeight(m_statbar_material->GetMaterial());
re.DrawStretchPic(0.0, 0.0, width, m_frame.size.height, 0, 0, fvWidth, fvHeight, m_statbar_material->GetMaterial());
//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);
re.DrawTilePic(0.0, 0.0, width, m_frame.size.height, m_statbar_material_flash->GetMaterial());
fvWidth = m_frame.size.width / m_vVirtualScale[0] / uii.Rend_GetShaderWidth(m_statbar_material_flash->GetMaterial());
fvHeight = m_frame.size.height / m_vVirtualScale[1] / uii.Rend_GetShaderHeight(m_statbar_material_flash->GetMaterial());
re.DrawStretchPic(0.0, 0.0, width, m_frame.size.height, 0, 0, fvWidth, fvHeight, m_statbar_material_flash->GetMaterial());
//re.DrawTilePic(0.0, 0.0, width, m_frame.size.height, m_statbar_material_flash->GetMaterial());
}
if (m_statbar_material_marker) {
@@ -521,13 +531,22 @@ void UIFakkLabel::DrawStatbar(float frac)
{
float y = m_frame.size.height * (1.0 - frac);
re.DrawTilePic(0.0, y, m_frame.size.width, m_frame.size.height, m_statbar_material->GetMaterial());
fvWidth = m_frame.size.width / m_vVirtualScale[0] / uii.Rend_GetShaderWidth(m_statbar_material->GetMaterial());
fvHeight = m_frame.size.height / m_vVirtualScale[1] / uii.Rend_GetShaderHeight(m_statbar_material->GetMaterial());
re.DrawStretchPic(0.0, y, m_frame.size.width, m_frame.size.height, 0, 0, fvWidth, fvHeight, m_statbar_material->GetMaterial());
//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);
re.DrawTilePic(
0.0, y, m_frame.size.width, m_frame.size.height, m_statbar_material_flash->GetMaterial()
);
fvWidth = m_frame.size.width / m_vVirtualScale[0] / uii.Rend_GetShaderWidth(m_statbar_material_flash->GetMaterial());
fvHeight = m_frame.size.height / m_vVirtualScale[1] / uii.Rend_GetShaderHeight(m_statbar_material_flash->GetMaterial());
re.DrawStretchPic(0.0, y, m_frame.size.width, m_frame.size.height, 0, 0, fvWidth, fvHeight, m_statbar_material_flash->GetMaterial());
//re.DrawTilePic(
// 0.0, y, m_frame.size.width, m_frame.size.height, m_statbar_material_flash->GetMaterial()
//);
}
if (m_statbar_material_marker) {
@@ -961,8 +980,8 @@ void UIFakkLabel::DrawStatRotator(float frac)
vNeedleDir[0] = fSinVal;
vNeedleDir[1] = -fCosVal;
vSize[0] = (m_frame.size.width + m_frame.size.height) / m_frame.size.width * m_angles[2] * m_vVirtualScale[0];
vSize[1] = (m_frame.size.width + m_frame.size.height) / m_frame.size.height * m_scale * m_vVirtualScale[1];
vSize[0] = (m_frame.size.width + m_frame.size.height) / m_frame.size.width * m_angles[2] * getVirtualScale()[0];
vSize[1] = (m_frame.size.width + m_frame.size.height) / m_frame.size.height * m_scale * getVirtualScale()[1];
vCenter[0] = (m_frame.size.width * 0.5f - vSize[0]) * vNeedleDir[0] + m_frame.size.width * 0.5f;
vCenter[1] = (m_frame.size.height * 0.5f - vSize[1]) * vNeedleDir[1] + m_frame.size.height * 0.5f;
@@ -1357,7 +1376,7 @@ void UIFakkLabel::Draw(void)
m_iFontAlignmentVertical,
Sys_LV_CL_ConvertString(va("%s", CL_ConfigString(cl.snap.ps.stats[m_stat_configstring]))),
UBlack,
m_bVirtual ? m_vVirtualScale : NULL
getVirtualScale()
);
} else {
m_font->PrintJustified(
@@ -1365,7 +1384,7 @@ void UIFakkLabel::Draw(void)
m_iFontAlignmentHorizontal,
m_iFontAlignmentVertical,
Sys_LV_CL_ConvertString(va("%s", CL_ConfigString(cl.snap.ps.stats[m_stat_configstring]))),
m_bVirtual ? m_vVirtualScale : NULL
getVirtualScale()
);
}
return;
@@ -1384,7 +1403,7 @@ void UIFakkLabel::Draw(void)
m_iFontAlignmentVertical,
va("%d", delta),
UBlack,
m_bVirtual ? m_vVirtualScale : NULL
getVirtualScale()
);
} else {
m_font->PrintJustified(
@@ -1392,7 +1411,7 @@ void UIFakkLabel::Draw(void)
m_iFontAlignmentHorizontal,
m_iFontAlignmentVertical,
va("%d", delta),
m_bVirtual ? m_vVirtualScale : NULL
getVirtualScale()
);
}
return;
@@ -1478,7 +1497,7 @@ void UIFakkLabel::Draw(void)
m_iFontAlignmentVertical,
Sys_LV_CL_ConvertString(va("%s", CL_ConfigString(CS_WEAPONS + cl.snap.ps.activeItems[m_itemindex]))),
UBlack,
m_bVirtual ? m_vVirtualScale : NULL
getVirtualScale()
);
} else {
m_font->PrintJustified(
@@ -1486,7 +1505,7 @@ void UIFakkLabel::Draw(void)
m_iFontAlignmentHorizontal,
m_iFontAlignmentVertical,
Sys_LV_CL_ConvertString(va("%s", CL_ConfigString(CS_WEAPONS + cl.snap.ps.activeItems[m_itemindex]))),
m_bVirtual ? m_vVirtualScale : NULL
getVirtualScale()
);
}
+43 -46
View File
@@ -124,9 +124,9 @@ void View3D::DrawFPS(void)
re.SetColor(UBlack);
re.DrawBox(
0.0,
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 4.0,
m_frame.pos.y + m_frame.size.height - m_font->getHeight() * 4.0,
m_frame.pos.x + m_frame.size.width,
m_font->getHeight(qfalse) * 4.0
m_font->getHeight() * 4.0
);
}
@@ -145,11 +145,11 @@ void View3D::DrawFPS(void)
}
m_font->Print(
m_font->getHeight(qfalse) * 10.0,
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 3.0,
m_font->getHeight(getHighResScale()) * 10.0 / getHighResScale()[0],
(m_frame.pos.y + m_frame.size.height - m_font->getHeight(getHighResScale()) * 3.0) / getHighResScale()[1],
string,
-1,
qfalse
getHighResScale()
);
// Draw elements count
@@ -162,11 +162,11 @@ void View3D::DrawFPS(void)
Com_sprintf(string, sizeof(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,
(m_font->getHeight(getHighResScale()) * 10.0) / getHighResScale()[0],
(m_frame.pos.y + m_frame.size.height - m_font->getHeight(getHighResScale()) * 2.0) / getHighResScale()[1],
string,
-1,
qfalse
getHighResScale()
);
Com_sprintf(
@@ -179,11 +179,11 @@ void View3D::DrawFPS(void)
);
m_font->Print(
m_font->getHeight(qfalse) * 10.0,
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse),
(m_font->getHeight(getHighResScale()) * 10.0) / getHighResScale()[0],
(m_frame.pos.y + m_frame.size.height - m_font->getHeight(getHighResScale())) / getHighResScale()[1],
string,
-1,
qfalse
getHighResScale()
);
m_font->setColor(UBlack);
@@ -208,32 +208,32 @@ void View3D::PrintSound(int channel, const char *name, float vol, int rvol, floa
float xStep;
float height;
height = m_font->getHeight(false);
height = m_font->getHeight(getHighResScale());
xStep = height;
x = 0;
Com_sprintf(buf, sizeof(buf), "%d", channel);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, false);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, getHighResScale());
x += xStep + xStep;
Com_sprintf(buf, sizeof(buf), "%s", name);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, false);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, getHighResScale());
x += xStep * 30.0;
Com_sprintf(buf, sizeof(buf), "vol:%.2f", vol);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, false);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, getHighResScale());
x += xStep * 8;
Com_sprintf(buf, sizeof(buf), "rvol:%.2f", (float)(rvol / 128.f));
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, false);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, getHighResScale());
x += xStep * 5;
Com_sprintf(buf, sizeof(buf), "pit:%.2f", pitch);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, false);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, getHighResScale());
x += xStep * 5;
Com_sprintf(buf, sizeof(buf), "base:%d", (int)base);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, false);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, getHighResScale());
line++;
}
@@ -264,8 +264,7 @@ void DisplayServerNetProfileInfo(UIFont *font, float y, netprofclient_t *netprof
(unsigned int)((float)(netprofile->outPackets.numFragmented + netprofile->inPackets.numFragmented)
/ (float)(netprofile->inPackets.totalProcessed + netprofile->outPackets.totalProcessed)
)),
-1,
qfalse
-1
);
font->Print(334, y, va("%i", netprofile->inPackets.percentDropped));
font->Print(364, y, va("%i", netprofile->outPackets.percentDropped));
@@ -276,8 +275,7 @@ void DisplayServerNetProfileInfo(UIFont *font, float y, netprofclient_t *netprof
(unsigned int)((float)(netprofile->outPackets.numDropped + netprofile->inPackets.numDropped)
/ (float)(netprofile->inPackets.totalProcessed + netprofile->outPackets.totalProcessed)
)),
-1,
qfalse
-1
);
font->Print(434, y, va("%i", netprofile->inPackets.percentDropped));
font->Print(464, y, va("%i", netprofile->outPackets.percentDropped));
@@ -288,8 +286,7 @@ void DisplayServerNetProfileInfo(UIFont *font, float y, netprofclient_t *netprof
(unsigned int)((float)(netprofile->outPackets.totalLengthConnectionLess
+ netprofile->inPackets.totalLengthConnectionLess)
/ (float)(netprofile->outPackets.totalSize + netprofile->inPackets.totalSize))),
-1,
qfalse
-1
);
font->Print(534, y, va("%i", netprofile->inPackets.bytesPerSec));
font->Print(594, y, va("%i", netprofile->outPackets.bytesPerSec));
@@ -303,7 +300,7 @@ void DisplayClientNetProfile(UIFont *font, float x, float y, netprofclient_t *ne
float fontHeight;
float columnHeight;
fontHeight = font->getHeight(qfalse);
fontHeight = font->getHeight();
columns[0] = x + 120;
columns[1] = x + 230;
columns[2] = x + 330;
@@ -402,13 +399,13 @@ void View3D::DrawNetProfile(void)
setFont("verdana-14");
m_font->setColor(UWhite);
fontHeight = m_font->getHeight(qfalse);
fontHeight = m_font->getHeight();
yOffset = sv_netprofileoverlay->integer + 8;
if (svs.netprofile.rate) {
m_font->Print(8, yOffset, va("Server Net Profile Max Rate: %i", svs.netprofile.rate), -1, qfalse);
m_font->Print(8, yOffset, va("Server Net Profile Max Rate: %i", svs.netprofile.rate), -1);
} else {
m_font->Print(8, yOffset, "Server Net Profile Max Rate: none", -1, qfalse);
m_font->Print(8, yOffset, "Server Net Profile Max Rate: none", -1);
}
columnHeight = fontHeight + fontHeight + yOffset;
@@ -487,10 +484,10 @@ void View3D::DrawNetProfile(void)
setFont("verdana-14");
m_font->setColor(UWhite);
fontHeight = m_font->getHeight(qfalse);
fontHeight = m_font->getHeight();
yOffset = cl_netprofileoverlay->integer + 16;
m_font->Print(16, yOffset, "Client Net Profile", -1, qfalse);
m_font->Print(16, yOffset, "Client Net Profile", -1);
NetProfileCalcStats(&cls.netprofile.outPackets, 500);
NetProfileCalcStats(&cls.netprofile.inPackets, 500);
@@ -567,7 +564,7 @@ void View3D::CenterPrint(void)
m_iFontAlignmentHorizontal,
m_iFontAlignmentVertical,
p,
m_bVirtual ? m_vVirtualScale : NULL
getVirtualScale()
);
m_font->setColor(UColor(1, 1, 1, alpha));
@@ -575,7 +572,7 @@ void View3D::CenterPrint(void)
frame = getClientFrame();
m_font->PrintJustified(
frame, m_iFontAlignmentHorizontal, m_iFontAlignmentVertical, p, m_bVirtual ? m_vVirtualScale : NULL
frame, m_iFontAlignmentHorizontal, m_iFontAlignmentVertical, p, getVirtualScale()
);
m_font->setColor(UBlack);
@@ -628,7 +625,7 @@ void View3D::LocationPrint(void)
alpha = Q_clamp_float(alpha, 0, 1);
x = m_x_coord / 640.f * m_screenframe.size.width;
y = (480 - m_font->getHeight(false) - m_y_coord) / 480.f * m_screenframe.size.height;
y = (480 - m_font->getHeight(getHighResScale()) - m_y_coord) / 480.f * m_screenframe.size.height;
if (m_x_coord == -1) {
horiz = FONT_JUSTHORZ_CENTER;
@@ -647,7 +644,7 @@ void View3D::LocationPrint(void)
horiz,
vert,
p,
m_bVirtual ? m_vVirtualScale : NULL
getVirtualScale()
);
m_font->setColor(UColor(1, 1, 1, alpha));
@@ -658,7 +655,7 @@ void View3D::LocationPrint(void)
horiz,
vert,
p,
m_bVirtual ? m_vVirtualScale : NULL
getVirtualScale()
);
m_font->setColor(UBlack);
@@ -746,7 +743,7 @@ void View3D::DrawSubtitleOverlay(void)
{
cvar_t *subAlpha;
int i;
float minX, maxY;
float minX, maxX;
int line;
subAlpha = Cvar_Get("subAlpha", "0.5", 0);
@@ -781,8 +778,8 @@ void View3D::DrawSubtitleOverlay(void)
}
}
minX = m_screenframe.size.height - m_font->getHeight(false) * 10;
maxY = (m_frame.pos.x + m_frame.size.width) - (m_frame.pos.x + m_frame.size.width) * 0.2f;
minX = m_screenframe.size.height - m_font->getHeight(getHighResScale()) * 10;
maxX = ((m_frame.pos.x + m_frame.size.width) - (m_frame.pos.x + m_frame.size.width) * 0.2f) / getHighResScale()[0];
line = 0;
for (i = 0; i < MAX_SUBTITLES; i++) {
@@ -790,7 +787,7 @@ void View3D::DrawSubtitleOverlay(void)
continue;
}
if (m_font->getWidth(subs[i]->string, sizeof(oldStrings[i])) > maxY) {
if (m_font->getWidth(subs[i]->string, sizeof(oldStrings[i])) > maxX) {
char buf[2048];
char *c;
char *end;
@@ -813,12 +810,12 @@ void View3D::DrawSubtitleOverlay(void)
width = m_font->getWidth(c, blockcount);
if (total + width > maxY) {
if (total + width > maxX) {
m_font->setColor(UColor(0, 0, 0, alpha[i] * subAlpha->value));
m_font->Print(18, m_font->getHeight(false) * line + minX + 1.f, buf, -1, false);
m_font->Print(18, (m_font->getHeight(getHighResScale()) * line + minX + 1.f) / getHighResScale()[1], buf, -1, getHighResScale());
m_font->setColor(UColor(1, 1, 1, alpha[i] * subAlpha->value));
m_font->Print(20, m_font->getHeight(false) * line + minX, buf, -1, false);
m_font->Print(20, (m_font->getHeight(getHighResScale()) * line + minX) / getHighResScale()[1], buf, -1, getHighResScale());
line++;
@@ -841,17 +838,17 @@ void View3D::DrawSubtitleOverlay(void)
}
m_font->setColor(UColor(0, 0, 0, alpha[i] * subAlpha->value));
m_font->Print(18, m_font->getHeight(false) * line + minX + 1.f, buf, -1, qfalse);
m_font->Print(18, (m_font->getHeight(getHighResScale()) * line + minX + 1.f) / getHighResScale()[1], buf, -1, getHighResScale());
m_font->setColor(UColor(1, 1, 1, alpha[i] * subAlpha->value));
m_font->Print(20, m_font->getHeight(false) * line + minX, buf, -1, qfalse);
m_font->Print(20, (m_font->getHeight(getHighResScale()) * line + minX) / getHighResScale()[1], buf, -1, getHighResScale());
line++;
} else {
m_font->setColor(UColor(0, 0, 0, alpha[i] * subAlpha->value));
m_font->Print(18, m_font->getHeight(false) * line + minX + 1.f, subs[i]->string, -1, qfalse);
m_font->Print(18, (m_font->getHeight(getHighResScale()) * line + minX + 1.f) / getHighResScale()[1], subs[i]->string, -1, getHighResScale());
m_font->setColor(UColor(1, 1, 1, alpha[i] * subAlpha->value));
m_font->Print(20, m_font->getHeight(false) * line + minX, subs[i]->string, -1, qfalse);
m_font->Print(20, (m_font->getHeight(getHighResScale()) * line + minX) / getHighResScale()[1], subs[i]->string, -1, getHighResScale());
line++;
}
+5
View File
@@ -389,6 +389,8 @@ typedef struct {
qhandle_t whiteShader;
qhandle_t consoleShader;
fontInfo_t consoleFont;
int refSequence;
} clientStatic_t;
extern clientStatic_t cls;
@@ -557,6 +559,9 @@ void UI_LoadResource( const char *name );
qboolean CL_CheckPaused(void);
int CL_GetRefSequence(void);
qboolean CL_IsRendererLoaded(void);
//
// cl_input
//
+2
View File
@@ -81,6 +81,7 @@ LPALGENBUFFERS qalGenBuffers;
LPALDELETEBUFFERS qalDeleteBuffers;
LPALISBUFFER qalIsBuffer;
LPALBUFFERDATA qalBufferData;
LPALBUFFERI qalBufferi;
LPALGETBUFFERF qalGetBufferf;
LPALGETBUFFERFV qalGetBufferfv;
LPALGETBUFFERI qalGetBufferi;
@@ -201,6 +202,7 @@ qboolean QAL_Init(const char *libname)
qalDeleteBuffers = GPA("alDeleteBuffers");
qalIsBuffer = GPA("alIsBuffer");
qalBufferData = GPA("alBufferData");
qalBufferi = GPA("alBufferi");
qalGetBufferf = GPA("alGetBufferf");
qalGetBufferfv = GPA("alGetBufferfv");
qalGetBufferi = GPA("alGetBufferi");
+1 -1
View File
@@ -120,7 +120,7 @@ extern LPALBUFFERDATA qalBufferData;
extern LPALBUFFERF qalBufferf;
extern LPALBUFFER3F qalBuffer3f;
extern LPALBUFFERFV qalBufferfv;
extern LPALBUFFERF qalBufferi;
extern LPALBUFFERI qalBufferi;
extern LPALBUFFER3F qalBuffer3i;
extern LPALBUFFERFV qalBufferiv;
extern LPALGETBUFFERF qalGetBufferf;
+2 -1
View File
@@ -34,11 +34,12 @@ extern "C" {
typedef struct snd_info_s
{
int rate;
int width;
float width;
int channels;
int samples;
int size;
int dataofs;
int dataalign;
} snd_info_t;
typedef struct snd_codec_s snd_codec_t;
+1 -1
View File
@@ -622,7 +622,7 @@ int S_MP3_CodecReadStream(snd_stream_t* stream, int bytes, void* buffer)
mp3info = stream->ptr;
// Make sure we get complete frames all the way through.
bytes -= bytes % (stream->info.channels * stream->info.width);
bytes -= fmod(bytes, (stream->info.channels * stream->info.width));
if (mp3info->buflen)
{
+13 -7
View File
@@ -133,6 +133,7 @@ static qboolean S_ReadRIFFHeader(fileHandle_t file, snd_info_t *info)
char dump[16];
int bits;
int fmtlen = 0;
int bytealign;
// skip the riff wav header
FS_Read(dump, 12, file);
@@ -149,17 +150,22 @@ static qboolean S_ReadRIFFHeader(fileHandle_t file, snd_info_t *info)
info->channels = FGetLittleShort(file);
info->rate = FGetLittleLong(file);
FGetLittleLong(file);
FGetLittleShort(file);
bytealign = 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;
}
//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->width = bits / 8.0;
info->dataofs = 0;
if (bits == 16) {
info->dataalign = 1;
} else {
info->dataalign = (bytealign / info->channels - 4) / 4 * 8 + 1;
}
// Skip the rest of the format chunk if required
if(fmtlen > 16)
+6 -2
View File
@@ -104,7 +104,7 @@ void S_Init(qboolean full_startup)
s_musicVolume = Cvar_Get("s_musicvolume", "0.9", CVAR_ARCHIVE);
s_ambientVolume = Cvar_Get("s_ambientvolume", "1.00", CVAR_ARCHIVE);
s_separation = Cvar_Get("s_separation", "0.5", CVAR_ARCHIVE);
s_khz = Cvar_Get("s_khz", "11", CVAR_ARCHIVE | CVAR_SOUND_LATCH);
s_khz = Cvar_Get("s_khz", "44", CVAR_ARCHIVE | CVAR_SOUND_LATCH);
s_loadas8bit = Cvar_Get("s_loadas8bit", "0", CVAR_ARCHIVE | CVAR_LATCH);
s_mixPreStep = Cvar_Get("s_mixPreStep", "0.05", CVAR_ARCHIVE);
s_show = Cvar_Get("s_show", "0", CVAR_CHEAT);
@@ -552,7 +552,7 @@ void S_StartLocalSound(const char *sound_name, qboolean force_load)
}
S_StartSound(
0,
NULL,
s_iListenerNumber,
CHAN_MENU,
sfxHandle,
@@ -749,6 +749,10 @@ void S_Play()
int i;
char name[MAX_QPATH];
if (Cmd_Argc() < 2) {
return;
}
for (i = 1; i < Cmd_Argc(); i++) {
if (strrchr(Cmd_Argv(i), '.')) {
Q_strncpyz(name, Cmd_Argv(i), sizeof(name));
+1
View File
@@ -62,6 +62,7 @@ typedef struct {
int dataofs;
int datasize;
int dataalign;
} wavinfo_t;
typedef struct sfx_s {
+63 -61
View File
@@ -43,13 +43,13 @@ short int GetLittleShort()
byte bytes[2];
} val;
# ifdef Q3_LITTLE_ENDIAN
#ifdef Q3_LITTLE_ENDIAN
val.bytes[0] = data_p[0];
val.bytes[1] = data_p[1];
# else
#else
val.bytes[0] = data_p[1];
val.bytes[1] = data_p[0];
# endif
#endif
data_p += sizeof(short);
return val.value;
@@ -67,17 +67,17 @@ int GetLittleLong()
byte bytes[4];
} val;
# ifdef Q3_LITTLE_ENDIAN
#ifdef Q3_LITTLE_ENDIAN
val.bytes[0] = data_p[0];
val.bytes[1] = data_p[1];
val.bytes[2] = data_p[2];
val.bytes[3] = data_p[3];
# else
#else
val.bytes[0] = data_p[3];
val.bytes[1] = data_p[2];
val.bytes[2] = data_p[1];
val.bytes[3] = data_p[0];
# endif
#endif
data_p += sizeof(int);
return val.value;
@@ -97,13 +97,13 @@ void SetLittleShort(int i)
val.value = i;
# ifdef Q3_LITTLE_ENDIAN
#ifdef Q3_LITTLE_ENDIAN
data_p[0] = val.bytes[0];
data_p[1] = val.bytes[1];
# else
#else
data_p[0] = val.bytes[1];
data_p[1] = val.bytes[0];
# endif
#endif
data_p += sizeof(short);
}
@@ -122,17 +122,17 @@ void SetLittleLong(int i)
val.value = i;
# ifdef Q3_LITTLE_ENDIAN
#ifdef Q3_LITTLE_ENDIAN
data_p[0] = val.bytes[0];
data_p[1] = val.bytes[1];
data_p[2] = val.bytes[2];
data_p[3] = val.bytes[3];
# else
#else
data_p[0] = val.bytes[3];
data_p[1] = val.bytes[2];
data_p[2] = val.bytes[1];
data_p[3] = val.bytes[0];
# endif
#endif
data_p += sizeof(int);
}
@@ -218,6 +218,7 @@ wavinfo_t GetWavinfo(const char *name, byte *wav, int wavlength)
{
wavinfo_t info;
int samples;
short bytealign;
memset(&info, 0, sizeof(wavinfo_t));
@@ -247,7 +248,9 @@ wavinfo_t GetWavinfo(const char *name, byte *wav, int wavlength)
if (info.format == 17) {
info.channels = GetLittleShort();
info.rate = (float)GetLittleLong();
data_p += 6;
data_p += 4;
bytealign = GetLittleShort();
info.width = (float)GetLittleShort() / 8.f;
data_p += 2;
@@ -270,12 +273,16 @@ wavinfo_t GetWavinfo(const char *name, byte *wav, int wavlength)
Com_Error(ERR_DROP, "Sound %s has a bad loop length", name);
}
info.dataofs = 0;
info.dataofs = data_p - wav;
info.datasize = iff_chunk_len - bytealign + info.dataofs;
info.dataalign = (bytealign / info.channels - 4) / 4 * 8 + 1;
} else if (info.format == 1) {
info.channels = GetLittleShort();
info.rate = (float)GetLittleLong();
data_p += 6;
info.width = (float)(GetLittleShort() / 8);
data_p += 4;
bytealign = GetLittleShort();
info.width = (float)GetLittleShort() / 8.f;
FindChunk("data");
if (!data_p) {
@@ -292,14 +299,16 @@ wavinfo_t GetWavinfo(const char *name, byte *wav, int wavlength)
Com_Error(ERR_DROP, "Sound %s has a bad loop length", name);
}
info.dataofs = data_p - wav;
info.dataofs = data_p - wav;
info.datasize = iff_chunk_len;
info.dataalign = (bytealign / info.channels - 4) / 4 * 8 + 1;
// dataalign should always be 1
assert(info.dataalign == 1);
} else {
Com_Printf("Microsoft PCM format only\n");
return info;
}
info.datasize = iff_chunk_len;
return info;
}
@@ -310,26 +319,24 @@ DownSampleWav
*/
qboolean DownSampleWav(wavinfo_t *info, byte *wav, int wavlength, int newkhz, byte **newdata)
{
int newdatasize;
byte* datap;
int i;
int ii;
int error;
int width;
int oldsamples;
int oldrate;
int newdatasize;
byte *datap;
int i;
int ii;
int error;
int width;
int oldsamples;
int oldrate;
newdatasize = 0;
datap = &wav[info->dataofs];
datap = &wav[info->dataofs];
if (info->channels > 1)
{
if (info->channels > 1) {
Com_DPrintf("Could not downsample WAV file. Stereo WAVs not supported!\n");
return 0;
}
if (info->format != 1 || !info->dataofs)
{
if (info->format != 1 || !info->dataofs) {
Com_DPrintf("Could not downsample WAV file. Not PCM format!\n");
return 0;
}
@@ -348,29 +355,27 @@ qboolean DownSampleWav(wavinfo_t *info, byte *wav, int wavlength, int newkhz, by
}
}
oldsamples = info->samples;
oldrate = info->rate;
oldsamples = info->samples;
oldrate = info->rate;
info->samples = newdatasize / width;
info->rate = (float)newkhz;
info->rate = (float)newkhz;
newdatasize += info->dataofs;
*newdata = (byte*)Z_TagMalloc(newdatasize, TAG_SOUND);
*newdata = (byte *)Z_TagMalloc(newdatasize, TAG_SOUND);
memcpy(*newdata, wav, info->dataofs);
iff_data = *newdata;
iff_end = *newdata + newdatasize;
iff_end = *newdata + newdatasize;
FindChunk("RIFF");
if (!data_p || strncmp((const char*)data_p + 8, "WAVE", 4u))
{
if (!data_p || strncmp((const char *)data_p + 8, "WAVE", 4u)) {
Com_DPrintf("Missing RIFF/WAVE chunks\n");
return 0;
}
iff_data = data_p + 12;
FindChunk("fmt ");
if (!data_p)
{
if (!data_p) {
Com_DPrintf("Missing fmt chunk\n");
return 0;
}
@@ -380,8 +385,7 @@ qboolean DownSampleWav(wavinfo_t *info, byte *wav, int wavlength, int newkhz, by
data_p += 8;
FindChunk("data");
if (!data_p)
{
if (!data_p) {
Com_DPrintf("Missing data chunk\n");
return 0;
}
@@ -427,10 +431,10 @@ S_LoadSound
*/
qboolean S_LoadSound(const char *fileName, sfx_t *sfx, int streamed, qboolean force_load)
{
int size;
int size;
fileHandle_t file_handle;
char tempName[MAX_RES_NAME + 1];
int realKhz;
char tempName[MAX_RES_NAME + 1];
int realKhz;
sfx->buffer = 0;
@@ -440,10 +444,10 @@ qboolean S_LoadSound(const char *fileName, sfx_t *sfx, int streamed, qboolean fo
if (streamed) {
sfx->length = 5000;
sfx->width = 1;
sfx->width = 1;
sfx->iFlags |= SFX_FLAG_STREAMED;
sfx->time_length = 5000.0;
sfx->data = NULL;
sfx->data = NULL;
return qtrue;
}
@@ -456,22 +460,20 @@ qboolean S_LoadSound(const char *fileName, sfx_t *sfx, int streamed, qboolean fo
}
size = FS_FOpenFileRead(fileName, &file_handle, qfalse, qtrue);
if (size <= 0)
{
if (size <= 0) {
if (file_handle) {
FS_FCloseFile(file_handle);
}
return qfalse;
}
sfx->data = (byte*)Z_TagMalloc(size, TAG_SOUND);
sfx->data = (byte *)Z_TagMalloc(size, TAG_SOUND);
FS_Read(sfx->data, size, file_handle);
FS_FCloseFile(file_handle);
sfx->info = GetWavinfo(fileName, sfx->data, size);
if (sfx->info.channels != 1 && !streamed)
{
if (sfx->info.channels != 1 && !streamed) {
Com_Printf("%s is a stereo wav file\n", fileName);
Z_Free(sfx->data);
sfx->data = NULL;
@@ -496,8 +498,8 @@ qboolean S_LoadSound(const char *fileName, sfx_t *sfx, int streamed, qboolean fo
}
if (!(sfx->iFlags & SFX_FLAG_STREAMED) && realKhz < sfx->info.rate) {
byte* newdata;
int newdatasize;
byte *newdata;
int newdatasize;
newdata = NULL;
if (sfx->iFlags & SFX_FLAG_NO_OFFSET) {
@@ -508,13 +510,13 @@ qboolean S_LoadSound(const char *fileName, sfx_t *sfx, int streamed, qboolean fo
if (newdatasize) {
Z_Free(sfx->data);
sfx->data = newdata;
sfx->data = newdata;
sfx->info.datasize = newdatasize;
}
}
sfx->length = sfx->info.samples;
sfx->width = sfx->info.width;
sfx->length = sfx->info.samples;
sfx->width = sfx->info.width;
sfx->time_length = sfx->info.samples / sfx->info.rate * 1000.f;
if (sfx->iFlags & SFX_FLAG_STREAMED) {
@@ -540,7 +542,7 @@ S_LoadMP3
*/
qboolean S_LoadMP3(const char *fileName, sfx_t *sfx)
{
int length;
int length;
fileHandle_t file_handle;
length = FS_FOpenFileRead(fileName, &file_handle, 0, 1);
@@ -552,9 +554,9 @@ qboolean S_LoadMP3(const char *fileName, sfx_t *sfx)
}
memset(&sfx->info, 0, sizeof(sfx->info));
sfx->data = (byte*)Z_TagMalloc(length, TAG_SOUND);
sfx->data = (byte *)Z_TagMalloc(length, TAG_SOUND);
sfx->length = length;
sfx->width = 1;
sfx->width = 1;
FS_Read(sfx->data, length, file_handle);
FS_FCloseFile(file_handle);
+123 -22
View File
@@ -100,6 +100,9 @@ int music_currentsong = 0;
static qboolean enumeration_ext = qfalse;
static qboolean enumeration_all_ext = qfalse;
static qboolean ima4_ext = qfalse;
static qboolean soft_block_align = qfalse;
song_t music_songs[MAX_MUSIC_SONGS];
openal_internal_t openal;
static float s_fFadeStartTime;
@@ -113,7 +116,7 @@ static int
S_OPENAL_SpatializeStereoSound(const vec3_t listener_origin, const vec3_t listener_left, const vec3_t origin);
static void S_OPENAL_reverb(int iChannel, int iReverbType, float fReverbLevel);
static bool S_OPENAL_LoadMP3_Codec(const char *_path, sfx_t *pSfx);
static ALuint S_OPENAL_Format(int width, int channels);
static ALuint S_OPENAL_Format(float width, int channels);
#define alDieIfError() __alDieIfError(__FILE__, __LINE__)
@@ -449,7 +452,9 @@ S_OPENAL_InitExtensions
*/
static bool S_OPENAL_InitExtensions()
{
Com_Printf("AL extensions ignored\n");
ima4_ext = qalIsExtensionPresent("AL_EXT_IMA4");
soft_block_align = qalIsExtensionPresent("AL_SOFT_block_alignment");
return true;
extensions_table_t extensions_table[4] = {
@@ -594,6 +599,7 @@ qboolean S_OPENAL_Init()
Com_Printf("OpenAL: No reverb support. Reverb is disabled.\n");
}
}
s_reverb->modified = false;
al_current_volume = Square(s_volume->value);
qalListenerf(AL_GAIN, al_current_volume);
@@ -612,7 +618,9 @@ qboolean S_OPENAL_Init()
}
for (i = 0; i < MAX_SOUNDSYSTEM_CHANNELS_2D_STREAM; i++) {
if (!S_OPENAL_InitChannel(i + MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D, &openal.chan_2D_stream[i])) {
if (!S_OPENAL_InitChannel(
i + MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D, &openal.chan_2D_stream[i]
)) {
return false;
}
}
@@ -638,6 +646,17 @@ qboolean S_OPENAL_Init()
return false;
}
//
// Disable sound virtualization on special channels
// (triggered music, ambient sounds...)
//
for (i = 0; i < MAX_SOUNDSYSTEM_SONGS; i++) {
openal.chan_song[i].set_no_virtualization();
}
openal.chan_mp3.set_no_virtualization();
openal.chan_trig_music.set_no_virtualization();
openal.chan_movie.set_no_virtualization();
Cmd_AddCommand("playmp3", S_OPENAL_PlayMP3);
Cmd_AddCommand("stopmp3", S_OPENAL_StopMP3);
Cmd_AddCommand("loadsoundtrack", S_loadsoundtrack);
@@ -827,7 +846,8 @@ void S_DumpInfo()
S_DumpStatus(
"Misc",
i,
openal.channel[MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D + MAX_SOUNDSYSTEM_CHANNELS_2D_STREAM + i]
openal.channel
[MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D + MAX_SOUNDSYSTEM_CHANNELS_2D_STREAM + i]
);
}
}
@@ -1357,16 +1377,15 @@ static void S_OPENAL_Start2DSound(
pChannel->iBaseRate = pChannel->sample_playback_rate();
pChannel->set_no_3d();
fRealVolume = fRealVolume * s_fVolumeGain;
pChannel->set_gain(fRealVolume);
pChannel->play();
} else {
pChannel->stop();
pChannel->set_no_3d();
pChannel->set_sfx(pSfx);
pChannel->set_gain(fRealVolume);
pChannel->play();
}
pChannel->set_gain(fRealVolume);
pChannel->play();
if (s_show_sounds->integer > 0) {
Com_DPrintf(
"OpenAL: 2D - %d (#%i) - %s (vol %f, mindist %f, maxdist %f)\n",
@@ -1818,7 +1837,9 @@ static int S_OPENAL_Start2DLoopSound(
pChannel->set_gain(fVolumeToPlay);
pChannel->start_sample();
if (s_show_sounds->integer > 0) {
Com_DPrintf("OpenAL: %d (#%i) - %s (vol %f)\n", cl.serverTime, pLoopSound->iChannel, pLoopSound->pSfx->name, fVolume);
Com_DPrintf(
"OpenAL: %d (#%i) - %s (vol %f)\n", cl.serverTime, pLoopSound->iChannel, pLoopSound->pSfx->name, fVolume
);
}
return iChannel;
@@ -2138,7 +2159,9 @@ void S_OPENAL_AddLoopSounds(const vec3_t vTempAxis)
}
if (s_show_sounds->integer > 0) {
Com_DPrintf("OpenAL: %d (#%i) - started loop - %s\n", cl.serverTime, pLoopSound->iChannel, pLoopSound->pSfx->name);
Com_DPrintf(
"OpenAL: %d (#%i) - started loop - %s\n", cl.serverTime, pLoopSound->iChannel, pLoopSound->pSfx->name
);
}
if (pLoopSound->pSfx->iFlags & (SFX_FLAG_NO_OFFSET)
@@ -2389,7 +2412,10 @@ S_OPENAL_reverb
*/
static void S_OPENAL_reverb(int iChannel, int iReverbType, float fReverbLevel)
{
// No reverb.
// FIXME: Connect source to effect slot
// see https://github.com/kcat/openal-soft/blob/master/examples/alreverb.c
// No reverb currently.
}
/*
@@ -2404,6 +2430,10 @@ void S_OPENAL_SetReverb(int iType, float fLevel)
if (al_use_reverb) {
s_bReverbChanged = true;
}
// FIXME: generate effect and auxiliary effect slot
// or destroy them
// see https://github.com/kcat/openal-soft/blob/master/examples/alreverb.c
}
/*
@@ -2475,7 +2505,16 @@ void S_OPENAL_Update()
if (s_reverb->modified) {
s_reverb->modified = false;
Com_Printf("FIXME: Allow reverb toggle at runtime in OpenAL code.\n");
if (s_reverb->integer) {
if (al_use_reverb) {
S_OPENAL_SetReverb(s_iReverbType, s_fReverbLevel);
} else {
Com_Printf("OpenAL: No reverb support. Reverb is disabled.\n");
}
} else if (al_use_reverb) {
S_OPENAL_SetReverb(0, 0);
}
}
if (s_show_num_active_sounds->integer == 1) {
@@ -2883,6 +2922,35 @@ void openal_channel::play()
alDieIfError();
}
/*
==============
openal_channel::set_no_virtualization
==============
*/
void openal_channel::set_no_virtualization()
{
#if AL_SOFT_direct_channels_remix
qalSourcei(source, AL_DIRECT_CHANNELS_SOFT, AL_REMIX_UNMATCHED_SOFT);
alDieIfError();
#elif AL_SOFT_direct_channels
qalSourcei(source, AL_DIRECT_CHANNELS_SOFT, AL_TRUE);
alDieIfError();
#endif
}
/*
==============
openal_channel::set_virtualization
==============
*/
void openal_channel::set_virtualization()
{
#if AL_SOFT_direct_channels_remix || AL_SOFT_direct_channels
qalSourcei(source, AL_DIRECT_CHANNELS_SOFT, AL_FALSE);
alDieIfError();
#endif
}
/*
==============
openal_channel::pause
@@ -2991,9 +3059,21 @@ bool openal_channel::set_sfx(sfx_t *pSfx)
return false;
}
if (pSfx->info.dataalign > 1 && !soft_block_align) {
Com_DPrintf(
"OpenAL: Alignment specified but AL doesn't support block alignment (%d).", pSfx->info.dataalign
);
return false;
}
qalGenBuffers(1, &pSfx->buffer);
alDieIfError();
if (pSfx->info.dataalign > 1) {
qalBufferi(pSfx->buffer, AL_UNPACK_BLOCK_ALIGNMENT_SOFT, pSfx->info.dataalign);
alDieIfError();
}
qalBufferData(
pSfx->buffer,
fmt,
@@ -4216,7 +4296,7 @@ int S_CurrentMoviePosition()
S_AL_Format
=================
*/
static ALuint S_OPENAL_Format(int width, int channels)
static ALuint S_OPENAL_Format(float width, int channels)
{
ALuint format = AL_FORMAT_MONO16;
@@ -4233,6 +4313,17 @@ static ALuint S_OPENAL_Format(int width, int channels)
} else if (channels == 2) {
format = AL_FORMAT_STEREO16;
}
} else if (width == 0.5) {
if (ima4_ext && soft_block_align) {
if (channels == 1) {
format = AL_FORMAT_MONO_IMA4;
} else if (channels == 2) {
format = AL_FORMAT_STEREO_IMA4;
}
} else {
// unsupported
format = 0;
}
}
return format;
@@ -4360,6 +4451,11 @@ bool openal_channel_two_d_stream::set_sfx(sfx_t *pSfx)
return true;
}
if (stream->info.dataalign > 1 && soft_block_align) {
qalBufferi(buffers[currentBuf], AL_UNPACK_BLOCK_ALIGNMENT_SOFT, stream->info.dataalign);
alDieIfError();
}
qalBufferData(buffers[currentBuf], pSfx->info.format, rawData, bytesRead, stream->info.rate);
alDieIfError();
@@ -4499,6 +4595,11 @@ void openal_channel_two_d_stream::update()
}
}
if (stream->info.dataalign > 1 && soft_block_align) {
qalBufferi(buffers[currentBuf], AL_UNPACK_BLOCK_ALIGNMENT_SOFT, stream->info.dataalign);
alDieIfError();
}
qalBufferData(buffers[currentBuf], format, rawData, bytesRead, stream->info.rate);
alDieIfError();
@@ -4527,7 +4628,7 @@ U32 openal_channel_two_d_stream::sample_offset()
ALint numProcessedBuffers = 0;
ALint numQueuedBuffers = 0;
unsigned int totalQueueLength = 0;
unsigned int bytesPerSample = 0;
unsigned int bitsPerSample = 0;
unsigned int offset = 0;
ALint bits = 0, channels = 0;
@@ -4541,7 +4642,7 @@ U32 openal_channel_two_d_stream::sample_offset()
alDieIfError();
totalQueueLength = getQueueLength();
bytesPerSample = getBytesPerSample();
bitsPerSample = getBitsPerSample();
assert(playerByteOffset < totalQueueLength);
assert(streamNextOffset >= totalQueueLength || stream);
@@ -4569,7 +4670,7 @@ U32 openal_channel_two_d_stream::sample_offset()
offset = totalQueueLength - streamNextOffset + playerByteOffset;
}
return offset / bytesPerSample;
return offset * 8 / bitsPerSample;
}
/*
@@ -4599,7 +4700,7 @@ void openal_channel_two_d_stream::set_sample_offset(U32 offset)
snd_stream_t *stream;
unsigned int bytesToRead, bytesRead;
unsigned int byteOffset;
unsigned int bytesPerSample;
unsigned int bitsPerSample;
unsigned int streamPosition;
ALuint format;
ALint numQueuedBuffers;
@@ -4612,8 +4713,8 @@ void openal_channel_two_d_stream::set_sample_offset(U32 offset)
stream = (snd_stream_t *)streamHandle;
streamPosition = getCurrentStreamPosition();
bytesPerSample = getBytesPerSample();
byteOffset = offset * bytesPerSample;
bitsPerSample = getBitsPerSample();
byteOffset = offset * bitsPerSample / 8;
if (byteOffset >= streamPosition && byteOffset < streamNextOffset) {
//
@@ -4863,13 +4964,13 @@ unsigned int openal_channel_two_d_stream::getCurrentStreamPosition() const
/*
==============
openal_channel_two_d_stream::getBytesPerSample
openal_channel_two_d_stream::getBitsPerSample
Return the number of bytes per sample.
It assumes that all pending buffers have the same channels and bits.
==============
*/
unsigned int openal_channel_two_d_stream::getBytesPerSample() const
unsigned int openal_channel_two_d_stream::getBitsPerSample() const
{
unsigned int bufferId;
ALint bits = 0, channels = 0;
@@ -4880,5 +4981,5 @@ unsigned int openal_channel_two_d_stream::getBytesPerSample() const
qalGetBufferi(buffers[bufferId], AL_CHANNELS, &channels);
alDieIfError();
return bits * channels / 8;
return bits * channels;
}
+3 -1
View File
@@ -95,6 +95,8 @@ public:
void set_no_3d();
void set_3d();
void set_no_virtualization();
void set_virtualization();
void set_gain(float gain);
void set_velocity(float v0, float v1, float v2);
@@ -165,7 +167,7 @@ private:
unsigned int getQueueLength() const;
unsigned int getCurrentStreamPosition() const;
unsigned int getBytesPerSample() const;
unsigned int getBitsPerSample() const;
};
struct openal_movie_channel : public openal_channel {
+1 -1
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.5)
cmake_minimum_required(VERSION 3.12)
project(fgame)
# Shared source files for modules
+8 -3
View File
@@ -71,9 +71,14 @@ void cVehicleSlot::NotSolid(void)
}
}
if (!ent->IsSubclassOfPlayer()) {
ent->setSolidType(SOLID_NOT);
}
// Added in 2.0
// Commented in OPM
// Not sure why since 2.0, players aren't made non-solid in slots
//if (!ent->IsSubclassOfPlayer()) {
// ent->setSolidType(SOLID_NOT);
//}
ent->setSolidType(SOLID_NOT);
}
void cVehicleSlot::Solid(void)
+3 -2
View File
@@ -2993,6 +2993,7 @@ Actor::Actor()
// The variable isn't set in original
//
m_bSilent = false;
m_bMumble = true;
}
/*
@@ -8389,7 +8390,7 @@ bool Actor::AttackEntryAnimation(void)
m_bNewEnemy = true;
return true;
}
} else if (fDistSquared > Square(1024)) {
} else if (fDistSquared > Square(1024) && (rand() % 4) == 0) {
Sentient *pSquadMate;
for (pSquadMate = m_pNextSquadMate; pSquadMate != this; pSquadMate = pSquadMate->m_pNextSquadMate) {
@@ -8701,7 +8702,7 @@ void Actor::FaceEnemyOrMotion(int iTimeIntoMove)
{
vec2_t vDelta;
VectorCopy2D(origin, vDelta);
VectorSub2D(origin, m_vLastEnemyPos, vDelta);
if (iTimeIntoMove <= 999) {
m_bFaceEnemy = true;
+10
View File
@@ -717,6 +717,16 @@ static void PM_NoclipMove(void)
// move
VectorMA(pm->ps->origin, pml.frametime, pm->ps->velocity, pm->ps->origin);
// Added in 2.0
// If the player is out of bounds in noclip mode,
// teleport it back to the (0,0,0) coordinates
for (i = 0; i < 3; i++) {
if (fabs(pm->ps->origin[i]) >= MAX_MAP_BOUNDS - 512) {
VectorClear(pm->ps->origin);
break;
}
}
}
//============================================================================
+1 -1
View File
@@ -652,7 +652,7 @@ movement on the server game.
#define MASK_CAMERASOLID (CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_BODY | MASK_WATER)
#define MASK_BEAM (CONTENTS_SOLID | CONTENTS_TRIGGER | CONTENTS_PLAYERCLIP | CONTENTS_BODY | CONTENTS_FENCE)
#define MASK_LADDER \
(CONTENTS_SOLID | CONTENTS_LADDER | CONTENTS_TRIGGER | CONTENTS_PLAYERCLIP | CONTENTS_BODY | CONTENTS_FENCE)
(CONTENTS_SOLID | CONTENTS_LADDER | CONTENTS_TRIGGER | CONTENTS_PLAYERCLIP | CONTENTS_BODY | CONTENTS_FENCE | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP | CONTENTS_BBOX)
#define MASK_AUTOCALCLIFE (CONTENTS_SOLID | CONTENTS_TRIGGER | CONTENTS_FENCE)
#define MASK_EXPLOSION (CONTENTS_SOLID | CONTENTS_TRIGGER | CONTENTS_WEAPONCLIP)
#define MASK_SOUND (CONTENTS_SOLID | CONTENTS_TRANSLUCENT)
+19 -19
View File
@@ -130,14 +130,14 @@ static PlayerStart *GetRandomSpawnpointFromList(spawnsort_t *pSpots, int nSpots)
}
}
float SpawnpointMetric_Ffa(const float *origin, DM_Team *dmTeam, const Player *player)
float SpawnpointMetric_Ffa(const vec3_t origin, DM_Team *dmTeam, const Player *player)
{
float fMinEnemyDistSquared = 23170.0f * 23170.0f;
float fMinEnemyDistSquared = Square(23170);
int i;
int nPlayers = dmManager.PlayerCount();
float fDist;
for (i = 1; i < nPlayers; i++) {
for (i = 1; i <= nPlayers; i++) {
Player *teammate = dmManager.GetPlayer(i);
if (teammate == player || teammate->IsDead() || teammate->IsSpectator()) {
continue;
@@ -150,12 +150,12 @@ float SpawnpointMetric_Ffa(const float *origin, DM_Team *dmTeam, const Player *p
}
}
return fMinEnemyDistSquared - (G_Random(0.25f) + 1.0f) * (1024.0f * 1024.0f);
return fMinEnemyDistSquared - (G_Random(0.25f) + 1.0f) * Square(1024);
}
float SpawnpointMetric_Team(const float *origin, DM_Team *dmTeam, const Player *player)
float SpawnpointMetric_Team(const vec3_t origin, DM_Team *dmTeam, const Player *player)
{
float fMinEnemyDistSquared = 23170.0f * 23170.0f;
float fMinEnemyDistSquared = Square(23170);
float fSumFriendDistSquared = 0.0f;
float fDistSquared;
float fMetric;
@@ -163,7 +163,7 @@ float SpawnpointMetric_Team(const float *origin, DM_Team *dmTeam, const Player *
int nPlayers = dmManager.PlayerCount();
int nFriends = 0;
for (i = 1; i < nPlayers; i++) {
for (i = 1; i <= nPlayers; i++) {
Player *teammate = dmManager.GetPlayer(i);
if (teammate == player || teammate->IsDead() || teammate->IsSpectator()) {
continue;
@@ -174,14 +174,12 @@ float SpawnpointMetric_Team(const float *origin, DM_Team *dmTeam, const Player *
if (teammate->GetDM_Team() == dmTeam) {
nFriends++;
fSumFriendDistSquared += fDistSquared;
} else {
if (fMinEnemyDistSquared > fDistSquared) {
fMinEnemyDistSquared = fDistSquared;
}
} else if (fMinEnemyDistSquared > fDistSquared) {
fMinEnemyDistSquared = fDistSquared;
}
}
fMetric = fMinEnemyDistSquared - (G_Random(0.25f) + 1.0f) * (1024.0f * 1024.0f);
fMetric = fMinEnemyDistSquared - (G_Random(0.25f) + 1.0f) * Square(1024);
if (nFriends) {
fMetric += 0.25f * ((23170.0f * 23170.0f) - fSumFriendDistSquared / nFriends);
@@ -190,9 +188,9 @@ float SpawnpointMetric_Team(const float *origin, DM_Team *dmTeam, const Player *
return fMetric;
}
float SpawnpointMetric_Objective(const float *origin, DM_Team *dmTeam, const Player *player)
float SpawnpointMetric_Objective(const vec3_t origin, DM_Team *dmTeam, const Player *player)
{
return rand() * 0.0000000005f;
return rand() / (float)RAND_MAX;
}
CLASS_DECLARATION(Listener, DM_Team, NULL) {
@@ -459,12 +457,12 @@ PlayerStart *DM_Team::GetRandomSpawnpointWithMetric(
vNewSpawn, player->mins, player->maxs, vEnd, player, MASK_PLAYERSOLID, qfalse, "TempSpawnPoint"
);
if (!trace.allsolid && !trace.startsolid && trace.fraction != 1.0f && trace.fraction != 1.0f
&& trace.plane.dist >= 0.8f) {
if (!trace.allsolid && !trace.startsolid && trace.fraction != 1.0f && trace.plane.dist >= 0.8f) {
points[numSpots].spawnpoint = new PlayerStart;
points[numSpots].spawnpoint->setOrigin(trace.endpos);
points[numSpots].spawnpoint->setAngles(spot->angles);
points[numSpots].fMetric = MetricFunction(vNewSpawn, this, player);
numSpots++;
if (numSpots >= (sizeof(points) / sizeof(points[0]))) {
break;
@@ -497,6 +495,7 @@ PlayerStart *DM_Team::GetRandomSpawnpointWithMetric(
if (!SpotWouldTelefrag(spot->origin)) {
points[numSpots].spawnpoint = spot;
points[numSpots].fMetric = MetricFunction(spot->origin, this, player);
numSpots++;
if (numSpots >= (sizeof(points) / sizeof(points[0]))) {
break;
@@ -677,6 +676,7 @@ DM_Manager::DM_Manager()
m_bAllowAxisRespawn = true;
m_bAllowAlliedRespawn = true;
m_bRoundActive = false;
m_iTotalMapTime = 0;
}
DM_Manager::~DM_Manager() {}
@@ -1245,7 +1245,7 @@ bool DM_Manager::CheckEndMatch()
if (AllowRespawn() || (!m_team_axis.IsDead() && !m_team_allies.IsDead())) {
int roundLimit = GetRoundLimit();
if (roundLimit > 0 && level.time >= m_iDefaultRoundLimit * 60 + m_fRoundTime) {
if (roundLimit > 0 && level.time >= roundLimit * 60 + m_fRoundTime) {
if (m_csTeamBombPlantSide != STRING_DRAW) {
if (m_bIgnoringClockForBomb) {
if (m_iNumBombsPlanted > 0) {
@@ -1254,7 +1254,7 @@ bool DM_Manager::CheckEndMatch()
m_bIgnoringClockForBomb = false;
} else if (m_iNumBombsPlanted > 0) {
G_PrintToAllClients("A bomb is still set!");
G_PrintToAllClients(va("%s\n", gi.LV_ConvertString("A Bomb is Still Set!")));
m_bIgnoringClockForBomb = true;
return false;
}
@@ -1328,7 +1328,7 @@ bool DM_Manager::CheckEndMatch()
return true;
} else if (m_iNumBombsPlanted >= m_iNumTargetsToDestroy - m_iNumTargetsDestroyed) {
if (!m_bIgnoringClockForBomb) {
G_PrintToAllClients("A bomb is still set!");
G_PrintToAllClients(va("%s\n", gi.LV_ConvertString("A Bomb is Still Set!")));
m_bIgnoringClockForBomb = true;
}
} else {
+13
View File
@@ -847,7 +847,20 @@ void Door::DoorBlocked(Event *ev)
if (state == STATE_OPENING || state == STATE_OPEN) {
spawnflags &= ~DOOR_START_OPEN;
const bool bIsMoving = EventPending(EV_MoveDone);
ProcessEvent(EV_Door_Close);
if (bIsMoving) {
// Added in OPM
// Reopen to the other side so sentients can still pass.
// This avoid entities like players trying to prevent the door
// from opening in multiplayer
diropened = -diropened;
e = new Event(EV_Door_Open);
e->AddEntity(other);
ProcessEvent(e);
}
} else {
e = new Event(EV_Door_Open);
e->AddEntity(other);
+8 -2
View File
@@ -2996,7 +2996,6 @@ void Entity::FadeIn(Event *ev)
if (ev->NumArgs() > 0) {
rate = ev->GetFloat(1);
assert(rate);
if (rate > 0) {
rate = FRAMETIME / rate;
}
@@ -3032,7 +3031,6 @@ void Entity::Fade(Event *ev)
if (ev->NumArgs() > 0) {
rate = ev->GetFloat(1);
assert(rate);
if (rate > 0) {
rate = FRAMETIME / rate;
}
@@ -5721,6 +5719,14 @@ void Entity::Delete(void)
// Delete the entity the next frame
if (g_iInThinks) {
if (ProcessingEvents) {
// Fixed in OPM
// Add a slight delay because otherwise this would cause an infinite loop
// when processing pending events
PostEvent(EV_Remove, 0.001);
return;
}
PostEvent(EV_Remove, 0);
} else {
delete this;
+36 -12
View File
@@ -43,7 +43,7 @@ Return whether or not the specified filename is for allies
*/
bool IsAlliedPlayerModel(const char *filename)
{
return !Q_stricmpn(filename, "/allied_", 8) || !Q_stricmpn(filename, "/american_", 10);
return !Q_stricmpn(filename, "allied_", 7) || !Q_stricmpn(filename, "american_", 9);
}
/*
@@ -55,7 +55,7 @@ Return whether or not the specified filename is for axis
*/
bool IsGermanPlayerModel(const char *filename)
{
return !Q_stricmpn(filename, "/german_", 8) || !Q_stricmpn(filename, "/IT_", 4) || !Q_stricmpn(filename, "/SC_", 4);
return !Q_stricmpn(filename, "german_", 7) || !Q_stricmpn(filename, "IT_", 3) || !Q_stricmpn(filename, "SC_", 3);
}
/*
@@ -140,9 +140,9 @@ void InitModelList()
}
if (IsAlliedPlayerModel(filename)) {
alliedModelList.AddObject(str(filename + 1, 0, len - 5));
alliedModelList.AddObject(str(filename, 0, len - 4));
} else {
germanModelList.AddObject(str(filename + 1, 0, len - 5));
germanModelList.AddObject(str(filename, 0, len - 4));
}
}
@@ -383,6 +383,36 @@ bool G_IsPlayer(gentity_t *ent)
return true;
}
/*
===========
G_GetRandomAlliedPlayerModel
============
*/
const char* G_GetRandomAlliedPlayerModel()
{
if (!alliedModelList.NumObjects()) {
return "";
}
const unsigned int index = rand() % alliedModelList.NumObjects();
return alliedModelList[index];
}
/*
===========
G_GetRandomGermanPlayerModel
============
*/
const char* G_GetRandomGermanPlayerModel()
{
if (!germanModelList.NumObjects()) {
return "";
}
const unsigned int index = rand() % germanModelList.NumObjects();
return germanModelList[index];
}
/*
===========
G_AddBot
@@ -429,14 +459,8 @@ void G_AddBot(const saved_bot_t *saved)
//
// Choose a random model
//
if (alliedModelList.NumObjects()) {
const unsigned int index = rand() % alliedModelList.NumObjects();
Info_SetValueForKey(userinfo, "dm_playermodel", alliedModelList[index]);
}
if (germanModelList.NumObjects()) {
const unsigned int index = rand() % germanModelList.NumObjects();
Info_SetValueForKey(userinfo, "dm_playergermanmodel", germanModelList[index]);
}
Info_SetValueForKey(userinfo, "dm_playermodel", G_GetRandomAlliedPlayerModel());
Info_SetValueForKey(userinfo, "dm_playergermanmodel", G_GetRandomGermanPlayerModel());
Info_SetValueForKey(userinfo, "fov", "80");
Info_SetValueForKey(userinfo, "ip", "localhost");
+3 -1
View File
@@ -40,4 +40,6 @@ void G_ResetBots();
void G_BotInit();
void G_BotFrame();
void G_BotPostInit();
void G_SpawnBots();
void G_SpawnBots();
const char* G_GetRandomAlliedPlayerModel();
const char* G_GetRandomGermanPlayerModel();
+2 -2
View File
@@ -772,7 +772,7 @@ void G_ClientUserinfoChanged(gentity_t *ent, const char *u)
clientnum = ent - g_entities;
if (gi.SanitizeName(s, client->pers.netname)) {
if (gi.SanitizeName(s, client->pers.netname, sizeof(client->pers.netname))) {
gi.Printf("WARNING: had to sanitize the name for client %i\n", clientnum);
}
@@ -794,7 +794,7 @@ void G_ClientUserinfoChanged(gentity_t *ent, const char *u)
Q_strncpyz(client->pers.dm_playergermanmodel, s, sizeof(client->pers.dm_playergermanmodel));
gi.setConfigstring(CS_PLAYERS + clientnum, va("name\\%s", client->pers.netname));
G_SetClientConfigString(ent);
if (ent->entity) {
float fov;
+14 -16
View File
@@ -1881,8 +1881,8 @@ void G_ExitLevel(void)
// The nextmap cvar was set (possibly by a vote - so go ahead and use it)
level.nextmap = sv_nextmap->string;
gi.cvar_set("nextmap", "");
} else // Use the next map in the maplist
{
} else {
// Use the next map in the maplist
char *s, *f, *t;
f = NULL;
@@ -1892,19 +1892,17 @@ void G_ExitLevel(void)
if (!Q_stricmp(t, level.mapname.c_str())) {
// it's in the list, go to the next one
t = strtok(NULL, seps);
if (t == NULL) // end of list, go to first one
{
if (f == NULL) // there isn't a first one, same level
{
level.nextmap = level.mapname;
} else {
level.nextmap = f;
}
} else {
if (t) {
level.nextmap = t;
} else if (f) {
// end of list, go to first one
level.nextmap = f;
} else {
// there isn't a first one, same level
level.nextmap = level.mapname;
}
free(s);
goto out;
break;
}
// set the first map
@@ -1915,7 +1913,7 @@ void G_ExitLevel(void)
}
free(s);
}
out:
// level.nextmap should be set now, but if it isn't use the same map
if (level.nextmap.length() == 0) {
// Stay on the same map since no nextmap was set
@@ -1929,8 +1927,8 @@ void G_ExitLevel(void)
// alias on another map
Q_strncpyz(command, level.nextmap, sizeof(command));
gi.SendConsoleCommand(command);
} else // use the level.nextmap variable
{
} else {
// use the level.nextmap variable
Com_sprintf(command, sizeof(command), "gamemap \"%s\"\n", level.nextmap.c_str());
gi.SendConsoleCommand(command);
}
+918 -1167
View File
File diff suppressed because it is too large. Load diff
+37 -40
View File
@@ -29,52 +29,49 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
class Entity;
typedef enum
{
STEPMOVE_OK,
STEPMOVE_BLOCKED_BY_ENTITY,
STEPMOVE_BLOCKED_BY_WORLD,
STEPMOVE_BLOCKED_BY_WATER,
STEPMOVE_BLOCKED_BY_FALL,
STEPMOVE_BLOCKED_BY_DOOR,
STEPMOVE_STUCK
typedef enum {
STEPMOVE_OK,
STEPMOVE_BLOCKED_BY_ENTITY,
STEPMOVE_BLOCKED_BY_WORLD,
STEPMOVE_BLOCKED_BY_WATER,
STEPMOVE_BLOCKED_BY_FALL,
STEPMOVE_BLOCKED_BY_DOOR,
STEPMOVE_STUCK
} stepmoveresult_t;
// movetype values
typedef enum
{
MOVETYPE_NONE, // never moves
MOVETYPE_STATIONARY, // never moves but does collide agains push objects
MOVETYPE_NOCLIP, // origin and angles change with no interaction
MOVETYPE_PUSH, // no clip to world, push on box contact
MOVETYPE_STOP, // no clip to world, stops on box contact
MOVETYPE_WALK, // gravity
MOVETYPE_FLY,
MOVETYPE_TOSS, // gravity
MOVETYPE_FLYMISSILE, // extra size to monsters
MOVETYPE_BOUNCE,
MOVETYPE_SLIDE,
MOVETYPE_GIB,
MOVETYPE_VEHICLE,
MOVETYPE_TURRET,
MOVETYPE_PORTABLE_TURRET
typedef enum {
MOVETYPE_NONE, // never moves
MOVETYPE_STATIONARY, // never moves but does collide agains push objects
MOVETYPE_NOCLIP, // origin and angles change with no interaction
MOVETYPE_PUSH, // no clip to world, push on box contact
MOVETYPE_STOP, // no clip to world, stops on box contact
MOVETYPE_WALK, // gravity
MOVETYPE_FLY,
MOVETYPE_TOSS, // gravity
MOVETYPE_FLYMISSILE, // extra size to monsters
MOVETYPE_BOUNCE,
MOVETYPE_SLIDE,
MOVETYPE_GIB,
MOVETYPE_VEHICLE,
MOVETYPE_TURRET,
MOVETYPE_PORTABLE_TURRET
} movetype_t;
typedef struct
{
Entity *ent;
Vector localorigin;
Vector origin;
Vector localangles;
Vector angles;
float deltayaw;
typedef struct {
Entity *ent;
Vector localorigin;
Vector origin;
Vector localangles;
Vector angles;
float deltayaw;
} pushed_t;
extern pushed_t pushed[];
extern pushed_t pushed[];
extern pushed_t *pushed_p;
void G_RunEntity( Entity *ent );
void G_Impact( Entity *e1, trace_t *trace );
qboolean G_PushMove( Entity *pusher, Vector move, Vector amove );
void G_CheckWater( Entity *ent );
Entity *G_TestEntityPosition( Entity *ent, Vector vOrg );
void G_RunEntity(Entity *ent);
void G_Impact(Entity *e1, trace_t *trace);
qboolean G_PushMove(Entity *pusher, Vector move, Vector amove);
void G_CheckWater(Entity *ent);
Entity *G_TestEntityPosition(Entity *ent, Vector vOrg);
+1 -1
View File
@@ -478,7 +478,7 @@ typedef struct gameImport_s {
void (*HudDrawAlpha)(int info, float alpha);
void (*HudDrawString)(int info, const char *string);
void (*HudDrawFont)(int info, const char *fontName);
qboolean (*SanitizeName)(const char *oldName, char *newName);
qboolean (*SanitizeName)(const char *oldName, char *newName, size_t bufferSize);
//
// Added in OPM
+7
View File
@@ -87,6 +87,13 @@ Called on a first-time connect
*/
void G_InitClientPersistant( gclient_t *client, const char *userinfo )
{
// Clear the persistent data
client->pers = {};
// Added in OPM
// Reset the persistent session data.
// This fixes some bugs like the player getting score
// from previous maps
G_WriteClientSessionData( client );
}
+13 -6
View File
@@ -924,10 +924,10 @@ float G_GetAngle(Vector movedir)
angle = RAD2DEG(atan(1.0) * 2 + atan(-movedir[0] / sqrt(-movedir[0] * movedir[0] + 1.0)));
if (movedir[1] < 0) {
return 360 - angle;
return (int)((360 - angle) * 10000) / 10000.0;
}
return angle;
return (int)(angle * 10000) / 10000.0;
}
/*
@@ -2171,9 +2171,9 @@ void G_PrintToAllClients(const char *pszString, int iType)
}
} else {
if (iType == 0) {
gi.SendServerCommand(-1, "print \"" HUD_MESSAGE_YELLOW "%s\n\"", pszString);
gi.SendServerCommand(-1, "print \"" HUD_MESSAGE_YELLOW "%s\"", pszString);
} else {
gi.SendServerCommand(-1, "print \"" HUD_MESSAGE_WHITE "%s\n\"", pszString);
gi.SendServerCommand(-1, "print \"" HUD_MESSAGE_WHITE "%s\"", pszString);
}
}
}
@@ -2232,9 +2232,12 @@ G_PrintDeathMessageEmulated(const char *s1, const char *s2, char *attackerName,
result2 = NULL;
if (type == tolower(type)) {
// Enemy
hudColor = 4;
} else {
hudColor = 5;
// Friend
//hudColor = 5;
hudColor = 4;
}
if (*s1 != 'x') {
@@ -2327,7 +2330,7 @@ void G_PrintDeathMessage_Old(const char *pszString)
continue;
}
gi.SendServerCommand(ent - g_entities, "print \"" HUD_MESSAGE_CHAT_RED "%s\"", pszString);
gi.SendServerCommand(ent - g_entities, "print \"%s\"", pszString);
}
}
@@ -2449,3 +2452,7 @@ gentity_t *G_GetGEntity(int ent_num)
return ent;
}
unsigned int G_GetWeaponCommand(unsigned int buttons) {
return GetWeaponCommand(buttons, g_protocol >= PROTOCOL_MOHTA_MIN ? WEAPON_COMMAND_MAX_VER17 : WEAPON_COMMAND_MAX_VER6);
}
+1
View File
@@ -327,3 +327,4 @@ const char *WeaponHandNumToName(weaponhand_t hand);
weaponhand_t WeaponHandNameToNum(str side);
void G_DebugTargets(Entity *e, str from);
void G_DebugDamage(float damage, Entity *victim, Entity *attacker, Entity *inflictor);
unsigned int G_GetWeaponCommand(unsigned int buttons);
+4 -8
View File
@@ -418,15 +418,11 @@ void Item::RemoveFromOwner(void)
void Item::Delete(void)
{
if (g_iInThinks) {
if (owner) {
RemoveFromOwner();
}
PostEvent(EV_Remove, 0);
} else {
delete this;
if (g_iInThinks && owner) {
RemoveFromOwner();
}
Animate::Delete();
}
void Item::SetNoRemove(Event *ev)
+8 -2
View File
@@ -969,8 +969,8 @@ void Level::CleanUp(qboolean samemap, qboolean resetConfigStrings)
gi.setConfigstring(CS_RAIN_NUMSHADERS, "0");
gi.setConfigstring(CS_CURRENT_OBJECTIVE, "");
for (int i = CS_OBJECTIVES; i < CS_OBJECTIVES + MAX_OBJECTIVES; i++) {
gi.setConfigstring(i, "");
for (i = 0; i < MAX_OBJECTIVES; i++) {
gi.setConfigstring(CS_OBJECTIVES + i, "");
}
gi.setConfigstring(CS_VOTE_TIME, "");
@@ -1097,6 +1097,12 @@ void Level::SpawnEntities(char *entities, int svsTime)
int start, end;
char name[128];
if (gi.Cvar_Get("g_invulnoverride", "0", 0)->integer == 1) {
// Added in 2.30
// Clear the invulnerable override when loading
gi.cvar_set("g_invulnoverride", "0");
}
Com_Printf("-------------------- Spawning Entities -----------------------\n");
t1 = gi.Milliseconds();
+1 -1
View File
@@ -3094,7 +3094,7 @@ void FuncLadder::AdjustPositionOnLadder(Entity *pUser)
);
}
pUser->setOrigin(trace.endpos + m_vFacingDir * 0.005);
pUser->setOrigin(trace.endpos);
}
void FuncLadder::EnsureOverLadder(Entity *pUser)
+156 -190
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2024 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -35,93 +35,81 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define MOVE_ANGLES 1
#define MOVE_ORIGIN 2
CLASS_DECLARATION( Trigger, Mover, "mover" )
{
{ &EV_MoveDone, &Mover::MoveDone },
{ NULL, NULL }
};
CLASS_DECLARATION(Trigger, Mover, "mover") {
{&EV_MoveDone, &Mover::MoveDone},
{NULL, NULL }
};
Mover::Mover()
{
endevent = NULL;
}
Mover::~Mover()
{
}
void Mover::MoveDone
(
Event *ev
)
{
Event * event;
Vector move;
Vector amove;
endevent = NULL;
}
// zero out the movement
Mover::~Mover() {}
void Mover::MoveDone(Event *ev)
{
Event *event;
Vector move;
Vector amove;
// zero out the movement
avelocity = vec_zero;
if( moveflags & MOVE_ANGLES )
{
amove = angledest - localangles;
}
else
{
amove = vec_zero;
}
if (moveflags & MOVE_ANGLES) {
amove = angledest - localangles;
} else {
amove = vec_zero;
}
velocity = vec_zero;
if( moveflags & MOVE_ORIGIN )
{
move = finaldest - localorigin;
}
else
{
move = vec_zero;
}
if (moveflags & MOVE_ORIGIN) {
move = finaldest - localorigin;
} else {
move = vec_zero;
}
accel = vec_zero;
accel = vec_zero;
aaccel = vec_zero;
if( !G_PushMove( this, move, amove ) )
{
// Delay finish till we can move into the final position
PostEvent( EV_MoveDone, FRAMETIME );
return;
}
if (!G_PushMove(this, move, amove)) {
// Added in OPM
// Check to make sure the event isn't pending
// blocked events called by G_PushMove() might alter
// the mover
if (!EventPending(EV_MoveDone)) {
// Delay finish till we can move into the final position
PostEvent(EV_MoveDone, FRAMETIME);
}
return;
}
//
// After moving, set origin to exact final destination
//
if( moveflags & MOVE_ORIGIN )
{
setLocalOrigin( finaldest );
}
//
// After moving, set origin to exact final destination
//
if (moveflags & MOVE_ORIGIN) {
setLocalOrigin(finaldest);
}
if( moveflags & MOVE_ANGLES )
{
localangles = angledest;
if (moveflags & MOVE_ANGLES) {
localangles = angledest;
if( ( localangles.x >= 360 ) || ( localangles.x < 0 ) )
{
localangles.x -= ( ( int )localangles.x / 360 ) * 360;
}
if( ( localangles.y >= 360 ) || ( localangles.y < 0 ) )
{
localangles.y -= ( ( int )localangles.y / 360 ) * 360;
}
if( ( localangles.z >= 360 ) || ( localangles.z < 0 ) )
{
localangles.z -= ( ( int )localangles.z / 360 ) * 360;
}
}
if ((localangles.x >= 360) || (localangles.x < 0)) {
localangles.x -= ((int)localangles.x / 360) * 360;
}
if ((localangles.y >= 360) || (localangles.y < 0)) {
localangles.y -= ((int)localangles.y / 360) * 360;
}
if ((localangles.z >= 360) || (localangles.z < 0)) {
localangles.z -= ((int)localangles.z / 360) * 360;
}
}
event = endevent;
endevent = NULL;
event = endevent;
endevent = NULL;
if( event )
ProcessEvent( event );
if (event) {
ProcessEvent(event);
}
}
/*
@@ -132,99 +120,87 @@ calculate self.velocity and self.nextthink to reach dest from
self.origin traveling at speed
===============
*/
void Mover::MoveTo( Vector tdest, Vector angdest, float tspeed, Event& event )
void Mover::MoveTo(Vector tdest, Vector angdest, float tspeed, Event& event)
{
Vector vdestdelta;
Vector angdestdelta;
float len;
float traveltime;
Vector vdestdelta;
Vector angdestdelta;
float len;
float traveltime;
assert( tspeed >= 0.0f );
assert(tspeed >= 0.0f);
if( !tspeed )
{
error( "MoveTo", "No speed is defined!" );
}
if (!tspeed) {
error("MoveTo", "No speed is defined!");
}
if( tspeed < 0.0f )
{
error( "MoveTo", "Speed is negative!" );
}
if (tspeed < 0.0f) {
error("MoveTo", "Speed is negative!");
}
// Cancel previous moves
CancelEventsOfType( EV_MoveDone );
// Cancel previous moves
CancelEventsOfType(EV_MoveDone);
moveflags = 0;
moveflags = 0;
if( endevent )
{
delete endevent;
}
if (endevent) {
delete endevent;
}
endevent = new Event( event );
endevent = new Event(event);
finaldest = tdest;
angledest = angdest;
finaldest = tdest;
angledest = angdest;
if( finaldest != localorigin )
{
moveflags |= MOVE_ORIGIN;
}
if( angledest != localangles )
{
moveflags |= MOVE_ANGLES;
}
if (finaldest != localorigin) {
moveflags |= MOVE_ORIGIN;
}
if (angledest != localangles) {
moveflags |= MOVE_ANGLES;
}
if( !moveflags )
{
// stop the object from moving
velocity = vec_zero;
avelocity = vec_zero;
if (!moveflags) {
// stop the object from moving
velocity = vec_zero;
avelocity = vec_zero;
// post the event so we don't wait forever
PostEvent( EV_MoveDone, FRAMETIME );
return;
}
// post the event so we don't wait forever
PostEvent(EV_MoveDone, FRAMETIME);
return;
}
// set destdelta to the vector needed to move
vdestdelta = tdest - localorigin;
angdestdelta[ 0 ] = angledist( angdest[ 0 ] - localangles[ 0 ] );
angdestdelta[ 1 ] = angledist( angdest[ 1 ] - localangles[ 1 ] );
angdestdelta[ 2 ] = angledist( angdest[ 2 ] - localangles[ 2 ] );
// set destdelta to the vector needed to move
vdestdelta = tdest - localorigin;
angdestdelta[0] = angledist(angdest[0] - localangles[0]);
angdestdelta[1] = angledist(angdest[1] - localangles[1]);
angdestdelta[2] = angledist(angdest[2] - localangles[2]);
if( tdest == localorigin )
{
// calculate length of vector based on angles
len = angdestdelta.length();
}
else
{
// calculate length of vector based on distance
len = vdestdelta.length();
}
if (tdest == localorigin) {
// calculate length of vector based on angles
len = angdestdelta.length();
} else {
// calculate length of vector based on distance
len = vdestdelta.length();
}
// divide by speed to get time to reach dest
traveltime = len / tspeed;
// divide by speed to get time to reach dest
traveltime = len / tspeed;
if( traveltime < level.frametime )
{
traveltime = level.frametime;
vdestdelta = vec_zero;
angdestdelta = vec_zero;
}
if (traveltime < level.frametime) {
traveltime = level.frametime;
vdestdelta = vec_zero;
angdestdelta = vec_zero;
}
// scale the destdelta vector by the time spent traveling to get velocity
if( moveflags & MOVE_ORIGIN )
{
velocity = vdestdelta * ( 1.0f / traveltime );
}
// scale the destdelta vector by the time spent traveling to get velocity
if (moveflags & MOVE_ORIGIN) {
velocity = vdestdelta * (1.0f / traveltime);
}
if( moveflags & MOVE_ANGLES )
{
avelocity = angdestdelta * ( 1.0f / traveltime );
}
if (moveflags & MOVE_ANGLES) {
avelocity = angdestdelta * (1.0f / traveltime);
}
PostEvent( EV_MoveDone, traveltime );
PostEvent(EV_MoveDone, traveltime);
}
/*
@@ -232,55 +208,45 @@ void Mover::MoveTo( Vector tdest, Vector angdest, float tspeed, Event& event )
LinearInterpolate
===============
*/
void Mover::LinearInterpolate
(
Vector tdest,
Vector angdest,
float time,
Event &event
)
void Mover::LinearInterpolate(Vector tdest, Vector angdest, float time, Event& event)
{
Vector vdestdelta;
Vector angdestdelta;
float t;
Vector vdestdelta;
Vector angdestdelta;
float t;
if( endevent )
{
delete endevent;
}
endevent = new Event( event );
finaldest = tdest;
angledest = angdest;
if (endevent) {
delete endevent;
}
endevent = new Event(event);
finaldest = tdest;
angledest = angdest;
// Cancel previous moves
CancelEventsOfType( EV_MoveDone );
// Cancel previous moves
CancelEventsOfType(EV_MoveDone);
// Quantize to FRAMETIME
if( time < FRAMETIME )
{
time = FRAMETIME;
}
// Quantize to FRAMETIME
if (time < FRAMETIME) {
time = FRAMETIME;
}
moveflags = 0;
t = 1 / time;
// scale the destdelta vector by the time spent traveling to get velocity
if( finaldest != localorigin )
{
vdestdelta = tdest - localorigin;
velocity = vdestdelta * t;
moveflags |= MOVE_ORIGIN;
}
moveflags = 0;
t = 1 / time;
// scale the destdelta vector by the time spent traveling to get velocity
if (finaldest != localorigin) {
vdestdelta = tdest - localorigin;
velocity = vdestdelta * t;
moveflags |= MOVE_ORIGIN;
}
if( angledest != localangles )
{
angdestdelta = angdest - localangles;
avelocity = angdestdelta * t;
moveflags |= MOVE_ANGLES;
}
if (angledest != localangles) {
angdestdelta = angdest - localangles;
avelocity = angdestdelta * t;
moveflags |= MOVE_ANGLES;
}
if( g_bBeforeThinks )
time -= FRAMETIME;
if (g_bBeforeThinks) {
time -= FRAMETIME;
}
PostEvent( EV_MoveDone, time );
PostEvent(EV_MoveDone, time);
}
+24 -27
View File
@@ -24,7 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// Base class for any object that needs to move to specific locations over a
// period of time. This class is kept separate from most entities to keep
// class size down for objects that don't need such behavior.
//
//
#pragma once
@@ -33,33 +33,30 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "trigger.h"
class Mover : public Trigger
{
private:
Vector finaldest;
Vector angledest;
Event *endevent;
int moveflags;
{
private:
Vector finaldest;
Vector angledest;
Event *endevent;
int moveflags;
public:
CLASS_PROTOTYPE( Mover );
public:
CLASS_PROTOTYPE(Mover);
Mover();
virtual ~Mover();
void MoveDone( Event *ev );
void MoveTo( Vector tdest, Vector angdest, float tspeed, Event &event );
void LinearInterpolate( Vector tdest, Vector angdest, float time, Event &event );
void Archive( Archiver &arc ) override;
};
Mover();
virtual ~Mover();
void MoveDone(Event *ev);
void MoveTo(Vector tdest, Vector angdest, float tspeed, Event& event);
void LinearInterpolate(Vector tdest, Vector angdest, float time, Event& event);
void Archive(Archiver& arc) override;
};
inline void Mover::Archive
(
Archiver &arc
)
{
Trigger::Archive( arc );
inline void Mover::Archive(Archiver& arc)
{
Trigger::Archive(arc);
arc.ArchiveVector( &finaldest );
arc.ArchiveVector( &angledest );
arc.ArchiveEventPointer( &endevent );
arc.ArchiveInteger( &moveflags );
}
arc.ArchiveVector(&finaldest);
arc.ArchiveVector(&angledest);
arc.ArchiveEventPointer(&endevent);
arc.ArchiveInteger(&moveflags);
}
+49 -14
View File
@@ -2413,6 +2413,12 @@ void Player::InitHealth(void)
//
m_fHealRate = 0;
edict->s.eFlags &= ~EF_DEAD;
// Fixed in OPM
// This avoid losing weapons when dying and then immediately respawning
CancelEventsOfType(EV_Player_DMDeathDrop);
// And this prevents the player from dying when respawning immediately after getting killed
CancelEventsOfType(EV_Player_Dead);
}
void Player::InitModel(void)
@@ -4057,9 +4063,9 @@ void Player::ClientMove(usercmd_t *ucmd)
// Also use the weapon movement speed
//
if (!IsZoomed()) {
client->ps.speed = (float)client->ps.speed * pWeap->m_fMovementSpeed;
client->ps.speed = (float)client->ps.speed * pWeap->GetMovementSpeed();
} else {
client->ps.speed = (float)client->ps.speed * pWeap->m_fZoomMovement * pWeap->m_fMovementSpeed;
client->ps.speed = (float)client->ps.speed * pWeap->GetZoomMovement();
}
}
}
@@ -4250,7 +4256,7 @@ void Player::ClientInactivityTimer(void)
//
// The player reached maximum team kills
//
G_PrintToAllClients(va("%s %s", client->pers.netname, message.c_str()), qfalse);
G_PrintToAllClients(va("%s %s\n", client->pers.netname, message.c_str()), 2);
if (Q_stricmp(Info_ValueForKey(client->pers.userinfo, "ip"), "localhost")) {
//
@@ -4742,7 +4748,7 @@ void Player::Think(void)
}
} else {
if ((server_new_buttons & BUTTON_USE)) {
SetPlayerSpectateRandom();
SetPlayerSpectate(true);
}
}
@@ -4801,7 +4807,7 @@ void Player::Think(void)
}
if (!IsDead()) {
m_iClientWeaponCommand = (server_new_buttons & WEAPON_COMMAND_MASK) >> 7;
m_iClientWeaponCommand = G_GetWeaponCommand(server_new_buttons);
switch (m_iClientWeaponCommand) {
case 0:
@@ -7279,7 +7285,7 @@ void Player::UpdateStats(void)
trace = G_Trace(m_vViewPos, vec_zero, vec_zero, vEnd, this, MASK_BEAM, qfalse, "infoclientcheck");
if (trace.ent && trace.ent->entity->IsSubclassOfPlayer()) {
if (trace.ent && trace.ent->entity->IsSubclassOfPlayer() && !(trace.ent->r.svFlags & SVF_NOCLIENT)) {
Player *p = static_cast<Player *>(trace.ent->entity);
if (IsSpectator() || p->GetTeam() == GetTeam()) {
@@ -10777,10 +10783,29 @@ void Player::EventDMMessage(Event *ev)
return;
}
//
// Added in OPM
//=============
// Print the dm message to console
sToken = "";
for (i = 2; i <= ev->NumArgs(); i++) {
if (i != 2) {
sToken += " ";
}
sToken += ev->GetString(i);
}
//=============
if (iMode == 0) {
//
// everyone
//
// Added in OPM
gi.Printf("%s (%zu) says to everyone: %s\n", client->pers.netname, edict - g_entities, sToken.c_str());
if (!IsSpectator() || g_spectate_allow_full_chat->integer) {
for (i = 0; i < game.maxclients; i++) {
ent = &g_entities[i];
@@ -10825,6 +10850,10 @@ void Player::EventDMMessage(Event *ev)
//
// team message
//
// Added in OPM
gi.Printf("%s (%zu) says to team: %s\n", client->pers.netname, edict - g_entities, sToken.c_str());
if (IsSpectator()) {
for (i = 0; i < game.maxclients; i++) {
ent = &g_entities[i];
@@ -10884,6 +10913,9 @@ void Player::EventDMMessage(Event *ev)
return;
}
// Added in OPM
gi.Printf("%s (%zu) says to client #%d: %s\n", client->pers.netname, edict - g_entities, iMode - 1, sToken.c_str());
gi.SendServerCommand(iMode - 1, "%s", szPrintString);
if (ent->entity != this) {
@@ -11195,17 +11227,17 @@ str Player::TranslateBattleLanguageTokens(const char *string)
void Player::EventIPrint(Event *ev)
{
str sString = ev->GetString(1);
qboolean iBold = qfalse;
str sString = ev->GetString(1);
qboolean iBold = qfalse;
if (ev->NumArgs() > 1) {
iBold = ev->GetInteger(2);
}
if (iBold) {
gi.SendServerCommand(edict - g_entities, "print \"" HUD_MESSAGE_WHITE "%s\n\"", sString.c_str());
gi.SendServerCommand(edict - g_entities, "print \"" HUD_MESSAGE_WHITE "%s\n\"", gi.LV_ConvertString(sString.c_str()));
} else {
gi.SendServerCommand(edict - g_entities, "print \"" HUD_MESSAGE_YELLOW "%s\n\"", sString.c_str());
gi.SendServerCommand(edict - g_entities, "print \"" HUD_MESSAGE_YELLOW "%s\n\"", gi.LV_ConvertString(sString.c_str()));
}
}
@@ -11681,6 +11713,13 @@ void Player::FireWeapon(int number, firemode_t mode)
return;
}
if (G_GetWeaponCommand(last_ucmd.buttons)) {
// Added in OPM
// If there is a weapon command (like DROP), then just don't fire
// this prevent tricky behaviors, like silent firing
return;
}
Sentient::FireWeapon(number, mode);
if (g_gametype->integer != GT_SINGLE_PLAYER) {
@@ -11986,10 +12025,6 @@ void Player::Spawned(void)
void Player::AddKills(int num)
{
num_kills += num;
if (g_gametype->integer >= GT_TEAM_ROUNDS) {
num_deaths += num;
}
}
void Player::AddDeaths(int num)
+26 -30
View File
@@ -345,18 +345,12 @@ void Player::AdjustAnimBlends(void)
if (m_fPartBlends[legs] <= 0.0f) {
if (partOldAnim[legs] != "") {
StopAnimating(iOldPartSlot);
}
if (partAnim[legs] == "") {
SetWeight(iPartSlot, 0.0);
} else {
SetWeight(iPartSlot, 1.0);
}
if (partAnim[legs] == "") {
SetWeight(iPartSlot, 0.0);
} else {
if (partAnim[legs] == "") {
SetWeight(iPartSlot, 0.0);
} else {
SetWeight(iPartSlot, 1.0);
}
SetWeight(iPartSlot, 1.0);
}
} else {
m_fPartBlends[legs] -= level.frametime * partBlendMult[legs];
@@ -387,12 +381,14 @@ void Player::AdjustAnimBlends(void)
if (partOldAnim[torso] != "") {
StopAnimating(iOldPartSlot);
partOldAnim[torso] = "";
}
if (partAnim[torso] == "") {
SetWeight(iPartSlot, 0.0);
} else {
SetWeight(iPartSlot, 1.0);
}
if (partAnim[torso] == "") {
SetWeight(iPartSlot, 0.0);
edict->s.actionWeight = 0.0;
} else {
SetWeight(iPartSlot, 1.0);
edict->s.actionWeight = 1.0;
}
} else {
m_fPartBlends[torso] = m_fPartBlends[torso] - level.frametime * partBlendMult[torso];
@@ -427,16 +423,16 @@ void Player::AdjustAnimBlends(void)
if (m_fPainBlend) {
if (m_sPainAnim == "") {
StopAnimating(ANIMSLOT_PAIN);
edict->s.frameInfo[ANIMSLOT_PAIN].weight = 0;
m_fPainBlend = 0;
animdone_Pain = false;
SetWeight(ANIMSLOT_PAIN, 0);
m_fPainBlend = 0;
animdone_Pain = false;
} else if (animdone_Pain) {
m_fPainBlend -= level.frametime * (10.0 / 3.0);
if (m_fPainBlend < 0.01f) {
StopAnimating(ANIMSLOT_PAIN);
edict->s.frameInfo[ANIMSLOT_PAIN].weight = 0;
m_fPainBlend = 0;
animdone_Pain = false;
SetWeight(ANIMSLOT_PAIN, 0);
m_fPainBlend = 0;
animdone_Pain = false;
}
}
@@ -444,12 +440,12 @@ void Player::AdjustAnimBlends(void)
int i;
float w;
edict->s.frameInfo[ANIMSLOT_PAIN].weight = m_fPainBlend;
w = 1.0 - m_fPainBlend * 0.5;
SetWeight(ANIMSLOT_PAIN, m_fPainBlend);
w = 1.0 - m_fPainBlend * 0.5;
for (i = 0; i < ANIMSLOT_PAIN; i++) {
if (edict->s.frameInfo[i].weight) {
edict->s.frameInfo[i].weight *= w;
if (GetWeight(i)) {
SetWeight(i, GetWeight(i) * w);
}
}
@@ -490,7 +486,7 @@ void Player::PlayerAnimDelta(float *vDelta)
// get the anim delta
gi.Anim_DeltaOverTime(edict->tiki, animnum, fBackTime, fTime, vNewDelta);
VectorMA(vDelta, edict->s.frameInfo[m_iPartSlot[legs]].weight, vNewDelta, vDelta);
VectorMA(vDelta, GetWeight(m_iPartSlot[legs]), vNewDelta, vDelta);
}
animnum = -1;
@@ -509,15 +505,15 @@ void Player::PlayerAnimDelta(float *vDelta)
gi.Anim_DeltaOverTime(edict->tiki, animnum, fBackTime, fTime, vNewDelta);
VectorMA(vDelta, edict->s.frameInfo[m_iPartSlot[torso]].weight, vNewDelta, vDelta);
VectorMA(vDelta, GetWeight(m_iPartSlot[torso]), vNewDelta, vDelta);
}
}
void Player::EventTestAnim(Event *ev)
{
str name;
str name;
float weight;
int animNum;
int animNum;
weight = ev->GetFloat(1);
if (weight <= 0) {
@@ -527,7 +523,7 @@ void Player::EventTestAnim(Event *ev)
}
if (ev->NumArgs() > 1) {
name = ev->GetString(1);
name = ev->GetString(1);
animNum = gi.Anim_NumForName(edict->tiki, name.c_str());
if (animNum == -1) {
gi.Printf("Couldn't find anim '%s'\n", name.c_str());
+1 -1
View File
@@ -1515,7 +1515,7 @@ qboolean Player::CondCanGetOffLadderTop(Conditional& condition)
angles.AngleVectorsLeft(&vForward);
vStart = origin - vForward * 12.0f;
vStart = origin - vForward * 12.0f * 1.005f;
vStart[2] += maxs[2] - 8.0f;
vEnd = vStart + vForward * 40.0f;
+215 -25
View File
@@ -29,6 +29,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "scriptexception.h"
#include "vehicleturret.h"
#include "weaputils.h"
#include "g_bot.h"
// We assume that we have limited access to the server-side
// and that most logic come from the playerstate_s structure
@@ -64,8 +65,10 @@ BotController::BotController()
m_botEyes.ofs[1] = 0;
m_botEyes.ofs[2] = DEFAULT_VIEWHEIGHT;
m_iCuriousTime = 0;
m_iAttackTime = 0;
m_iCuriousTime = 0;
m_iAttackTime = 0;
m_iConfirmTime = 0;
m_iEnemyEyesTag = -1;
m_iNextTauntTime = 0;
@@ -91,7 +94,7 @@ void BotController::Init(void)
InitState_Curious(&botfuncs[1]);
InitState_Grenade(&botfuncs[2]);
InitState_Idle(&botfuncs[3]);
InitState_Weapon(&botfuncs[4]);
//InitState_Weapon(&botfuncs[4]);
}
void BotController::GetUsercmd(usercmd_t *ucmd)
@@ -160,6 +163,8 @@ void BotController::UpdateBotStates(void)
movement.MoveThink(m_botCmd);
rotation.TurnThink(m_botCmd, m_botEyes);
CheckUse();
CheckValidWeapon();
}
void BotController::CheckUse(void)
@@ -177,7 +182,7 @@ void BotController::CheckUse(void)
trace = G_Trace(start, vec_zero, vec_zero, end, controlledEnt, MASK_USABLE, false, "BotController::CheckUse");
// It may be a door
if ((trace.allsolid || trace.startsolid || trace.fraction != 1.0f) && trace.entityNum) {
if ((trace.allsolid || trace.startsolid || trace.fraction != 1.0f) && trace.ent) {
if (trace.ent->entity->IsSubclassOfDoor()) {
Door *door = static_cast<Door *>(trace.ent->entity);
if (door->isOpen()) {
@@ -195,6 +200,17 @@ void BotController::CheckUse(void)
}
}
void BotController::CheckValidWeapon() {
Weapon* weapon = controlledEnt->GetActiveWeapon(WEAPON_MAIN);
if (!weapon) {
// If holstered, use the best weapon available
UseWeaponWithAmmo();
} else if (!weapon->HasAmmo(FIRE_PRIMARY) && !controlledEnt->GetNewActiveWeapon()) {
// In case the current weapon has no ammo, use the best available weapon
UseWeaponWithAmmo();
}
}
void BotController::SendCommand(const char *text)
{
char *buffer;
@@ -372,7 +388,9 @@ Clear the bot's enemy
void BotController::ClearEnemy(void)
{
m_iAttackTime = 0;
m_iConfirmTime = 0;
m_pEnemy = NULL;
m_iEnemyEyesTag = -1;
m_vOldEnemyPos = vec_zero;
m_vLastEnemyPos = vec_zero;
}
@@ -459,6 +477,7 @@ void BotController::State_Reset(void)
m_vLastEnemyPos = vec_zero;
m_vLastDeathPos = vec_zero;
m_pEnemy = NULL;
m_iEnemyEyesTag = -1;
}
/*
@@ -647,7 +666,24 @@ bool BotController::CheckCondition_Attack(void)
maxDistance = Q_min(world->m_fAIVisionDistance, world->farplane_distance * 0.828);
if (controlledEnt->CanSee(sent, 80, maxDistance, false)) {
m_pEnemy = sent;
if (m_pEnemy != sent) {
m_iEnemyEyesTag = -1;
}
if (!m_pEnemy) {
// Slight reaction time
m_iConfirmTime = level.inttime + (200 + G_Random(200));
m_iAttackTime = 0;
}
m_pEnemy = sent;
m_vLastEnemyPos = m_pEnemy->origin;
if (level.inttime < m_iConfirmTime) {
return false;
}
}
if (m_pEnemy && level.inttime >= m_iConfirmTime) {
m_iAttackTime = level.inttime + 1000;
return true;
}
@@ -674,10 +710,12 @@ void BotController::State_EndAttack(void)
void BotController::State_Attack(void)
{
bool bMelee = false;
bool bCanSee = false;
float fMinDistance = 128;
float fMinDistanceSquared = fMinDistance * fMinDistance;
Weapon *pWeap = controlledEnt->GetActiveWeapon(WEAPON_MAIN);
bool bNoMove = false;
float fEnemyDistanceSquared;
Weapon *pWeap = controlledEnt->GetActiveWeapon(WEAPON_MAIN);
bool bNoMove = false;
if (!m_pEnemy || !IsValidEnemy(m_pEnemy)) {
// Ignore dead enemies
@@ -686,9 +724,11 @@ void BotController::State_Attack(void)
}
float fDistanceSquared = (m_pEnemy->origin - controlledEnt->origin).lengthSquared();
if (controlledEnt->CanSee(
m_pEnemy, 20, Q_min(world->m_fAIVisionDistance, world->farplane_distance * 0.828), false
)) {
m_vOldEnemyPos = m_vLastEnemyPos;
bCanSee =
controlledEnt->CanSee(m_pEnemy, 20, Q_min(world->m_fAIVisionDistance, world->farplane_distance * 0.828), false);
if (bCanSee) {
if (!pWeap) {
return;
}
@@ -706,7 +746,7 @@ void BotController::State_Attack(void)
float length;
length = controlledEnt->velocity.length();
if ((length / sv_runspeed->value) > (pWeap->GetMaxFireMovement() * pWeap->GetMovementSpeed())) {
if ((length / sv_runspeed->value) > (pWeap->GetMaxFireMovementMult())) {
bNoMove = true;
movement.ClearMove();
}
@@ -723,7 +763,9 @@ void BotController::State_Attack(void)
if (controlledEnt->client->ps.stats[STAT_AMMO] > 0 || controlledEnt->client->ps.stats[STAT_CLIPAMMO] > 0) {
if (fDistanceSquared <= fPrimaryBulletRangeSquared) {
if (pWeap->IsSemiAuto()) {
if (controlledEnt->client->ps.iViewModelAnim == VM_ANIM_IDLE || controlledEnt->client->ps.iViewModelAnim >= VM_ANIM_IDLE_0 && controlledEnt->client->ps.iViewModelAnim <= VM_ANIM_IDLE_2) {
if (controlledEnt->client->ps.iViewModelAnim == VM_ANIM_IDLE
|| controlledEnt->client->ps.iViewModelAnim >= VM_ANIM_IDLE_0
&& controlledEnt->client->ps.iViewModelAnim <= VM_ANIM_IDLE_2) {
if (fSpreadFactor < 0.25) {
m_botCmd.buttons ^= BUTTON_ATTACKLEFT;
if (pWeap->GetZoom()) {
@@ -748,43 +790,86 @@ void BotController::State_Attack(void)
m_botCmd.buttons &= ~(BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT);
controlledEnt->ZoomOff();
}
} else if (pWeap->GetFireType(FIRE_SECONDARY) == FT_MELEE) {
bMelee = true;
} else {
m_botCmd.buttons &= ~(BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT);
controlledEnt->ZoomOff();
}
if (pWeap->GetFireType(FIRE_SECONDARY) == FT_MELEE) {
if (controlledEnt->client->ps.stats[STAT_AMMO] <= 0 && controlledEnt->client->ps.stats[STAT_CLIPAMMO] <= 0) {
bMelee = true;
} else if (fDistanceSquared <= fSecondaryBulletRangeSquared) {
bMelee = true;
}
}
if (bMelee) {
m_botCmd.buttons &= ~BUTTON_ATTACKLEFT;
if (fDistanceSquared <= fSecondaryBulletRangeSquared) {
m_botCmd.buttons ^= BUTTON_ATTACKRIGHT;
} else {
m_botCmd.buttons &= ~BUTTON_ATTACKRIGHT;
}
} else {
m_botCmd.buttons &= ~(BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT);
controlledEnt->ZoomOff();
}
m_iAttackTime = level.inttime + 1000;
m_vOldEnemyPos = m_vLastEnemyPos;
m_vLastEnemyPos = m_pEnemy->centroid;
m_iAttackTime = level.inttime + 1000;
m_iAttackStopAimTime = level.inttime + 3000;
m_vLastEnemyPos = m_pEnemy->centroid;
} else {
m_botCmd.buttons &= ~(BUTTON_ATTACKLEFT | BUTTON_ATTACKRIGHT);
fMinDistanceSquared = 0;
}
rotation.AimAt(m_pEnemy->centroid + Vector(G_CRandom(8), G_CRandom(8), G_CRandom(8)));
if (bCanSee || level.inttime < m_iAttackStopAimTime) {
Vector vRandomOffset;
Vector vTarget;
orientation_t eyes_or;
if (m_iEnemyEyesTag == -1) {
// Cache the tag
m_iEnemyEyesTag = gi.Tag_NumForName(m_pEnemy->edict->tiki, "eyes bone");
}
if (m_iEnemyEyesTag != -1) {
// Use the enemy's eyes bone
m_pEnemy->GetTag(m_iEnemyEyesTag, &eyes_or);
vRandomOffset = Vector(G_CRandom(8), G_CRandom(8), -G_Random(32));
vTarget = eyes_or.origin + vRandomOffset;
rotation.AimAt(eyes_or.origin + vRandomOffset);
} else {
vRandomOffset = Vector(G_CRandom(8), G_CRandom(8), 16 + G_Random(m_pEnemy->viewheight - 16));
vTarget = m_pEnemy->origin + vRandomOffset;
}
rotation.AimAt(vTarget);
} else {
AimAtAimNode();
}
if (bNoMove) {
return;
}
fEnemyDistanceSquared = (controlledEnt->origin - m_vLastEnemyPos).lengthSquared();
if ((!movement.MoveToBestAttractivePoint(5) && !movement.IsMoving())
|| (m_vOldEnemyPos != m_vLastEnemyPos && !movement.MoveDone())) {
if (!bMelee) {
if ((controlledEnt->origin - m_vLastEnemyPos).lengthSquared() < fMinDistanceSquared) {
|| (m_vOldEnemyPos != m_vLastEnemyPos && !movement.MoveDone()) || fEnemyDistanceSquared < fMinDistanceSquared) {
if (!bMelee || !bCanSee) {
if (fEnemyDistanceSquared < fMinDistanceSquared) {
Vector vDir = controlledEnt->origin - m_vLastEnemyPos;
VectorNormalizeFast(vDir);
movement.AvoidPath(m_vLastEnemyPos, fMinDistance, Vector(controlledEnt->orientation[1]) * 512);
} else {
movement.MoveNear(m_vLastEnemyPos, fMinDistance);
movement.MoveTo(m_vLastEnemyPos);
}
if (!bCanSee && movement.MoveDone()) {
// Lost track of the enemy
ClearEnemy();
return;
}
} else {
movement.MoveTo(m_vLastEnemyPos);
@@ -851,6 +936,102 @@ void BotController::State_BeginWeapon(void)
SendCommand(va("use \"%s\"", weap->model.c_str()));
}
Weapon* BotController::FindWeaponWithAmmo() {
Weapon *next;
int n;
int j;
int bestrank;
Weapon *bestweapon;
const Container<int>& inventory = controlledEnt->getInventory();
n = inventory.NumObjects();
// Search until we find the best weapon with ammo
bestweapon = NULL;
bestrank = -999999;
for (j = 1; j <= n; j++) {
next = (Weapon *)G_GetEntity(inventory.ObjectAt(j));
assert(next);
if (!next->IsSubclassOfWeapon() || next->IsSubclassOfInventoryItem()) {
continue;
}
if (next->GetWeaponClass() & WEAPON_CLASS_THROWABLE) {
continue;
}
if (next->GetRank() < bestrank) {
continue;
}
if (!next->HasAmmo(FIRE_PRIMARY)) {
continue;
}
bestweapon = (Weapon*)next;
bestrank = bestweapon->GetRank();
}
return bestweapon;
}
Weapon* BotController::FindMeleeWeapon() {
Weapon *next;
int n;
int j;
int bestrank;
Weapon *bestweapon;
const Container<int>& inventory = controlledEnt->getInventory();
n = inventory.NumObjects();
// Search until we find the best weapon with ammo
bestweapon = NULL;
bestrank = -999999;
for (j = 1; j <= n; j++) {
next = (Weapon *)G_GetEntity(inventory.ObjectAt(j));
assert(next);
if (!next->IsSubclassOfWeapon() || next->IsSubclassOfInventoryItem()) {
continue;
}
if (next->GetRank() < bestrank) {
continue;
}
if (next->GetFireType(FIRE_SECONDARY) != FT_MELEE) {
continue;
}
bestweapon = (Weapon*)next;
bestrank = bestweapon->GetRank();
}
return bestweapon;
}
void BotController::UseWeaponWithAmmo() {
Weapon* bestWeapon = FindWeaponWithAmmo();
if (!bestWeapon) {
//
// If there is no weapon with ammo, fallback to a weapon that can melee
//
bestWeapon = FindMeleeWeapon();
}
if (!bestWeapon || bestWeapon == controlledEnt->GetActiveWeapon(WEAPON_MAIN)) {
return;
}
controlledEnt->useWeapon(bestWeapon, WEAPON_MAIN);
}
void BotController::Spawned(void)
{
ClearEnemy();
@@ -901,6 +1082,15 @@ void BotController::Killed(Event *ev)
event.AddString("auto");
controlledEnt->ProcessEvent(event);
//
// This is useful to change nationality in Spearhead and Breakthrough
// this allows the AI to use more weapons
//
Info_SetValueForKey(controlledEnt->client->pers.userinfo, "dm_playermodel", G_GetRandomAlliedPlayerModel());
Info_SetValueForKey(controlledEnt->client->pers.userinfo, "dm_playergermanmodel", G_GetRandomGermanPlayerModel());
G_ClientUserinfoChanged(controlledEnt->edict, controlledEnt->client->pers.userinfo);
}
void BotController::GotKill(Event *ev)
+13 -4
View File
@@ -110,12 +110,13 @@ private:
float m_fYawSpeedMult;
};
class BotState {
class BotState
{
public:
virtual bool CheckCondition() const = 0;
virtual void Begin() = 0;
virtual void End() = 0;
virtual void Think() = 0;
virtual void Begin() = 0;
virtual void End() = 0;
virtual void Think() = 0;
};
class BotController : public Listener
@@ -137,12 +138,15 @@ private:
// States
int m_iCuriousTime;
int m_iAttackTime;
int m_iConfirmTime;
int m_iAttackStopAimTime;
Vector m_vLastCuriousPos;
Vector m_vNewCuriousPos;
Vector m_vOldEnemyPos;
Vector m_vLastEnemyPos;
Vector m_vLastDeathPos;
SafePtr<Sentient> m_pEnemy;
int m_iEnemyEyesTag;
// Input
usercmd_t m_botCmd;
@@ -157,7 +161,12 @@ private:
int m_iNextTauntTime;
private:
Weapon* FindWeaponWithAmmo(void);
Weapon* FindMeleeWeapon(void);
void UseWeaponWithAmmo(void);
void CheckUse(void);
void CheckValidWeapon(void);
void State_DefaultBegin(void);
void State_DefaultEnd(void);
+31 -1
View File
@@ -118,14 +118,44 @@ void BotMovement::MoveThink(usercmd_t& botcmd)
}
if (m_bTempAway) {
Vector nextPos;
Vector dir;
m_bTempAway = true;
m_iTempAwayTime = level.inttime + 750;
m_iNumBlocks++;
// Try to backward a little
if (m_Path.CurrentNode()) {
nextPos = m_Path.CurrentNode()->point;
} else {
nextPos = m_vTargetPos;
}
m_Path.Clear();
m_Path.ForceShortLookahead();
m_vCurrentGoal = controlledEntity->origin + Vector(G_CRandom(512), G_CRandom(512), G_CRandom(512));
if (rand() % 10 != 0) {
dir = nextPos - controlledEntity->origin;
dir.z = 0;
dir.normalize();
if (dir.x < -0.5 || dir.x > 0.5) {
dir.x *= 4;
dir.y /= 4;
} else if (dir.y < -0.5 || dir.y > 0.5) {
dir.x /= 4;
dir.y *= 4;
} else {
dir.x = G_CRandom(2);
dir.y = G_CRandom(2);
}
m_vCurrentGoal = nextPos + dir * 128;
} else {
m_vCurrentGoal = controlledEntity->origin + Vector(G_CRandom(512), G_CRandom(512), G_CRandom(512));
}
} else {
m_iNumBlocks = 0;
+3 -3
View File
@@ -62,7 +62,7 @@ void BotRotation::TurnThink(usercmd_t& botcmd, usereyes_t& eyeinfo)
m_vTargetAng[PITCH] -= 360;
}
factor = 0.25f;
factor = 0.5f;
maxchange = 360;
if (maxchange < 240) {
@@ -84,7 +84,7 @@ void BotRotation::TurnThink(usercmd_t& botcmd, usereyes_t& eyeinfo)
m_vCurrentAng[i] += anglespeed;
m_vCurrentAng[i] = AngleMod(m_vCurrentAng[i]);
//demping
//damping
m_vAngSpeed[i] *= 0.2 * (1 - factor);
}
@@ -132,7 +132,7 @@ Make the bot face to the specified direction
*/
void BotRotation::AimAt(Vector vPos)
{
Vector vDelta = vPos - controlledEntity->centroid;
Vector vDelta = vPos - controlledEntity->EyePosition();
VectorNormalize(vDelta);
vectoangles(vDelta, m_vTargetAng);
+6 -2
View File
@@ -2126,7 +2126,8 @@ Event EV_ScriptOrigin_GetAngle
NULL,
"get the angles of the entity using just one value.\n"
"Gets the yaw of the entity or an up and down\n"
"direction if newAngle is [0-359] or -1 or -2"
"direction if newAngle is [0-359] or -1 or -2",
EV_GETTER
);
CLASS_DECLARATION(ScriptSlave, ScriptOrigin, "script_origin") {
@@ -2173,7 +2174,10 @@ void ScriptOrigin::SetAngleEvent(Event* ev)
void ScriptOrigin::GetAngleEvent(Event* ev)
{
ev->AddFloat(G_GetAngle(angles));
Vector forward;
angles.AngleVectorsLeft(&forward);
ev->AddFloat(G_GetAngle(forward));
}
/*****************************************************************************/
+174 -134
View File
@@ -1435,6 +1435,15 @@ Event EV_ScriptThread_FileRead
EV_NORMAL
);
Event EV_ScriptThread_FileClose
(
"fclose",
EV_DEFAULT,
"i",
"filehandle",
"Closes file of given file handle",
EV_NORMAL
);
Event EV_ScriptThread_FileClose2
(
"fclose",
EV_DEFAULT,
@@ -2191,6 +2200,7 @@ CLASS_DECLARATION(Listener, ScriptThread, NULL) {
{&EV_ScriptThread_Earthquake2, &ScriptThread::Earthquake },
{&EV_ScriptThread_FadeSound, &ScriptThread::FadeSound },
{&EV_ScriptThread_FileClose, &ScriptThread::FileClose },
{&EV_ScriptThread_FileClose2, &ScriptThread::FileClose },
{&EV_ScriptThread_FileCopy, &ScriptThread::FileCopy },
{&EV_ScriptThread_FileEof, &ScriptThread::FileEof },
{&EV_ScriptThread_FileError, &ScriptThread::FileError },
@@ -2478,7 +2488,7 @@ void ScriptThread::Stop(void)
}
}
void ScriptThread::Wait(float time)
void ScriptThread::Wait(int time)
{
StartTiming(level.inttime + time);
m_ScriptVM->Suspend();
@@ -2496,7 +2506,7 @@ void ScriptThread::Getcvar(Event *ev)
str s = gi.Cvar_Get(varName.c_str(), "", 0)->string;
if (strstr(s.c_str(), ".")) {
for (int i = s.length() - 1; i >= 0; i--) {
for (size_t i = s.length() - 1; i >= 0; i--) {
if (s[i] == '0') {
s[i] = 0;
} else {
@@ -2797,7 +2807,7 @@ void ScriptThread::IPrintln(Event *ev)
sString += ev->GetString(i);
}
G_PrintToAllClients(gi.LV_ConvertString(sString), false);
gi.SendServerCommand(-1, "print \"" HUD_MESSAGE_YELLOW "%s\n\"", gi.LV_ConvertString(sString.c_str()));
}
void ScriptThread::IPrintlnBold(Event *ev)
@@ -2810,7 +2820,7 @@ void ScriptThread::IPrintlnBold(Event *ev)
sString += ev->GetString(i);
}
G_PrintToAllClients(gi.LV_ConvertString(sString), true);
gi.SendServerCommand(-1, "print \"" HUD_MESSAGE_WHITE "%s\n\"", gi.LV_ConvertString(sString.c_str()));
}
void ScriptThread::IPrintln_NoLoc(Event *ev)
@@ -2823,7 +2833,7 @@ void ScriptThread::IPrintln_NoLoc(Event *ev)
sString += ev->GetString(i);
}
G_PrintToAllClients(sString, false);
gi.SendServerCommand(-1, "print \"" HUD_MESSAGE_YELLOW "%s\n\"", sString.c_str());
}
void ScriptThread::IPrintlnBold_NoLoc(Event *ev)
@@ -2836,7 +2846,7 @@ void ScriptThread::IPrintlnBold_NoLoc(Event *ev)
sString += ev->GetString(i);
}
G_PrintToAllClients(sString, true);
gi.SendServerCommand(-1, "print \"" HUD_MESSAGE_WHITE "%s\n\"", sString.c_str());
}
void ScriptThread::MPrint(Event *ev)
@@ -4093,7 +4103,7 @@ void ScriptThread::EventRadiusDamage(Event *ev)
void ScriptThread::EventBspTransition(Event *ev)
{
str map = ev->GetString(1);
str map = ev->GetString(1);
bool skipFade = false;
if (ev->NumArgs() >= 2) {
@@ -4203,12 +4213,12 @@ void ScriptThread::EventPointsWithinDist(Event *ev)
{
Vector delta;
Vector v1, v2;
float fDistance;
v1 = ev->GetVector(1);
v2 = ev->GetVector(2);
float fDistance;
v1 = ev->GetVector(1);
v2 = ev->GetVector(2);
fDistance = ev->GetFloat(3);
delta = v1 - v2;
delta = v1 - v2;
// check squared distance
ev->AddInteger(delta.lengthSquared() < Square(fDistance));
@@ -5361,15 +5371,15 @@ void ScriptThread::FileOpen(Event *ev)
f = fopen(filename, accesstype);
if (f == NULL) {
ev->AddInteger(0);
return;
} else {
ev->AddInteger((int)(size_t)f);
Com_sprintf(buf, sizeof(buf), "%i", scriptfiles->integer + 1);
gi.cvar_set("sv_scriptfiles", buf);
if (!f) {
ev->AddNil();
return;
}
ev->AddListener(new OSFile(f));
Com_sprintf(buf, sizeof(buf), "%i", scriptfiles->integer + 1);
gi.cvar_set("sv_scriptfiles", buf);
}
void ScriptThread::FileWrite(Event *ev) {}
@@ -5378,11 +5388,10 @@ void ScriptThread::FileRead(Event *ev) {}
void ScriptThread::FileClose(Event *ev)
{
int id = 0;
int numArgs = 0;
int ret = 0;
FILE *f = NULL;
char buf[16] = {0};
OSFile *osFile = NULL;
int numArgs = 0;
FILE *f = NULL;
char buf[16] = {0};
numArgs = ev->NumArgs();
@@ -5390,57 +5399,30 @@ void ScriptThread::FileClose(Event *ev)
throw ScriptException("Wrong arguments count for fclose!\n");
}
id = ev->GetInteger(1);
/*if( (int)scriptFiles[0].f != id && (int)scriptFiles[1].f != id )
{
gi.Printf("Wrong file handle for fclose!\n");
return;
osFile = (OSFile *)ev->GetListener(1);
if (!osFile || !osFile->isSubclassOf(OSFile)) {
throw ScriptException("Not a file!\n");
}
if( (int)scriptFiles[0].f == id )
{
scriptFiles[0].inUse = 0;
fclose( scriptFiles[0].f );
return;
}
else if( (int)scriptFiles[1].f == id )
{
scriptFiles[1].inUse = 0;
fclose( scriptFiles[1].f );
return;
}
else
{
gi.Printf("Unknown error while closing file - fclose!\n");
return;
}*/
f = (FILE *)id;
f = (FILE *)osFile->getOSFile();
if (f == NULL) {
throw ScriptException("File handle is NULL for fclose!\n");
}
ret = fclose(f);
// delete the file object
delete osFile;
if (ret == 0) {
ev->AddInteger(0);
Com_sprintf(buf, sizeof(buf), "%i", scriptfiles->integer - 1);
gi.cvar_set("sv_scriptfiles", buf);
return;
} else {
ev->AddInteger(ret);
return;
}
Com_sprintf(buf, sizeof(buf), "%i", scriptfiles->integer - 1);
gi.cvar_set("sv_scriptfiles", buf);
}
void ScriptThread::FileEof(Event *ev)
{
int id = 0;
int numArgs = 0;
int ret = 0;
FILE *f = NULL;
OSFile *osFile = NULL;
int numArgs = 0;
int ret = 0;
FILE *f = NULL;
numArgs = ev->NumArgs();
@@ -5448,9 +5430,12 @@ void ScriptThread::FileEof(Event *ev)
throw ScriptException("Wrong arguments count for feof!\n");
}
id = ev->GetInteger(1);
osFile = (OSFile *)ev->GetListener(1);
if (!osFile || !osFile->isSubclassOf(OSFile)) {
throw ScriptException("Not a file!\n");
}
f = (FILE *)id;
f = (FILE *)osFile->getOSFile();
ret = feof(f);
@@ -5459,7 +5444,7 @@ void ScriptThread::FileEof(Event *ev)
void ScriptThread::FileSeek(Event *ev)
{
int id = 0;
OSFile *osFile = NULL;
int numArgs = 0;
int pos = 0;
long int offset = 0;
@@ -5472,9 +5457,12 @@ void ScriptThread::FileSeek(Event *ev)
throw ScriptException("Wrong arguments count for fseek!\n");
}
id = ev->GetInteger(1);
osFile = (OSFile *)ev->GetListener(1);
if (!osFile || !osFile->isSubclassOf(OSFile)) {
throw ScriptException("Not a file!\n");
}
f = (FILE *)id;
f = (FILE *)osFile->getOSFile();
offset = ev->GetInteger(2);
@@ -5495,7 +5483,7 @@ void ScriptThread::FileSeek(Event *ev)
void ScriptThread::FileTell(Event *ev)
{
int id = 0;
OSFile *osFile = NULL;
int numArgs = 0;
long int ret = 0;
FILE *f = NULL;
@@ -5506,9 +5494,12 @@ void ScriptThread::FileTell(Event *ev)
throw ScriptException("Wrong arguments count for ftell!\n");
}
id = ev->GetInteger(1);
osFile = (OSFile *)ev->GetListener(1);
if (!osFile || !osFile->isSubclassOf(OSFile)) {
throw ScriptException("Not a file!\n");
}
f = (FILE *)id;
f = (FILE *)osFile->getOSFile();
ret = ftell(f);
@@ -5517,7 +5508,7 @@ void ScriptThread::FileTell(Event *ev)
void ScriptThread::FileRewind(Event *ev)
{
int id = 0;
OSFile *osFile = NULL;
int numArgs = 0;
long int ret = 0;
FILE *f = NULL;
@@ -5528,20 +5519,23 @@ void ScriptThread::FileRewind(Event *ev)
throw ScriptException("Wrong arguments count for frewind!\n");
}
id = ev->GetInteger(1);
osFile = (OSFile *)ev->GetListener(1);
if (!osFile || !osFile->isSubclassOf(OSFile)) {
throw ScriptException("Not a file!\n");
}
f = (FILE *)id;
f = (FILE *)osFile->getOSFile();
rewind(f);
}
void ScriptThread::FilePutc(Event *ev)
{
int id = 0;
int numArgs = 0;
int ret = 0;
FILE *f = NULL;
int c = 0;
OSFile *osFile = NULL;
int numArgs = 0;
int ret = 0;
FILE *f = NULL;
int c = 0;
numArgs = ev->NumArgs();
@@ -5549,9 +5543,12 @@ void ScriptThread::FilePutc(Event *ev)
throw ScriptException("Wrong arguments count for fputc!\n");
}
id = ev->GetInteger(1);
osFile = (OSFile *)ev->GetListener(1);
if (!osFile || !osFile->isSubclassOf(OSFile)) {
throw ScriptException("Not a file!\n");
}
f = (FILE *)id;
f = (FILE *)osFile->getOSFile();
c = ev->GetInteger(2);
@@ -5562,11 +5559,11 @@ void ScriptThread::FilePutc(Event *ev)
void ScriptThread::FilePuts(Event *ev)
{
int id = 0;
int numArgs = 0;
int ret = 0;
FILE *f = NULL;
str c;
OSFile *osFile = NULL;
int numArgs = 0;
int ret = 0;
FILE *f = NULL;
str c;
numArgs = ev->NumArgs();
@@ -5574,9 +5571,12 @@ void ScriptThread::FilePuts(Event *ev)
throw ScriptException("Wrong arguments count for fputs!\n");
}
id = ev->GetInteger(1);
osFile = (OSFile *)ev->GetListener(1);
if (!osFile || !osFile->isSubclassOf(OSFile)) {
throw ScriptException("Not a file!\n");
}
f = (FILE *)id;
f = (FILE *)osFile->getOSFile();
c = ev->GetString(2);
//gi.Printf("Putting line into a file\n");
@@ -5587,10 +5587,10 @@ void ScriptThread::FilePuts(Event *ev)
void ScriptThread::FileGetc(Event *ev)
{
int id = 0;
int numArgs = 0;
int ret = 0;
FILE *f = NULL;
OSFile *osFile = NULL;
int numArgs = 0;
int ret = 0;
FILE *f = NULL;
numArgs = ev->NumArgs();
@@ -5598,9 +5598,12 @@ void ScriptThread::FileGetc(Event *ev)
throw ScriptException("Wrong arguments count for fgetc!\n");
}
id = ev->GetInteger(1);
osFile = (OSFile *)ev->GetListener(1);
if (!osFile || !osFile->isSubclassOf(OSFile)) {
throw ScriptException("Not a file!\n");
}
f = (FILE *)id;
f = (FILE *)osFile->getOSFile();
ret = fgetc(f);
@@ -5609,12 +5612,12 @@ void ScriptThread::FileGetc(Event *ev)
void ScriptThread::FileGets(Event *ev)
{
int id = 0;
int numArgs = 0;
int maxCount = 0;
FILE *f = NULL;
char *c = NULL;
char *buff = NULL;
OSFile *osFile = NULL;
int numArgs = 0;
int maxCount = 0;
FILE *f = NULL;
char *c = NULL;
char *buff = NULL;
numArgs = ev->NumArgs();
@@ -5622,9 +5625,12 @@ void ScriptThread::FileGets(Event *ev)
throw ScriptException("Wrong arguments count for fgets!\n");
}
id = ev->GetInteger(1);
osFile = (OSFile *)ev->GetListener(1);
if (!osFile || !osFile->isSubclassOf(OSFile)) {
throw ScriptException("Not a file!\n");
}
f = (FILE *)id;
f = (FILE *)osFile->getOSFile();
maxCount = ev->GetInteger(2);
@@ -5657,10 +5663,10 @@ void ScriptThread::FileGets(Event *ev)
void ScriptThread::FileError(Event *ev)
{
int id = 0;
int numArgs = 0;
int ret = 0;
FILE *f = NULL;
OSFile *osFile = NULL;
int numArgs = 0;
int ret = 0;
FILE *f = NULL;
numArgs = ev->NumArgs();
@@ -5668,9 +5674,12 @@ void ScriptThread::FileError(Event *ev)
throw ScriptException("Wrong arguments count for ferror!\n");
}
id = ev->GetInteger(1);
osFile = (OSFile *)ev->GetListener(1);
if (!osFile || !osFile->isSubclassOf(OSFile)) {
throw ScriptException("Not a file!\n");
}
f = (FILE *)id;
f = (FILE *)osFile->getOSFile();
ret = ferror(f);
@@ -5679,10 +5688,10 @@ void ScriptThread::FileError(Event *ev)
void ScriptThread::FileFlush(Event *ev)
{
int id = 0;
int numArgs = 0;
int ret = 0;
FILE *f = NULL;
OSFile *osFile = NULL;
int numArgs = 0;
int ret = 0;
FILE *f = NULL;
numArgs = ev->NumArgs();
@@ -5690,9 +5699,12 @@ void ScriptThread::FileFlush(Event *ev)
throw ScriptException("Wrong arguments count for fflush!\n");
}
id = ev->GetInteger(1);
osFile = (OSFile *)ev->GetListener(1);
if (!osFile || !osFile->isSubclassOf(OSFile)) {
throw ScriptException("Not a file!\n");
}
f = (FILE *)id;
f = (FILE *)osFile->getOSFile();
ret = fflush(f);
@@ -5701,7 +5713,6 @@ void ScriptThread::FileFlush(Event *ev)
void ScriptThread::FileExists(Event *ev)
{
int id = 0;
int numArgs = 0;
FILE *f = 0;
str filename;
@@ -5729,13 +5740,13 @@ void ScriptThread::FileExists(Event *ev)
void ScriptThread::FileReadAll(Event *ev)
{
int id = 0;
int numArgs = 0;
FILE *f = NULL;
char *ret = NULL;
long currentPos = 0;
size_t size = 0;
size_t sizeRead = 0;
OSFile *osFile = NULL;
int numArgs = 0;
FILE *f = NULL;
char *ret = NULL;
long currentPos = 0;
size_t size = 0;
size_t sizeRead = 0;
numArgs = ev->NumArgs();
@@ -5743,9 +5754,12 @@ void ScriptThread::FileReadAll(Event *ev)
throw ScriptException("Wrong arguments count for freadall!\n");
}
id = ev->GetInteger(1);
osFile = (OSFile *)ev->GetListener(1);
if (!osFile || !osFile->isSubclassOf(OSFile)) {
throw ScriptException("Not a file!\n");
}
f = (FILE *)id;
f = (FILE *)osFile->getOSFile();
currentPos = ftell(f);
fseek(f, 0, SEEK_END);
@@ -5769,11 +5783,11 @@ void ScriptThread::FileReadAll(Event *ev)
void ScriptThread::FileSaveAll(Event *ev)
{
int id = 0;
int numArgs = 0;
FILE *f = NULL;
size_t sizeWrite = 0;
str text;
OSFile *osFile = NULL;
int numArgs = 0;
FILE *f = NULL;
size_t sizeWrite = 0;
str text;
numArgs = ev->NumArgs();
@@ -5781,8 +5795,12 @@ void ScriptThread::FileSaveAll(Event *ev)
throw ScriptException("Wrong arguments count for fsaveall!\n");
}
id = ev->GetInteger(1);
f = (FILE *)id;
osFile = (OSFile *)ev->GetListener(1);
if (!osFile || !osFile->isSubclassOf(OSFile)) {
throw ScriptException("Not a file!\n");
}
f = (FILE *)osFile->getOSFile();
text = ev->GetString(2);
@@ -5798,7 +5816,6 @@ void ScriptThread::FileSaveAll(Event *ev)
void ScriptThread::FileRemove(Event *ev)
{
int id = 0;
int numArgs = 0;
int ret = 0;
str filename;
@@ -5822,7 +5839,6 @@ void ScriptThread::FileRemove(Event *ev)
void ScriptThread::FileRename(Event *ev)
{
int id = 0;
int numArgs = 0;
int ret = 0;
str oldfilename, newfilename;
@@ -7049,4 +7065,28 @@ void ScriptThread::TraceDetails(Event *ev)
array.setArrayAtRef(entityIndex, entityValue);
ev->AddValue(array);
}
}
CLASS_DECLARATION(Listener, OSFile, NULL) {
{NULL, NULL}
};
OSFile::OSFile()
: file(NULL)
{}
OSFile::OSFile(void *inFile)
: file(inFile)
{}
OSFile::~OSFile()
{
if (file) {
fclose((FILE *)file);
}
}
void *OSFile::getOSFile() const
{
return file;
}
+17 -2
View File
@@ -196,7 +196,7 @@ public:
void Execute(Event *ev);
void Execute();
void Execute(ScriptVariable *data, int dataSize);
void Wait(float time);
void Wait(int time);
void Pause(void);
void ScriptExecute(ScriptVariable *data, int dataSize, ScriptVariable& returnValue);
void ScriptExecuteInternal(ScriptVariable *data = NULL, int dataSize = 0);
@@ -345,4 +345,19 @@ public:
void UnregisterEvent(Event *ev);
void VisionGetNaked(Event *ev);
void VisionSetNaked(Event *ev);
};
};
class OSFile : public Listener
{
CLASS_PROTOTYPE(OSFile);
public:
OSFile();
OSFile(void *inFile);
~OSFile();
void *getOSFile() const;
private:
void *file;
};
+26 -6
View File
@@ -531,7 +531,7 @@ Event EV_Sentient_ForceDropWeapon2
);
Event EV_Sentient_ForceDropHealth
(
"forcedropweapon",
"forcedrophealth",
EV_DEFAULT,
NULL,
NULL,
@@ -540,7 +540,7 @@ Event EV_Sentient_ForceDropHealth
);
Event EV_Sentient_ForceDropHealth2
(
"forcedropweapon",
"forcedrophealth",
EV_DEFAULT,
NULL,
NULL,
@@ -578,6 +578,24 @@ Event EV_Sentient_GetNewActiveWeap
"gets new active weapon",
EV_RETURN
);
Event EV_Sentient_GetNewActiveWeapon
(
"newActiveWeapon",
EV_DEFAULT,
NULL,
NULL,
"gets new active weapon",
EV_GETTER
);
Event EV_Sentient_GetNewActiveWeaponHand
(
"newActiveWeaponHand",
EV_DEFAULT,
NULL,
NULL,
"gets the hand of the new active weapon",
EV_GETTER
);
Event EV_Sentient_GetActiveWeap
(
"getactiveweap",
@@ -656,10 +674,12 @@ CLASS_DECLARATION(Animate, Sentient, NULL) {
{&EV_Sentient_ForceDropWeapon2, &Sentient::EventForceDropWeapon },
{&EV_Sentient_GetForceDropWeapon, &Sentient::EventGetForceDropWeapon },
{&EV_Sentient_GetActiveWeap, &Sentient::GetActiveWeap },
{&EV_Sentient_GetNewActiveWeap, &Sentient::GetNewActiveWeapon },
{&EV_Sentient_Client_Landing, &Sentient::EventClientLanding },
{NULL, NULL }
{&EV_Sentient_GetActiveWeap, &Sentient::GetActiveWeap },
{&EV_Sentient_GetNewActiveWeap, &Sentient::GetNewActiveWeaponOld },
{&EV_Sentient_GetNewActiveWeapon, &Sentient::GetNewActiveWeapon },
{&EV_Sentient_GetNewActiveWeaponHand, &Sentient::GetNewActiveWeaponHand },
{&EV_Sentient_Client_Landing, &Sentient::EventClientLanding },
{NULL, NULL }
};
Container<Sentient *> SentientList;
+6
View File
@@ -321,6 +321,7 @@ public:
Weapon *GetNewActiveWeapon(void);
weaponhand_t GetNewActiveWeaponHand(void);
void ClearNewActiveWeapon(void);
void SetNewActiveWeapon(Weapon* weapon, weaponhand_t hand);
void Holster(qboolean putaway);
void SafeHolster(qboolean putaway);
void ActivateNewWeapon(void);
@@ -355,12 +356,17 @@ public:
// Custom openmohaa stuff
//
void GetActiveWeap(Event *ev);
void GetNewActiveWeaponOld(Event *ev);
void GetNewActiveWeapon(Event *ev);
void GetNewActiveWeaponHand(Event *ev);
void EventClientLanding(Event *ev);
void FootstepMain(trace_t *trace, int iRunning, int iEquipment);
void Footstep(const char *szTagName, int iRunning, int iEquipment);
void LandingSound(float volume, int iEquipment);
const Container<int>& getInventory() const;
const Container<Ammo*>& getAmmoInventory() const;
};
typedef SafePtr<Sentient> SentientPtr;
+38 -10
View File
@@ -54,8 +54,13 @@ Weapon *Sentient::GetNewActiveWeapon(void)
void Sentient::ClearNewActiveWeapon(void)
{
newActiveWeapon.weapon.Clear();
newActiveWeapon.hand = WEAPON_ERROR;
SetNewActiveWeapon(NULL, WEAPON_ERROR);
}
void Sentient::SetNewActiveWeapon(Weapon* weapon, weaponhand_t hand)
{
newActiveWeapon.weapon = weapon;
newActiveWeapon.hand = hand;
}
void Sentient::EventGiveAmmo(Event *ev)
@@ -1097,6 +1102,9 @@ void Sentient::useWeapon(const char *weaponname, weaponhand_t hand)
// Find the item in the sentient's inventory
weapon = (Weapon *)FindItem(weaponname);
if (!weapon) {
weapon = (Weapon *)FindItemByExternalName(weaponname);
}
// If it exists, then make the change to the slot number specified
if (weapon) {
@@ -1114,8 +1122,7 @@ void Sentient::useWeapon(Weapon *weapon, weaponhand_t hand)
}
if (newActiveWeapon.weapon) {
newActiveWeapon.weapon = weapon;
newActiveWeapon.hand = hand;
SetNewActiveWeapon(weapon, hand);
return;
}
@@ -1127,14 +1134,15 @@ void Sentient::useWeapon(Weapon *weapon, weaponhand_t hand)
activeWeaponList[WEAPON_OFFHAND]->PutAway();
}
if (activeWeaponList[WEAPON_MAIN] && activeWeaponList[WEAPON_MAIN] != weapon) {
if (activeWeaponList[WEAPON_MAIN] == weapon) {
return;
}
if (activeWeaponList[WEAPON_MAIN]) {
activeWeaponList[WEAPON_MAIN]->PutAway();
}
newActiveWeapon.weapon = weapon;
newActiveWeapon.hand = hand;
//ChangeWeapon( weapon, hand );
SetNewActiveWeapon(weapon, hand);
}
void Sentient::EventUseWeaponClass(Event *ev)
@@ -1287,11 +1295,23 @@ Ammo *Sentient::FindAmmoByName(str name)
return NULL;
}
void Sentient::GetNewActiveWeapon(Event *ev)
void Sentient::GetNewActiveWeaponOld(Event *ev)
{
ScriptDeprecatedAltVariable("newActiveWeapon");
ev->AddEntity(GetNewActiveWeapon());
}
void Sentient::GetNewActiveWeapon(Event* ev)
{
ev->AddEntity(GetNewActiveWeapon());
}
void Sentient::GetNewActiveWeaponHand(Event* ev)
{
ev->AddInteger(GetNewActiveWeaponHand());
}
void Sentient::GetActiveWeap(Event *ev)
{
weaponhand_t weaponhand;
@@ -1308,3 +1328,11 @@ void Sentient::GetActiveWeap(Event *ev)
ev->AddEntity(weapon);
}
const Container<int>& Sentient::getInventory() const {
return inventory;
}
const Container<Ammo*>& Sentient::getAmmoInventory() const {
return ammo_inventory;
}
+78 -62
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
Copyright (C) 2024 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -122,106 +122,107 @@ Event EV_SmokeGrenade_SetMaxAlpha
"sets maximum opacity of an individual smoke particle, in 0-1 range"
);
CLASS_DECLARATION(EffectEntity, SmokeGrenade, "smokegrenade")
{
{ &EV_SmokeGrenade_SetSpawnRate, &SmokeGrenade::EventSetSpawnrate },
{ &EV_SmokeGrenade_SetBouncefactor, &SmokeGrenade::EventSetBouncefactor },
{ &EV_SmokeGrenade_SetLife, &SmokeGrenade::EventSetLife },
{ &EV_SmokeGrenade_SetSpawnLife, &SmokeGrenade::EventSetSpawnLife },
{ &EV_SmokeGrenade_SetScalerate, &SmokeGrenade::EventSetScalerate },
{ &EV_SmokeGrenade_SetVelocity, &SmokeGrenade::EventSetVelocity },
{ &EV_SmokeGrenade_SetSpin, &SmokeGrenade::EventSetSpin },
{ &EV_SmokeGrenade_SetOffset, &SmokeGrenade::EventSetOffset },
{ &EV_SmokeGrenade_SetScale, &SmokeGrenade::EventSetScale },
{ &EV_SmokeGrenade_SetFadein, &SmokeGrenade::EventSetFadein },
{ &EV_SmokeGrenade_SetFadedelay, &SmokeGrenade::EventSetFadedelay },
{ &EV_SmokeGrenade_SetMaxAlpha, &SmokeGrenade::EventSetMaxAlpha },
{ NULL, NULL }
CLASS_DECLARATION(EffectEntity, SmokeGrenade, "smokegrenade") {
{&EV_SmokeGrenade_SetSpawnRate, &SmokeGrenade::EventSetSpawnrate },
{&EV_SmokeGrenade_SetBouncefactor, &SmokeGrenade::EventSetBouncefactor},
{&EV_SmokeGrenade_SetLife, &SmokeGrenade::EventSetLife },
{&EV_SmokeGrenade_SetSpawnLife, &SmokeGrenade::EventSetSpawnLife },
{&EV_SmokeGrenade_SetScalerate, &SmokeGrenade::EventSetScalerate },
{&EV_SmokeGrenade_SetVelocity, &SmokeGrenade::EventSetVelocity },
{&EV_SmokeGrenade_SetSpin, &SmokeGrenade::EventSetSpin },
{&EV_SmokeGrenade_SetOffset, &SmokeGrenade::EventSetOffset },
{&EV_SmokeGrenade_SetScale, &SmokeGrenade::EventSetScale },
{&EV_SmokeGrenade_SetFadein, &SmokeGrenade::EventSetFadein },
{&EV_SmokeGrenade_SetFadedelay, &SmokeGrenade::EventSetFadedelay },
{&EV_SmokeGrenade_SetMaxAlpha, &SmokeGrenade::EventSetMaxAlpha },
{NULL, NULL }
};
void SmokeGrenade::EventSetSpawnrate(Event* ev)
void SmokeGrenade::EventSetSpawnrate(Event *ev)
{
float rate = ev->GetFloat(1);
if (rate < 0.001f) rate = 0.001f;
if (rate < 0.001f) {
rate = 0.001f;
}
spawnRate = 1000.0f / rate;
}
void SmokeGrenade::EventSetBouncefactor(Event* ev)
void SmokeGrenade::EventSetBouncefactor(Event *ev)
{
bounceFactor = ev->GetFloat(1);
}
void SmokeGrenade::EventSetLife(Event* ev)
void SmokeGrenade::EventSetLife(Event *ev)
{
nextRemoveTime = level.time + ev->GetFloat(1);
}
void SmokeGrenade::EventSetSpawnLife(Event* ev)
void SmokeGrenade::EventSetSpawnLife(Event *ev)
{
spawnLife = ev->GetFloat(1);
}
void SmokeGrenade::EventSetScalerate(Event* ev)
void SmokeGrenade::EventSetScalerate(Event *ev)
{
scaleRate = ev->GetFloat(1);
}
void SmokeGrenade::EventSetVelocity(Event* ev)
void SmokeGrenade::EventSetVelocity(Event *ev)
{
velocity[0] = ev->GetFloat(1);
velocity[1] = ev->GetFloat(2);
velocity[2] = ev->GetFloat(3);
}
void SmokeGrenade::EventSetSpin(Event* ev)
void SmokeGrenade::EventSetSpin(Event *ev)
{
spinRate = ev->GetFloat(1);
}
void SmokeGrenade::EventSetOffset(Event* ev)
void SmokeGrenade::EventSetOffset(Event *ev)
{
offset[0] = ev->GetFloat(1);
offset[1] = ev->GetFloat(2);
offset[2] = ev->GetFloat(3);
}
void SmokeGrenade::EventSetScale(Event* ev)
void SmokeGrenade::EventSetScale(Event *ev)
{
scale = ev->GetFloat(1) * 0.5;
}
void SmokeGrenade::EventSetFadein(Event* ev)
void SmokeGrenade::EventSetFadein(Event *ev)
{
fadeIn = ev->GetFloat(1);
}
void SmokeGrenade::EventSetFadedelay(Event* ev)
void SmokeGrenade::EventSetFadedelay(Event *ev)
{
fadeDelay = ev->GetFloat(1);
}
void SmokeGrenade::EventSetMaxAlpha(Event* ev)
void SmokeGrenade::EventSetMaxAlpha(Event *ev)
{
maxAlpha = ev->GetFloat(1);
}
SmokeGrenade::SmokeGrenade()
{
flags |= FL_THINK;
nextRemoveTime = level.time + 1.0;
spawnRate = 1000;
bounceFactor = 0.0;
spawnLife = 1.0;
scaleRate = 1.0;
velocity = vec_zero;
offset = vec_zero;
spinRate = 0.0;
scale = 1.0;
fadeIn = 0.0;
fadeDelay = spawnLife;
maxAlpha = 1.0;
lastSpawnTime = level.inttime + 150;
flags |= FL_THINK;
nextRemoveTime = level.time + 1.0;
spawnRate = 1000;
bounceFactor = 0.0;
spawnLife = 1.0;
scaleRate = 1.0;
velocity = vec_zero;
offset = vec_zero;
spinRate = 0.0;
scale = 1.0;
fadeIn = 0.0;
fadeDelay = spawnLife;
maxAlpha = 1.0;
lastSpawnTime = level.inttime + 150;
}
void SmokeGrenade::Think()
@@ -233,42 +234,57 @@ void SmokeGrenade::Think()
if (level.inttime >= lastSpawnTime + spawnRate) {
SmokeSprite sp;
float degrees;
float degrees;
lastSpawnTime += spawnRate;
sp.origin = origin;
sp.origin = origin;
sp.spawnTime = level.time;
sp.scale = scale;
sp.scale = scale;
degrees = angles.y + (((level.inttime / 1000.0 - 176.0) * spinRate) * -0.36);
RotatePointAroundAxis(
sp.velocity,
2,
velocity,
degrees
);
sp.spawnLife = spawnLife;
RotatePointAroundAxis(sp.velocity, 2, velocity, degrees);
sp.spawnLife = spawnLife;
sp.bounceFactor = bounceFactor;
sp.scaleStart = scale;
sp.scaleRate = scaleRate;
sp.fadeIn = fadeIn;
sp.fadeDelay = fadeDelay;
sp.maxAlpha = maxAlpha;
sp.owner = owner;
sp.scaleStart = scale;
sp.scaleRate = scaleRate;
sp.fadeIn = fadeIn;
sp.fadeDelay = fadeDelay;
sp.maxAlpha = maxAlpha;
sp.owner = owner;
G_AddSmokeSprite(&sp);
}
}
void SmokeGrenade::setOwner(Sentient* other)
void SmokeGrenade::Archive(Archiver& arc)
{
EffectEntity::Archive(arc);
arc.ArchiveFloat(&nextRemoveTime);
arc.ArchiveInteger(&spawnRate);
arc.ArchiveFloat(&bounceFactor);
arc.ArchiveFloat(&spawnLife);
arc.ArchiveFloat(&scaleRate);
arc.ArchiveVector(&velocity);
arc.ArchiveFloat(&spinRate);
arc.ArchiveVector(&offset);
arc.ArchiveFloat(&scale);
arc.ArchiveFloat(&fadeIn);
arc.ArchiveFloat(&fadeDelay);
arc.ArchiveFloat(&maxAlpha);
arc.ArchiveInteger(&lastSpawnTime);
arc.ArchiveSafePointer(&owner);
}
void SmokeGrenade::setOwner(Sentient *other)
{
owner = other;
}
Sentient* SmokeGrenade::getOwner() const
Sentient *SmokeGrenade::getOwner() const
{
return owner;
}
+32 -29
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
Copyright (C) 2024 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -26,43 +26,46 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
class Sentient;
class SmokeGrenade : public EffectEntity {
class SmokeGrenade : public EffectEntity
{
CLASS_PROTOTYPE(SmokeGrenade);
public:
SmokeGrenade();
void EventSetSpawnrate(Event* ev);
void EventSetBouncefactor(Event* ev);
void EventSetLife(Event* ev);
void EventSetSpawnLife(Event* ev);
void EventSetScalerate(Event* ev);
void EventSetVelocity(Event* ev);
void EventSetSpin(Event* ev);
void EventSetOffset(Event* ev);
void EventSetScale(Event* ev);
void EventSetFadein(Event* ev);
void EventSetFadedelay(Event* ev);
void EventSetMaxAlpha(Event* ev);
void EventSetSpawnrate(Event *ev);
void EventSetBouncefactor(Event *ev);
void EventSetLife(Event *ev);
void EventSetSpawnLife(Event *ev);
void EventSetScalerate(Event *ev);
void EventSetVelocity(Event *ev);
void EventSetSpin(Event *ev);
void EventSetOffset(Event *ev);
void EventSetScale(Event *ev);
void EventSetFadein(Event *ev);
void EventSetFadedelay(Event *ev);
void EventSetMaxAlpha(Event *ev);
void Think() override;
void setOwner(Sentient* other);
Sentient* getOwner() const;
void Archive(Archiver& arc);
void setOwner(Sentient *other);
Sentient *getOwner() const;
private:
float nextRemoveTime;
int spawnRate;
float bounceFactor;
float spawnLife;
float scaleRate;
Vector velocity;
float spinRate;
Vector offset;
float scale;
float fadeIn;
float fadeDelay;
float maxAlpha;
int lastSpawnTime;
float nextRemoveTime;
int spawnRate;
float bounceFactor;
float spawnLife;
float scaleRate;
Vector velocity;
float spinRate;
Vector offset;
float scale;
float fadeIn;
float fadeDelay;
float maxAlpha;
int lastSpawnTime;
SafePtr<Sentient> owner;
};
+9 -1
View File
@@ -1681,6 +1681,10 @@ void VehicleTurretGun::EndRemoteControl()
m_iFiring = 0;
m_vTargetAngles = m_vLocalAngles;
// Added in OPM
// Clear the camera shake/jitter
m_fCurrViewJitter = 0;
//
// Added in OPM.
// The camera must be removed after ending the remote control.
@@ -2130,7 +2134,11 @@ void VehicleTurretGunTandem::SwitchToLinkedTurret()
} else {
pTurret = m_PrimaryTurret;
// Added in 2.30
m_PrimaryTurret->m_SwitchLabel.Execute(this, pTurret, NULL);
if (m_PrimaryTurret) {
// Fixed in OPM
// Check for primary turret before setting the switch label
m_PrimaryTurret->m_SwitchLabel.Execute(this, pTurret, NULL);
}
}
SetActiveTurret(pTurret);
+39 -9
View File
@@ -901,6 +901,16 @@ Event EV_Weapon_DoneAnimating
EV_NORMAL
);
Event EV_Weapon_GetPutaway
(
"putaway",
EV_DEFAULT,
NULL,
NULL,
"Returns whether or not the given weapon is being put away",
EV_GETTER
);
CLASS_DECLARATION(Item, Weapon, NULL) {
{&EV_SetAnim, &Weapon::SetWeaponAnimEvent },
{&EV_Item_Pickup, &Weapon::PickupWeapon },
@@ -1001,6 +1011,7 @@ CLASS_DECLARATION(Item, Weapon, NULL) {
// Added in OPM
//
{&EV_Weapon_DoneAnimating, &Weapon::DoneAnimating },
{&EV_Weapon_GetPutaway, &Weapon::EventGetPutaway },
{NULL, NULL }
};
@@ -1238,15 +1249,9 @@ void Weapon::Delete(void)
{
if (g_iInThinks) {
DetachGun();
if (owner) {
RemoveFromOwner();
}
PostEvent(EV_Remove, 0);
} else {
delete this;
}
Item::Delete();
}
//======================
@@ -1640,7 +1645,6 @@ void Weapon::GetMuzzlePosition(vec3_t position, vec3_t vBarrelPos, vec3_t forwar
int i;
owner = (Player *)this->owner.Pointer();
assert(owner);
// We should always have an owner
if (!owner) {
@@ -4629,12 +4633,38 @@ Listener *Weapon::GetScriptOwner(void)
return owner;
}
//======================
//Weapon::DoneAnimating
//======================
void Weapon::DoneAnimating(Event* ev) {
// Added in OPM
// Set to idle when done reloading
SetWeaponIdleAnim();
}
//======================
//Weapon::GetMaxFireMovementMult
//======================
void Weapon::EventGetPutaway(Event* ev) {
// Added in OPM
// Set to idle when done reloading
ev->AddInteger(GetPutaway());
}
//======================
//Weapon::GetMaxFireMovementMult
//======================
float Weapon::GetMaxFireMovementMult() const {
return m_fMaxFireMovement * m_fMovementSpeed;
}
//======================
//Weapon::GetMaxFireMovementMult
//======================
float Weapon::GetZoomMovement() const {
return m_fZoomMovement * m_fMovementSpeed;
}
//======================
//Weapon::GetMaxFireMovement
//======================
+3
View File
@@ -460,7 +460,10 @@ public:
firemode_t GetFireMode(void);
qboolean IsSemiAuto(void);
void DoneAnimating(Event *ev);
void EventGetPutaway(Event *ev);
float GetMaxFireMovementMult() const;
float GetZoomMovement() const;
float GetMaxFireMovement() const;
};
+1 -1
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.5)
cmake_minimum_required(VERSION 3.12)
include_directories("./common")
include_directories("./gcdkey")
+5 -5
View File
@@ -96,7 +96,7 @@ void gsDebugAssert (const char *szError,const char *szText, const char *szFi
// continues rendering
void _gsDebugAssert (const char *string)
{
printf(string);
printf("%s", string);
while(1)
{
@@ -118,7 +118,7 @@ void gsDebugAssert (const char *szError,const char *szText, const char *szFi
void _gsDebugAssert (const char *string)
{
scePrintf(string);
scePrintf("%s", string);
while(1);;
}
@@ -127,7 +127,7 @@ void gsDebugAssert (const char *szError,const char *szText, const char *szFi
#elif defined _MACOSX
void _gsDebugAssert (const char *string)
{
printf(string);
printf("%s", string);
while(1)
{
@@ -139,7 +139,7 @@ void gsDebugAssert (const char *szError,const char *szText, const char *szFi
#elif defined _LINUX
void _gsDebugAssert (const char *string)
{
printf(string);
printf("%s", string);
while(1)
{
@@ -170,7 +170,7 @@ void gsDebugAssert (const char *szError,const char *szText, const char *szFi
void _gsDebugAssert (const char *string)
{
printf(string);
printf("%s", string);
while(1);;
}
+7
View File
@@ -62,6 +62,9 @@ void CL_CharEvent( int key ) {
void CL_Disconnect() {
}
void CL_AbnormalDisconnect() {
}
void CL_MapLoading( qboolean flush, const char *pszMapName ) {
}
@@ -129,3 +132,7 @@ qboolean CL_FinishedIntro( void ) {
int R_CountTextureMemory() {
return 0;
}
qboolean CL_UseLargeLightmap(const char* mapName) {
return qtrue;
}
-1
View File
@@ -103,7 +103,6 @@ int success_pos;
%left TOKEN_DOUBLE_COLON
%left TOKEN_SEMICOLON
%right TOKEN_DOLLAR
%left TOKEN_NUMBER
%token TOKEN_INCREMENT TOKEN_DECREMENT TOKEN_PERIOD
+23 -10
View File
@@ -190,6 +190,8 @@ static bool UseField( void )
string ([^\\\"\r\n]|\\.)*
identifier [^\{\}\(\)\[\]\r\n\,:; \t]
nonexpr [0-9a-zA-Z_\"'?@#`\.\x80-\xff]
nonnumeric [a-zA-Z_\"'?@#`\x80-\xff]
alphanum [a-zA-Z0-9_]+
varname [a-zA-Z0-9_\"\$]+
@@ -205,7 +207,7 @@ varname [a-zA-Z0-9_\"\$]+
"//"[^\r\n]* { if( prev_yylex != TOKEN_EOL ) YYLEX( TOKEN_EOL ); }
<VARIABLES>"size" { BEGIN(INITIAL); YYLEX(TOKEN_SIZE); }
<VARIABLES>[ ]*\./([0-9]*[^0-9[:space:]]) { YYLEX(TOKEN_PERIOD); }
<VARIABLES>[ \t]*\./([0-9]*[^0-9[:space:]]) { YYLEX(TOKEN_PERIOD); }
<VARIABLES>\"{string}\" { BEGIN(INITIAL); TextEscapeValue(yytext + 1, strlen( yytext ) - 2 ); YYLEX(TOKEN_STRING); }
<VARIABLES>{varname} {
TextValue(yytext, strlen(yytext));
@@ -221,9 +223,15 @@ varname [a-zA-Z0-9_\"\$]+
unput(yytext[yyleng - 1]);
yyreducepos(1);
}
\"{string}\" { TextEscapeValue( yytext + 1, yyleng - 2 ); YYLEX( TOKEN_STRING ); }
\"{string}\"{nonexpr} {
BEGIN(IDENTIFIER);
yymore();
}
\"{string}\" { TextEscapeValue( yytext + 1, yyleng - 2 ); YYLEX( TOKEN_STRING ); }
"?" { YYLEX( TOKEN_TERNARY ); }
"if" { YYLEX( TOKEN_IF ); }
@@ -264,15 +272,15 @@ varname [a-zA-Z0-9_\"\$]+
">" { YYLEX( TOKEN_GREATER_THAN ); }
"<=" { YYLEX( TOKEN_LESS_THAN_OR_EQUAL ); }
">=" { YYLEX( TOKEN_GREATER_THAN_OR_EQUAL ); }
[ ]"-" { YYLEX( TOKEN_NEG ); }
[ \t]"-" { YYLEX( TOKEN_NEG ); }
"+" { YYLEX( TOKEN_PLUS ); }
"+=" { YYLEX( TOKEN_PLUS_EQUALS ); }
"++"|[ ]"++" { YYLEX( TOKEN_INCREMENT ); }
"-"|"-"[ ]|[ ]"-"[ ] { YYLEX( TOKEN_MINUS ); }
"++"|[ \t]"++" { YYLEX( TOKEN_INCREMENT ); }
"-"|"-"[ \t]|[ \t]"-"[ \t] { YYLEX( TOKEN_MINUS ); }
"-=" { YYLEX( TOKEN_MINUS_EQUALS ); }
[ ]"-=" { YYLEX( TOKEN_MINUS_EQUALS ); }
"--"|[ ]"--" { YYLEX( TOKEN_DECREMENT ); }
[ \t]"-=" { YYLEX( TOKEN_MINUS_EQUALS ); }
"--"|[ \t]"--" { YYLEX( TOKEN_DECREMENT ); }
"*" { YYLEX( TOKEN_MULTIPLY ); }
"*=" { YYLEX( TOKEN_MULTIPLY_EQUALS ); }
"/" { YYLEX( TOKEN_DIVIDE ); }
@@ -293,7 +301,6 @@ varname [a-zA-Z0-9_\"\$]+
"." { YYLEX( TOKEN_PERIOD ); }
"," { YYLEX( TOKEN_COMMA ); }
"#" { YYLEX( TOKEN_NUMBER ); }
"NULL" { YYLEX( TOKEN_NULL ); }
"NIL" { YYLEX( TOKEN_NIL ); }
@@ -312,11 +319,17 @@ varname [a-zA-Z0-9_\"\$]+
[\r\n]+ { if (prev_yylex != TOKEN_EOL) YYLEX(TOKEN_EOL); }
[ \t] { ; }
[0-9^`]+ {
[0-9]+ {
char* p = nullptr;
yylval.s.val.intValue = std::strtol(yytext, &p, 10);
YYLEX(TOKEN_INTEGER);
}
[0-9\.]+{nonnumeric} {
BEGIN(IDENTIFIER);
yymore();
}
[0-9\.]+|[0-9\.]+("e+"|"e-")+[0-9\.] {
char* p = nullptr;
yylval.s.val.floatValue = std::strtof(yytext, &p);
+22 -11
View File
@@ -1,4 +1,5 @@
cmake_minimum_required(VERSION 3.5)
cmake_minimum_required(VERSION 3.12)
project(qcommon)
if(${CMAKE_VERSION} VERSION_GREATER "3.12")
@@ -8,7 +9,7 @@ endif()
include("./q_version.cmake")
# Shared source files for modules
set(SOURCES_SHARED
set(SOURCES_SHARED_UBER
"${CMAKE_SOURCE_DIR}/code/qcommon/class.cpp"
"${CMAKE_SOURCE_DIR}/code/qcommon/con_set.cpp"
"${CMAKE_SOURCE_DIR}/code/qcommon/con_timer.cpp"
@@ -17,25 +18,35 @@ set(SOURCES_SHARED
"${CMAKE_SOURCE_DIR}/code/qcommon/lz77.cpp"
"${CMAKE_SOURCE_DIR}/code/qcommon/mem_blockalloc.cpp"
"${CMAKE_SOURCE_DIR}/code/qcommon/mem_tempalloc.cpp"
"${CMAKE_SOURCE_DIR}/code/qcommon/q_math.c"
"${CMAKE_SOURCE_DIR}/code/qcommon/q_shared.c"
"${CMAKE_SOURCE_DIR}/code/qcommon/script.cpp"
"${CMAKE_SOURCE_DIR}/code/qcommon/str.cpp"
"${CMAKE_SOURCE_DIR}/code/script/scriptexception.cpp"
"${CMAKE_SOURCE_DIR}/code/script/scriptvariable.cpp"
)
add_library(qcommon INTERFACE)
target_sources(qcommon INTERFACE ${SOURCES_SHARED})
add_library(qcommon_uber INTERFACE)
target_sources(qcommon_uber INTERFACE ${SOURCES_SHARED_UBER})
target_compile_features(qcommon_uber INTERFACE cxx_nullptr)
target_include_directories(qcommon_uber INTERFACE "../qcommon" "../script")
if(DEBUG_MEM_BLOCK)
target_compile_definitions(qcommon INTERFACE _DEBUG_MEMBLOCK=1)
target_compile_definitions(qcommon_uber INTERFACE _DEBUG_MEMBLOCK=1)
endif()
target_include_directories(qcommon INTERFACE "../qcommon" "../script")
target_compile_features(qcommon INTERFACE cxx_nullptr)
target_compile_features(qcommon INTERFACE c_variadic_macros)
target_link_libraries(qcommon INTERFACE qcommon_version)
set(SOURCES_SHARED
"${CMAKE_SOURCE_DIR}/code/qcommon/puff.c"
"${CMAKE_SOURCE_DIR}/code/qcommon/q_math.c"
"${CMAKE_SOURCE_DIR}/code/qcommon/q_shared.c"
)
add_library(qcommon_shared INTERFACE)
target_sources(qcommon_shared INTERFACE ${SOURCES_SHARED})
target_compile_features(qcommon_shared INTERFACE c_variadic_macros)
target_include_directories(qcommon_shared INTERFACE "../qcommon")
target_link_libraries(qcommon_shared INTERFACE qcommon_version)
add_library(qcommon INTERFACE)
target_link_libraries(qcommon INTERFACE qcommon_shared qcommon_uber)
# Source files for standalone executable
set(SOURCES_COMMON
+501 -604
View File
File diff suppressed because it is too large. Load diff
+5 -1
View File
@@ -766,6 +766,10 @@ static qboolean CM_ValidateFacet( facet_t *facet ) {
Vector4Copy( planes[ facet->surfacePlane ].plane, plane );
w = BaseWindingForPlane( plane, plane[3] );
for ( j = 0 ; j < facet->numBorders && w ; j++ ) {
if ( facet->borderPlanes[j] == -1 ) {
FreeWinding( w );
return qfalse;
}
Vector4Copy( planes[ facet->borderPlanes[j] ].plane, plane );
if ( !facet->borderInward[j] ) {
VectorSubtract( vec3_origin, plane, plane );
@@ -783,7 +787,7 @@ static qboolean CM_ValidateFacet( facet_t *facet ) {
FreeWinding( w );
for ( j = 0 ; j < 3 ; j++ ) {
if ( bounds[1][j] - bounds[0][j] > MAX_MAP_BOUNDS ) {
if ( bounds[1][j] - bounds[0][j] > MAP_SIZE ) {
return qfalse; // we must be missing a plane
}
}
+4 -1
View File
@@ -61,7 +61,10 @@ properly.
#define MAX_FACETS 1024
#define MAX_PATCH_PLANES 4096 // 2048 su44: increased for m1l2a
// Changed in OPM
// In OG it's 4096, however due to a tiny floating point difference
// between x86 and x64, more patch planes can appear in x64
#define MAX_PATCH_PLANES 6144
typedef struct {
float plane[4];
+6 -6
View File
@@ -160,8 +160,8 @@ void WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs)
vec_t v;
int i,j;
mins[0] = mins[1] = mins[2] = MAX_MAP_BOUNDS;
maxs[0] = maxs[1] = maxs[2] = -MAX_MAP_BOUNDS;
mins[0] = mins[1] = mins[2] = 99999;
maxs[0] = maxs[1] = maxs[2] = -99999;
for (i=0 ; i<w->numpoints ; i++)
{
@@ -208,7 +208,7 @@ winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist)
// find the major axis
max = -MAX_MAP_BOUNDS;
max = -MAP_SIZE;
x = -1;
for (i=0 ; i<3; i++)
{
@@ -242,8 +242,8 @@ winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist)
CrossProduct (vup, normal, vright);
VectorScale (vup, MAX_MAP_BOUNDS, vup);
VectorScale (vright, MAX_MAP_BOUNDS, vright);
VectorScale (vup, MAP_SIZE, vup);
VectorScale (vright, MAP_SIZE, vright);
// project a really big axis aligned box onto the plane
w = AllocWinding (4);
@@ -564,7 +564,7 @@ void CheckWinding (winding_t *w)
p1 = w->p[i];
for (j=0 ; j<3 ; j++)
if (p1[j] > MAX_MAP_BOUNDS || p1[j] < -MAX_MAP_BOUNDS)
if (p1[j] > MAP_SIZE || p1[j] < -MAP_SIZE)
Com_Error (ERR_DROP, "CheckFace: BUGUS_RANGE: %f",p1[j]);
j = i+1 == w->numpoints ? 0 : i+1;
+2 -2
View File
@@ -667,7 +667,7 @@ static void Cmd_TokenizeString2( const char *text_in, qboolean ignoreQuotes ) {
while ( 1 ) {
// skip whitespace
while ( *text && *text <= ' ' ) {
while ( *text && ( unsigned char )*text <= ' ' ) {
text++;
}
if ( !*text ) {
@@ -715,7 +715,7 @@ static void Cmd_TokenizeString2( const char *text_in, qboolean ignoreQuotes ) {
cmd_argc++;
// skip until whitespace, quote, or command
while ( *text > ' ' ) {
while ( ( unsigned char )*text > ' ' ) {
if ( !ignoreQuotes && text[0] == '"' ) {
break;
}
+68 -29
View File
@@ -419,30 +419,40 @@ void QDECL Com_Error( int code, const char *fmt, ... ) {
Cvar_Set("com_errorMessage", com_errorMessage);
if (code == ERR_DISCONNECT || code == ERR_SERVERDISCONNECT) {
CL_Disconnect();
CL_FlushMemory( );
if (com_cl_running && com_cl_running->integer) {
CL_AbnormalDisconnect();
CL_FlushMemory();
CL_StartHunkUsers(qfalse);
} else {
SV_Shutdown(va("Server disconnected: %s", com_errorMessage));
}
// make sure we can get at our local stuff
FS_PureServerSetLoadedPaks("", "");
com_errorEntered = qfalse;
longjmp (abortframe, -1);
} else if (code == ERR_DROP) {
Com_Printf ("********************\nERROR: %s\n********************\n", com_errorMessage);
SV_Shutdown (va("Server crashed: %s", com_errorMessage));
CL_Disconnect();
CL_FlushMemory( );
SV_Shutdown(va("Server crashed: %s", com_errorMessage));
#ifndef DEDICATED
if (com_cl_running && com_cl_running->integer) {
CL_AbnormalDisconnect();
CL_FlushMemory();
CL_StartHunkUsers(qfalse);
}
#endif
FS_PureServerSetLoadedPaks("", "");
com_errorEntered = qfalse;
longjmp (abortframe, -1);
} else if ( code == ERR_NEED_CD ) {
SV_Shutdown( "Server didn't have CD" );
if ( com_cl_running && com_cl_running->integer ) {
CL_Disconnect();
CL_FlushMemory( );
com_errorEntered = qfalse;
CL_CDDialog();
} else {
Com_Printf("Server didn't have CD\n" );
}
SV_Shutdown("Server didn't have CD");
if (com_cl_running && com_cl_running->integer) {
CL_Disconnect();
CL_FlushMemory();
com_errorEntered = qfalse;
CL_CDDialog();
} else {
Com_Printf("Server didn't have CD\n");
}
FS_PureServerSetLoadedPaks("", "");
longjmp (abortframe, -1);
} else {
@@ -1602,6 +1612,22 @@ static void Com_InitRand(void)
srand(time(NULL));
}
/*
=================
Com_ConfigExists
=================
*/
qboolean Com_ConfigExists(const char* configname) {
fileHandle_t handle = (fileHandle_t)0;
if (FS_FOpenFileRead(va("configs/%s", configname), &handle, qfalse, qfalse) == -1) {
return qfalse;
}
FS_FCloseFile(handle);
return qtrue;
}
/*
=================
Com_Init
@@ -1676,7 +1702,9 @@ void Com_Init( char *commandLine ) {
Cbuf_AddText( "exec menu.cfg\n" );
Cbuf_AddText ("exec newconfig.cfg\n");
// Removed in OPM
// Not relevant as there is no auto-configurator
//Cbuf_AddText ("exec newconfig.cfg\n");
cvar_global_force = qtrue;
Cbuf_Execute( 0 );
@@ -1689,27 +1717,33 @@ void Com_Init( char *commandLine ) {
config = Cvar_Get( "config", "omconfig.cfg", 0 );
if( strlen( config->string ) <= 1 )
if( strlen( config->string ) > 1 )
{
size_t len = strlen( config->string );
Q_strncpyz( configname, config->string, len >= sizeof( configname ) ? sizeof( configname ) : len );
COM_StripExtension( configname, configname, sizeof( configname ) );
Q_strcat( configname, sizeof( configname ), ".cfg" );
SaveRegistryInfo( 1, "config", configname, sizeof( configname ) );
}
else
{
long size = sizeof( configname );
LoadRegistryInfo(1, "config", configname, &size );
COM_DefaultExtension( configname, sizeof( configname ), ".cfg" );
}
else
{
size_t len = strlen( config->string );
strncpy( configname, config->string, len >= sizeof( configname ) ? sizeof( configname ) : len );
COM_StripExtension( configname, configname, sizeof( configname ) );
strcat( configname, ".cfg" );
SaveRegistryInfo( 1, "config", configname, sizeof( configname ) );
}
SaveRegistryInfo( 1, "config", configname, sizeof( configname ) );
Cvar_Set( "config", configname );
Com_Printf( "Config: %s\n", configname );
Cbuf_AddText( va( "exec configs/%s\n", configname ) );
if ( !Com_ConfigExists( configname )) {
Com_Printf( "The config file '%s' doesn't exist, using unnamedsoldier.cfg as a template\n", configname );
Cbuf_AddText( va( "exec configs/unnamedsoldier.cfg\n", configname ) );
} else {
Cbuf_AddText( va( "exec configs/%s\n", configname ) );
}
if( Com_SafeMode() )
{
@@ -1829,7 +1863,9 @@ void Com_Init( char *commandLine ) {
Sys_Init();
//Sys_InitPIDFile(FS_GetCurrentGameDir());
#ifdef NDEBUG
Sys_InitPIDFile(FS_GetCurrentGameDir());
#endif
// Pick a random port value
Com_RandomBytes((byte*)&qport, sizeof(int));
@@ -2370,11 +2406,14 @@ void Com_Shutdown (void) {
}
qboolean Com_SanitizeName( const char *pszOldName, char *pszNewName )
qboolean Com_SanitizeName( const char *pszOldName, char *pszNewName, size_t bufferSize )
{
int i;
qboolean bBadName = qfalse;
const char *p = pszOldName;
size_t maxLength;
maxLength = (bufferSize / sizeof(char)) - 1;
if( *pszOldName && *pszOldName <= ' ' )
{
@@ -2387,7 +2426,7 @@ qboolean Com_SanitizeName( const char *pszOldName, char *pszNewName )
}
i = 0;
for( i = 0; *p && *p >= ' '; p++, i++ )
for( i = 0; *p && *p >= ' ' && i < maxLength; p++, i++ )
{
if( *p == '~' || *p == '`' )
{
+13 -3
View File
@@ -2367,6 +2367,9 @@ char **FS_ListFilteredFiles( const char *path, const char *extension, const char
}
pathLength = strlen( path );
if ( path[pathLength-1] == '\\' || path[pathLength-1] == '/' ) {
pathLength--;
}
extensionLength = strlen( extension );
nfiles = 0;
FS_ReturnPath(path, zpath, &pathDepth);
@@ -2445,13 +2448,18 @@ char **FS_ListFilteredFiles( const char *path, const char *extension, const char
}
// unique the match
temp = pathLength;
if (pathLength) {
temp++; // include the '/'
}
if (bDirSearch) {
strcpy(zpath, name + pathLength);
zpath[length - pathLength - 1] = 0;
strcpy(zpath, name + temp);
zpath[length - temp - 1] = 0;
nfiles = FS_AddFileToList(zpath, list, nfiles);
}
else {
nfiles = FS_AddFileToList(name + pathLength, list, nfiles);
nfiles = FS_AddFileToList(name + temp, list, nfiles);
}
}
}
@@ -4004,7 +4012,9 @@ void FS_Restart( int checksumFeed ) {
// try to start up normally
FS_Startup(com_basegame->string);
#ifndef STANDALONE
FS_CheckPak0( );
#endif
// if we can't find default.cfg, assume that the paths are
// busted and error out now, rather than getting an unreadable
+10 -1
View File
@@ -73,7 +73,8 @@ EventQueueNode Event::EventQueue;
int DisableListenerNotify = 0;
bool Listener::EventSystemStarted = 0;
bool Listener::EventSystemStarted = false;
bool Listener::ProcessingEvents = false;
Event EV_Listener_CancelFor
(
@@ -575,6 +576,8 @@ void L_ProcessPendingEvents()
{
EventQueueNode *node;
Listener::ProcessingEvents = true;
int t = EVENT_msec;
while (!LL_Empty(&Event::EventQueue, next, prev)) {
Listener *obj;
@@ -600,6 +603,8 @@ void L_ProcessPendingEvents()
delete node;
}
Listener::ProcessingEvents = false;
}
void L_ShutdownEvents(void)
@@ -3007,6 +3012,8 @@ qboolean Listener::ProcessPendingEvents(void)
t = EVENT_msec;
Listener::ProcessingEvents = true;
event = Event::EventQueue.next;
while (event != &Event::EventQueue) {
Listener *obj;
@@ -3039,6 +3046,8 @@ qboolean Listener::ProcessPendingEvents(void)
}
}
Listener::ProcessingEvents = false;
return processedEvents;
}
Loaded 100 of 315 files, more files were not shown because too many files have changed in this diff. Show more