Compare commits

...
800 Commits
Author SHA1 Message Date
smallmodel 586da44c30 Remove what's Working documentation as everything is implemented 2024-11-24 18:03:15 +01:00
smallmodel 3956e03557 Use Ubuntu 22.04 as the runner OS for linux, to use a lower GLIBC version 2024-11-24 16:31:38 +01:00
ysdragon 8d0b7b77c6 Check for libc and link against execinfo lib for musl libc 2024-11-24 16:04:30 +01:00
ysdragon 23ad991743 Use nullptr instead 2024-11-24 16:04:30 +01:00
smallmodel 4493b2c42e Prevent integer overflow when interpolating verts 2024-11-24 15:58:18 +01:00
smallmodel 8b6b1597d7 Check for bHitPerson in MV0, MV1 and MV2
This checks if the sentient being hit is dead, and skip it when moving the vehicle so the vehicle doesn't get stuck for when a sentient is dying
2024-11-23 22:58:51 +01:00
smallmodel dddedba721 Update getting_started_running.md 2024-11-23 21:14:42 +01:00
smallmodel be34870a18 Copy the channel origin to the sound entity origin when loading
If the channel had a valid entity at the time of saving, make sure to restore the origin
2024-11-23 21:12:58 +01:00
smallmodel 4d4b9288c6 Don't update the streamed channel if the source status AL_INITIAL
This can occur when starting a new sound without playing it, which can happen when reloading the sound system while all sounds are paused (game paused)
2024-11-23 18:42:27 +01:00
smallmodel fc9be91124 Update OpenAL to 1.24.0
PowerPC will remain on 1.23.1 until the compile issue is resolved
2024-11-23 17:24:05 +01:00
smallmodel 0d24c620fb Update GCC to version 14 2024-11-23 16:08:25 +01:00
smallmodel 89140f775e Archive entities at the order they were created
This fixes an issue where turrets would Think() before the base they are mounted on (like tanks), which means the turret would set its origin before the base (tank) does. This issue also occurs on the original game
2024-11-23 15:19:05 +01:00
smallmodel de6718b511 Include a new section on how to obtain demos online 2024-11-22 21:03:54 +01:00
smallmodel 5c094f9c8a More clarity 2024-11-22 20:57:26 +01:00
smallmodel e2f4d8cd6b Use explicit constants when checking g_gametype 2024-11-22 19:44:53 +01:00
smallmodel 04da76167c Set the correct face mode for when the AI is facing a entity that allows AI to face
This fixes a mistake where AI would turn away from the player if the player approaches too much
2024-11-22 18:52:36 +01:00
smallmodel 90639cee36 Fix incorrect effect being spawned for MakeEffect CGM 2024-11-22 18:18:27 +01:00
smallmodel ecfdcca4d5 Update README 2024-11-21 22:07:11 +01:00
smallmodel 3790f057e1 Fix an infinite loop in BulletAttack
This would be caused by an entity that is inside another entity, like 2 actors at the same location
2024-11-21 20:41:57 +01:00
smallmodel 44d8adcfb0 Set the eyePos when loading from save
Server uses the playerState's vEyePos as the position, to add entities to snapshots, so make sure it's initialized before the next snapshot is sent
2024-11-21 20:26:12 +01:00
smallmodel 64f877ae80 Use the correct convention for installing the project
On Win32:
- Binaries and libraries will be installed by default in <PREFIX>/bin
- The prefix is set to `Program Files/openmohaa` by default

On Unix:
- Binaries and libraries will be installed by default in <PREFIX>/lib/openmohaa
- Shared data will be installed in <PREFIX>/share/applications, <PREFIX>/share/metainfo and <PREFIX>/share/icons
- The prefix is set to `/usr/local` by default
2024-11-21 19:49:43 +01:00
smallmodel 2ce8450a7e Use fprintf to stderr 2024-11-21 01:14:08 +01:00
smallmodel 7e7b3ab280 Fix PDB files mistakenly not included 2024-11-21 00:13:37 +01:00
smallmodel 48c2d026e6 Fix ActorPath not archiving path properly
It was mistakenly archiving the first path multiple times instead of the whole path array. This lead to AI strangely moving after loading from save
2024-11-20 23:32:37 +01:00
smallmodel ad825f5114 Reimplement noise functions 2024-11-20 23:02:22 +01:00
smallmodel 120a486aea Use CMake installation directory
This removes the use of the DESTINATION parameter from install() command and instead rely on default values.
The shared build action file was modified to package installed files in a single folder
2024-11-20 22:50:49 +01:00
Joey Riches 864cdf1fc6 CMake: Add uninstall target
https://gitlab.kitware.com/cmake/community/-/wikis/FAQ#can-i-do-make-uninstall-with-cmake

Useful when for testing system-wide installation with linux
2024-11-20 18:01:30 +01:00
Joey Riches f1c12e0649 misc: Add linux assets
Add a .desktop file, this is used by application launchers in order to
find and execute applications, this should be installed to
`/usr/share/applications/org.openmoh.openmohaa.desktop`.

Add appstream metainfo, this provides metainfo that is used by Software
Centers for discoverability, this should be installed to
`/usr/share/metainfo/org.openmoh.openmohaa.metainfo.xml`.

This will open the door to getting OpenMoHAA packaged up by various
linux distros.
2024-11-20 16:40:01 +01:00
smallmodel 58d8a73269 Don't abort() on interrupt or on program termination 2024-11-20 12:46:04 +01:00
smallmodel c788d57c52 Use abort() rather than doing a segfault 2024-11-19 23:15:01 +01:00
smallmodel 50eda4156a Don't remove the weapon if it has no start ammo
Instead, prevent sentients from picking up weapons if they get no ammo from it and they already have that weapon. Instead, just let the weapon be picked up as a new weapon
2024-11-19 22:44:04 +01:00
smallmodel 1e609a4b2f Ignore bullet tracers in 1.11 and below
Before 2.0, the tracer frequency is set on almost all weapons. This has some artifacts on multiplayer, the tracer doesn't look adjusted in first-person view
2024-11-19 22:24:50 +01:00
smallmodel a0e2162dd7 Fix 1.11 servers filtered out 2024-11-19 22:16:55 +01:00
smallmodel 01dfbcdbfe Properly print the backtrace and generate a core dump on both Windows/Unix 2024-11-19 21:45:49 +01:00
smallmodel 862af012cb Fix infinite loop while getting the number of lines in objectives 2024-11-19 20:26:23 +01:00
smallmodel d83374d38c Set the default compass scale to 0.5 for the base game 2024-11-19 19:44:55 +01:00
smallmodel 05e14f6364 Adjust the objectives menu accordingly depending on the game message box which depends on the compass scale 2024-11-19 19:41:46 +01:00
smallmodel 6bc621462c Use CL_FontStringWidth instead of uie.FontStringWidth 2024-11-19 19:17:16 +01:00
smallmodel acb08b89f7 Fix constant for screenOrg 2024-11-18 22:03:58 +01:00
smallmodel 2107523eda Use MAX_CLIENTS - 1 instead of 63 2024-11-18 21:57:02 +01:00
smallmodel 2662174eba Fix radar clients not blinking when talking 2024-11-18 21:22:50 +01:00
smallmodel 59d03ff6f0 Return a virtual scale with the correct ratio if scale variable is set
This prevents the widget from being stretched out on widescreen, currently only the compass uses scalecvar
2024-11-18 21:13:43 +01:00
smallmodel 05d304dfc3 Set ignoredFiles only if ignore_files was specified
This fixes a crash that would occur due to a NULL string
2024-11-18 20:38:03 +01:00
smallmodel 614ed6e632 Use the vartree for flags, rather than copying the flags to a signed int value 2024-11-18 19:47:54 +01:00
smallmodel eb938c872d Make varnode endian-independant
This fixes terrain rendering incorrectly on big-endian architectures by using bit operation. The `flags` field in the union always matched the first byte of the variance float value instead of the least significant byte
2024-11-18 19:44:00 +01:00
smallmodel 46e1aa979b Use ARRAY_LEN instead of sizeof 2024-11-18 18:46:14 +01:00
smallmodel ec5acb4d98 Fix bad glDepthRange 2024-11-17 22:59:49 +01:00
smallmodel b237222761 Update features.md 2024-11-17 22:27:20 +01:00
smallmodel 652df1a5af Prevent players with SVF_NOCLIENT to use objects 2024-11-17 22:10:03 +01:00
smallmodel 69621335db Put the target extension version in the version string 2024-11-17 21:31:45 +01:00
smallmodel 7b58fbec8a Fix comparison operator for char 2024-11-17 21:25:54 +01:00
smallmodel aeb8aa8e55 Don't send a voice chat message if the entity is not sent to clients 2024-11-17 20:28:03 +01:00
smallmodel e74e113199 Fix voice message always being sent to enemies in team message 2024-11-17 20:26:40 +01:00
smallmodel 953091cdc8 Move and rename macros to snd_local_new.h 2024-11-17 19:11:59 +01:00
smallmodel 5819145af8 Synchronize the entity time with the channel time when loading
This prevents the channel from stopping immediately during respatialization, the entity time may be updated quite some time after loading
2024-11-17 18:46:21 +01:00
smallmodel 154464cda1 Set the server huddraw elements on single-player mode
This fixes huddraw elements not being archived properly when the map starts
2024-11-17 18:26:00 +01:00
smallmodel 2342f08a79 Print the new damage when g_showbullettrace is turned on 2024-11-17 18:02:57 +01:00
smallmodel 16711a33ef Fix bulletthroughwood and bulletthroughmetal not being archived correctly
This caused issues on some single-player maps where bullet would go through walls
2024-11-17 18:02:35 +01:00
smallmodel cea0d95fee Set the pitch to default when setting a new SFX
This fixes channels having an incorrect pitch when starting the sound under some circumstances
2024-11-17 17:12:36 +01:00
smallmodel 989ec9574c Fix too high farVal for glDepthRange 2024-11-17 16:46:21 +01:00
smallmodel b0b82f0252 Fix incorrect start trace for Actor::DontFaceWall()
This fixes AI not turning from wall
2024-11-17 16:36:45 +01:00
smallmodel 80ddba1013 Fix constant string for "officer" disguise type
This fixes the officer think not working at all
2024-11-17 16:36:19 +01:00
smallmodel 23f776d3c7 Fix typo 2024-11-17 14:32:44 +01:00
smallmodel 880acf9120 Make com_target_game and com_target_demo write-protected (can only be set at startup) 2024-11-17 14:28:00 +01:00
smallmodel 598110477e Archive the m_bAlwaysAway variable 2024-11-16 22:35:55 +01:00
smallmodel ffdfbc3c7d Fix the bullet stopping after the first entity 2024-11-16 21:57:12 +01:00
smallmodel a7dc8b3493 Don't archive r_fastsky variable
This prevents this setting to be altered by mods forever
2024-11-16 21:36:56 +01:00
smallmodel 67d8cad64d Allow sound files from OS disk in pure mode 2024-11-16 21:34:19 +01:00
smallmodel b007842fb4 Fix pure checksums not matching the server 2024-11-16 21:32:53 +01:00
smallmodel 2c4b5fc9ba Rename the type variable to currentType so it doesn't take precedence over the type member
This fixes an issue where it was the type variable that was being set, rather than the type member
2024-11-16 20:07:26 +01:00
smallmodel e96a3f4f59 Use c_str() instead of accessing m_data
c_str() will always return a valid string even if empty
2024-11-16 19:27:48 +01:00
smallmodel 8eded28efc Fix the typename in the error message for incompatible types 2024-11-16 19:22:01 +01:00
smallmodel b68bb4cee7 Fix integer overflow in wait command that would cause infinite loop in stock scripts
It was causing a rare infinite loop in anim/stand.scr where it waits for 9999999 if the actor is unarmed and medic
2024-11-16 19:10:26 +01:00
smallmodel 824cfd789c Properly save and restore entity's children solidity 2024-11-16 18:19:45 +01:00
smallmodel a0b80a9096 Fix string not usable for targetname 2024-11-16 18:17:19 +01:00
smallmodel 857d25825b Remove tmvolume like other commands when shutting down OpenAL 2024-11-16 16:57:59 +01:00
smallmodel 735832829d Don't drop the weapon if it has no ammo 2024-11-16 00:29:44 +01:00
smallmodel 5703161166 Fix grenade dropping no ammo
This makes the weapon drop at least 1 ammo clip
2024-11-16 00:29:13 +01:00
smallmodel d85455e9ec Don't export referenced paks if download is disabled on the server 2024-11-15 21:00:20 +01:00
smallmodel f6c9de4286 Use com_basegame instead of BASEGAME macro 2024-11-15 20:58:46 +01:00
smallmodel a598cbf0dc Update running documentation 2024-11-14 20:25:26 +01:00
smallmodel 67b285924c Prefix OpenAL with debug prints 2024-11-14 19:49:22 +01:00
smallmodel 0c206beb45 Expect a SimpleEntity rather than an Entity
The specified path in FollowPath can be a Waypoint which is a subclass of SimpleEntity
2024-11-14 19:46:16 +01:00
smallmodel 9a6472210c Use a separate user-data location for the demo version 2024-11-13 23:15:31 +01:00
smallmodel 7576d1241d Add hardware requirements for non-x86 architectures 2024-11-13 21:49:43 +01:00
smallmodel fb2f3bddaa Fix the intermission screen (mission failed/success) not hiding immediately on the base game 2024-11-13 20:01:05 +01:00
smallmodel 96ca9c20e4 Rework fade sequence and make it work 2024-11-13 19:40:31 +01:00
smallmodel d01fa33e46 Use 0.31 for Breakthrough demo
This makes the Breakthrough demo client compatible with Breakthrough demo servers
2024-11-13 00:07:07 +01:00
smallmodel ab84a6ea58 Add support for the demo version of the game
This allows the demo version of the game to be used, both for playing on demo servers, or for hosting a demo server
2024-11-12 23:09:37 +01:00
smallmodel b0a683c188 Don't localize if the localization hasn't been initialized 2024-11-12 23:09:32 +01:00
smallmodel e5ef61c5d2 Abort decal loading if a shader cannot be found while loading 2024-11-12 23:00:38 +01:00
smallmodel 02af9a763d Better support for older BSP versions 2024-11-12 20:56:26 +01:00
smallmodel 132903a843 Use different fields for protocol version 6 and 8 2024-11-12 20:56:02 +01:00
smallmodel fe862badf6 Add printdeathmsg from moh 2.0 and above 2024-11-12 18:37:17 +01:00
smallmodel 1ad5964c2f Implement stoploopsound from moh 2.0 and above 2024-11-12 18:21:24 +01:00
smallmodel 851a16e18c Fix the bullet tracer scale 2024-11-12 00:09:29 +01:00
smallmodel 763a79cb74 Fix angle when in turret 2024-11-11 23:48:39 +01:00
smallmodel c9ccb0efaf Check for Sentient instead of Player 2024-11-11 23:48:19 +01:00
smallmodel 9e060d11b6 Allow user-created variables 2024-11-11 20:58:37 +01:00
smallmodel 50fdbaf152 Use CVAR_RESETSTRING instead of CVAR_SERVER_CREATED 2024-11-11 20:36:03 +01:00
smallmodel ccca958ec5 Get the grid1 on each iteration in case it has been reallocated
This fixes a very rare crash that would occur when loading a world map
2024-11-11 19:48:49 +01:00
smallmodel dd37ba2741 Properly archive clients 2024-11-11 19:06:05 +01:00
smallmodel 81b49236a5 Use proper types for playerState_t structure 2024-11-11 19:00:36 +01:00
smallmodel 894e1d7d66 Properly cleanup the existing owner from targets 2024-11-11 18:37:29 +01:00
smallmodel 9d83d58756 Create path only if the target is a SplinePath 2024-11-11 18:28:56 +01:00
smallmodel 54b9a0c340 Fix incorrect SKB offsets 2024-11-11 18:28:42 +01:00
smallmodel 2cf380c15d Add scale field for skel header 2024-11-11 18:12:50 +01:00
smallmodel d400d8927d Fix archive data between 64-bit and 32-bit architectures 2024-11-11 17:52:24 +01:00
smallmodel fef30ff3d5 Clear the splinepath entity flag when destroying 2024-11-11 17:35:41 +01:00
smallmodel 4023c9d863 Fix isOpen event, must return true if it's not closed 2024-11-11 16:40:43 +01:00
smallmodel 7bcb91bbb5 Don't allocate the mark if the number of allocated polys is insufficient
There was a very rare occurrence where it would hang trying to find a free mark poly, when the number of specified polys was more than the number of allocated polys. This bug also occurs in the original game
2024-11-11 15:14:20 +01:00
smallmodel 5edee7d12e Add tmvolume from Spearhead and Breakthrough 2024-11-11 14:24:57 +01:00
smallmodel 51c7e27bc1 Fix the switch label not being archived 2024-11-11 14:05:14 +01:00
smallmodel f400190531 Fix the switch label called incorrectly for VehicleTurretGunTandem 2024-11-11 14:04:51 +01:00
smallmodel 8732e368b6 Clear the last command angles when loading 2024-11-11 13:49:33 +01:00
smallmodel 7e4da514f6 Update features.md 2024-11-10 22:14:03 +01:00
smallmodel 9a55939b42 Fix weapon selection 2024-11-10 22:10:34 +01:00
smallmodel cd89d2c0b4 Don't execute reloadmap if the server is not running 2024-11-10 22:10:24 +01:00
smallmodel 661b08a7fa Don't set g_shownpc to 1 when developer is set 2024-11-10 21:47:58 +01:00
smallmodel d27f928e2d Update features.md 2024-11-10 20:58:46 +01:00
smallmodel 079555e43a Fix VehicleTurretGun sound 2024-11-10 19:29:33 +01:00
smallmodel fcc4e94655 Continue traveling if the bullet trace goes backwards 2024-11-10 19:02:59 +01:00
smallmodel c5721f8a2c Fix variable name starting with multiple consecutive numbers 2024-11-10 17:55:54 +01:00
smallmodel e5acee55ea Restore old behavior of "angle" event of the ScriptOrigin class on previous versions (below 2.30) 2024-11-10 17:42:37 +01:00
smallmodel d3f3b9b51c Don't allow lean in single-player in the base game 2024-11-10 17:01:56 +01:00
smallmodel 48e9db8966 Don't reload the state table when archiving
This fixes multiple issues where the player could end on an incorrect move type after loading from save, like getting out of the ladder
2024-11-10 16:50:23 +01:00
smallmodel 67486f1e49 Clear the player velocity on intermission 2024-11-10 16:17:03 +01:00
smallmodel 923a6de394 Clear the velocity when both walking and frozen 2024-11-10 16:07:55 +01:00
smallmodel de0e4954f8 Call G_MoveClientToIntermission() instead of setting the immobile flag 2024-11-10 15:53:06 +01:00
smallmodel 1ef1bad9ae Add network profiling tool from Spearhead and Breakthrough
Profiling can be enabled with `cl_netprofile` and `sv_netprofile`, the overlay can be shown using `cl_netprofileoverlay` and `sv_netprofileoverlay` and the server can dump network profile using the `netprofiledump` command
2024-11-09 21:38:16 +01:00
smallmodel 23a035e2ca Use a default value for maxlen and bVirtualScale for Print 2024-11-09 19:38:15 +01:00
smallmodel ec73268f94 Reorder methods 2024-11-09 19:21:24 +01:00
smallmodel 2b06cc690e Add reloadmap server command from Breakthrough 2024-11-09 16:03:08 +01:00
smallmodel 7afc2427ac Finish DrawBoundingBox() entity implementation 2024-11-09 15:51:27 +01:00
smallmodel f3bbcba4f0 Set blue horizontal lines for debug bbox 2024-11-09 15:16:46 +01:00
smallmodel 0dca08a66a Fix actor position on a turret 2024-11-09 14:35:52 +01:00
smallmodel f646151ce2 Set medium difficulty by default 2024-11-09 13:27:24 +01:00
smallmodel 2e0e5db260 Implement bindweap 2024-11-09 00:27:42 +01:00
smallmodel f34aad03cd Add script owner implementation 2024-11-09 00:18:59 +01:00
smallmodel 332d209f62 Check if the turret's vehicle entity is valid 2024-11-08 22:31:49 +01:00
smallmodel 888e35466b Drop error if the Script cannot load the file 2024-11-08 22:28:33 +01:00
smallmodel 1f69fce10e Don't check for CONTENTS_BBOX on the base game for large bullets passing through entities
Some mods have tanks with mounted turrets and this would cause issues as the bullet would hit the tank instead
2024-11-08 22:06:51 +01:00
smallmodel ac3eb58671 Return 4 from getconnstate even if it's deprecated 2024-11-08 21:46:25 +01:00
smallmodel 14f3e2faf9 Add a comment about driver solidity 2024-11-08 21:26:23 +01:00
smallmodel a528e916c2 Add the owner when starting a thread from trigger_multipleall if the activator is a projectile 2024-11-08 21:26:09 +01:00
smallmodel e6f83bc1d6 Fix the exit position for the base game 2024-11-08 20:46:45 +01:00
smallmodel 841a8d2b4a Remove clientState_t from g_local.h (shouldn't be defined here) 2024-11-08 20:37:22 +01:00
smallmodel a51c250a31 Add ScriptDeprecated macros 2024-11-08 19:33:15 +01:00
smallmodel c2291e92c4 Add Anim_AngularDelta 2024-11-08 19:32:53 +01:00
smallmodel b8cc3313b1 Check for valid tiki in PF functions 2024-11-08 19:26:37 +01:00
smallmodel d1fca3e499 Check for valid skeletor 2024-11-08 19:24:07 +01:00
smallmodel 66b882346f Clear the animation delta when the animation is invalid 2024-11-08 19:13:56 +01:00
smallmodel b38fedb18c Make the vehicle path drive from TurretMove
This fixes the issue where the AB41 can't be controlled
2024-11-07 20:23:24 +01:00
smallmodel e6559c6ae6 Fire the turret only when attackleft is pressed 2024-11-07 20:02:49 +01:00
smallmodel 772aad79d7 Disable cubemap-based lighting due to rendering artifacts/bugs occurring 2024-11-07 19:37:12 +01:00
smallmodel 3e84dbe6ac Initialize skipFade 2024-11-06 18:53:43 +01:00
smallmodel 381f2b02f5 Add a paragraph about which release should be downloaded 2024-11-05 22:53:54 +01:00
smallmodel f347102ecb Add the skipFade parameter in bsptransition so the fade can be skipped
Useful for scripts that are using fadeout during cinematics and then transitioning to the nextmap, like in e2l2 where vehicles explode at the end of the mission
2024-11-05 22:37:33 +01:00
smallmodel f5d2fdbcad Return an empty string if the channel is neither playing nor paused
It was only checking if the channel was playing. This was an issue because, in the main menu the music is paused, which means saving from main menu would not save the music filename
2024-11-05 22:16:15 +01:00
smallmodel ab037f1890 Properly center the window 2024-11-05 22:03:43 +01:00
smallmodel a933c78d93 Explosions must not kill the window immediately 2024-11-05 22:02:30 +01:00
smallmodel d08f539e6d Correctly initialize the window object 2024-11-05 22:02:08 +01:00
smallmodel caea6e6bba Return a reference to a const str for the result of Target() 2024-11-05 21:58:19 +01:00
smallmodel 6970e2d00c Properly check entity sight against passOwnerNum 2024-11-05 21:48:43 +01:00
smallmodel af084542c4 Don't set the leadside 2024-11-05 21:48:14 +01:00
smallmodel 9f728580b6 Fix Y normal for the output color from cube being mistakenly used twice
This improves the overall lighting from cubemap
2024-11-05 20:31:56 +01:00
smallmodel c25d0b668a Only check if m_bVisible is non-zero 2024-11-05 20:30:30 +01:00
smallmodel 1e29fd7d2b Refactor SetScript/SetThread 2024-11-05 19:52:13 +01:00
smallmodel 67f822d492 Process label of type 'none'
A none variable should be considered valid, it will just clear the label
2024-11-05 18:43:28 +01:00
smallmodel effbbd6c62 Support long subtitles 2024-11-05 01:14:21 +01:00
smallmodel db802d1a4c Update the running documentation 2024-11-04 22:56:06 +01:00
smallmodel fba40370af Only create launchers for the standalone game 2024-11-04 22:52:49 +01:00
smallmodel fc0ca18632 Add missing QUAKED comments 2024-11-04 21:32:16 +01:00
smallmodel 059b0ba34f Override respondTo method for TriggerEntity
This makes TriggerEntity respond to any object that is a subclass of Entity. This is useful for scripts wanting script_model to touch triggers for cinematic purposes (for example, the bike crash gag at the end of e2l2)
2024-11-04 21:22:09 +01:00
smallmodel e833b08a8e Fix G_GetAngle returning the wrong angle (was flipped) 2024-11-04 20:37:28 +01:00
smallmodel afc431c413 Add a basic launcher 2024-11-04 01:00:53 +01:00
smallmodel 81e407a924 Add EXE_EXT 2024-11-03 21:45:27 +01:00
smallmodel 1f232efdf3 Add the push velocity when jumping from a valid ground entity 2024-11-03 20:34:49 +01:00
smallmodel 94e1830895 Don't jump when on top of another sentient 2024-11-03 20:32:17 +01:00
smallmodel 406f804ef8 Don't jump when inside a vehicle or turret 2024-11-03 20:30:37 +01:00
smallmodel 437f20dfb9 Set the view angles when archiving 2024-11-03 20:21:01 +01:00
smallmodel ff4438bce9 Properly load the statemap file and get the pain conditions when archiving 2024-11-03 20:12:14 +01:00
smallmodel 5cb343730b Rename Conditions to m_conditions 2024-11-03 20:06:31 +01:00
smallmodel dacaaa2cef Add missing variables from archive 2024-11-03 20:02:55 +01:00
smallmodel 2e6e20cf09 Set the m_bHasJumped value when jumping 2024-11-03 20:01:21 +01:00
smallmodel 2da379bade Fix typo for nodropweapons 2024-11-03 19:30:56 +01:00
smallmodel cf8f755f6c Make comment more clear 2024-11-03 19:23:11 +01:00
smallmodel 8114003c84 Add screenshot/levelshot allowed stuff commands 2024-11-03 18:54:34 +01:00
smallmodel bb47ba468c Fix game.skill and game.detail missing getters 2024-11-03 18:51:27 +01:00
smallmodel b97c47ab32 Cast to clock_t before left-shift 2024-11-03 18:40:18 +01:00
smallmodel 9042ea320c Refactor UI_RegisterLoadResource 2024-11-03 18:38:12 +01:00
smallmodel 98e725ef7b Fix EV_StatsUpdater_UpdateStats missing parameter declaration 2024-11-03 18:28:00 +01:00
smallmodel 05b2d3529e Implement UI_EndLoadResource 2024-11-03 18:27:41 +01:00
smallmodel 00dbc74269 Use MAX_WEAPON_ANIM_SLOTS instead of a constant 2024-11-03 15:36:55 +01:00
smallmodel 8addeedf5e Fix event parameters being incorrectly archived 2024-11-03 15:33:14 +01:00
smallmodel bc834b021c Use and draw the marker material when specified
This is used by the fuse stopwatch hud
2024-11-03 15:09:47 +01:00
smallmodel 6bac4bd57a Add assertions to check for valid squad mates 2024-11-03 15:09:27 +01:00
smallmodel 51324aa8e9 Archive the ProjectileTarget ID
The ID was missing during save, this caused issues with projectile generators when looking for a local target
2024-11-03 01:51:17 +01:00
smallmodel 7d1d92980a Disable the charge life when set to 0 2024-11-03 01:40:34 +01:00
smallmodel 3d42197f50 Initialize the minlife field 2024-11-03 01:26:30 +01:00
smallmodel 8a774c02dc Call G_BeginIntermission() instead of G_MissionFailed() when calling missionfailed 2024-11-03 00:41:26 +01:00
smallmodel a644e8a09c Check for GT_SINGLE_PLAYER instead of 0 2024-11-03 00:40:59 +01:00
smallmodel 6f51427c7c Add a function to count the number of valid clients 2024-11-03 00:34:33 +01:00
smallmodel 62bcf58d83 Call G_RestartLevelWithDelay instead in G_MissionFailed 2024-11-03 00:33:33 +01:00
smallmodel f40f206161 Don't add the owner velocity by default
This fixes an issue where AI would throw grenades incorrectly
2024-11-03 00:21:27 +01:00
smallmodel 1235f42143 Set the grenade mode when tossing a grenade with the specified speed 2024-11-03 00:20:47 +01:00
smallmodel 1016bfa1ad Fix calcgrenadetoss2 not pointing to the correct method 2024-11-03 00:19:31 +01:00
smallmodel f9ce111784 Set the targetname for projectiles 2024-11-02 22:38:45 +01:00
smallmodel 4c057faf73 Add a newline for warnings 2024-11-02 21:51:19 +01:00
smallmodel 4f16179c09 getmins/getmaxs are getters instead of returns 2024-11-02 21:46:55 +01:00
smallmodel 6991c9f9f7 Fix save comment not having the proper string 2024-11-02 21:22:24 +01:00
smallmodel 6e6dac0b74 Proper formatting 2024-11-02 20:56:32 +01:00
smallmodel 23f9c1a1e6 Only set the effect angles from the supplied angles if the spawnthing doesn't have angle set 2024-11-02 20:14:30 +01:00
smallmodel e4b2c863d8 Fix angles not being set correctly from the base 2024-11-02 20:13:23 +01:00
smallmodel ae16994289 Fix amplitude mistakenly being set instead of the base 2024-11-02 19:46:32 +01:00
smallmodel b8b17bb0c9 Implement VSS wind 2024-11-02 19:12:09 +01:00
smallmodel 3098fc98d3 Don't change the velocity for VSS, this was a mistake 2024-11-02 19:01:05 +01:00
smallmodel f3ecfd04da Use macro flags rather than constant values 2024-11-02 18:41:56 +01:00
smallmodel 0796fab24b Fix VSS sources not lerping at all 2024-11-02 18:06:56 +01:00
smallmodel 0fda31b430 Fix radial velocity/circle effects not properly applying 2024-11-02 17:52:33 +01:00
smallmodel 84a2b4be76 Use cg_effect_physicsrate instead of a constant value 2024-11-02 17:51:44 +01:00
smallmodel 5269fbb1fa Don't set the accel flag for swarm FX 2024-11-02 17:26:08 +01:00
smallmodel f23dfa091e Fix wrong flag used for checking for PMF_NO_HUD 2024-11-02 13:48:03 +01:00
smallmodel 32c3964474 Fix the source line having the entire file 2024-11-01 00:11:09 +01:00
smallmodel 6ff92f0a7e Process the ubersound folder differently depending on the target version
- On 1.11 and below, the ubersound folder is parsed either only in dedicated server mode or in client-only mode
- On 2.0 and above, alias are cleared and the ubersound folder is always parsed in multiplayer on both client and server
2024-10-31 23:57:18 +01:00
smallmodel c795b2390e Add a ScriptMaster constructor 2024-10-31 23:55:12 +01:00
smallmodel ce7005103c Handle the case where a vector is given for the face command 2024-10-31 23:51:36 +01:00
smallmodel 1a18878f26 Parse unary operators last when calling events 2024-10-31 22:16:20 +01:00
smallmodel 1e036a7689 Clear the torso and legs state when the movement type is set to portable turret 2024-10-31 19:49:05 +01:00
smallmodel 858b27b809 Handle the case where the legs or the torso state is NULL 2024-10-31 19:48:30 +01:00
smallmodel b4841a878b Only set the first found mark time and alpha fade 2024-10-31 19:37:42 +01:00
smallmodel 4565b6a9a8 Add cg_addhud and cg_removehud as whitelisted stuff commands 2024-10-31 01:45:37 +01:00
smallmodel 9ffb407d11 Fix incorrect/uninitialized token returned when there is a macro 2024-10-31 01:31:41 +01:00
smallmodel 0f3ffa267a Parse const array elements properly 2024-10-31 01:22:38 +01:00
smallmodel 74c8aa95f5 Properly ignore single-digits 2024-10-30 23:21:14 +01:00
smallmodel 4853235d86 Don't parse the token as a variable if the identifier only contains number
This fixes an issue where floats would be parsed as a variable after brackets
2024-10-30 22:42:55 +01:00
smallmodel 0d01ea939d Fix whole script file being printed sometimes on error 2024-10-30 21:25:15 +01:00
smallmodel 5ba6c006c2 Fix compile error 2024-10-30 00:23:42 +01:00
smallmodel 22e7d1e2e4 Only put animation definitions that exist, rather than setting a NULL animation definition
This fixes issues when searching animations by name
2024-10-29 22:27:22 +01:00
smallmodel c650af7b55 Fix stack corruption due to an improper assignment to the alias 2024-10-29 21:37:31 +01:00
smallmodel 2ce5e498ab Use CurrentScriptThread() when getting the current script class
So if the current thread is NULL, it will properly throw an exception
2024-10-29 21:11:44 +01:00
smallmodel d3212c55a0 Properly parse and cache ubersounds, and don't cache resources that must be always loaded to avoid filling up sound indexes 2024-10-29 21:02:16 +01:00
smallmodel becf9f5d8c Cache the source position to improve the source search time
This greatly reduces the time to compile big scripts
2024-10-29 20:26:51 +01:00
smallmodel 9cd8133068 Fix the directory prefix when using filters for FS_ListFilteredFiles 2024-10-29 20:25:25 +01:00
smallmodel 48fa5c0ce6 Parse all scr files inside the ubersound folder 2024-10-28 23:29:04 +01:00
smallmodel 6fc7199719 Register server sounds in multiplayer 2024-10-28 23:28:05 +01:00
smallmodel 9e04f94625 Check if the entity is valid after processing pending events during spawn 2024-10-28 23:14:46 +01:00
smallmodel c9b844b9ea Count the number of loaded anims and don't return a valid animation definition if there are no loaded animations 2024-10-28 22:57:52 +01:00
smallmodel 497058d7f4 Make the driver nonsolid while moving 2024-10-28 22:30:52 +01:00
smallmodel a509dd4692 Fix vehicle exit position when targeting the base game
The base game always uses, when specified, the exit position
2024-10-28 22:25:49 +01:00
smallmodel 8fdfffab36 Keep the mouse cursor position when the client disconnects 2024-10-28 21:13:47 +01:00
smallmodel aa118bceb3 Set the door speed based on the door type 2024-10-28 20:59:58 +01:00
smallmodel 4da50a78d5 Merge pull request #483 from smallmodel/marks_fix
Fix mark fragments being randomly culled or missing, especially on moving brush models
2024-10-28 20:59:28 +01:00
smallmodel 4d27a6daa3 Fix incorrect vert dist 2024-10-28 20:55:03 +01:00
smallmodel b6f8997a01 Make the mark object local to the entity 2024-10-28 20:47:01 +01:00
smallmodel 568efd4742 Fix the link to the build branch 2024-10-28 19:05:16 +01:00
smallmodel bf68808eae Set the skel index for each updated entity so poses only update when needed
This fixes poses being updated even if they don't need update (no frame changed), which resulted in some performance loss and some rare accuracy issues when AI fire weapons
2024-10-28 00:55:37 +01:00
smallmodel 5cbd2dd988 Use true/false rather than qtrue/qfalse 2024-10-28 00:45:21 +01:00
smallmodel 92b4ae2702 Use ANIM_WEIGHT_NONE instead of 0 2024-10-27 22:16:04 +01:00
smallmodel a8cdf0b5ad Don't update the upper animation if the think state is attack/grenade/killed/pain 2024-10-27 21:48:13 +01:00
smallmodel e8dfa0206b Use a macro constant for movement/action skan blend frames 2024-10-27 21:39:16 +01:00
smallmodel afe1ba47cf Decrease the time tolerance between frames to make animations smoother 2024-10-27 19:37:56 +01:00
smallmodel 2afa9adceb Add a link to mp-navigation for bots 2024-10-27 18:19:58 +01:00
smallmodel ef32200c8d Target older macOS versions 2024-10-27 17:45:23 +01:00
smallmodel dae7795478 Add NDEBUG compile definition on non-debug builds 2024-10-27 17:45:20 +01:00
smallmodel 7c96b68623 Specify the home directory location for macOS 2024-10-27 15:16:01 +01:00
smallmodel 558e69dba8 Archive the vehicle name
This was missing and this allows the torso state to the modheight to set the bounding box height. Before that, it did not recognize the turret so the modheight was still set to stand. It caused issues when trying to get out a vehicle turret, like the flak88 in e1l1 (the player wasn't able to get out of the turret)
2024-10-27 14:27:44 +01:00
smallmodel da7cd03f09 Increase packed animation time precision
This tries to fix some client commands replaying
2024-10-27 13:42:42 +01:00
smallmodel 6934e5cff8 Check for valid target list in GetScriptTarget() 2024-10-27 12:16:19 +01:00
smallmodel c7cdde7bc2 Check if the target list is valid before adding the entity 2024-10-26 22:42:21 +02:00
smallmodel 940ac789b9 Change the current fov only if the fov is currently the selected fov
This prevents the player from modifying the fov while zooming
2024-10-26 22:42:18 +02:00
smallmodel 3d46bae1d0 Stop the triggered music when the server is restarted 2024-10-26 15:07:47 +02:00
smallmodel 16bedf7e86 Warp the sample offset for small streams so it doesn't get past the stream size 2024-10-26 15:07:09 +02:00
KevDoy 2ee531511b Add: Instructions for installing GOG binaries on *nix 2024-10-26 14:58:34 +02:00
smallmodel 0ad5222946 Use the correct stopwatch for explosives 2024-10-26 13:34:33 +02:00
smallmodel 2b4aef4ea6 Add a newline to Cmd_Stuff
Next commands weren't correctly appended
2024-10-26 13:28:49 +02:00
smallmodel 679cf4b7ec Correctly remove "prespawn"/"spawn" waittill when loading from save 2024-10-26 13:27:32 +02:00
smallmodel a993b8d352 Specify "Fixed" instead of "Added" as it's a bug that was fixed 2024-10-26 00:34:50 +02:00
smallmodel b7403347bb Ignore the first responder if it's disabled so the UI doesn't get blocked by it 2024-10-26 00:30:42 +02:00
smallmodel bf978256e9 Add changes from upstream, like pipefile, random number seed 2024-10-25 22:33:02 +02:00
smallmodel 9bd25e9734 Combine mouse movement events in event queue 2024-10-25 22:08:24 +02:00
smallmodel e7499cca04 Also halt the secondary server list if it exists, when canceling refresh 2024-10-25 22:07:23 +02:00
smallmodel e2d6156b5a Apply the hidden visibility for all functions only on macOS
The backtrace still prints the name of functions regardless of the visibility on macOS
2024-10-25 22:01:49 +02:00
smallmodel 31cb6216c9 Use a volatile variable to prevent the function from being entirely optimized 2024-10-25 21:06:30 +02:00
smallmodel e75f5bbbfc Version number typo 2024-10-25 21:01:01 +02:00
smallmodel 69cc87212a Bumped the version number to 0.80.0 due to the number of changes and the completeness 2024-10-25 20:49:23 +02:00
smallmodel 3c1500002b Implement the destructor for the World class to free up the target list 2024-10-25 20:44:00 +02:00
smallmodel b2287f3d83 Avoid using nextSnap if the prediction is disabled in the next snap
This prevent blinking issues like flashing arms
2024-10-24 21:56:44 +02:00
smallmodel 005a278210 Use CF_CAMERA_ANGLES_TURRETMODE 2024-10-24 21:08:52 +02:00
smallmodel 976e2ae022 Remove useless GetSentientOwner() 2024-10-24 21:08:44 +02:00
smallmodel 8fe87e1067 Handle turret camera flags which has no interpolation 2024-10-24 21:08:26 +02:00
smallmodel d142ded9ad Add RF_FRAMELERP flag to ref entity 2024-10-24 21:08:04 +02:00
smallmodel 090f362bb6 Declare g_allowvote as a serverinfo variable 2024-10-23 23:10:22 +02:00
smallmodel ff3c25cc07 Add cg_allowvote 2024-10-23 23:09:39 +02:00
smallmodel ed22a51a72 Only allow breakthrough clients when targeting mohaab 2024-10-23 22:22:09 +02:00
smallmodel 9e0c11a970 Reset scoreboard values like the objective and the picture when initializing a new game 2024-10-23 21:04:23 +02:00
smallmodel edb52a8448 Properly move items in the map rotation list 2024-10-23 20:52:22 +02:00
smallmodel afb08e0ea9 Prevent adding duplicate maps in the rotation list 2024-10-23 20:49:00 +02:00
smallmodel 8758ba6cb1 Fix the map not starting after applying the rotation list 2024-10-23 20:42:03 +02:00
smallmodel e6a9968d23 Remove useless assertion 2024-10-23 20:25:17 +02:00
smallmodel fcd2d2e668 Use the correct weapon selection menu 2024-10-23 20:15:29 +02:00
smallmodel 991c8869d1 Properly draw circles 2024-10-23 20:10:34 +02:00
smallmodel aef9dc1704 Add feature to show static models culling with r_showcull 2024-10-23 20:07:17 +02:00
smallmodel 848cf7ac01 Fix AddPointToBounds not properly setting the max bounds 2024-10-23 20:03:07 +02:00
smallmodel de1d3b6ef4 Don't reset the client structure on single-player 2024-10-22 22:36:46 +02:00
smallmodel 29f8ff8d71 Set the new frame radius
This fixes an issue when culling static models as it uses the radius and the radius wasn't initialized
2024-10-22 22:26:55 +02:00
smallmodel b641a1040c Fix incorrect cull point height (should be squared) 2024-10-22 22:25:59 +02:00
smallmodel 83acdeb16e Allow activation of the game menu so it can be focused 2024-10-22 22:06:19 +02:00
smallmodel aa2d73a1c8 Correctly copy frame bounds 2024-10-22 21:56:35 +02:00
smallmodel b7a643aa59 Fix AI wrongly aiming at the wrong direction 2024-10-22 21:51:03 +02:00
smallmodel 3d454c90cb Rework the target list, use a container instead of an hash set so the target list gets archived correctly
This fixes an issue when loading from a save. A variable referencing target list container would have random entities in it, which would cause errors and crashes when trying to do an action on the array of entities
2024-10-22 20:05:53 +02:00
smallmodel 590b3f5cbb Fix class ID for throbbing box classes 2024-10-22 00:48:11 +02:00
smallmodel f87e6d5938 Fix barrel jitter
This fixes barrel objects improperly jittering back and forth, sometimes forever
2024-10-21 22:12:13 +02:00
smallmodel 901e81cdf5 Format barrels source file 2024-10-21 21:59:12 +02:00
smallmodel d2ed2f5e95 Correct the gamma with the proper destination resolution when resampling 2024-10-21 21:37:08 +02:00
smallmodel c580ccdee1 Only print a warning instead of dropping when the next snapshot is out of range 2024-10-21 21:26:07 +02:00
smallmodel 8ecbe1dd79 Set the script origin local angles and angles when setting the angle
This fixes the issue where a ScriptOrigin would rotate in the wrong direction
2024-10-21 20:27:52 +02:00
smallmodel 64696c7645 Return the angle using the forward vector 2024-10-21 20:24:47 +02:00
smallmodel ff0dcbd786 Add G_GetAngle 2024-10-21 20:24:33 +02:00
smallmodel a3e5d62c96 Increase the precision of the delta animation time 2024-10-21 19:54:25 +02:00
smallmodel 267e2f4b15 Add a workaround against inactivity timer for mods that handle spectating 2024-10-21 19:25:52 +02:00
smallmodel d52bf52e6a Add BUTTON_ANY flag when moving mouse 2024-10-21 19:22:54 +02:00
smallmodel f5391bbfa0 Use BUTTON_ANY to check for input rather than BUTTON_MOUSE 2024-10-21 19:03:19 +02:00
smallmodel a218106c8b Reset the number of songs when freeing all songs
This fixes an issue where songs from previous maps get played on maps without a music file
2024-10-21 18:40:42 +02:00
smallmodel 8f54f4b806 When loading from save, set the edict model directly rather than loading and resetting animations 2024-10-20 23:25:42 +02:00
smallmodel 78b2637c66 Don't replay animation for new snapshot entities
This prevent cannons effects from replaying due to it being shown when the player exits the cannon
2024-10-20 23:18:00 +02:00
smallmodel 4b25e24a13 Fix issues when using turret while charging a grenade or using the mine detector 2024-10-20 22:42:44 +02:00
smallmodel aa0c704655 Instead of resetting the state, prevent using the turret if the player is charging 2024-10-20 22:42:05 +02:00
smallmodel 4da099d15c Add GetChargeFraction() 2024-10-20 22:41:21 +02:00
smallmodel 0bb11d76bd Remove accidental print 2024-10-20 22:22:36 +02:00
smallmodel c146452570 Attempt to fix animation time going back and forth 2024-10-20 22:21:27 +02:00
smallmodel ed05983a57 Use ceiling for the packed anim time
This is an attempt to fix an issue where the animation time would deviate from 1 bit and would go back and forth
2024-10-20 22:19:57 +02:00
smallmodel 909dc96c2f Use a separate CG_InterpolateAnimParms function for animation 2024-10-20 22:18:40 +02:00
smallmodel 863a6293e7 Don't draw the lensflare in UI 2024-10-20 19:12:42 +02:00
smallmodel 7a49f6fc8b Fix the fuse stopwatch 2024-10-20 18:55:27 +02:00
smallmodel c1433a6d9e Use the correct stopwatch type for when the sticky bomb gets wet 2024-10-20 18:54:36 +02:00
smallmodel 374b8b9ae7 Add fuse stopwatch 2024-10-20 18:52:50 +02:00
smallmodel e2f5c80afc Stop charging the weapon when using turret 2024-10-20 18:46:23 +02:00
smallmodel 29911380d1 Use the weapon owner rather than the last successful hit entity 2024-10-20 01:00:55 +02:00
smallmodel 405a4bfe28 Fix debug line delay not working properly 2024-10-20 00:55:08 +02:00
smallmodel 87e41f0c21 Set the model before anything else 2024-10-19 22:44:07 +02:00
smallmodel dce2bcca7c Initialize bModelSet 2024-10-19 22:41:32 +02:00
smallmodel 00421a7666 Process client events with the correct order
Effects that are using commanddelay were not working at all, this fixes the processing of delayed events so they get processed sequentially and at the correct time
2024-10-19 22:38:46 +02:00
smallmodel fd426926e9 Set all alpha color channel in the current static model to prevent vertices from hiding randomly 2024-10-19 21:54:08 +02:00
smallmodel d83634f8a2 Allow to specify a model when spawning an entity 2024-10-19 21:40:23 +02:00
smallmodel 6efac1c0f7 Don't set animation 2024-10-19 21:27:03 +02:00
smallmodel 3a68ca7f4b Handle static shader data and entity surface values for when deforming vertexes 2024-10-19 20:45:50 +02:00
smallmodel 8898919fd3 Correctly parse lightingSpecular parameters 2024-10-19 20:45:24 +02:00
smallmodel 40834380cf Check if the snap is valid before getting the client number 2024-10-19 20:39:57 +02:00
smallmodel 18abf3854d Use normals for deform vertexes
This fixes the issue where some ocean shaders would look inconsistent
2024-10-19 20:33:57 +02:00
smallmodel 6d0b4f8cb7 Fix PVS sound overflow 2024-10-18 23:50:52 +02:00
smallmodel fc1f795e83 Use ULightGreen color on SH/BT for dm messages 2024-10-18 23:19:09 +02:00
smallmodel ef09f136d4 Fix sound indexes not erased correctly 2024-10-18 23:15:59 +02:00
smallmodel 6136bbd019 Set g_netoptimize to 1 when spawning server 2024-10-18 23:05:53 +02:00
smallmodel 5136aa4886 Properly handle and delete unused non visible entity sounds to free up sound indexes 2024-10-18 23:01:27 +02:00
smallmodel 1a3122bef3 Fix pointer to integer warning 2024-10-18 22:14:45 +02:00
smallmodel 23d7db814c Use an unsigned integer for the column size
This fixes compile warnings
2024-10-18 22:03:41 +02:00
smallmodel 3174ca5da9 Explicitly mark overridden methods 2024-10-18 22:02:27 +02:00
smallmodel 6a107419e3 Only change the maxclients when the map is different
It fixes an issue where on restart, only the number of snapshot entities was changed without the memory being reallocated for it
2024-10-18 20:26:27 +02:00
smallmodel 6d69a8033f Initialize the radar 2024-10-18 20:12:47 +02:00
smallmodel bb9ccdd3b9 Make the bot move slowly when aiming with a semi-auto to improve the spread of their weapon 2024-10-18 20:03:39 +02:00
smallmodel 5b3ce85695 Add a method to get the spread factor 2024-10-18 19:52:49 +02:00
KevDoyandsmallmodel 84c5bfa777 Add Open MoHAA Text Logos
Add a logo and update the README file to use the new logo

---------

Co-authored-by: smallmodel <15067410+smallmodel@users.noreply.github.com>
2024-10-18 19:26:01 +02:00
smallmodel d9166478e5 Set the weapon animation back to idle when finished animating
This fixes an issue that also occur in OG, where some weapons would constantly replay the same sounds (often reload/rechamber) when the weapon entity is removed then added to the client snapshot
2024-10-17 17:50:33 +02:00
smallmodel 373fe45b50 Add an example for using bots 2024-10-17 16:33:26 +02:00
smallmodel cd83091101 Update the ubuntu version for publishing tags 2024-10-17 16:00:06 +02:00
smallmodel 631abd2b0f Update section about bots 2024-10-17 15:59:03 +02:00
smallmodel 02df233205 Refactor UploadCompressed 2024-10-17 15:17:20 +02:00
Jesse Mitchell 11e9d0f9ba [macOS / Compiler Fix] Alter offset for Mouse Buttons
Fix the mouse buttons code and alter how the mouseButton check works
2024-10-17 01:24:22 +02:00
smallmodel 35fea91268 Download and install ninja on Windows, from the official ninja-build GitHub repository
This greatly reduces the compile time on Windows
2024-10-16 22:33:08 +02:00
smallmodel 6f3d79ae1b Use multi-config generators and specify the build type in the --config when using the cmake command instead of using CMAKE_BUILD_TYPE. Also build third-party libraries in Release mode 2024-10-16 22:04:33 +02:00
smallmodel 32da07ea80 Cache Linux apt packages
This avoid overloading servers by downloading the same set of packages multiple times
2024-10-16 20:35:19 +02:00
smallmodel e9a76f933b Cast to int32 rather than uint32 when writing the packed velocity
This fixes an issue where the integer could overflow, on some platforms like ARM the integer would be 0
2024-10-16 19:52:47 +02:00
smallmodel 6b6adf1147 Copy second and third triangles, this was forgotten 2024-10-16 18:28:41 +02:00
smallmodel 6413e770e1 Update compiling doc 2024-10-15 23:46:21 +02:00
smallmodel 7d1067108b Swap the archive type on big endian architectures 2024-10-15 23:38:39 +02:00
smallmodel e00ebda641 Disable compression for big endian systems 2024-10-15 23:33:00 +02:00
smallmodel 2b6fc0602a Avoid misaligned memory access 2024-10-15 23:18:14 +02:00
smallmodel 53c09b5342 Correctly swap skeletons for CPUs that don't support misaligned memory access 2024-10-15 23:10:04 +02:00
smallmodel d78d8abb9f Correctly load SKB models on big endian architectures 2024-10-15 23:07:58 +02:00
smallmodel f6b459b408 Correctly copy long/short taking into account memory overlaps 2024-10-15 22:49:23 +02:00
smallmodel 581585a47c Prevent clearing the event command list if the event system is not initialized
This fixes the issue where the game could crash (especially in optimized release) due to a memory corruption, because the event command list was deconstructed earlier
2024-10-15 20:52:53 +02:00
smallmodel ddbdcc91dd Don't use an offset for the reverse table 2024-10-15 19:22:54 +02:00
smallmodel 8f8b75e0aa Set symbols visibility to hidden by default
This fixes an issue where shared libraries would use functions from in the executable because they have the same name, which would cause memory corruption
2024-10-14 20:36:06 +02:00
smallmodel 2e673a6bc9 Delete posted events when canceling 2024-10-13 23:49:52 +02:00
smallmodel 8c2b92d151 Remove player from turret when deleted 2024-10-13 23:22:13 +02:00
smallmodel 032fb9b5ba Make sure to delete all conditional objects
This fixes the issue where memory would be leaked by conditionals
2024-10-13 22:09:38 +02:00
smallmodel b1c5d6c62a Increase the backtrace size to 64 2024-10-13 11:32:20 +02:00
smallmodel 037af5d728 Don't access the removed node 2024-10-13 11:32:11 +02:00
Leszek Godlewski 61a2b6a837 Don't call into the OAL channel in S_OPENAL_GetMusicFilename if QAL init failed
Prevent a crash upon vid_restart
2024-10-13 00:25:17 +02:00
smallmodel 13698a9590 MINS and MAXS must be signed values 2024-10-12 01:16:31 +02:00
smallmodel 4f2907ef77 Remove LADDER_HAND_HEIGHT (useless) 2024-10-12 01:16:04 +02:00
smallmodel 8667d11c52 Prevent SV_DropClient() from being called recursively if the client is dropped by a kick or timeout and has too many reliable commands 2024-10-11 22:55:24 +02:00
smallmodel 24309095ff Rework bot save/load:
- Only save and restore the userinfo
- Restore bots when the server spawns
- Read client session data like real players
2024-10-11 22:54:40 +02:00
smallmodel d5a90ded17 Add a comment about primary weapon selection on map change 2024-10-11 21:51:52 +02:00
smallmodel 9d744367ac Add firstTime parameter for bots 2024-10-11 21:46:49 +02:00
smallmodel 46a46a9536 Remove unnecessary code 2024-10-10 22:29:17 +02:00
smallmodel 224c1df553 Test against entities with BSP solidity when testing client visibility 2024-10-10 21:38:51 +02:00
smallmodel bcea5af30f Remove unused sound index that were used for non visible players 2024-10-10 21:22:59 +02:00
smallmodel 211ce09c0b Don't create sound index for non visible players if net optimization is disabled 2024-10-10 21:22:35 +02:00
smallmodel 1e41a2595d Leave 1 second minimum between each call to RefindPath() 2024-10-10 20:27:52 +02:00
smallmodel 36a080b3a9 Call InitModelList() once
This fixes an issue where the model list would get initialized each frame
2024-10-10 20:11:12 +02:00
smallmodel a3050f6c64 Avoid using too much performance to update the loading screen, especially on low-end PCs 2024-10-10 19:48:23 +02:00
smallmodel be5deddc1d Make indexes and coordinates 16-bytes aligned 2024-10-10 19:10:12 +02:00
smallmodel 36f9bdb88c Use intptr_t instead of size_t because intptr_t can hold a pointer which is not always the case for size_t 2024-10-10 19:07:20 +02:00
smallmodel 1a33e9a15b Add BotRotation class to handle bot turning 2024-10-09 21:21:19 +02:00
smallmodel 4157a49c7e Remove useless include 2024-10-09 21:21:13 +02:00
smallmodel f27be7314e Add a BotMovement class for managing bot movements 2024-10-09 20:46:39 +02:00
smallmodel a425038fa6 Set macOS rpath to @executable_path 2024-10-09 19:38:32 +02:00
smallmodel 0b07858bfc Refactor PlayerBot to use a separate controller class, alongside classes that manage bots 2024-10-08 22:17:22 +02:00
smallmodel 7dbf1d7bf5 Add a method to get the ladder 2024-10-08 21:52:49 +02:00
smallmodel 34c44ab2cf Add a method to get the max fire movement 2024-10-08 21:52:43 +02:00
smallmodel 5ec106642d Fix node cover mask 2024-10-08 21:00:01 +02:00
smallmodel dcd9ce91a8 Use the raw integer value of the squared distance when comparing nodes 2024-10-08 20:42:22 +02:00
smallmodel a05fbfe69b Fix incorrect value of AI_CONCEALMENT_MASK 2024-10-08 20:38:34 +02:00
smallmodel feb76f4fb4 Allow entities other than SimpleActor for finding covers and sniper nodes 2024-10-08 20:31:50 +02:00
smallmodel d467b68187 Add node editing support, with a way to dynamically load, remove and modify nodes while editing 2024-10-08 20:25:33 +02:00
smallmodel de18fa2860 Refactor Entity::FovCheck 2024-10-08 20:14:10 +02:00
smallmodel 58f6c719a9 Add code to select current node in view and draw it for editing later 2024-10-08 01:14:40 +02:00
smallmodel b2fa21a111 Format navigation source file 2024-10-07 23:52:39 +02:00
smallmodel f94099e350 Don't link nodes that can't be reached with an high fall height 2024-10-07 23:49:39 +02:00
smallmodel e2f11879d5 MAXS_Z is 94 2024-10-07 23:05:37 +02:00
Sébastien Noel aa15b3ea7f Allow to build against system libs instead of bundled copy 2024-10-07 20:51:23 +02:00
smallmodel 1624d10a01 Don't check for bots for smoothclients 2024-10-07 00:51:01 +02:00
smallmodel 0d53adf9bd Rework bot spawning
- Add a sv_sharedbots to specify if real client slots should be used
- Removed m_bSpawnBot from level, bots are spawned directly in G_BotBegin instead
- sv_numbots can be used to directly configure the number of bots to spawn
- Fix the way bots spawn/unspawn on-demand
- Documented g_bot functions
2024-10-06 22:57:39 +02:00
smallmodel 295c267c31 Automatically join a team if the bot was put in spectator, and automatically select a primary weapon if none was selected 2024-10-06 22:57:31 +02:00
smallmodel d4b3f7378e Don't update the new path check time when there is a new move 2024-10-06 22:29:55 +02:00
smallmodel a503e18966 Make the bot move to the enemy only if it was seen 2024-10-06 22:29:29 +02:00
smallmodel b1f7d641fc Use game.maxclients for the maximum number of bots 2024-10-06 21:44:10 +02:00
smallmodel 5019d1e4f9 Spawn bots after the server has spawned 2024-10-06 21:43:42 +02:00
smallmodel 2aa0205872 Clear client persistent to avoid leaking data 2024-10-06 21:01:05 +02:00
smallmodel a7befa8882 When a client disconnects, delete the entity on the next frame if the function is called while in thinks 2024-10-06 21:00:40 +02:00
smallmodel a5058c7bab Call Delete() instead of deleting the item as it could cause issues if the item is being deleted while iterating over edicts 2024-10-06 19:57:03 +02:00
smallmodel f5558d106e Don't set the last radar time if the entity number is above the max number of clients 2024-10-06 19:19:44 +02:00
smallmodel d19328230c Allow more bots to be spawned alongside the minimum number of players 2024-10-06 18:50:42 +02:00
smallmodel b77464386c Count actual clients that aren't spectating 2024-10-06 18:46:23 +02:00
smallmodel 9119319429 Avoid unbalancing teams when removing bots 2024-10-06 18:46:02 +02:00
smallmodel d3d85fded0 Add TEAM_MAX 2024-10-06 18:37:31 +02:00
smallmodel 9b9642df8f Add a very tiny offset off the facing dir as a workaround the 1 bit difference between 32-bit and 64-bit
In 64-bit, some windings are off by 1 bit (float values) compared to 32-bit, which causes issue on some maps like `dm/mp_stadt_dm` where the player would get stuck climbing up because of the blocking patch at the top
2024-10-06 17:33:48 +02:00
smallmodel e564a97b05 Check if the delta is exactly 16 2024-10-06 17:31:02 +02:00
smallmodel a150cb5c6e Also check for liberation game type when the team is dead 2024-10-06 16:58:20 +02:00
smallmodel afd7943b62 Fix incorrect teams and controllers for TOW objectives 2024-10-06 15:20:45 +02:00
smallmodel 09eb130b6d Update curiosity and MoveDone() 2024-10-06 14:24:32 +02:00
smallmodel 5869ba06bc Update the attack time when moving 2024-10-06 01:13:12 +02:00
smallmodel b6c2638c1b Make curiosity random 2024-10-06 01:01:03 +02:00
smallmodel 16b0f0d625 Use random() in CuriousSound() 2024-10-06 00:53:31 +02:00
smallmodel 9293930628 Make bots jump off ladder
They don't support ladders yet
2024-10-05 23:59:32 +02:00
smallmodel 46935b165c Fix MoveDone() not checking for height, also return false when temporarily getting away 2024-10-05 23:57:02 +02:00
smallmodel c0dd08f6e0 Set an higher firing sound in MP 2024-10-05 21:24:45 +02:00
smallmodel 1fde1647e8 Use the proper enum for BroadcastAIEvent 2024-10-05 21:24:29 +02:00
smallmodel 7ef006ccca Fix nodes improperly connecting to other nodes that are below the ground 2024-10-05 21:15:37 +02:00
smallmodel fd69d6b42c Allow the bot to get out if stuck while falling 2024-10-05 20:46:16 +02:00
smallmodel 627f66fb5b Add basic pathnode editing feature 2024-10-05 20:45:56 +02:00
smallmodel 8451c11916 Add a feature to dynamically create a master class for development 2024-10-05 20:17:11 +02:00
smallmodel 6bbbbcfb05 Allow spawning a simple entity 2024-10-05 20:15:50 +02:00
smallmodel 63465278a5 When there is no free player start spot, try to find a random player s tart one 2024-10-05 20:15:40 +02:00
smallmodel 2980771deb Fix path node connection, use the target node num 2024-10-05 20:13:03 +02:00
smallmodel 1169b84c2f Make sure the entity is valid before checking for the bad place team 2024-10-05 20:12:37 +02:00
smallmodel 355491a950 Reduce the bot attack time to avoid the bot getting stuck 2024-10-05 14:47:09 +02:00
smallmodel 7caa0adbab Toggle use button and don't use if the door is open 2024-10-05 14:46:44 +02:00
smallmodel 8acc51c489 Correctly add/remove bots 2024-10-05 13:54:53 +02:00
smallmodel 732fd98593 Make the bot strafe when attacking 2024-10-05 13:43:09 +02:00
smallmodel 21a610d22c Fix NoticeEvent ignoring other players on FFA 2024-10-05 11:56:08 +02:00
smallmodel a379e6efbf Don't use Ninja on Windows because of chocolatey servers causing troubles 2024-10-05 00:39:23 +02:00
smallmodel b1e1b6cc68 Properly aim at the last enemy position with some randomness applied 2024-10-04 22:10:51 +02:00
smallmodel da86e0ce34 Fix bot incorrectly jumping 2024-10-04 21:23:49 +02:00
smallmodel 6ca12eb0de Fix bot sometimes being stuck respawning between team spawn intervals 2024-10-04 20:27:28 +02:00
smallmodel a25442368b Make the bot jump more to avoid getting stuck 2024-10-04 20:25:05 +02:00
smallmodel e7e95d47a5 Prevent others from picking up the health item if their future health will be full 2024-10-04 19:59:09 +02:00
smallmodel 292fe8eab4 Stop moving if there is a maximum fire movement so the weapon can be fired 2024-10-04 19:48:09 +02:00
smallmodel 272a401189 Make the bot jump even if the path is not valid to get out of spawns with no path nodes 2024-10-04 19:03:33 +02:00
smallmodel 592e3f47e9 Handle curiosity sounds better by getting the owner of concerned entities and ignoring team mates 2024-10-03 22:54:25 +02:00
smallmodel cabf1a9043 Make AI path more random 2024-10-03 22:23:46 +02:00
smallmodel e623541861 Improve the way bots turn, make it smoother 2024-10-03 21:57:29 +02:00
smallmodel b74b6f8c1d Use the last attacker origin instead of the last death position 2024-10-03 21:33:12 +02:00
smallmodel 11abdd451f Fix incorrect dir for PathSearch::FindPathAway 2024-10-03 21:27:30 +02:00
smallmodel 1c3596b1f9 Add more conditions to check for valid enemies when attacking 2024-10-03 20:45:23 +02:00
smallmodel 1e73333fbe Make bot path more random when idle 2024-10-03 20:22:54 +02:00
smallmodel 6eb49f567a Made tempaway path better 2024-10-03 20:10:33 +02:00
smallmodel 0120e7e4a5 Add liberation messages 2024-10-03 19:06:03 +02:00
smallmodel 10e4d3db11 Check if the activeItem is within the configstring range to avoid leaking data 2024-10-03 19:05:56 +02:00
smallmodel 0b34d2dbb8 Fix ammo bits being incorrect 2024-10-02 23:04:30 +02:00
smallmodel be1ef1de0e Try respawning when the player should respawn
This fixes an issue where bots wouldn't respawn with `sv_team_spawn_interval` set
2024-10-02 22:18:07 +02:00
smallmodel ef45c988c6 Fix player spectating often not spectating the next alive player 2024-10-02 22:16:58 +02:00
smallmodel 3ecdee1b89 Make bots play a taunt when they get a kill 2024-10-02 21:54:56 +02:00
smallmodel c7561b1f6d Send the GotKill event to the attacker when killed 2024-10-02 21:50:59 +02:00
smallmodel 50a3df8dff Fix the instant message maximum number on AA and SH/BT 2024-10-02 21:49:20 +02:00
smallmodel dfde4a58de Improve bot movements
- Do random movements if the path cannot be found
- Reset the movement if the bot is really blocked
- Set an higher fall height
2024-10-02 21:29:38 +02:00
smallmodel 090ba308d8 Clear bot buttons after spawning
This fixes a rare occurrence where the bot would fire and reload after spawning
2024-10-02 20:14:24 +02:00
smallmodel e01e989c22 Check if the snap is valid when notifying for hit/kill
The game would crash otherwise, this is also an issue in the original game
2024-10-02 20:10:29 +02:00
smallmodel a9b4af98fc Make bots use random player models 2024-10-02 19:42:03 +02:00
smallmodel 30f5442728 Limit bot vision distance to the farplane 2024-10-02 19:41:25 +02:00
smallmodel 123ca2812a Define and use DEFAULT_SFX_NUMBER_PLAYING 2024-10-02 19:02:20 +02:00
smallmodel 95435ea512 Improve bot movement
- The bot will immediately move upon spawning
- If blocked, the block will move randomly to get out
- There is now only 1/5 chance the bot will go to the location where they died
2024-10-02 18:34:45 +02:00
smallmodel db625baadd Set the healrate to 0 (instant) by default on protocol 8 and below (vanilla AA) 2024-10-02 18:12:10 +02:00
smallmodel 200a80aa02 Automatically choose a primary weapon for bots 2024-10-02 17:02:59 +02:00
smallmodel 0472a93c3f Ignore kills when telefragging
This fixes an issue (that also occur on OG) where telefrags would also count towards teamkills
2024-10-02 17:02:48 +02:00
smallmodel 9b70e646dc Add "auto" to automatically choose a primary weapon 2024-10-02 16:52:22 +02:00
smallmodel 388ab210a7 Fix incorrect obituary hit location 2024-10-02 16:42:10 +02:00
smallmodel 15e8a71249 Fix bot userinfo accumulating with previous bot userinfo 2024-10-02 15:59:41 +02:00
smallmodel dfd04f0d41 Reset the player state when using a turret
This prevents the player from using the turret + hold their weapon to crouch and become impossible to hit
2024-10-02 14:50:11 +02:00
smallmodel 88ac49c0c9 Set the correct flag when the player is using a turret 2024-10-02 14:35:37 +02:00
smallmodel 7d6ff3e6a4 Format bg source files 2024-10-02 14:09:36 +02:00
smallmodel c68fbfacb9 Set the EF_PLAYER_IN_MENU flag when the player is talking 2024-10-02 14:09:27 +02:00
smallmodel 8e51c7ca3b Fix VEHICLE_TYPE state condition not returning the vehicle type
This fixes player lacking animation when using heavy weapons like the granatwerfer
2024-10-02 14:09:07 +02:00
smallmodel 33064f8392 Set a default minimum delay between text messages 2024-10-02 13:31:45 +02:00
smallmodel 40141465b5 Add a section about flood protection 2024-10-02 13:29:58 +02:00
smallmodel 13d855c2e7 Use Cmd_Argv() to check for dmmessage 2024-10-02 13:07:04 +02:00
smallmodel 2f8b6a2009 Satisfy stufftext tests 2024-10-02 12:27:57 +02:00
smallmodel 23e56e767f Increase sphere light limit
Some servers have a lot of objects in maps, causing all spheres to be used
2024-10-02 12:18:58 +02:00
smallmodel ce5b954c4d Use the target game version when sending the version to the server, instead of the global project version
The non-dedicated server version of MOH: Breakthrough (standalone executable) rejects clients that have a version of 2.30 or below, or a version of 2.50 or above (0.1 difference), which prevents playing LAN sessions of Breakthrough. To solve this issue, the client now sends a version value that is within the allowed version range for the target game
2024-10-01 23:36:05 +02:00
smallmodel a0c20663a0 Don't make the player not solid in a vehicle slot
This fixes player not taking hits from explosions
2024-10-01 23:25:01 +02:00
smallmodel 56f850b59d Don't add the same world surface more than once
This fixes an issue where shaders like water, ocean would look strange or completely black, due to them blending against each other multiple times
2024-10-01 20:51:56 +02:00
smallmodel 253d4e2c4d Fix jammed door message printed on the first client 2024-10-01 20:26:17 +02:00
smallmodel 6fef42d6e0 Localize the jammed door message 2024-10-01 20:25:51 +02:00
smallmodel d6a00a5984 Fix IsOpen event not being used
Some multiplayer and single-player scripts rely on it
2024-10-01 20:24:12 +02:00
smallmodel 26a1e24e3a Fix TIKI_ParseAnimations incorrectly swallowing the full animation file when the map doesn't match
This fixes missing animations
2024-10-01 19:53:33 +02:00
smallmodel 6103efa8cc Don't set the entity angles immediately during glue
The game expects objects to glue and keep their initial angles/origin
2024-10-01 19:03:17 +02:00
smallmodel 9a7ba0786c Set the correct number of bits for the large bullet flag in 2.0 and above
This fixes the issue where there the client (in spearhead protocol mode) would read 2 bits instead of the 1 bit the server sent, which would cause a parse error
2024-10-01 18:52:39 +02:00
smallmodel 935efaeb3a Fix sound event being posted with incorrect arguments
The argument wouldn't contain "wait" when necessary, which would cause scripts to be stuck forever waiting for sound to be done
2024-10-01 18:09:56 +02:00
smallmodel 020a6d8b66 Fix stupid compile error mistake 2024-09-30 22:39:33 +02:00
smallmodel 9dea8fc41e Fix wrong pointer type passed to strncmp 2024-09-30 21:59:14 +02:00
smallmodel 3a7e249edf Refactored svflags and use the correct entity server flags 2024-09-30 19:58:41 +02:00
smallmodel c406aaf74f Add a feature that prevents teams from being uneven 2024-09-29 19:00:19 +02:00
smallmodel 83938471ca Set the blue component of the temp model entity
This fixes particles having an incorrect color sometimes
2024-09-29 15:41:35 +02:00
smallmodel db6ff8901b Set the render effect of skyportal and skyentity when adding them to the snapshot
This fixes the issue where some entities like effects would be visible through the sky
2024-09-29 15:27:54 +02:00
smallmodel 737ee3af64 Specify the compiler to use globally for macOS 2024-09-29 14:46:42 +02:00
smallmodel 9ea40f31e4 Clear all entities on registration 2024-09-29 13:30:56 +02:00
smallmodel 27bd6f4b1c Merge pull request #379 from smallmodel/me/throbbingbox
Fix the destroyed model of specific throbbing boxes
2024-09-29 13:09:09 +02:00
smallmodel b9e9137f90 Fix the spelling for the default explosive sound 2024-09-29 13:03:10 +02:00
smallmodel bee0bbbe90 Initialize the effect and destroyed model for the specific ThrobbingBox explosive classes 2024-09-29 13:02:56 +02:00
smallmodel 277ca0c951 Handle bigger offsets in sample_ms_offset()
This fixes an issue where when the offset was big enough, the value would overflow and start again from 0
2024-09-29 12:34:07 +02:00
smallmodel 8aa059dd21 When paused, keep in sync with the server time (#371)
This fixes an issue where a temporary lag would occur when starting a single-player map, or when pausing/unpausing the game
2024-09-29 00:10:52 +02:00
smallmodel c39bdd246a Correctly load DDS file on bigendian architectures 2024-09-28 20:56:55 +02:00
smallmodel 9823af9159 Fix light grid offsets endianness 2024-09-28 20:45:04 +02:00
smallmodel 9ee0e0a3c9 Correctly copy data on big-endian (#365) 2024-09-28 20:09:42 +02:00
smallmodel bf184fb719 Use #pragma once instead of #ifndef 2024-09-27 20:19:11 +02:00
smallmodel 94f308c50f Draw a black outline for game messages and death messages when targeting mohta or mohtt 2024-09-27 20:01:48 +02:00
smallmodel bfa0ef64ec Fix the letterbox not transitioning smoothly
This fixes the letterbox being shown immediately
2024-09-27 19:35:30 +02:00
smallmodel 98fc0a8cb9 Fix the letterbox not correctly rendering
When a letterbox was active, it was covering the entire screen
2024-09-27 19:33:39 +02:00
smallmodel facabc09f5 Don't set the label shader if the specified material name is considered empty (#364)
For labels linking to a variable for the shader, this prevents the label from still being rendered, drawing the tiled square grid (notexture)
2024-09-27 18:30:03 +02:00
smallmodel 51afcd7b96 Fix loading screen being incorrectly displayed
This fixes an issue where some part of the loading screen would not be drawn correctly, due to the screen being updated recursively through UI_Update()
2024-09-27 17:59:03 +02:00
smallmodel 340f1bb287 Put chat first in game and add a statement for disabling text messages 2024-09-26 22:13:33 +02:00
smallmodel 40c8479448 Update server configuration documentation 2024-09-26 20:48:26 +02:00
smallmodel 27e2063bf9 Add server configuration documentation 2024-09-26 20:30:37 +02:00
smallmodel e43f0a9285 Add a new feature to enable/disable instant messages and text chat with a variable to set the minimum delay between messages 2024-09-26 19:29:56 +02:00
smallmodel a977cbdd26 Update README 2024-09-26 19:27:11 +02:00
smallmodel dbc536c6c2 Fix voice chat time not working on FFA 2024-09-26 19:10:01 +02:00
smallmodel 97c9075503 Fix a small mistake in normal calculations for MM_ClipVelocity2D
Same error as commit c76dda1523. This fixes an issue where AI would run too slowly, like the crate guy in the intro of e1l1, the crate guy was too slow that it ran through the intro vehicle
2024-09-26 18:20:25 +02:00
smallmodel 290e45062d Set the server time before calling ge->RunFrame() in SV_SpawnServer()
This fixes an issue where some scripts wouldn't be initialized in time, like those that set AI animations. For example this caused an issue with the plane passenger in e2l1, where the animation would get reset due to a very specific chain of events
2024-09-26 01:18:11 +02:00
smallmodel fc6bffe683 Don't post event when loading save game 2024-09-26 01:01:27 +02:00
smallmodel 1fb8327ca9 Don't let the frame msec go below 0 2024-09-25 22:14:27 +02:00
smallmodel 36208de902 Fix spawn time delta 2024-09-25 22:12:29 +02:00
smallmodel 5403577642 Fix the return value of FS_Seek
It returns a negative value on failure, so handle that properly
2024-09-25 21:04:55 +02:00
smallmodel c76dda1523 Fix a small mistake in normal calculations for MM_ClipVelocity
This leaded to some occasional errors in AI movement, like in e3l2 where the medic gets stuck while going down the stairs
2024-09-25 20:22:42 +02:00
smallmodel b5034e5b12 Fix the m_iSaySlot being mistakenly used for the weight cross blend, the specified slot parameter must be used instead
This fixes #266 where some AIs would lack speech animation
2024-09-25 20:04:58 +02:00
smallmodel b039333922 Call AnimName() to get the current animation name 2024-09-25 19:48:06 +02:00
smallmodel b504e0d109 Call CurrentAnim() to retrieve the animation index 2024-09-25 19:47:43 +02:00
smallmodel 0692b9dcdb Fix events sometimes not being posted to entities
Fixes #253
2024-09-25 19:41:21 +02:00
smallmodel 085b72154f Use a more modern implementation of minizip from ioquake3 2024-09-24 22:25:33 +02:00
smallmodel 4f99c0fa98 Merge branch 'me_main' 2024-09-24 20:11:44 +02:00
smallmodel b38b71eb44 Small mistake fix 2024-09-24 20:11:34 +02:00
smallmodel 639da1a4b8 Remove unused variables 2024-09-24 20:09:39 +02:00
smallmodel f2d27aae3f Update getting_started_running.md 2024-09-24 20:06:37 +02:00
smallmodel 931876ac77 Remove lidbad-0.15.1b 2024-09-24 20:03:30 +02:00
smallmodel e5f62a9188 Update features.md 2024-09-24 20:02:41 +02:00
smallmodel 3fb699979c Fix small equality mistake (expected assignment) 2024-09-23 22:44:11 +02:00
smallmodel 85f15a1f28 Delete spawnthings when their last temp model is freed
This fixes:
- Losing FPS in a match with a lot of players, due to a massive amount of emitters getting spawned every time a weapon fires
- Memory leaks due to emitters staying in memory forever after being spawned
2024-09-23 19:29:07 +02:00
smallmodel 758017b638 If the temp model being removed is the head one, use its sibling 2024-09-23 19:16:31 +02:00
smallmodel 724d1db9b8 Properly clear parents of orphaned entities 2024-09-22 21:38:35 +02:00
smallmodel 00421fbee6 Fix the link to the branch build workflow 2024-09-22 20:18:40 +02:00
smallmodel 2510bab41f Change the order of the target os for more clarity 2024-09-22 20:16:51 +02:00
smallmodel c6675f2013 Remove special features code to avoid any confusion 2024-09-22 20:06:31 +02:00
smallmodel 1fd6c2bd52 Merge pull request #360 from pryon/UINotepad-fixes
UINotepad fixes and improvements
2024-09-22 19:35:52 +02:00
smallmodel 8f355fe188 Add Voip code from ioq3 2024-09-22 16:50:44 +02:00
smallmodel dbd10a281b call CL_ShutdownInput() 2024-09-22 16:39:30 +02:00
smallmodel d57ea3695b Add VOIP code for cl_input 2024-09-22 16:38:00 +02:00
smallmodel 8dd74b7789 Get rid of the code that sends next fragments from clients 2024-09-22 16:35:12 +02:00
smallmodel 36c00f146d Improve gamepad support 2024-09-22 16:19:55 +02:00
SmileTheory aba9f25744 Fix frame_msec possibly being zero in cl_input.c.
This fixes a mouse freezing bug.
2024-09-22 16:14:01 +02:00
smallmodel dacfa6ae55 Made common source file a C file as it should be 2024-09-22 16:03:02 +02:00
smallmodel f53fba082a Improve memory for debugging purposes 2024-09-22 15:45:29 +02:00
smallmodel 764b95f617 Set a better name for binaries to properly distinguish the name of the architecture 2024-09-22 14:56:02 +02:00
smallmodel 3237b3564e Update getting started running 2024-09-22 14:23:51 +02:00
Zack Middleton 985731f543 Fix command line variables not being set correctly
+seta, +sets, and +setu were ignored because Com_AddStartupCommands
thought Com_StartupVariable handled it.

+set didn't allow value to be multiple tokens which due to Unix shell
unintuitively removing quotes causes the variable to only be set to
the first token. This could be worked around by escaping quotes

    ioq3ded +set g_motd \"hello world\"

but it doesn't match behavior of other start up commands (which now
includes seta, sets, and setu) that use all tokens.
2024-09-22 13:47:55 +02:00
Thilo Schulz 7c28efe9cd Fix bug where Com_StartupVariable would set CVAR_USER_CREATED on already existing cvars 2024-09-22 13:36:23 +02:00
smallmodel 5b567f4cba Fix music volume not restored when the map restarts after the intermission 2024-09-22 01:39:40 +02:00
smallmodel 78918eb59d Correctly process statements with a semicolon 2024-09-22 01:23:23 +02:00
smallmodel 1848506f09 Properly pass the size of the path buffer into Q_strncpyz 2024-09-21 23:09:16 +02:00
smallmodel ce0004a296 Use unsafe version of strcpy as the buffer length is unknown 2024-09-21 23:08:52 +02:00
smallmodel e85d3f2a19 Pass the correct size to Q_strncpyz 2024-09-21 22:50:53 +02:00
smallmodel 4e5a0a30bf Fix subtitle being incorrect due to the size of the pointer (and not the size of the string) being passed to Q_strncpyz 2024-09-21 21:09:12 +02:00
pryon 9ab37e54b4 Fix CodeQL printf argument type warning 2024-09-21 20:59:27 +02:00
smallmodel 0bd15172b1 Use Ninja generator for faster builds and set compiler/flags in environment variables directly to reduce copy-pasted parameters 2024-09-21 20:34:45 +02:00
pryon fe0e5c1d9c Fix bug when multiple lines are joined together after copy-pasting text 2024-09-21 20:08:11 +02:00
pryon 5128d88722 Fix bug when deleting multiple lines doesn't actually remove everything selected 2024-09-21 20:04:57 +02:00
pryon 173ca3e58e Fix assertion failures on str operations 2024-09-21 20:02:58 +02:00
pryon 2a13fca737 Fix an off-by-one bug when selection points are determined 2024-09-21 20:01:03 +02:00
pryon b3a9f4423b Fix crash when saving a file with no contents or with no name 2024-09-21 19:52:20 +02:00
pryon 62c24826e6 Silence some localization error console spam messages
This helps to reduce the number of `LOCALIZATION ERROR` messages in the console for strings that couldn't be translated anyway
2024-09-21 19:49:43 +02:00
pryon a3d2c2c044 Properly free uipopup_describe instances 2024-09-21 19:46:32 +02:00
pryon 72409622ef Stop activating controls when their vertical scrollbar is hovered over
This fixes the annoyance of open windows (console, notepad) losing focus just by simply moving the mouse around
2024-09-21 19:43:18 +02:00
pryon c8a2de8235 Implement FS_FileTime for proper retrieval of file date/size info in FilePicker 2024-09-21 19:37:50 +02:00
pryon 6b91846b0c Reimplement Sys_ListFiles and Sys_ListFilteredFiles
They had several bugs, like showing the current and parent directory entires twice, not seeing files but only directories, etc.
2024-09-21 19:36:13 +02:00
pryon 92190220aa Implement clipboard functionality 2024-09-21 19:32:23 +02:00
smallmodel 705d30d125 Add ninja/cmake/clang to the list of packages to install 2024-09-21 19:18:35 +02:00
pryon c316dc7b00 Fix incorrect line width calculation when tabs are present 2024-09-21 19:17:25 +02:00
smallmodel 529dc29d08 Remove CMake parallel build setting 2024-09-21 19:15:26 +02:00
smallmodel 91e760bf5f Use a more recent version of ubuntu image for linux 2024-09-21 18:50:10 +02:00
smallmodel 61e24499bf Cross-compile macOS binaries with single hosted runner image 2024-09-21 18:44:23 +02:00
smallmodel 75621651e5 Add arm64 to valid OSX architectures 2024-09-21 18:30:37 +02:00
smallmodel 3973b95746 Build MacOS binaries from GitHub Action 2024-09-20 23:09:07 +02:00
smallmodel f9d264058b Use safe version of sprintf and strcpy 2024-09-20 23:08:53 +02:00
smallmodel a69d9d4483 Fix compilation errors for MacOS, and add support for MacOS 2024-09-20 21:31:27 +02:00
smallmodel 8b19d00086 Remove the last OpenAL linking as it's already linked before 2024-09-20 21:29:15 +02:00
smallmodel 1156d4f881 Replaced (u)int64_t with long long to avoid constructor conflicts with some compilers 2024-09-20 21:28:36 +02:00
smallmodel 08c5186426 Use stdlib.h as malloc.h is deprecated 2024-09-20 21:27:53 +02:00
smallmodel 61b4a817f3 Move alloca include directive to q_platform.h due to difference between platforms 2024-09-20 20:52:41 +02:00
smallmodel 13710904ba Update getting started installation 2024-09-20 18:45:15 +02:00
smallmodel 015ebb650e Clean up ClassDef class 2024-09-19 22:50:33 +02:00
smallmodel 17d623bf85 Add more clarity + check the length of the const_str enumeration and the length of the const string array to make sure they both match 2024-09-19 21:23:19 +02:00
smallmodel 0049348de5 Update features documentation 2024-09-19 21:06:22 +02:00
smallmodel 20d11f5f97 Add max_amount parameter to the EV_Sentient_GiveAmmo documentation 2024-09-19 21:02:04 +02:00
smallmodel 047a7bb949 Deprecate r_forceClampToEdge in favor of automatic detection
This avoids setting the variable manually to fix sky seams and weird graphical artifacts. Now, it's detected automatically
2024-09-19 21:00:22 +02:00
smallmodel 52c79f7f77 Make crates correctly fall 2024-09-19 20:49:33 +02:00
smallmodel c97bc2e977 Add more clarity in crateobject.cpp 2024-09-19 20:38:31 +02:00
smallmodel 78d564cc04 Fix CrateThink stopping when it shouldn't 2024-09-19 20:34:04 +02:00
smallmodel e27c0716c4 Allow more stufftext commands when the local server is running
Those stufftext commands are primarily used by single-player maps and briefings
2024-09-19 20:14:15 +02:00
smallmodel 35d037daff small detail change 2024-09-19 20:00:53 +02:00
smallmodel f055162ac0 Adjust the quick message DM console rectangle to avoid seeing characters 2024-09-19 19:46:27 +02:00
smallmodel f2e32c737b Fix the gap in the console between the bottom line and the text 2024-09-19 19:46:07 +02:00
smallmodel 205709271b Add fixes from upstream ioq3 2024-09-19 19:24:31 +02:00
smallmodel 3e70a9fab8 Fix mistakes that lead to compilation errors 2024-09-19 19:19:58 +02:00
smallmodel 733c6c96f0 Merge pull request #359 from twolife/spelling
Fix a few typos
2024-09-19 17:44:08 +02:00
Sébastien Noel a010e648ee Fix a few typos 2024-09-19 10:52:47 +02:00
smallmodel 1c7b561aa9 Filter stufftext commands
This works by allowing the stufftext server command to be executed if the statement only contains whitelisted commands and variables
2024-09-18 23:51:39 +02:00
smallmodel 75a71d35ec Avoid calling isspace with a character that has a value below 0 2024-09-18 23:04:01 +02:00
smallmodel 7c0f0672bd Add r_vidmode1024 and r_vidmodemax so the display resolution can be changed in Spearhead and Breakthrough 2024-09-18 22:59:30 +02:00
smallmodel 8fc6b6e3c3 Correctly handle quick message and message mode for the chat window
This fixes the chat window not being put in quick message mode at all when intended, now it also correctly handle team/private message modes
2024-09-18 22:14:16 +02:00
smallmodel 6c2c8ca2b7 Don't archive s_openaldevice and s_openaldriver 2024-09-18 22:10:33 +02:00
smallmodel 1b6bdd07e7 Disable function keys for UI
This fixes the issue where menus like the message mode can't be toggled
2024-09-18 21:51:35 +02:00
smallmodel 539688dd3d Reduced the delay to 33 ms (30 fps) to update the loading bar
This makes the loading bar smoother
2024-09-18 20:56:13 +02:00
smallmodel 08e09c3b4c Avoid setting variables with the same value
This prevents the console from being spammed with constant variable change when `developer` is set to 2
2024-09-18 20:55:02 +02:00
smallmodel 4259053c7e Expose methods for basic DMA (when OpenAL is unavailable) 2024-09-18 20:49:38 +02:00
smallmodel c221cfd493 Reorganize workflows and use multiple environments for different release stages 2024-09-18 20:33:30 +02:00
smallmodel 41298b53d4 Add PRODUCT_VERSION_STAGE variable to define the stage of the software through builds 2024-09-18 18:13:57 +02:00
smallmodel ddcd05adc6 Cancel other CodeQL actions on newer pushes 2024-09-18 17:10:25 +02:00
smallmodel a28cd64c7a Update implementation documentation again 2024-09-18 00:30:38 +02:00
smallmodel 38e62fef18 Update the implementation documentation with the current state 2024-09-18 00:26:51 +02:00
smallmodel 3f139f463b Remove stub print 2024-09-18 00:19:05 +02:00
smallmodel 0597191319 Implement SkelVec3::IsUnit 2024-09-18 00:18:08 +02:00
smallmodel f4c8b0c21f Initialize the cube build info
This should fix lighting being too dark or incorrect in some places
2024-09-17 22:22:42 +02:00
smallmodel bba7031f3d Add more clarity to code 2024-09-17 22:20:20 +02:00
smallmodel 4785913e02 compare_light_intensities should compare intensity as integers directly 2024-09-17 21:31:50 +02:00
smallmodel a6808d1f6a Fix incorrect light color for point lights and spot lights, also handle negative point light intensity
This fixes lighting from sphere being computed incorrectly for entities, making entities often look black or having strange lighting color
2024-09-17 21:27:14 +02:00
smallmodel 7188e9832a Fix leaf iteration 2024-09-17 20:51:00 +02:00
smallmodel 0cce0c81fb Prevent world values from being overridden by entities 2024-09-17 20:32:39 +02:00
smallmodel a60baa03e0 Add MAX_SPHERE_LIGHTS 2024-09-17 20:06:35 +02:00
smallmodel b0c8dafb33 Correctly compute colors for static model in vertex lit texture 2024-09-17 20:02:37 +02:00
smallmodel b672fc8b29 Add #if, #if_not and #else shader statements 2024-09-17 20:00:24 +02:00
smallmodel eac69f659f For dot/oneminusdot, shader needs normal 2024-09-17 20:00:00 +02:00
smallmodel d9ab65154c Fix incorrect lighting grid blend 2024-09-17 00:27:01 +02:00
smallmodel c120aed8bb Fix incorrect static model grid lighting 2024-09-16 22:11:58 +02:00
smallmodel ecdbe3d959 Don't check lightmap for RB_StageIteratorVertexLitTextureUnfogged to be used 2024-09-16 22:01:04 +02:00
smallmodel 96d10fb8b0 Mark r_light_nolight as cheat 2024-09-16 20:50:02 +02:00
smallmodel 2ab826268d Clear the legs state during the torso evaluation when the movecontrol is not legs
The legs state won't be stuck anymore waiting for an empty animation. This could happen under special circumstances, when the torso evaluation sets the movecontrol to non-legs (clears the legs anim) and then back to legs in subsequent iterations.
Fixes #105, the issue cannot be exploited anymore for land-sharking
2024-09-16 20:20:19 +02:00
smallmodel c3e3f368e0 use cheats rather than sv_cheats to check if the client is connected to a cheat server 2024-09-16 18:59:36 +02:00
smallmodel f35582489d Fix support for british, russian and italian voices in Spearhead and Breakthrough 2024-09-16 18:09:56 +02:00
smallmodel 9acea3484d Play zing sounds only if the location if the zing is valid
This fixes a potential crash where uninitialized position would be passed to the sound system
2024-09-16 17:39:15 +02:00
smallmodel a72da9b73e Fix incorrect terrain height for poly
This caused decals to float in the air when they were placed on the terrain
2024-09-15 23:49:42 +02:00
smallmodel df53d35967 Fix real dynamic lighting algorithm for both terrain and patch
This fixes #356 where real dynamic lighting would look completely wrong, making it look like there are graphical artifacts on surfaces
2024-09-15 21:23:17 +02:00
smallmodel e5e7421d3c Fix terrain lightmap when there is a dynamic light map
This fixes terrain having a completely wrong lightmap texture coordinates for dynamic lighting
2024-09-15 21:21:38 +02:00
smallmodel 6ff25d00fc Use lightmap offset for grid surface when a dlightmap is specified 2024-09-15 21:15:01 +02:00
smallmodel 4a5b0b3105 Fix y lightmap position when allocating a new lightmap block
See the issue with dynamic lights: #356
2024-09-15 19:39:22 +02:00
smallmodel d05d964432 Fix NaN lmapStep for terrain patches 2024-09-15 19:34:25 +02:00
smallmodel daa4a67b49 Reuse dlightmap in R_CheckDlightSurface and R_CheckDlightTerrain 2024-09-15 19:34:06 +02:00
smallmodel 9c0224911c Reset the number of dynamic lights when calculating the real terrain lighting
This fixes a crash that can occur when there is only the terrain that can be lit with dlights
2024-09-15 12:02:05 +02:00
smallmodel ef5759cff5 Don't execute commands during the intro 2024-09-15 01:21:20 +02:00
smallmodel 77292fb9ab First person spectator fix (not working yet) 2024-09-15 01:21:17 +02:00
smallmodel 6fb9ab078e Implement RE_DrawBackground_DrawPixels 2024-09-15 01:12:00 +02:00
smallmodel 844a72e0f3 Add DrawPixels and PixelZoom 2024-09-15 01:11:52 +02:00
smallmodel 46e9046629 Implement VehicleHalfTrack 2024-09-15 01:03:37 +02:00
smallmodel e5af60787e Partially implement GetZone/IsInZone 2024-09-15 00:42:35 +02:00
smallmodel 4b0696a187 Implement remaining methods of ClientGameCommandManager 2024-09-15 00:42:22 +02:00
smallmodel a6377fedab Remove useless code 2024-09-14 23:36:19 +02:00
smallmodel 2f884e6d55 Call Key_GetCatcher/Key_SetCatcher instead of modifying the variable directly 2024-09-14 23:32:24 +02:00
smallmodel 28f8c65771 Key_SetCatcher() must use cls.keyCatchers 2024-09-14 23:30:30 +02:00
smallmodel b509ef5ab4 Deactivate the mouse only when loading 2024-09-14 23:29:30 +02:00
smallmodel 9f48dabaec Play the game's intro when starting 2024-09-14 22:59:27 +02:00
smallmodel 5b0224ae3c Implement support for playing movies
Videos like briefings and intro are now played correctly
2024-09-14 22:58:43 +02:00
smallmodel c3ef267d6d Implement movie audio in OpenAL code 2024-09-14 21:55:15 +02:00
smallmodel fe9b298705 Export cl_movieaudio 2024-09-14 21:53:19 +02:00
smallmodel 0b106cf47e Print errors only when developer mode is set 2024-09-14 13:21:08 +02:00
smallmodel 9b417c9b26 Add EV_Client_ForceFeedback (unused) 2024-09-14 13:20:55 +02:00
smallmodel 37d5458c4c Partially implement cinematic support for reading RoQ files (no audio yet) 2024-09-13 23:00:31 +02:00
smallmodel 77d48cb104 Don't call UI_ClearBackground in cinematic mode 2024-09-13 22:58:37 +02:00
smallmodel a25200741a Finis the loading screen if it's the default 2024-09-13 22:23:53 +02:00
smallmodel d04a32920a Fix an incorrect parameter value passed to FS_Read when reading the DCL file 2024-09-13 21:49:45 +02:00
smallmodel 792b676c11 Set the number of brush models
The level marks system depends on the number of brush models and leafs, having a number that doesn't match what was saved would cause a crash
2024-09-13 21:47:57 +02:00
smallmodel 690a7a7557 Format cl_ui file 2024-09-13 21:36:23 +02:00
smallmodel e128c93ad9 Declare CL_FinishedStartStage 2024-09-13 21:25:41 +02:00
smallmodel 39add5ccec Fix incorrect parsing of music volumes 2024-09-13 20:01:01 +02:00
smallmodel a1a89cba34 Allow dynamic adjustment for the size of status columns in SVC_Status 2024-09-13 19:50:29 +02:00
smallmodel 2d696cf500 Also use the port when connecting to a server 2024-09-13 19:07:06 +02:00
smallmodel 45fe0bc8b7 Add an IP column
See #353 where servers would appear twice
2024-09-13 19:06:38 +02:00
smallmodel 9fc4c67187 Fix a crash when insep is 0 2024-09-13 19:05:30 +02:00
smallmodel 34aeab5f77 Fix the game type string being empty
(see #353 for the game type)
2024-09-13 18:34:43 +02:00
smallmodel b510452260 Remove useless comment 2024-09-12 23:48:46 +02:00
smallmodel 89b8d5a67b Use source files in renderercommon 2024-09-12 23:46:13 +02:00
smallmodel 500e3a3b2c Add support for JPEG screenshots 2024-09-12 23:33:39 +02:00
smallmodel 47e575ed9a define USE_INTERNAL_JPEG for compatible JPEG struct size 2024-09-12 23:33:21 +02:00
smallmodel 10b30d74e7 Implement sample_volume() 2024-09-12 22:23:27 +02:00
smallmodel 1ba4c6b7ad Remove useless comment 2024-09-12 22:18:09 +02:00
smallmodel eb899be95e Implement RE_GetGraphicsInfo 2024-09-12 21:40:07 +02:00
smallmodel 6d993af419 Fix compiler warning 2024-09-12 21:09:07 +02:00
smallmodel a136cccbe1 Implement R_CraterTerrain 2024-09-12 21:02:04 +02:00
smallmodel 2b43ebfca4 Add ter_crater command 2024-09-12 20:43:24 +02:00
smallmodel 06f4980ee1 Implement ghost textures with particles 2024-09-12 20:09:05 +02:00
smallmodel 6cdf5b7b7e Process .gst files 2024-09-12 19:44:36 +02:00
smallmodel 117b9a5579 Add declarations for GHOST functions 2024-09-12 19:42:41 +02:00
smallmodel 9475be8f6f Remove entityNumIndexes/staticModelNumIndexes from declaration as it causes compilation issue on some compilers 2024-09-11 23:41:47 +02:00
smallmodel 41ca1797f9 Implement basic GHOST methods and functions 2024-09-11 23:21:50 +02:00
smallmodel e56ae3d266 Update features.md 2024-09-11 21:07:55 +02:00
smallmodel 735ffaf80b Implement swipe 2024-09-11 19:57:45 +02:00
smallmodel ed52d1c648 Implement R_FastDlightTerrain 2024-09-11 19:19:38 +02:00
smallmodel 78fa90c59b Move RB_StaticMesh to tr_model.cpp for info world tris 2024-09-11 19:03:41 +02:00
smallmodel 548a3efe5a Implement R_InfoWorldTris_f and R_PrintInfoWorldtris 2024-09-11 18:57:50 +02:00
smallmodel 18a12eeba3 Fix loop breaking instead of continuing 2024-09-11 18:51:05 +02:00
smallmodel 83d486ceeb Add missing declarations 2024-09-11 18:48:47 +02:00
smallmodel d898c0f995 Implement R_PrintInfoStaticModels 2024-09-11 18:45:17 +02:00
smallmodel 02faf6f8c1 Implement R_Sky_ChangeFrustum 2024-09-11 18:27:19 +02:00
smallmodel 3478bbddf2 Implement RB_ComputeShadowVolume 2024-09-11 18:02:39 +02:00
smallmodel fd1ee31e1e Remove useless comment 2024-09-11 17:56:26 +02:00
smallmodel 4a565f0985 Declare R_GetLightingGridValueFast 2024-09-11 00:23:43 +02:00
smallmodel c68f23cdaf Fix compilation warnings 2024-09-11 00:21:31 +02:00
smallmodel e386eb00ef Implement all lighting functions 2024-09-11 00:12:13 +02:00
smallmodel 662d048bf4 Implement R_AddLightGridSurfacesToScene 2024-09-10 20:42:05 +02:00
smallmodel d9e3cc2188 Add a way to draw the skeleton for debugging purposes 2024-09-10 20:16:56 +02:00
smallmodel a586f13af8 Remove CL_GamespyServers_f as there is an existing implementation 2024-09-10 19:58:28 +02:00
smallmodel 37820c1673 Generate QKey 2024-09-10 19:57:25 +02:00
smallmodel 8a2e4ca470 Add Com_RandomBytes and Com_IsVoipTarget 2024-09-10 19:54:25 +02:00
smallmodel 3a5da64c6f Make radar clients speak on mohaas/mohaab 2024-09-10 19:50:43 +02:00
smallmodel 9c018a2330 Implement CGM_FENCEPOST 2024-09-10 19:40:53 +02:00
smallmodel 0840cdd83a Restore the old behavior where the bullet would hit all entities in sight. Only works when targeting mohaa version 1.x
Fixes #348. Since 2.0, bullet trace stops after the first hit entity even if it's a trigger, which can be an issue on some SP maps.
2024-09-10 19:01:34 +02:00
smallmodel e972747969 Update documentation
This adds an example for using fs_homepath
2024-09-09 23:59:06 +02:00
smallmodel e151c6eb15 Update documentation 2024-09-09 23:38:37 +02:00
smallmodel 603444a69f Fix an issue where the remaining time would reach 0:00 and the match would never end
See #287, this occurred when the fraglimit was defined.
2024-09-09 22:25:54 +02:00
smallmodel 999e0fd721 Implement test emitter 2024-09-09 21:48:40 +02:00
smallmodel 47131dec44 Fix wrong special effects count 2024-09-09 21:43:20 +02:00
smallmodel 6adad053d9 Explicitly disable looping when setting the sample loop count to a value other than 0
This fixes a rare occurrence where some sounds would loop forever
2024-09-09 00:15:39 +02:00
smallmodel 725561b655 Fix the usage of memory, strings, constant and parameters 2024-09-08 23:54:47 +02:00
smallmodel b84fbf452e Pass a vec4_t to GL_SetFogColor() rather than a vec3_t 2024-09-08 23:49:48 +02:00
smallmodel eb7af2bce9 Implement basic test emitter functions 2024-09-08 23:33:55 +02:00
smallmodel 7c57c4b131 Fix wrong secondary ammo type being picked up 2024-09-08 20:20:58 +02:00
smallmodel 4460466cb3 Implement RE_SetRenderTime 2024-09-08 19:43:37 +02:00
smallmodel eea19d733d Add R_UpdateGhostTextures (unimplemented) 2024-09-08 19:43:29 +02:00
smallmodel abc97dcab3 Implement R_AddTerrainMarkSurfaces and RE_AddTerrainMarkToScene 2024-09-08 19:40:00 +02:00
smallmodel 065c791a10 Implement CG_ResetEffectCommandCvars 2024-09-08 19:29:40 +02:00
smallmodel 6b902e7f5d Remove "unimplemented" comment 2024-09-08 18:49:45 +02:00
smallmodel df0cb87b35 Implement CG_AddLightShow (cg_acidtrip) 2024-09-08 18:48:15 +02:00
smallmodel 0b9687fea4 Implement functions for printing content types, surface properties and surface types 2024-09-08 18:39:39 +02:00
smallmodel 99fbe092bc Use correct names for surface flags 2024-09-08 18:34:02 +02:00
smallmodel 7a7849ae83 Remove comment 2024-09-08 18:25:10 +02:00
smallmodel 47830bb330 Update version number 2024-09-08 18:24:59 +02:00
smallmodel 0dfb1a3a2a Use Com_DPrintf for TIKI/alias warnings/errors
This prevent the console from getting spammed with developer errors in production
2024-09-08 18:22:12 +02:00
smallmodel e2e1ab0275 Fix status command column length breaking some programs 2024-09-08 18:09:54 +02:00
smallmodel 4249cacf2f Support token dollar in variable name
This fixes mods like trapshooting not working because of a '$' in a variable name
2024-09-08 18:03:43 +02:00
smallmodel 4e3ec52673 Fix a crash due to NULL string being appended 2024-09-08 18:02:57 +02:00
smallmodel 98991a4a7a Fix file ordering with uppercase/lowercase file names 2024-09-08 17:59:30 +02:00
smallmodel bca6d656b6 Fix bad verts value passed to CG_AddFragmentToScene 2024-09-08 17:53:35 +02:00
smallmodel ffc3580d43 Implement CG_CheckCaptureKey 2024-09-08 16:31:19 +02:00
smallmodel c18cdc78ea Fix Cgame key catching 2024-09-08 15:48:46 +02:00
smallmodel 77ecc73631 Implement lens flare / sun flares
Some maps like mohdm1 have a sun flares, now when you look up the sky towards the sun direction, you will see the flare of the sun
2024-09-08 15:31:18 +02:00
smallmodel 3834f51d74 Fix GetNamedWidget() always returning the last valid widget
This is problematic when doing different logic when a widget doesn't exist, for example when loading a map, if the continue button doesn't exist then the game should continue automatically
2024-09-08 15:06:43 +02:00
smallmodel 86ddec3f76 Clear the world to prevent crashes 2024-09-08 14:59:10 +02:00
smallmodel 4d12bcb184 Export s_sun 2024-09-08 00:52:03 +02:00
smallmodel 7d93723382 Update getting started doc 2024-09-07 23:58:56 +02:00
smallmodel 8e1a52bbb7 Implement VIS debugging 2024-09-07 23:58:50 +02:00
smallmodel cd9b1a741f Match CG_PermanentMark parameters
This fixes #355
2024-09-07 23:57:17 +02:00
smallmodel cefe331e0c Remove useless surface flags 2024-09-07 23:51:52 +02:00
smallmodel 14d1fae54a Implement all treadmark functions 2024-09-06 22:10:22 +02:00
smallmodel a1601be7a6 Implement code to make tread mark decals 2024-09-05 23:54:01 +02:00
smallmodel a2ebeb11e3 Update features.md 2024-09-05 23:10:50 +02:00
smallmodel b7f0f32878 Fix DCL signature on big-endian architectures 2024-09-05 01:14:42 +02:00
smallmodel 58e39add5b Implemented treadmarks update functions 2024-09-05 01:04:53 +02:00
smallmodel 61725c95df Add MASK_TREADMARKS 2024-09-05 00:43:36 +02:00
smallmodel 71a1df661a Fix current mark's alpha component not updating properly 2024-09-04 21:54:49 +02:00
smallmodel 9eed0eab5f Implement CG_PermanentMark 2024-09-04 21:51:42 +02:00
smallmodel e42b6fe0a9 Fix current mark not updating if it has a rotation 2024-09-04 21:51:16 +02:00
smallmodel b1e640ad1d Implement CG_PermanentMark 2024-09-04 21:41:16 +02:00
smallmodel 2fc091fdf7 Skip loading if the file length is less than the dcl header length 2024-09-04 20:56:41 +02:00
smallmodel 47ba241e7d Fix file being closed but still used afterwards 2024-09-04 20:50:22 +02:00
smallmodel c0d37c504a Fix infinite loop in R_TerrainHeightForPoly 2024-09-04 20:46:10 +02:00
smallmodel 1e0195f6e3 Add variables that will be used in unimplemented functions 2024-09-04 20:29:29 +02:00
smallmodel e806c1ddf1 Move MAX_MARK values to tr_types_new.h 2024-09-04 20:23:20 +02:00
smallmodel 78f0072c59 Update the SFX datasize when downsampling
This fixes #349 where the size of the AL buffer didn't match the real downsampled size, which would cause AL to read way past of end of the data buffer
2024-09-04 20:12:46 +02:00
smallmodel 1022ce531a Fix AL buffers having sound data past end of the sound buffer 2024-09-04 20:10:56 +02:00
smallmodel 7f08a7bca8 Remove register keyword as it's deprecated since C++17 2024-09-04 20:10:21 +02:00
smallmodel 4123bef60d Implement R_ApplyLevelDecal 2024-09-04 20:05:48 +02:00
smallmodel c6464efa07 Implement level mark loading and updating 2024-09-04 00:02:07 +02:00
453 changed files with 42995 additions and 84174 deletions

No files matched your search

+17
View File
@@ -0,0 +1,17 @@
name: Build branch
on:
push:
branches:
- '**'
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build-all:
uses: ./.github/workflows/shared-build.yml
with:
environment: "testing"
-256
View File
@@ -1,256 +0,0 @@
name: Build
on:
push:
branches:
- '**'
pull_request:
workflow_call:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: RelWithDebInfo
jobs:
build-platform-linux:
strategy:
matrix:
architecture: [
{name: 'amd64', triple: 'x86_64-linux-gnu'},
{name: 'i686', triple: 'i686-linux-gnu'},
{name: 'arm64', triple: 'aarch64-linux-gnu'},
{name: 'armhf', triple: 'arm-linux-gnueabihf'},
{name: 'powerpc', triple: 'powerpc-linux-gnu'},
{name: 'ppc64', triple: 'powerpc64-linux-gnu'},
{name: 'ppc64el', triple: 'powerpc64le-linux-gnu'}
]
name: "Building for platform linux-${{matrix.architecture.name}}"
runs-on: ubuntu-22.04
steps:
- name: Settings
working-directory: ${{github.workspace}}
run: |
echo "CMAKE_BUILD_PARALLEL_LEVEL=$(($(nproc) * 16))" >> $GITHUB_ENV
# echo "CMAKE_GENERATOR=Ninja" >> $GITHUB_ENV
- name: Install required packages
run: |
sudo apt update && sudo apt install -y flex bison \
libpulse-dev portaudio19-dev libasound2-dev libjack-dev libpipewire-0.3-dev qtbase5-dev libdbus-1-dev
- name: Install required cross-platform packages (${{ matrix.architecture.triple }})
if: matrix.architecture.name != 'amd64'
run: sudo apt install -y gcc-12-${{ matrix.architecture.triple }} g++-12-${{ matrix.architecture.triple }}
# Setup SDL
- name: Set up SDL
id: sdl
uses: libsdl-org/setup-sdl@main
with:
version: sdl2-latest
build-type: Release
cmake-arguments: "-DCMAKE_C_COMPILER=clang
-DCMAKE_CXX_COMPILER=clang++
-DCMAKE_C_FLAGS=--target=${{ matrix.architecture.triple }}
-DCMAKE_CXX_FLAGS=--target=${{ matrix.architecture.triple }}"
# soft-oal setup
# Use GCC instead of Clang because of missing SSE intrinsics
# It also doesn't enable altivec support on PowerPC by default
- name: Checkout soft-oal
uses: actions/checkout@v4
with:
repository: 'kcat/openal-soft'
path: 'thirdparties/soft-oal'
ref: '1.23.1'
- name: Configure and install soft-oal
working-directory: ${{github.workspace}}/thirdparties/soft-oal
run: |
cmake -B ./build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
-DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/soft-oal/install' \
-DCMAKE_C_COMPILER=${{ matrix.architecture.triple }}-gcc-12 \
-DCMAKE_CXX_COMPILER=${{ matrix.architecture.triple }}-g++-12
cmake --build ./build --config ${{env.BUILD_TYPE}}
cmake --install ./build --config ${{env.BUILD_TYPE}}
- uses: actions/checkout@v4
with:
path: 'source'
- name: CMake Settings
run: |
echo "CMAKE_PARAM=--log-level=VERBOSE \
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} \
-DCMAKE_INSTALL_PREFIX='${{github.workspace}}/install' \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_C_FLAGS=--target=${{ matrix.architecture.triple }} \
-DCMAKE_CXX_FLAGS=--target=${{ matrix.architecture.triple }} \
-DOPENAL_LIBRARY='${{github.workspace}}/thirdparties/soft-oal' \
-DOPENAL_INCLUDE_DIR='${{github.workspace}}/thirdparties/soft-oal/include' \
-DGIT_REVISION_BUILD_NUMBER=${{ github.run_number }}" >> $GITHUB_ENV
- name: Configure CMake
working-directory: ${{github.workspace}}
run: |
cmake -B ./build ${{ env.CMAKE_PARAM }} ./source
- name: Build
working-directory: ${{github.workspace}}
run: |
cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
- name: Test
working-directory: ${{github.workspace}}
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: |
cd "${{github.workspace}}/build"
ctest -C ${{env.BUILD_TYPE}}
- name: Install
working-directory: ${{github.workspace}}
# Install to the directory defined in CMAKE_INSTALL_PREFIX
run: |
cmake --install ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
# Create hard-link and copy symbolic links
cp -l ${{steps.sdl.outputs.prefix}}/lib/libSDL2-2.0.so.0 '${{github.workspace}}/install/'
cp -l ${{github.workspace}}/thirdparties/soft-oal/install/lib/libopenal.so.1 '${{github.workspace}}/install/'
- uses: actions/upload-artifact@v4
with:
name: out-linux-${{matrix.architecture.name}}
if-no-files-found: error
path:
${{github.workspace}}/install
build-platform-windows:
strategy:
matrix:
architecture: [
{name: 'x64', config: 'x64' },
{name: 'x86', config: 'Win32' },
{name: 'arm64', config: 'ARM64' }
]
name: "Building for platform windows-${{matrix.architecture.name}}"
runs-on: windows-2022
steps:
- name: Settings
working-directory: ${{github.workspace}}
run: |
echo "CMAKE_BUILD_PARALLEL_LEVEL=$((Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors * 16)" >> $GITHUB_ENV
# Setup SDL
- name: Set up SDL
id: sdl
uses: libsdl-org/setup-sdl@main
with:
version: sdl2-latest
build-type: Release
cmake-arguments: "-A ${{ matrix.architecture.config }}"
- name: Install Flex/Bison
working-directory: ${{github.workspace}}
run: |
mkdir thirdparties && cd thirdparties
git clone --depth 1 --single-branch --branch v2.5.25 https://github.com/lexxmark/winflexbison.git
cmake -B winflexbison-build -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/winflexbison-install' ./winflexbison
cmake --build winflexbison-build --config Release --parallel
cmake --install winflexbison-build
# soft-oal setup
- name: Checkout soft-oal
uses: actions/checkout@v4
with:
repository: 'kcat/openal-soft'
path: 'thirdparties/soft-oal'
ref: '1.23.1'
# soft-oal build
# Statically link the CRT runtime into OAL as a workaround to prevent crashes
- name: Configure and install soft-oal
working-directory: ${{github.workspace}}/thirdparties/soft-oal
run: |
cmake -B ./build -A ${{ matrix.architecture.config }} `
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} `
-DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/soft-oal/install' `
-DALSOFT_BUILD_ROUTER=OFF `
-DALSOFT_REQUIRE_WINMM=ON `
-DALSOFT_REQUIRE_DSOUND=ON `
-DALSOFT_REQUIRE_WASAPI=ON `
-DCMAKE_C_FLAGS_RELEASE="/MT /O2 /Ob2 /DNDEBUG" `
-DCMAKE_CXX_FLAGS_RELEASE="/MT /O2 /Ob2 /DNDEBUG" `
-DCMAKE_C_FLAGS_MINSIZEREL="/MT /O2 /Ob2 /DNDEBUG" `
-DCMAKE_CXX_FLAGS_MINSIZEREL="/MT /O1 /Ob1 /DNDEBUG" `
-DCMAKE_C_FLAGS_RELWITHDEBINFO="/MT /Zi /O2 /Ob1 /DNDEBUG" `
-DCMAKE_CXX_FLAGS_RELWITHDEBINFO="/MT /Zi /O2 /Ob1 /DNDEBUG"
cmake --build ./build --config ${{env.BUILD_TYPE}}
cmake --install ./build --config ${{env.BUILD_TYPE}}
# Unfortunately soft-oal produces a binary called OpenAL32 even in 64-bit
if (("x64", "ARM64") -icontains "${{ matrix.architecture.config }}") { Rename-Item -Path '.\install\bin\OpenAL32.dll' -NewName 'OpenAL64.dll' }
- uses: actions/checkout@v4
with:
path: 'source'
- name: CMake Settings
run: |
echo "CMAKE_PARAM=-A ${{ matrix.architecture.config }} `
--log-level=VERBOSE `
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} `
-DCMAKE_INSTALL_PREFIX='${{github.workspace}}/install' `
-DGIT_REVISION_BUILD_NUMBER=${{ github.run_number }} `
-DBISON_EXECUTABLE='${{github.workspace}}/thirdparties/winflexbison-install/win_bison.exe' `
-DOPENAL_LIBRARY='${{github.workspace}}/thirdparties/soft-oal' `
-DOPENAL_INCLUDE_DIR='${{github.workspace}}/thirdparties/soft-oal/include' `
-DFLEX_EXECUTABLE='${{github.workspace}}/thirdparties/winflexbison-install/win_flex.exe'".Replace("`r", "").Replace("`n", "") >> $env:GITHUB_ENV
- name: Configure CMake
working-directory: ${{github.workspace}}
run: |
cmake -B ./build ${{ env.CMAKE_PARAM }} ./source
- name: Build
working-directory: ${{github.workspace}}
run: |
cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
- name: Test
working-directory: ${{github.workspace}}
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: |
cd "${{github.workspace}}/build"
ctest -C ${{env.BUILD_TYPE}}
- name: Install
working-directory: ${{github.workspace}}
# Install to the directory defined in CMAKE_INSTALL_PREFIX
run: |
cmake --install ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
Copy-Item '${{steps.sdl.outputs.prefix}}/bin/*.dll' -Destination '${{github.workspace}}/install'
Copy-Item '${{github.workspace}}/thirdparties/soft-oal/install/bin/*.dll' -Destination '${{github.workspace}}/install'
- uses: actions/upload-artifact@v4
with:
name: out-windows-${{matrix.architecture.name}}
if-no-files-found: error
path: |
${{github.workspace}}/install
!${{github.workspace}}/install/**/*.pdb
- uses: actions/upload-artifact@v4
with:
name: out-windows-${{matrix.architecture.name}}-pdb
if-no-files-found: error
path: |
${{github.workspace}}/install
@@ -20,6 +20,10 @@ on:
schedule:
- cron: '42 8 * * 1'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
analyze:
name: Analyze
+477
View File
@@ -0,0 +1,477 @@
name: Shared build workflow
on:
workflow_call:
inputs:
environment:
required: true
type: string
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: RelWithDebInfo
RELEASE_STAGE: ${{ vars.RELEASE_STAGE || 'unstable' }}
jobs:
##########################
#
# Linux
# Ubuntu 22.04
#
# Using this version instead of 24.04 to use a lower GLIBC version (2.34)
##########################
build-platform-linux:
strategy:
matrix:
architecture: [
{name: 'amd64', triple: 'x86_64-linux-gnu'},
{name: 'i686', triple: 'i686-linux-gnu'},
{name: 'arm64', triple: 'aarch64-linux-gnu'},
{name: 'armhf', triple: 'arm-linux-gnueabihf'},
{name: 'powerpc', triple: 'powerpc-linux-gnu'},
{name: 'ppc64', triple: 'powerpc64-linux-gnu'},
{name: 'ppc64el', triple: 'powerpc64le-linux-gnu'}
]
name: "Building for platform linux-${{matrix.architecture.name}}"
runs-on: "ubuntu-22.04"
environment: ${{ inputs.environment }}
steps:
###
# Packages
###
- uses: awalsh128/cache-apt-pkgs-action@latest
name: Install required packages
with:
packages: flex bison ninja-build cmake clang libpulse-dev portaudio19-dev libasound2-dev libjack-dev libpipewire-0.3-dev qtbase5-dev libdbus-1-dev
version: "0.1"
- uses: awalsh128/cache-apt-pkgs-action@latest
name: Install required cross-platform packages (${{ matrix.architecture.triple }})
if: matrix.architecture.name != 'amd64'
with:
packages: gcc-12-${{ matrix.architecture.triple }} g++-12-${{ matrix.architecture.triple }}
version: "0.1"
- name: Settings
working-directory: ${{github.workspace}}
run: |
echo "CMAKE_GENERATOR=Ninja Multi-Config" >> $GITHUB_ENV
echo "CC=clang" >> $GITHUB_ENV
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
###
# Setup SDL
- name: Set up SDL
id: sdl
uses: libsdl-org/setup-sdl@main
with:
version: 2-latest
build-type: Release
# Workaround for when changing the runner OS version
cmake-arguments: "-DCACHE_OS_VERSION=Ubuntu_22.04"
###
# OpenAL
###
# soft-oal setup
- name: Checkout soft-oal
uses: actions/checkout@v4
with:
repository: 'kcat/openal-soft'
path: 'thirdparties/soft-oal'
ref: ${{ env.OPENAL_REF }}
- 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'
cmake --build ./build --config Release --parallel
cmake --install ./build --config Release
###
# Project
###
- uses: actions/checkout@v4
with:
path: 'source'
- name: CMake Settings
run: |
echo "CMAKE_PARAM=--log-level=VERBOSE \
-DCMAKE_INSTALL_PREFIX='${{github.workspace}}/install' \
-DOPENAL_LIBRARY='${{github.workspace}}/thirdparties/soft-oal' \
-DOPENAL_INCLUDE_DIR='${{github.workspace}}/thirdparties/soft-oal/include' \
-DGIT_REVISION_BUILD_NUMBER=${{ github.run_number }} \
-DPRODUCT_VERSION_STAGE='${{ env.RELEASE_STAGE }}'" >> $GITHUB_ENV
- name: Configure CMake
working-directory: ${{github.workspace}}
run: |
cmake -B ./build ${{ env.CMAKE_PARAM }} ./source
- name: Build
working-directory: ${{github.workspace}}
run: |
cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel
- name: Test
working-directory: ${{github.workspace}}
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: |
cd "${{github.workspace}}/build"
ctest -C ${{env.BUILD_TYPE}}
- name: Install
working-directory: ${{github.workspace}}
# Install to the directory defined in CMAKE_INSTALL_PREFIX
run: |
cmake --install ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
# Copy libraries
mkdir ${{github.workspace}}/package
cp -l ${{steps.sdl.outputs.prefix}}/lib/libSDL2-2.0.so.0 '${{github.workspace}}/package/'
cp -l ${{github.workspace}}/thirdparties/soft-oal/install/lib/libopenal.so.1 '${{github.workspace}}/package/'
if [ -d ${{github.workspace}}/install/bin ]; then cp -r ${{github.workspace}}/install/bin/openmohaa/. '${{github.workspace}}/package'; fi
if [ -d ${{github.workspace}}/install/lib ]; then cp -r ${{github.workspace}}/install/lib/openmohaa/. '${{github.workspace}}/package'; fi
###
# Artifacts
###
- uses: actions/upload-artifact@v4
with:
name: out-linux-${{matrix.architecture.name}}
if-no-files-found: error
path:
${{github.workspace}}/package
##########################
#
# Microsoft Windows
# Windows Server 2022
#
##########################
build-platform-windows:
strategy:
matrix:
architecture: [
{name: 'x64', config: 'x64', toolset: 'x64' },
{name: 'x86', config: 'Win32', toolset: 'x64_x86' },
{name: 'arm64', config: 'ARM64', toolset: 'x64_arm64' }
]
name: "Building for platform windows-${{matrix.architecture.name}}"
runs-on: "windows-2022"
environment: ${{ inputs.environment }}
steps:
###
# Packages
###
#
# Commented out for now, chocolatey servers started complaining about too many requests
#
#- name: Install required packages
# run: |
# choco install -y ninja
- name: Install required packages
run: |
$DownloadPath="$($env:USERPROFILE)\Downloads"
Invoke-WebRequest "https://github.com/ninja-build/ninja/releases/download/v1.12.1/ninja-win.zip" -OutFile "$DownloadPath\ninja-win.zip"
Expand-Archive -Path "$DownloadPath\ninja-win.zip" -DestinationPath "$($env:PROGRAMFILES)\ninja"
echo "$($env:PROGRAMFILES)\ninja" >> $GITHUB_PATH
- name: Install Flex/Bison
working-directory: ${{github.workspace}}
run: |
mkdir thirdparties && cd thirdparties
git clone --depth 1 --single-branch --branch v2.5.25 https://github.com/lexxmark/winflexbison.git
cmake -B winflexbison-build -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/winflexbison-install' ./winflexbison
cmake --build winflexbison-build --config Release --parallel
cmake --install winflexbison-build --config Release
- name: Settings
working-directory: ${{github.workspace}}
run: |
echo "CMAKE_GENERATOR=Ninja Multi-Config" >> $env:GITHUB_ENV
echo "CC=cl.exe" >> $env:GITHUB_ENV
echo "CXX=cl.exe" >> $env:GITHUB_ENV
pushd "$($env:PROGRAMFILES)\Microsoft Visual Studio\*\*\VC\Auxiliary\Build"
cmd /c "vcvarsall.bat ${{ matrix.architecture.toolset }} & set" | ForEach-Object {
if ($_ -match "=") {
# Split into key=value
$var = $_.split("=", 2);
echo "$($var[0])=$($var[1])" >> $env:GITHUB_ENV
}
}
popd
###
# SDL
###
# Setup SDL
- name: Set up SDL
id: sdl
uses: libsdl-org/setup-sdl@main
with:
version: 2-latest
build-type: Release
cmake-arguments: ""
###
# OpenAL
###
# soft-oal setup
- name: Checkout soft-oal
uses: actions/checkout@v4
with:
repository: 'kcat/openal-soft'
path: 'thirdparties/soft-oal'
ref: '1.24.0'
# soft-oal build
# Statically link the CRT runtime into OAL as a workaround to prevent crashes
- 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' `
-DALSOFT_BUILD_ROUTER=OFF `
-DALSOFT_REQUIRE_WINMM=ON `
-DALSOFT_REQUIRE_DSOUND=ON `
-DALSOFT_REQUIRE_WASAPI=ON `
-DCMAKE_C_FLAGS_RELEASE="/MT /O2 /Ob2 /DNDEBUG" `
-DCMAKE_CXX_FLAGS_RELEASE="/MT /O2 /Ob2 /DNDEBUG" `
-DCMAKE_C_FLAGS_MINSIZEREL="/MT /O2 /Ob2 /DNDEBUG" `
-DCMAKE_CXX_FLAGS_MINSIZEREL="/MT /O1 /Ob1 /DNDEBUG" `
-DCMAKE_C_FLAGS_RELWITHDEBINFO="/MT /Zi /O2 /Ob1 /DNDEBUG" `
-DCMAKE_CXX_FLAGS_RELWITHDEBINFO="/MT /Zi /O2 /Ob1 /DNDEBUG"
cmake --build ./build --config Release --parallel
cmake --install ./build --config Release
# Unfortunately soft-oal produces a binary called OpenAL32 even in 64-bit
if (("x64", "ARM64") -icontains "${{ matrix.architecture.config }}") { Rename-Item -Path '.\install\bin\OpenAL32.dll' -NewName 'OpenAL64.dll' }
###
# Project
###
- uses: actions/checkout@v4
with:
path: 'source'
- name: CMake Settings
run: |
echo "CMAKE_PARAM= `
--log-level=VERBOSE `
-DCMAKE_INSTALL_PREFIX='${{github.workspace}}/install' `
-DGIT_REVISION_BUILD_NUMBER=${{ github.run_number }} `
-DBISON_EXECUTABLE='${{github.workspace}}/thirdparties/winflexbison-install/win_bison.exe' `
-DOPENAL_LIBRARY='${{github.workspace}}/thirdparties/soft-oal' `
-DOPENAL_INCLUDE_DIR='${{github.workspace}}/thirdparties/soft-oal/include' `
-DFLEX_EXECUTABLE='${{github.workspace}}/thirdparties/winflexbison-install/win_flex.exe' `
-DPRODUCT_VERSION_STAGE='${{ env.RELEASE_STAGE }}'".Replace("`r", "").Replace("`n", "") >> $env:GITHUB_ENV
- name: Configure CMake
working-directory: ${{github.workspace}}
run: |
cmake -B ./build ${{ env.CMAKE_PARAM }} ./source
- name: Build
working-directory: ${{github.workspace}}
run: |
cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel
- name: Test
working-directory: ${{github.workspace}}
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: |
cd "${{github.workspace}}/build"
ctest -C ${{env.BUILD_TYPE}}
- name: Install
working-directory: ${{github.workspace}}
# Install to the directory defined in CMAKE_INSTALL_PREFIX
run: |
cmake --install ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
New-Item -ItemType Directory '${{github.workspace}}/package'
Copy-Item '${{steps.sdl.outputs.prefix}}/bin/*.dll' -Destination '${{github.workspace}}/package'
Copy-Item '${{github.workspace}}/thirdparties/soft-oal/install/bin/*.dll' -Destination '${{github.workspace}}/package'
if (Test-Path ${{github.workspace}}/install/bin) { Copy-Item '${{github.workspace}}/install/bin/*' -Include '*.dll','*.exe','*.pdb' -Destination '${{github.workspace}}/package' }
if (Test-Path ${{github.workspace}}/install/lib) { Copy-Item '${{github.workspace}}/install/lib/*' -Include '*.dll','*.exe','*.pdb' -Destination '${{github.workspace}}/package' }
###
# Artifact
###
- uses: actions/upload-artifact@v4
with:
name: out-windows-${{matrix.architecture.name}}
if-no-files-found: error
path: |
${{github.workspace}}/package
!${{github.workspace}}/package/**/*.pdb
- uses: actions/upload-artifact@v4
with:
name: out-windows-${{matrix.architecture.name}}-pdb
if-no-files-found: error
path: |
${{github.workspace}}/package
##########################
#
# Apple macOS
# macOS 14
#
# This version is used as the OS, as older versions are slower.
##########################
build-platform-macos:
strategy:
matrix:
architecture: [
{name: 'x86_64', triple: 'x86_64-apple-macos10.8'},
{name: 'arm64', triple: 'arm64-apple-macos11'}
]
name: "Building for platform macos-${{matrix.architecture.name}}"
runs-on: "macos-14"
environment: ${{inputs.environment}}
steps:
###
# Packages
###
# Install required packages
# Paths on x86_64 and ARM64 are different for homebrew
- name: Install required packages
run: |
brew update && brew install git flex bison ninja cmake llvm ninja
- name: Settings
working-directory: ${{github.workspace}}
run: |
echo "CMAKE_GENERATOR=Ninja Multi-Config" >> $GITHUB_ENV
echo "CC=clang" >> $GITHUB_ENV
echo "CXX=clang++" >> $GITHUB_ENV
echo "MACOSX_DEPLOYMENT_TARGET=10.15" >> $GITHUB_ENV
###
# SDL
###
# Setup SDL
- name: Set up SDL
id: sdl
uses: libsdl-org/setup-sdl@main
with:
version: 2-latest
build-type: Release
cmake-arguments: "-DCMAKE_OSX_ARCHITECTURES=${{ matrix.architecture.name }}
-DCMAKE_VERBOSE_MAKEFILE=on"
###
# OpenAL
###
# soft-oal setup
# Use GCC instead of Clang because of missing SSE intrinsics
# It also doesn't enable altivec support on PowerPC by default
- name: Checkout soft-oal
uses: actions/checkout@v4
with:
repository: 'kcat/openal-soft'
path: 'thirdparties/soft-oal'
ref: '1.24.0'
- 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_VERBOSE_MAKEFILE=on
cmake --build ./build --config Release --parallel
cmake --install ./build --config Release
###
# Project
###
- uses: actions/checkout@v4
with:
path: 'source'
- name: CMake Settings
run: |
echo "CMAKE_PARAM=--log-level=VERBOSE \
-DCMAKE_INSTALL_PREFIX='${{github.workspace}}/install' \
-DCMAKE_VERBOSE_MAKEFILE=on \
-DCMAKE_OSX_ARCHITECTURES=${{ matrix.architecture.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 }} \
-DPRODUCT_VERSION_STAGE='${{ env.RELEASE_STAGE }}'" >> $GITHUB_ENV
- name: Configure CMake
working-directory: ${{github.workspace}}
run: |
cmake -B ./build ${{ env.CMAKE_PARAM }} ./source
- name: Build
working-directory: ${{github.workspace}}
run: |
cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} --parallel
- name: Test
working-directory: ${{github.workspace}}
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: |
cd "${{github.workspace}}/build"
ctest -C ${{env.BUILD_TYPE}}
- name: Install
working-directory: ${{github.workspace}}
# Install to the directory defined in CMAKE_INSTALL_PREFIX
run: |
cmake --install ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
# Create hard-link and copy symbolic links
mkdir ${{github.workspace}}/package
cp -l ${{steps.sdl.outputs.prefix}}/lib/libSDL2-2.0.0.dylib '${{github.workspace}}/package/'
cp -l ${{github.workspace}}/thirdparties/soft-oal/install/lib/libopenal.1.dylib '${{github.workspace}}/package/'
if [ -d ${{github.workspace}}/install/bin ]; then cp -r ${{github.workspace}}/install/bin/openmohaa/. '${{github.workspace}}/package'; fi
if [ -d ${{github.workspace}}/install/lib ]; then cp -r ${{github.workspace}}/install/lib/openmohaa/. '${{github.workspace}}/package'; fi
###
# Artifacts
###
- uses: actions/upload-artifact@v4
with:
name: out-macos-${{matrix.architecture.name}}
if-no-files-found: error
path:
${{github.workspace}}/package
@@ -6,7 +6,7 @@ on:
- "v*.*.*"
env:
RELEASE_TYPE: ${{ vars.RELEASE_TYPE || 'test' }}
RELEASE_STAGE: ${{ vars.RELEASE_STAGE || 'unstable' }}
RELEASE_IS_PRERELEASE: ${{ vars.RELEASE_IS_PRELEASE }}
permissions:
@@ -14,7 +14,9 @@ permissions:
jobs:
build-all:
uses: ./.github/workflows/build-cmake.yml
uses: ./.github/workflows/shared-build.yml
with:
environment: "release"
deploy_all:
strategy:
@@ -31,15 +33,17 @@ jobs:
'linux-ppc64',
'linux-ppc64el',
'windows-x64',
'windows-x86',
'windows-x64-pdb',
'windows-x86',
'windows-x86-pdb',
'windows-arm64',
'windows-arm64-pdb'
'windows-arm64-pdb',
'macos-x86_64',
'macos-arm64'
]
runs-on: ubuntu-22.04
environment: release
runs-on: ubuntu-24.04
environment: "release"
needs: [build-all]
env:
@@ -58,6 +62,6 @@ jobs:
- name: Release
uses: softprops/action-gh-release@v2
with:
name: '${{github.ref_name}}-${{env.RELEASE_TYPE}}'
name: '${{github.ref_name}}-${{env.RELEASE_STAGE}}'
prerelease: ${{env.RELEASE_IS_PRERELEASE}}
files: ${{github.workspace}}/${{ env.RELEASE_NAME }}.zip
+142 -17
View File
@@ -5,6 +5,14 @@ include(TargetArch.cmake)
target_architecture(TARGET_ARCH)
set(USE_INTERNAL_LIBS ON)
if(USE_SYSTEM_LIBS)
set(USE_INTERNAL_LIBS OFF)
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})
if(TARGET_GAME_TYPE)
message(SEND_ERROR "TARGET_GAME_TYPE is now unsupported, it is now done at runtime.")
@@ -14,23 +22,35 @@ endif()
set(TARGET_BASE_GAME "./")
set(CMAKE_DEBUG_POSTFIX "-dbg")
#
# Microsoft compiler specific parameters
#
if(MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE)
# Treat no return type as error
add_compile_options(/we4715)
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
#
# Clang and GCC specific parameters
#
if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
add_compile_options(-Wno-comment)
# Treat no return type as error
add_compile_options(-Werror=return-type)
endif()
#
# Clang specific parameters
#
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# Ignore warnings for code like 'assert("Assert string")'
add_compile_options(-Wno-pointer-bool-conversion)
endif()
#
# GCC specific parameters
#
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# Add this option on gcc to prevent functions from having the STB_GNU_UNIQUE binding
# Otherwise, it would prevent libraries from being unloaded
@@ -48,6 +68,8 @@ ELSE()
set(TARGET_ARCH_SUFFIX ${TARGET_ARCH})
ENDIF()
set(TARGET_BIN_SUFFIX ".${TARGET_ARCH}")
message(STATUS "Architecture detected: ${TARGET_ARCH}, suffix set to ${TARGET_ARCH_SUFFIX}.")
IF(WIN32)
@@ -61,7 +83,7 @@ ELSE()
ENDIF()
IF(CMAKE_BUILD_TYPE MATCHES Debug)
add_definitions(-D_DEBUG)
add_compile_definitions(_DEBUG)
# NOTE: The following may mess up function importation
#if(UNIX)
@@ -69,18 +91,60 @@ IF(CMAKE_BUILD_TYPE MATCHES Debug)
# set(CMAKE_ENABLE_EXPORTS ON)
# message(STATUS "Enabling exports on Unix for backtrace")
#endif()
ELSE()
# Non-debug builds
add_compile_definitions(NDEBUG)
ENDIF()
# Common stuff
if(APPLE)
# macOS doesn't search the executable path by default
# so, locate libraries like SDL in the executable path
set(CMAKE_INSTALL_RPATH "@executable_path")
set(CMAKE_BUILD_WITH_INSTALL_RPATH ON)
if(CMAKE_C_COMPILER_ID MATCHES "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "GNU")
# Set the visibility to hidden on macOS to prevent shared libraries from
# using functions in the executable
# it's ok to hide them because the backtrace on macOS will still print the name of the functions
add_compile_options(-fvisibility=hidden)
endif()
endif()
#
# Setup the installation directory
#
if(WIN32)
# By default, both DLLs and EXEs are in the same directory
set(CMAKE_DEFAULT_INSTALL_RUNTIME_DIR bin)
set(BIN_INSTALL_SUBDIR ".")
set(LIB_INSTALL_SUBDIR ".")
else()
# Unix
set(CMAKE_DEFAULT_INSTALL_RUNTIME_DIR lib)
set(BIN_INSTALL_SUBDIR ${CMAKE_PROJECT_NAME})
set(LIB_INSTALL_SUBDIR ${CMAKE_PROJECT_NAME})
endif()
# By default, put both binaries and shared libraries in the same directory
# the game uses internal shared libraries that must be in the same folder as the binaries
set(CMAKE_INSTALL_BINDIR ${CMAKE_DEFAULT_INSTALL_RUNTIME_DIR} CACHE PATH "Binary dir")
set(CMAKE_INSTALL_LIBDIR ${CMAKE_INSTALL_BINDIR} CACHE PATH "Library dir")
include(GNUInstallDirs)
#
# Common stuff
#
add_subdirectory("code/qcommon")
add_subdirectory("code/gamespy")
#
# Application
#
add_subdirectory("code/sys")
##
## Server app
##
add_subdirectory("code/server")
add_executable(omohaaded "code/null/null_client.c" "code/null/null_input.c" "code/null/null_snddma.c")
@@ -91,21 +155,23 @@ target_link_libraries(omohaaded PRIVATE omohserver)
target_link_libraries(omohaaded PRIVATE syslib)
target_link_libraries(omohaaded PRIVATE qcommon qcommon_standalone)
# Gamespy dependency
# Add the gamespy dependency
target_include_directories(omohaaded PUBLIC "code/qcommon" "code/script" "code/gamespy" "code/server")
set_target_properties(omohaaded PROPERTIES OUTPUT_NAME "omohaaded${TARGET_BASE_SUFFIX}${TARGET_ARCH_SUFFIX}")
set_target_properties(omohaaded PROPERTIES OUTPUT_NAME "omohaaded${TARGET_BIN_SUFFIX}")
set_target_properties(omohaaded PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
INSTALL(TARGETS omohaaded DESTINATION ${CMAKE_INSTALL_BINDIR}/${BIN_INSTALL_SUBDIR})
if (MSVC)
target_link_options(omohaaded PRIVATE "/MANIFEST:NO")
INSTALL(FILES $<TARGET_PDB_FILE:omohaaded> DESTINATION "./" OPTIONAL)
INSTALL(FILES $<TARGET_PDB_FILE:omohaaded> DESTINATION ${CMAKE_INSTALL_BINDIR}/${BIN_INSTALL_SUBDIR} OPTIONAL)
endif()
INSTALL(TARGETS omohaaded DESTINATION "./")
if (NOT BUILD_NO_CLIENT)
##
## Client app
##
add_subdirectory("code/client")
add_subdirectory("code/renderer")
add_subdirectory("code/sdl")
@@ -121,18 +187,77 @@ if (NOT BUILD_NO_CLIENT)
target_link_libraries(openmohaa PRIVATE omohclient)
target_link_libraries(openmohaa PRIVATE omohrenderer omohsdl)
target_link_libraries(openmohaa PRIVATE qcommon qcommon_standalone)
### Gamespy dependency
target_include_directories(openmohaa PUBLIC "code/qcommon" "code/script" "code/gamespy" "code/server" "code/client" "code/uilib" "code/jpeg-8c")
set_target_properties(openmohaa PROPERTIES OUTPUT_NAME "openmohaa${TARGET_BASE_SUFFIX}${TARGET_ARCH_SUFFIX}")
# 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}")
set_target_properties(openmohaa PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
target_link_libraries(openmohaa PRIVATE jpeg8)
if(USE_INTERNAL_JPEG)
target_include_directories(openmohaa PUBLIC "code/jpeg-8c")
target_link_libraries(openmohaa PRIVATE jpeg8)
else()
find_package(JPEG REQUIRED)
target_include_directories(openmohaa PUBLIC ${JPEG_INCLUDE_DIRS})
target_link_libraries(openmohaa PRIVATE ${JPEG_LIBRARIES})
endif()
INSTALL(TARGETS openmohaa DESTINATION ${CMAKE_INSTALL_BINDIR}/${BIN_INSTALL_SUBDIR})
if (MSVC)
target_link_options(openmohaa PRIVATE "/MANIFEST:NO")
INSTALL(FILES $<TARGET_PDB_FILE:openmohaa> DESTINATION "./" OPTIONAL)
INSTALL(FILES $<TARGET_PDB_FILE:openmohaa> DESTINATION ${CMAKE_INSTALL_BINDIR}/${BIN_INSTALL_SUBDIR} OPTIONAL)
endif()
INSTALL(TARGETS openmohaa DESTINATION "./")
if(UNIX AND NOT APPLE)
#
# Desktop entries installation on Unix
#
set(TARGET_ARCH ${TARGET_BIN_SUFFIX})
# Configure the .desktop entries with the arch suffix
configure_file(
misc/linux/org.openmoh.openmohaa.desktop.in
${CMAKE_BINARY_DIR}/misc/linux/org.openmoh.openmohaa.desktop
@ONLY
)
configure_file(
misc/linux/org.openmoh.openmohaab.desktop.in
${CMAKE_BINARY_DIR}/misc/linux/org.openmoh.openmohaab.desktop
@ONLY
)
configure_file(
misc/linux/org.openmoh.openmohaas.desktop.in
${CMAKE_BINARY_DIR}/misc/linux/org.openmoh.openmohaas.desktop
@ONLY
)
# Install .desktop entries
install(FILES ${CMAKE_BINARY_DIR}/misc/linux/org.openmoh.openmohaa.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications)
install(FILES ${CMAKE_BINARY_DIR}/misc/linux/org.openmoh.openmohaab.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications)
install(FILES ${CMAKE_BINARY_DIR}/misc/linux/org.openmoh.openmohaas.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications)
install(FILES misc/linux/org.openmoh.openmohaa.metainfo.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/metainfo)
install(FILES misc/openmohaa.svg DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/symbolic/apps/ RENAME org.openmoh.openmohaa.svg)
endif()
endif()
#
# Launcher
#
add_subdirectory(code/Launcher)
#
# uninstall target
#
if(NOT TARGET uninstall)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
endif()
+7 -14
View File
@@ -1,34 +1,28 @@
# OpenMoHAA
![Build](https://github.com/openmoh/openmohaa/actions/workflows/build-cmake.yml/badge.svg?branch=main) [![Release](https://img.shields.io/github/v/release/openmoh/openmohaa)](https://github.com/openmoh/openmohaa/releases) [![Downloads](https://img.shields.io/github/downloads/openmoh/openmohaa/total)](https://github.com/openmoh/openmohaa/releases)
[![Build](https://github.com/openmoh/openmohaa/actions/workflows/branches-build.yml/badge.svg?branch=main)](https://github.com/openmoh/openmohaa/actions/workflows/branches-build.yml) [![Release](https://img.shields.io/github/v/release/openmoh/openmohaa)](https://github.com/openmoh/openmohaa/releases) [![Downloads](https://img.shields.io/github/downloads/openmoh/openmohaa/total)](https://github.com/openmoh/openmohaa/releases)
![License](https://img.shields.io/github/license/openmoh/openmohaa) ![Commits](https://img.shields.io/github/commit-activity/t/openmoh/openmohaa)
![Discord](https://img.shields.io/discord/596049712579215361?logo=discord&logoColor=white&color=5865F2)
```
/ _ \ _ __ ___ _ __ | \/ |/ _ \| | | | / \ / \
| | | | '_ \ / _ \ '_ \| |\/| | | | | |_| | / _ \ / _ \
| |_| | |_) | __/ | | | | | | |_| | _ |/ ___ \ / ___ \
\___/| .__/ \___|_| |_|_| |_|\___/|_| |_/_/ \_\/_/ \_\
|_|
```
![logo](misc/openmohaa-text-sm.png)
## Intro
The main goal of OpenMoHAA is to ensure the future and continuity of **Medal of Honor: Allied Assault**. It has always been a dream in the community to provide patches and security fixes for the game. Thanks to the ioquake3 project, F.A.K.K SDK and other quality tools, OpenMoHAA has already reached more than half of its goal: to create 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** 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).
## Getting started
- [Installing OpenMoHAA](docs/getting_started_installation.md)
- [Downloading and installing OpenMoHAA](docs/getting_started_installation.md)
- [Running OpenMoHAA and using expansion assets](docs/getting_started_running.md)
- [Dedicated server configuration](docs/configuration/server.md)
## Current state
### Single-player
The entire single-player campaign can be played from start to end. There may be occasional bugs though; if you encounter any, please create a new [GitHub issue](https://github.com/openmoh/openmohaa/issues) describing them.
The entire single-player campaign should work (Allied Assault, Spearhead and Breakthrough). If you encounter any bug, please create a new [GitHub issue](https://github.com/openmoh/openmohaa/issues) describing them.
### Multiplayer
@@ -40,8 +34,7 @@ All game modes including `Tug-of-War` from Medal of Honor: Spearhead, and `Liber
## Features
- [What's working](docs/features_implementation.md)
- [New features](docs/features.md)
- [List of new features](docs/features.md)
- [Scripting commands](https://htmlpreview.github.io/?https://github.com/openmoh/openmohaa/blob/main/docs/features_g_allclasses.html)
## Compiling
+10 -4
View File
@@ -71,12 +71,14 @@ function(target_architecture output_var)
foreach(osx_arch ${CMAKE_OSX_ARCHITECTURES})
if("${osx_arch}" STREQUAL "ppc" AND ppc_support)
set(osx_arch_ppc TRUE)
elseif("${osx_arch}" STREQUAL "ppc64" AND ppc_support)
set(osx_arch_ppc64 TRUE)
elseif("${osx_arch}" STREQUAL "i386")
set(osx_arch_i386 TRUE)
elseif("${osx_arch}" STREQUAL "x86_64")
set(osx_arch_x86_64 TRUE)
elseif("${osx_arch}" STREQUAL "ppc64" AND ppc_support)
set(osx_arch_ppc64 TRUE)
elseif("${osx_arch}" STREQUAL "arm64")
set(osx_arch_arm64 TRUE)
else()
message(FATAL_ERROR "Invalid OS X arch name: ${osx_arch}")
endif()
@@ -87,6 +89,10 @@ function(target_architecture output_var)
list(APPEND ARCH ppc)
endif()
if(osx_arch_ppc64)
list(APPEND ARCH ppc64)
endif()
if(osx_arch_i386)
list(APPEND ARCH i386)
endif()
@@ -95,8 +101,8 @@ function(target_architecture output_var)
list(APPEND ARCH x86_64)
endif()
if(osx_arch_ppc64)
list(APPEND ARCH ppc64)
if(osx_arch_arm64)
list(APPEND ARCH arm64)
endif()
else()
# figure out extension for the source file
+21
View File
@@ -0,0 +1,21 @@
if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt")
endif()
file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
foreach(file ${files})
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
execute_process(
COMMAND "@CMAKE_COMMAND@" -E remove "$ENV{DESTDIR}${file}"
OUTPUT_VARIABLE rm_out
RESULT_VARIABLE rm_retval
)
if(NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
endif()
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
endif()
endforeach()
+36
View File
@@ -0,0 +1,36 @@
project(Launcher)
set(LAUNCHER_SOURCES "${CMAKE_SOURCE_DIR}/code/Launcher/launch_main.cpp")
if (WIN32)
set(LAUNCHER_SOURCES ${LAUNCHER_SOURCES}
"${CMAKE_SOURCE_DIR}/code/Launcher/launch_win32.cpp"
"${CMAKE_SOURCE_DIR}/code/sys/win_resource.rc")
else()
set(LAUNCHER_SOURCES ${LAUNCHER_SOURCES}
"${CMAKE_SOURCE_DIR}/code/Launcher/launch_linux.cpp")
endif()
function (create_launcher name type)
if (NOT BUILD_NO_CLIENT)
add_executable(openmohaa_launcher_${name} ${LAUNCHER_SOURCES})
target_include_directories(openmohaa_launcher_${name} PUBLIC "../qcommon")
target_compile_definitions(openmohaa_launcher_${name} PRIVATE NO_RC_MANIFEST=1 TARGET_GAME=${type})
target_compile_features(openmohaa_launcher_${name} PRIVATE cxx_std_17)
set_target_properties(openmohaa_launcher_${name} PROPERTIES OUTPUT_NAME "launch_openmohaa_${name}${TARGET_BIN_SUFFIX}")
INSTALL(TARGETS openmohaa_launcher_${name} DESTINATION ${CMAKE_INSTALL_BINDIR}/${BIN_INSTALL_SUBDIR})
endif()
#add_executable(omohaaded_launcher_${name} ${LAUNCHER_SOURCES})
#target_include_directories(omohaaded_launcher_${name} PUBLIC "../qcommon")
#target_compile_definitions(omohaaded_launcher_${name} PRIVATE NO_RC_MANIFEST=1 TARGET_GAME=${type} DEDICATED=1)
#target_compile_features(omohaaded_launcher_${name} PRIVATE cxx_std_17)
#set_target_properties(omohaaded_launcher_${name} PROPERTIES OUTPUT_NAME "launch_omohaaded_${name}${TARGET_BIN_SUFFIX}")
#
#INSTALL(TARGETS omohaaded_launcher_${name} DESTINATION ${CMAKE_INSTALL_BINDIR}/${PROJECT_INSTALL_SUBDIR})
endfunction()
create_launcher(base 0)
create_launcher(spearhead 1)
create_launcher(breakthrough 2)
+32
View File
@@ -0,0 +1,32 @@
/*
===========================================================================
Copyright (C) 2024 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
OpenMoHAA source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// launch.h: Base interface for starting programs
#include "q_platform.h"
#include <filesystem>
#include <string>
#include <vector>
std::filesystem::path GetProgramLocation();
void LaunchProgram(const std::filesystem::path& path, const std::vector<std::string>& argumentList);
+80
View File
@@ -0,0 +1,80 @@
/*
===========================================================================
Copyright (C) 2024 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
OpenMoHAA source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// main.cpp: Windows implementation of the launcher
#include "launch.h"
#include <unistd.h>
#include <spawn.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string>
#include <iostream>
extern "C" char** environ;
std::filesystem::path GetProgramLocation()
{
char path[FILENAME_MAX];
ssize_t count = readlink("/proc/self/exe", path, FILENAME_MAX);
return std::filesystem::path(std::string(path, (count > 0) ? count : 0)).parent_path();
}
void LaunchProgram(const std::filesystem::path& path, const std::vector<std::string>& argumentList)
{
pid_t pid;
std::string pathString = path.string();
size_t argCount = argumentList.size();
char** argv;
int status;
argv = new char*[argCount + 2];
argv[0] = (char*)pathString.c_str();
for (size_t i = 0; i < argCount; i++) {
argv[i + 1] = (char*)argumentList[i].c_str();
}
argv[argCount + 1] = NULL;
//status = posix_spawn(&pid, pathString.c_str(), NULL, NULL, argv, environ);
//delete[] argv;
//if (status != 0) {
// std::cout << "posix_spawn returned error: " << status << std::endl;
// return;
//}
//
// Using execve rather than posix_spawn
// This replaces the current process that is not needed anyway
//
status = execve(pathString.c_str(), argv, environ);
delete[] argv;
if (status == -1) {
std::cout << "posix_spawn returned error: " << errno << std::endl;
return;
}
waitpid(pid, NULL, 0);
}
+67
View File
@@ -0,0 +1,67 @@
/*
===========================================================================
Copyright (C) 2024 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
OpenMoHAA source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// main.cpp: The launcher
#include "launch.h"
#include <iostream>
#include <string>
#include <vector>
const char* targetGameList[] =
{
"Base",
"Spearhead",
"Breakthrough"
};
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;
#else
const char* programName = "omohaaded" "." ARCH_STRING DLL_SUFFIX EXE_EXT;
#endif
argumentList.push_back("+set");
argumentList.push_back("com_target_game");
argumentList.push_back(std::to_string(TARGET_GAME));
for (size_t i = 1; i < argc; i++) {
argumentList.push_back(argv[i]);
}
std::cout << "Using the target game: " << targetGameList[TARGET_GAME] << std::endl;
std::cout << std::endl;
std::cout << "Expected program name: " << programName << std::endl;
const std::filesystem::path programLocation = GetProgramLocation();
const std::filesystem::path programPath = programLocation / programName;
std::cout << "Program location: " << programLocation << std::endl;
std::cout << "Expected path: " << programPath << std::endl;
LaunchProgram(programPath, argumentList);
return 0;
}
+87
View File
@@ -0,0 +1,87 @@
/*
===========================================================================
Copyright (C) 2024 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
OpenMoHAA source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// main.cpp: Windows implementation of the launcher
#include "launch.h"
#include <Windows.h>
#include <string>
#include <iostream>
std::filesystem::path GetProgramLocation()
{
wchar_t path[FILENAME_MAX] = { 0 };
GetModuleFileNameW(nullptr, path, FILENAME_MAX);
return std::filesystem::path(path).parent_path();
}
void LaunchProgram(const std::filesystem::path& path, const std::vector<std::string>& argumentList)
{
PROCESS_INFORMATION processInfo;
STARTUPINFOW startupInfo;
BOOL returnValue;
std::wstring osCommandLine;
std::wstring commandLine;
size_t argCount = argumentList.size();
memset(&processInfo, 0, sizeof(processInfo));
memset(&startupInfo, 0, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);
for (size_t i = 0; i < argCount; i++) {
commandLine += L"\"";
commandLine += std::wstring(argumentList[i].begin(), argumentList[i].end());
commandLine += L"\"";
if (i != argCount - 1) {
commandLine += L" ";
}
}
osCommandLine = path.wstring();
osCommandLine += L" ";
osCommandLine += commandLine;
returnValue = CreateProcessW(
path.wstring().c_str(),
(LPWSTR)osCommandLine.c_str(),
NULL,
NULL,
FALSE,
0,
NULL,
std::filesystem::current_path().wstring().c_str(),
&startupInfo,
&processInfo
);
if (!returnValue) {
std::cout << "Error in CreateProcess: " << GetLastError() << std::endl;
return;
}
WaitForSingleObject(processInfo.hProcess, INFINITE);
CloseHandle(processInfo.hProcess);
CloseHandle(processInfo.hThread);
}
+4 -9
View File
@@ -27,16 +27,11 @@ target_compile_features(cgame PUBLIC cxx_nullptr)
target_compile_features(cgame PUBLIC c_variadic_macros)
target_link_libraries(cgame PUBLIC qcommon)
set_target_properties(cgame PROPERTIES PREFIX "${TARGET_PLATFORM_PREFIX}")
set_target_properties(cgame PROPERTIES OUTPUT_NAME "cgame${TARGET_ARCH_SUFFIX}")
set_target_properties(cgame PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TARGET_BASE_GAME}")
set_target_properties(cgame PROPERTIES PREFIX "")
set_target_properties(cgame PROPERTIES OUTPUT_NAME "cgame${TARGET_BIN_SUFFIX}")
INSTALL(
TARGETS cgame
LIBRARY DESTINATION "${TARGET_BASE_GAME}"
RUNTIME DESTINATION "${TARGET_BASE_GAME}"
)
INSTALL(TARGETS cgame DESTINATION ${CMAKE_INSTALL_LIBDIR}/${LIB_INSTALL_SUBDIR})
if(MSVC)
INSTALL(FILES $<TARGET_PDB_FILE:cgame> DESTINATION "${TARGET_BASE_GAME}" OPTIONAL)
INSTALL(FILES $<TARGET_PDB_FILE:cgame> DESTINATION ${CMAKE_INSTALL_LIBDIR}/${LIB_INSTALL_SUBDIR} OPTIONAL)
endif()
+181 -53
View File
@@ -564,7 +564,16 @@ Event EV_Client_LoopSound
EV_DEFAULT,
"sFFf",
"soundName volume min_distance pitch",
"Play the specifed sound as a looping sound"
"Play the specified sound as a looping sound"
);
// Added in 2.0
Event EV_Client_StopLoopSound
(
"stoploopsound",
EV_DEFAULT,
NULL,
NULL,
"Stop the looping sound"
);
Event EV_Client_Cache
(
@@ -985,7 +994,7 @@ Event EV_Client_BounceDecal(
"maxamount temporary",
"Put a mark when the tempmodel bounces and hits a surface\n"
"maxamount = Max amount of decals to make when bouncing\n"
"temporary = specify 1 for a temporary mark that only appears for a short time, 0 for a decal that stays aroung "
"temporary = specify 1 for a temporary mark that only appears for a short time, 0 for a decal that stays around "
"longer (default is 0)\n"
);
Event EV_Client_SetDecalRadius
@@ -1085,6 +1094,15 @@ Event EV_Client_Print
"string",
"Prints a string."
);
// Added in 2.0
Event EV_Client_PrintDeathMsg
(
"printdeathmsg",
EV_DEFAULT,
"sssss",
"msg1, msg2, killer, victim, deathType",
"Prints a death message string. Used to allow death messages to appear in their correct language on client machines.."
);
Event EV_Client_SetVolumetric
(
"volumetric",
@@ -1122,7 +1140,7 @@ Event EV_Client_SetAlignStretch(
EV_DEFAULT,
"F",
"scaleMultiplier",
"Aligns the temp model to the direction of travel, and stretches it betwen the last and current positions.\n"
"Aligns the temp model to the direction of travel, and stretches it between the last and current positions.\n"
);
Event EV_Client_SetClampVelocity
(
@@ -1195,6 +1213,14 @@ Event EV_Client_SFXStartDelayed
"fDelay sCommand arg1 arg2 arg3 arg4 arg5 arg6 arg7 arg8",
"Used for adding commands to a special effect with a time delay"
);
Event EV_Client_PlayForceFeedback
(
"playforcefeedback",
EV_DEFAULT,
"s",
"effectname",
"Starts a force feedback effect."
);
EffectsEventQueueNode EffectsEventQueue;
@@ -1261,6 +1287,7 @@ CLASS_DECLARATION(Listener, ClientGameCommandManager, NULL) {
{&EV_Client_StopSound, &ClientGameCommandManager::StopSound },
{&EV_Client_StopAliasChannel, &ClientGameCommandManager::StopAliasChannel },
{&EV_Client_LoopSound, &ClientGameCommandManager::LoopSound },
{&EV_Client_StopLoopSound, &ClientGameCommandManager::StopLoopSound },
{&EV_Client_Cache, &ClientGameCommandManager::Cache },
{&EV_Client_CacheImage, &ClientGameCommandManager::CacheImage },
{&EV_Client_CacheFont, &ClientGameCommandManager::CacheFont },
@@ -1323,6 +1350,7 @@ CLASS_DECLARATION(Listener, ClientGameCommandManager, NULL) {
{&EV_Client_SetClampVelocity, &ClientGameCommandManager::SetClampVel },
{&EV_Client_SetClampVelocityAxis, &ClientGameCommandManager::SetClampVelAxis },
{&EV_Client_Print, &ClientGameCommandManager::Print },
{&EV_Client_PrintDeathMsg, &ClientGameCommandManager::PrintDeathMsg },
{&EV_Client_EyeLimits, &ClientGameCommandManager::SetEyeLimits },
{&EV_Client_EyeMovement, &ClientGameCommandManager::SetEyeMovement },
{&EV_Client_SFXStart, &ClientGameCommandManager::StartSFX },
@@ -1394,9 +1422,11 @@ qboolean ClientGameCommandManager::PostEventForEntity(Event *ev, float fWait)
EffectsEventQueueNode *node;
int inttime;
if (!m_fEventWait || current_entity_number < 0) {
if (!str::icmp(ev->getName(), ")")) {
m_fEventWait = 0.0;
if (m_fEventWait < 0 || current_entity_number < 0) {
if (m_fEventWait != 0.0) {
if (!str::icmp(ev->getName(), ")")) {
m_fEventWait = 0.0;
}
}
delete ev;
@@ -1413,7 +1443,7 @@ qboolean ClientGameCommandManager::PostEventForEntity(Event *ev, float fWait)
event = EffectsEventQueue.next;
inttime = EVENT_msec + (fWait * 1000.0f + 0.5f);
while (event != &EffectsEventQueue && inttime > event->inttime) {
while (event != &EffectsEventQueue && inttime >= event->inttime) {
event = event->next;
}
@@ -1449,8 +1479,8 @@ void ClientGameCommandManager::SetBaseAndAmplitude(Event *ev, Vector& base, Vect
base[j] = ev->GetFloat(i++);
amplitude[j] = ev->GetFloat(i++);
} else {
base[j] = 0.0;
amplitude[j] = atof(org.c_str());
base[j] = atof(org.c_str());
amplitude[j] = 0.0;
}
}
}
@@ -1473,6 +1503,13 @@ void ClientGameCommandManager::Print(Event *ev)
}
}
void ClientGameCommandManager::PrintDeathMsg(Event* ev)
{
if (current_entity) {
cgi.DPrintf("%d:%s\n", current_entity->entityNumber, ev->GetString(1).c_str());
}
}
qboolean ClientGameCommandManager::IsBlockCommand(const str& name)
{
if (!str::icmp(name, "originspawn")) {
@@ -1552,7 +1589,6 @@ void ClientGameCommandManager::CommandDelay(Event *ev)
ev1->AddValue(ev->GetValue(i));
}
delay = ev->GetFloat(1) * 1000;
if (current_entity_number != -1) {
PostEventForEntity(ev1, fWait);
} else {
@@ -1562,6 +1598,16 @@ void ClientGameCommandManager::CommandDelay(Event *ev)
current_tiki->name
);
}
if (IsBlockCommand(eventName)) {
m_fEventWait = fWait;
} else {
m_fEventWait = 0;
}
if (current_entity_number == -1 && m_fEventWait > 0) {
m_fEventWait = -1;
}
}
void ClientGameCommandManager::StartSFX(Event *ev)
@@ -2599,7 +2645,9 @@ void ClientGameCommandManager::SetColorRange(Event *ev)
return;
}
// FIXME: unused stub??
//
// Unused
//
}
//=============
@@ -2825,7 +2873,9 @@ void ClientGameCommandManager::SetAccel(Event *ev)
m_spawnthing->cgd.accel[1] = ev->GetFloat(2);
m_spawnthing->cgd.accel[2] = ev->GetFloat(3);
m_spawnthing->cgd.flags2 |= T2_ACCEL;
if (!(m_spawnthing->cgd.flags & T_SWARM)) {
m_spawnthing->cgd.flags2 |= T2_ACCEL;
}
}
void ClientGameCommandManager::SetFriction(Event *ev)
@@ -3054,7 +3104,7 @@ spawnthing_t *ClientGameCommandManager::InitializeSpawnthing(spawnthing_t *sp)
sp->cgd.parent = -1;
sp->cgd.tiki = nullptr;
sp->cgd.lightstyle = -1;
sp->cgd.physicsRate = 10;
sp->cgd.physicsRate = cg_effect_physicsrate->integer;
sp->cgd.shadername = "beamshader";
sp->cgd.decal_orientation = 0;
sp->cgd.decal_radius = 10;
@@ -3873,7 +3923,7 @@ void ClientGameCommandManager::PlaySound(
} else {
if (debugSound->integer) {
Com_Printf(
"\nWARNING: OVERRIDE OVERRIDE OVERRIDESound %s had all its parm overriden by code.\n\n",
"\nWARNING: OVERRIDE OVERRIDE OVERRIDESound %s had all its parm overridden by code.\n\n",
sound_name.c_str()
);
}
@@ -3987,6 +4037,9 @@ void ClientGameCommandManager::StopSound(Event *ev)
cgi.S_StopSound(current_entity_number, channel);
}
//===============
// StopAliasChannel
//===============
void ClientGameCommandManager::StopAliasChannel(Event *ev)
{
str sound_name;
@@ -4082,6 +4135,54 @@ void ClientGameCommandManager::LoopSound(Event *ev)
current_centity->tikiLoopSoundFlags = 0;
}
//===============
// StopLoopSound
//===============
void ClientGameCommandManager::StopLoopSound(Event* ev)
{
if (!current_centity) {
cgi.DPrintf("CCM::StopLoopSound : StopLoopSound in %s without current_centity\n", cgi.TIKI_Name(current_tiki));
return;
}
Com_Printf("\n\nClientGameCommandManager::StopLoopSound\n\n");
current_centity->tikiLoopSound = NULL;
}
//===============
// CacheImageResource
//===============
void CacheImageResource(const char* stuff) {
str real_stuff;
char filename[1024];
if (cgi.fsDebug->integer == 2) {
Com_Printf("client cacheimage: %s\n", stuff);
}
Q_strncpyz(filename, stuff, sizeof(filename));
cgi.FS_CanonicalFilename(filename);
cgi.R_RegisterShaderNoMip(filename);
}
//===============
// CacheFontResource
//===============
void CacheFontResource(const char* stuff) {
str real_stuff;
char filename[1024];
if (cgi.fsDebug->integer == 2) {
Com_Printf("client cacheimage: %s\n", stuff);
}
Q_strncpyz(filename, stuff, sizeof(filename));
cgi.FS_CanonicalFilename(filename);
cgi.R_LoadFont(filename);
}
//===============
// CacheResource
//===============
@@ -4121,12 +4222,12 @@ void ClientGameCommandManager::Cache(Event *ev)
void ClientGameCommandManager::CacheImage(Event *ev)
{
// FIXME: stub
CacheImageResource(ev->GetString(1).c_str());
}
void ClientGameCommandManager::CacheFont(Event *ev)
{
// FIXME: stub
CacheFontResource(ev->GetString(1).c_str());
}
//===============
@@ -4134,15 +4235,16 @@ void ClientGameCommandManager::CacheFont(Event *ev)
//===============
void AliasResource(dtiki_t *pmdl, const char *alias, const char *realname, const char *parameters)
{
if (pmdl) {
if (!pmdl->a->alias_list) {
pmdl->a->alias_list = cgi.AliasList_New(pmdl->a->name);
}
cgi.Alias_ListAdd((AliasList_t *)pmdl->a->alias_list, alias, realname, parameters);
} else {
if (!pmdl) {
cgi.Alias_Add(alias, realname, parameters);
return;
}
if (!pmdl->a->alias_list) {
pmdl->a->alias_list = cgi.AliasList_New(pmdl->a->name);
}
cgi.Alias_ListAdd((AliasList_t*)pmdl->a->alias_list, alias, realname, parameters);
}
qboolean bLoadForMap(const char *psMapsBuffer, const char *name)
@@ -4203,19 +4305,32 @@ void ClientGameCommandManager::AliasCache(Event *ev)
psMapsBuffer = NULL;
for (i = 3; i <= ev->NumArgs(); i++) {
if (!strcmp(ev->GetToken(i).c_str(), "maps")) {
str s = ev->GetString(i);
if (!s.icmp("maps")) {
i++;
psMapsBuffer = ev->GetToken(i);
} else if (!strcmp(ev->GetToken(i).c_str(), "always")) {
bAlwaysLoaded = true;
} else {
strcat(parmbuffer, ev->GetToken(i));
strcat(parmbuffer, " ");
psMapsBuffer = (char *)ev->GetToken(i).c_str();
continue;
}
if (!s.icmp("always")) {
bAlwaysLoaded = true;
continue;
}
strcat(parmbuffer, s);
strcat(parmbuffer, " ");
}
if (bAlwaysLoaded || bLoadForMap(psMapsBuffer, ev->GetString(1))) {
if (bAlwaysLoaded) {
AliasResource(current_tiki, ev->GetString(1), ev->GetString(2), parmbuffer);
}
if (bLoadForMap(psMapsBuffer, ev->GetString(1))) {
if (!bAlwaysLoaded) {
AliasResource(current_tiki, ev->GetString(1), ev->GetString(2), parmbuffer);
}
CacheResource(ev->GetString(2));
}
}
@@ -4245,28 +4360,33 @@ void ClientGameCommandManager::Alias(Event *ev)
psMapsBuffer = NULL;
for (i = 3; i <= ev->NumArgs(); i++) {
if (!strcmp(ev->GetToken(i).c_str(), "maps")) {
str s = ev->GetString(i);
if (!s.icmp("maps")) {
i++;
psMapsBuffer = ev->GetToken(i);
} else if (!strcmp(ev->GetToken(i).c_str(), "always")) {
psMapsBuffer = (char *)ev->GetToken(i).c_str();
continue;
}
if (!s.icmp("always")) {
bAlwaysLoaded = true;
} else if (subtitle) {
strcat(parmbuffer, "\"");
strcat(parmbuffer, s);
strcat(parmbuffer, "\" ");
subtitle = 0;
} else {
subtitle = s.icmp("subtitle") == 0;
if (!subtitle) {
if (!Q_stricmp(ev->GetToken(i), "subtitle") || !Q_stricmp(ev->GetToken(i), "forcesubtitle")) {
subtitle = qtrue;
strcat(parmbuffer, ev->GetToken(i));
} else {
strcat(parmbuffer, ev->GetToken(i));
}
} else {
strcat(parmbuffer, "\"");
strcat(parmbuffer, ev->GetToken(i));
strcat(parmbuffer, "\"");
subtitle = qfalse;
subtitle = s.icmp("forcesubtitle") == 0;
}
strcat(parmbuffer, " ");
strcat(parmbuffer, s);
}
strcat(parmbuffer, " ");
}
if (bAlwaysLoaded || bLoadForMap(psMapsBuffer, ev->GetString(1))) {
@@ -4998,7 +5118,15 @@ bool ClientGameCommandManager::GetTagPositionAndOrientation(str tagname, orienta
//===============
void ClientGameCommandManager::RestartAllEmitters(void)
{
// FIXME: stub??
ctempmodel_t *p;
//
// FIXME: not sure if it's the right thing
//
for (p = m_active_tempmodels.prev; p != &m_active_tempmodels; p = p->next) {
p->cgd.createTime = cg.time;
}
}
//===============
@@ -5209,7 +5337,7 @@ void CG_ClientCommandDebugMessage(centity_t *cent, const char *fmt, ...)
char msg[1024];
va_start(argptr, fmt);
vsprintf(msg, fmt, argptr);
Q_vsnprintf(msg, sizeof(msg), fmt, argptr);
va_end(argptr);
if ((!cg_debugAnimWatch->integer) || ((cg_debugAnimWatch->integer - 1) == cent->currentState.number)) {
@@ -5364,7 +5492,7 @@ qboolean CG_Command_ProcessFile(const char *filename, qboolean quiet, dtiki_t *c
current_tiki = NULL;
// Update the loading screen
sprintf(tempName, "m%s", filename);
Com_sprintf(tempName, sizeof(tempName), "m%s", filename);
cgi.LoadResource(tempName);
bufstart = buffer;
@@ -5373,7 +5501,7 @@ qboolean CG_Command_ProcessFile(const char *filename, qboolean quiet, dtiki_t *c
Event *ev;
// grab each line as we go
strcpy(com_token, COM_ParseExt(&buffer, qtrue));
Q_strncpyz(com_token, COM_ParseExt(&buffer, qtrue), sizeof(com_token));
if (!com_token[0]) {
break;
}
@@ -5381,7 +5509,7 @@ qboolean CG_Command_ProcessFile(const char *filename, qboolean quiet, dtiki_t *c
if (!Q_stricmp(com_token, "end") || !Q_stricmp(com_token, "server")) {
// skip the line
while (1) {
strcpy(com_token, COM_ParseExt(&buffer, qfalse));
Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token));
if (!com_token[0]) {
break;
}
@@ -5394,7 +5522,7 @@ qboolean CG_Command_ProcessFile(const char *filename, qboolean quiet, dtiki_t *c
// get the rest of the line
while (1) {
strcpy(com_token, COM_ParseExt(&buffer, qfalse));
Q_strncpyz(com_token, COM_ParseExt(&buffer, qfalse), sizeof(com_token));
if (!com_token[0]) {
break;
}
@@ -5406,7 +5534,7 @@ qboolean CG_Command_ProcessFile(const char *filename, qboolean quiet, dtiki_t *c
cgi.FS_FreeFile((void *)bufstart);
// Update the loading screen
sprintf(tempName, "o%s", filename);
Com_sprintf(tempName, sizeof(tempName), "o%s", filename);
cgi.LoadResource(tempName);
return qtrue;
+2
View File
@@ -764,6 +764,7 @@ private:
void SpawnVSSSource(int count, int timealive);
void EventViewKick(Event *ev);
void Print(Event *ev);
void PrintDeathMsg(Event *ev); // Added in 2.0
void StartBlock(Event *ev);
void EndBlock(Event *ev);
void UpdateSpawnThing(spawnthing_t *ep);
@@ -851,6 +852,7 @@ private:
void StopSound(Event *ev);
void StopAliasChannel(Event *ev);
void LoopSound(Event *ev);
void StopLoopSound(Event *ev); // Added in 2.0
void Cache(Event *ev);
void CacheImage(Event *ev);
void CacheFont(Event *ev);
+205 -65
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
Copyright (C) 2008-2024 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -160,17 +160,157 @@ baseshader_t *CG_GetShaderUnderCrosshair(qboolean bVerbose, trace_t *pRetTrace)
static void CG_PrintContentTypes(int iContentFlags)
{
// FIXME: unimplemented
if (iContentFlags & CONTENTS_SOLID) {
cgi.Printf(" solid");
}
if (iContentFlags & CONTENTS_LAVA) {
cgi.Printf(" lava");
}
if (iContentFlags & CONTENTS_SLIME) {
cgi.Printf(" slime");
}
if (iContentFlags & CONTENTS_WATER) {
cgi.Printf(" water");
}
if (iContentFlags & CONTENTS_FOG) {
cgi.Printf(" fog");
}
if (iContentFlags & CONTENTS_FENCE) {
cgi.Printf(" fence");
}
if (iContentFlags & CONTENTS_AREAPORTAL) {
cgi.Printf(" areaportal");
}
if (iContentFlags & CONTENTS_PLAYERCLIP) {
cgi.Printf(" playerclip");
}
if (iContentFlags & CONTENTS_VEHICLECLIP) {
cgi.Printf(" vehicleclip");
}
if (iContentFlags & CONTENTS_MONSTERCLIP) {
cgi.Printf(" monsterclip");
}
if (iContentFlags & CONTENTS_WEAPONCLIP) {
cgi.Printf(" weaponclip");
}
if (iContentFlags & CONTENTS_SHOOTONLY) {
cgi.Printf(" shootableonly");
}
if (iContentFlags & CONTENTS_ORIGIN) {
cgi.Printf(" origin");
}
if (iContentFlags & CONTENTS_TRANSLUCENT) {
cgi.Printf(" trans");
}
}
static void CG_PrintSurfaceProperties(int iSurfaceFlags)
{
// FIXME: unimplemented
if (iSurfaceFlags & SURF_NODAMAGE) {
cgi.Printf(" nodamage");
}
if (iSurfaceFlags & SURF_SLICK) {
cgi.Printf(" slick");
}
if (iSurfaceFlags & SURF_SKY) {
cgi.Printf(" sky");
}
if (iSurfaceFlags & SURF_LADDER) {
cgi.Printf(" ladder");
}
if (iSurfaceFlags & SURF_NOIMPACT) {
cgi.Printf(" noimpact");
}
if (iSurfaceFlags & SURF_NOMARKS) {
cgi.Printf(" nomarks");
}
if (iSurfaceFlags & SURF_CASTSHADOW) {
cgi.Printf(" castshadow");
}
if (iSurfaceFlags & SURF_NODRAW) {
cgi.Printf(" nodraw");
}
if (iSurfaceFlags & SURF_NOLIGHTMAP) {
cgi.Printf(" nolightmap");
}
if (iSurfaceFlags & SURF_ALPHASHADOW) {
cgi.Printf(" alphashadow");
}
if (iSurfaceFlags & SURF_NOSTEPS) {
cgi.Printf(" nofootsteps");
}
if (iSurfaceFlags & SURF_NONSOLID) {
cgi.Printf(" nonsolid");
}
if (iSurfaceFlags & SURF_OVERBRIGHT) {
cgi.Printf(" overbright");
}
if (iSurfaceFlags & SURF_BACKSIDE) {
cgi.Printf(" backside");
}
if (iSurfaceFlags & SURF_NODLIGHT) {
cgi.Printf(" nodlight");
}
if (iSurfaceFlags & SURF_HINT) {
cgi.Printf(" hint");
}
if (iSurfaceFlags & SURF_PATCH) {
cgi.Printf(" patch");
}
}
static void CG_PrintSurfaceType(int iSurfType)
{
// FIXME: unimplemented
switch (iSurfType & MASK_SURF_TYPE) {
case SURF_FOLIAGE:
cgi.Printf("foliage");
break;
case SURF_SNOW:
cgi.Printf("snow");
break;
case SURF_CARPET:
cgi.Printf("carpet");
break;
case SURF_SAND:
cgi.Printf("sand");
break;
case SURF_PUDDLE:
cgi.Printf("puddle");
break;
case SURF_GLASS:
cgi.Printf("glass");
break;
case SURF_GRAVEL:
cgi.Printf("gravel");
break;
case SURF_MUD:
cgi.Printf("mud");
break;
case SURF_DIRT:
cgi.Printf("dirt");
break;
case SURF_GRILL:
cgi.Printf("metal grill");
break;
case SURF_GRASS:
cgi.Printf("grass");
break;
case SURF_ROCK:
cgi.Printf("rock");
break;
case SURF_PAPER:
cgi.Printf("paper");
break;
case SURF_WOOD:
cgi.Printf("wood");
break;
case SURF_METAL:
cgi.Printf("metal");
break;
default:
cgi.Printf("!!*none specified*!!");
break;
}
}
void CG_GetCHShader(void)
@@ -216,9 +356,9 @@ void CG_EditCHShader(void)
pShader = CG_GetShaderUnderCrosshair(qfalse, NULL);
if (pShader) {
strcpy(name, "editspecificshader ");
strcat(name, pShader->shader);
strcat(name, "\n");
Q_strncpyz(name, "editspecificshader ", sizeof(name));
Q_strcat(name, sizeof(name), pShader->shader);
Q_strcat(name, sizeof(name), "\n");
cgi.AddCommand(name);
} else {
cgi.Printf("No surface selected\n");
@@ -340,65 +480,65 @@ typedef struct {
} consoleCommand_t;
static consoleCommand_t commands[] = {
{"useweaponclass", &CG_UseWeaponClass_f },
{"weapnext", &CG_NextWeapon_f },
{"weapprev", &CG_PrevWeapon_f },
{"uselast", &CG_UseLastWeapon_f },
{"holster", &CG_HolsterWeapon_f },
{"weapdrop", &CG_DropWeapon_f },
{"toggleitem", &CG_ToggleItem_f },
{"+scores", &CG_ScoresDown_f },
{"-scores", &CG_ScoresUp_f },
{"viewpos", &CG_Viewpos_f },
{"sizeup", &CG_SizeUp_f },
{"sizedown", &CG_SizeDown_f },
{"cg_eventlist", &CG_EventList_f },
{"cg_eventhelp", &CG_EventHelp_f },
{"cg_dumpevents", &CG_DumpEventHelp_f },
{"cg_pendingevents", &CG_PendingEvents_f },
{"cg_classlist", &CG_ClassList_f },
{"cg_classtree", &CG_ClassTree_f },
{"cg_classevents", &CG_ClassEvents_f },
{"cg_dumpclassevents", &CG_DumpClassEvents_f },
{"cg_dumpallclasses", &CG_DumpAllClasses_f },
{"testemitter", &CG_TestEmitter_f },
{"triggertestemitter", &CG_TriggerTestEmitter_f },
{"prevemittercommand", &CG_PrevEmitterCommand_f },
{"nextemittercommand", &CG_NextEmitterCommand_f },
{"newemittercommand", &CG_NewEmitterCommand_f },
{"deleteemittercommand", &CG_DeleteEmitterCommand_f },
{"dumpemitter", &CG_DumpEmitter_f },
{"loademitter", &CG_LoadEmitter_f },
{"resetvss", &CG_ResetVSSSources },
{"getchshader", &CG_GetCHShader },
{"editchshader", &CG_EditCHShader },
{"messagemode", &CG_MessageMode_f },
{"messagemode_all", &CG_MessageMode_All_f },
{"messagemode_team", &CG_MessageMode_Team_f },
{"messagemode_private", &CG_MessageMode_Private_f },
{"say", &CG_MessageSingleAll_f },
{"sayteam", &CG_MessageSingleTeam_f },
{"teamsay", &CG_MessageSingleTeam_f },
{"sayprivate", &CG_MessageSingleClient_f },
{"sayone", &CG_MessageSingleClient_f },
{"wisper", &CG_MessageSingleClient_f },
{"instamsg_main", &CG_InstaMessageMain_f },
{"instamsg_group_a", &CG_InstaMessageGroupA_f },
{"instamsg_group_b", &CG_InstaMessageGroupB_f },
{"instamsg_group_c", &CG_InstaMessageGroupC_f },
{"instamsg_group_d", &CG_InstaMessageGroupD_f },
{"instamsg_group_e", &CG_InstaMessageGroupE_f },
{"pushmenu_teamselect", &CG_PushMenuTeamSelect_f },
{"pushmenu_weaponselect", &CG_PushMenuWeaponSelect_f },
{"useweaponclass", &CG_UseWeaponClass_f },
{"weapnext", &CG_NextWeapon_f },
{"weapprev", &CG_PrevWeapon_f },
{"uselast", &CG_UseLastWeapon_f },
{"holster", &CG_HolsterWeapon_f },
{"weapdrop", &CG_DropWeapon_f },
{"toggleitem", &CG_ToggleItem_f },
{"+scores", &CG_ScoresDown_f },
{"-scores", &CG_ScoresUp_f },
{"viewpos", &CG_Viewpos_f },
{"sizeup", &CG_SizeUp_f },
{"sizedown", &CG_SizeDown_f },
{"cg_eventlist", &CG_EventList_f },
{"cg_eventhelp", &CG_EventHelp_f },
{"cg_dumpevents", &CG_DumpEventHelp_f },
{"cg_pendingevents", &CG_PendingEvents_f },
{"cg_classlist", &CG_ClassList_f },
{"cg_classtree", &CG_ClassTree_f },
{"cg_classevents", &CG_ClassEvents_f },
{"cg_dumpclassevents", &CG_DumpClassEvents_f },
{"cg_dumpallclasses", &CG_DumpAllClasses_f },
{"testemitter", &CG_TestEmitter_f },
{"triggertestemitter", &CG_TriggerTestEmitter_f },
{"prevemittercommand", &CG_PrevEmitterCommand_f },
{"nextemittercommand", &CG_NextEmitterCommand_f },
{"newemittercommand", &CG_NewEmitterCommand_f },
{"deleteemittercommand", &CG_DeleteEmitterCommand_f },
{"dumpemitter", &CG_DumpEmitter_f },
{"loademitter", &CG_LoadEmitter_f },
{"resetvss", &CG_ResetVSSSources },
{"getchshader", &CG_GetCHShader },
{"editchshader", &CG_EditCHShader },
{"messagemode", &CG_MessageMode_f },
{"messagemode_all", &CG_MessageMode_All_f },
{"messagemode_team", &CG_MessageMode_Team_f },
{"messagemode_private", &CG_MessageMode_Private_f },
{"say", &CG_MessageSingleAll_f },
{"sayteam", &CG_MessageSingleTeam_f },
{"teamsay", &CG_MessageSingleTeam_f },
{"sayprivate", &CG_MessageSingleClient_f },
{"sayone", &CG_MessageSingleClient_f },
{"wisper", &CG_MessageSingleClient_f },
{"instamsg_main", &CG_InstaMessageMain_f },
{"instamsg_group_a", &CG_InstaMessageGroupA_f },
{"instamsg_group_b", &CG_InstaMessageGroupB_f },
{"instamsg_group_c", &CG_InstaMessageGroupC_f },
{"instamsg_group_d", &CG_InstaMessageGroupD_f },
{"instamsg_group_e", &CG_InstaMessageGroupE_f },
{"pushmenu_teamselect", &CG_PushMenuTeamSelect_f },
{"pushmenu_weaponselect", &CG_PushMenuWeaponSelect_f },
// Added in 2.0
{"pushcallvote", &CG_PushCallVote_f },
{"pushcallvotesublist", &CG_PushCallVoteSubList_f },
{"pushcallvotesubtext", &CG_PushCallVoteSubText_f },
{"pushcallvotesubinteger",&CG_PushCallVoteSubInteger_f },
{"pushcallvotesubfloat", &CG_PushCallVoteSubFloat_f },
{"pushcallvotesubclient", &CG_PushCallVoteSubClient_f },
{"pushvote", &CG_PushVote_f },
{"callentryvote", &CG_CallEntryVote_f },
{"pushcallvote", &CG_PushCallVote_f },
{"pushcallvotesublist", &CG_PushCallVoteSubList_f },
{"pushcallvotesubtext", &CG_PushCallVoteSubText_f },
{"pushcallvotesubinteger", &CG_PushCallVoteSubInteger_f},
{"pushcallvotesubfloat", &CG_PushCallVoteSubFloat_f },
{"pushcallvotesubclient", &CG_PushCallVoteSubClient_f },
{"pushvote", &CG_PushVote_f },
{"callentryvote", &CG_CallEntryVote_f },
};
/*
+70 -36
View File
@@ -675,14 +675,17 @@ void CG_DrawObjectives()
{
float vColor[4];
float fX, fY;
int iNumObjectives;
float fObjectivesTop;
static float fWidth;
float fHeight;
int iNumLines[20];
int iTotalNumLines;
int i;
int ii;
int iCurrentObjective;
float fTimeDelta;
const char *pszLocalizedText;
const char *pszLine;
iTotalNumLines = 0;
for (i = CS_OBJECTIVES; i < CS_OBJECTIVES + MAX_OBJECTIVES; ++i) {
@@ -702,26 +705,30 @@ void CG_DrawObjectives()
return;
}
for (i = 0; i < MAX_OBJECTIVES; i++) {
if ((cg.Objectives[i].flags & 0xFFFFFFFE)) {
iNumLines[i] = 0;
// Added in 2.0
// Get the minimum Y value, it should be below the compass
fObjectivesTop = cgi.UI_GetObjectivesTop();
iNumObjectives = 0;
for (ii = 0; ii < MAX_STRING_CHARS; ii++) {
if (cg.Objectives[i].text[ii] == '\n') {
iTotalNumLines++;
iNumLines[i]++;
} else if (!cg.Objectives[i].text[ii]) {
iTotalNumLines++;
iNumLines[i]++;
break;
}
}
for (i = 0; i < MAX_OBJECTIVES; i++) {
if ((cg.Objectives[i].flags == OBJ_FLAG_NONE) || (cg.Objectives[i].flags & OBJ_FLAG_HIDDEN)) {
continue;
}
iNumObjectives++;
iNumLines[i] = 0;
pszLocalizedText = cgi.LV_ConvertString(cg.Objectives[i].text);
for (pszLine = strchr(pszLocalizedText, '\n'); pszLine; pszLine = strchr(pszLine + 1, '\n')) {
iNumLines[i]++;
}
iTotalNumLines += iNumLines[i];
}
fX = 25.0;
fY = 125.0;
fWidth = (float)(25 * iTotalNumLines + 155) + 5.0 - 130.0;
fY = fObjectivesTop + 5;
fWidth = (float)(iTotalNumLines * 12 + fObjectivesTop + iNumObjectives * 25 + 32) - fY;
vColor[2] = 0.2f;
vColor[1] = 0.2f;
vColor[0] = 0.2f;
@@ -730,7 +737,7 @@ void CG_DrawObjectives()
cgi.R_DrawStretchPic(fX, fY, 450.0, fWidth, 0.0, 0.0, 1.0, 1.0, cgs.media.objectivesBackShader);
fX = 30.0;
fY = 130.0;
fY = fObjectivesTop + 10;
vColor[0] = 1.0;
vColor[1] = 1.0;
vColor[2] = 1.0;
@@ -740,12 +747,12 @@ void CG_DrawObjectives()
fY = fY + 5.0;
cgi.R_DrawString(cgs.media.objectiveFont, "_______________________________________________________", fX, fY, -1, 0);
fHeight = 155.0;
fHeight = fObjectivesTop + 35;
for (i = 0; i < MAX_OBJECTIVES; ++i) {
qhandle_t hBoxShader;
if ((cg.Objectives[i].flags & OBJ_FLAG_HIDDEN) || !cg.Objectives[i].flags) {
if ((cg.Objectives[i].flags == OBJ_FLAG_NONE) || (cg.Objectives[i].flags & OBJ_FLAG_HIDDEN)) {
continue;
}
@@ -789,7 +796,7 @@ void CG_DrawObjectives()
cgi.R_SetColor(vColor);
cgi.R_DrawStretchPic(fX, fY, 16.0, 16.0, 0.0, 0.0, 1.0, 1.0, hBoxShader);
fHeight += 25 * iNumLines[i];
fHeight += iNumLines[i] * 12 + 25;
}
}
@@ -927,6 +934,8 @@ void CG_UpdateAttackerDisplay()
void CG_UpdateCountdown()
{
const char* message = "";
if (!cg.snap) {
return;
}
@@ -937,16 +946,24 @@ void CG_UpdateCountdown()
iSecondsLeft = (cgs.matchEndTime - cg.time) / 1000;
if (iSecondsLeft >= 0) {
iMinutesLeft = iSecondsLeft / 60;
cgi.Cvar_Set(
"ui_timemessage", va("%s %2i:%02i", cgi.LV_ConvertString("Time Left:"), iMinutesLeft, iSecondsLeft % 60)
);
message = va("%s %2i:%02i", cgi.LV_ConvertString("Time Left:"), iMinutesLeft, iSecondsLeft % 60);
} else if (!cgs.matchEndTime) {
cgi.Cvar_Set("ui_timemessage", "");
message = "";
}
} else {
// The match has not started yet
cgi.Cvar_Set("ui_timemessage", "Waiting For Players");
message = "Waiting For Players";
}
if (strcmp(ui_timemessage->string, message)) {
cgi.Cvar_Set("ui_timemessage", message);
}
}
static void CG_RemoveStopwatch() {
cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_stopwatch\n");
cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_fuse\n");
cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_fuse_wet\n");
}
void CG_DrawStopwatch()
@@ -954,38 +971,55 @@ void CG_DrawStopwatch()
int iFraction;
if (!cg_hud->integer) {
cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_stopwatch\n");
CG_RemoveStopwatch();
return;
}
if (!cgi.stopWatch->iStartTime) {
cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_stopwatch\n");
CG_RemoveStopwatch();
return;
}
if (cgi.stopWatch->iStartTime >= cgi.stopWatch->iEndTime) {
cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_stopwatch\n");
CG_RemoveStopwatch();
return;
}
if (cgi.stopWatch->iEndTime <= cg.time) {
cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_stopwatch\n");
CG_RemoveStopwatch();
return;
}
if (cg.ObjectivesCurrentAlpha >= 0.02) {
cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_stopwatch\n");
CG_RemoveStopwatch();
return;
}
if (cg.snap && cg.snap->ps.stats[STAT_HEALTH] <= 0) {
cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_stopwatch\n");
CG_RemoveStopwatch();
return;
}
if (cgi.stopWatch->eType >= SWT_FUSE_WET) {
iFraction = cgi.stopWatch->iEndTime - cgi.stopWatch->iStartTime;
} else {
iFraction = cgi.stopWatch->iEndTime - cg.time;
}
iFraction = cgi.stopWatch->iEndTime - cg.time;
cgi.Cvar_Set("ui_stopwatch", va("%i", iFraction));
cgi.Cmd_Execute(EXEC_NOW, "ui_addhud hud_stopwatch\n");
switch (cgi.stopWatch->eType) {
case SWT_NORMAL:
default:
cgi.Cmd_Execute(EXEC_NOW, "ui_addhud hud_stopwatch\n");
break;
case SWT_FUSE:
cgi.Cmd_Execute(EXEC_NOW, "ui_addhud hud_fuse\n");
break;
case SWT_FUSE_WET:
cgi.Cmd_Execute(EXEC_NOW, "ui_removehud hud_fuse\n");
cgi.Cmd_Execute(EXEC_NOW, "ui_addhud hud_fuse_wet\n");
break;
}
}
void CG_DrawInstantMessageMenu()
@@ -1085,7 +1119,7 @@ void CG_DrawSpectatorView_ver_15()
char buf[128];
iClientNum = cg.snap->ps.stats[STAT_INFOCLIENT];
sprintf(buf, "%s : %i", cg.clientinfo[iClientNum].name, cg.snap->ps.stats[STAT_INFOCLIENT_HEALTH]);
Com_sprintf(buf, sizeof(buf), "%s : %i", cg.clientinfo[iClientNum].name, cg.snap->ps.stats[STAT_INFOCLIENT_HEALTH]);
hShader = 0;
color[0] = 0.5;
@@ -1190,7 +1224,7 @@ void CG_DrawCrosshair()
return;
}
if ((cg.snap->ps.pm_flags & PMF_NO_LEAN) || (cg.snap->ps.pm_flags & PMF_INTERMISSION)) {
if ((cg.snap->ps.pm_flags & PMF_NO_HUD) || (cg.snap->ps.pm_flags & PMF_INTERMISSION)) {
return;
}
+5 -3
View File
@@ -503,6 +503,7 @@ extern "C" {
extern cvar_t *voiceChat;
extern cvar_t *cg_shadowscount;
extern cvar_t *cg_shadowdebug;
extern cvar_t *ui_timemessage;
//
// cg_main.c
@@ -729,8 +730,8 @@ extern "C" {
void CG_InitTestTreadMark();
void CG_AddTreadMarks();
int CG_PermanentMark(
const vec3_t origin,
const vec3_t dir,
vec3_t origin,
vec3_t dir,
float orientation,
float fSScale,
float fTScale,
@@ -923,7 +924,8 @@ qboolean CG_LightStyleColor(int style, int realtime, vec4_t color, qboolean clam
void CG_InstaMessageGroupD_f(void);
void CG_InstaMessageGroupE_f(void);
void CG_HudPrint_f(void);
int CG_CheckCaptureKey(int key, qboolean down, unsigned int time);
qboolean CG_CheckCaptureKey(int key, qboolean down, unsigned int time);
//
// cg_vehicle.cpp
+71 -36
View File
@@ -110,6 +110,7 @@ cvar_t *vm_lean_lower;
cvar_t *voiceChat;
cvar_t *cg_shadowscount;
cvar_t *cg_shadowdebug;
cvar_t *ui_timemessage;
/*
=================
@@ -197,53 +198,87 @@ void CG_RegisterCvars(void)
vm_lean_lower = cgi.Cvar_Get("vm_lean_lower", "0.1", 0);
voiceChat = cgi.Cvar_Get("cg_voicechat", "1", 0);
ui_timemessage = cgi.Cvar_Get("ui_timemessage", "", 0);
// see if we are also running the server on this machine
temp = cgi.Cvar_Get("sv_running", "0", 0);
cgs.localServer = temp->integer;
}
/*
================
CG_RegisterSoundsForFile
Register the specified ubersound source file
================
*/
void CG_RegisterSoundsForFile(const char *name)
{
int startTime;
int endTime;
Com_Printf("\n\n-----------PARSING '%s'------------\n", name);
Com_Printf(
"Any SetCurrentTiki errors means that tiki wasn't prefetched and tiki-specific sounds for it won't work. To "
"fix prefetch the tiki. Ignore if you don't use that tiki on this level.\n"
);
startTime = cgi.Milliseconds();
CG_Command_ProcessFile(name, qfalse, NULL);
endTime = cgi.Milliseconds();
Com_Printf("Parse/Load time: %f seconds.\n", (float)(endTime - startTime) / 1000.0);
Com_Printf("-------------PARSING '%s' DONE---------------\n\n", name);
}
/*
=================
qsort_compare_strings
perform case-insensitive sorting
=================
*/
int qsort_compare_strings(const void *s1, const void *s2)
{
return Q_stricmp(*(const char **)s1, *(const char **)s2);
}
/*
=================
CG_RegisterSounds
called during a precache command
Called during a precache command
=================
*/
void CG_RegisterSounds(void)
{
int startTime;
int endTime;
char filename[MAX_QPATH];
char **fileList;
int numFiles;
int i;
Com_Printf("\n\n-----------PARSING UBERSOUND------------\n");
Com_Printf(
"Any SetCurrentTiki errors means that tiki wasn't prefetched and "
"tiki-specific sounds for it won't work. To fix prefe"
"tch the tiki. Ignore if you don't use that tiki on this level.\n"
);
Com_sprintf(filename, sizeof(filename), "ubersound/ubersound.scr");
fileList = cgi.FS_ListFilteredFiles("ubersound/", "scr", "*.scr", qfalse, &numFiles, qtrue);
if (cg_target_game >= TG_MOHTA) {
// Fixed in 2.0
// The behavior has changed, all aliases get cleared
if (cgs.gametype != GT_SINGLE_PLAYER) {
cgi.Alias_Clear();
}
} else {
if (!cgs.localServer) {
cgi.Alias_Clear();
}
}
qsort(fileList, numFiles, sizeof(char *), &qsort_compare_strings);
startTime = cgi.Milliseconds();
CG_Command_ProcessFile(filename, 0, 0);
endTime = cgi.Milliseconds();
for (i = 0; i < numFiles; i++) {
// Added in 2.0
// Since 2.0, all files in the ubersound folder
// are parsed
CG_RegisterSoundsForFile(va("ubersound/%s", fileList[i]));
}
Com_Printf("Parse/Load time: %f seconds.\n", (endTime - startTime) / 1000.0f);
Com_Printf("-------------UBERSOUND DONE---------------\n\n");
Com_Printf("\n\n-----------PARSING UBERDIALOG------------\n");
Com_Printf(
"Any SetCurrentTiki errors means that tiki wasn't prefetched and "
"tiki-specific sounds for it won't work. To fix prefe"
"tch the tiki. Ignore if you don't use that tiki on this level.\n"
);
Com_sprintf(filename, sizeof(filename), "ubersound/uberdialog.scr");
startTime = cgi.Milliseconds();
CG_Command_ProcessFile(filename, 0, 0);
endTime = cgi.Milliseconds() - startTime;
Com_Printf("Parse/Load time: %f seconds.\n", endTime / 1000.0f);
Com_Printf("-------------UBERDIALOG DONE---------------\n\n");
cgi.FS_FreeFileList(fileList);
}
/*
@@ -338,7 +373,7 @@ void CG_ProcessConfigString(int num, qboolean modelOnly)
if (cg.rain.numshaders) {
// Fixed in OPM
// not sure why some maps set a digit at the end...
int len = strlen(cg.rain.currentShader);
size_t len = strlen(cg.rain.currentShader);
if (isdigit(cg.rain.currentShader[len - 1])) {
cg.rain.currentShader[len - 1] = 0;
}
@@ -366,7 +401,7 @@ void CG_ProcessConfigString(int num, qboolean modelOnly)
if (num >= CS_OBJECTIVES && num < CS_OBJECTIVES + MAX_OBJECTIVES) {
cobjective_t *objective = &cg.Objectives[num - CS_OBJECTIVES];
objective->flags = atoi(Info_ValueForKey(str, "flags"));
strcpy(objective->text, Info_ValueForKey(str, "text"));
Q_strncpyz(objective->text, Info_ValueForKey(str, "text"), sizeof(objective->text));
}
switch (num) {
@@ -421,7 +456,7 @@ void CG_ProcessConfigString(int num, qboolean modelOnly)
if (len) {
qboolean streamed;
char buf[1024];
strcpy(buf, str);
Q_strncpyz(buf, str, sizeof(buf));
streamed = buf[len - 1] != '0';
buf[len - 1] = 0;
@@ -823,7 +858,7 @@ void Com_Error(int level, const char *error, ...)
char text[1024];
va_start(argptr, error);
vsprintf(text, error, argptr);
Q_vsnprintf(text, sizeof(text), error, argptr);
va_end(argptr);
cgi.Error(level, "%s", text);
@@ -835,7 +870,7 @@ void Com_Printf(const char *msg, ...)
char text[1024];
va_start(argptr, msg);
vsprintf(text, msg, argptr);
Q_vsnprintf(text, sizeof(text), msg, argptr);
va_end(argptr);
cgi.Printf("%s", text);
+1165 -276
View File
File diff suppressed because it is too large. Load diff
+116 -105
View File
@@ -180,6 +180,117 @@ void CG_PlayerTeamIcon(refEntity_t *pModel, entityState_t *pPlayerState)
}
}
/*
===============
CG_InterpolateAnimParms
Interpolate between current and next entity
===============
*/
void CG_InterpolateAnimParms(entityState_t* state, entityState_t* sNext, refEntity_t* model)
{
static cvar_t *vmEntity = NULL;
int i;
float t;
float animLength;
float t1, t2;
if (!vmEntity) {
vmEntity = cgi.Cvar_Get("viewmodelanim", "1", 0);
}
if (sNext && sNext->usageIndex == state->usageIndex) {
t1 = cg.time - cg.snap->serverTime;
t2 = cg.nextSnap->serverTime - cg.snap->serverTime;
t = t1 / t2;
model->actionWeight = (sNext->actionWeight - state->actionWeight) * t + state->actionWeight;
for (i = 0; i < MAX_FRAMEINFOS; i++) {
if (sNext->frameInfo[i].weight) {
model->frameInfo[i].index = sNext->frameInfo[i].index;
if (sNext->frameInfo[i].index == state->frameInfo[i].index && state->frameInfo[i].weight) {
model->frameInfo[i].weight =
(sNext->frameInfo[i].weight - state->frameInfo[i].weight) * t + state->frameInfo[i].weight;
if (sNext->frameInfo[i].time >= state->frameInfo[i].time) {
model->frameInfo[i].time = (sNext->frameInfo[i].time - state->frameInfo[i].time) * t + state->frameInfo[i].time;
} else {
animLength = cgi.Anim_Time(model->tiki, sNext->frameInfo[i].index);
if (!animLength) {
t1 = 0.0;
} else {
t1 = (animLength + sNext->frameInfo[i].time - state->frameInfo[i].time) * t
+ state->frameInfo[i].time;
}
t2 = t1;
while (t2 > animLength) {
t2 -= animLength;
if (t2 == t1) {
t2 = 1.0;
break;
}
t1 = t2;
}
model->frameInfo[i].time = t2;
}
} else {
animLength = cgi.Anim_Time(model->tiki, sNext->frameInfo[i].index);
if (!animLength) {
t1 = 0.0;
} else {
t1 = sNext->frameInfo[i].time - (cg.nextSnap->serverTime - cg.time) / 1000.0;
}
model->frameInfo[i].time = Q_max(0, t1);
model->frameInfo[i].weight = sNext->frameInfo[i].weight;
}
} else if (sNext->frameInfo[i].index == state->frameInfo[i].index) {
animLength = cgi.Anim_Time(model->tiki, sNext->frameInfo[i].index);
if (!animLength) {
t1 = 0.0;
} else {
t1 = (cg.time - cg.snap->serverTime) / 1000.0 + state->frameInfo[i].time;
}
model->frameInfo[i].index = Q_clamp_int(state->frameInfo[i].index, 0, model->tiki->a->num_anims - 1);
model->frameInfo[i].time = Q_min(animLength, t1);
model->frameInfo[i].weight = (1.0 - t) * state->frameInfo[i].weight;
} else {
model->frameInfo[i].index = -1;
model->frameInfo[i].weight = 0.0;
}
}
} else {
// no next state, don't blend anims
model->actionWeight = state->actionWeight;
for (i = 0; i < MAX_FRAMEINFOS; i++) {
if (state->frameInfo[i].weight) {
model->frameInfo[i].index = Q_clamp_int(state->frameInfo[i].index, 0, model->tiki->a->num_anims - 1);
model->frameInfo[i].time = state->frameInfo[i].time;
model->frameInfo[i].weight = state->frameInfo[i].weight;
} else {
model->frameInfo[i].index = -1;
model->frameInfo[i].weight = 0.0;
}
}
}
if (vmEntity->integer == state->number) {
static cvar_t *curanim;
if (!curanim) {
curanim = cgi.Cvar_Get("viewmodelanimslot", "1", 0);
}
cgi.Cvar_Set("viewmodelanimclienttime", va("%0.2f", model->frameInfo[curanim->integer].time));
}
}
/*
===============
CG_CastFootShadow
@@ -550,7 +661,7 @@ void CG_AnimationDebugMessage(int number, const char *fmt, ...)
char msg[1024];
va_start(argptr, fmt);
vsprintf(msg, fmt, argptr);
Q_vsnprintf(msg, sizeof(msg), fmt, argptr);
va_end(argptr);
if ((!cg_debugAnimWatch->integer) || ((cg_debugAnimWatch->integer - 1) == number)) {
@@ -654,8 +765,8 @@ void CG_UpdateForceModels()
pszAlliesPartial = dm_playermodel->string;
pszAxisPartial = dm_playergermanmodel->string;
sprintf(szAlliesModel, "models/player/%s.tik", pszAlliesPartial);
sprintf(szAxisModel, "models/player/%s.tik", pszAxisPartial);
Com_sprintf(szAlliesModel, sizeof(szAlliesModel), "models/player/%s.tik", pszAlliesPartial);
Com_sprintf(szAxisModel, sizeof(szAxisModel), "models/player/%s.tik", pszAxisPartial);
hModel = cgi.R_RegisterModel(szAlliesModel);
if (!hModel) hModel = cgi.R_RegisterModel("models/player/american_army.tik");
@@ -697,7 +808,6 @@ void CG_ModelAnim(centity_t *cent, qboolean bDoShaderTime)
int i;
vec3_t vMins, vMaxs, vTmp;
const char *szTagName;
static cvar_t *vmEntity = NULL;
int iAnimFlags;
s1 = &cent->currentState;
@@ -709,10 +819,6 @@ void CG_ModelAnim(centity_t *cent, qboolean bDoShaderTime)
memset(&model, 0, sizeof(model));
if (!vmEntity) {
vmEntity = cgi.Cvar_Get("viewmodelanim", "1", 0);
}
if (cent->interpolate) {
sNext = &cent->nextState;
}
@@ -880,103 +986,7 @@ void CG_ModelAnim(centity_t *cent, qboolean bDoShaderTime)
model.renderfx |= s1->renderfx;
cgi.TIKI_SetEyeTargetPos(model.tiki, model.entityNumber, s1->eyeVector);
if (sNext && sNext->usageIndex == s1->usageIndex) {
float t;
float animLength;
float t1, t2;
t1 = cg.time - cg.snap->serverTime;
t2 = cg.nextSnap->serverTime - cg.snap->serverTime;
t = t1 / t2;
model.actionWeight = (sNext->actionWeight - s1->actionWeight) * t + s1->actionWeight;
for (i = 0; i < MAX_FRAMEINFOS; i++) {
if (sNext->frameInfo[i].weight) {
model.frameInfo[i].index = sNext->frameInfo[i].index;
if (sNext->frameInfo[i].index == s1->frameInfo[i].index && s1->frameInfo[i].weight) {
model.frameInfo[i].weight =
(sNext->frameInfo[i].weight - s1->frameInfo[i].weight) * t + s1->frameInfo[i].weight;
if (sNext->frameInfo[i].time >= s1->frameInfo[i].time) {
model.frameInfo[i].time =
(sNext->frameInfo[i].time - s1->frameInfo[i].time) * t + s1->frameInfo[i].time;
} else {
animLength = cgi.Anim_Time(model.tiki, sNext->frameInfo[i].index);
if (!animLength) {
t1 = 0.0;
} else {
t1 = (animLength + sNext->frameInfo[i].time - s1->frameInfo[i].time) * t
+ s1->frameInfo[i].time;
}
t2 = t1;
while (t2 > animLength) {
t2 -= animLength;
}
model.frameInfo[i].time = t2;
}
} else {
animLength = cgi.Anim_Time(model.tiki, sNext->frameInfo[i].index);
if (!animLength) {
t1 = 0.0;
} else {
t1 = sNext->frameInfo[i].time - (cg.nextSnap->serverTime - cg.time) / 1000.0;
}
t2 = t1;
if (t2 < 0.0) {
t2 = 0.0;
}
model.frameInfo[i].time = t2;
model.frameInfo[i].weight = sNext->frameInfo[i].weight;
}
} else if (sNext->frameInfo[i].index == s1->frameInfo[i].index) {
animLength = cgi.Anim_Time(model.tiki, sNext->frameInfo[i].index);
if (!animLength) {
t1 = 0.0;
} else {
t1 = (cg.time - cg.snap->serverTime) / 1000.0 + s1->frameInfo[i].time;
}
t2 = t1;
if (t2 < animLength) {
t2 = animLength;
}
model.frameInfo[i].index = s1->frameInfo[i].index;
model.frameInfo[i].time = t2;
model.frameInfo[i].weight = (1.0 - t) * s1->frameInfo[i].weight;
} else {
model.frameInfo[i].index = -1;
model.frameInfo[i].weight = 0.0;
}
}
} else {
// no next state, don't blend anims
model.actionWeight = s1->actionWeight;
for (i = 0; i < MAX_FRAMEINFOS; i++) {
if (s1->frameInfo[i].weight) {
model.frameInfo[i].index = s1->frameInfo[i].index;
model.frameInfo[i].time = s1->frameInfo[i].time;
model.frameInfo[i].weight = s1->frameInfo[i].weight;
} else {
model.frameInfo[i].index = -1;
model.frameInfo[i].weight = 0.0;
}
}
}
if (vmEntity->integer == s1->number) {
static cvar_t *curanim;
if (!curanim) {
curanim = cgi.Cvar_Get("viewmodelanimslot", "1", 0);
}
cgi.Cvar_Set("viewmodelanimclienttime", va("%0.2f", model.frameInfo[curanim->integer].time));
}
CG_InterpolateAnimParms(s1, sNext, &model);
if (cent->currentState.parent != ENTITYNUM_NONE) {
int iTagNum;
@@ -1227,6 +1237,7 @@ void CG_ModelAnim(centity_t *cent, qboolean bDoShaderTime)
memset(model.surfaces, 0, sizeof(model.surfaces));
CG_ViewModelAnimation(&model);
model.renderfx |= RF_FRAMELERP;
cgi.ForceUpdatePose(&model);
if ((cent->currentState.eFlags & EF_UNARMED) || cg_drawviewmodel->integer <= 1
+2 -2
View File
@@ -51,7 +51,7 @@ void RainTouch(ctempmodel_t *ct, trace_t *trace)
void ClientGameCommandManager::RainTouch(Event *ev)
{
// FIXME: unimplemented
// Nothing to do
}
void ClientGameCommandManager::InitializeRainCvars()
@@ -60,7 +60,7 @@ void ClientGameCommandManager::InitializeRainCvars()
cg_rain = cgi.Cvar_Get("cg_rain", "1", CVAR_ARCHIVE);
cg_rain_drawcoverage =
cgi.Cvar_Get("cg_rain_drawcoverage", "0", CVAR_SAVEGAME | CVAR_SERVER_CREATED | CVAR_SYSTEMINFO);
cgi.Cvar_Get("cg_rain_drawcoverage", "0", CVAR_SAVEGAME | CVAR_RESETSTRING | CVAR_SYSTEMINFO);
cg.rain.density = 0.0;
cg.rain.speed = 2048.0f;
+96 -37
View File
@@ -26,6 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cg_local.h"
#include "cg_parsemsg.h"
#include "cg_specialfx.h"
#include "cg_radar.h"
#include "str.h"
@@ -426,7 +427,7 @@ static void CG_BulletTracerEffect(const vec3_t i_vStart, const vec3_t i_vEnd, in
0,
1,
1.0,
1.0,
scale,
BEAM_INVERTED,
1000.0,
iLife,
@@ -735,8 +736,14 @@ static void CG_MakeBulletTracerInternal(
}
commandManager.PlaySound("snd_b_zing", vZingPosA, -1, fVolume, -1.0f, fPitch, 1);
commandManager.PlaySound("snd_b_zing", vZingPosB, -1, fVolume, -1.0f, fPitch, 1);
commandManager.PlaySound("snd_b_zing", vZingPosC, -1, fVolume, -1.0f, fPitch, 1);
if (fZingDistB != 9999) {
commandManager.PlaySound("snd_b_zing", vZingPosB, -1, fVolume, -1.0f, fPitch, 1);
if (fZingDistC != 9999) {
commandManager.PlaySound("snd_b_zing", vZingPosC, -1, fVolume, -1.0f, fPitch, 1);
}
}
}
}
@@ -866,7 +873,8 @@ void CG_AddBulletImpacts()
fVolume = 0.75f;
}
if (wall_impact_type[iImpSndIndexRA] == SFX_BHIT_WOOD_LITE || wall_impact_type[iImpSndIndexRA] == SFX_BHIT_WOOD_HARD) {
if (wall_impact_type[iImpSndIndexRA] == SFX_BHIT_WOOD_LITE
|| wall_impact_type[iImpSndIndexRA] == SFX_BHIT_WOOD_HARD) {
sSoundName = "snd_bh_metal";
} else {
sSoundName = "snd_bh_wood";
@@ -897,7 +905,8 @@ void CG_AddBulletImpacts()
fVolume = 0.75f;
}
if (wall_impact_type[iImpSndIndexRB] == SFX_BHIT_WOOD_LITE || wall_impact_type[iImpSndIndexRB] == SFX_BHIT_WOOD_HARD) {
if (wall_impact_type[iImpSndIndexRB] == SFX_BHIT_WOOD_LITE
|| wall_impact_type[iImpSndIndexRB] == SFX_BHIT_WOOD_HARD) {
sSoundName = "snd_bh_metal";
} else {
sSoundName = "snd_bh_wood";
@@ -952,7 +961,8 @@ void CG_AddBulletImpacts()
fVolume = 0.75f;
}
if (wall_impact_type[iImpSndIndexLB] == SFX_BHIT_WOOD_LITE || wall_impact_type[iImpSndIndexLB] == SFX_BHIT_WOOD_HARD) {
if (wall_impact_type[iImpSndIndexLB] == SFX_BHIT_WOOD_LITE
|| wall_impact_type[iImpSndIndexLB] == SFX_BHIT_WOOD_HARD) {
sSoundName = "snd_bh_metal";
} else {
sSoundName = "snd_bh_wood";
@@ -1482,7 +1492,7 @@ void CG_ParseCGMessage_ver_15()
vStart[2] = cgi.MSG_ReadCoord();
cgi.MSG_ReadDir(vEnd);
sfxManager.MakeEffect_Normal(SFX_EXP_GREN_PUDDLE + iType, vStart, vEnd);
sfxManager.MakeEffect_Normal((iType - CGM_MAKE_EFFECT_1) + SFX_OIL_LEAK_BIG, vStart, vEnd);
break;
case CGM_MAKE_CRATE_DEBRIS:
@@ -1566,7 +1576,11 @@ void CG_ParseCGMessage_ver_15()
case CGM_HUDDRAW_SHADER:
iInfo = cgi.MSG_ReadByte();
strcpy(cgi.HudDrawElements[iInfo].shaderName, cgi.MSG_ReadString());
Q_strncpyz(
cgi.HudDrawElements[iInfo].shaderName,
cgi.MSG_ReadString(),
sizeof(cgi.HudDrawElements[iInfo].shaderName)
);
cgi.HudDrawElements[iInfo].string[0] = 0;
cgi.HudDrawElements[iInfo].pFont = NULL;
cgi.HudDrawElements[iInfo].fontName[0] = 0;
@@ -1608,12 +1622,16 @@ void CG_ParseCGMessage_ver_15()
case CGM_HUDDRAW_STRING:
iInfo = cgi.MSG_ReadByte();
cgi.HudDrawElements[iInfo].hShader = 0;
strcpy(cgi.HudDrawElements[iInfo].string, cgi.MSG_ReadString());
Q_strncpyz(
cgi.HudDrawElements[iInfo].string, cgi.MSG_ReadString(), sizeof(cgi.HudDrawElements[iInfo].string)
);
break;
case CGM_HUDDRAW_FONT:
iInfo = cgi.MSG_ReadByte();
strcpy(cgi.HudDrawElements[iInfo].fontName, cgi.MSG_ReadString());
Q_strncpyz(
cgi.HudDrawElements[iInfo].fontName, cgi.MSG_ReadString(), sizeof(cgi.HudDrawElements[iInfo].fontName)
);
cgi.HudDrawElements[iInfo].hShader = 0;
cgi.HudDrawElements[iInfo].shaderName[0] = 0;
// load the font
@@ -1622,16 +1640,19 @@ void CG_ParseCGMessage_ver_15()
case CGM_NOTIFY_KILL:
case CGM_NOTIFY_HIT:
{
int iOldEnt;
if (cg.snap) {
const char *soundName;
int iOldEnt;
iOldEnt = current_entity_number;
iOldEnt = current_entity_number;
current_entity_number = cg.snap->ps.clientNum;
if (iType == CGM_NOTIFY_HIT) {
commandManager.PlaySound("dm_kill_notify", NULL, CHAN_LOCAL, 2.0, -1, -1, 1);
soundName = "dm_kill_notify";
} else {
commandManager.PlaySound("dm_hit_notify", NULL, CHAN_LOCAL, 2.0, -1, -1, 1);
soundName = "dm_hit_notify";
}
commandManager.PlaySound(soundName, NULL, CHAN_LOCAL, 2.0, -1, -1, 1);
current_entity_number = iOldEnt;
}
@@ -1653,29 +1674,58 @@ void CG_ParseCGMessage_ver_15()
if (iLarge) {
current_entity_number = iInfo;
commandManager.PlaySound(szTmp, vStart, CHAN_LOCAL, -1, -1, -1, 0);
} else {
commandManager.PlaySound(szTmp, vStart, CHAN_AUTO, -1, -1, -1, 0);
} else if (cg.snap) {
current_entity_number = cg.snap->ps.clientNum;
commandManager.PlaySound(szTmp, vStart, CHAN_AUTO, -1, -1, -1, 1);
commandManager.PlaySound(szTmp, vStart, CHAN_LOCAL, -1, -1, -1, 1);
}
CG_RadarClientSpeaks(iInfo);
current_entity_number = iOldEnt;
}
break;
case CGM_FENCEPOST:
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
vEnd[0] = cgi.MSG_ReadCoord();
vEnd[1] = cgi.MSG_ReadCoord();
vEnd[2] = cgi.MSG_ReadCoord();
cgi.MSG_ReadByte();
cgi.MSG_ReadByte();
VectorSubtract(vEnd, vStart, vTmp);
{
int iHalf;
vec3_t vForward, vRight, vUp;
float fLength;
// FIXME: unimplemented
// ?? can't figure out what is this
vStart[0] = cgi.MSG_ReadCoord();
vStart[1] = cgi.MSG_ReadCoord();
vStart[2] = cgi.MSG_ReadCoord();
vEnd[0] = cgi.MSG_ReadCoord();
vEnd[1] = cgi.MSG_ReadCoord();
vEnd[2] = cgi.MSG_ReadCoord();
iHalf = cgi.MSG_ReadByte();
cgi.MSG_ReadByte();
VectorSubtract(vEnd, vStart, vForward);
fLength = VectorNormalize(vForward);
iCount = fLength / 2.0;
MakeNormalVectors(vForward, vRight, vUp);
for (i = 0; i < iCount; i++) {
vec3_t vOrg;
vec3_t vNormal;
VectorCopy(vStart, vOrg);
VectorMA(vOrg, random(), vForward, vOrg);
VectorMA(vOrg, crandom() * iHalf, vRight, vOrg);
VectorMA(vOrg, crandom() * iHalf, vUp, vOrg);
//
// Spawn the fence wood effect
//
VectorSubtract(vStart, vOrg, vNormal);
VectorNormalize(vNormal);
sfxManager.MakeEffect_Normal(SFX_FENCE_WOOD, vOrg, vNormal);
}
}
break;
default:
cgi.Error(ERR_DROP, "CG_ParseCGMessage: Unknown CGM message type");
@@ -1853,7 +1903,7 @@ void CG_ParseCGMessage_ver_6()
vStart[2] = cgi.MSG_ReadCoord();
cgi.MSG_ReadDir(vEnd);
sfxManager.MakeEffect_Normal(SFX_EXP_GREN_PUDDLE + iType, vStart, vEnd);
sfxManager.MakeEffect_Normal((iType - CGM6_MAKE_EFFECT_1) + SFX_OIL_LEAK_BIG, vStart, vEnd);
break;
case CGM6_MAKE_CRATE_DEBRIS:
@@ -1917,7 +1967,11 @@ void CG_ParseCGMessage_ver_6()
case CGM6_HUDDRAW_SHADER:
iInfo = cgi.MSG_ReadByte();
strcpy(cgi.HudDrawElements[iInfo].shaderName, cgi.MSG_ReadString());
Q_strncpyz(
cgi.HudDrawElements[iInfo].shaderName,
cgi.MSG_ReadString(),
sizeof(cgi.HudDrawElements[iInfo].shaderName)
);
cgi.HudDrawElements[iInfo].string[0] = 0;
cgi.HudDrawElements[iInfo].pFont = NULL;
cgi.HudDrawElements[iInfo].fontName[0] = 0;
@@ -1959,12 +2013,16 @@ void CG_ParseCGMessage_ver_6()
case CGM6_HUDDRAW_STRING:
iInfo = cgi.MSG_ReadByte();
cgi.HudDrawElements[iInfo].hShader = 0;
strcpy(cgi.HudDrawElements[iInfo].string, cgi.MSG_ReadString());
Q_strncpyz(
cgi.HudDrawElements[iInfo].string, cgi.MSG_ReadString(), sizeof(cgi.HudDrawElements[iInfo].string)
);
break;
case CGM6_HUDDRAW_FONT:
iInfo = cgi.MSG_ReadByte();
strcpy(cgi.HudDrawElements[iInfo].fontName, cgi.MSG_ReadString());
Q_strncpyz(
cgi.HudDrawElements[iInfo].fontName, cgi.MSG_ReadString(), sizeof(cgi.HudDrawElements[iInfo].fontName)
);
cgi.HudDrawElements[iInfo].hShader = 0;
cgi.HudDrawElements[iInfo].shaderName[0] = 0;
// load the font
@@ -1973,10 +2031,11 @@ void CG_ParseCGMessage_ver_6()
case CGM6_NOTIFY_KILL:
case CGM6_NOTIFY_HIT:
{
if (cg.snap) {
int iOldEnt;
iOldEnt = current_entity_number;
iOldEnt = current_entity_number;
current_entity_number = cg.snap->ps.clientNum;
if (iType == CGM6_NOTIFY_HIT) {
commandManager.PlaySound("dm_kill_notify", NULL, CHAN_LOCAL, 2.0, -1, -1, 1);
@@ -2005,10 +2064,10 @@ void CG_ParseCGMessage_ver_6()
current_entity_number = iInfo;
commandManager.PlaySound(szTmp, vStart, CHAN_LOCAL, -1, -1, -1, 0);
} else {
} else if (cg.snap) {
current_entity_number = cg.snap->ps.clientNum;
commandManager.PlaySound(szTmp, vStart, CHAN_AUTO, -1, -1, -1, 1);
commandManager.PlaySound(szTmp, vStart, CHAN_LOCAL, -1, -1, -1, 1);
}
current_entity_number = iOldEnt;
+20 -3
View File
@@ -190,8 +190,9 @@ void CG_ShowTrace(trace_t *trace, int passent, const char *reason)
assert(reason);
assert(trace);
sprintf(
Com_sprintf(
text,
sizeof(text),
"%0.2f : Pass (%d) Frac %f Hit (%d): '%s'\n",
(float)cg.time / 1000.0f,
passent,
@@ -349,6 +350,13 @@ static void CG_InterpolatePlayerStateCamera(void)
return;
}
// Added in 2.0
if (cg.predicted_player_state.camera_flags & CF_CAMERA_ANGLES_TURRETMODE) {
VectorCopy(cg.nextSnap->ps.camera_origin, cg.camera_origin);
VectorCopy(cg.nextSnap->ps.camera_angles, cg.camera_angles);
return;
}
for (i = 0; i < 3; i++) {
cg.camera_origin[i] = prev->ps.camera_origin[i] + f * (next->ps.camera_origin[i] - prev->ps.camera_origin[i]);
cg.camera_angles[i] = LerpAngle(prev->ps.camera_angles[i], next->ps.camera_angles[i], f);
@@ -493,8 +501,13 @@ void CG_PredictPlayerState(void)
cg_pmove.leanSpeed = 2.f;
} else {
cg_pmove.alwaysAllowLean = qtrue;
if (cgs.gametype != GT_SINGLE_PLAYER) {
cg_pmove.leanMax = 40.f;
} else {
// Don't allow lean in single-player, like in the original game
cg_pmove.leanMax = 0;
}
cg_pmove.leanMax = 40.f;
cg_pmove.leanAdd = 10.f;
cg_pmove.leanRecoverSpeed = 15.f;
cg_pmove.leanSpeed = 4.f;
@@ -515,7 +528,11 @@ void CG_PredictPlayerState(void)
// the server time is beyond our current cg.time,
// because predicted player positions are going to
// be ahead of everything else anyway
if (cg.nextSnap && !cg.nextFrameTeleport && !cg.thisFrameTeleport) {
// Added in OPM: prediction check
// Don't use the next snapshot if the prediction is about to be disabled
// this prevent "blinking" issues like when entering a vehicle turret gun
// where arms would be seen shortly
if (cg.nextSnap && !cg.nextFrameTeleport && !cg.thisFrameTeleport && !(cg.nextSnap->ps.pm_flags & PMF_NO_PREDICTION)) {
cg.predicted_player_state = cg.nextSnap->ps;
cg.physicsTime = cg.nextSnap->serverTime;
} else {
+5 -2
View File
@@ -120,6 +120,7 @@ functions exported to the main executable
// console variable interaction
cvar_t *(*Cvar_Get)(const char *var_name, const char *value, int flags);
cvar_t *(*Cvar_Find)(const char *var_name);
void (*Cvar_Set)(const char *var_name, const char *value);
// ClientCommand and ConsoleCommand parameter access
@@ -360,6 +361,8 @@ functions exported to the main executable
void (*UI_ShowMenu)(const char *name, qboolean bForce);
void (*UI_HideMenu)(const char *name, qboolean bForce);
int (*UI_FontStringWidth)(fontheader_t *font, const char *string, int maxLen);
// Added in 2.0
float (*UI_GetObjectivesTop)(void);
int (*Key_StringToKeynum)(const char *str);
const char *(*Key_KeynumToBindString)(int keyNum);
@@ -465,8 +468,8 @@ functions exported to the main executable
int (*CG_GetParent)(int entNum);
float (*CG_GetObjectiveAlpha)();
int (*CG_PermanentMark)(
const vec3_t origin,
const vec3_t dir,
vec3_t origin,
vec3_t dir,
float orientation,
float sScale,
float tScale,
+43 -41
View File
@@ -58,19 +58,19 @@ void CG_PrepScoreBoardInfo()
{
switch (cgs.gametype) {
case GT_TEAM_ROUNDS:
strcpy(cg.scoresMenuName, "DM_Round_Scoreboard");
Q_strncpyz(cg.scoresMenuName, "DM_Round_Scoreboard", sizeof(cg.scoresMenuName));
break;
case GT_OBJECTIVE:
strcpy(cg.scoresMenuName, "Obj_Scoreboard");
Q_strncpyz(cg.scoresMenuName, "Obj_Scoreboard", sizeof(cg.scoresMenuName));
break;
case GT_TOW:
strcpy(cg.scoresMenuName, "Tow_Scoreboard");
Q_strncpyz(cg.scoresMenuName, "Tow_Scoreboard", sizeof(cg.scoresMenuName));
break;
case GT_LIBERATION:
strcpy(cg.scoresMenuName, "Lib_Scoreboard");
Q_strncpyz(cg.scoresMenuName, "Lib_Scoreboard", sizeof(cg.scoresMenuName));
break;
default:
strcpy(cg.scoresMenuName, "DM_Scoreboard");
Q_strncpyz(cg.scoresMenuName, "DM_Scoreboard", sizeof(cg.scoresMenuName));
break;
}
}
@@ -296,14 +296,15 @@ void CG_ParseScores_ver_15()
switch (iClientTeam) {
case 1:
strcpy(szString3, cgi.LV_ConvertString("Spectators"));
Q_strncpyz(szString3, cgi.LV_ConvertString("Spectators"), sizeof(szString3));
break;
case 2:
strcpy(szString3, cgi.LV_ConvertString("Free-For-Allers"));
Q_strncpyz(szString3, cgi.LV_ConvertString("Free-For-Allers"), sizeof(szString3));
break;
case 3:
sprintf(
Com_sprintf(
szString3,
sizeof(szString3),
"%s - %d %s",
cgi.LV_ConvertString("Allies"),
atoi(cgi.Argv(2 + iCurrentEntry + iDatumCount * i)),
@@ -312,8 +313,9 @@ void CG_ParseScores_ver_15()
iCurrentEntry++;
break;
case 4:
sprintf(
Com_sprintf(
szString3,
sizeof(szString3),
"%s - %d %s",
cgi.LV_ConvertString("Axis"),
atoi(cgi.Argv(2 + iCurrentEntry + iDatumCount * i)),
@@ -322,7 +324,7 @@ void CG_ParseScores_ver_15()
iCurrentEntry++;
break;
default:
strcpy(szString3, cgi.LV_ConvertString("No Team"));
Q_strncpyz(szString3, cgi.LV_ConvertString("No Team"), sizeof(szString3));
break;
}
} else if (iClientNum == -2) {
@@ -330,14 +332,14 @@ void CG_ParseScores_ver_15()
szString2[0] = 0;
szString3[0] = 0;
} else {
strcpy(szString2, va("%i", iClientNum));
strcpy(szString3, cg.clientinfo[iClientNum].name);
Q_strncpyz(szString2, va("%i", iClientNum), sizeof(szString2));
Q_strncpyz(szString3, cg.clientinfo[iClientNum].name, sizeof(szString3));
}
strcpy(szString4, cgi.Argv(2 + iCurrentEntry + iDatumCount * i));
strcpy(szString5, cgi.Argv(3 + iCurrentEntry + iDatumCount * i));
strcpy(szString6, cgi.Argv(4 + iCurrentEntry + iDatumCount * i));
strcpy(szString7, cgi.Argv(5 + iCurrentEntry + iDatumCount * i));
Q_strncpyz(szString4, cgi.Argv(2 + iCurrentEntry + iDatumCount * i), sizeof(szString4));
Q_strncpyz(szString5, cgi.Argv(3 + iCurrentEntry + iDatumCount * i), sizeof(szString5));
Q_strncpyz(szString6, cgi.Argv(4 + iCurrentEntry + iDatumCount * i), sizeof(szString6));
Q_strncpyz(szString7, cgi.Argv(5 + iCurrentEntry + iDatumCount * i), sizeof(szString7));
if (cgs.gametype >= GT_TEAM_ROUNDS && iClientNum == -1
&& (iClientTeam == TEAM_ALLIES || iClientTeam == TEAM_AXIS)) {
@@ -370,19 +372,19 @@ void CG_ParseScores_ver_15()
} else {
iClientNum = atoi(cgi.Argv(iCurrentEntry + iDatumCount * i));
if (iClientNum >= 0) {
strcpy(szString2, va("%i", iClientNum));
strcpy(szString3, cg.clientinfo[iClientNum].name);
strcpy(szString4, cgi.Argv(1 + iCurrentEntry + iDatumCount * i));
strcpy(szString5, cgi.Argv(2 + iCurrentEntry + iDatumCount * i));
strcpy(szString6, cgi.Argv(3 + iCurrentEntry + iDatumCount * i));
strcpy(szString7, cgi.Argv(4 + iCurrentEntry + iDatumCount * i));
Q_strncpyz(szString2, va("%i", iClientNum), sizeof(szString2));
Q_strncpyz(szString3, cg.clientinfo[iClientNum].name, sizeof(szString3));
Q_strncpyz(szString4, cgi.Argv(1 + iCurrentEntry + iDatumCount * i), sizeof(szString4));
Q_strncpyz(szString5, cgi.Argv(2 + iCurrentEntry + iDatumCount * i), sizeof(szString5));
Q_strncpyz(szString6, cgi.Argv(3 + iCurrentEntry + iDatumCount * i), sizeof(szString6));
Q_strncpyz(szString7, cgi.Argv(4 + iCurrentEntry + iDatumCount * i), sizeof(szString7));
} else {
szString2[0] = 0;
if (iClientNum == -3) {
strcpy(szString2, cgi.LV_ConvertString("Players"));
Q_strncpyz(szString2, cgi.LV_ConvertString("Players"), sizeof(szString2));
bIsHeader = qtrue;
} else if (iClientNum == -2) {
strcpy(szString2, cgi.LV_ConvertString("Spectators"));
Q_strncpyz(szString2, cgi.LV_ConvertString("Spectators"), sizeof(szString2));
bIsHeader = qtrue;
} else {
// unknown
@@ -535,32 +537,32 @@ void CG_ParseScores_ver_6()
switch (iClientTeam) {
case 1:
strcpy(szString2, cgi.LV_ConvertString("Spectators"));
Q_strncpyz(szString2, cgi.LV_ConvertString("Spectators"), sizeof(szString2));
break;
case 2:
strcpy(szString2, cgi.LV_ConvertString("Free-For-Allers"));
Q_strncpyz(szString2, cgi.LV_ConvertString("Free-For-Allers"), sizeof(szString2));
break;
case 3:
strcpy(szString2, cgi.LV_ConvertString("Allies"));
Q_strncpyz(szString2, cgi.LV_ConvertString("Allies"), sizeof(szString2));
break;
case 4:
strcpy(szString2, cgi.LV_ConvertString("Axis"));
Q_strncpyz(szString2, cgi.LV_ConvertString("Axis"), sizeof(szString2));
break;
default:
strcpy(szString2, cgi.LV_ConvertString("No Team"));
Q_strncpyz(szString2, cgi.LV_ConvertString("No Team"), sizeof(szString2));
break;
}
} else if (iClientNum == -2) {
// spectating
szString2[0] = 0;
} else {
strcpy(szString2, cg.clientinfo[iClientNum].name);
Q_strncpyz(szString2, cg.clientinfo[iClientNum].name, sizeof(szString2));
}
strcpy(szString3, cgi.Argv(2 + iCurrentEntry + iDatumCount * i));
strcpy(szString4, cgi.Argv(3 + iCurrentEntry + iDatumCount * i));
strcpy(szString5, cgi.Argv(4 + iCurrentEntry + iDatumCount * i));
strcpy(szString6, cgi.Argv(5 + iCurrentEntry + iDatumCount * i));
Q_strncpyz(szString3, cgi.Argv(2 + iCurrentEntry + iDatumCount * i), sizeof(szString3));
Q_strncpyz(szString4, cgi.Argv(3 + iCurrentEntry + iDatumCount * i), sizeof(szString4));
Q_strncpyz(szString5, cgi.Argv(4 + iCurrentEntry + iDatumCount * i), sizeof(szString5));
Q_strncpyz(szString6, cgi.Argv(5 + iCurrentEntry + iDatumCount * i), sizeof(szString6));
if (iClientNum == cg.snap->ps.clientNum) {
pItemTextColor = vThisClientTextColor;
@@ -587,17 +589,17 @@ void CG_ParseScores_ver_6()
} else {
iClientNum = atoi(cgi.Argv(iCurrentEntry + iDatumCount * i));
if (iClientNum >= 0) {
strcpy(szString2, cg.clientinfo[iClientNum].name);
strcpy(szString3, cgi.Argv(1 + iCurrentEntry + iDatumCount * i));
strcpy(szString4, cgi.Argv(2 + iCurrentEntry + iDatumCount * i));
strcpy(szString5, cgi.Argv(3 + iCurrentEntry + iDatumCount * i));
strcpy(szString6, cgi.Argv(4 + iCurrentEntry + iDatumCount * i));
Q_strncpyz(szString2, cg.clientinfo[iClientNum].name, sizeof(szString2));
Q_strncpyz(szString3, cgi.Argv(1 + iCurrentEntry + iDatumCount * i), sizeof(szString3));
Q_strncpyz(szString4, cgi.Argv(2 + iCurrentEntry + iDatumCount * i), sizeof(szString4));
Q_strncpyz(szString5, cgi.Argv(3 + iCurrentEntry + iDatumCount * i), sizeof(szString5));
Q_strncpyz(szString6, cgi.Argv(4 + iCurrentEntry + iDatumCount * i), sizeof(szString6));
} else {
if (iClientNum == -3) {
strcpy(szString2, cgi.LV_ConvertString("Players"));
Q_strncpyz(szString2, cgi.LV_ConvertString("Players"), sizeof(szString2));
bIsHeader = qtrue;
} else if (iClientNum == -2) {
strcpy(szString2, cgi.LV_ConvertString("Spectators"));
Q_strncpyz(szString2, cgi.LV_ConvertString("Spectators"), sizeof(szString2));
bIsHeader = qtrue;
} else {
// unknown
+263 -8
View File
@@ -1,6 +1,7 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
Copyright (C) 2008-2024 the OpenMoHAA team
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of OpenMoHAA source code.
@@ -26,11 +27,27 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cg_local.h"
#include "../fgame/bg_voteoptions.h"
static qboolean CG_IsStatementFiltered(char *cmd);
/*
================
IsWeaponAllowed
Returns true if the weapon is allowed
================
*/
static const char *IsWeaponAllowed(int dmFlags, int flags)
{
return (dmFlags & flags) ? "0" : "1";
}
/*
================
QueryLandminesAllowed2
Returns true if landmines is allowed by the map or by a dm flag
================
*/
static qboolean QueryLandminesAllowed2(const char *mapname, int dmflags)
{
if (dmflags & DF_WEAPON_NO_LANDMINE) {
@@ -134,6 +151,7 @@ void CG_ParseServerinfo(void)
cgi.Cvar_Set("cg_fraglimit", Info_ValueForKey(info, "fraglimit"));
cgi.Cvar_Set("cg_timelimit", Info_ValueForKey(info, "timelimit"));
cgi.Cvar_Set("cg_maxclients", Info_ValueForKey(info, "sv_gametype"));
cgi.Cvar_Set("cg_allowvote", Info_ValueForKey(info, "g_allowvote"));
cgi.Cvar_Set("cg_obj_alliedtext1", Info_ValueForKey(info, "g_obj_alliedtext1"));
cgi.Cvar_Set("cg_obj_alliedtext2", Info_ValueForKey(info, "g_obj_alliedtext2"));
cgi.Cvar_Set("cg_obj_alliedtext3", Info_ValueForKey(info, "g_obj_alliedtext3"));
@@ -148,10 +166,10 @@ void CG_ParseServerinfo(void)
cgi.Cvar_Set("cg_scoreboardpicover", Info_ValueForKey(info, "g_scoreboardpicover"));
mapChecksumStr = Info_ValueForKey(info, "sv_mapChecksum");
if (mapChecksumStr && mapChecksumStr[0]) {
cgs.mapChecksum = atoi(mapChecksumStr);
cgs.mapChecksum = atoi(mapChecksumStr);
cgs.useMapChecksum = qtrue;
} else {
cgs.mapChecksum = 0;
cgs.mapChecksum = 0;
cgs.useMapChecksum = qfalse;
}
@@ -169,7 +187,7 @@ void CG_ParseServerinfo(void)
if (spawnpos) {
Q_strncpyz(map, mapname, spawnpos - mapname + 1);
} else {
strcpy(map, mapname);
Q_strncpyz(map, mapname, sizeof(map));
}
Com_sprintf(cgs.mapname, sizeof(cgs.mapname), "maps/%s.bsp", map);
@@ -311,12 +329,12 @@ static void CG_ServerCommand(qboolean modelOnly)
}
return;
} else if (!strcmp(cmd, "printdeathmsg")) {
const char *s1, *s2, * attackerName, * victimName, *type;
const char *s1, *s2, *attackerName, *victimName, *type;
const char *result1, *result2;
int hudColor;
result1 = NULL;
result2 = NULL;
result1 = NULL;
result2 = NULL;
s1 = cgi.Argv(1);
s2 = cgi.Argv(2);
attackerName = cgi.Argv(3);
@@ -352,7 +370,14 @@ static void CG_ServerCommand(qboolean modelOnly)
}
if (!strcmp(cmd, "stufftext")) {
cgi.Cmd_Stuff(cgi.Argv(1));
char *cmd = cgi.Argv(1);
if (CG_IsStatementFiltered(cmd)) {
// Added in OPM
// Don't execute filtered commands
return;
}
cgi.Cmd_Stuff(cmd);
cgi.Cmd_Stuff("\n");
return;
}
@@ -429,3 +454,233 @@ void CG_ExecuteNewServerCommands(int latestSequence, qboolean differentServer)
}
}
}
//
// List of client variables allowed to be changed by the server
//
static const char *whiteListedVariables[] = {
"r_fastsky", // some mods set this variable to make the sky uniform
"ui_hud",
};
//
// List of client variables allowed to be changed by the server
//
static const char *whiteListedLocalServerVariables[] = {"ui_hidemouse", "ui_showmouse", "cg_marks_add"};
//
// List of commands allowed to be executed by the server
//
static const char *whiteListedCommands[] = {
"primarydmweapon",
"pushmenu",
"pushmenu_teamselect",
"pushmenu_weaponselect",
"popmenu",
"wait",
"globalwidgetcommand", // used for mods adding custom HUDs
"ui_addhud",
"ui_removehud",
"tmstart",
"tmstartloop",
"tmstop",
"tmvolume",
"`stufftext",
"+moveup", // workaround for mods that want to prevent inactivity when handling the spectate
"-moveup",
"screenshot",
"screenshotJPEG",
"levelshot"
};
//
// List of commands allowed to be executed by the server
//
static const char *whiteListedLocalServerCommands[] = {
"spmap", // Used by briefings
"map",
"disconnect",
"cinematic",
"showmenu",
"hidemenu"
};
/*
====================
CG_IsVariableFiltered
Returns whether or not the variable should be filtered
====================
*/
static qboolean CG_IsVariableFiltered(const char *name)
{
cvar_t *var;
size_t i;
for (i = 0; i < ARRAY_LEN(whiteListedVariables); i++) {
if (!Q_stricmp(name, whiteListedVariables[i])) {
return qfalse;
}
}
if (cgs.localServer) {
for (i = 0; i < ARRAY_LEN(whiteListedLocalServerVariables); i++) {
if (!Q_stricmp(name, whiteListedLocalServerVariables[i])) {
return qfalse;
}
}
}
// Filtered
return qtrue;
}
/*
====================
CG_IsSetVariableFiltered
Returns whether or not the variable should be filtered
====================
*/
static qboolean CG_IsSetVariableFiltered(const char *name, char type)
{
cvar_t *var;
if (!CG_IsVariableFiltered(name)) {
return qfalse;
}
if (type != 'u' && type != 's') {
// Don't allow custom info variables to avoid flooding
// the client with many serverinfo and userinfo variables
var = cgi.Cvar_Find(name);
if (!var) {
// Allow as it doesn't exist
return qfalse;
}
if (var->flags & CVAR_USER_CREATED) {
// Allow, it's user-created, wouldn't cause issues
return qfalse;
}
}
// Filtered
return qtrue;
}
/*
====================
CG_IsCommandFiltered
Returns whether or not the variable should be filtered
====================
*/
static qboolean CG_IsCommandFiltered(const char *name)
{
size_t i;
for (i = 0; i < ARRAY_LEN(whiteListedCommands); i++) {
if (!Q_stricmp(name, whiteListedCommands[i])) {
return qfalse;
}
}
if (cgs.localServer) {
// Allow more commands when the client is hosting the server
// Mostly used on single-player mode, like when briefings switch to the next map
for (i = 0; i < ARRAY_LEN(whiteListedLocalServerCommands); i++) {
if (!Q_stricmp(name, whiteListedLocalServerCommands[i])) {
return qfalse;
}
}
}
//
// Test variables
//
return CG_IsVariableFiltered(name);
}
/*
====================
RemoveEndToken
====================
*/
static qboolean RemoveEndToken(char* com_token) {
char* p;
for (p = com_token; p[0]; p++) {
if (*p == ';') {
*p = 0;
return qtrue;
}
}
return qfalse;
}
/*
====================
CG_IsStatementFiltered
Returns whether or not the statement is filtered
====================
*/
static qboolean CG_IsStatementFiltered(char *cmd)
{
char* parsed;
char* p;
char com_token[256];
qboolean bNextStatement = qfalse;
parsed = cmd;
for (Q_strncpyz(com_token, COM_ParseExt(&parsed, qtrue), sizeof(com_token)); com_token[0]; Q_strncpyz(com_token, COM_ParseExt(&parsed, qtrue), sizeof(com_token))) {
bNextStatement = RemoveEndToken(com_token);
if (com_token[0] == ';') {
continue;
}
if (!Q_stricmp(com_token, "set") || !Q_stricmp(com_token, "setu") || !Q_stricmp(com_token, "seta")
|| !Q_stricmp(com_token, "sets")) {
char type = com_token[3];
//
// variable
//
Q_strncpyz(com_token, COM_ParseExt(&parsed, qfalse), sizeof(com_token));
bNextStatement |= RemoveEndToken(com_token);
if (com_token[0] == ';') {
continue;
}
if (CG_IsSetVariableFiltered(com_token, type)) {
return qtrue;
}
} else {
//
// normal command
//
if (CG_IsCommandFiltered(com_token)) {
return qtrue;
}
}
if (!bNextStatement) {
// Skip up to the next statement
while (parsed && parsed[0]) {
char c = parsed[0];
parsed++;
if (c == '\n' || c == ';') {
break;
}
}
}
}
return qfalse;
}
+9 -6
View File
@@ -73,10 +73,10 @@ static void CG_ResetEntity(centity_t *cent)
CG_RemoveClientEntity(cent->currentState.number, tiki, cent);
// reset the animation for the entities
if (tiki && tiki->a->bIsCharacter) {
if (tiki) {
for (i = 0; i < MAX_FRAMEINFOS; i++) {
cent->animLast[i] = cent->currentState.frameInfo[i].index;
cent->animLastTimes[i] = cent->currentState.frameInfo[i].time;
cent->animLast[i] = -1;
cent->animLastTimes[i] = -1;
if (cent->currentState.frameInfo[i].weight) {
cent->animLastWeight |= 1 << i;
} else {
@@ -87,7 +87,8 @@ static void CG_ResetEntity(centity_t *cent)
} else {
// clear all the last animations
for (i = 0; i < MAX_FRAMEINFOS; i++) {
cent->animLast[i] = -1;
cent->animLast[i] = -1;
cent->animLastTimes[i] = 0.0;
}
cent->animLastWeight = 0;
@@ -346,8 +347,10 @@ static snapshot_t *CG_ReadNextSnapshot(void)
snapshot_t *dest;
if (cg.latestSnapshotNum > cgs.processedSnapshotNum + 1000) {
cgi.Error(
ERR_DROP, "CG_ReadNextSnapshot: way out of range, %i > %i", cg.latestSnapshotNum, cgs.processedSnapshotNum
cgi.Printf(
"WARNING: CG_ReadNextSnapshot: way out of range, %i > %i\n",
cg.latestSnapshotNum,
cgs.processedSnapshotNum
);
}
+3 -3
View File
@@ -95,7 +95,7 @@ void ClientSpecialEffectsManager::LoadEffects()
cgi.DPrintf("Loading Special Effects...\n");
AxisClear(axis);
for (i = 0; i < MAX_SPECIAL_EFFECTS; i++) {
for (i = 0; i < SFX_COUNT; i++) {
switch (i) {
case SFX_BHIT_PAPER_LITE:
szEffectModel = "models/fx/bh_paper_lite.tik";
@@ -512,7 +512,7 @@ void ClientSpecialEffectsManager::ExecuteEffect(
current_tiki = NULL;
pCommand->emitter->cgd.origin = vPos;
if (pCommand->emitter->cgd.flags & T_ANGLES) {
if (!(pCommand->emitter->cgd.flags & T_ANGLES)) {
pCommand->emitter->cgd.angles = vAngles;
}
@@ -1194,5 +1194,5 @@ qboolean ClientSpecialEffectsManager::EffectsPending()
specialeffect_t *ClientSpecialEffectsManager::GetTestEffectPointer()
{
return &m_effects[SPECIAL_EFFECT_TEST];
return &m_effects[SFX_TEST_EFFECT];
}
+1 -4
View File
@@ -170,12 +170,9 @@ public:
specialeffectcommand_t *AddNewCommand();
};
#define MAX_SPECIAL_EFFECTS 99
#define SPECIAL_EFFECT_TEST MAX_SPECIAL_EFFECTS - 1
class ClientSpecialEffectsManager : public Listener
{
specialeffect_t m_effects[99];
specialeffect_t m_effects[SFX_COUNT];
qboolean m_bEffectsLoaded;
int m_iNumPendingEvents;
+92 -20
View File
@@ -79,6 +79,11 @@ void ClientGameCommandManager::FreeTempModel(ctempmodel_t *p)
RemoveClientEntity(p->number, p->cgd.tiki, NULL, p);
if (m_active_tempmodels.next == p) {
// use the next active temp model
m_active_tempmodels.next = p->next;
}
// remove from the doubly linked active list
p->prev->next = p->next;
p->next->prev = p->prev;
@@ -86,6 +91,22 @@ void ClientGameCommandManager::FreeTempModel(ctempmodel_t *p)
// the free list is only singly linked
p->next = m_free_tempmodels;
m_free_tempmodels = p;
if (p->m_spawnthing) {
p->m_spawnthing->numtempmodels--;
// delete unused spawnthings
if (!p->m_spawnthing->numtempmodels) {
m_emitters.RemoveObject(p->m_spawnthing);
if (p->m_spawnthing == m_spawnthing) {
m_spawnthing = NULL;
}
delete p->m_spawnthing;
}
p->m_spawnthing = NULL;
}
}
//===============
@@ -418,9 +439,11 @@ qboolean ClientGameCommandManager::TempModelRealtimeEffects(ctempmodel_t *p, flo
p->ent.shaderRGBA[0] = (int)((float)tempColor[0] * vLighting[0]);
p->ent.shaderRGBA[1] = (int)((float)tempColor[1] * vLighting[1]);
p->ent.shaderRGBA[2] = (int)((float)tempColor[2] * vLighting[2]);
} else {
p->ent.shaderRGBA[0] = tempColor[0];
p->ent.shaderRGBA[1] = tempColor[1];
p->ent.shaderRGBA[2] = tempColor[2];
}
if (p->cgd.flags & T_FADEIN && (fadein < 1)) // Do the fadein effect
@@ -518,6 +541,7 @@ qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t *p, float ftime
Vector tempangles;
trace_t trace;
float dot;
int i;
VectorCopy(p->ent.origin, p->lastEnt.origin);
AxisCopy(p->ent.axis, p->lastEnt.axis);
@@ -633,9 +657,7 @@ qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t *p, float ftime
p->cgd.velocity.x = Q_clamp_float(p->cgd.velocity.x, p->cgd.minVel.x, p->cgd.maxVel.x);
p->cgd.velocity.y = Q_clamp_float(p->cgd.velocity.y, p->cgd.minVel.y, p->cgd.maxVel.y);
p->cgd.velocity.z = Q_clamp_float(p->cgd.velocity.z, p->cgd.minVel.z, p->cgd.maxVel.z);
}
if (p->cgd.flags2 & T2_CLAMP_VEL_AXIS) {
} else if (p->cgd.flags2 & T2_CLAMP_VEL_AXIS) {
Vector localVelocity;
localVelocity.x = DotProduct(p->cgd.velocity, p->ent.axis[0]);
localVelocity.y = DotProduct(p->cgd.velocity, p->ent.axis[1]);
@@ -650,8 +672,48 @@ qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t *p, float ftime
p->cgd.velocity.z = DotProduct(localVelocity, p->ent.axis[2]);
}
if (p->cgd.flags2 & T_ALIGN) {
// FIXME: vss wind
if (p->cgd.flags2 & T2_WIND_AFFECT) {
for (i = 0; i < 3; i++) {
float fWind;
switch (i) {
case 0:
fWind = vss_wind_x->value;
break;
case 1:
fWind = vss_wind_y->value;
break;
case 2:
fWind = vss_wind_z->value;
break;
}
if (fWind < 0) {
if (p->cgd.velocity[i] > fWind) {
p->cgd.velocity[i] -= ftime * vss_wind_strength->value;
if (p->cgd.velocity[i] > fWind) {
p->cgd.velocity[i] = fWind;
}
} else if (p->cgd.velocity[i] < fWind) {
p->cgd.velocity[i] += ftime * vss_movement_dampen->value;
if (p->cgd.velocity[i] < fWind) {
p->cgd.velocity[i] = fWind;
}
}
} else {
if (p->cgd.velocity[i] < fWind) {
p->cgd.velocity[i] += ftime * vss_wind_strength->value;
if (p->cgd.velocity[i] > fWind) {
p->cgd.velocity[i] = fWind;
}
} else if (p->cgd.velocity[i] > fWind) {
p->cgd.velocity[i] -= ftime * vss_wind_strength->value;
if (p->cgd.velocity[i] < fWind) {
p->cgd.velocity[i] = fWind;
}
}
}
}
}
} else {
Vector normal;
@@ -913,7 +975,12 @@ void ClientGameCommandManager::AddTempModels(void)
// time of this tempmodel
lerpfrac = (float)(cg.time - p->lastPhysicsTime) / (float)physics_rate;
// Clamp
lerpfrac = Q_clamp_float(lerpfrac, 0, 1);
if (lerpfrac > 1 || (p->cgd.flags2 & T2_PHYSICS_EVERYFRAME)) {
lerpfrac = 1;
}
if (lerpfrac < 0) {
lerpfrac = 0;
}
// Increment the time this tempmodel has been alive
p->aliveTime += frameTime;
@@ -1137,7 +1204,13 @@ void ClientGameCommandManager::SpawnTempModel(int mcount)
{
Vector dst;
// Create a circular shaped burst around the up vector
float angle = ((float)count / (float)m_spawnthing->count) * 360; // * M_PI * 2;
float angle;
if (mcount == 1) {
angle = random() * 360;
} else {
angle = ((float)count / (float)m_spawnthing->count) * 360; // * M_PI * 2;
}
Vector end = Vector(vLeft) * m_spawnthing->sphereRadius * current_entity_scale;
RotatePointAroundVector(dst, Vector(vForward), end, angle);
@@ -1390,7 +1463,7 @@ void ClientGameCommandManager::SpawnTempModel(int mcount)
p->cgd.avelocity[i] = m_spawnthing->avelocity_amplitude[i] * random() + m_spawnthing->avelocity_base[i];
// Randomize angles or set absolute
p->cgd.angles[i] += random() * m_spawnthing->angles_amplitude[i];
p->cgd.angles[i] = m_spawnthing->angles_amplitude[i] * random() + m_spawnthing->cgd.angles[i];
}
// If forward velocity is set, just use that otherwise use random
@@ -1424,18 +1497,15 @@ void ClientGameCommandManager::SpawnTempModel(int mcount)
}
}
// Calculate one tick of velocity based on time alive ( passed in )
p->cgd.origin = p->cgd.origin + (p->cgd.velocity * ((float)p->aliveTime / 1000.0f) * current_entity_scale);
if (p->cgd.flags2 & T2_ACCEL) {
if (m_spawnthing->cgd.flags2 & T2_RADIALVELOCITY) {
float fLength;
p->cgd.velocity = p->cgd.origin - start;
fLength = p->cgd.velocity.length();
if (fLength) {
float fVel = m_spawnthing->cgd.velocity.x
+ (m_spawnthing->cgd.velocity.y + m_spawnthing->cgd.velocity.z * crandom()) / fLength;
float fVel = m_spawnthing->cgd.velocity[0]
+ (m_spawnthing->cgd.velocity[1] + m_spawnthing->cgd.velocity[2] * random()) / fLength;
p->cgd.velocity *= fVel;
}
@@ -1446,20 +1516,22 @@ void ClientGameCommandManager::SpawnTempModel(int mcount)
(m_spawnthing->randvel_base[i] + m_spawnthing->randvel_amplitude[i] * random()) * current_entity_scale;
if (m_spawnthing->cgd.flags & T_RANDVELAXIS) {
p->cgd.velocity += fVel * Vector(m_spawnthing->tag_axis[i]);
if (p->cgd.flags2 & T2_NOTAGAXIS) {
p->cgd.velocity += fVel * Vector(m_spawnthing->axis[i]);
} else {
p->cgd.velocity += fVel * Vector(m_spawnthing->tag_axis[i]);
}
} else {
p->cgd.velocity[i] += fVel;
}
}
if (p->cgd.flags & (T_ALIGN | T_DETAIL)) {
if (p->cgd.velocity.x && p->cgd.velocity.y) {
p->cgd.angles = p->cgd.velocity.toAngles();
}
p->cgd.origin += p->cgd.velocity * (p->aliveTime / 1000.0) * current_entity_scale;
p->cgd.angles = p->cgd.velocity.toAngles();
}
p->cgd.origin += p->cgd.velocity * (p->aliveTime / 1000.0) * current_entity_scale;
if (p->cgd.flags & T_AUTOCALCLIFE) {
Vector end, delta;
float length, speed;
File diff suppressed because it is too large. Load diff
+34 -5
View File
@@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cg_local.h"
#include "str.h"
#include "../client/keycodes.h"
void CG_MessageMode_f(void)
{
@@ -61,8 +62,8 @@ void CG_MessageMode_Private_f(void)
return;
}
clientNum = atoi(cgi.Argv(1)) - 1;
if (clientNum < 0 || clientNum >= MAX_CLIENTS) {
clientNum = atoi(cgi.Argv(1));
if (clientNum < 1 || clientNum >= MAX_CLIENTS) {
cgi.Printf(HUD_MESSAGE_CHAT_WHITE "Message Error: %s is a bad client number\n", cgi.Argv(1));
return;
}
@@ -192,8 +193,36 @@ void CG_HudPrint_f(void)
cgi.Printf("\x1%s", cgi.Argv(1));
}
int CG_CheckCaptureKey(int key, qboolean down, unsigned int time)
qboolean CG_CheckCaptureKey(int key, qboolean down, unsigned int time)
{
// FIXME: unimplemented
return 0;
char minKey = '1', maxKey = '9';
if (!cg.iInstaMessageMenu || !down) {
return qfalse;
}
if (cg_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) {
maxKey = '8';
}
if (key < minKey || key > maxKey) {
if (key == K_ESCAPE || key == '0') {
cg.iInstaMessageMenu = 0;
return qtrue;
}
return qfalse;
}
if (cg.iInstaMessageMenu == -1) {
if (key > '6') {
cg.iInstaMessageMenu = 0;
} else {
cg.iInstaMessageMenu = key - '0';
}
} else if (cg.iInstaMessageMenu > 0) {
cgi.SendClientCommand(va("dmmessage 0 *%i%i\n", cg.iInstaMessageMenu, key - '0'));
cg.iInstaMessageMenu = 0;
}
return qtrue;
}
+51 -11
View File
@@ -242,6 +242,7 @@ void CG_OffsetFirstPersonView(refEntity_t *pREnt, qboolean bUseWorldPosition)
float mat[3][3];
vec3_t vOldOrigin;
vec3_t vStart, vEnd, vMins, vMaxs;
vec3_t vVelocity;
trace_t trace;
VectorSet(vMins, -6, -6, -6);
@@ -297,6 +298,15 @@ 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)) {
VectorCopy(cg.predicted_player_state.velocity, vVelocity);
} else {
//
// Added in OPM
// When frozen, there must be no movement at all
VectorClear(vVelocity);
}
if (bUseWorldPosition) {
iMask = MASK_VIEWSOLID;
} else {
@@ -367,7 +377,7 @@ void CG_OffsetFirstPersonView(refEntity_t *pREnt, qboolean bUseWorldPosition)
}
if (cg.predicted_player_state.walking) {
fVel = VectorLength(cg.predicted_player_state.velocity);
fVel = VectorLength(vVelocity);
fPhase = fVel * 0.0015 + 0.9;
cg.fCurrentViewBobPhase += (cg.frametime / 1000.0 + cg.frametime / 1000.0) * M_PI * fPhase;
@@ -446,7 +456,7 @@ void CG_OffsetFirstPersonView(refEntity_t *pREnt, qboolean bUseWorldPosition)
AngleVectorsLeft(vDelta, mat[0], mat[1], mat[2]);
CG_CalcViewModelMovement(
cg.fCurrentViewBobPhase, cg.fCurrentViewBobAmp, cg.predicted_player_state.velocity, vDelta
cg.fCurrentViewBobPhase, cg.fCurrentViewBobAmp, vVelocity, vDelta
);
VectorMA(pREnt->origin, vDelta[0], mat[0], pREnt->origin);
@@ -712,7 +722,37 @@ float CG_SensitivityScale()
void CG_AddLightShow()
{
// FIXME: unimplemented
int i;
float fSlopeY, fSlopeZ;
float x, y, z;
vec3_t vOrg;
float r, g, b;
float fMax;
fSlopeY = tan(cg.refdef.fov_x * 0.5);
fSlopeZ = tan(cg.refdef.fov_y * 0.5);
for (i = 0; i < cg_acidtrip->integer; i++) {
x = pow(random(), 1.0 / 3.0) * 2048.0;
y = crandom() * x * fSlopeY;
z = crandom() * x * fSlopeZ;
VectorCopy(cg.refdef.vieworg, vOrg);
VectorMA(vOrg, x, cg.refdef.viewaxis[0], vOrg);
VectorMA(vOrg, y, cg.refdef.viewaxis[1], vOrg);
VectorMA(vOrg, z, cg.refdef.viewaxis[2], vOrg);
r = random();
g = random();
b = random();
fMax = Q_max(r, Q_max(g, b));
r /= fMax;
g /= fMax;
b /= fMax;
cgi.R_AddLightToScene(vOrg, (rand() & 0x1FF) + 0x80, r, g, b, 0);
}
}
qboolean CG_FrustumCullSphere(const vec3_t vPos, float fRadius) {
@@ -871,13 +911,13 @@ void CG_DrawActiveFrame(int serverTime, int frameTime, stereoFrame_t stereoView,
{
default:
case 0:
cgi.UI_HideMenu("mission_success_1", CVAR_ARCHIVE);
cgi.UI_HideMenu("mission_success_1", qtrue);
break;
case 2:
cgi.UI_HideMenu("mission_success_2", CVAR_ARCHIVE);
cgi.UI_HideMenu("mission_success_2", qtrue);
break;
case 3:
cgi.UI_HideMenu("mission_success_3", CVAR_ARCHIVE);
cgi.UI_HideMenu("mission_success_3", qtrue);
break;
}
} else {
@@ -885,21 +925,21 @@ void CG_DrawActiveFrame(int serverTime, int frameTime, stereoFrame_t stereoView,
{
default:
case 0:
cgi.UI_HideMenu("mission_failed_1", CVAR_ARCHIVE);
cgi.UI_HideMenu("mission_failed_1", qtrue);
break;
case 2:
cgi.UI_HideMenu("mission_failed_2", CVAR_ARCHIVE);
cgi.UI_HideMenu("mission_failed_2", qtrue);
break;
case 3:
cgi.UI_HideMenu("mission_failed_3", CVAR_ARCHIVE);
cgi.UI_HideMenu("mission_failed_3", qtrue);
break;
}
}
} else {
if (cgi.Cvar_Get("g_success", "", 0)->integer) {
cgi.UI_HideMenu("StatsScreen_Success", qfalse);
cgi.UI_HideMenu("StatsScreen_Success", qtrue);
} else {
cgi.UI_HideMenu("StatsScreen_Failed", qfalse);
cgi.UI_HideMenu("StatsScreen_Failed", qtrue);
}
}
}
+3 -3
View File
@@ -351,7 +351,7 @@ void CG_ViewModelAnimation(refEntity_t *pModel)
} else {
iAnimPrefixIndex = CG_GetVMAnimPrefixIndex();
cgi.anim->g_iLastEquippedWeaponStat = cg.snap->ps.stats[STAT_EQUIPPED_WEAPON];
strcpy(cgi.anim->g_szLastActiveItem, CG_ConfigString(CS_WEAPONS + cg.snap->ps.activeItems[1]));
Q_strncpyz(cgi.anim->g_szLastActiveItem, CG_ConfigString(CS_WEAPONS + cg.snap->ps.activeItems[1]), sizeof(cgi.anim->g_szLastActiveItem));
cgi.anim->g_iLastAnimPrefixIndex = iAnimPrefixIndex;
bAnimChanged = qtrue;
@@ -359,7 +359,7 @@ void CG_ViewModelAnimation(refEntity_t *pModel)
}
if (cgi.anim->g_iLastVMAnim == -1) {
sprintf(szAnimName, "%s_idle", AnimPrefixList[iAnimPrefixIndex]);
Com_sprintf(szAnimName, sizeof(szAnimName), "%s_idle", AnimPrefixList[iAnimPrefixIndex]);
cgi.anim->g_VMFrameInfo[cgi.anim->g_iCurrentVMAnimSlot].index = cgi.Anim_NumForName(pTiki, szAnimName);
if (cgi.anim->g_VMFrameInfo[cgi.anim->g_iCurrentVMAnimSlot].index == -1) {
@@ -428,7 +428,7 @@ void CG_ViewModelAnimation(refEntity_t *pModel)
break;
}
sprintf(szAnimName, "%s_%s", AnimPrefixList[iAnimPrefixIndex], pszAnimSuffix);
Com_sprintf(szAnimName, sizeof(szAnimName), "%s_%s", AnimPrefixList[iAnimPrefixIndex], pszAnimSuffix);
if (!bWeaponChanged) {
fCrossblendTime =
cgi.Anim_CrossblendTime(pTiki, cgi.anim->g_VMFrameInfo[cgi.anim->g_iCurrentVMAnimSlot].index);
+30 -40
View File
@@ -209,7 +209,7 @@ void ClientGameCommandManager::ResetVSSSources()
void ClientGameCommandManager::ResetVSSSources(Event *ev)
{
// FIXME: stub??
ResetVSSSources();
}
void CG_ResetVSSSources()
@@ -289,13 +289,13 @@ qboolean VSS_SourcePhysics(cvssource_t *pSource, float ftime)
fWind = 0.0;
if ((pSource->flags2 & 5) != 0) {
if ((pSource->flags2 & (T2_ACCEL | T2_MOVE)) != 0) {
VectorMA(pSource->velocity, ftime, pSource->repulsion, pSource->velocity);
}
pSource->lastOrigin = pSource->newOrigin;
if (pSource->flags & 0x800) {
if (pSource->flags & T_COLLISION) {
trace.allsolid = qfalse;
CG_ClipMoveToEntities(
pSource->newOrigin, vec3_origin, vec3_origin, pSource->newOrigin, -1, MASK_VOLUMETRIC_SMOKE, &trace, qfalse
@@ -315,11 +315,11 @@ qboolean VSS_SourcePhysics(cvssource_t *pSource, float ftime)
}
}
if (pSource->flags2 & 5) {
if (pSource->flags2 & (T2_ACCEL | T2_MOVE)) {
VectorMA(pSource->newOrigin, ftime, pSource->velocity, pSource->newOrigin);
}
if (pSource->flags & 0x800) {
if (pSource->flags & T_COLLISION) {
CG_Trace(
&trace,
pSource->lastOrigin,
@@ -363,7 +363,7 @@ qboolean VSS_SourcePhysics(cvssource_t *pSource, float ftime)
}
iSmokeType = abs(pSource->smokeType);
if (pSource->flags2 & 5) {
if (pSource->flags2 & (T2_ACCEL | T2_MOVE)) {
VectorCopy(pSource->velocity, vVel);
for (i = 0; i < 3; i++) {
@@ -624,7 +624,7 @@ qboolean VSS_LerpSource(cvssource_t *pCurrent, cvssourcestate_t *pState, float f
{
int i;
if (pCurrent->flags & 0xA0000) {
if (pCurrent->flags & (T_HARDLINK | T_PARENTLINK)) {
Vector parentOrigin;
for (i = 0; i < 3; i++) {
@@ -643,7 +643,7 @@ qboolean VSS_LerpSource(cvssource_t *pCurrent, cvssourcestate_t *pState, float f
parentOrigin = e->origin;
VectorAdd(pState->origin, parentOrigin, pState->origin);
} else if (pCurrent->flags2 & 5) {
} else if (pCurrent->flags2 & (T2_ACCEL | T2_MOVE)) {
for (i = 0; i < 3; i++) {
pState->origin[i] =
(pCurrent->newOrigin[i] - pCurrent->lastOrigin[i]) * fLerpFrac + pCurrent->lastOrigin[i];
@@ -746,9 +746,8 @@ void ClientGameCommandManager::SpawnVSSSource(int count, int timealive)
pSource->startAlpha = (random() * 0.15 + 0.85) * fDensity;
pSource->newDensity = 0.0;
if (m_spawnthing->cgd.flags & 1) {
if (m_spawnthing->cgd.flags & T_RANDSCALE) {
pSource->newRadius = RandomizeRange(m_spawnthing->cgd.scalemin, m_spawnthing->cgd.scalemax);
;
if (pSource->newRadius > 32.0) {
pSource->newRadius = 32.0;
}
@@ -777,16 +776,16 @@ void ClientGameCommandManager::SpawnVSSSource(int count, int timealive)
pSource->roll = anglemod(fAngle);
if (random() < 0.5) {
pSource->flags |= 0x40000;
pSource->flags |= T_RANDOMROLL;
}
VectorCopy(m_spawnthing->axis[0], vNewForward);
if (m_spawnthing->cgd.flags & 4) {
if (m_spawnthing->cgd.flags & T_SPHERE) {
VectorCopy(m_spawnthing->cgd.origin, pSource->newOrigin);
do {
vNewForward = Vector(crandom(), crandom(), crandom());
} while (Vector::Dot(vNewForward, vNewForward) < 1.0);
} else if (m_spawnthing->cgd.flags & 0x10) {
} else if (m_spawnthing->cgd.flags & T_CIRCLE) {
if (m_spawnthing->sphereRadius != 0.0) {
Vector dst, end;
@@ -799,7 +798,7 @@ void ClientGameCommandManager::SpawnVSSSource(int count, int timealive)
fAngle += fAngleStep;
}
} else if (m_spawnthing->cgd.flags & 8) {
} else if (m_spawnthing->cgd.flags & T_INWARDSPHERE) {
Vector dir, end;
do {
dir = Vector(crandom(), crandom(), crandom());
@@ -808,7 +807,7 @@ void ClientGameCommandManager::SpawnVSSSource(int count, int timealive)
end = m_spawnthing->cgd.origin + dir * m_spawnthing->sphereRadius;
VectorCopy(end, pSource->newOrigin);
vNewForward = dir * -1.0;
} else if (m_spawnthing->cgd.flags2 & 0x20000) {
} else if (m_spawnthing->cgd.flags2 & T2_CONE) {
float fHeight, fRadius;
float fAngle;
float sina, cosa;
@@ -830,8 +829,6 @@ void ClientGameCommandManager::SpawnVSSSource(int count, int timealive)
VectorMA(m_spawnthing->cgd.origin, fRadius * cosa, m_spawnthing->axis[1], pSource->newOrigin);
VectorMA(m_spawnthing->cgd.origin, fRadius * sina, m_spawnthing->axis[2], pSource->newOrigin);
} else if (m_spawnthing->sphereRadius) {
VectorCopy(m_spawnthing->cgd.origin, pSource->newOrigin);
} else {
Vector dir, end;
do {
dir = Vector(crandom(), crandom(), crandom());
@@ -841,6 +838,8 @@ void ClientGameCommandManager::SpawnVSSSource(int count, int timealive)
end = m_spawnthing->cgd.origin + dir * m_spawnthing->sphereRadius;
VectorCopy(end, pSource->newOrigin);
vNewForward = dir;
} else {
VectorCopy(m_spawnthing->cgd.origin, pSource->newOrigin);
}
for (i = 0; i < 3; i++) {
@@ -874,15 +873,14 @@ void ClientGameCommandManager::SpawnVSSSource(int count, int timealive)
for (i = 0; i < 3; ++i) {
float fDist = m_spawnthing->axis_offset_base[i] + random() * m_spawnthing->axis_offset_amplitude[i];
if (pSource->flags2 & 0x80) {
if (pSource->flags2 & T2_PARALLEL) {
pSource->newOrigin += Vector(m_spawnthing->axis[i]) * fDist;
} else {
pSource->newOrigin += Vector(m_spawnthing->tag_axis[i]) * fDist;
}
}
pSource->velocity *= pSource->lifeTime / 1000.0;
pSource->newOrigin += pSource->velocity;
pSource->newOrigin += pSource->velocity * (pSource->lifeTime / 1000.0);
if (vss_lighting_fps->integer) {
cgi.R_GetLightingForSmoke(pSource->newLighting, pSource->newOrigin);
}
@@ -1225,13 +1223,13 @@ void ClientGameCommandManager::AddVSSSources()
pComp = pCurrent->prev;
newEnt.renderfx = 0;
if (pCurrent->flags < 0 && !cg_detail->integer) {
if ((pCurrent->flags & T_DETAIL) && !cg_detail->integer) {
FreeVSSSource(pCurrent);
continue;
}
if ((pCurrent->flags2 & 0x4000) != 0) {
newEnt.renderfx = 0x4000000;
if ((pCurrent->flags2 & T2_ALWAYSDRAW) != 0) {
newEnt.renderfx = RF_ALWAYSDRAW;
}
if (pCurrent->lastPhysicsTime) {
@@ -1240,8 +1238,8 @@ void ClientGameCommandManager::AddVSSSources()
mstime = physics_rate;
}
if (mstime >= physics_rate || (pCurrent->flags2 & 0x10) != 0) {
if (!VSS_SourcePhysics(pCurrent, (float)mstime * 0.001)) {
if (mstime >= physics_rate || (pCurrent->flags2 & T2_PHYSICS_EVERYFRAME) != 0) {
if (!VSS_SourcePhysics(pCurrent, (float)mstime / 1000.0)) {
FreeVSSSource(pCurrent);
continue;
}
@@ -1265,26 +1263,18 @@ void ClientGameCommandManager::AddVSSSources()
}
}
fLerpFrac = (cg.time - pCurrent->lastPhysicsTime) / physics_rate;
if (fLerpFrac > 1.0) {
fLerpFrac = 1.0;
} else if (fLerpFrac < 0.0) {
fLerpFrac = 0.0;
}
fLerpFrac = (float)(cg.time - pCurrent->lastPhysicsTime) / (float)physics_rate;
fLerpFrac = Q_clamp_float(fLerpFrac, 0, 1);
fLightingFrac = (cg.time - pCurrent->lastLightingTime) / lighting_rate;
if (fLightingFrac > 1.0) {
fLightingFrac = 1.0;
} else if (fLightingFrac < 0.0) {
fLightingFrac = 0.0;
}
fLightingFrac = (float)(cg.time - pCurrent->lastLightingTime) / (float)lighting_rate;
fLightingFrac = Q_clamp_float(fLightingFrac, 0, 1);
if (lastVSSFrameTime) {
pCurrent->lifeTime += frameTime;
}
if (!pCurrent->lastValid) {
if (!VSS_SourcePhysics(pCurrent, (float)physics_rate * 0.001)) {
if (!VSS_SourcePhysics(pCurrent, (float)physics_rate / 1000)) {
ClientGameCommandManager::FreeVSSSource(pCurrent);
continue;
}
@@ -1338,12 +1328,12 @@ void ClientGameCommandManager::AddVSSSources()
pCurrent->roll -= j;
}
if ((pCurrent->flags & 0x40000) != 0) {
if ((pCurrent->flags & T_RANDOMROLL) != 0) {
newEnt.hModel = hModel;
} else {
newEnt.hModel = hModel2;
}
} else if ((pCurrent->flags & 0x40000) != 0) {
} else if ((pCurrent->flags & T_RANDOMROLL) != 0) {
newEnt.hModel = hModel;
} else {
newEnt.hModel = hModel2;
+17 -11
View File
@@ -52,18 +52,24 @@ endif()
set(OLD_VALUE ${BUILD_SHARED_LIBS})
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
add_subdirectory("../libmad" "./libmad" EXCLUDE_FROM_ALL)
target_link_libraries(omohclient INTERFACE mad)
set(BUILD_SHARED_LIBS ${OLD_VALUE} CACHE BOOL "" FORCE)
if (USE_OPENAL)
# Try to use OpenAL
find_package(OpenAL)
if (OPENAL_FOUND)
target_compile_definitions(omohclient INTERFACE USE_OPENAL=1)
target_include_directories(omohclient INTERFACE ${OPENAL_INCLUDE_DIR}/AL)
target_link_libraries(omohclient INTERFACE ${OPENAL_LIBRARY})
endif()
if(USE_INTERNAL_MAD)
add_subdirectory("../libmad" "./libmad" EXCLUDE_FROM_ALL)
target_link_libraries(omohclient INTERFACE mad)
else()
include(FindPackageHandleStandardArgs)
find_path(LIBMAD_INCLUDE_DIRS mad.h)
find_library(LIBMAD_LIBRARIES mad)
find_package_handle_standard_args(
LibMad
DEFAULT_MSG
LIBMAD_LIBRARIES
LIBMAD_INCLUDE_DIRS
)
target_include_directories(omohclient INTERFACE ${LIBMAD_INCLUDE_DIRS})
target_link_libraries(omohclient INTERFACE ${LIBMAD_LIBRARIES})
endif()
set(BUILD_SHARED_LIBS ${OLD_VALUE} CACHE BOOL "" FORCE)
target_sources(omohclient INTERFACE ${SOURCES_CLIENT} ${SOURCES_UILIB})
+60 -15
View File
@@ -248,21 +248,23 @@ qboolean CL_GetSnapshot( int snapshotNumber, snapshot_t *snapshot ) {
if (snapshot->numEntities != count) {
Com_DPrintf("CL_GetSnapshot: Not all children could find their parents.\n");
for (i = count; i < snapshot->numEntities; i++)
for (i = snapshot->numEntities; i < count; i++)
{
s1 = &cl.parseEntities[(clSnap->parseEntitiesNum + i) & (MAX_PARSE_ENTITIES - 1)];
if (parents[s1->number] >= 0) {
Com_DPrintf(
"CL_GetSnapshot: entity %d with parent %d and model '%s' at %.2f %.2f %.2f, could not find parent.\n",
s1->number,
s1->parent,
CL_ConfigString(CS_MODELS + s1->modelindex),
s1->origin[0],
s1->origin[1],
s1->origin[2]
);
for (pnum = 0; pnum < count; pnum++) {
s1 = &cl.parseEntities[(clSnap->parseEntitiesNum + pnum) & (MAX_PARSE_ENTITIES - 1)];
if (parents[s1->number] >= 0) {
Com_DPrintf(
"CL_GetSnapshot: entity %d with parent %d and model '%s' at %.2f %.2f %.2f, could not find parent.\n",
s1->number,
s1->parent,
CL_ConfigString(CS_MODELS + s1->modelindex),
s1->origin[0],
s1->origin[1],
s1->origin[2]
);
parents[s1->number] = -2;
parents[s1->number] = -2;
}
}
}
}
@@ -625,6 +627,7 @@ void CL_InitCGameDLL( clientGameImport_t *cgi, clientGameExport_t **cge ) {
cgi->LV_ConvertString = Sys_LV_CL_ConvertString;
cgi->Cvar_Get = Cvar_Get;
cgi->Cvar_Find = Cvar_FindVar;
cgi->Cvar_Set = Cvar_Set;
cgi->Argc = Cmd_Argc;
@@ -769,7 +772,8 @@ void CL_InitCGameDLL( clientGameImport_t *cgi, clientGameExport_t **cge ) {
cgi->UI_ShowMenu = UI_ShowMenu;
cgi->UI_HideMenu = UI_HideMenu;
cgi->UI_FontStringWidth = uie.FontStringWidth;
cgi->UI_FontStringWidth = CL_FontStringWidth;
cgi->UI_GetObjectivesTop = UI_GetObjectivesTop;
cgi->Key_StringToKeynum = Key_StringToKeynum;
cgi->Key_KeynumToBindString = Key_KeynumToBindString;
cgi->Key_GetKeysForCommand = Key_GetKeysForCommand;
@@ -1111,6 +1115,42 @@ void CL_FirstSnapshot( void ) {
Cbuf_AddText( cl_activeAction->string );
Cvar_Set( "activeAction", "" );
}
#ifdef USE_MUMBLE
if ((cl_useMumble->integer) && !mumble_islinked()) {
int ret = mumble_link(CLIENT_WINDOW_TITLE);
Com_Printf("Mumble: Linking to Mumble application %s\n", ret==0?"ok":"failed");
}
#endif
#ifdef USE_VOIP
if (!clc.voipCodecInitialized) {
int i;
int error;
clc.opusEncoder = opus_encoder_create(48000, 1, OPUS_APPLICATION_VOIP, &error);
if ( error ) {
Com_DPrintf("VoIP: Error opus_encoder_create %d\n", error);
return;
}
for (i = 0; i < MAX_CLIENTS; i++) {
clc.opusDecoder[i] = opus_decoder_create(48000, 1, &error);
if ( error ) {
Com_DPrintf("VoIP: Error opus_decoder_create(%d) %d\n", i, error);
return;
}
clc.voipIgnore[i] = qfalse;
clc.voipGain[i] = 1.0f;
}
clc.voipCodecInitialized = qtrue;
clc.voipMuteAll = qfalse;
Cmd_AddCommand ("voip", CL_Voip_f);
Cvar_Set("cl_voipSendTarget", "spatial");
Com_Memset(clc.voipTargets, ~0, sizeof(clc.voipTargets));
}
#endif
}
static int lastSnapFlags;
@@ -1161,7 +1201,12 @@ void CL_SetCGameTime( void ) {
// allow pause in single player
if ( paused->integer && com_sv_running->integer ) {
// paused
CL_AdjustTimeDelta();
//CL_AdjustTimeDelta();
// Fixed in OPM
// Keep in sync with the server time.
// In OG, the game could lag for a short time
// when pausing and unpausing frequently
cl.serverTimeDelta = cl.snap.serverTime - cls.realtime;
return;
}
+159 -51
View File
@@ -35,6 +35,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "../uilib/ui_public.h"
#include "snd_local.h"
#include "cl_ui.h"
#define MAXSIZE 8
#define MINSIZE 4
@@ -55,6 +57,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
static void RoQ_init( void );
static void CL_FinishedCinematic();
/******************************************************************************
*
@@ -126,6 +129,10 @@ typedef struct {
int playonwalls;
byte* buf;
long drawX, drawY;
long realTime;
long currTime;
long soundTime;
} cin_cache;
static cinematics_t cin;
@@ -133,6 +140,10 @@ static cin_cache cinTable[MAX_VIDEO_HANDLES];
static int currentHandle = -1;
static int CL_handle = -1;
static connstate_t oldClientState;
static int audioStartTime = 0;
extern "C" int s_soundtime; // sample PAIRS
@@ -160,7 +171,7 @@ static int CIN_HandleForVideo(void) {
}
extern "C" int CL_ScaledMilliseconds(void);
extern "C" int Com_Milliseconds(void);
//-----------------------------------------------------------------------------
// RllSetupTable
@@ -1091,8 +1102,6 @@ static void RoQReset( void ) {
static void RoQInterrupt(void)
{
// Removed in OPM
#if 0
byte *framedata;
short sbuf[32768];
int ssize;
@@ -1144,24 +1153,20 @@ redump:
case ZA_SOUND_MONO:
if (!cinTable[currentHandle].silent) {
ssize = RllDecodeMonoToStereo( framedata, sbuf, cinTable[currentHandle].RoQFrameSize, 0, (unsigned short)cinTable[currentHandle].roq_flags);
S_RawSamples(0, ssize, 22050, 2, 1, (byte *)sbuf, 1.0f, -1);
// S_RawSamples(0, ssize, 22050, 2, 1, (byte *)sbuf, 1.0f, -1);
}
break;
case ZA_SOUND_STEREO:
if (!cinTable[currentHandle].silent) {
if (cinTable[currentHandle].numQuads == -1) {
S_Update();
s_rawend[0] = s_soundtime;
}
ssize = RllDecodeStereoToStereo( framedata, sbuf, cinTable[currentHandle].RoQFrameSize, 0, (unsigned short)cinTable[currentHandle].roq_flags);
S_RawSamples(0, ssize, 22050, 2, 2, (byte *)sbuf, 1.0f, -1);
// S_RawSamples(0, ssize, 22050, 2, 2, (byte *)sbuf, 1.0f, -1);
}
break;
case ROQ_QUAD_INFO:
if (cinTable[currentHandle].numQuads == -1) {
readQuadInfo( framedata );
setupQuad( 0, 0 );
cinTable[currentHandle].startTime = cinTable[currentHandle].lastTime = CL_ScaledMilliseconds();
cinTable[currentHandle].startTime = cinTable[currentHandle].lastTime = Com_Milliseconds();
}
if (cinTable[currentHandle].numQuads != 1) cinTable[currentHandle].numQuads = 0;
break;
@@ -1216,7 +1221,6 @@ redump:
// assert(cinTable[currentHandle].RoQFrameSize <= 65536);
// r = FS_Read( cin.file, cinTable[currentHandle].RoQFrameSize+8, cinTable[currentHandle].iFile );
cinTable[currentHandle].RoQPlayed += cinTable[currentHandle].RoQFrameSize+8;
#endif
}
/******************************************************************************
@@ -1229,7 +1233,10 @@ redump:
static void RoQ_init( void )
{
cinTable[currentHandle].startTime = cinTable[currentHandle].lastTime = CL_ScaledMilliseconds();
cinTable[currentHandle].startTime = cinTable[currentHandle].lastTime = Com_Milliseconds();
cinTable[currentHandle].realTime = Com_Milliseconds();
cinTable[currentHandle].currTime = 0;
cinTable[currentHandle].soundTime = 0;
cinTable[currentHandle].RoQPlayed = 24;
@@ -1276,8 +1283,10 @@ static void RoQShutdown( void ) {
cinTable[currentHandle].iFile = 0;
}
S_StopMovieAudio();
if (cinTable[currentHandle].alterGameState) {
clc.state = CA_DISCONNECTED;
clc.state = oldClientState;
// we can't just do a vstr nextmap, because
// if we are aborting the intro cinematic with
// a devmap command, nextmap would be valid by
@@ -1289,8 +1298,29 @@ static void RoQShutdown( void ) {
}
CL_handle = -1;
}
cinTable[currentHandle].fileName[0] = 0;
currentHandle = -1;
CL_FinishedCinematic();
}
static void CL_FinishedCinematic()
{
const char* s;
if (!CL_FinishedIntro())
{
CL_FinishedStartStage();
return;
}
s = Cvar_VariableString("nextmap");
if (*s)
{
Cbuf_ExecuteText(EXEC_APPEND, va("%s\n", s));
Cvar_Set("nextmap", "");
}
}
/*
@@ -1331,8 +1361,11 @@ Fetch and decompress the pending frame
e_status CIN_RunCinematic (int handle)
{
int start = 0;
int thisTime = 0;
int deltaTime;
int frameTime;
int soundTime;
int newTime;
long tfps;
if (handle < 0 || handle>= MAX_VIDEO_HANDLES || cinTable[handle].status == FMV_EOF) return FMV_EOF;
@@ -1360,24 +1393,46 @@ e_status CIN_RunCinematic (int handle)
return cinTable[currentHandle].status;
}
thisTime = CL_ScaledMilliseconds();
if (cinTable[currentHandle].shader && (abs(thisTime - cinTable[currentHandle].lastTime))>100) {
cinTable[currentHandle].startTime += thisTime - cinTable[currentHandle].lastTime;
frameTime = Com_Milliseconds();
deltaTime = frameTime - cinTable[currentHandle].realTime;
if (deltaTime > 100) {
deltaTime = 100;
}
cinTable[currentHandle].tfps = (((CL_ScaledMilliseconds() - cinTable[currentHandle].startTime)*3)/100);
start = cinTable[currentHandle].startTime;
while( (cinTable[currentHandle].tfps != cinTable[currentHandle].numQuads)
newTime = cinTable[currentHandle].currTime + deltaTime;
if (cl_movieaudio->integer) {
soundTime = S_CurrentMoviePosition();
if (soundTime > cinTable[currentHandle].currTime || soundTime > cinTable[currentHandle].soundTime) {
cinTable[currentHandle].currTime = newTime + (deltaTime * (soundTime - newTime)) / 100;
}
else {
cinTable[currentHandle].currTime = newTime;
}
cinTable[currentHandle].soundTime = soundTime;
} else {
//
// Fixed in OPM
//
cinTable[currentHandle].currTime = newTime;
}
cinTable[currentHandle].realTime = frameTime;
tfps = (cinTable[currentHandle].currTime * 3) / 100;
while( (tfps != cinTable[currentHandle].numQuads)
&& (cinTable[currentHandle].status == FMV_PLAY) )
{
RoQInterrupt();
if (start != cinTable[currentHandle].startTime) {
cinTable[currentHandle].tfps = (((CL_ScaledMilliseconds() - cinTable[currentHandle].startTime)*3)/100);
start = cinTable[currentHandle].startTime;
cinTable[currentHandle].realTime = Com_Milliseconds();
if (cinTable[currentHandle].realTime > frameTime + 66) {
break;
}
}
cinTable[currentHandle].lastTime = thisTime;
cinTable[currentHandle].lastTime = frameTime;
if (cinTable[currentHandle].status == FMV_LOOPED) {
cinTable[currentHandle].status = FMV_PLAY;
@@ -1400,9 +1455,6 @@ CIN_PlayCinematic
==================
*/
int CIN_PlayCinematic( const char *arg, int x, int y, int w, int h, int systemBits ) {
return 0;
// Removed in OPM
#if 0
unsigned short RoQID;
char name[MAX_OSPATH];
int i;
@@ -1428,7 +1480,7 @@ int CIN_PlayCinematic( const char *arg, int x, int y, int w, int h, int systemBi
cin.currentHandle = currentHandle;
strcpy(cinTable[currentHandle].fileName, name);
Q_strncpyz(cinTable[currentHandle].fileName, name, sizeof(cinTable[currentHandle].fileName));
cinTable[currentHandle].ROQSize = 0;
cinTable[currentHandle].ROQSize = FS_FOpenFileRead (cinTable[currentHandle].fileName, &cinTable[currentHandle].iFile, qtrue, qtrue);
@@ -1474,17 +1526,12 @@ int CIN_PlayCinematic( const char *arg, int x, int y, int w, int h, int systemBi
clc.state = CA_CINEMATIC;
}
if (!cinTable[currentHandle].silent) {
s_rawend[0] = s_soundtime;
}
return currentHandle;
}
Com_DPrintf("trFMV::play(), invalid RoQ ID\n");
RoQShutdown();
return -1;
#endif
}
void CIN_SetExtents (int handle, int x, int y, int w, int h) {
@@ -1600,33 +1647,96 @@ void CIN_DrawCinematic (int handle) {
cinTable[handle].dirty = qfalse;
}
static unsigned short CL_PlayRoQ(const char* name, const char* arg, const char* s) {
unsigned short RoQID;
Com_Memset(&cin, 0, sizeof(cinematics_t) );
currentHandle = CIN_HandleForVideo();
cin.currentHandle = currentHandle;
Q_strncpyz(cinTable[currentHandle].fileName, name, sizeof(cinTable[currentHandle].fileName));
cinTable[currentHandle].ROQSize = 0;
cinTable[currentHandle].ROQSize = FS_FOpenFileRead (cinTable[currentHandle].fileName, &cinTable[currentHandle].iFile, qtrue, qtrue);
if (cinTable[currentHandle].ROQSize<=0) {
Com_DPrintf("Can not find RoQ cinematic '%s'\n", name);
CL_FinishedCinematic();
return -1;
}
if ((s && s[0] == '1') || Q_stricmp(arg,"demoend.roq")==0 || Q_stricmp(arg,"end.roq")==0) {
cinTable[currentHandle].holdAtEnd = qtrue;
}
CIN_SetExtents(currentHandle, 0, 0, 640, 480);
cinTable[currentHandle].alterGameState = qtrue;
initRoQ();
FS_Read (cin.file, 16, cinTable[currentHandle].iFile);
RoQID = (unsigned short)(cin.file[0]) + (unsigned short)(cin.file[1])*256;
if (RoQID == 0x1084)
{
RoQ_init();
// FS_Read (cin.file, cinTable[currentHandle].RoQFrameSize+8, cinTable[currentHandle].iFile);
cinTable[currentHandle].status = FMV_PLAY;
Com_DPrintf("trFMV::play(), playing %s\n", arg);
if (cl_movieaudio->integer) {
audioStartTime = Com_Milliseconds();
S_SetupMovieAudio(name);
}
oldClientState = clc.state;
clc.state = CA_CINEMATIC;
if (cls.glconfig.maxTextureSize <= 256 || s && *s == '2') {
//cinTable[currentHandle].interlaced = qtrue;
}
CL_handle = currentHandle;
do {
SCR_RunCinematic();
} while (!cinTable[currentHandle].buf && cinTable[currentHandle].status == FMV_PLAY);
UI_CloseConsole();
return currentHandle;
}
Com_DPrintf("trFMV::play(), invalid RoQ ID\n");
RoQShutdown();
return -1;
}
void CL_PlayCinematic_f(void) {
char *arg, *s;
int bits = CIN_system;
char name[256];
Com_DPrintf("CL_PlayCinematic_f\n");
if (clc.state == CA_CINEMATIC) {
SCR_StopCinematic();
}
arg = Cmd_Argv( 1 );
Com_DPrintf("CL_PlayCinematic( %s )\n", arg);
s = Cmd_Argv(2);
if ((s && s[0] == '1') || Q_stricmp(arg,"demoend.roq")==0 || Q_stricmp(arg,"end.roq")==0) {
bits |= CIN_hold;
}
if (s && s[0] == '2') {
bits |= CIN_loop;
CL_StartHunkUsers(qfalse);
S_StopAllSounds2(qtrue);
Com_sprintf(name, sizeof(name), "video/%s", arg);
if (Q_stricmp(&name[strlen(name) - 4], ".roq")) {
Com_Printf("Bad or missing cinematic extension.\n");
return;
}
S_StopAllSounds2( qtrue );
CL_handle = CIN_PlayCinematic( arg, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, bits );
if (CL_handle >= 0) {
do {
SCR_RunCinematic();
} while (cinTable[currentHandle].buf == NULL && cinTable[currentHandle].status == FMV_PLAY); // wait for first frame (load codebook and sound)
}
CL_PlayRoQ(name, arg, s);
}
@@ -1646,7 +1756,5 @@ void SCR_RunCinematic (void)
void SCR_StopCinematic(void) {
if (CL_handle >= 0 && CL_handle < MAX_VIDEO_HANDLES) {
CIN_StopCinematic(CL_handle);
S_StopAllSounds2( qtrue );
CL_handle = -1;
}
}
+178 -17
View File
@@ -56,6 +56,10 @@ qboolean in_guimouse;
kbutton_t in_up, in_down;
#ifdef USE_VOIP
kbutton_t in_voiprecord;
#endif
kbutton_t in_buttons[16];
qboolean in_mlooking;
@@ -258,6 +262,20 @@ void IN_SpeedUp(void) {IN_KeyUp(&in_speed);}
void IN_StrafeDown(void) {IN_KeyDown(&in_strafe);}
void IN_StrafeUp(void) {IN_KeyUp(&in_strafe);}
#ifdef USE_VOIP
void IN_VoipRecordDown(void)
{
IN_KeyDown(&in_voiprecord);
Cvar_Set("cl_voipSend", "1");
}
void IN_VoipRecordUp(void)
{
IN_KeyUp(&in_voiprecord);
Cvar_Set("cl_voipSend", "0");
}
#endif
void IN_Button0Down(void) {IN_KeyDown(&in_buttons[0]);}
void IN_Button0Up(void) {IN_KeyUp(&in_buttons[0]);}
void IN_Button1Down(void) {IN_KeyDown(&in_buttons[1]);}
@@ -461,6 +479,16 @@ CL_JoystickMove
void CL_JoystickMove( usercmd_t *cmd ) {
float anglespeed;
float yaw = j_yaw->value * cl.joystickAxis[j_yaw_axis->integer];
float right = j_side->value * cl.joystickAxis[j_side_axis->integer];
float forward = j_forward->value * cl.joystickAxis[j_forward_axis->integer];
float pitch = j_pitch->value * cl.joystickAxis[j_pitch_axis->integer];
float up = j_up->value * cl.joystickAxis[j_up_axis->integer];
if ( in_speed.active ^ cl_run->integer ) {
cmd->buttons |= BUTTON_RUN;
}
if ( in_speed.active ) {
anglespeed = 0.001 * cls.frametime * cl_anglespeedkey->value;
} else {
@@ -468,18 +496,22 @@ void CL_JoystickMove( usercmd_t *cmd ) {
}
if ( !in_strafe.active ) {
cl.viewangles[YAW] += anglespeed * cl_yawspeed->value * cl.joystickAxis[AXIS_SIDE];
cl.viewangles[YAW] += anglespeed * yaw;
cmd->rightmove = ClampChar( cmd->rightmove + (int)right );
} else {
cmd->rightmove = ClampChar( cmd->rightmove + cl.joystickAxis[AXIS_SIDE] );
cl.viewangles[YAW] += anglespeed * right;
cmd->rightmove = ClampChar( cmd->rightmove + (int)yaw );
}
if ( in_mlooking ) {
cl.viewangles[PITCH] += anglespeed * cl_pitchspeed->value * cl.joystickAxis[AXIS_FORWARD];
cl.viewangles[PITCH] += anglespeed * forward;
cmd->forwardmove = ClampChar( cmd->forwardmove + (int)pitch );
} else {
cmd->forwardmove = ClampChar( cmd->forwardmove + cl.joystickAxis[AXIS_FORWARD] );
cl.viewangles[PITCH] += anglespeed * pitch;
cmd->forwardmove = ClampChar( cmd->forwardmove + (int)forward );
}
cmd->upmove = ClampChar( cmd->upmove + cl.joystickAxis[AXIS_UP] );
cmd->upmove = ClampChar( cmd->upmove + (int)up );
}
/*
@@ -565,6 +597,8 @@ void CL_MouseMove( usercmd_t *cmd ) {
mx *= cgameSensitivity;
my *= cgameSensitivity;
cmd->buttons |= BUTTON_ANY;
// add mouse X/Y movement to cmd
if(in_strafe.active)
cmd->rightmove = ClampChar(cmd->rightmove + m_side->value * mx);
@@ -617,8 +651,8 @@ void CL_CmdButtons( usercmd_t *cmd ) {
if (UI_MenuActive() || UI_ConsoleIsOpen()) {
cmd->buttons |= BUTTON_TALK;
}
if (in_speed.active == !cl_run->integer) {
if ( in_speed.active ^ cl_run->integer ) {
cmd->buttons |= BUTTON_RUN;
}
@@ -726,6 +760,12 @@ void CL_CreateNewCommands( void ) {
frame_msec = com_frameTime - old_com_frameTime;
// if running over 1000fps, act as if each frame is 1ms
// prevents divisions by zero
if ( frame_msec < 1 ) {
frame_msec = 1;
}
// if running less than 5fps, truncate the extra time to prevent
// unexpected moves after a hitch
if ( frame_msec > 200 ) {
@@ -917,6 +957,58 @@ void CL_WritePacket( void ) {
count = MAX_PACKET_USERCMDS;
Com_Printf("MAX_PACKET_USERCMDS\n");
}
#ifdef USE_VOIP
if (clc.voipOutgoingDataSize > 0)
{
if((clc.voipFlags & VOIP_SPATIAL) || Com_IsVoipTarget(clc.voipTargets, sizeof(clc.voipTargets), -1))
{
MSG_WriteByte (&buf, clc_voipOpus);
MSG_WriteByte (&buf, clc.voipOutgoingGeneration);
MSG_WriteLong (&buf, clc.voipOutgoingSequence);
MSG_WriteByte (&buf, clc.voipOutgoingDataFrames);
MSG_WriteData (&buf, clc.voipTargets, sizeof(clc.voipTargets));
MSG_WriteByte(&buf, clc.voipFlags);
MSG_WriteShort (&buf, clc.voipOutgoingDataSize);
MSG_WriteData (&buf, clc.voipOutgoingData, clc.voipOutgoingDataSize);
// If we're recording a demo, we have to fake a server packet with
// this VoIP data so it gets to disk; the server doesn't send it
// back to us, and we might as well eliminate concerns about dropped
// and misordered packets here.
if(clc.demorecording && !clc.demowaiting)
{
const int voipSize = clc.voipOutgoingDataSize;
msg_t fakemsg;
byte fakedata[MAX_MSGLEN];
MSG_Init (&fakemsg, fakedata, sizeof (fakedata));
MSG_Bitstream (&fakemsg);
MSG_WriteLong (&fakemsg, clc.reliableAcknowledge);
MSG_WriteByte (&fakemsg, svc_voipOpus);
MSG_WriteShort (&fakemsg, clc.clientNum);
MSG_WriteByte (&fakemsg, clc.voipOutgoingGeneration);
MSG_WriteLong (&fakemsg, clc.voipOutgoingSequence);
MSG_WriteByte (&fakemsg, clc.voipOutgoingDataFrames);
MSG_WriteShort (&fakemsg, clc.voipOutgoingDataSize );
MSG_WriteBits (&fakemsg, clc.voipFlags, VOIP_FLAGCNT);
MSG_WriteData (&fakemsg, clc.voipOutgoingData, voipSize);
MSG_WriteByte (&fakemsg, svc_EOF);
CL_WriteDemoMessage (&fakemsg, 0);
}
clc.voipOutgoingSequence += clc.voipOutgoingDataFrames;
clc.voipOutgoingDataSize = 0;
clc.voipOutgoingDataFrames = 0;
}
else
{
// We have data, but no targets. Silently discard all data
clc.voipOutgoingDataSize = 0;
clc.voipOutgoingDataFrames = 0;
}
}
#endif
if ( count >= 1 ) {
if ( cl_showSend->integer ) {
Com_Printf( "(%i)", count );
@@ -973,16 +1065,6 @@ void CL_WritePacket( void ) {
}
CL_Netchan_Transmit (&clc.netchan, &buf);
// clients never really should have messages large enough
// to fragment, but in case they do, fire them all off
// at once
// TTimo: this causes a packet burst, which is bad karma for winsock
// added a WARNING message, we'll see if there are legit situations where this happens
while ( clc.netchan.unsentFragments ) {
Com_DPrintf( "WARNING: #462 unsent fragments (not supposed to happen!)\n" );
CL_Netchan_TransmitNextFragment( &clc.netchan );
}
}
/*
@@ -1094,6 +1176,85 @@ void CL_InitInput( void ) {
Cmd_AddCommand("+mlook", IN_MLookDown);
Cmd_AddCommand("-mlook", IN_MLookUp);
#ifdef USE_VOIP
Cmd_AddCommand ("+voiprecord", IN_VoipRecordDown);
Cmd_AddCommand ("-voiprecord", IN_VoipRecordUp);
#endif
cl_nodelta = Cvar_Get ("cl_nodelta", "0", 0);
cl_debugMove = Cvar_Get ("cl_debugMove", "0", 0);
}
/*
============
CL_ShutdownInput
============
*/
void CL_ShutdownInput(void)
{
Cmd_RemoveCommand("centerview");
Cmd_RemoveCommand("+moveup");
Cmd_RemoveCommand("-moveup");
Cmd_RemoveCommand("+movedown");
Cmd_RemoveCommand("-movedown");
Cmd_RemoveCommand("+left");
Cmd_RemoveCommand("-left");
Cmd_RemoveCommand("+right");
Cmd_RemoveCommand("-right");
Cmd_RemoveCommand("+forward");
Cmd_RemoveCommand("-forward");
Cmd_RemoveCommand("+back");
Cmd_RemoveCommand("-back");
Cmd_RemoveCommand("+lookup");
Cmd_RemoveCommand("-lookup");
Cmd_RemoveCommand("+lookdown");
Cmd_RemoveCommand("-lookdown");
Cmd_RemoveCommand("+strafe");
Cmd_RemoveCommand("-strafe");
Cmd_RemoveCommand("+moveleft");
Cmd_RemoveCommand("-moveleft");
Cmd_RemoveCommand("+moveright");
Cmd_RemoveCommand("-moveright");
Cmd_RemoveCommand("+speed");
Cmd_RemoveCommand("-speed");
Cmd_RemoveCommand("+attack");
Cmd_RemoveCommand("-attack");
Cmd_RemoveCommand("+button0");
Cmd_RemoveCommand("-button0");
Cmd_RemoveCommand("+button1");
Cmd_RemoveCommand("-button1");
Cmd_RemoveCommand("+button2");
Cmd_RemoveCommand("-button2");
Cmd_RemoveCommand("+button3");
Cmd_RemoveCommand("-button3");
Cmd_RemoveCommand("+button4");
Cmd_RemoveCommand("-button4");
Cmd_RemoveCommand("+button5");
Cmd_RemoveCommand("-button5");
Cmd_RemoveCommand("+button6");
Cmd_RemoveCommand("-button6");
Cmd_RemoveCommand("+button7");
Cmd_RemoveCommand("-button7");
Cmd_RemoveCommand("+button8");
Cmd_RemoveCommand("-button8");
Cmd_RemoveCommand("+button9");
Cmd_RemoveCommand("-button9");
Cmd_RemoveCommand("+button10");
Cmd_RemoveCommand("-button10");
Cmd_RemoveCommand("+button11");
Cmd_RemoveCommand("-button11");
Cmd_RemoveCommand("+button12");
Cmd_RemoveCommand("-button12");
Cmd_RemoveCommand("+button13");
Cmd_RemoveCommand("-button13");
Cmd_RemoveCommand("+button14");
Cmd_RemoveCommand("-button14");
Cmd_RemoveCommand("+mlook");
Cmd_RemoveCommand("-mlook");
#ifdef USE_VOIP
Cmd_RemoveCommand("+voiprecord");
Cmd_RemoveCommand("-voiprecord");
#endif
}
+2 -2
View File
@@ -148,7 +148,7 @@ void CL_Draw3DModel(
hModel[iCurrNum] = model;
iIndex[iCurrNum] = -1;
strcpy(szAnimName[iCurrNum], anim);
Q_strncpyz(szAnimName[iCurrNum], anim, sizeof(szAnimName[iCurrNum]));
} else {
iCurrNum = i;
@@ -164,7 +164,7 @@ void CL_Draw3DModel(
}
} else {
iIndex[iCurrNum] = -1;
strcpy(szAnimName[iCurrNum], anim);
Q_strncpyz(szAnimName[iCurrNum], anim, sizeof(szAnimName[iCurrNum]));
}
}
+10 -4
View File
@@ -984,6 +984,8 @@ CL_InitKeyCommands
*/
void CL_InitKeyCommands(void)
{
int i;
// register our functions
Cmd_AddCommand("bind", Key_Bind_f);
Cmd_AddCommand("unbind", Key_Unbind_f);
@@ -997,6 +999,10 @@ void CL_InitKeyCommands(void)
Cmd_AddCommand("ctrlbindlist", Key_AltBindlist_f);
memset(menubound, 0, sizeof(menubound));
for (i = K_F1; i <= K_F15; i++) {
menubound[i] = qtrue;
}
}
/*
@@ -1089,7 +1095,7 @@ void CL_KeyEvent(int key, qboolean down, unsigned time)
if (clc.state > CA_DISCONNECTED && cge && !Key_GetCatcher() && cge->CG_CheckCaptureKey(key, down, time)
&& key != K_ESCAPE) {
if (key == K_CONSOLE || (keys[K_SHIFT].down && key == K_ESCAPE)) {
if (key != K_CONSOLE && (!keys[K_SHIFT].down || key != K_ESCAPE)) {
return;
}
}
@@ -1134,9 +1140,9 @@ void CL_KeyEvent(int key, qboolean down, unsigned time)
if (key >= K_MOUSE1 && key <= K_MOUSE5) {
if (down) {
cl.mouseButtons |= (1 << (key + (256 - K_MOUSE1)));
cl.mouseButtons |= (1 << (key - K_MOUSE1));
} else {
cl.mouseButtons &= ~(1 << (key + (256 - K_MOUSE1)));
cl.mouseButtons &= ~(1 << (key - K_MOUSE1));
}
if (in_guimouse) {
@@ -1346,5 +1352,5 @@ Key_SetCatcher
*/
void Key_SetCatcher(int catcher)
{
keyCatchers = catcher;
cls.keyCatchers = catcher;
}
+180 -204
View File
@@ -56,6 +56,8 @@ cvar_t *cl_showTimeDelta;
cvar_t *cl_freezeDemo;
cvar_t *cl_shownet;
cvar_t *cl_netprofile;
cvar_t *cl_netprofileoverlay;
cvar_t *cl_showSend;
cvar_t *cl_timedemo;
cvar_t *cl_timedemoLog;
@@ -118,6 +120,7 @@ cvar_t *cl_r_fullscreen;
cvar_t *cl_consoleKeys;
cvar_t *name;
cvar_t *cl_rate;
clientActive_t cl;
clientConnection_t clc;
@@ -167,8 +170,6 @@ void CL_ShowIP_f(void);
void CL_ServerStatus_f(void);
void CL_ServerStatusResponse( netadr_t from, msg_t *msg );
void CL_GamespyServers_f( void );
static qboolean cl_bCLSystemStarted = qfalse;
/*
@@ -706,7 +707,7 @@ void CL_PlayDemo_f( void ) {
clc.state = CA_CONNECTED;
clc.demoplaying = qtrue;
Q_strncpyz( cls.servername, Cmd_Argv(1), sizeof( cls.servername ) );
Q_strncpyz( clc.servername, Cmd_Argv(1), sizeof( clc.servername ) );
// read demo messages until connected
while ( clc.state >= CA_CONNECTED && clc.state < CA_PRIMED ) {
@@ -832,7 +833,7 @@ void CL_MapLoading( qboolean flush, const char *pszMapName ) {
if (pszMapName) {
// if we are already connected to the local host, stay connected
if (clc.state >= CA_CONNECTED && !Q_stricmp(cls.servername, "localhost")) {
if (clc.state >= CA_CONNECTED && !Q_stricmp(clc.servername, "localhost")) {
clc.state = CA_CONNECTED; // so the connect screen is drawn
Com_Memset(cls.updateInfoString, 0, sizeof(cls.updateInfoString));
Com_Memset(clc.serverMessage, 0, sizeof(clc.serverMessage));
@@ -843,11 +844,11 @@ void CL_MapLoading( qboolean flush, const char *pszMapName ) {
// clear nextmap so the cinematic shutdown doesn't execute it
Cvar_Set("nextmap", "");
CL_Disconnect();
Q_strncpyz(cls.servername, "localhost", sizeof(cls.servername));
Q_strncpyz(clc.servername, "localhost", sizeof(clc.servername));
clc.state = CA_CHALLENGING; // so the connect screen is drawn
clc.connectStartTime = cls.realtime;
clc.connectTime = -RETRANSMIT_TIMEOUT;
NET_StringToAdr(cls.servername, &clc.serverAddress, NA_UNSPEC);
NET_StringToAdr(clc.servername, &clc.serverAddress, NA_UNSPEC);
// we don't need a challenge on the localhost
CL_CheckForResend();
@@ -912,6 +913,8 @@ This is also called on Com_Error and Com_Quit, so it shouldn't cause any errors
=====================
*/
void CL_Disconnect() {
int mouseX, mouseY;
if ( !com_cl_running || !com_cl_running->integer ) {
return;
}
@@ -947,8 +950,16 @@ void CL_Disconnect() {
CL_WritePacket();
}
// Fixed in OPM
// Don't reset the mouse every time the client disconnects
mouseX = cl.mousex;
mouseY = cl.mousey;
CL_ClearState ();
cl.mousex = mouseX;
cl.mousey = mouseY;
// wipe the client connection
Com_Memset( &clc, 0, sizeof( clientConnection_t ) );
@@ -1049,7 +1060,7 @@ void CL_RequestMotd( void ) {
Info_SetValueForKey( info, "renderer", cls.glconfig.renderer_string );
Info_SetValueForKey( info, "version", com_version->string );
NET_OutOfBandPrint( NS_CLIENT, cls.updateServer, "getmotd \"%s\"\n", info );
CL_NET_OutOfBandPrint( cls.updateServer, "getmotd \"%s\"\n", info );
}
/*
@@ -1132,7 +1143,7 @@ void CL_RequestAuthorization( void ) {
fs = Cvar_Get ("cl_anonymous", "0", CVAR_INIT|CVAR_SYSTEMINFO );
NET_OutOfBandPrint(NS_CLIENT, cls.authorizeServer, "getKeyAuthorize %i %s", fs->integer, nums );
CL_NET_OutOfBandPrint(cls.authorizeServer, "getKeyAuthorize %i %s", fs->integer, nums );
}
/*
@@ -1174,12 +1185,12 @@ void CL_Setenv_f( void ) {
char buffer[1024];
int i;
strcpy( buffer, Cmd_Argv(1) );
strcat( buffer, "=" );
Q_strncpyz( buffer, Cmd_Argv(1), sizeof( buffer ) );
Q_strcat( buffer, sizeof( buffer ), "=" );
for ( i = 2; i < argc; i++ ) {
strcat( buffer, Cmd_Argv( i ) );
strcat( buffer, " " );
Q_strcat( buffer, sizeof( buffer ), Cmd_Argv( i ) );
Q_strcat( buffer, sizeof( buffer ), " " );
}
putenv( buffer );
@@ -1201,28 +1212,32 @@ CL_Disconnect_f
==================
*/
void CL_Disconnect_f( void ) {
if ( clc.state != CA_DISCONNECTED ) {
qboolean bConsoleState = UI_ConsoleIsOpen();
qboolean bConsoleState;
Com_Printf("\nDisconnected from server\n");
SV_Shutdown("Disconnected from server\n");
if ( clc.state == CA_DISCONNECTED ) {
return;
}
if (com_cl_running && com_cl_running->integer)
{
CL_AbnormalDisconnect();
CL_FlushMemory();
CL_StartHunkUsers(qfalse);
S_StopAllSounds2(1);
S_TriggeredMusic_PlayIntroMusic();
}
bConsoleState = UI_ConsoleIsOpen();
UI_FocusMenuIfExists();
Com_Printf("\nDisconnected from server\n");
SV_Shutdown("Disconnected from server\n");
if (bConsoleState) {
UI_OpenConsole();
} else {
UI_CloseConsole();
}
if (com_cl_running && com_cl_running->integer)
{
CL_AbnormalDisconnect();
CL_FlushMemory();
CL_StartHunkUsers(qfalse);
S_StopAllSounds2(1);
S_TriggeredMusic_PlayIntroMusic();
}
UI_FocusMenuIfExists();
if (bConsoleState) {
UI_OpenConsole();
} else {
UI_CloseConsole();
}
}
@@ -1234,12 +1249,12 @@ CL_Reconnect_f
================
*/
void CL_Reconnect_f( void ) {
if ( !strlen( cls.servername ) || !strcmp( cls.servername, "localhost" ) ) {
if ( !strlen( clc.servername ) || !strcmp( clc.servername, "localhost" ) ) {
Com_Printf( "Can't reconnect to localhost.\n" );
return;
}
Cvar_Set("ui_singlePlayerActive", "0");
Cbuf_AddText( va("connect %s\n", cls.servername ) );
Cbuf_AddText( va("connect %s\n", clc.servername ) );
}
/*
@@ -1275,9 +1290,9 @@ void CL_Connect( const char *server, netadrtype_t family ) {
CL_FlushMemory( );
*/
Q_strncpyz( cls.servername, server, sizeof( cls.servername ) );
Q_strncpyz( clc.servername, server, sizeof( clc.servername ) );
if( !NET_StringToAdr( cls.servername, &clc.serverAddress, family ) ) {
if( !NET_StringToAdr( clc.servername, &clc.serverAddress, family ) ) {
Com_Printf( "Bad server address\n" );
clc.state = CA_DISCONNECTED;
UI_PushMenu("badserveraddy");
@@ -1288,7 +1303,7 @@ void CL_Connect( const char *server, netadrtype_t family ) {
}
serverString = NET_AdrToStringwPort(clc.serverAddress);
Com_Printf( "%s resolved to %s\n", cls.servername, serverString );
Com_Printf( "%s resolved to %s\n", clc.servername, serverString );
if (cl_guidServerUniq->integer)
CL_UpdateGUID(serverString, strlen(serverString));
@@ -1464,7 +1479,11 @@ void CL_Rcon_f( void ) {
}
}
NET_SendPacket (NS_CLIENT, strlen(message)+1, message, to);
NET_SendPacket (NS_CLIENT, strlen(message) + 1, message, to);
if (cl_netprofile->integer) {
NetProfileAddPacket(&cls.netprofile.inPackets, strlen(message) + 1, NETPROF_PACKET_MESSAGE);
}
}
/*
@@ -1483,7 +1502,6 @@ void CL_SendPureChecksums( void ) {
// "cp"
// "Yf"
Com_sprintf(cMsg, sizeof(cMsg), "Yf ");
Q_strcat(cMsg, sizeof(cMsg), va("%d ", cl.serverId) );
Q_strcat(cMsg, sizeof(cMsg), pChecksums);
for (i = 0; i < 2; i++) {
cMsg[i] += '\n';
@@ -1707,7 +1725,7 @@ CL_Clientinfo_f
void CL_Clientinfo_f( void ) {
Com_Printf( "--------- Client Information ---------\n" );
Com_Printf( "state: %i\n", clc.state );
Com_Printf( "Server: %s\n", cls.servername );
Com_Printf( "Server: %s\n", clc.servername );
Com_Printf ("User info settings:\n");
Info_Print( Cvar_InfoString( CVAR_USERINFO ) );
Com_Printf( "--------------------------------------\n" );
@@ -1908,7 +1926,7 @@ void CL_InitDownloads(void) {
if (FS_ComparePaks( missingfiles, sizeof( missingfiles ), qfalse ) )
{
// NOTE TTimo I would rather have that printed as a modal message box
// but at this point while joining the game we don't know wether we will successfully join or not
// but at this point while joining the game we don't know whether we will successfully join or not
Com_Printf( "\nWARNING: You are missing some files referenced by the server:\n%s"
"You might not be able to join the game\n"
"Go to the setting menu to turn on autodownload, or get the file elsewhere\n\n", missingfiles );
@@ -1967,12 +1985,12 @@ void CL_CheckForResend( void ) {
// if ( !Sys_IsLANAddress( clc.serverAddress ) ) {
// CL_RequestAuthorization();
// }
NET_OutOfBandPrint(NS_CLIENT, clc.serverAddress, "getchallenge");
CL_NET_OutOfBandPrint(clc.serverAddress, "getchallenge");
break;
case CA_AUTHORIZING:
// resend the cd key authorization
gcd_compute_response(cl_cdkey, Cmd_Argv(1), cls.gcdResponse, CDResponseMethod_REAUTH);
NET_OutOfBandPrint(NS_CLIENT, clc.serverAddress, "authorizeThis %s", cls.gcdResponse);
CL_NET_OutOfBandPrint(clc.serverAddress, "authorizeThis %s", cls.gcdResponse);
break;
case CA_CHALLENGING:
/*
@@ -1996,13 +2014,13 @@ wombat: sending conect here: an example connect string from MOHAA looks like thi
Info_SetValueForKey(info, "protocol", va("%i", com_protocol->integer));
Info_SetValueForKey( info, "qport", va("%i", port ) );
Info_SetValueForKey(info, "challenge", va("%i", clc.challenge));
Info_SetValueForKey(info, "version", com_shortversion->string);
Info_SetValueForKey(info, "version", com_target_version->string);
if (com_target_game->integer == target_game_e::TG_MOHTT) {
// only send if maintt is loaded
Info_SetValueForKey(info, "clientType", "Breakthrough");
}
strcpy(data, "connect ");
Q_strncpyz(data, "connect ", sizeof(data));
// TTimo adding " " around the userinfo string to avoid truncated userinfo on the server
// (Com_TokenizeString tokenizes around spaces)
data[8] = '"';
@@ -2235,6 +2253,10 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
char *s;
char *c;
const char *reason;
if (cl_netprofile->integer) {
NetProfileAddPacket(&cls.netprofile.inPackets, msg->cursize, NETPROF_PACKET_MESSAGE);
}
MSG_BeginReadingOOB( msg );
MSG_ReadLong( msg ); // skip the -1
@@ -2319,7 +2341,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
// echo request from server
if ( !Q_stricmp(c, "echo") ) {
NET_OutOfBandPrint( NS_CLIENT, from, "%s", Cmd_Argv(1) );
CL_NET_OutOfBandPrint(from, "%s", Cmd_Argv(1) );
return;
}
@@ -2327,7 +2349,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
if ( !Q_stricmp(c, "getKey") ) {
clc.state = CA_AUTHORIZING;
gcd_compute_response(cl_cdkey, Cmd_Argv(1), cls.gcdResponse, CDResponseMethod_NEWAUTH);
NET_OutOfBandPrint(NS_CLIENT, from, "authorizeThis %s", cls.gcdResponse);
CL_NET_OutOfBandPrint(from, "authorizeThis %s", cls.gcdResponse);
return;
}
@@ -2575,12 +2597,17 @@ void CL_Frame ( int msec ) {
}
#endif
if ( clc.state == CA_DISCONNECTED && !UI_MenuActive()
&& !com_sv_running->integer ) {
// if disconnected, bring up the menu
S_StopAllSounds2( qtrue );
S_TriggeredMusic_PlayIntroMusic();
UI_MenuEscape( "main" );
if (CL_FinishedIntro()) {
if (clc.state == CA_DISCONNECTED) {
if (!UI_MenuActive() && !com_sv_running->integer) {
// if disconnected, bring up the menu
S_StopAllSounds2(qtrue);
S_TriggeredMusic_PlayIntroMusic();
UI_MenuEscape("main");
}
} else if (clc.state == CA_CINEMATIC) {
UI_ForceMenuOff(qtrue);
}
}
// if recording an avi, lock to a fixed fps
@@ -2615,7 +2642,7 @@ void CL_Frame ( int msec ) {
now.tm_min,
now.tm_sec );
Q_strncpyz( serverName, cls.servername, MAX_OSPATH );
Q_strncpyz( serverName, clc.servername, MAX_OSPATH );
// Replace the ":" in the address as it is not a valid
// file name character
p = strstr( serverName, ":" );
@@ -2649,6 +2676,31 @@ void CL_Frame ( int msec ) {
cls.timeScaled = com_timescale->integer != 1;
//
// Added in 2.0: network profiling
//
if (cl_netprofile->integer) {
if (!cls.netprofile.initialized) {
memset(&cls.netprofile, 0, sizeof(cls.netprofile));
cls.netprofile.initialized = qtrue;
}
if (cls.netprofile.rate != cl_rate->integer) {
cls.netprofile.rate = cl_rate->integer;
if (cls.netprofile.rate < 1000) {
cls.netprofile.rate = 1000;
} else if (cls.netprofile.rate > 90000) {
cls.netprofile.rate = 90000;
}
}
cls.netprofile.outPackets.updateTime = Com_Milliseconds();
cls.netprofile.inPackets.updateTime = cls.netprofile.outPackets.updateTime;
} else {
cls.netprofile.initialized = qfalse;
}
// see if we need to update any userinfo
CL_CheckUserinfo();
@@ -2859,7 +2911,7 @@ void CL_RefStaticClear( void ) {
CL_CG_PermanentMark
============
*/
int CL_CG_PermanentMark(const vec3_t origin, const vec3_t dir, float orientation,
int CL_CG_PermanentMark(vec3_t origin, vec3_t dir, float orientation,
float fSScale, float fTScale, float red, float green, float blue, float alpha,
qboolean dolighting, float fSCenter, float fTCenter,
markFragment_t *pMarkFragments, void *pPolyVerts )
@@ -3123,7 +3175,7 @@ void CL_VidMode_f( void ) {
mode = atoi( Cmd_Argv( 1 ) );
if( CL_SetVidMode( mode ) ) {
sprintf( text, "%d", mode );
Com_sprintf( text, sizeof( text ), "%d", mode );
Cvar_Set( "r_mode", text );
}
}
@@ -3142,10 +3194,10 @@ void CL_TikiInfoCommand_f( void ) {
name = Cmd_Argv( 1 );
if( strchr( name, '/' ) ) {
strcpy( modelname, name );
Q_strncpyz( modelname, name, sizeof( modelname ) );
} else {
strcpy( modelname, "models/" );
strcat( modelname, name );
Q_strncpyz( modelname, "models/", sizeof( modelname ) );
Q_strcat( modelname, sizeof( modelname ), name );
}
COM_DefaultExtension( modelname, sizeof( modelname ), ".tik" );
@@ -3237,8 +3289,6 @@ it by filling it with 2048 bytes of random data.
*/
static void CL_GenerateQKey(void)
{
// FIXME: unimplemented
/*
int len = 0;
unsigned char buff[ QKEY_SIZE ];
fileHandle_t f;
@@ -3268,7 +3318,6 @@ static void CL_GenerateQKey(void)
FS_FCloseFile( f );
Com_Printf( "QKEY generated\n" );
}
*/
}
/*
@@ -3316,6 +3365,8 @@ void CL_Init( void ) {
cl_master = Cvar_Get ("cl_master", MASTER_SERVER_NAME, CVAR_ARCHIVE);
cl_timeNudge = Cvar_Get ("cl_timeNudge", "0", CVAR_TEMP );
cl_shownet = Cvar_Get ("cl_shownet", "0", CVAR_TEMP );
cl_netprofile = Cvar_Get("cl_netprofile", "0", CVAR_TEMP);
cl_netprofileoverlay = Cvar_Get("cl_netprofileoverlay", "0", CVAR_TEMP);
cl_showSend = Cvar_Get ("cl_showSend", "0", CVAR_TEMP );
cl_showTimeDelta = Cvar_Get ("cl_showTimeDelta", "0", CVAR_TEMP );
cl_freezeDemo = Cvar_Get ("cl_freezeDemo", "0", CVAR_TEMP );
@@ -3431,7 +3482,7 @@ void CL_Init( void ) {
// userinfo
name = Cvar_Get ("name", "UnnamedSoldier", CVAR_USERINFO | CVAR_ARCHIVE );
Cvar_Get ("rate", "5000", CVAR_USERINFO | CVAR_ARCHIVE );
cl_rate = Cvar_Get ("rate", "5000", CVAR_USERINFO | CVAR_ARCHIVE );
Cvar_Get ("snaps", "20", CVAR_USERINFO | CVAR_ARCHIVE );
Cvar_Get ("password", "", CVAR_USERINFO);
Cvar_Get ("dm_playermodel", "american_army", CVAR_USERINFO | CVAR_ARCHIVE );
@@ -3463,7 +3514,6 @@ void CL_Init( void ) {
Cmd_AddCommand ("reconnect", CL_Reconnect_f);
Cmd_AddCommand ("localservers", CL_LocalServers_f);
Cmd_AddCommand ("globalservers", CL_GlobalServers_f);
Cmd_AddCommand ("refreshserverlist", CL_GamespyServers_f); // wombat: gamespy query
Cmd_AddCommand ("rcon", CL_Rcon_f);
Cmd_AddCommand ("setenv", CL_Setenv_f );
Cmd_AddCommand ("ping", CL_Ping_f );
@@ -3498,7 +3548,6 @@ void CL_Init( void ) {
S_Init(qtrue);
#endif
// fixme: should we leave it?
CL_GenerateQKey();
Cvar_Get( "cl_guid", "", CVAR_USERINFO | CVAR_ROM );
CL_UpdateGUID( NULL, 0 );
@@ -3569,6 +3618,8 @@ void CL_Shutdown(const char* finalmsg, qboolean disconnect, qboolean quit) {
Cmd_RemoveCommand ("video");
Cmd_RemoveCommand ("stopvideo");
CL_ShutdownInput();
Cvar_Set( "cl_running", "0" );
recursive = qfalse;
@@ -3588,6 +3639,7 @@ static void CL_SetServerInfo(serverInfo_t *server, const char *info, int ping) {
server->maxClients = atoi(Info_ValueForKey(info, "sv_maxclients"));
Q_strncpyz(server->game,Info_ValueForKey(info, "game"), MAX_NAME_LENGTH);
server->gameType = atoi(Info_ValueForKey(info, "gametype"));
Q_strncpyz(server->gameTypeString, Info_ValueForKey(info, "gametypestring"), sizeof(server->gameTypeString));
server->netType = atoi(Info_ValueForKey(info, "nettype"));
server->minPing = atoi(Info_ValueForKey(info, "minping"));
server->maxPing = atoi(Info_ValueForKey(info, "maxping"));
@@ -3636,6 +3688,8 @@ void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) {
char *infoString;
int prot;
char *gamename;
char *pszVersion;
char *pszServerType;
qboolean gameMismatch;
infoString = MSG_ReadString( msg );
@@ -3664,12 +3718,42 @@ void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) {
#ifdef LEGACY_PROTOCOL
&& prot != com_legacyprotocol->integer
#endif
&& (com_target_demo->integer || prot != protocol_version_demo)
)
{
Com_DPrintf( "Different protocol info packet: %s\n", infoString );
return;
}
if (!com_target_demo->integer && protocol_version_demo != protocol_version_full && prot == protocol_version_demo) {
Com_DPrintf("Full version found compatible demo protocol version. %s\n", infoString);
}
pszVersion = Info_ValueForKey(infoString, "gamever");
pszServerType = Info_ValueForKey(infoString, "serverType");
if (*pszVersion) {
if (*pszVersion == 'd') {
pszVersion++;
}
if (com_target_game->integer >= target_game_e::TG_MOHTT) {
if (atoi(pszServerType) == target_game_e::TG_MOHTT) {
if (fabs(atof(pszVersion)) < 2.3f) {
return;
}
} else {
if (fabs(atof(pszVersion)) < 2.1f) {
return;
}
}
} else {
if (fabs(atof(pszVersion) - com_target_version->value) > 0.1f) {
return;
}
}
}
// iterate servers waiting for ping response
for (i=0; i<MAX_PINGREQUESTS; i++)
{
@@ -3815,7 +3899,7 @@ int CL_ServerStatus( const char *serverAddress, char *serverStatusString, int ma
serverStatus->retrieved = qfalse;
serverStatus->time = 0;
serverStatus->startTime = Com_Milliseconds();
NET_OutOfBandPrint( NS_CLIENT, to, "getstatus" );
CL_NET_OutOfBandPrint(to, "getstatus" );
return qfalse;
}
}
@@ -3827,7 +3911,7 @@ int CL_ServerStatus( const char *serverAddress, char *serverStatusString, int ma
serverStatus->retrieved = qfalse;
serverStatus->startTime = Com_Milliseconds();
serverStatus->time = 0;
NET_OutOfBandPrint( NS_CLIENT, to, "getstatus" );
CL_NET_OutOfBandPrint(to, "getstatus" );
return qfalse;
}
return qfalse;
@@ -3839,10 +3923,10 @@ CL_ServerStatusResponse
===================
*/
void CL_ServerStatusResponse( netadr_t from, msg_t *msg ) {
char *s;
char info[MAX_INFO_STRING];
int i, l, score, ping;
int len;
const char *s;
char info[MAX_INFO_STRING];
int i, l, score, ping;
int len;
serverStatus_t *serverStatus;
serverStatus = NULL;
@@ -3966,133 +4050,22 @@ void CL_LocalServers_f( void ) {
to.type = NA_BROADCAST;
NET_SendPacket( NS_CLIENT, strlen( message ), message, to );
if (cl_netprofile->integer) {
NetProfileAddPacket(&cls.netprofile.inPackets, strlen( message ), NETPROF_PACKET_MESSAGE);
}
// Added in OPM (from ioquake3)
to.type = NA_MULTICAST6;
NET_SendPacket( NS_CLIENT, strlen( message ), message, to );
if (cl_netprofile->integer) {
NetProfileAddPacket(&cls.netprofile.inPackets, strlen(message), NETPROF_PACKET_MESSAGE);
}
}
}
}
/*
==================
CL_GamespyServers_f
==================
*/
// currently about 1000 mohaa servers at a time. when set higher, buffer must be increased!
#define MAX_GAMESPYSERVERS 16
void CL_GamespyServers_f( void ) {
// FIXME: unimplemented
#if 0
char buffer[10240];
int bytesRead;
int i, count, max, total;
serverAddress_t addresses[MAX_GAMESPYSERVERS];
int numservers;
byte* buffptr;
byte* buffend;
// if ( Cmd_Argc() < 1) {
// Com_Printf( "usage: gamespyservers [keywords]\n");
// return;
// }
Com_Printf( "Requesting servers from the GameSpy master...\n" );
Cvar_Set( "dm_serverstatus", "Getting List.");
if (!NETGS_CreateMasterSocket()) {
Com_Printf( "CL_GamespyServers_f: could not create socket.\n" );
return;
}
if (!NETGS_SendMasterRequest()) {
Com_Printf( "CL_GamespyServers_f: could not send master request.\n" );
return;
}
bytesRead = NETGS_ReceiveMasterResponse( buffer, sizeof(buffer) );
if (!bytesRead) {
Com_Printf( "CL_GamespyServers_f: Error in Response.\n" );
return;
}
// parse through server response string
numservers = 0;
buffptr = ( byte * )buffer;
buffend = buffptr + bytesRead;
while (buffptr+1 < buffend) {
if ( buffptr >= buffend - 6 ) {
break;
}
// parse out ip
addresses[numservers].ip[0] = *buffptr++;
addresses[numservers].ip[1] = *buffptr++;
addresses[numservers].ip[2] = *buffptr++;
addresses[numservers].ip[3] = *buffptr++;
// parse out port
addresses[numservers].port = *buffptr++;
addresses[numservers].port += (*buffptr++) << 8;
Com_DPrintf( "server: %d ip: %d.%d.%d.%d:%d\n",numservers,
addresses[numservers].ip[0],
addresses[numservers].ip[1],
addresses[numservers].ip[2],
addresses[numservers].ip[3],
BigShort(addresses[numservers].port) );
numservers++;
if (numservers >= MAX_GAMESPYSERVERS) {
break;
}
// parse out "\\final\\"
if (buffptr[0] == '\\' && buffptr[1] == 'f' && buffptr[2] == 'i' && buffptr[3] == 'n' && buffptr[4] == 'a' && buffptr[6] == 'l' && buffptr[6] == '\\') {
break;
}
}
cls.numglobalservers = 0;
cls.numGlobalServerAddresses = 0;
count = cls.numglobalservers;
max = MAX_GLOBAL_SERVERS;
for (i = 0; i < numservers && count < max; i++) {
// build net address
serverInfo_t *server = &cls.globalServers[count];
CL_InitServerInfo( server, &addresses[i] );
// advance to next slot
count++;
}
if ( cls.numGlobalServerAddresses < MAX_GLOBAL_SERVERS ) {
// if we couldn't store the servers in the main list anymore
for (; i < numservers && count >= max; i++) {
serverAddress_t *addr;
// just store the addresses in an additional list
addr = &cls.globalServerAddresses[cls.numGlobalServerAddresses++];
addr->ip[0] = addresses[i].ip[0];
addr->ip[1] = addresses[i].ip[1];
addr->ip[2] = addresses[i].ip[2];
addr->ip[3] = addresses[i].ip[3];
addr->port = addresses[i].port;
}
}
cls.numglobalservers = count;
total = count + cls.numGlobalServerAddresses;
Com_Printf("%d servers parsed (total %d)\n", numservers, total);
Cvar_Set( "dm_serverstatus", "Server List Received.");
Cvar_SetValue( "dm_servercount", total );
#endif
}
/*
==================
CL_GlobalServers_f
@@ -4118,7 +4091,7 @@ void CL_GlobalServers_f( void ) {
int numAddress = 0;
for ( i = 1; i <= MAX_MASTER_SERVERS; i++ ) {
sprintf(command, "sv_master%d", i);
Com_sprintf(command, sizeof(command), "sv_master%d", i);
masteraddress = Cvar_VariableString(command);
if(!*masteraddress)
@@ -4136,7 +4109,7 @@ void CL_GlobalServers_f( void ) {
return;
}
sprintf(command, "sv_master%d", masterNum);
Com_sprintf(command, sizeof(command), "sv_master%d", masterNum);
masteraddress = Cvar_VariableString(command);
if(!*masteraddress)
@@ -4192,7 +4165,7 @@ void CL_GlobalServers_f( void ) {
Q_strcat(command, sizeof(command), Cmd_Argv(i));
}
NET_OutOfBandPrint( NS_SERVER, to, "%s", command );
CL_NET_OutOfBandPrint( to, "%s", command );
}
@@ -4412,7 +4385,7 @@ void CL_Ping_f( void ) {
CL_SetServerInfoByAddress(pingptr->adr, NULL, 0);
NET_OutOfBandPrint( NS_CLIENT, to, "\x02getinfo xxx" );
CL_NET_OutOfBandPrint( to, "\x02getinfo xxx" );
}
/*
@@ -4465,10 +4438,10 @@ void CL_Dialog_f( void ) {
return;
}
strcpy( title, Cmd_Argv( 1 ) );
strcpy( cvar, Cmd_Argv( 2 ) );
strcpy( command, Cmd_Argv( 3 ) );
strcpy( cancelCommand, Cmd_Argv( 4 ) );
Q_strncpyz( title, Cmd_Argv( 1 ), sizeof( title ) );
Q_strncpyz( cvar, Cmd_Argv( 2 ), sizeof( cvar ) );
Q_strncpyz( command, Cmd_Argv( 3 ), sizeof( command ) );
Q_strncpyz( cancelCommand, Cmd_Argv( 4 ), sizeof( cancelCommand ) );
if( Cmd_Argc() > 5 ) {
width = atoi( Cmd_Argv( 5 ) );
@@ -4482,17 +4455,17 @@ void CL_Dialog_f( void ) {
}
if( Cmd_Argc() > 7 ) {
strcpy( shader, Cmd_Argv( 7 ) );
Q_strncpyz( shader, Cmd_Argv( 7 ), sizeof( shader ) );
} else {
shader[ 0 ] = 0;
}
if( Cmd_Argc() > 8 ) {
strcpy( okshader, Cmd_Argv( 8 ) );
Q_strncpyz( okshader, Cmd_Argv( 8 ), sizeof(okshader) );
} else {
okshader[ 0 ] = 0;
}
if( Cmd_Argc() > 9 ) {
strcpy( cancelshader, Cmd_Argv( 9 ) );
Q_strncpyz( cancelshader, Cmd_Argv( 9 ), sizeof(cancelshader) );
} else {
cancelshader[ 0 ] = 0;
}
@@ -4506,7 +4479,10 @@ CL_ServerRestarted
==================
*/
void CL_ServerRestarted( void ) {
S_StopAllSounds2( qfalse );
//S_StopAllSounds2( qfalse );
// Fixed in OPM
// Also stop the music
S_StopAllSounds2( qtrue );
UI_ServerLoaded();
UI_ClearState();
@@ -4579,7 +4555,7 @@ qboolean CL_UpdateVisiblePings_f(int source) {
memcpy(&cl_pinglist[j].adr, &server[i].adr, sizeof(netadr_t));
cl_pinglist[j].start = Sys_Milliseconds();
cl_pinglist[j].time = 0;
NET_OutOfBandPrint( NS_CLIENT, cl_pinglist[j].adr, "getinfo xxx" );
CL_NET_OutOfBandPrint( cl_pinglist[j].adr, "getinfo xxx" );
slots++;
}
}
@@ -4667,7 +4643,7 @@ void CL_ServerStatus_f(void) {
return;
}
NET_OutOfBandPrint( NS_CLIENT, *toptr, "getstatus" );
CL_NET_OutOfBandPrint( *toptr, "getstatus" );
serverStatus = CL_GetServerStatus( *toptr );
serverStatus->address = *toptr;
@@ -4736,7 +4712,7 @@ qboolean CL_CDKeyValidate( const char *key, const char *checksum ) {
}
}
sprintf(chs, "%02x", sum);
Com_sprintf(chs, sizeof(chs), "%02x", sum);
if (checksum && !Q_stricmp(chs, checksum)) {
return qtrue;
+23 -3
View File
@@ -132,7 +132,7 @@ CL_Netchan_TransmitNextFragment
=================
*/
void CL_Netchan_TransmitNextFragment( netchan_t *chan ) {
Netchan_TransmitNextFragment( chan );
Netchan_TransmitNextFragment( chan, cl_netprofile->integer ? &cls.netprofile.inPackets : NULL );
}
/*
@@ -144,7 +144,7 @@ void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg ) {
MSG_WriteByte( msg, clc_EOF );
CL_Netchan_Encode( msg );
Netchan_Transmit( chan, msg->cursize, msg->data );
Netchan_Transmit( chan, msg->cursize, msg->data, cl_netprofile->integer ? &cls.netprofile.inPackets : NULL );
}
extern int oldsize;
@@ -158,10 +158,30 @@ CL_Netchan_Process
qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ) {
int ret;
ret = Netchan_Process( chan, msg );
ret = Netchan_Process( chan, msg, cl_netprofile->integer ? &cls.netprofile.outPackets : NULL );
if (!ret)
return qfalse;
CL_Netchan_Decode( msg );
newsize += msg->cursize;
return qtrue;
}
/*
=================
CL_NET_OutOfBandPrint
=================
*/
void CL_NET_OutOfBandPrint(netadr_t adr, const char* format, ...) {
va_list argptr;
char string[MAX_MSGLEN];
va_start(argptr, format);
Q_vsnprintf(string, sizeof(string), format, argptr);
va_end(argptr);
NET_OutOfBandPrint(NS_CLIENT, adr, "%s", string);
if (cl_netprofile->integer) {
NetProfileAddPacket(&cls.netprofile.inPackets, strlen(string), NETPROF_PACKET_MESSAGE);
}
}
+199 -7
View File
@@ -223,13 +223,13 @@ qboolean CL_UnpackNonPVSClient(int* packed, radarUnpacked_t* unpacked) {
range = 0;
}
unpacked->x = x * range / 63.f;
unpacked->y = y * range / 63.f;
unpacked->x = x * range / (MAX_CLIENTS - 1);
unpacked->y = y * range / (MAX_CLIENTS - 1);
if (!bValid)
{
unpacked->x = x * range / 63.f * 1024;
unpacked->y = y * range / 63.f * 1024;
unpacked->x = x * range / (MAX_CLIENTS - 1) * 1024.0;
unpacked->y = y * range / (MAX_CLIENTS - 1) * 1024.0;
}
unpacked->yaw = yaw * 11.25f;
@@ -429,12 +429,24 @@ void CL_SystemInfoChanged( void ) {
// in some cases, outdated cp commands might get sent with this news serverId
cl.serverId = atoi( Info_ValueForKey( systemInfo, "sv_serverid" ) );
#ifdef USE_VOIP
#ifdef LEGACY_PROTOCOL
if(clc.compat)
clc.voipEnabled = qfalse;
else
#endif
{
s = Info_ValueForKey( systemInfo, "sv_voipProtocol" );
clc.voipEnabled = !Q_stricmp(s, "opus");
}
#endif
// don't set any vars when playing a demo
if ( clc.demoplaying ) {
return;
}
s = Info_ValueForKey( systemInfo, "sv_cheats" );
s = Info_ValueForKey( systemInfo, "cheats" );
cl_connectedToCheatServer = atoi( s );
if ( !cl_connectedToCheatServer ) {
Cvar_SetCheatState();
@@ -784,6 +796,178 @@ void CL_ParseDownload ( msg_t *msg ) {
}
}
#ifdef USE_VOIP
static
qboolean CL_ShouldIgnoreVoipSender(int sender)
{
if (!cl_voip->integer)
return qtrue; // VoIP is disabled.
else if ((sender == clc.clientNum) && (!clc.demoplaying))
return qtrue; // ignore own voice (unless playing back a demo).
else if (clc.voipMuteAll)
return qtrue; // all channels are muted with extreme prejudice.
else if (clc.voipIgnore[sender])
return qtrue; // just ignoring this guy.
else if (clc.voipGain[sender] == 0.0f)
return qtrue; // too quiet to play.
return qfalse;
}
/*
=====================
CL_PlayVoip
Play raw data
=====================
*/
static void CL_PlayVoip(int sender, int samplecnt, const byte *data, int flags)
{
if(flags & VOIP_DIRECT)
{
S_RawSamples(sender + 1, samplecnt, 48000, 2, 1,
data, clc.voipGain[sender], -1);
}
if(flags & VOIP_SPATIAL)
{
S_RawSamples(sender + MAX_CLIENTS + 1, samplecnt, 48000, 2, 1,
data, 1.0f, sender);
}
}
/*
=====================
CL_ParseVoip
A VoIP message has been received from the server
=====================
*/
static
void CL_ParseVoip ( msg_t *msg, qboolean ignoreData ) {
static short decoded[VOIP_MAX_PACKET_SAMPLES*4]; // !!! FIXME: don't hard code
const int sender = MSG_ReadShort(msg);
const int generation = MSG_ReadByte(msg);
const int sequence = MSG_ReadLong(msg);
const int frames = MSG_ReadByte(msg);
const int packetsize = MSG_ReadShort(msg);
const int flags = MSG_ReadBits(msg, VOIP_FLAGCNT);
unsigned char encoded[4000];
int numSamples;
int seqdiff;
int written = 0;
int i;
Com_DPrintf("VoIP: %d-byte packet from client %d\n", packetsize, sender);
if (sender < 0)
return; // short/invalid packet, bail.
else if (generation < 0)
return; // short/invalid packet, bail.
else if (sequence < 0)
return; // short/invalid packet, bail.
else if (frames < 0)
return; // short/invalid packet, bail.
else if (packetsize < 0)
return; // short/invalid packet, bail.
if (packetsize > sizeof (encoded)) { // overlarge packet?
int bytesleft = packetsize;
while (bytesleft) {
int br = bytesleft;
if (br > sizeof (encoded))
br = sizeof (encoded);
MSG_ReadData(msg, encoded, br);
bytesleft -= br;
}
return; // overlarge packet, bail.
}
MSG_ReadData(msg, encoded, packetsize);
if (ignoreData) {
return; // just ignore legacy speex voip data
} else if (!clc.voipCodecInitialized) {
return; // can't handle VoIP without libopus!
} else if (sender >= MAX_CLIENTS) {
return; // bogus sender.
} else if (CL_ShouldIgnoreVoipSender(sender)) {
return; // Channel is muted, bail.
}
// !!! FIXME: make sure data is narrowband? Does decoder handle this?
Com_DPrintf("VoIP: packet accepted!\n");
seqdiff = sequence - clc.voipIncomingSequence[sender];
// This is a new "generation" ... a new recording started, reset the bits.
if (generation != clc.voipIncomingGeneration[sender]) {
Com_DPrintf("VoIP: new generation %d!\n", generation);
opus_decoder_ctl(clc.opusDecoder[sender], OPUS_RESET_STATE);
clc.voipIncomingGeneration[sender] = generation;
seqdiff = 0;
} else if (seqdiff < 0) { // we're ahead of the sequence?!
// This shouldn't happen unless the packet is corrupted or something.
Com_DPrintf("VoIP: misordered sequence! %d < %d!\n",
sequence, clc.voipIncomingSequence[sender]);
// reset the decoder just in case.
opus_decoder_ctl(clc.opusDecoder[sender], OPUS_RESET_STATE);
seqdiff = 0;
} else if (seqdiff * VOIP_MAX_PACKET_SAMPLES*2 >= sizeof (decoded)) { // dropped more than we can handle?
// just start over.
Com_DPrintf("VoIP: Dropped way too many (%d) frames from client #%d\n",
seqdiff, sender);
opus_decoder_ctl(clc.opusDecoder[sender], OPUS_RESET_STATE);
seqdiff = 0;
}
if (seqdiff != 0) {
Com_DPrintf("VoIP: Dropped %d frames from client #%d\n",
seqdiff, sender);
// tell opus that we're missing frames...
for (i = 0; i < seqdiff; i++) {
assert((written + VOIP_MAX_PACKET_SAMPLES) * 2 < sizeof (decoded));
numSamples = opus_decode(clc.opusDecoder[sender], NULL, 0, decoded + written, VOIP_MAX_PACKET_SAMPLES, 0);
if ( numSamples <= 0 ) {
Com_DPrintf("VoIP: Error decoding frame %d from client #%d\n", i, sender);
continue;
}
written += numSamples;
}
}
numSamples = opus_decode(clc.opusDecoder[sender], encoded, packetsize, decoded + written, ARRAY_LEN(decoded) - written, 0);
if ( numSamples <= 0 ) {
Com_DPrintf("VoIP: Error decoding voip data from client #%d\n", sender);
numSamples = 0;
}
#if 0
static FILE *encio = NULL;
if (encio == NULL) encio = fopen("voip-incoming-encoded.bin", "wb");
if (encio != NULL) { fwrite(encoded, packetsize, 1, encio); fflush(encio); }
static FILE *decio = NULL;
if (decio == NULL) decio = fopen("voip-incoming-decoded.bin", "wb");
if (decio != NULL) { fwrite(decoded+written, numSamples*2, 1, decio); fflush(decio); }
#endif
written += numSamples;
Com_DPrintf("VoIP: playback %d bytes, %d samples, %d frames\n",
written * 2, written, frames);
if(written > 0)
CL_PlayVoip(sender, written, (const byte *) decoded, flags);
clc.voipIncomingSequence[sender] = sequence + frames;
}
#endif
/*
=====================
CL_ParseCommandString
@@ -932,8 +1116,16 @@ void CL_ParseServerMessage( msg_t *msg ) {
}
CL_ParseCGMessage( msg );
break;
case svc_voipSpeex:
#ifdef USE_VOIP
CL_ParseVoip( msg, qtrue );
#endif
break;
case svc_voipOpus:
#ifdef USE_VOIP
CL_ParseVoip( msg, !clc.voipEnabled );
#endif
break;
}
}
}
+8 -6
View File
@@ -343,7 +343,7 @@ void SCR_DrawDemoRecording( void ) {
}
pos = FS_FTell( clc.demofile );
sprintf( string, "RECORDING %s: %ik", clc.demoName, pos / 1024 );
Com_sprintf( string, sizeof( string ), "RECORDING %s: %ik", clc.demoName, pos / 1024 );
SCR_DrawStringExt( 320 - strlen( string ) * 4, 20, 8, string, g_color_table[7], qtrue, qfalse );
}
@@ -520,16 +520,18 @@ text to the screen.
==================
*/
void SCR_UpdateScreen( void ) {
static int recursive;
static qboolean screen_recursive;
if ( !scr_initialized ) {
return; // not initialized yet
}
if ( ++recursive > 2 ) {
Com_Error( ERR_FATAL, "SCR_UpdateScreen: recursively called" );
if (screen_recursive) {
// already called
return;
}
recursive = 1;
screen_recursive = qtrue;
CL_StartHunkUsers(qfalse);
SCR_SimpleUpdateScreen();
@@ -553,6 +555,6 @@ void SCR_UpdateScreen( void ) {
}
}
recursive = 0;
screen_recursive = qfalse;
}
+225 -164
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.
@@ -136,7 +136,8 @@ static unsigned int startCountHigh;
static unsigned int loadCountLow;
static unsigned int loadCountHigh;
static unsigned int loadCount;
static unsigned int lastTime;
static unsigned int lastTime = 0;
static unsigned int updateTime = 0;
static unsigned int loadNumber;
static unsigned int totalLoadTime;
static unsigned int currentLoadTime;
@@ -265,7 +266,7 @@ static void GetClientState(uiClientState_t *state)
{
state->connectPacketCount = clc.connectPacketCount;
state->connState = clc.state;
Q_strncpyz(state->servername, cls.servername, sizeof(state->servername));
Q_strncpyz(state->servername, clc.servername, sizeof(state->servername));
Q_strncpyz(state->updateInfoString, cls.updateInfoString, sizeof(state->updateInfoString));
Q_strncpyz(state->messageString, clc.serverMessage, sizeof(state->messageString));
state->clientNum = cl.snap.ps.clientNum;
@@ -1001,10 +1002,14 @@ static UIRect2D getQuickMessageDMConsoleRectangle(void)
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.65;
rect.size.width = cls.glconfig.vidWidth;
rect.size.height = 38.0;
rect.pos.x = 0;
rect.pos.y = cls.glconfig.vidHeight * 0.66;
rect.size.width = cls.glconfig.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;
}
return rect;
@@ -1017,7 +1022,7 @@ UI_DMMessageModesMatch
*/
static qboolean UI_DMMessageModesMatch(int iMode)
{
qboolean bQuickMessage;
qboolean bQuickMessage = qfalse;
if (iMode && (iMode != 300 || dm_console->GetQuickMessageMode())) {
if (iMode < 0) {
@@ -1048,13 +1053,15 @@ static void UI_SetDMConsoleMode(int iMode)
return;
}
bQuickMessage = qfalse;
if (iMode < 0) {
bQuickMessage = qtrue;
iMode = -iMode;
}
if (iMode == 300) {
bQuickMessage = dm_console->GetMessageMode();
iMode = dm_console->GetMessageMode();
}
if (dm_console->GetQuickMessageMode()) {
@@ -1064,8 +1071,8 @@ static void UI_SetDMConsoleMode(int iMode)
}
} else {
if (bQuickMessage) {
dm_console->setFrame(getDefaultDMConsoleRectangle());
dm_console->SetQuickMessageMode(qfalse);
dm_console->setFrame(getQuickMessageDMConsoleRectangle());
dm_console->SetQuickMessageMode(bQuickMessage);
}
}
@@ -1086,7 +1093,7 @@ static void UI_SetDMConsoleMode(int iMode)
dm_console->setTitle(Sys_LV_CL_ConvertString(
"Chat Window (Enter to send/close) (all|team|private to change mode) : Messaging to All"
));
} else if (iMode == 100) {
} else if (iMode == 200) {
dm_console->setTitle(Sys_LV_CL_ConvertString(
"Chat Window (Enter to send/close) (all|team|private to change mode) : Messaging to Team"
));
@@ -1204,6 +1211,16 @@ static UIRect2D getDefaultDMBoxRectangle(void)
return UIRect2D(width, 0, cls.glconfig.vidWidth - (width + 192.0f), 120.0f);
}
/*
====================
UI_GetObjectivesTop
====================
*/
float UI_GetObjectivesTop(void)
{
return getDefaultGMBoxRectangle().pos.y;
}
/*
====================
UI_ShowHudList
@@ -1460,7 +1477,7 @@ void UI_FocusMenuIfExists(void)
currentMenu->ActivateMenu();
if (ui_newvidmode->integer == -1) {
Cvar_Get("ui_newvidmode", va("%d", r_mode), CVAR_SERVER_CREATED);
Cvar_Get("ui_newvidmode", va("%d", r_mode), CVAR_RESETSTRING);
Cvar_SetValue("ui_newvidmode", r_mode);
}
} else {
@@ -1664,7 +1681,7 @@ 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, cls.glconfig.vidWidth, cls.glconfig.vidHeight, 0, cls.glconfig.vidWidth, cls.glconfig.vidHeight, 0, -1, 1
);
re.Scissor(0, 0, cls.glconfig.vidWidth, cls.glconfig.vidHeight);
re.SetColor(g_color_table[0]);
@@ -1702,7 +1719,36 @@ void UI_DrawIntro(void)
view3d->setShow(false);
UI_ClearBackground();
// FIXME: draw intro
if (cls.startStage < 3 || cls.startStage >= 12) {
return;
}
if (intro_stage.material->GetMaterial()) {
float swidth;
float sheight;
vec4_t color;
VectorSet4(color, 1, 1, 1, 1);
if (intro_stage.fadetime) {
float frac;
frac = Q_clamp_float((cls.realtime - intro_stage.starttime) / intro_stage.fadetime, 0, 1);
color[0] = color[1] = color[2] =
intro_stage.alpha_start + frac * (intro_stage.alpha_end - intro_stage.alpha_start);
}
swidth = view3d->getFrame().getMaxX();
sheight = view3d->getFrame().getMaxY();
re.SetColor(color);
re.DrawStretchPic(0.0, 0.0, swidth, sheight, 0.0, 0.0, 1.0, 1.0, intro_stage.material->GetMaterial());
re.SetColor(NULL);
}
if (cls.realtime >= intro_stage.endtime) {
CL_FinishedStartStage();
}
}
/*
@@ -1809,17 +1855,9 @@ void UI_Update(void)
}
// don't care about the intro
/*
if( CL_FinishedIntro() )
{
}
else
{
UI_DrawIntro();
}
*/
if (!server_loading && (clc.state == CA_CONNECTING || clc.state == CA_CHALLENGING) && ui_pConnectingMenu) {
if (!CL_FinishedIntro()) {
UI_DrawIntro();
} else if (!server_loading && (clc.state == CA_CONNECTING || clc.state == CA_CHALLENGING) && ui_pConnectingMenu) {
view3d->setShow(false);
UI_ClearBackground();
@@ -1857,7 +1895,7 @@ void UI_Update(void)
if (clc.state <= CA_PRIMED) {
view3d->setShow(false);
UI_ClearBackground();
} else if (clc.state == CA_PRIMED || clc.state == CA_ACTIVE) {
} else if (clc.state == CA_ACTIVE || clc.state == CA_CINEMATIC) {
Com_FakeUnpause();
view3d->setShow(true);
} else {
@@ -2638,7 +2676,7 @@ void UI_PushMenuSP_f(void)
}
if ((!com_cl_running || !com_cl_running->integer || clc.state == CA_DISCONNECTED || !cg_gametype->integer)
&& (!com_sv_running || !com_sv_running->integer || !g_gametype->integer)) {
&& (!com_sv_running || !com_sv_running->integer || g_gametype->integer == GT_SINGLE_PLAYER)) {
UI_PushMenu(Cmd_Argv(1));
}
}
@@ -2659,7 +2697,7 @@ void UI_PushMenuMP_f(void)
}
if (com_cl_running && com_cl_running->integer && clc.state != CA_DISCONNECTED && cg_gametype->integer
&& com_sv_running && com_sv_running->integer && g_gametype->integer) {
&& com_sv_running && com_sv_running->integer && g_gametype->integer != GT_SINGLE_PLAYER) {
cmd = Cmd_Argv(1);
//
@@ -3013,14 +3051,14 @@ void CL_PingServers_f(void)
if (!noudp->integer) {
adr.type = NA_BROADCAST;
adr.port = BigShort(12203);
NET_OutOfBandPrint(NS_SERVER, adr, "info %i", 8);
CL_NET_OutOfBandPrint(adr, "info %i", 8);
}
noipx = Cvar_Get("noipx", "0", CVAR_INIT);
if (!noipx->integer) {
adr.type = NA_BROADCAST_IPX;
adr.port = BigShort(12203);
NET_OutOfBandPrint(NS_SERVER, adr, "info %i", 8);
CL_NET_OutOfBandPrint(adr, "info %i", 8);
}
for (i = 0; i < 16; i++) {
@@ -3035,7 +3073,7 @@ void CL_PingServers_f(void)
adr.port = BigShort(12203);
}
NET_OutOfBandPrint(NS_SERVER, adr, "info %i", 8);
CL_NET_OutOfBandPrint(adr, "info %i", 8);
} else {
Com_Printf("Bad address: %s\n", adrstring);
}
@@ -3549,7 +3587,7 @@ UI_WantsKeyboard
*/
void UI_WantsKeyboard()
{
cls.keyCatchers |= KEYCATCH_UI;
Key_SetCatcher(Key_GetCatcher() | KEYCATCH_UI);
}
struct widgettrans_s {
@@ -3712,102 +3750,6 @@ void CL_FillUIImports(void)
uii.GetConfigstring = CL_ConfigString;
uii.UI_CloseDMConsole = UI_CloseDMConsole;
#if 0
uii.TIKI_RegisterModel = TIKI_RegisterTiki;
uii.Cvar_Get = Cvar_Get;
uii.Argc = Cmd_Argc;
uii.Argv = Cmd_Argv;
uii.Cmd_ExecuteText = Cbuf_ExecuteText;
uii.FS_FOpenFile = FS_FOpenFileByMode;
uii.FS_Read = FS_Read;
uii.FS_Write = FS_Write;
uii.FS_FCloseFile = FS_FCloseFile;
uii.FS_GetFileList = FS_GetFileList;
uii.FS_Seek = FS_Seek;
uii.R_RegisterModel = re.RegisterModel;
uii.R_RegisterSkin = re.RegisterShader;
uii.R_RegisterShader = re.RegisterShader;
uii.R_RegisterShaderNoMip = re.RegisterShaderNoMip;
uii.R_ClearScene = re.ClearScene;
uii.R_AddRefEntityToScene = re.AddRefEntityToScene;
uii.R_AddPolyToScene = re.AddPolyToScene;
uii.R_AddLightToScene = re.AddLightToScene;
uii.R_RenderScene = re.RenderScene;
uii.R_SetColor = re.SetColor;
uii.R_DrawStretchPic = re.DrawStretchPic;
uii.UpdateScreen = SCR_UpdateScreen;
uii.S_StartLocalSound = S_StartLocalSound;
uii.S_RegisterSound = S_RegisterSound;
uii.Key_KeynumToStringBuf = Key_KeynumToStringBuf;
uii.Key_KeynumToString = Key_KeynumToString;
uii.Key_GetBindingBuf = Key_GetBindingBuf;
uii.Key_IsDown = Key_IsDown;
uii.Key_GetOverstrikeMode = Key_GetOverstrikeMode;
uii.Key_SetOverstrikeMode = Key_SetOverstrikeMode;
uii.Key_ClearStates = Key_ClearStates;
uii.Key_GetCatcher = Key_GetCatcher;
uii.Key_SetCatcher = Key_SetCatcher;
uii.GetClipboardData = CL_GetClipboardData;
uii.GetClientState = GetClientState;
uii.GetGlconfig = CL_GetGlconfig;
uii.GetConfigString = GetConfigString;
uii.LAN_GetServerCount = LAN_GetServerCount;
uii.LAN_GetServerAddressString = LAN_GetServerAddressString;
uii.LAN_GetServerInfo = LAN_GetServerInfo;
uii.LAN_GetPingQueueCount = LAN_GetPingQueueCount;
uii.LAN_ServerStatus = LAN_GetServerStatus;
uii.LAN_ClearPing = LAN_ClearPing;
uii.LAN_GetPing = LAN_GetPing;
uii.LAN_GetPingInfo = LAN_GetPingInfo;
uii.LAN_GetServerPing = LAN_GetServerPing;
uii.LAN_MarkServerVisible = LAN_MarkServerVisible;
uii.LAN_UpdateVisiblePings = LAN_UpdateVisiblePings;
uii.GetCDKey = CLUI_GetCDKey;
uii.SetCDKey = CLUI_SetCDKey;
uii.R_RegisterFont = re.RegisterFont;
uii.R_Text_Width = re.Text_Width;
uii.R_Text_Height = re.Text_Height;
uii.R_Text_Paint = re.Text_Paint;
uii.R_Text_PaintChar = re.Text_PaintChar;
uii.R_GetShaderName = re.GetShaderName;
uii.Cmd_Stuff = Cbuf_AddText;
uii.Cvar_GetString = CvarGetForUI;
uii.Cvar_Reset = Cvar_Reset;
uii.Cvar_Find = Cvar_FindVar;
uii.Cvar_Set = UI_Cvar_Set;
uii.File_PickFile = PickFile;
uii.File_FreeFile = FS_FreeFile;
uii.File_ListFiles = ListFilesForUI;
uii.File_OpenFile = FS_ReadFile;
uii.File_WriteFile = FS_WriteTextFile;
uii.Rend_SetColor = re.SetColor;
uii.Snd_PlaySound = UI_StartLocalSound;
uii.Snd_RegisterSound = UI_RegisterSound;
uii.Alias_Add = Alias_Add;
uii.Alias_FindRandom = Alias_FindRandom;
uii.Sys_Error = Com_Error;
uii.Sys_IsKeyDown = IsKeyDown;
uii.Sys_Milliseconds = Sys_Milliseconds;
uii.Sys_Printf = Com_Printf;
uii.Sys_DPrintf = Com_DPrintf;
uii.Sys_GetClipboard = Sys_GetWholeClipboard;
uii.Sys_SetClipboard = Sys_SetClipboard;
uii.Cmd_CompleteCommandByNumber = Cmd_CompleteCommandByNumber;
uii.Cvar_CompleteCvarByNumber = Cvar_CompleteVariableByNumber;
uii.UI_WantsKeyboard = UI_WantsKeyboard;
uii.Client_TranslateWidgetName = TranslateWidgetName;
uii.Connect = CL_Connect;
uii.Key_GetKeynameForCommand = Key_GetKeynameForCommand;
uii.Key_GetCommandForKey = Key_GetBinding;
uii.Key_SetBinding = Key_SetBinding;
uii.Key_GetKeysForCommand = Key_GetKeysForCommand;
uii.Key_KeynumToString = Key_KeynumToBindString;
uii.GetConfigstring = CL_ConfigString;
uii.UI_CloseDMConsole = UI_CloseDMConsole;
#endif
}
/*
@@ -3890,7 +3832,13 @@ void UI_ResolutionChange(void)
{
UIRect2D frame;
ui_compass_scale = Cvar_Get("ui_compass_scale", "0.75", CVAR_ARCHIVE | CVAR_LATCH);
if (com_target_game->integer >= TG_MOHTA) {
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);
}
CL_FillUIImports();
CL_FillUIDef();
@@ -3978,10 +3926,10 @@ void S_ServerLoaded(void)
S_TriggeredMusic_Stop();
s_bSoundPaused = qtrue;
S_ReLoad( &svs.soundSystem );
S_ReLoad(&svs.soundSystem);
if( svs.tm_filename[ 0 ] ) {
S_TriggeredMusic_SetupHandle( svs.tm_filename, svs.tm_loopcount, svs.tm_offset, 0 );
if (svs.tm_filename[0]) {
S_TriggeredMusic_SetupHandle(svs.tm_filename, svs.tm_loopcount, svs.tm_offset, 0);
}
}
@@ -4027,6 +3975,11 @@ void UI_ServerLoaded(void)
return;
}
if (ui_sCurrentLoadingMenu == "loading_default") {
UI_FinishLoadingScreen_f();
return;
}
server_loading_waiting = qtrue;
event = new Event(EV_Widget_Enable);
@@ -4322,7 +4275,7 @@ public:
void UpdateStats(Event *ev);
};
Event EV_StatsUpdater_UpdateStats;
Event EV_StatsUpdater_UpdateStats("updatestats", EV_DEFAULT, NULL, NULL, "Update the stats on the missionLog");
CLASS_DECLARATION(Listener, StatsUpdater, NULL) {
{NULL, NULL}
@@ -4733,7 +4686,7 @@ CL_FinishedIntro
*/
qboolean CL_FinishedIntro(void)
{
return !cls.startStage;
return cls.startStage == 0;
}
/*
@@ -4743,7 +4696,87 @@ CL_FinishedStartStage
*/
void CL_FinishedStartStage(void)
{
// FIXME: stub
int wait;
switch (cls.startStage++) {
case 1:
Cbuf_ExecuteText(EXEC_NOW, "cinematic EAlogo.RoQ\n");
break;
case 2:
intro_stage.alpha_start = 0.0;
intro_stage.alpha_end = 1.0;
wait = ui_titlescreen_fadein->value * 1000.0;
intro_stage.fadetime = wait;
intro_stage.starttime = cls.realtime;
intro_stage.endtime = cls.realtime + wait;
intro_stage.material = uWinMan.RegisterShader("mohaa_title");
break;
case 3:
intro_stage.alpha_start = 1.0;
intro_stage.alpha_end = 1.0;
wait = ui_legalscreen_stay->value * 1000.0;
intro_stage.fadetime = 0.0;
intro_stage.starttime = cls.realtime;
intro_stage.endtime = cls.realtime + wait;
break;
case 4:
intro_stage.alpha_start = 1.0;
intro_stage.alpha_end = 0.0;
wait = ui_titlescreen_fadeout->value * 1000.0;
intro_stage.fadetime = wait;
intro_stage.starttime = cls.realtime;
intro_stage.endtime = cls.realtime + wait;
break;
case 5:
intro_stage.alpha_start = 0.0;
intro_stage.alpha_end = 1.0;
wait = ui_legalscreen_fadein->value * 1000.0;
intro_stage.fadetime = wait;
intro_stage.starttime = cls.realtime;
intro_stage.endtime = cls.realtime + wait;
intro_stage.material = uWinMan.RegisterShader("legal");
break;
case 6:
intro_stage.alpha_start = 1.0;
intro_stage.alpha_end = 1.0;
wait = ui_legalscreen_stay->value * 1000.0;
intro_stage.fadetime = 0.0;
intro_stage.starttime = cls.realtime;
intro_stage.endtime = cls.realtime + wait;
break;
case 7:
intro_stage.alpha_start = 1.0;
intro_stage.alpha_end = 0.0;
wait = ui_legalscreen_fadeout->value * 1000.0;
intro_stage.fadetime = wait;
intro_stage.starttime = cls.realtime;
intro_stage.endtime = cls.realtime + wait;
break;
case 8:
if (com_target_game->integer >= target_game_e::TG_MOHTA) {
cls.startStage = 0;
return;
}
Cbuf_ExecuteText(EXEC_NOW, "cinematic 2015intro.RoQ\n");
break;
case 9:
Cbuf_ExecuteText(EXEC_NOW, "cinematic intro.RoQ\n");
break;
case 10:
cls.startStage = 0;
break;
default:
break;
}
}
/*
@@ -4759,9 +4792,6 @@ void UI_StartStageKeyEvent(void)
SCR_StopCinematic();
}
break;
case 12:
SCR_StopCinematic();
break;
case 3:
case 4:
case 5:
@@ -4780,11 +4810,9 @@ void UI_StartStageKeyEvent(void)
break;
case 9:
case 10:
case 11:
if (ui_skip_legalscreen->integer) {
cls.startStage = 11;
CL_FinishedStartStage();
}
SCR_StopCinematic();
break;
default:
break;
}
}
@@ -4812,8 +4840,8 @@ void CL_TryStartIntro(void)
UI_ToggleConsole();
} else {
// FIXME: no intro from now
//Cvar_Set( cl_playintro->name, "0" );
//UI_StartIntro_f();
Cvar_Set(cl_playintro->name, "0");
UI_StartIntro_f();
}
}
@@ -4974,6 +5002,20 @@ void UI_HideStatistics_f()
statsUpdater.CancelEventsOfType(EV_StatsUpdater_UpdateStats);
}
/*
====================
UI_SalesScreen_f
====================
*/
void UI_SalesScreen_f()
{
if (random() > 0.5) {
Cbuf_AddText("pushmenu sales_splash1\n");
} else {
Cbuf_AddText("pushmenu sales_splash2\n");
}
}
/*
====================
CL_ShutdownUI
@@ -5169,7 +5211,7 @@ void CL_InitializeUI(void)
ui_success = Cvar_Get("ui_success", "0", 0);
ui_failed = Cvar_Get("ui_failed", "0", 0);
ui_returnmenu = Cvar_Get("ui_returnmenu", "0", 0);
ui_skip_eamovie = Cvar_Get("ui_skip_eamovie", "0", 0);
ui_skip_eamovie = Cvar_Get("ui_skip_eamovie", "1", 0);
ui_skip_titlescreen = Cvar_Get("ui_skip_titlescreen", "1", 0);
ui_skip_legalscreen = Cvar_Get("ui_skip_legalscreen", "1", 0);
ui_titlescreen_fadein = Cvar_Get("ui_titlescreen_fadein", "1", 0);
@@ -5244,6 +5286,7 @@ void CL_InitializeUI(void)
Cmd_AddCommand("-statistics", UI_HideStatistics_f);
Cmd_AddCommand("setreturnmenu", UI_SetReturnMenuToCurrent);
Cmd_AddCommand("gotoreturnmenu", UI_PushReturnMenu_f);
Cmd_AddCommand("salesscreen", UI_SalesScreen_f);
if (developer->integer) {
UColor bgColor;
@@ -5365,6 +5408,10 @@ void CL_InitializeUI(void)
CL_ClearButtons();
cls.uiStarted = qtrue;
if (!com_dedicated->integer) {
CL_TryStartIntro();
}
}
static char **loadStrings;
@@ -5402,7 +5449,16 @@ void UI_BeginLoadResource(void)
UI_EndLoadResource
====================
*/
void UI_EndLoadResource(void) {}
void UI_EndLoadResource(void)
{
clock_t time;
time = clock() - (((clock_t)startCountHigh << 32) | startCountLow) + (((clock_t)loadCountHigh << 32) | loadCountLow);
loadCountHigh = time >> 32;
loadCountLow = time;
loadCount = time >> 25;
}
/*
====================
@@ -5468,19 +5524,17 @@ void UI_RegisterLoadResource(const char *name)
high = loadNumber - 1;
while (low <= high) {
i = (high + low) / 2;
i = (low + high) / 2;
j = strcmp(name, loadStrings[i]);
if (j >= 0) {
if (j <= 0) {
currentLoadTime += loadTimes[i];
loadTimes[i] = 0;
return;
}
if (j < 0) {
high = i - 1;
} else if (j > 0) {
low = i + 1;
} else {
high = i - 1;
currentLoadTime += loadTimes[i];
loadTimes[i] = 0;
break;
}
}
}
@@ -5493,12 +5547,19 @@ UI_TestUpdateScreen
void UI_TestUpdateScreen(unsigned int timeout)
{
unsigned int newTime = Sys_Milliseconds();
unsigned int startRenderTime, endRenderTime;
if (newTime - lastTime >= timeout) {
lastTime = newTime;
Sys_PumpMessageLoop();
SCR_UpdateScreen();
if (timeout > 0 && (newTime - lastTime) < (timeout + updateTime)) {
return;
}
startRenderTime = Sys_Milliseconds();
Sys_PumpMessageLoop();
SCR_UpdateScreen();
endRenderTime = Sys_Milliseconds();
updateTime = Q_min(endRenderTime - startRenderTime, 1000);
lastTime = endRenderTime;
}
/*
@@ -5536,7 +5597,7 @@ void UI_LoadResource(const char *name)
Cvar_SetValue("loadingbar", (float)currentLoadTime / (float)totalLoadTime);
}
UI_TestUpdateScreen(333u);
UI_TestUpdateScreen(33);
}
/*
@@ -5812,12 +5873,12 @@ void UI_EndLoad(void)
}
file = FS_FOpenFileWrite(loadName);
sprintf(buf, "%d\n%d %d\n", 3, loadNumber, size);
Com_sprintf(buf, sizeof(buf), "%d\n%d %d\n", 3, loadNumber, size);
FS_Write(buf, strlen(buf), file);
for (i = 0; i < loadNumber; i++) {
sprintf(buf, "%s\n%d\n", base[i]->name, base[i]->loadCount);
Com_sprintf(buf, sizeof(buf), "%s\n%d\n", base[i]->name, base[i]->loadCount);
FS_Write(buf, strlen(buf), file);
}
+4 -1
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
Copyright (C) 2023-2024 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -35,6 +35,7 @@ typedef struct {
extern cvar_t *ui_health_start;
extern cvar_t *ui_health_end;
extern cvar_t *sound_overlay;
extern cvar_t *cl_movieaudio;
//
// initialization
@@ -55,6 +56,7 @@ const char *CvarGetForUI(const char *name, const char *defval);
void UI_ClearState(void);
void CL_BeginRegistration(void);
void CL_EndRegistration(void);
float UI_GetObjectivesTop(void);
//
// menu
@@ -111,6 +113,7 @@ void UI_DeleteScoreBoardItems(int iMaxIndex);
void UI_BeginLoad(const char *pszMapName);
void UI_EndLoad(void);
void UI_AbortLoad(void);
int CL_FontStringWidth(fontheader_t* pFont, const char* pszString, int iMaxLen);
void UI_BeginLoadResource(void);
void UI_EndLoadResource(void);
void UI_EndLoadResource(const char *name);
+28 -1
View File
@@ -61,6 +61,7 @@ UIDMBox::UIDMBox()
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 )
@@ -278,6 +279,28 @@ float UIDMBox::PrintWrap( UIFont *font, float x, float y, str text )
float UIDMBox::DrawItem( item_t *in, float x, float y, float alpha )
{
if (m_drawoutline) {
//
// Draw an outline
//
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);
}
in->font->setColor(in->color);
in->font->setAlpha(alpha);
@@ -316,7 +339,11 @@ void UIDMBox::Print( const char *text )
}
else if (*text == MESSAGE_CHAT_GREEN)
{
m_items[m_numitems].color = UGreen;
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;
+4 -5
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2015-2024 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -20,8 +20,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __CL_UIDMBOX_H__
#define __CL_UIDMBOX_H__
#pragma once
static constexpr unsigned int DMBOX_ITEM_FLAG_BOLD = 2u;
static constexpr unsigned int DMBOX_ITEM_FLAG_DEATH = 4u;
@@ -47,6 +46,8 @@ protected:
int m_movespeed;
int m_iBeginDecay;
int m_iEndDecay;
// Added in OPM
bool m_drawoutline;
public:
CLASS_PROTOTYPE( UIDMBox );
@@ -75,5 +76,3 @@ public:
void setRealShow( bool b );
void Clear( void );
};
#endif /* __CL_UIDMBOX_H__ */
+4 -2
View File
@@ -104,8 +104,10 @@ void FilePickerClass::Initialize(
currentDirectory += "/";
}
extension = ext;
ignoredFiles = ignore_files;
extension = ext;
if (ignore_files) {
ignoredFiles = ignore_files;
}
SetupFiles();
}
+23
View File
@@ -61,6 +61,7 @@ UIGMBox::UIGMBox()
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 )
@@ -272,6 +273,28 @@ float UIGMBox::PrintWrap( UIFont *font, float x, float y, str text )
float UIGMBox::DrawItem( item_t *in, float x, float y, float alpha )
{
if (m_drawoutline) {
//
// Draw an outline
//
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);
}
in->font->setColor(in->color);
in->font->setAlpha(alpha);
+4 -5
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2015-2024 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -20,8 +20,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __CL_UIGMBOX_H__
#define __CL_UIGMBOX_H__
#pragma once
static constexpr unsigned int GMBOX_ITEM_FLAG_BOLD = 1u;
@@ -44,6 +43,8 @@ protected:
int m_movespeed;
int m_iBeginDecay;
int m_iEndDecay;
// Added in OPM
bool m_drawoutline;
public:
CLASS_PROTOTYPE( UIGMBox );
@@ -72,5 +73,3 @@ public:
void setRealShow( bool b );
void Clear( void );
};
#endif
+25 -11
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
Copyright (C) 2023-2024 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -25,12 +25,12 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
class LANGameItem : public UIListCtrlItem
{
str strings[5];
str strings[6];
public:
LANGameItem();
LANGameItem(
const str& hostName, const str& mapName, const str& players, const str& gameTypeString, const str& ping
const str& hostName, const str& mapName, const str& players, const str& gameTypeString, const str& ping, const str& ipAddress
);
int getListItemValue(int which) const override;
@@ -65,6 +65,11 @@ UILANGameClass::UILANGameClass()
m_iLastUpdateTime = 0;
m_noservers_mat = uWinMan.RegisterShader("textures/menu/noservers");
//
// Added in OPM
//
m_bVirtual = false;
}
void UILANGameClass::Draw(void)
@@ -102,11 +107,12 @@ void UILANGameClass::UpdateUIElement(void)
width = getClientFrame().size.width - 16.f;
AddColumn(Sys_LV_CL_ConvertString("Server Name"), 0, width * 0.4f, false, false);
AddColumn(Sys_LV_CL_ConvertString("Map"), 1, width * 0.15f, false, false);
AddColumn(Sys_LV_CL_ConvertString("Players"), 2, width * 0.165f, true, true);
AddColumn(Sys_LV_CL_ConvertString("GameType"), 3, width * 0.22f, false, false);
AddColumn(Sys_LV_CL_ConvertString("Ping"), 4, width * 0.065f, true, false);
AddColumn(Sys_LV_CL_ConvertString("Server Name"), 0, width * 0.27f, false, false); // was 0.4
AddColumn(Sys_LV_CL_ConvertString("Map"), 1, width * 0.12f, false, false); // was 0.15
AddColumn(Sys_LV_CL_ConvertString("Players"), 2, width * 0.08f, true, true); // was 0.165
AddColumn(Sys_LV_CL_ConvertString("GameType"), 3, width * 0.118f, false, false); // was 0.22
AddColumn(Sys_LV_CL_ConvertString("Ping"), 4, width * 0.052f, true, false); // was 0.065
AddColumn(Sys_LV_CL_ConvertString("IP"), 5, width * 0.36f, false, false); // Added in OPM
uWinMan.ActivateControl(this);
@@ -134,7 +140,9 @@ void UILANGameClass::SetupServers(void)
pServerInfo->mapName,
va("%02i/%02i", pServerInfo->clients, pServerInfo->maxClients),
pServerInfo->gameTypeString,
str(pServerInfo->ping)
str(pServerInfo->ping),
// Added in OPM
NET_AdrToStringwPort(pServerInfo->adr)
);
}
@@ -167,7 +175,7 @@ void UILANGameClass::JoinServer(Event *ev)
const serverInfo_t& serverInfo = cls.localServers[getCurrentItem() - 1];
UI_SetReturnMenuToCurrent();
CL_Connect(NET_AdrToString(serverInfo.adr), netadrtype_t::NA_UNSPEC);
CL_Connect(NET_AdrToStringwPort(serverInfo.adr), netadrtype_t::NA_UNSPEC);
}
qboolean UILANGameClass::KeyEvent(int key, unsigned int time)
@@ -197,7 +205,7 @@ qboolean UILANGameClass::KeyEvent(int key, unsigned int time)
LANGameItem::LANGameItem() {}
LANGameItem::LANGameItem(
const str& hostName, const str& mapName, const str& players, const str& gameTypeString, const str& ping
const str& hostName, const str& mapName, const str& players, const str& gameTypeString, const str& ping, const str& ipAddress
)
{
strings[0] = hostName;
@@ -205,6 +213,12 @@ LANGameItem::LANGameItem(
strings[2] = players;
strings[3] = gameTypeString;
strings[4] = ping;
//
// Added in OPM
//
strings[5] = ipAddress;
}
int LANGameItem::getListItemValue(int which) const
+2 -2
View File
@@ -95,7 +95,7 @@ UIFAKKLoadGameClass::UIFAKKLoadGameClass()
{
Connect(this, EV_UIListBase_ItemDoubleClicked, EV_UIListBase_ItemDoubleClicked);
Connect(this, EV_UIListBase_ItemSelected, EV_UIListBase_ItemSelected);
AllowActivate(false);
AllowActivate(true);
m_bRemovePending = false;
setHeaderFont("facfont-20");
@@ -287,7 +287,7 @@ qboolean UIFAKKLoadGameClass::KeyEvent(int key, unsigned int time)
}
break;
default:
return UIListBase::KeyEvent(key, time);
return UIListCtrl::KeyEvent(key, time);
}
return qfalse;
+28 -20
View File
@@ -76,7 +76,7 @@ void UIMapRotationListBox::PopulateRotationList()
maplistVar = Cvar_Get("ui_maplist_ffa", "", 0);
}
strcpy(mapBuffer, maplistVar->string);
Q_strncpyz(mapBuffer, maplistVar->string, sizeof(mapBuffer));
for (token = strtok(mapBuffer, " /"); token; token = strtok(NULL, " /")) {
if (!Q_stricmp(token, "dm")) {
@@ -143,7 +143,7 @@ void UIMapListBox::PopulateMapList()
bool bHasTOW = false;
bool bHasLib = false;
strcpy(mapName, filename);
Q_strncpyz(mapName, filename, sizeof(mapName));
mapName[strlen(mapName) - 4] = 0;
if (!COM_IsMapValid(mapName)) {
@@ -151,7 +151,7 @@ void UIMapListBox::PopulateMapList()
}
if (bTugOfWar || bLiberation) {
strcpy(tokenized, mapName);
Q_strncpyz(tokenized, mapName, sizeof(tokenized));
for (token = strtok(tokenized, "_"); token; token = strtok(NULL, "_")) {
if (bLiberation) {
@@ -181,7 +181,7 @@ void UIMapListBox::PopulateMapList()
}
}
} else if (bObjective) {
strcpy(tokenized, mapName);
Q_strncpyz(tokenized, mapName, sizeof(tokenized));
for (token = strtok(tokenized, "_"); token; token = strtok(NULL, "_")) {
if (!Q_stricmp(token, "obj")) {
@@ -209,9 +209,9 @@ void UIMapListBox::PopulateMapList()
char mapName[256];
char tokenized[256];
strcpy(mapName, filename);
Q_strncpyz(mapName, filename, sizeof(mapName));
mapName[strlen(mapName) - 4] = 0;
strcpy(tokenized, mapName);
Q_strncpyz(tokenized, mapName, sizeof(tokenized));
token = strtok(tokenized, "_");
if (!Q_stricmp(token, "obj") || !Q_stricmp(mapName, "mp_ship_lib")) {
@@ -237,7 +237,7 @@ void UIMapListBox::PopulateMapList()
const char *filename = filenames[i];
char mapName[256];
strcpy(mapName, filename);
Q_strncpyz(mapName, filename, sizeof(mapName));
mapName[strlen(mapName) - 4] = 0;
if (!COM_IsMapValid(mapName)) {
@@ -277,20 +277,27 @@ void UIAddToRotationButton::Released(Event *ev)
if (mapList && rotationList) {
size_t mapLength = 0;
int item = mapList->getCurrentItem();
int item = mapList->getCurrentItem();
str currentItemText;
if (item) {
currentItemText = mapList->getItemText(item);
}
for (i = 1; i <= rotationList->getNumItems(); i++) {
str text = rotationList->getItemText(i);
if (text == currentItemText) {
// Added in OPM
// Prevent adding duplicates
item = 0;
break;
}
mapLength += text.length();
}
if (item) {
str text = mapList->getItemText(item);
if (prefixLength + mapLength + text.length() < 256) {
rotationList->AddItem(text, NULL);
}
if (item && prefixLength + mapLength + currentItemText.length() < 256) {
rotationList->AddItem(currentItemText, NULL);
}
}
@@ -356,7 +363,7 @@ void UIRotationApplyButton::Released(Event *ev)
char map[256];
bool bHasTOW = false, bHasObj = false, bHasLib = false, bHasShip = false;
strcpy(map, text);
Q_strncpyz(map, text, sizeof(map));
for (token = strtok(map, "_"); token; token = strtok(NULL, "_")) {
if (!Q_stricmp(token, "TOW")) {
bHasTOW = true;
@@ -387,11 +394,12 @@ void UIRotationApplyButton::Released(Event *ev)
}
maplistStr += text;
maplistStr += " ";
if (i == 1) {
Cvar_Set("ui_dmmap", maplistStr);
}
maplistStr += " ";
}
}
@@ -413,10 +421,10 @@ void UIRotationMoveItemUpButton::Released(Event *ev)
list = static_cast<UIListBox *>(uWinMan.FindWidget("Rotation List"));
item = list->getCurrentItem();
if (item < list->getNumItems() && list->getNumItems() > 1) {
str text = list->getItemText(item + 1);
if (item > 1 && list->getNumItems() > 1) {
str text = list->getItemText(item - 1);
list->DeleteItem(list->getCurrentItem() - 1);
list->DeleteItem(item - 1);
list->InsertItem(text, item);
list->setCurrentItem(item - 1);
}
@@ -440,7 +448,7 @@ void UIRotationMoveItemDownButton::Released(Event *ev)
if (item < list->getNumItems() && list->getNumItems() > 1) {
str text = list->getItemText(item + 1);
list->DeleteItem(list->getCurrentItem() + 1);
list->DeleteItem(item + 1);
list->InsertItem(text, item);
list->setCurrentItem(item + 1);
}
+1 -1
View File
@@ -83,7 +83,7 @@ void PickFile(const char *name, Listener *obj, Event& event)
if (name && *name && strchr(name, '/')) {
currentpath = name;
for (i = currentpath.length(); i > 0; i--) {
for (i = currentpath.length() - 1; i > 0; i--) {
if (currentpath[i] == '/') {
break;
}
+14 -11
View File
@@ -58,7 +58,7 @@ void UIRadar::Draw(void)
float inv;
float iconSize;
int blinkTime, speakTime;
float origin[2], axis[2];
vec2_t origin, axis;
float halfScale;
int i;
@@ -105,17 +105,17 @@ void UIRadar::Draw(void)
halfScale = iconSize * 0.5f;
for (i = 0; i < MAX_CLIENTS; i++) {
float delta[2];
float newOrg[2];
float screenOrg[2];
float length;
vec2_t delta;
vec2_t newOrg;
vec2_t screenOrg;
float length;
radar = &g_radarClients[i];
if (i == g_radarClientNum) {
continue;
}
if (!g_radarClients[i].time) {
if (!radar->time) {
continue;
}
@@ -128,10 +128,13 @@ void UIRadar::Draw(void)
// make the icon blink
if (delta >= 0 && delta < speakTime && ((delta / blinkTime) % 2) == 0) {
continue;
}
if (delta < 0 || delta >= speakTime) {
radar->lastSpeakTime = 0;
}
}
radar->lastSpeakTime = 0;
delta[0] = radar->origin[0] - origin[0];
delta[1] = radar->origin[1] - origin[1];
newOrg[0] = -(delta[0] * axis[0] + delta[1] * axis[1]) * inv;
@@ -140,12 +143,12 @@ void UIRadar::Draw(void)
if (length > 1)
{
newOrg[0] = -(delta[0] * axis[0] + delta[1] * axis[1]) * inv * (1.f / length);
newOrg[1] = (delta[0] * axis[1] + delta[1] * -axis[0]) * inv * (1.f / length);
newOrg[0] *= 1.f / length;
newOrg[1] *= 1.f / length;
}
screenOrg[0] = -((halfScale * (1.141f * newOrg[1] + m_vVirtualScale[0])) - ((1.f + newOrg[1]) * 0.5f * m_frame.size.width));
screenOrg[1] = -((halfScale * (1.141f * newOrg[0] + m_vVirtualScale[1])) - ((1.f + newOrg[0]) * 0.5f * m_frame.size.height));
screenOrg[0] = -((halfScale * (1.414f * newOrg[1] + m_vVirtualScale[0])) - ((1.f + newOrg[1]) * 0.5f * m_frame.size.width));
screenOrg[1] = -((halfScale * (1.414f * newOrg[0] + m_vVirtualScale[1])) - ((1.f + newOrg[0]) * 0.5f * m_frame.size.height));
uii.Rend_DrawPicStretched2(
screenOrg[0],
+11 -1
View File
@@ -651,6 +651,9 @@ static void AddFilter(char* filter, const char* value) {
void UIFAKKServerList::CancelRefresh( Event *ev )
{
ServerListHalt(m_serverList[0]);
if (m_serverList[1]) {
ServerListHalt(m_serverList[1]);
}
}
void UIFAKKServerList::NewServerList( void )
@@ -1037,6 +1040,7 @@ void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, v
{
const char* pszHostName;
bool bDiffVersion;
bool bIsDemo;
str sServerName;
str sPlayers;
const char* pszGameVer;
@@ -1044,12 +1048,14 @@ void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, v
pszHostName = ServerGetStringValue(server, "hostname", "(NONE)");
bDiffVersion = false;
bIsDemo = false;
pszGameVer = ServerGetStringValue(server, "gamever", "1.00");
pszGameVerNumber = pszGameVer;
if (pszGameVerNumber[0] == 'd') {
// demo server
pszGameVerNumber++;
bIsDemo = true;
}
if (com_target_game->integer >= target_game_e::TG_MOHTT) {
@@ -1074,7 +1080,11 @@ void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, v
}
}
// always show the version
sServerName = va(" (%s) %s", pszGameVer, pszHostName);
if (!bIsDemo) {
sServerName = va(" (%s) %s", pszGameVerNumber, pszHostName);
} else {
sServerName = va(" (d%s) %s", pszGameVerNumber, pszHostName);
}
iRealIP = inet_addr(ServerGetAddress(server));
iPort = ServerGetIntValue(server, "hostport", PORT_SERVER);
+83 -7
View File
@@ -439,8 +439,10 @@ void UIFakkLabel::LayoutRenderModelAnim(Event *ev)
void UIFakkLabel::DrawStatbar(float frac)
{
vec4_t col;
float alpha;
vec4_t col;
float alpha;
qhandle_t hMat;
float w, h;
col[0] = col[1] = col[2] = col[3] = 1.0;
@@ -475,11 +477,7 @@ void UIFakkLabel::DrawStatbar(float frac)
m_lastfrac = frac;
alpha = 1.0 - ((float)uid.time - m_flashtime) / 1500.0;
if (alpha < 0.0) {
alpha = 0.0;
} else if (alpha > 1.0) {
alpha = 1.0;
}
alpha = Q_clamp_float(alpha, 0, 1);
col[3] = alpha;
@@ -496,6 +494,24 @@ void UIFakkLabel::DrawStatbar(float frac)
re.SetColor(col);
re.DrawTilePic(0.0, 0.0, width, m_frame.size.height, m_statbar_material_flash->GetMaterial());
}
if (m_statbar_material_marker) {
hMat = m_statbar_material_marker->GetMaterial();
w = re.GetShaderWidth(hMat);
h = re.GetShaderHeight(hMat);
re.DrawStretchPic(
m_frame.size.width * frac - w * 0.5,
m_frame.size.height * 0.5 - h * 0.5,
w,
h,
0,
0,
1,
1,
hMat
);
}
break;
}
case L_STATBAR_VERTICAL:
@@ -513,6 +529,24 @@ void UIFakkLabel::DrawStatbar(float frac)
0.0, y, m_frame.size.width, m_frame.size.height, m_statbar_material_flash->GetMaterial()
);
}
if (m_statbar_material_marker) {
hMat = m_statbar_material_marker->GetMaterial();
w = re.GetShaderWidth(hMat);
h = re.GetShaderHeight(hMat);
re.DrawStretchPic(
m_frame.size.width * frac - w * 0.5,
m_frame.size.height * 0.5 - h * 0.5,
w,
h,
0,
0,
1,
1,
hMat
);
}
break;
}
default:
@@ -542,6 +576,24 @@ void UIFakkLabel::DrawStatbar(float frac)
m_statbar_material_flash->GetMaterial()
);
}
if (m_statbar_material_marker) {
hMat = m_statbar_material_marker->GetMaterial();
w = re.GetShaderWidth(hMat);
h = re.GetShaderHeight(hMat);
re.DrawStretchPic(
m_frame.size.width * frac - w * 0.5,
m_frame.size.height * 0.5 - h * 0.5,
w,
h,
0,
0,
1,
1,
hMat
);
}
break;
}
case L_STATBAR_VERTICAL:
@@ -569,6 +621,24 @@ void UIFakkLabel::DrawStatbar(float frac)
m_statbar_material_flash->GetMaterial()
);
}
if (m_statbar_material_marker) {
hMat = m_statbar_material_marker->GetMaterial();
w = re.GetShaderWidth(hMat);
h = re.GetShaderHeight(hMat);
re.DrawStretchPic(
m_frame.size.width * frac - w * 0.5,
m_frame.size.height * 0.5 - h * 0.5,
w,
h,
0,
0,
1,
1,
hMat
);
}
break;
}
case L_STATBAR_VERTICAL_REVERSE:
@@ -1393,6 +1463,12 @@ void UIFakkLabel::Draw(void)
return;
}
if (cl.snap.ps.activeItems[m_itemindex] < 0 || cl.snap.ps.activeItems[m_itemindex] >= MAX_WEAPONS) {
// Fixed in OPM
// Make sure to not overflow configstrings
return;
}
m_font->setColor(m_foreground_color);
if (m_bOutlinedText) {
File diff suppressed because it is too large. Load diff
+3
View File
@@ -51,6 +51,9 @@ protected:
void OnDeactivate(Event *ev);
void DrawSubtitleOverlay(void);
// Added in 2.0
void DrawNetProfile(void);
public:
View3D();
+72 -7
View File
@@ -36,6 +36,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cl_curl.h"
#endif /* USE_CURL */
#ifdef USE_VOIP
#include <opus.h>
#endif
// file full of random crap that gets used to create cl_guid
#define QKEY_FILE "qkey"
#define QKEY_SIZE 2048
@@ -174,6 +178,7 @@ typedef struct {
int lastPacketSentTime; // for retransmits during connection
int lastPacketTime; // for timeouts
char servername[MAX_OSPATH]; // name of server from original connect (used by reconnect)
netadr_t serverAddress;
int connectTime; // for connection retransmits
int connectStartTime;
@@ -239,15 +244,42 @@ typedef struct {
int timeDemoMaxDuration; // maximum frame duration
unsigned char timeDemoDurations[ MAX_TIMEDEMO_DURATIONS ]; // log of frame durations
float aviVideoFrameRemainder;
float aviSoundFrameRemainder;
#ifdef USE_VOIP
qboolean voipEnabled;
qboolean voipCodecInitialized;
// incoming data...
// !!! FIXME: convert from parallel arrays to array of a struct.
OpusDecoder *opusDecoder[MAX_CLIENTS];
byte voipIncomingGeneration[MAX_CLIENTS];
int voipIncomingSequence[MAX_CLIENTS];
float voipGain[MAX_CLIENTS];
qboolean voipIgnore[MAX_CLIENTS];
qboolean voipMuteAll;
// outgoing data...
// if voipTargets[i / 8] & (1 << (i % 8)),
// then we are sending to clientnum i.
uint8_t voipTargets[(MAX_CLIENTS + 7) / 8];
uint8_t voipFlags;
OpusEncoder *opusEncoder;
int voipOutgoingDataSize;
int voipOutgoingDataFrames;
int voipOutgoingSequence;
byte voipOutgoingGeneration;
byte voipOutgoingData[1024];
float voipPower;
#endif
#ifdef LEGACY_PROTOCOL
qboolean compat;
#endif
// big stuff at end of structure so most offsets are 15 bits or less
netchan_t netchan;
float aviVideoFrameRemainder;
float aviSoundFrameRemainder;
} clientConnection_t;
extern clientConnection_t clc;
@@ -297,8 +329,6 @@ typedef struct {
qboolean cddialog; // bring up the cd needed dialog next frame
qboolean no_menus;
char servername[MAX_OSPATH]; // name of server from original connect (used by reconnect)
// when the server clears the hunk, all of these must be restarted
qboolean rendererRegistered;
qboolean cgameStarted;
@@ -353,8 +383,8 @@ typedef struct {
void* savedCgameState;
size_t savedCgameStateSize;
char gcdResponse[73];
int unknown3_0;
int currentRate;
// Added in 2.0
netprofclient_t netprofile;
qhandle_t charSetShader;
qhandle_t whiteShader;
qhandle_t consoleShader;
@@ -385,6 +415,8 @@ extern cvar_t *cl_connect_timeout;
extern cvar_t *cl_maxpackets;
extern cvar_t *cl_packetdup;
extern cvar_t *cl_shownet;
extern cvar_t *cl_netprofile;
extern cvar_t *cl_netprofileoverlay;
extern cvar_t *cl_showSend;
extern cvar_t *cl_timeNudge;
extern cvar_t *cl_showTimeDelta;
@@ -445,6 +477,32 @@ extern cvar_t *cl_r_fullscreen;
extern cvar_t *cl_consoleKeys;
#ifdef USE_MUMBLE
extern cvar_t *cl_useMumble;
extern cvar_t *cl_mumbleScale;
#endif
#ifdef USE_VOIP
// cl_voipSendTarget is a string: "all" to broadcast to everyone, "none" to
// send to no one, or a comma-separated list of client numbers:
// "0,7,2,23" ... an empty string is treated like "all".
extern cvar_t *cl_voipUseVAD;
extern cvar_t *cl_voipVADThreshold;
extern cvar_t *cl_voipSend;
extern cvar_t *cl_voipSendTarget;
extern cvar_t *cl_voipGainDuringCapture;
extern cvar_t *cl_voipCaptureMult;
extern cvar_t *cl_voipShowMeter;
extern cvar_t *cl_voip;
// 20ms at 48k
#define VOIP_MAX_FRAME_SAMPLES ( 20 * 48 )
// 3 frame is 60ms of audio, the max opus will encode at once
#define VOIP_MAX_PACKET_FRAMES 3
#define VOIP_MAX_PACKET_SAMPLES ( VOIP_MAX_FRAME_SAMPLES * VOIP_MAX_PACKET_FRAMES )
#endif
extern cvar_t *cg_gametype;
extern cvar_t* j_pitch;
@@ -520,6 +578,7 @@ void IN_MouseOn( void );
void IN_MouseOff( void );
void CL_InitInput (void);
void CL_ShutdownInput(void);
void CL_SendCmd (void);
void CL_ClearState (void);
void CL_ReadPackets (void);
@@ -545,6 +604,10 @@ extern int cl_connectedToPureServer;
extern int cl_connectedToCheatServer;
extern msg_t *cl_currentMSG;
#ifdef USE_VOIP
void CL_Voip_f( void );
#endif
void CL_SystemInfoChanged( void );
void CL_ParseServerMessage( msg_t *msg );
@@ -583,6 +646,7 @@ void Con_DrawCharacter (int cx, int line, int num);
void Con_CheckResize (void);
void Con_Init (void);
void Con_Shutdown (void);
void Con_Clear_f (void);
void Con_ToggleConsole_f (void);
void Con_DrawNotify (void);
@@ -670,6 +734,7 @@ void LAN_SaveServersToCache( void );
void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg); //int length, const byte *data );
void CL_Netchan_TransmitNextFragment( netchan_t *chan );
qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg );
void CL_NET_OutOfBandPrint( netadr_t adr, const char* format, ... );
//
// cl_avi.c
+25
View File
@@ -592,4 +592,29 @@ void S_ReLoad(soundsystemsavegame_t* pSave) {
// FIXME: unimplemented
}
/*
==============
S_StopMovieAudio
==============
*/
void S_StopMovieAudio() {
}
/*
==============
S_CurrentMoviePosition
==============
*/
int S_CurrentMoviePosition() {
return 0;
}
/*
==============
S_SetupMovieAudio
==============
*/
void S_SetupMovieAudio(const char* pszMovieName) {
}
#endif
+4
View File
@@ -86,6 +86,10 @@ const char* S_GetMusicFilename();
int S_GetMusicLoopCount();
unsigned int S_GetMusicOffset();
void S_StopMovieAudio();
int S_CurrentMoviePosition();
void S_SetupMovieAudio(const char* pszMovieName);
#ifdef __cplusplus
}
#endif
+7 -7
View File
@@ -161,12 +161,12 @@ void S_Base_SoundList( void ) {
char type[4][16];
char mem[2][16];
strcpy(type[0], "16bit");
strcpy(type[1], "adpcm");
strcpy(type[2], "daub4");
strcpy(type[3], "mulaw");
strcpy(mem[0], "paged out");
strcpy(mem[1], "resident ");
Q_strncpyz(type[0], "16bit", sizeof(type[0]));
Q_strncpyz(type[1], "adpcm", sizeof(type[1]));
Q_strncpyz(type[2], "daub4", sizeof(type[2]));
Q_strncpyz(type[3], "mulaw", sizeof(type[3]));
Q_strncpyz(mem[0], "paged out", sizeof(mem[0]));
Q_strncpyz(mem[1], "resident ", sizeof(mem[1]));
total = 0;
for (sfx=s_knownSfx, i=0 ; i<s_numSfx ; i++, sfx++) {
size = sfx->soundLength;
@@ -303,7 +303,7 @@ static sfx_t *S_FindName( const char *name ) {
sfx = &s_knownSfx[i];
Com_Memset (sfx, 0, sizeof(*sfx));
strcpy (sfx->soundName, name);
Q_strncpyz (sfx->soundName, name, sizeof(sfx->soundName));
sfx->next = sfxHash[hash];
sfxHash[hash] = sfx;
+11 -1
View File
@@ -280,15 +280,25 @@ S_BeginRegistration
*/
void S_BeginRegistration()
{
int i;
Com_Printf("------- Sound Begin Registration -------\n");
S_StopAllSounds(true);
++s_registrationSequence;
s_registrationSequence++;
s_inRegistration = true;
s_knownSfx[0].registration_sequence = s_registrationSequence;
Com_Printf("------- Sound Begin Registration Complete -------\n");
// Added in OPM
// Reset all sound entities
// OG doesn't do this but this makes sure
// entities don't leak info from previous sessions
for (i = 0; i < ARRAY_LEN(s_entity); i++) {
s_entity[i] = s_entity_t{};
}
}
/*
+2 -2
View File
@@ -34,7 +34,7 @@ void load_sfx_info()
sfx_infos[0].max_factor = -1.0;
sfx_infos[0].loop_start = -1;
sfx_infos[0].loop_end = -1;
sfx_infos[0].max_number_playing = 5;
sfx_infos[0].max_number_playing = DEFAULT_SFX_NUMBER_PLAYING;
number_of_sfx_infos = 1;
for (current_sound_file = 0; current_sound_file < 10; current_sound_file++) {
@@ -62,7 +62,7 @@ void load_sfx_info()
sfx_infos[number_of_sfx_infos].max_factor = -1.f;
sfx_infos[number_of_sfx_infos].loop_start = -1;
sfx_infos[number_of_sfx_infos].loop_end = -1;
sfx_infos[number_of_sfx_infos].max_number_playing = 5;
sfx_infos[number_of_sfx_infos].max_number_playing = DEFAULT_SFX_NUMBER_PLAYING;
number_of_sfx_infos++;
}
} else if (!Q_stricmp(token, "loopstart")) {
+18 -1
View File
@@ -36,6 +36,22 @@ extern cvar_t *s_separation;
extern cvar_t *s_musicVolume;
extern cvar_t *s_ambientVolume;
#define MAX_SOUNDSYSTEM_CHANNELS_3D 32
#define MAX_SOUNDSYSTEM_CHANNELS_2D 32
#define MAX_SOUNDSYSTEM_CHANNELS_2D_STREAM 32
#define MAX_SOUNDSYSTEM_POSITION_CHANNELS (MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D + MAX_SOUNDSYSTEM_CHANNELS_2D_STREAM)
#define MAX_SOUNDSYSTEM_SONGS 2
#define MAX_SOUNDSYSTEM_MISC_CHANNELS 3
#define MAX_SOUNDSYSTEM_CHANNELS \
(MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D + MAX_SOUNDSYSTEM_CHANNELS_2D_STREAM + MAX_SOUNDSYSTEM_SONGS \
+ MAX_SOUNDSYSTEM_MISC_CHANNELS)
#define MAX_SOUNDSYSTEM_LOOP_SOUNDS 64
#define SOUNDSYSTEM_CHANNEL_MP3_ID \
(MAX_SOUNDSYSTEM_CHANNELS_3D + MAX_SOUNDSYSTEM_CHANNELS_2D + MAX_SOUNDSYSTEM_CHANNELS_2D_STREAM + MAX_SOUNDSYSTEM_SONGS)
#define SOUNDSYSTEM_CHANNEL_TRIGGER_MUSIC_ID (SOUNDSYSTEM_CHANNEL_MP3_ID + 1)
#define SOUNDSYSTEM_CHANNEL_MOVIE_ID (SOUNDSYSTEM_CHANNEL_TRIGGER_MUSIC_ID + 1)
typedef struct {
int format;
float rate;
@@ -134,7 +150,7 @@ typedef struct {
} channelbasesavegame_t;
typedef struct {
channelbasesavegame_t Channels[96];
channelbasesavegame_t Channels[MAX_SOUNDSYSTEM_CHANNELS];
} soundsystemsavegame_t;
enum channel_flags_t {
@@ -162,6 +178,7 @@ enum loopsound_flags_t {
#define MAX_SFX 1400
#define MAX_SFX_INFOS 1000
#define MAX_LOOP_SOUNDS 64
#define DEFAULT_SFX_NUMBER_PLAYING 10 //5
extern qboolean s_bLastInitSound;
extern qboolean s_bSoundStarted;
+6 -9
View File
@@ -203,7 +203,7 @@ void DumpChunks()
iff_chunk_len = GetLittleLong();
Com_Printf("0x%x : %s (%d)\n", data_p - 4, str, iff_chunk_len);
Com_Printf("0x%p : %s (%d)\n", data_p - 4, str, iff_chunk_len);
data_p += (iff_chunk_len + 1) & ~1;
} while (data_p < (byte *)iff_end);
@@ -404,6 +404,8 @@ qboolean DownSampleWav(wavinfo_t *info, byte *wav, int wavlength, int newkhz, by
datap += width;
}
assert(iff_end - data_p == 0);
return newdatasize;
}
@@ -414,10 +416,7 @@ DownSampleWav_MILES
*/
int DownSampleWav_MILES(wavinfo_t *info, byte *wav, int wavlength, int newkhz, byte **newdata)
{
//STUB_DESC("sound stuff");
//return 0;
// FIXME: unimplemented
// Fallback to software downsampling
// Fallback to software downsampling
return DownSampleWav(info, wav, wavlength, newkhz, newdata);
}
@@ -440,9 +439,6 @@ qboolean S_LoadSound(const char *fileName, sfx_t *sfx, int streamed, qboolean fo
}
if (streamed) {
//
// Added in 2.0
// Will be loaded next time
sfx->length = 5000;
sfx->width = 1;
sfx->iFlags |= SFX_FLAG_STREAMED;
@@ -513,6 +509,7 @@ qboolean S_LoadSound(const char *fileName, sfx_t *sfx, int streamed, qboolean fo
if (newdatasize) {
Z_Free(sfx->data);
sfx->data = newdata;
sfx->info.datasize = newdatasize;
}
}
@@ -525,7 +522,7 @@ qboolean S_LoadSound(const char *fileName, sfx_t *sfx, int streamed, qboolean fo
sfx->data = NULL;
}
sprintf(tempName, "k%s", fileName);
Com_sprintf(tempName, sizeof(tempName), "k%s", fileName);
UI_LoadResource(tempName);
if (strstr(fileName, "sound/null.wav")) {
+1 -1
View File
@@ -233,7 +233,7 @@ static sfxHandle_t S_AL_BufferFind(const char *filename)
ptr = &knownSfx[sfx];
memset(ptr, 0, sizeof(*ptr));
ptr->masterLoopSrc = -1;
strcpy(ptr->filename, filename);
Q_strncpyz(ptr->filename, filename, sizeof(ptr->filename));
}
// Return the handle
File diff suppressed because it is too large. Load diff
+10 -22
View File
@@ -29,22 +29,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
typedef int S32;
typedef unsigned int U32;
#define MAX_OPENAL_CHANNELS_3D 32
#define MAX_OPENAL_CHANNELS_2D 32
#define MAX_OPENAL_CHANNELS_2D_STREAM 32
#define MAX_OPENAL_POSITION_CHANNELS (MAX_OPENAL_CHANNELS_3D + MAX_OPENAL_CHANNELS_2D + MAX_OPENAL_CHANNELS_2D_STREAM)
#define MAX_OPENAL_SONGS 2
#define MAX_OPENAL_MISC_CHANNELS 3
#define MAX_OPENAL_CHANNELS \
(MAX_OPENAL_CHANNELS_3D + MAX_OPENAL_CHANNELS_2D + MAX_OPENAL_CHANNELS_2D_STREAM + MAX_OPENAL_SONGS \
+ MAX_OPENAL_MISC_CHANNELS)
#define MAX_OPENAL_LOOP_SOUNDS 64
#define OPENAL_CHANNEL_MP3_ID \
(MAX_OPENAL_CHANNELS_3D + MAX_OPENAL_CHANNELS_2D + MAX_OPENAL_CHANNELS_2D_STREAM + MAX_OPENAL_SONGS)
#define OPENAL_CHANNEL_TRIGGER_MUSIC_ID (OPENAL_CHANNEL_MP3_ID + 1)
#define OPENAL_CHANNEL_MOVIE_ID (OPENAL_CHANNEL_TRIGGER_MUSIC_ID + 1)
#define MAX_STREAM_BUFFERS 16
#define MAX_BUFFER_SAMPLES 16384
@@ -184,19 +168,23 @@ private:
unsigned int getBytesPerSample() const;
};
struct openal_movie_channel : public openal_channel {
};
struct openal_internal_t {
openal_channel chan_3D[MAX_OPENAL_CHANNELS_3D];
openal_channel chan_2D[MAX_OPENAL_CHANNELS_2D];
openal_channel_two_d_stream chan_2D_stream[MAX_OPENAL_CHANNELS_2D_STREAM];
openal_channel_two_d_stream chan_song[MAX_OPENAL_SONGS];
openal_channel chan_3D[MAX_SOUNDSYSTEM_CHANNELS_3D];
openal_channel chan_2D[MAX_SOUNDSYSTEM_CHANNELS_2D];
openal_channel_two_d_stream chan_2D_stream[MAX_SOUNDSYSTEM_CHANNELS_2D_STREAM];
openal_channel_two_d_stream chan_song[MAX_SOUNDSYSTEM_SONGS];
openal_channel_two_d_stream chan_mp3;
openal_channel_two_d_stream chan_trig_music;
openal_channel_two_d_stream chan_movie;
// Pointers to channels
openal_channel *channel[MAX_OPENAL_CHANNELS];
openal_channel *channel[MAX_SOUNDSYSTEM_CHANNELS];
openal_loop_sound_t loop_sounds[MAX_OPENAL_LOOP_SOUNDS];
openal_loop_sound_t loop_sounds[MAX_SOUNDSYSTEM_LOOP_SOUNDS];
openal_channel movieChannel;
sfx_t movieSFX;
+18
View File
@@ -150,6 +150,7 @@ void S_TriggeredMusic_SetupHandle(const char* pszName, int iLoopCount, int iOffs
void S_TriggeredMusic_Start();
void S_TriggeredMusic_StartLoop();
void S_TriggeredMusic_Stop();
void S_TriggeredMusic_Volume();
void S_TriggeredMusic_Pause();
void S_TriggeredMusic_Unpause();
void S_TriggeredMusic_PlayIntroMusic();
@@ -166,3 +167,20 @@ unsigned int S_GetMusicOffset();
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
#ifdef USE_VOIP
void S_StartCapture( void );
int S_AvailableCaptureSamples( void );
void S_Capture( int samples, byte *data );
void S_StopCapture( void );
void S_MasterGain( float gain );
#endif
#ifdef __cplusplus
}
#endif
+22 -11
View File
@@ -27,8 +27,24 @@ file(
add_library(fgame SHARED ${SOURCES_GAME})
find_package(BISON)
find_package(FLEX)
#
# Workaround to get a recent version Flex and Bison executables in MacOS
# as Bison 2.3 shipped with MacOS doesn't work
#
if (CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin")
execute_process(COMMAND brew --prefix bison RESULT_VARIABLE APP_RESULT OUTPUT_VARIABLE APP_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE)
if (APP_RESULT EQUAL 0 AND EXISTS "${APP_PREFIX}")
set(BISON_EXECUTABLE "${APP_PREFIX}/bin/bison")
endif()
execute_process(COMMAND brew --prefix flex RESULT_VARIABLE APP_RESULT OUTPUT_VARIABLE APP_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE)
if (APP_RESULT EQUAL 0 AND EXISTS "${APP_PREFIX}")
set(FLEX_EXECUTABLE "${APP_PREFIX}/bin/flex")
endif()
endif()
find_package(BISON 3 REQUIRED)
find_package(FLEX REQUIRED)
if (FLEX_FOUND)
flex_target(fgame-lexer ${CMAKE_SOURCE_DIR}/code/parser/lex_source.txt ${CMAKE_SOURCE_DIR}/code/parser/generated/yyLexer.cpp DEFINES_FILE ${CMAKE_SOURCE_DIR}/code/parser/generated/yyLexer.h COMPILE_FLAGS "-Cem --nounistd")
@@ -50,16 +66,11 @@ target_compile_features(fgame PUBLIC cxx_nullptr)
target_compile_features(fgame PUBLIC c_variadic_macros)
target_link_libraries(fgame PUBLIC qcommon)
set_target_properties(fgame PROPERTIES PREFIX "${TARGET_PLATFORM_PREFIX}")
set_target_properties(fgame PROPERTIES OUTPUT_NAME "game${TARGET_ARCH_SUFFIX}")
set_target_properties(fgame PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TARGET_BASE_GAME}")
set_target_properties(fgame PROPERTIES PREFIX "")
set_target_properties(fgame PROPERTIES OUTPUT_NAME "game${TARGET_BIN_SUFFIX}")
INSTALL(
TARGETS fgame
LIBRARY DESTINATION "${TARGET_BASE_GAME}"
RUNTIME DESTINATION "${TARGET_BASE_GAME}"
)
INSTALL(TARGETS fgame DESTINATION ${CMAKE_INSTALL_LIBDIR}/${LIB_INSTALL_SUBDIR})
if(MSVC)
INSTALL(FILES $<TARGET_PDB_FILE:fgame> DESTINATION "${TARGET_BASE_GAME}" OPTIONAL)
INSTALL(FILES $<TARGET_PDB_FILE:fgame> DESTINATION ${CMAKE_INSTALL_LIBDIR}/${LIB_INSTALL_SUBDIR} OPTIONAL)
endif()
+76 -34
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.
@@ -327,7 +327,7 @@ void ClearProjectileTargets()
ProjectileTarget::ProjectileTarget()
{
m_iTarget = -1;
m_iID = -1;
setMoveType(MOVETYPE_NONE);
setSolidType(SOLID_NOT);
hideModel();
@@ -337,12 +337,19 @@ ProjectileTarget::ProjectileTarget()
void ProjectileTarget::EventSetId(Event *ev)
{
m_iTarget = ev->GetInteger(1);
m_iID = ev->GetInteger(1);
}
int ProjectileTarget::GetTarget() const
int ProjectileTarget::GetId() const
{
return m_iTarget;
return m_iID;
}
void ProjectileTarget::Archive(Archiver& arc)
{
Entity::Archive(arc);
arc.ArchiveInteger(&m_iID);
}
CLASS_DECLARATION(Animate, ProjectileGenerator, "ProjectileGenerator") {
@@ -583,7 +590,7 @@ void ProjectileGenerator::GetLocalTargets()
m_projectileTargets.ClearObjectList();
for (i = 1; i <= g_projectileTargets.NumObjects(); i++) {
ProjectileTarget *target = g_projectileTargets.ObjectAt(i);
if (m_iId == target->GetTarget()) {
if (m_iId == target->GetId()) {
m_projectileTargets.AddObject(target);
}
}
@@ -1635,7 +1642,7 @@ ThrobbingBox_Explosive::ThrobbingBox_Explosive()
setModel("items\\\\pulse_explosive.tik");
m_sUsedModel = "items/explosive.tik";
m_sSound = "explose_flak88";
m_sSound = "explode_flak88";
m_sActivateSound = "plantbomb";
m_sTickSound = "bombtick";
@@ -1809,6 +1816,7 @@ void ThrobbingBox_Explosive::OnBlowUp(Event *ev)
ent = veh->QueryDriverSlotEntity(0);
if (ent) {
ent->takedamage = DAMAGE_YES;
ent->Damage(this, this, ent->health * 2.f, vec_zero, vec_zero, vec_zero, 50, 0, MOD_VEHICLE);
}
}
@@ -1842,7 +1850,7 @@ void ThrobbingBox_Explosive::OnUse(Event *ev)
if (m_fStopwatchDuration > 0) {
Player *player = static_cast<Player *>(G_FindTarget(this, "player"));
player->SetStopwatch(m_fStopwatchDuration, SWT_FUSE);
player->SetStopwatch(m_fStopwatchDuration, SWT_NORMAL);
LoopSound(m_sTickSound);
}
@@ -1899,6 +1907,13 @@ CLASS_DECLARATION(ThrobbingBox_Explosive, ThrobbingBox_ExplodePlayerFlak88, "Thr
{NULL, NULL}
};
ThrobbingBox_ExplodePlayerFlak88::ThrobbingBox_ExplodePlayerFlak88()
{
spawnflags |= TBE_SPAWNFLAG_DESTROYED_MODEL;
m_sDestroyedModel = "statweapons/flak88_d.tik";
m_sEffect = "fx/demodamage_flak88.tik";
}
/*QUAKED ThrobbingBox_ExplodeFlak88 (1.0 0.0 1.0) (-12 -12 -12) (12 12 12)
Explosive throbbing box. Connect to the object you want to make explode.
@@ -1921,6 +1936,12 @@ CLASS_DECLARATION(ThrobbingBox_Explosive, ThrobbingBox_ExplodeFlak88, "Throbbing
{NULL, NULL}
};
ThrobbingBox_ExplodeFlak88::ThrobbingBox_ExplodeFlak88()
{
m_sDestroyedModel = "statweapons/flak88_d.tik";
m_sEffect = "fx/demodamage_flak88.tik";
}
/*QUAKED ThrobbingBox_ExplodeNebelwerfer (1.0 0.0 1.0) (-12 -12 -12) (12 12 12) ReplaceModel
Explosive throbbing box. Connect to the object you want to make explode.
@@ -1943,6 +1964,11 @@ CLASS_DECLARATION(ThrobbingBox_Explosive, ThrobbingBox_ExplodeNebelwerfer, "Thro
{NULL, NULL}
};
ThrobbingBox_ExplodeNebelwerfer::ThrobbingBox_ExplodeNebelwerfer()
{
m_sDestroyedModel = "statweapons/nebelwerfer_d.tik";
}
/*QUAKED ThrobbingBox_ExplodePlayerNebelwerfer (1.0 0.0 1.0) (-12 -12 -12) (12 12 12) ReplaceModel
Explosive throbbing box. Connect to the object you want to make explode.
@@ -1961,10 +1987,16 @@ CLASS_DECLARATION(ThrobbingBox_Explosive, ThrobbingBox_ExplodeNebelwerfer, "Thro
---------------------------------------------------------------------------------------------
*/
CLASS_DECLARATION(ThrobbingBox_Explosive, ThrobbingBox_ExplodePlayerNebelwerfer, "ThrobbingBox_ExplodeNebelwerfer") {
CLASS_DECLARATION(ThrobbingBox_Explosive, ThrobbingBox_ExplodePlayerNebelwerfer, "ThrobbingBox_ExplodePlayerNebelwerfer") {
{NULL, NULL}
};
ThrobbingBox_ExplodePlayerNebelwerfer::ThrobbingBox_ExplodePlayerNebelwerfer()
{
spawnflags |= TBE_SPAWNFLAG_DESTROYED_MODEL;
m_sDestroyedModel = "statweapons/nebelwerfer_d.tik";
}
/*QUAKED ThrobbingBox_Stickybomb (1.0 0.0 1.0) (-12 -12 -12) (12 12 12) ReplaceModel WetFuse
Stickybomb throbbing box. Connect to the object you want to make explode.
@@ -1984,7 +2016,7 @@ CLASS_DECLARATION(ThrobbingBox_Explosive, ThrobbingBox_ExplodePlayerNebelwerfer,
Event EV_StickyBombWet("stickybombwet", EV_DEFAULT, NULL, NULL, NULL);
CLASS_DECLARATION(ThrobbingBox_Explosive, ThrobbingBox_Stickybomb, "ThrobbingBox_ExplodeNebelwerfer") {
CLASS_DECLARATION(ThrobbingBox_Explosive, ThrobbingBox_Stickybomb, "ThrobbingBox_Stickybomb") {
{&EV_Damage, &ThrobbingBox_Stickybomb::OnBlowUp },
{&EV_Use, &ThrobbingBox_Stickybomb::OnStickyBombUse},
{&EV_StickyBombWet, &ThrobbingBox_Stickybomb::OnStickyBombWet},
@@ -2022,7 +2054,7 @@ void ThrobbingBox_Stickybomb::OnStickyBombWet(Event *ev)
player = static_cast<Player *>(G_FindTarget(this, "player"));
player->SetStopwatch(0, SWT_NORMAL);
player->SetStopwatch(m_fStopwatchDuration - (level.svsFloatTime - m_fStopwatchStartTime), SWT_FUSE);
player->SetStopwatch(m_fStopwatchDuration - (level.svsFloatTime - m_fStopwatchStartTime), SWT_FUSE_WET);
}
void ThrobbingBox_Stickybomb::OnStickyBombUse(Event *ev)
@@ -2462,31 +2494,38 @@ CLASS_DECLARATION(SimpleArchivedEntity, AISpawnPoint, "info_aispawnpoint") {
AISpawnPoint::AISpawnPoint()
{
m_iHealth = 100;
m_iAccuracy = 20;
m_iAmmoGrenade = 0;
m_iBalconyHeight = 128;
m_iDisguiseLevel = 1;
m_fDisguisePeriod = 30000;
m_fDisguiseRange = 256;
m_fEnemyShareRange = 0;
m_fFixedLeash = 0.0;
m_iHealth = 100;
m_iAccuracy = 20;
m_iAmmoGrenade = 0;
m_iBalconyHeight = 128;
m_iDisguiseLevel = 1;
m_fDisguisePeriod = 30000;
m_fDisguiseRange = 256;
m_fEnemyShareRange = 0;
m_fFixedLeash = 0.0;
m_fGrenadeAwareness = 20.0;
m_fMaxNoticeTimeScale = 1;
m_fSoundAwareness = 100;
m_bPatrolWaitTrigger = 0;
m_fHearing = 2048;
m_fSight = world->m_fAIVisionDistance;
m_fFov = 90;
m_fLeash = 512;
m_fMinDist = 128.0;
m_fMaxDist = 1024;
m_fInterval = 128.0;
m_bDontDropWeapons = 0;
m_bDontDropHealth = 0;
m_bNoSurprise = 0;
m_bForceDropWeapon = 0;
m_bForceDropHealth = 0;
m_bPatrolWaitTrigger = false;
m_fHearing = 2048;
m_fSight = world->m_fAIVisionDistance;
m_fFov = 90;
m_fLeash = 512;
m_fMinDist = 128.0;
m_fMaxDist = 1024;
m_fInterval = 128.0;
m_bDontDropWeapons = false;
m_bDontDropHealth = false;
m_bNoSurprise = false;
m_bForceDropWeapon = false;
m_bForceDropHealth = false;
}
void AISpawnPoint::GetForceDropHealth(Event *ev)
@@ -2496,7 +2535,10 @@ void AISpawnPoint::GetForceDropHealth(Event *ev)
void AISpawnPoint::SetForceDropHealth(Event *ev)
{
// This is a bug on original mohaab (2.30 and 2.40), it should be m_bForceDropHealth
// Fixed in OPM
// This does look like a mistake on original mohaab (2.30 and 2.40)
// it should be m_bForceDropHealth.
// That's the reason why AI often don't drop weapons
//m_bForceDropWeapon = ev->GetBoolean(1);
m_bForceDropHealth = ev->GetBoolean(1);
}
+17 -3
View File
@@ -26,8 +26,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "animate.h"
typedef enum {
CONTROLLER_ALLIES,
CONTROLLER_AXIS,
CONTROLLER_ALLIES,
CONTROLLER_DRAW
} eController;
@@ -45,7 +45,7 @@ void ClearProjectileTargets();
class ProjectileTarget : public Entity
{
private:
int m_iTarget;
int m_iID;
public:
CLASS_PROTOTYPE(ProjectileTarget);
@@ -53,7 +53,9 @@ public:
ProjectileTarget();
void EventSetId(Event *ev);
int GetTarget() const;
int GetId() const;
void Archive(Archiver& arc) override;
};
#define MAX_PROJECTILE_GENERATOR_TARGETS 16
@@ -275,24 +277,36 @@ class ThrobbingBox_ExplodePlayerFlak88 : public ThrobbingBox_Explosive
{
public:
CLASS_PROTOTYPE(ThrobbingBox_ExplodePlayerFlak88);
public:
ThrobbingBox_ExplodePlayerFlak88();
};
class ThrobbingBox_ExplodeFlak88 : public ThrobbingBox_Explosive
{
public:
CLASS_PROTOTYPE(ThrobbingBox_ExplodeFlak88);
public:
ThrobbingBox_ExplodeFlak88();
};
class ThrobbingBox_ExplodeNebelwerfer : public ThrobbingBox_Explosive
{
public:
CLASS_PROTOTYPE(ThrobbingBox_ExplodeNebelwerfer);
public:
ThrobbingBox_ExplodeNebelwerfer();
};
class ThrobbingBox_ExplodePlayerNebelwerfer : public ThrobbingBox_Explosive
{
public:
CLASS_PROTOTYPE(ThrobbingBox_ExplodePlayerNebelwerfer);
public:
ThrobbingBox_ExplodePlayerNebelwerfer();
};
#define TBE_SPAWNFLAG_DESTROYED_MODEL 1
+8 -8
View File
@@ -269,13 +269,13 @@ void TOWObjective::TakeOver(Event *ev)
switch (controller) {
case CONTROLLER_ALLIES:
gi.cvar_set(m_sAxisObjName.c_str(), "1");
gi.cvar_set(m_sAlliesObjName.c_str(), "0");
break;
case CONTROLLER_AXIS:
gi.cvar_set(m_sAxisObjName.c_str(), "0");
gi.cvar_set(m_sAlliesObjName.c_str(), "1");
break;
case CONTROLLER_AXIS:
gi.cvar_set(m_sAxisObjName.c_str(), "1");
gi.cvar_set(m_sAlliesObjName.c_str(), "0");
break;
default:
break;
}
@@ -308,13 +308,13 @@ void TOWObjective::OnInitialize(Event *ev)
switch (m_eController) {
case CONTROLLER_ALLIES:
gi.cvar_set(m_sAxisObjName.c_str(), "1");
gi.cvar_set(m_sAlliesObjName.c_str(), "0");
break;
case CONTROLLER_AXIS:
gi.cvar_set(m_sAxisObjName.c_str(), "0");
gi.cvar_set(m_sAlliesObjName.c_str(), "1");
break;
case CONTROLLER_AXIS:
gi.cvar_set(m_sAxisObjName.c_str(), "1");
gi.cvar_set(m_sAlliesObjName.c_str(), "0");
break;
case CONTROLLER_DRAW:
gi.cvar_set(m_sAxisObjName.c_str(), "0");
gi.cvar_set(m_sAlliesObjName.c_str(), "0");
+1 -1
View File
@@ -59,8 +59,8 @@ class TOWObjectiveMan
{
private:
Container<TOWObjective *> m_towObjectives;
int m_iNumAxisObjectives;
int m_iNumAlliesObjectives;
int m_iNumAxisObjectives;
public:
TOWObjectiveMan();
+199 -19
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2018 the OpenMoHAA team
Copyright (C) 2018-2024 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -22,42 +22,222 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "vehicle.h"
#include "player.h"
#include "g_phys.h"
CLASS_DECLARATION(DrivableVehicle, VehicleHalfTrack, "VehicleHalfTrack")
{
{ &EV_Damage, &VehicleHalfTrack::EventDamage },
{ &EV_Killed, &VehicleHalfTrack::Killed },
{ NULL, NULL }
CLASS_DECLARATION(DrivableVehicle, VehicleHalfTrack, "VehicleHalfTrack") {
{&EV_Damage, &VehicleHalfTrack::EventDamage},
{&EV_Killed, &VehicleHalfTrack::Killed },
{NULL, NULL }
};
VehicleHalfTrack::VehicleHalfTrack()
{
;
}
void VehicleHalfTrack::Think()
{
vmove_t vm;
flags |= FL_POSTTHINK;
vmove_t vm;
flags |= FL_POSTTHINK;
prev_velocity = velocity;
prev_velocity = velocity;
SetSlotsNonSolid();
SetSlotsNonSolid();
SetMoveInfo(&vm);
VmoveSingle(&vm);
GetMoveInfo(&vm);
SetMoveInfo(&vm);
VmoveSingle(&vm);
GetMoveInfo(&vm);
SetSlotsSolid();
SetSlotsSolid();
}
void VehicleHalfTrack::Postthink()
{
// FIXME: STUB
float turn;
Vector i, j, k;
int index;
trace_t trace;
Vector normalsum;
int numnormals;
Vector temp;
Vector pitch, roll;
Vector acceleration;
Vector atmp, atmp2, aup;
VehicleBase *v;
VehicleBase *last;
float drivespeed;
Vector primal_angles;
Vector vTmp;
Vector n_angles;
primal_angles = angles;
if (drivable) {
if (m_bAutoPilot) {
AutoPilot();
}
currentspeed = moveimpulse;
turnangle = turnangle * 0.25 + turnimpulse;
turnangle = Q_clamp_float(turnangle, -maxturnrate, maxturnrate);
real_velocity = origin - prev_origin;
prev_origin = origin;
prev_acceleration = real_acceleration;
real_acceleration = real_velocity - prev_velocity;
prev_velocity = real_velocity;
acceleration = real_acceleration - prev_acceleration;
temp = angles;
temp.AngleVectorsLeft(&i, &j, &k);
j = vec_zero - j;
numnormals = 0;
for (index = 0; index < MAX_CORNERS; index++) {
Vector start, end;
Vector boxoffset;
Vector t_mins(-8, -8, -8), t_maxs(8, 8, 8);
boxoffset = Corners[index];
start = origin + i * boxoffset[0] + j * boxoffset[1] + k * boxoffset[2];
end = start + Vector(0, 0, -400);
trace = G_Trace(start, t_mins, t_maxs, end, this, MASK_VEHICLE_TIRES, false, "Vehicle::PostThink Corners");
if (trace.fraction != 1.0 || trace.startsolid) {
normalsum += trace.plane.normal;
}
}
angles[2] = 0;
if (m_iNumNormals > 1) {
temp = normalsum / numnormals;
temp.normalize();
i = temp.CrossProduct(temp, j);
pitch = i;
angles[0] = -pitch.toPitch();
}
turn = turnangle / 200.0;
if (groundentity) {
Vector newvel;
Vector flatvel;
velocity[0] *= 0.925f;
velocity[1] *= 0.925f;
flatvel = orientation[0];
velocity += flatvel * currentspeed;
flatvel[2] = 0;
drivespeed = Q_clamp_float(velocity * flatvel, -speed, speed);
newvel = flatvel * drivespeed;
velocity[0] = newvel[0];
velocity[1] = newvel[1];
velocity[2] += drivespeed * jumpimpulse;
avelocity *= 0.05f;
if (steerinplace) {
if (drivespeed < 350) {
drivespeed = 350;
}
}
avelocity.y += turn * drivespeed;
} else {
avelocity *= 0.1f;
}
angles += avelocity * level.frametime;
setAngles(angles);
}
drivespeed = acceleration * orientation[0];
if (drivable && driver.ent) {
str sound_name;
if (currentspeed > 0) {
sound_name = "snd_forward";
} else if (currentspeed < 0) {
sound_name = "snd_backward";
} else {
sound_name = "snd_idle";
}
LoopSound(sound_name);
}
i = orientation[0];
j = orientation[1];
k = orientation[2];
if (driver.ent) {
driver.ent->setOrigin(origin + i * driveroffset[0] + j * driveroffset[1] + k * driveroffset[2]);
if (drivable) {
// clear the driver velocity
driver.ent->velocity = vec_zero;
// set the driver angles to the vehicle's angle
driver.ent->setAngles(angles);
}
}
n_angles = (angles - primal_angles) * level.frametime;
if (n_angles.x > 180 || n_angles.x < -180) {
n_angles.x = 0;
}
if (n_angles.y > 180 || n_angles.y < -180) {
n_angles.y = 0;
}
if (n_angles.z > 180 || n_angles.z < -180) {
n_angles.z = 0;
}
if (n_angles.x > -1 || n_angles.x < 1) {
n_angles.x = 0;
}
if (n_angles.y > -1 || n_angles.y < 1) {
n_angles.y = 0;
}
if (n_angles.z > -1 || n_angles.z < 1) {
n_angles.z = 0;
}
avelocity = n_angles;
for (last = this; last->vlink; last = v) {
v = last->vlink;
v->setOrigin(origin + i * v->offset.x + j * v->offset.y + k * v->offset.z);
v->avelocity = avelocity;
v->velocity = velocity;
v->angles[ROLL] = angles[ROLL];
v->angles[YAW] = angles[YAW];
v->angles[PITCH] = (int)(drivespeed / 4.f + v->angles[PITCH]) % 360;
v->setAngles(v->angles);
}
CheckWater();
WorldEffects();
last_origin = origin;
if (!driver.ent && !velocity.length() && groundentity && !(watertype & CONTENTS_LAVA)) {
// make the vehicle stationary if it's completely immobile
flags &= ~FL_POSTTHINK;
if (drivable) {
setMoveType(MOVETYPE_STATIONARY);
}
}
}
void VehicleHalfTrack::Killed(Event* ev)
void VehicleHalfTrack::Killed(Event *ev)
{
deadflag = DEAD_DEAD;
deadflag = DEAD_DEAD;
}
+53 -8
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.
@@ -31,6 +31,8 @@ cVehicleSlot::cVehicleSlot()
prev_takedamage = (damage_t)-1;
prev_solid = (solid_t)-1;
prev_contents = -1;
prev_num_children = 0;
}
void cVehicleSlot::NotSolid(void)
@@ -51,11 +53,20 @@ void cVehicleSlot::NotSolid(void)
prev_contents = ent->edict->r.contents;
ent->takedamage = DAMAGE_NO;
ent->setSolidType(SOLID_NOT);
prev_num_children = 0;
for (i = 0; i < ent->numchildren; i++) {
Entity *sub = G_GetEntity(ent->children[i]);
if (sub && !sub->IsSubclassOfWeapon()) {
// Fixed in OPM
// Check for solidity
if (sub && !sub->IsSubclassOfWeapon() && sub->getSolidType() != SOLID_NOT) {
// Fixed in OPM
// Save children solidity so it can properly be restored later
prev_children_ent[prev_num_children] = sub;
prev_children_solid[prev_num_children] = (solid_t)sub->getSolidType();
prev_num_children++;
sub->setSolidType(SOLID_NOT);
}
}
@@ -67,7 +78,7 @@ void cVehicleSlot::NotSolid(void)
void cVehicleSlot::Solid(void)
{
int i;
int i, j;
if (!(flags & FL_SWIM)) {
return;
@@ -87,12 +98,24 @@ void cVehicleSlot::Solid(void)
prev_solid = (solid_t)-1;
prev_contents = -1;
//
// Fixed in OPM
// Restore children solidity
//
for (i = 0; i < ent->numchildren; i++) {
Entity *sub = G_GetEntity(ent->children[i]);
if (sub && !sub->IsSubclassOfWeapon()) {
sub->setSolidType(SOLID_BBOX);
for (j = 0; j < prev_num_children; j++) {
if (prev_children_ent[j] == sub) {
sub->setSolidType(prev_children_solid[j]);
}
}
//sub->setSolidType(SOLID_NOT);
}
}
prev_num_children = 0;
}
cTurretSlot::cTurretSlot()
@@ -136,9 +159,19 @@ void cTurretSlot::NotSolid(void)
}
}
prev_num_children = 0;
for (i = 0; i < ent->numchildren; i++) {
Entity *sub = G_GetEntity(ent->children[i]);
if (sub && !sub->IsSubclassOfWeapon()) {
// Fixed in OPM
// Check for solidity
if (sub && !sub->IsSubclassOfWeapon() && sub->getSolidType() != SOLID_NOT) {
// Fixed in OPM
// Save children solidity so it can properly be restored later
prev_children_ent[prev_num_children] = sub;
prev_children_solid[prev_num_children] = (solid_t)sub->getSolidType();
prev_num_children++;
sub->setSolidType(SOLID_NOT);
}
}
@@ -146,7 +179,7 @@ void cTurretSlot::NotSolid(void)
void cTurretSlot::Solid(void)
{
int i;
int i, j;
if (!(flags & FL_SWIM)) {
return;
@@ -177,10 +210,22 @@ void cTurretSlot::Solid(void)
}
}
//
// Fixed in OPM
// Restore children solidity
//
for (i = 0; i < ent->numchildren; i++) {
Entity *sub = G_GetEntity(ent->children[i]);
if (sub && !sub->IsSubclassOfWeapon()) {
sub->setSolidType(SOLID_BBOX);
for (j = 0; j < prev_num_children; j++) {
if (prev_children_ent[j] == sub) {
sub->setSolidType(prev_children_solid[j]);
}
}
//sub->setSolidType(SOLID_NOT);
}
}
prev_num_children = 0;
}
+9 -2
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.
@@ -46,12 +46,19 @@ protected:
solid_t prev_solid;
int prev_contents;
//
// Added in OPM
// Used for properly saving and restoring children solidity
Entity *prev_children_ent[MAX_MODEL_CHILDREN];
solid_t prev_children_solid[MAX_MODEL_CHILDREN];
int prev_num_children;
public:
cVehicleSlot();
virtual void NotSolid(void);
virtual void Solid(void);
void Archive(Archiver &arc) override;
void Archive(Archiver& arc) override;
};
inline void cVehicleSlot::Archive(Archiver& arc)
+5 -2
View File
@@ -334,7 +334,10 @@ void VehicleTank::Postthink()
// the tank was non-solid with a player driver,
// instead of the driver being non-solid.
//setSolidType(SOLID_NOT);
driver.ent->setSolidType(SOLID_NOT);
// Fixed in OPM
// Driver is made non-solid in Vehicle::MoveThink
//driver.ent->setSolidType(SOLID_NOT);
} else {
driver.ent->takedamage = DAMAGE_NO;
driver.ent->setSolidType(SOLID_NOT);
@@ -503,7 +506,7 @@ void VehicleTank::UpdateSound()
// This method only work when called from script.
// But it is not called automatically when the player actually uses the vehicle
// when that vehicle is unlocked.
// So the other native method is overriden instead
// So the other native method is overridden instead
/*
void VehicleTank::AttachDriverSlot(Event *ev)
{
+92 -93
View File
@@ -558,7 +558,7 @@ Event EV_Actor_DamagePuff
EV_DEFAULT,
"vv",
"position direction",
"Spawns a puff of 'blood' smoke at the speficied location in the specified direction.",
"Spawns a puff of 'blood' smoke at the specified location in the specified direction.",
EV_NORMAL
);
Event EV_Actor_SetAngleYawSpeed
@@ -2628,7 +2628,7 @@ CLASS_DECLARATION(SimpleActor, Actor, "Actor") {
//{&EV_Actor_SetBreathSteam2, &Actor::EventSetBreathSteam },
//====
{&EV_Actor_CalcGrenadeToss, &Actor::EventCalcGrenadeToss },
{&EV_Actor_CalcGrenadeToss2, &Actor::EventCalcGrenadeToss },
{&EV_Actor_CalcGrenadeToss2, &Actor::EventCalcGrenadeToss2 },
{&EV_Actor_GetNoSurprise, &Actor::EventGetNoSurprise },
{&EV_Actor_SetNoSurprise, &Actor::EventSetNoSurprise },
{&EV_Actor_SetNoSurprise2, &Actor::EventSetNoSurprise },
@@ -3212,7 +3212,7 @@ void Actor::GetMoveInfo(mmove_t *mm)
m_Dest - Vector(0, 0, 16384),
(Entity *)NULL,
MASK_MOVEINFO,
qfalse,
false,
"Actor::GetMoveInfo"
);
@@ -3744,7 +3744,7 @@ void Actor::DoMove(void)
case ANIM_MODE_SCRIPTED:
setAngles(angles + Vector(0, angular_delta, 0));
trace = G_Trace(
origin, mins, maxs, origin + frame_delta, this, edict->clipmask & ~MASK_SCRIPT_SLAVE, qtrue, "Actor"
origin, mins, maxs, origin + frame_delta, this, edict->clipmask & ~MASK_SCRIPT_SLAVE, true, "Actor"
);
SafeSetOrigin(trace.endpos);
velocity = frame_delta / level.frametime;
@@ -3956,7 +3956,7 @@ bool Actor::CanShoot(Entity *ent)
Vector vGunPos;
if (FriendlyInLineOfFire(ent)) {
// Added in 2.0
// Added in 2.0
// Check if a friend is in sight
bCanShoot = false;
} else if (ent->IsSubclassOfSentient()) {
@@ -3974,7 +3974,7 @@ bool Actor::CanShoot(Entity *ent)
this,
sen,
MASK_CANSEE,
qfalse,
false,
"Actor::CanShoot centroid"
)) {
bCanShoot = true;
@@ -3986,7 +3986,7 @@ bool Actor::CanShoot(Entity *ent)
this,
sen,
MASK_CANSEE,
qfalse,
false,
"Actor::CanShoot eyes"
)) {
bCanShoot = true;
@@ -4027,7 +4027,7 @@ bool Actor::CanSeeFrom(vec3_t pos, Entity *ent)
return false;
}
return G_SightTrace(pos, vec_zero, vec_zero, ent->centroid, this, ent, MASK_CANSEE, qfalse, "Actor::CanSeeFrom");
return G_SightTrace(pos, vec_zero, vec_zero, ent->centroid, this, ent, MASK_CANSEE, false, "Actor::CanSeeFrom");
}
/*
@@ -4300,14 +4300,14 @@ void Actor::ShowInfo(float fDot, float fDist)
G_DebugLine(centroid, a, 0.0, 1.0, 0.0, 1.0);
G_DebugCircle(a, m_fLeash, 0.0, 1.0, 0.0, 1.0, qtrue);
G_DebugCircle(a, m_fLeash, 0.0, 1.0, 0.0, 1.0, true);
G_DebugCircle(centroid, m_fMinDistance, 1.0, 0.0, 0.0, 1.0, qtrue);
G_DebugCircle(centroid, m_fMinDistance, 1.0, 0.0, 0.0, 1.0, true);
G_DebugCircle(centroid, m_fMaxDistance, 0.0, 0.0, 1.0, 1.0, qtrue);
G_DebugCircle(centroid, m_fMaxDistance, 0.0, 0.0, 1.0, 1.0, true);
} else if (g_entinfo->integer == 2) {
G_DebugCircle(centroid, m_fHearing, 1.0, 0.0, 0.0, 1.0, qtrue);
G_DebugCircle(centroid, m_fSight, 0.0, 0.0, 1.0, 1.0, qtrue);
G_DebugCircle(centroid, m_fHearing, 1.0, 0.0, 0.0, 1.0, true);
G_DebugCircle(centroid, m_fSight, 0.0, 0.0, 1.0, 1.0, true);
}
}
@@ -5057,7 +5057,7 @@ void Actor::HandlePain(Event *ev)
//FIXME: macro
SetCuriousAnimHint(7);
// Added in 2.30 the m_bIsCurous check
// Added in 2.30 the m_bIsCurous check
if (m_bEnableEnemy && m_ThinkStates[THINKLEVEL_IDLE] == THINKSTATE_IDLE && m_bIsCurious) {
SetEnemyPos(attacker->origin);
m_pszDebugState = "from_pain";
@@ -5394,7 +5394,8 @@ void Actor::MovePath(float fMoveSpeed)
if (m_WallDir) {
if (level.inttime >= m_iWallDodgeTimeout) {
m_WallDir = 0;
} else if (DotProduct2D(mm.desired_dir, m_PrevObstacleNormal) > 0 && CrossProduct2D(mm.desired_dir, m_PrevObstacleNormal) < 0) {
} else if (DotProduct2D(mm.desired_dir, m_PrevObstacleNormal) > 0
&& CrossProduct2D(mm.desired_dir, m_PrevObstacleNormal) < 0) {
m_iWallDodgeTimeout = level.inttime + 1000;
m_WallDir = -m_WallDir;
}
@@ -5646,13 +5647,20 @@ void Actor::EventSetMood(Event *ev)
===============
Actor::EventDamagePuff
Spawns a puff of 'blood' smoke at the speficied location in the specified direction.
Spawns a puff of 'blood' smoke at the specified location in the specified direction.
===============
*/
void Actor::EventDamagePuff(Event *ev)
{
Vector pos = ev->GetVector(1);
Vector dir = ev->GetVector(2);
int bulletbits;
// Fixed in OPM
// Large bullet flag normally take 2 bits since 2.0.
// However, in OG Spearhead and Breakthrough, EventDamagePuff
// mistakenly uses 1 bit which causes a parse message error
bulletbits = (g_protocol >= protocol_e::PROTOCOL_MOHTA_MIN) ? 2 : 1;
gi.SetBroadcastVisible(pos, NULL);
@@ -5662,7 +5670,7 @@ void Actor::EventDamagePuff(Event *ev)
gi.MSG_WriteCoord(pos.z);
gi.MSG_WriteDir(dir);
gi.MSG_WriteBits(0, 1);
gi.MSG_WriteBits(0, bulletbits);
gi.MSG_EndCGM();
}
@@ -6206,7 +6214,7 @@ bool Actor::MoveToPatrolCurrentNode(void)
IdleLook();
Anim_Idle();
// tell scripts the move has failed
parm.movefail = qtrue;
parm.movefail = true;
return false;
}
@@ -6596,15 +6604,7 @@ void Actor::DetectSmokeGrenades(void)
if (fDistSquared > Square(256) || InFOV(sprite->origin)) {
if (G_SightTrace(
eyePos,
vec_zero,
vec_zero,
sprite->origin,
this,
NULL,
MASK_CANSEE,
qfalse,
"Actor::DetectSmokeGrenades"
eyePos, vec_zero, vec_zero, sprite->origin, this, NULL, MASK_CANSEE, false, "Actor::DetectSmokeGrenades"
)) {
m_PotentialEnemies.ConfirmEnemy(this, sprite->owner);
}
@@ -6696,12 +6696,12 @@ void Actor::EventSetAnim(Event *ev)
int slot = 0;
int anim;
const_str flagVal;
qboolean flagged = qfalse;
qboolean flagged = false;
switch (ev->NumArgs()) {
case 4:
flagVal = ev->GetConstString(4);
flagged = qtrue;
flagged = true;
if (flagVal != STRING_FLAGGED) {
ScriptError("unknown keyword '%s', expected 'flagged'", Director.GetString(flagVal).c_str());
}
@@ -6732,11 +6732,11 @@ void Actor::EventSetAnim(Event *ev)
}
if (!slot) {
flagged = qtrue;
flagged = true;
}
if (flagged) {
parm.motionfail = qtrue;
parm.motionfail = true;
}
if (!m_bLevelMotionAnim) {
@@ -6750,7 +6750,7 @@ void Actor::EventSetAnim(Event *ev)
StartMotionAnimSlot(slot, anim, weight);
if (flagged) {
m_iMotionSlot = GetMotionSlot(slot);
parm.motionfail = qfalse;
parm.motionfail = false;
}
}
}
@@ -6764,10 +6764,10 @@ End action animation.
*/
void Actor::EventEndActionAnim(Event *ev)
{
parm.upperfail = qtrue;
parm.upperfail = true;
if (!m_bLevelActionAnim) {
ChangeActionAnim();
parm.upperfail = qfalse;
parm.upperfail = false;
}
}
@@ -6794,7 +6794,7 @@ void Actor::EventSetMotionAnim(Event *ev)
UnknownAnim(Director.GetString(name), edict->tiki);
}
parm.motionfail = qtrue;
parm.motionfail = true;
if (!m_bLevelMotionAnim) {
ChangeMotionAnim();
@@ -6805,7 +6805,7 @@ void Actor::EventSetMotionAnim(Event *ev)
// set the slot
m_iMotionSlot = GetMotionSlot(0);
parm.motionfail = qfalse;
parm.motionfail = false;
}
}
@@ -6843,7 +6843,7 @@ void Actor::EventSetAimMotionAnim(Event *ev)
UnknownAnim(Director.GetString(name), edict->tiki);
}
parm.motionfail = qtrue;
parm.motionfail = true;
if (!m_bLevelMotionAnim) {
ChangeMotionAnim();
@@ -6856,7 +6856,7 @@ void Actor::EventSetAimMotionAnim(Event *ev)
StartAimMotionAnimSlot(2, anim_high);
m_iMotionSlot = GetMotionSlot(1);
parm.motionfail = qfalse;
parm.motionfail = false;
}
}
@@ -6907,7 +6907,7 @@ void Actor::EventSetActionAnim(Event *ev)
UnknownAnim(derivedName, edict->tiki);
}
parm.upperfail = qtrue;
parm.upperfail = true;
if (!m_bLevelActionAnim) {
ChangeActionAnim();
m_bAimAnimSet = true;
@@ -6918,7 +6918,7 @@ void Actor::EventSetActionAnim(Event *ev)
StartAimAnimSlot(1, anim_forward);
StartAimAnimSlot(2, anim_down);
m_iActionSlot = GetActionSlot(0);
parm.upperfail = qfalse;
parm.upperfail = false;
}
}
@@ -6973,13 +6973,16 @@ void Actor::EventSetUpperAnim(Event *ev)
UnknownAnim(Director.GetString(name), edict->tiki);
}
parm.upperfail = qtrue;
parm.upperfail = true;
if (!m_bLevelActionAnim) {
ChangeActionAnim();
m_bActionAnimSet = true;
StartActionAnimSlot(anim);
m_iActionSlot = SimpleActor::GetActionSlot(0);
parm.upperfail = qfalse;
m_iActionSlot = GetActionSlot(0);
parm.upperfail = false;
}
}
@@ -7007,7 +7010,7 @@ bool Actor::SoundSayAnim(const_str name, byte bLevelSayAnim)
edict->tiki->a->name
);
Sound(Director.GetString(name), CHAN_AUTO, 0, 0, 0, NULL, 0, 1, 1, -1);
Sound(Director.GetString(name), CHAN_AUTO, 0, 0, NULL, 0, 0, 1, 1, -1);
return true;
}
@@ -7091,7 +7094,7 @@ void Actor::EventSetSayAnim(Event *ev)
}
name = ev->GetConstString(1);
parm.sayfail = qtrue;
parm.sayfail = true;
anim = gi.Anim_NumForName(edict->tiki, Director.GetString(name));
if (anim == -1) {
@@ -7147,7 +7150,7 @@ void Actor::EventSetSayAnim(Event *ev)
m_iSaySlot = GetSaySlot();
}
parm.sayfail = qfalse;
parm.sayfail = false;
}
/*
@@ -7313,6 +7316,8 @@ void Actor::UpdateUpperAnim(void)
if (!m_bActionAnimSet) {
Unregister(STRING_UPPERANIMDONE);
}
return;
}
gi.Anim_FlagsSkel(edict->tiki, anim);
@@ -7699,10 +7704,7 @@ void Actor::SetThinkState(eThinkState state, eThinkLevel level)
m_csIdleMood = STRING_NERVOUS;
map = m_ThinkMap[THINKSTATE_ATTACK];
if (map != THINK_ALARM
&& map != THINK_WEAPONLESS
&& map != THINK_DOG_ATTACK
&& !GetWeapon(WEAPON_MAIN)) {
if (map != THINK_ALARM && map != THINK_WEAPONLESS && map != THINK_DOG_ATTACK && !GetWeapon(WEAPON_MAIN)) {
Com_Printf(
"^~^~^ LD ERROR: (entnum %i, radnum %i, targetname '%s'): forcing weaponless attack state.\n"
"^~^~^ Level designers should specify 'type_attack weaponless' for this guy.\n",
@@ -8135,8 +8137,8 @@ void Actor::EndState(int level)
{
GlobalFuncs_t *think;
think = &GlobalFuncs[m_Think[level]];
m_Think[level] = THINK_VOID;
think = &GlobalFuncs[m_Think[level]];
m_Think[level] = THINK_VOID;
if (think->EndState) {
(this->*think->EndState)();
@@ -8264,8 +8266,8 @@ void Actor::FixAIParameters(void)
if (m_pTetherEnt) {
fMinLeash = 64;
if (m_pTetherEnt->IsSubclassOfEntity()) {
Entity* pEnt = static_cast<Entity*>(m_pTetherEnt.Pointer());
fMinLeash = pEnt->maxs[0] - pEnt->mins[1] + pEnt->maxs[1] - pEnt->mins[1];
Entity *pEnt = static_cast<Entity *>(m_pTetherEnt.Pointer());
fMinLeash = pEnt->maxs[0] - pEnt->mins[1] + pEnt->maxs[1] - pEnt->mins[1];
}
if (m_fLeash < fMinLeash) {
@@ -8597,7 +8599,7 @@ bool Actor::PassesTransitionConditions_Disguise(void)
this,
player,
MASK_TRANSITION,
qfalse,
false,
"Actor::PassesTransitionConditions_Disguise"
);
}
@@ -9151,7 +9153,7 @@ void Actor::CuriousSound(int iType, vec3_t sound_origin, float fDistSquared, flo
}
}
if ((fRangeFactor * m_fSoundAwareness) < (rand() / (0x7fffffff / 100.0))) {
if ((fRangeFactor * m_fSoundAwareness) < random()) {
return;
}
@@ -9231,8 +9233,7 @@ void Actor::WeaponSound(int iType, vec3_t sound_origin, float fDistSquared, floa
pEnemy = pOwner->m_Enemy;
}
if (pOwner->m_Team == m_Team && !pEnemy && pOwner->IsSubclassOfActor()
&& originator->IsSubclassOfWeapon()) {
if (pOwner->m_Team == m_Team && !pEnemy && pOwner->IsSubclassOfActor() && originator->IsSubclassOfWeapon()) {
Actor *pActor = static_cast<Actor *>(pOwner);
Weapon *pWeapon = static_cast<Weapon *>(originator);
@@ -9455,7 +9456,7 @@ void Actor::NotifySquadmateKilled(Sentient *pSquadMate, Sentient *pAttacker)
this,
pSquadMate,
MASK_AI_CANSEE,
qfalse,
false,
"Actor::NotifySquadmateKilled"
);
}
@@ -9638,7 +9639,7 @@ bool Actor::ValidGrenadePath(const Vector& vFrom, const Vector& vTo, Vector& vVe
G_DebugLine(vFrom, vPoint1, 1.0, 0.5, 0.5, 1.0);
}
if (!G_SightTrace(vFrom, mins, maxs, vPoint1, this, NULL, MASK_GRENADEPATH, qfalse, "Actor::ValidGrenadePath 1")) {
if (!G_SightTrace(vFrom, mins, maxs, vPoint1, this, NULL, MASK_GRENADEPATH, false, "Actor::ValidGrenadePath 1")) {
return false;
}
@@ -9651,9 +9652,7 @@ bool Actor::ValidGrenadePath(const Vector& vFrom, const Vector& vTo, Vector& vVe
G_DebugLine(vPoint1, vPoint2, 1.0, 0.5, 0.5, 1.0);
}
if (!G_SightTrace(
vPoint1, mins, maxs, vPoint2, this, NULL, MASK_GRENADEPATH, qfalse, "Actor::ValidGrenadePath 2"
)) {
if (!G_SightTrace(vPoint1, mins, maxs, vPoint2, this, NULL, MASK_GRENADEPATH, false, "Actor::ValidGrenadePath 2")) {
return false;
}
@@ -9673,16 +9672,14 @@ bool Actor::ValidGrenadePath(const Vector& vFrom, const Vector& vTo, Vector& vVe
if (ai_debug_grenades->integer) {
G_DebugLine(vPoint2, vPoint3, 1.0, 0.5, 0.5, 1.0);
}
if (!G_SightTrace(
vPoint2, mins, maxs, vPoint3, this, NULL, MASK_GRENADEPATH, qfalse, "Actor::ValidGrenadePath 3"
)) {
if (!G_SightTrace(vPoint2, mins, maxs, vPoint3, this, NULL, MASK_GRENADEPATH, false, "Actor::ValidGrenadePath 3")) {
return false;
}
if (ai_debug_grenades->integer) {
G_DebugLine(vPoint3, vTo, 1.0, 0.5, 0.5, 1.0);
}
trace = G_Trace(vPoint3, mins, maxs, vTo, this, MASK_GRENADEPATH, qfalse, "Actor::ValidGrenadePath 4");
trace = G_Trace(vPoint3, mins, maxs, vTo, this, MASK_GRENADEPATH, false, "Actor::ValidGrenadePath 4");
if (!trace.allsolid) {
if (!trace.ent) {
return true;
@@ -9715,7 +9712,7 @@ Vector Actor::CalcThrowVelocity(const Vector& vFrom, const Vector& vTo)
vDelta = vTo - vFrom;
fHorzDistSquared = vDelta.lengthXYSquared();
fDistance = sqrt(fHorzDistSquared + vDelta.z * vDelta.z);
fDistance = sqrt(fHorzDistSquared + Square(vDelta.z));
// original irl equation: v10 = sqrt(fGravity * 0.5 * fHorzDistSquared / (fDistance * trigMult ))
// trigMult = (cos(th)/ tan(al) - sin(th)/tanSquared(al))
@@ -10490,8 +10487,7 @@ bool Actor::CanMovePathWithLeash(void) const
}
VectorSub2D(origin, m_vHome, delta);
if (VectorLength2DSquared(delta) >= m_fLeashSquared
&& DotProduct2D(m_Path.CurrentDelta(), delta) >= 0) {
if (VectorLength2DSquared(delta) >= m_fLeashSquared && DotProduct2D(m_Path.CurrentDelta(), delta) >= 0) {
return false;
}
@@ -10530,7 +10526,7 @@ Vector Actor::GunTarget(bool bNoCollision, const vec3_t position, const vec3_t f
static cvar_t *aiScatterWide = gi.Cvar_Get("g_aiScatterWide", "16.0", 0);
static cvar_t *aiScatterHeight = gi.Cvar_Get("g_aiScatterHeight", "45.0", 0);
static cvar_t *aiRanges[4];
static qboolean doInit = qtrue;
static qboolean doInit = true;
float fAccuracy, fCoverFactor;
Vector aimDir;
@@ -10566,7 +10562,7 @@ Vector Actor::GunTarget(bool bNoCollision, const vec3_t position, const vec3_t f
dir.normalize();
if (g_target_game > target_game_e::TG_MOH) {
if (DotProduct2D(forward, dir) < aiMaxDeviation->value) {
if (DotProduct(forward, dir) < aiMaxDeviation->value) {
Vector vOut;
VectorMA(position, 2048, forward, vOut);
@@ -10614,7 +10610,7 @@ Vector Actor::GunTarget(bool bNoCollision, const vec3_t position, const vec3_t f
vPos = player->centroid;
if (!G_SightTrace(
GunPosition(), vec_zero, vec_zero, vPos, m_Enemy, this, MASK_CANSEE, qfalse, "Actor::GunTarget 1"
GunPosition(), vec_zero, vec_zero, vPos, m_Enemy, this, MASK_CANSEE, false, "Actor::GunTarget 1"
)) {
fCoverFactor *= aifCoverFactor->value;
vPos = m_Enemy->EyePosition();
@@ -11148,9 +11144,9 @@ Actor::EventSound
void Actor::EventSound(Event *ev)
{
if (g_gametype->integer == GT_SINGLE_PLAYER || m_Team == TEAM_AMERICAN) {
ProcessSoundEvent(ev, qtrue);
ProcessSoundEvent(ev, true);
} else {
ProcessSoundEvent(ev, qfalse);
ProcessSoundEvent(ev, false);
}
}
@@ -11387,7 +11383,7 @@ void Actor::StrafeToAttack(float fDist, vec3_t vDir)
return;
}
if (!G_SightTrace(origin, mins, maxs, vSpot, this, NULL, MASK_TARGETPATH, qtrue, "Actor::StrafeToAttack 1")) {
if (!G_SightTrace(origin, mins, maxs, vSpot, this, NULL, MASK_TARGETPATH, true, "Actor::StrafeToAttack 1")) {
ClearPath();
return;
}
@@ -11403,7 +11399,7 @@ void Actor::StrafeToAttack(float fDist, vec3_t vDir)
this,
m_Enemy,
MASK_CANSEE,
qfalse,
false,
"Actor::StrafeToAttack 1"
)) {
ClearPath();
@@ -11588,8 +11584,8 @@ void Actor::DontFaceWall(void)
VectorSub2D(m_vDfwPos, origin, vDelta);
if (Square(fErrorLerp * -14.0 + 16.0) > VectorLength2DSquared(vDelta) &&
(fabs(AngleNormalize180(m_fDfwRequestedYaw - m_DesiredYaw)) <= fErrorLerp * -29.0 + 30.0
if (Square(fErrorLerp * -14.0 + 16.0) > VectorLength2DSquared(vDelta)
&& (fabs(AngleNormalize180(m_fDfwRequestedYaw - m_DesiredYaw)) <= fErrorLerp * -29.0 + 30.0
|| fabs(AngleNormalize180(m_fDfwDerivedYaw - m_DesiredYaw)) <= fErrorLerp * -29.0 + 30.0)) {
if (AvoidingFacingWall()) {
SetDesiredYaw(m_fDfwDerivedYaw);
@@ -11610,12 +11606,12 @@ void Actor::DontFaceWall(void)
start.y -= origin.y;
fEyeRadius = VectorLength2D(start);
start.x = origin.x + fEyeRadius * fCosAngle;
start.y = origin.x + fEyeRadius * fSinAngle;
start.y = origin.y + fEyeRadius * fSinAngle;
end.x = start.x + fCosAngle * 64;
end.y = start.y + fSinAngle * 64;
end.z = start.z;
trace = G_Trace(start, vec_zero, vec_zero, end, this, MASK_CANSEE, qfalse, "Actor::DontFaceWall");
trace = G_Trace(start, vec_zero, vec_zero, end, this, MASK_CANSEE, false, "Actor::DontFaceWall");
if (trace.entityNum == ENTITYNUM_NONE || trace.fraction > 0.999f || trace.startsolid) {
m_eDontFaceWallMode = 3;
@@ -11623,7 +11619,7 @@ void Actor::DontFaceWall(void)
return;
}
if (trace.entityNum != ENTITYNUM_WORLD && trace.ent->entity->AIDontFace()) {
if (trace.entityNum != ENTITYNUM_WORLD && !trace.ent->entity->AIDontFace()) {
m_eDontFaceWallMode = 4;
m_fDfwDerivedYaw = m_fDfwRequestedYaw;
return;
@@ -11916,8 +11912,10 @@ void Actor::EventCalcGrenadeToss2(Event *ev)
}
if (fDistSquared < Square(1024)) {
// See if it can roll
vPoint = GrenadeThrowPoint(vFrom, vDelta, STRING_ANIM_GRENADETOSS_SCR);
vVel = CanRollGrenade(vPoint, vTargetPos);
if (vVel != vPointTarget) {
m_vGrenadeVel = vVel;
m_eGrenadeMode = AI_GREN_TOSS_ROLL;
@@ -11930,6 +11928,7 @@ void Actor::EventCalcGrenadeToss2(Event *ev)
if (!speed) {
vPoint = GrenadeThrowPoint(vFrom, vDelta, STRING_ANIM_GRENADETHROW_SCR);
vVel = CanThrowGrenade(vPoint, vTargetPos);
if (vVel != vec_zero) {
m_vGrenadeVel = vVel;
m_eGrenadeMode = AI_GREN_TOSS_THROW;
@@ -11946,7 +11945,9 @@ void Actor::EventCalcGrenadeToss2(Event *ev)
vVel = vTargetPos - vPoint;
vVel.normalize();
vVel *= speed;
m_vGrenadeVel = vVel;
m_vGrenadeVel = vVel;
m_eGrenadeMode = AI_GREN_TOSS_THROW;
ev->AddConstString(STRING_ANIM_GRENADETOSS_SCR);
SetDesiredYawDir(m_vGrenadeVel);
@@ -12121,9 +12122,7 @@ void Actor::SetPathToNotBlockSentient(Sentient *pOther)
vDest = origin + vPerp * 48;
if (G_SightTrace(
vDest, mins, maxs, vDest, this, pOther, MASK_SOLID, qfalse, "Actor::SetPathToNotBlockSentient 1"
)) {
if (G_SightTrace(vDest, mins, maxs, vDest, this, pOther, MASK_SOLID, false, "Actor::SetPathToNotBlockSentient 1")) {
SetPathWithinDistance(vDest, NULL, 96, 0);
}
@@ -12133,9 +12132,7 @@ void Actor::SetPathToNotBlockSentient(Sentient *pOther)
vDest = origin - vPerp * 48;
if (G_SightTrace(
vDest, mins, maxs, vDest, this, pOther, MASK_SOLID, qfalse, "Actor::SetPathToNotBlockSentient 2"
)) {
if (G_SightTrace(vDest, mins, maxs, vDest, this, pOther, MASK_SOLID, false, "Actor::SetPathToNotBlockSentient 2")) {
SetPathWithinDistance(vDest, NULL, 96, 0);
}
@@ -12172,7 +12169,7 @@ void Actor::LookAround(float fFovAdd)
VectorMA(vEyePos, 1024, vDest, vDest);
trace = G_Trace(EyePosition(), vec_zero, vec_zero, vDest, this, MASK_LOOK, qfalse, "Actor::LookAround");
trace = G_Trace(EyePosition(), vec_zero, vec_zero, vDest, this, MASK_LOOK, false, "Actor::LookAround");
if (trace.fraction > 0.125) {
m_bHasDesiredLookDest = true;
VectorCopy(trace.endpos, m_vDesiredLookDest);
@@ -12282,8 +12279,9 @@ const char *Actor::DumpCallTrace(const char *pszFmt, ...) const
vPlayer = p->origin;
}
i1 = sprintf(
i1 = Com_sprintf(
szTemp,
sizeof(szTemp),
"map = %s\n"
"time = %i (%i:%02i)\n"
"entnum = %i, targetname = '%s'\n"
@@ -12318,7 +12316,7 @@ const char *Actor::DumpCallTrace(const char *pszFmt, ...) const
if (pszFmt) {
va_list args2;
va_copy(args2, args);
i2 = i1 + vsprintf(&szTemp[i1], pszFmt, args);
i2 = i1 + Q_vsnprintf(szTemp + i1, sizeof(szTemp) - i1, pszFmt, args);
}
va_end(args);
@@ -12329,8 +12327,9 @@ const char *Actor::DumpCallTrace(const char *pszFmt, ...) const
t = time(0);
ptm = localtime(&t);
sprintf(
Com_sprintf(
szFile,
sizeof(szFile),
"main\\ai_trace_%s_%i_%i_%02i%02i.log",
sv_mapname->string,
ptm->tm_mon + 1,
+1 -1
View File
@@ -120,7 +120,7 @@ void Actor::Think_DisguiseOfficer(void)
{
Com_Printf("Actor::Think_DisguiseOfficer: invalid think state %i\n", m_State);
char assertStr[16317] = {0};
strcpy(assertStr, "\"invalid think state\"\n\tMessage: ");
Q_strncpyz(assertStr, "\"invalid think state\"\n\tMessage: ", sizeof(assertStr));
Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("thinkstate = %i", m_State));
assert(!assertStr);
}
+1 -1
View File
@@ -124,7 +124,7 @@ void Actor::Think_DisguiseRover(void)
{
Com_Printf("Actor::Think_DisguiseOfficer: invalid think state %i\n", m_State);
char assertStr[16317] = {0};
strcpy(assertStr, "\"invalid think state\"\n\tMessage: ");
Q_strncpyz(assertStr, "\"invalid think state\"\n\tMessage: ", sizeof(assertStr));
Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("thinkstate = %i", m_State));
assert(!assertStr);
}
+1 -1
View File
@@ -474,7 +474,7 @@ void Actor::FinishedAnimation_Grenade(void)
break;
default:
char assertStr[16317] = {0};
strcpy(assertStr, "\"invalid grenade state in FinishedAnimation()\"\n\tMessage: ");
Q_strncpyz(assertStr, "\"invalid grenade state in FinishedAnimation()\"\n\tMessage: ", sizeof(assertStr));
Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("state = %i", m_eGrenadeState));
assert(!assertStr);
break;
+10 -10
View File
@@ -145,31 +145,31 @@ void Actor::ThinkHoldGun_TurretGun(void)
if (m_State == ACTOR_STATE_MACHINE_GUNNER_RELOADING) {
m_fCrouchWeight = 0;
temp = (origin[2] + 71.6f - m_pTurret->origin[2]) / 39.f;
temp = (origin[2] + 71.6f - m_pTurret->origin[2]) / 39.0f;
if (temp >= -1.0 && temp <= 1.0) {
m_pTurret->angles[0] = RAD2DEG(atan(temp / sqrt(temp * -temp + 1)));
m_pTurret->setAngles(m_pTurret->angles);
}
} else {
m_fCrouchWeight = machine_gunner_hands_up_stand / 17.1f;
if (m_fCrouchWeight < -1.0) {
m_fCrouchWeight = -1.0;
if (m_fCrouchWeight < -1.0f) {
m_fCrouchWeight = -1.0f;
}
}
VectorScale2D(orientation[0], -(m_fCrouchWeight * -9.3f + 23.4f), offset);
VectorScale2D(orientation[0], -(23.4 - m_fCrouchWeight * 9.3), offset);
VectorAdd2D(newOrigin, offset, newOrigin);
VectorScale2D(orientation[1], m_fCrouchWeight * 2.6f + 10.3f, offset);
VectorScale2D(orientation[1], 10.3 + m_fCrouchWeight * 2.6, offset);
VectorAdd2D(newOrigin, offset, newOrigin);
} else {
m_fCrouchWeight = machine_gunner_hands_up_stand / (heightDiff - 38.7f);
m_fCrouchWeight = machine_gunner_hands_up_stand / (heightDiff - 38.7);
if (m_fCrouchWeight > 1.0) {
m_fCrouchWeight = 1.0;
}
VectorScale2D(orientation[0], -(m_fCrouchWeight * -3.f + 23.4f), offset);
VectorScale2D(orientation[0], -(23.4 - m_fCrouchWeight * 3.0), offset);
VectorAdd2D(newOrigin, offset, newOrigin);
VectorScale2D(orientation[1], m_fCrouchWeight * -1.6f + 10.3f, offset);
VectorScale2D(orientation[1], 10.3 - m_fCrouchWeight * 1.6, offset);
VectorAdd2D(newOrigin, offset, newOrigin);
}
@@ -182,11 +182,11 @@ void Actor::ThinkHoldGun_TurretGun(void)
UpdateAimMotion();
UpdateAnim();
newOrigin[2] += 18;
newOrigin[2] = origin[2] + 18.0;
end[0] = newOrigin[0];
end[1] = newOrigin[1];
end[2] = newOrigin[2] - 94;
end[2] = origin[2] - 94.0;
trace = G_Trace(newOrigin, MINS, MAXS, end, this, MASK_PATHSOLID, qfalse, "Actor::ThinkHoldGun_TurretGun");
if (trace.fraction != 1.0 && !trace.startsolid && !trace.allsolid && trace.ent) {
+1 -1
View File
@@ -121,7 +121,7 @@ void Actor::Think_Weaponless(void)
} else {
Com_Printf("Think_Weaponless: invalid think state %i\n", m_State);
char assertStr[16317] = {0};
strcpy(assertStr, "\"invalid think state\"\n\tMessage: ");
Q_strncpyz(assertStr, "\"invalid think state\"\n\tMessage: ", sizeof(assertStr));
Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("thinkstate = %i", m_State));
assert(!assertStr);
}
+5 -4
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.
@@ -142,7 +142,8 @@ int ActorEnemy::UpdateThreat(Actor *pSelf)
Square(305),
Square(254),
Square(200),
Square(137)};
Square(137)
};
static int iWeaponThreat[7][5] = {
{5, 3, 1, 1, 1},
{8, 6, 4, 2, 1},
@@ -165,7 +166,7 @@ int ActorEnemy::UpdateThreat(Actor *pSelf)
}
m_iThreat = 10000;
if (m_bVisible == true) {
if (m_bVisible) {
m_iThreat = 10500;
}
@@ -321,7 +322,7 @@ void ActorEnemySet::FlagBadEnemy(Sentient *pEnemy)
// Added in 2.0.
// Set the reaction time
pActorEnemy->m_iNextEnemyTime = level.inttime + 5000;
pActorEnemy->m_iNextEnemyTime = level.inttime + 5000;
pActorEnemy->m_fLastLookTime = level.time;
pActorEnemy->m_fVisibility = 0.0;
+16 -18
View File
@@ -105,8 +105,8 @@ public:
inline void ActorPath::Archive(Archiver& arc)
{
int pos;
int startpathpos;
int index;
int i;
arc.ArchiveInteger(&m_pathlen);
@@ -115,42 +115,40 @@ inline void ActorPath::Archive(Archiver& arc)
m_path = new PathInfo[m_pathlen];
}
if (m_pathlen > 0) {
for (int i = 0; i < m_pathlen; i++) {
m_path->Archive(arc);
}
for (i = 0; i < m_pathlen; i++) {
m_path[i].Archive(arc);
}
if (!arc.Saving()) {
arc.ArchiveInteger(&pos);
if (pos == -1) {
arc.ArchiveInteger(&index);
if (index == -1) {
m_pathpos = NULL;
} else {
m_pathpos = &m_path[pos];
m_pathpos = &m_path[index];
}
arc.ArchiveInteger(&startpathpos);
if (startpathpos == -1) {
arc.ArchiveInteger(&index);
if (index == -1) {
m_startpathpos = NULL;
} else {
m_startpathpos = &m_path[pos];
m_startpathpos = &m_path[index];
}
} else {
if (m_pathpos) {
pos = m_pathpos - m_path;
index = m_pathpos - m_path;
} else {
pos = -1;
index = -1;
}
arc.ArchiveInteger(&pos);
arc.ArchiveInteger(&index);
if (m_startpathpos) {
pos = m_startpathpos - m_path;
index = m_startpathpos - m_path;
} else {
pos = -1;
index = -1;
}
arc.ArchiveInteger(&pos);
arc.ArchiveInteger(&index);
}
} else if (arc.Loading()) {
m_pathpos = 0;
+7 -7
View File
@@ -315,8 +315,8 @@ void Animate::NewAnim(int animnum, int slot, float weight)
const tiki_singlecmd_t& single_cmd = cmds.cmds[ii];
int eventNum;
strcpy(cmdName, "_client_");
strcpy(cmdName + 8, single_cmd.args[0]);
Q_strncpyz(cmdName, "_client_", longest + 8 + 1);
Q_strncpyz(cmdName + 8, single_cmd.args[0], longest + 1);
eventNum = Event::FindEventNum(cmdName);
@@ -386,8 +386,8 @@ void Animate::NewAnim(int animnum, int slot, float weight)
const tiki_singlecmd_t& single_cmd = cmds.cmds[ii];
int eventNum;
strcpy(cmdName, "_client_");
strcpy(cmdName + 8, single_cmd.args[0]);
Q_strncpyz(cmdName, "_client_", longestAllFrames + 8 + 1);
Q_strncpyz(cmdName + 8, single_cmd.args[0], longestAllFrames + 1);
eventNum = Event::FindEventNum(cmdName);
@@ -554,8 +554,8 @@ void Animate::DoExitCommands(int slot)
const tiki_singlecmd_t& single_cmd = cmds.cmds[ii];
int eventNum;
strcpy(cmdName, "_client_");
strcpy(cmdName + 8, single_cmd.args[0]);
Q_strncpyz(cmdName, "_client_", longest + 8 + 1);
Q_strncpyz(cmdName + 8, single_cmd.args[0], longest + 1);
eventNum = Event::FindEventNum(cmdName);
@@ -596,7 +596,7 @@ int Animate::NumAnims(void)
const char *Animate::AnimName(int slot)
{
return gi.Anim_NameForNum(edict->tiki, edict->s.frameInfo[slot].index);
return gi.Anim_NameForNum(edict->tiki, CurrentAnim(slot));
}
void Animate::AnimFinished(int slot)
+9 -10
View File
@@ -109,6 +109,11 @@ const char *ArchiveFile::Filename(void)
qboolean ArchiveFile::Compress()
{
#ifdef Q3_BIG_ENDIAN
// FIXME: Decompressing crashes on big-endian architectures
return false;
#endif
byte *tempbuf;
size_t out_len;
size_t tempbuf_len;
@@ -310,7 +315,7 @@ void Archiver::FileError(const char *fmt, ...)
char text[1024];
va_start(argptr, fmt);
vsprintf(text, fmt, argptr);
Q_vsnprintf(text, sizeof(text), fmt, argptr);
va_end(argptr);
fileerror = true;
@@ -517,7 +522,6 @@ void ArchiveSwapValue<Quat>(Quat* value) {
#define ARCHIVE(func, type) \
void Archiver::Archive##func(type *v) \
{ \
int i; \
if (archivemode == ARCHIVE_WRITE) { \
type nv = *v; \
ArchiveSwapValue(&nv); \
@@ -559,7 +563,6 @@ void Archiver::ArchiveSvsTime(int *time)
void Archiver::ArchiveVec2(vec2_t vec)
{
int i;
if (archivemode == ARCHIVE_WRITE) {
vec2_t nv = { vec[0], vec[1] };
ArchiveSwapValue(nv, 2);
@@ -572,7 +575,6 @@ void Archiver::ArchiveVec2(vec2_t vec)
void Archiver::ArchiveVec3(vec3_t vec)
{
int i;
if (archivemode == ARCHIVE_WRITE) {
vec3_t nv = { vec[0], vec[1], vec[2]};
ArchiveSwapValue(nv, 3);
@@ -585,7 +587,6 @@ void Archiver::ArchiveVec3(vec3_t vec)
void Archiver::ArchiveVec4(vec4_t vec)
{
int i;
if (archivemode == ARCHIVE_WRITE) {
vec4_t nv = { vec[0], vec[1], vec[2], vec[3] };
ArchiveSwapValue(nv, 4);
@@ -784,8 +785,6 @@ void Archiver::ArchiveString(str *string)
}
}
} else {
fileSize_t s;
#ifndef NDEBUG
CheckWrite();
#endif
@@ -1124,7 +1123,8 @@ int Archiver::ReadType(void)
void Archiver::WriteType(int type)
{
archivefile.Write(&type, sizeof(type));
int nt = LittleLong(type);
archivefile.Write(&nt, sizeof(nt));
}
void Archiver::CheckType(int type)
@@ -1147,8 +1147,7 @@ void Archiver::CheckType(int type)
}
}
} else {
int nt = LittleLong(type);
archivefile.Write(&nt, sizeof(nt));
WriteType(type);
}
}
+2 -5
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.
@@ -22,8 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// archive.h: OpenMoHAA Archiver
#ifndef __ARCHIVE_H__
#define __ARCHIVE_H__
#pragma once
#include "g_local.h"
#include "class.h"
@@ -343,5 +342,3 @@ void con_map<key, value>::Archive(Archiver& arc)
arc.ArchiveInteger(&tempInt); \
(thing) = (type)tempInt; \
}
#endif // __ARCHIVE_H__
+2 -5
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.
@@ -22,8 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// armor.h: Standard armor that prevents a percentage of damage per hit.
#ifndef __ARMOR_H__
#define __ARMOR_H__
#pragma once
#include "weapon.h"
@@ -40,5 +39,3 @@ class Armor : public Item
qboolean Pickupable( Entity *other ) override;
};
#endif /* armor.h */
+325 -443
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.
@@ -30,7 +30,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
/*****************************************************************************
/*QUAKED func_barrel (0 0.25 0.5) ? INDESTRUCTABLE
Brush model barrel object
Bashing only makes thunk or gong sounds (depending on wether it's full or not)
Bashing only makes thunk or gong sounds (depending on whether it's full or not)
Bullets and explosions effects are dependant apon the type of barrel.
"barreltype" sets the type of barrel that it is. Valid settings are:
- "water" makes the barrel be filled with water.
@@ -45,562 +45,444 @@ Does nothing special at all. It's just a poor empty barrel. aww :(
******************************************************************************/
Event EV_Barrel_Think
(
(
"_barrel_think",
EV_DEFAULT,
NULL,
NULL,
"think function for a barrel."
);
);
Event EV_Barrel_Setup
(
(
"_barrel_setup",
EV_DEFAULT,
NULL,
NULL,
"Does the post spawn setup of the barrel"
);
);
Event EV_Barrel_SetType
(
(
"barreltype",
EV_DEFAULT,
"s",
"type",
"Sets the barrel's type"
);
);
CLASS_DECLARATION( Entity, BarrelObject, "func_barrel" )
{
{ &EV_Barrel_Setup, &BarrelObject::BarrelSetup },
{ &EV_Barrel_Think, &BarrelObject::BarrelThink },
{ &EV_Barrel_SetType, &BarrelObject::BarrelSetType },
{ &EV_Damage, &BarrelObject::BarrelDamaged },
{ &EV_Killed, &BarrelObject::BarrelKilled },
{ NULL, NULL }
CLASS_DECLARATION(Entity, BarrelObject, "func_barrel") {
{&EV_Barrel_Setup, &BarrelObject::BarrelSetup },
{&EV_Barrel_Think, &BarrelObject::BarrelThink },
{&EV_Barrel_SetType, &BarrelObject::BarrelSetType},
{&EV_Damage, &BarrelObject::BarrelDamaged},
{&EV_Killed, &BarrelObject::BarrelKilled },
{NULL, NULL }
};
BarrelObject::BarrelObject()
{
AddWaitTill(STRING_DEATH);
AddWaitTill(STRING_DEATH);
if (LoadingSavegame) {
return;
}
if (LoadingSavegame)
{
return;
}
edict->s.eType = ET_GENERAL;
edict->s.eType = ET_GENERAL;
m_iBarrelType = 0;
m_fFluidAmount = 0;
m_fHeightFluid = 0;
m_iBarrelType = 0;
m_fFluidAmount = 0;
m_fHeightFluid = 0;
for (int i = 0; i < MAX_BARREL_LEAKS; i++) {
m_bLeaksActive[i] = 0;
}
for( int i = 0; i < MAX_BARREL_LEAKS; i++ )
{
m_bLeaksActive[ i ] = 0;
}
m_fDamageSoundTime = 0;
mass = 500;
max_health = 75;
health = 75;
deadflag = DEAD_NO;
takedamage = DAMAGE_YES;
m_vJitterAngles = vec_zero;
m_fDamageSoundTime = 0;
mass = 500;
max_health = 75;
health = 75;
deadflag = DEAD_NO;
takedamage = DAMAGE_YES;
m_vJitterAngles = vec_zero;
PostEvent( EV_Barrel_Setup, EV_POSTSPAWN );
PostEvent(EV_Barrel_Setup, EV_POSTSPAWN);
}
int BarrelObject::PickBarrelLeak
(
void
)
int BarrelObject::PickBarrelLeak(void)
{
int iHighest;
float fHighestHeight;
int iHighest;
float fHighestHeight;
for( int i = 0; i < MAX_BARREL_LEAKS; i++ )
{
if( !m_bLeaksActive[ i ] ) {
return i;
}
}
for (int i = 0; i < MAX_BARREL_LEAKS; i++) {
if (!m_bLeaksActive[i]) {
return i;
}
}
fHighestHeight = m_vLeaks[ 0 ][ 2 ];
iHighest = 0;
fHighestHeight = m_vLeaks[0][2];
iHighest = 0;
for( int i = 1; i < MAX_BARREL_LEAKS; i++ )
{
if( m_vLeaks[ 0 ][ 2 ] > fHighestHeight )
{
fHighestHeight = m_vLeaks[ 0 ][ 2 ];
iHighest = i;
}
}
for (int i = 1; i < MAX_BARREL_LEAKS; i++) {
if (m_vLeaks[0][2] > fHighestHeight) {
fHighestHeight = m_vLeaks[0][2];
iHighest = i;
}
}
return iHighest;
return iHighest;
}
void BarrelObject::BarrelSetup
(
Event *ev
)
void BarrelObject::BarrelSetup(Event *ev)
{
setMoveType( MOVETYPE_PUSH );
setSolidType( SOLID_BSP );
setMoveType(MOVETYPE_PUSH);
setSolidType(SOLID_BSP);
m_vStartAngles = angles;
m_fJitterScale = 64.0f / size[ 2 ];
m_vStartAngles = angles;
m_fJitterScale = 64.0f / size[2];
m_fFluidAmount = size[ 0 ] * size[ 1 ] * size[ 2 ] / 150.0f;
m_fHeightFluid = m_fFluidAmount / size[ 2 ];
m_fFluidAmount = size[0] * size[1] * size[2] / 150.0f;
m_fHeightFluid = m_fFluidAmount / size[2];
// Position the barrel correctly
CheckGround();
// Position the barrel correctly
CheckGround();
}
void BarrelObject::BarrelSetType
(
Event *ev
)
void BarrelObject::BarrelSetType(Event *ev)
{
str sType = ev->GetString( 1 );
str sType = ev->GetString(1);
if( !sType.icmp( "oil" ) )
{
health = 75;
m_iBarrelType = BARREL_OIL;
if (!sType.icmp("oil")) {
health = 75;
m_iBarrelType = BARREL_OIL;
CacheResource( "models/fx/barrel_empty_destroyed.tik" );
CacheResource( "models/fx/barrel_oil_destroyed.tik" );
}
else if( !sType.icmp( "water" ) )
{
health = 75;
m_iBarrelType = BARREL_WATER;
CacheResource("models/fx/barrel_empty_destroyed.tik");
CacheResource("models/fx/barrel_oil_destroyed.tik");
} else if (!sType.icmp("water")) {
health = 75;
m_iBarrelType = BARREL_WATER;
CacheResource( "models/fx/barrel_empty_destroyed.tik" );
CacheResource( "models/fx/barrel_water_destroyed.tik" );
}
else if( !sType.icmp( "gas" ) )
{
spawnflags &= ~BARREL_INDESTRUCTABLE;
health = 75;
m_iBarrelType = BARREL_GAS;
CacheResource("models/fx/barrel_empty_destroyed.tik");
CacheResource("models/fx/barrel_water_destroyed.tik");
} else if (!sType.icmp("gas")) {
spawnflags &= ~BARREL_INDESTRUCTABLE;
health = 75;
m_iBarrelType = BARREL_GAS;
CacheResource( "models/fx/barrel_gas_destroyed.tik" );
}
else
{
health = 75;
m_iBarrelType = BARREL_EMPTY;
CacheResource("models/fx/barrel_gas_destroyed.tik");
} else {
health = 75;
m_iBarrelType = BARREL_EMPTY;
CacheResource( "models/fx/barrel_empty_destroyed.tik" );
}
CacheResource("models/fx/barrel_empty_destroyed.tik");
}
max_health = health;
max_health = health;
}
void BarrelObject::BarrelThink
(
Event *ev
)
void BarrelObject::BarrelThink(Event *ev)
{
int i;
int iBiggestLeak;
float fFluidTop;
int i;
int iBiggestLeak;
float fFluidTop;
iBiggestLeak = 0;
iBiggestLeak = 0;
fFluidTop = m_fFluidAmount / m_fHeightFluid + ( mins[ 2 ] + origin[ 2 ] );
for( i = 0; i < MAX_BARREL_LEAKS; i++ )
{
if( !m_bLeaksActive[ i ] ) {
continue;
}
fFluidTop = m_fFluidAmount / m_fHeightFluid + (mins[2] + origin[2]);
for (i = 0; i < MAX_BARREL_LEAKS; i++) {
if (!m_bLeaksActive[i]) {
continue;
}
// Send infos to clients
if( m_vLeaks[ i ][ 2 ] <= fFluidTop )
{
gi.SetBroadcastVisible( m_vLeaks[ i ], m_vLeaks[ i ] );
// Send infos to clients
if (m_vLeaks[i][2] > fFluidTop) {
gi.SetBroadcastVisible(m_vLeaks[i], m_vLeaks[i]);
if( m_vLeaks[ i ][ 2 ] <= fFluidTop - 1.3f )
{
if( m_vLeaks[ i ][ 2 ] <= fFluidTop - 3.0f )
{
// big leak
if (m_iBarrelType == BARREL_OIL) {
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_3));
} else {
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_7));
}
if( m_iBarrelType == BARREL_OIL )
{
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_1));
}
else
{
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_5));
}
gi.MSG_WriteCoord(m_vLeaks[i][0]);
gi.MSG_WriteCoord(m_vLeaks[i][1]);
gi.MSG_WriteCoord(m_vLeaks[i][2]);
gi.MSG_WriteDir(m_vLeakNorms[i]);
gi.MSG_EndCGM();
m_fFluidAmount -= 1.0f;
iBiggestLeak |= 4;
}
else
{
// medium leak
m_bLeaksActive[i] = qfalse;
} else {
gi.SetBroadcastVisible(m_vLeaks[i], m_vLeaks[i]);
if( m_iBarrelType == BARREL_OIL )
{
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_2));
}
else
{
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_6));
}
if (m_vLeaks[i][2] > fFluidTop - 1.3f) {
// small leak
m_fFluidAmount -= 0.75f;
iBiggestLeak |= 2;
}
}
else
{
// small leak
if (m_iBarrelType == BARREL_OIL) {
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_3));
} else {
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_7));
}
if( m_iBarrelType == BARREL_OIL )
{
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_3));
}
else
{
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_7));
}
m_fFluidAmount -= 0.5f;
iBiggestLeak |= 1;
} else if (m_vLeaks[i][2] > fFluidTop - 3.0f) {
// medium leak
m_fFluidAmount -= 0.5f;
iBiggestLeak |= 1;
}
if (m_iBarrelType == BARREL_OIL) {
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_2));
} else {
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_6));
}
gi.MSG_WriteCoord( m_vLeaks[ i ][ 0 ] );
gi.MSG_WriteCoord( m_vLeaks[ i ][ 1 ] );
gi.MSG_WriteCoord( m_vLeaks[ i ][ 2 ] );
gi.MSG_WriteDir( m_vLeakNorms[ i ] );
gi.MSG_EndCGM();
}
else
{
gi.SetBroadcastVisible( m_vLeaks[ i ], m_vLeaks[ i ] );
m_fFluidAmount -= 0.75f;
iBiggestLeak |= 2;
} else {
// big leak
if( m_iBarrelType == BARREL_OIL )
{
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_3));
}
else
{
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_7));
}
if (m_iBarrelType == BARREL_OIL) {
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_1));
} else {
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_5));
}
gi.MSG_WriteCoord( m_vLeaks[ i ][ 0 ] );
gi.MSG_WriteCoord( m_vLeaks[ i ][ 1 ] );
gi.MSG_WriteCoord( m_vLeaks[ i ][ 2 ] );
gi.MSG_WriteDir( m_vLeakNorms[ i ] );
gi.MSG_EndCGM();
m_fFluidAmount -= 1.0f;
iBiggestLeak |= 4;
}
m_bLeaksActive[ i ] = qfalse;
}
}
gi.MSG_WriteCoord(m_vLeaks[i][0]);
gi.MSG_WriteCoord(m_vLeaks[i][1]);
gi.MSG_WriteCoord(m_vLeaks[i][2]);
gi.MSG_WriteDir(m_vLeakNorms[i]);
gi.MSG_EndCGM();
}
}
if( m_vJitterAngles[ 0 ] == 0.0f && m_vJitterAngles[ 2 ] == 0.0f )
{
if( !VectorCompare( angles, m_vStartAngles ) )
{
setAngles( m_vStartAngles );
}
}
if (m_vJitterAngles[0] == 0.0f && m_vJitterAngles[2] == 0.0f) {
if (!VectorCompare(angles, m_vStartAngles)) {
setAngles(m_vStartAngles);
}
}
else {
Vector ang;
setAngles( Vector( m_vStartAngles[ 0 ] + m_vJitterAngles[ 0 ], m_vStartAngles[ 1 ], m_vStartAngles[ 2 ] + m_vJitterAngles[ 2 ] ) );
ang = m_vStartAngles;
ang[0] += m_vJitterAngles[0];
ang[2] += m_vJitterAngles[2];
setAngles(ang);
if( m_vJitterAngles[ 0 ] > 0.0f )
{
m_vJitterAngles[ 0 ] -= 1.f / 3.f * m_fJitterScale;
if (m_vJitterAngles[0] < 0) {
m_vJitterAngles[0] += 1.f / 3.f * m_fJitterScale;
if( m_vJitterAngles[ 0 ] > 0.0f )
{
m_vJitterAngles[ 0 ] = 0.0f;
}
}
else if( m_vJitterAngles[ 0 ] < 0.0f )
{
m_vJitterAngles[ 0 ] += 1.f / 3.f * m_fJitterScale;
if (m_vJitterAngles[0] > 0) {
m_vJitterAngles[0] = 0;
}
} else if (m_vJitterAngles[0] > 0) {
m_vJitterAngles[0] -= 1.f / 3.f * m_fJitterScale;
if( m_vJitterAngles[ 0 ] < 0.0f )
{
m_vJitterAngles[ 0 ] = 0.0f;
}
}
if (m_vJitterAngles[0] < 0) {
m_vJitterAngles[0] = 0;
}
}
m_vJitterAngles[ 0 ] = -m_vJitterAngles[ 0 ];
m_vJitterAngles[0] = -m_vJitterAngles[0];
if( m_vJitterAngles[ 2 ] > 0.0f )
{
m_vJitterAngles[ 2 ] -= 1.f / 3.f * m_fJitterScale;
if (m_vJitterAngles[2] < 0) {
m_vJitterAngles[2] += 1.f / 3.f * m_fJitterScale;
if( m_vJitterAngles[ 2 ] > 0.0f )
{
m_vJitterAngles[ 2 ] = 0.0f;
}
}
else if( m_vJitterAngles[ 2 ] < 0.0f )
{
m_vJitterAngles[ 2 ] += 1.f / 3.f * m_fJitterScale;
if (m_vJitterAngles[2] > 0) {
m_vJitterAngles[2] = 0;
}
} else if (m_vJitterAngles[2] > 0) {
m_vJitterAngles[2] -= 1.f / 3.f * m_fJitterScale;
if( m_vJitterAngles[ 2 ] < 0.0f )
{
m_vJitterAngles[ 2 ] = 0.0f;
}
}
if (m_vJitterAngles[2] < 0) {
m_vJitterAngles[2] = 0;
}
}
m_vJitterAngles[ 2 ] = -m_vJitterAngles[ 2 ];
m_vJitterAngles[2] = -m_vJitterAngles[2];
}
// Check for at least one active leak to play a sound
for( i = 0; i < MAX_BARREL_LEAKS; i++ )
{
if( m_bLeaksActive[ i ] ) {
break;
}
}
// Check for at least one active leak to play a sound
for (i = 0; i < MAX_BARREL_LEAKS; i++) {
if (m_bLeaksActive[i]) {
break;
}
}
// Play a leak sound
if( i != MAX_BARREL_LEAKS && iBiggestLeak )
{
if( !( iBiggestLeak & 4 ) )
{
if( iBiggestLeak & 2 )
{
// medium leak
LoopSound( "liquid_leak", 0.60f, -1.0f, -1.0f, 0.90f );
}
else
{
// small leak
LoopSound( "liquid_leak", 0.30f, -1.0f, -1.0f, 0.80f );
}
}
else
{
// big leak
LoopSound( "liquid_leak", 1.0f, -1.0f, -1.0f, 1.0f );
}
}
// Play a leak sound
if (i != MAX_BARREL_LEAKS && iBiggestLeak) {
if (iBiggestLeak & 4) {
// big leak
LoopSound("liquid_leak", 1, -1, -1, 1);
} else if (iBiggestLeak & 2) {
// medium leak
LoopSound("liquid_leak", 0.6, -1, -1, 0.9);
} else {
// small leak
LoopSound("liquid_leak", 0.3, -1, -1, 0.8);
}
}
if( i == MAX_BARREL_LEAKS ) {
StopLoopSound();
}
if (i == MAX_BARREL_LEAKS) {
StopLoopSound();
}
if( m_vJitterAngles[ 0 ] || m_vJitterAngles[ 2 ] || i < MAX_BARREL_LEAKS )
{
m_fLastEffectTime += 0.075f;
if (m_vJitterAngles[0] || m_vJitterAngles[2] || i < MAX_BARREL_LEAKS) {
m_fLastEffectTime += 0.075f;
if( level.time >= m_fLastEffectTime )
{
m_fLastEffectTime = level.time + 0.075f;
}
if (m_fLastEffectTime <= level.time) {
m_fLastEffectTime = level.time + 0.075f;
}
PostEvent( EV_Barrel_Think, m_fLastEffectTime - level.time );
}
PostEvent(EV_Barrel_Think, m_fLastEffectTime - level.time);
}
}
void BarrelObject::BarrelDamaged
(
Event *ev
)
void BarrelObject::BarrelDamaged(Event *ev)
{
Vector vDir;
Vector vForward;
Vector vRight;
int iDamage;
int iMeansOfDeath;
Vector vHitPos;
Vector vHitDirection;
Vector vHitNormal;
Vector vDir;
Vector vForward;
Vector vRight;
int iDamage;
int iMeansOfDeath;
Vector vHitPos;
Vector vHitDirection;
Vector vHitNormal;
if( !takedamage )
{
return;
}
if (!takedamage) {
return;
}
iDamage = ev->GetInteger( 2 );
iMeansOfDeath = ev->GetInteger( 9 );
vHitPos = ev->GetVector( 4 );
vHitDirection = ev->GetVector( 5 );
vHitNormal = ev->GetVector( 6 );
iDamage = ev->GetInteger(2);
iMeansOfDeath = ev->GetInteger(9);
vHitPos = ev->GetVector(4);
vHitDirection = ev->GetVector(5);
vHitNormal = ev->GetVector(6);
vDir = ( vHitDirection - vHitNormal ) * 0.5f;
AngleVectors( angles, vForward, vRight, NULL );
vDir = (vHitDirection - vHitNormal) * 0.5f;
AngleVectors(angles, vForward, vRight, NULL);
m_vJitterAngles[ 0 ] += DotProduct( vDir, vForward ) * m_fJitterScale * 0.0275f * ( float )iDamage;
m_vJitterAngles[ 2 ] += DotProduct( vDir, vRight ) * m_fJitterScale * 0.0275f * ( float )iDamage;
m_vJitterAngles[0] += DotProduct(vDir, vForward) * m_fJitterScale * 0.0275f * (float)iDamage;
m_vJitterAngles[2] += DotProduct(vDir, vRight) * m_fJitterScale * 0.0275f * (float)iDamage;
if( m_vJitterAngles[ 0 ] > m_fJitterScale * 1.5f )
{
m_vJitterAngles[ 0 ] = m_fJitterScale * 1.5f;
}
else if( m_vJitterAngles[ 0 ] < -( m_fJitterScale * 1.5f ) )
{
m_vJitterAngles[ 0 ] = -( m_fJitterScale * 1.5f );
}
if (m_vJitterAngles[0] > m_fJitterScale * 1.5f) {
m_vJitterAngles[0] = m_fJitterScale * 1.5f;
} else if (m_vJitterAngles[0] < -(m_fJitterScale * 1.5f)) {
m_vJitterAngles[0] = -(m_fJitterScale * 1.5f);
}
if( m_vJitterAngles[ 2 ] > m_fJitterScale * 1.5f )
{
m_vJitterAngles[ 2 ] = m_fJitterScale * 1.5f;
}
else if( m_vJitterAngles[ 2 ] < -( m_fJitterScale * 1.5f ) )
{
m_vJitterAngles[ 2 ] = -( m_fJitterScale * 1.5f );
}
if (m_vJitterAngles[2] > m_fJitterScale * 1.5f) {
m_vJitterAngles[2] = m_fJitterScale * 1.5f;
} else if (m_vJitterAngles[2] < -(m_fJitterScale * 1.5f)) {
m_vJitterAngles[2] = -(m_fJitterScale * 1.5f);
}
if( !( spawnflags & BARREL_INDESTRUCTABLE ) )
{
if( ( iMeansOfDeath == MOD_VEHICLE || iMeansOfDeath == MOD_ROCKET ||
iMeansOfDeath == MOD_GRENADE || iMeansOfDeath == MOD_EXPLODEWALL ||
iMeansOfDeath == MOD_EXPLOSION || m_iBarrelType == BARREL_GAS ) &&
iMeansOfDeath != MOD_BASH
)
{
if( iDamage >= health )
{
PostEvent( EV_Killed, 0.01f );
takedamage = DAMAGE_NO;
return;
}
if (!(spawnflags & BARREL_INDESTRUCTABLE)) {
if ((iMeansOfDeath == MOD_VEHICLE || iMeansOfDeath == MOD_ROCKET || iMeansOfDeath == MOD_GRENADE
|| iMeansOfDeath == MOD_EXPLODEWALL || iMeansOfDeath == MOD_EXPLOSION || m_iBarrelType == BARREL_GAS)
&& iMeansOfDeath != MOD_BASH) {
if (iDamage >= health) {
PostEvent(EV_Killed, 0.01f);
takedamage = DAMAGE_NO;
return;
}
if( m_iBarrelType == BARREL_GAS )
{
iDamage /= 2;
if (m_iBarrelType == BARREL_GAS) {
iDamage /= 2;
health -= iDamage;
if( health < 1.0f )
health = 1.0f;
}
}
}
health -= iDamage;
if (health < 1.0f) {
health = 1.0f;
}
}
}
}
if( !EventPending( EV_Barrel_Think ) )
{
m_fLastEffectTime = level.time - 0.075f;
ProcessEvent( EV_Barrel_Think );
}
if (!EventPending(EV_Barrel_Think)) {
m_fLastEffectTime = level.time - 0.075f;
ProcessEvent(EV_Barrel_Think);
}
if( m_iBarrelType <= BARREL_WATER )
{
int index = PickBarrelLeak();
if (m_iBarrelType <= BARREL_WATER) {
int index = PickBarrelLeak();
if( vHitPos[ 2 ] <= m_fFluidAmount / m_fHeightFluid + origin[ 2 ] + mins[ 2 ] )
{
m_bLeaksActive[ index ] = qtrue;
m_vLeaks[ index ] = vHitPos;
m_vLeakNorms[ index ] = vHitNormal;
if (vHitPos[2] <= m_fFluidAmount / m_fHeightFluid + origin[2] + mins[2]) {
m_bLeaksActive[index] = qtrue;
m_vLeaks[index] = vHitPos;
m_vLeakNorms[index] = vHitNormal;
gi.SetBroadcastVisible( vHitPos, vHitPos );
gi.SetBroadcastVisible(vHitPos, vHitPos);
if( m_iBarrelType == BARREL_OIL )
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_4));
else
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_8));
}
else
{
gi.SetBroadcastVisible( vHitPos, vHitPos );
if (m_iBarrelType == BARREL_OIL) {
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_4));
} else {
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_8));
}
} else {
gi.SetBroadcastVisible(vHitPos, vHitPos);
if( m_iBarrelType == BARREL_OIL )
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_3));
else
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_7));
}
if (m_iBarrelType == BARREL_OIL) {
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_3));
} else {
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_EFFECT_7));
}
}
gi.MSG_WriteCoord( vHitPos[ 0 ] );
gi.MSG_WriteCoord( vHitPos[ 1 ] );
gi.MSG_WriteCoord( vHitPos[ 2 ] );
gi.MSG_WriteDir( vHitNormal );
gi.MSG_EndCGM();
}
gi.MSG_WriteCoord(vHitPos[0]);
gi.MSG_WriteCoord(vHitPos[1]);
gi.MSG_WriteCoord(vHitPos[2]);
gi.MSG_WriteDir(vHitNormal);
gi.MSG_EndCGM();
}
}
void BarrelObject::BarrelKilled
(
Event *ev
)
void BarrelObject::BarrelKilled(Event *ev)
{
float fFluidTop;
Vector vPos;
str sModel;
float fFluidTop;
Vector vPos;
str sModel;
setSolidType( SOLID_NOT );
PostEvent( EV_Remove, 0.05f );
setSolidType(SOLID_NOT);
PostEvent(EV_Remove, 0.05f);
vPos[ 2 ] = ( mins[ 2 ] + origin[ 2 ] );
fFluidTop = m_fFluidAmount / m_fHeightFluid + vPos[ 2 ];
vPos[2] = (mins[2] + origin[2]);
fFluidTop = m_fFluidAmount / m_fHeightFluid + vPos[2];
if( m_iBarrelType == BARREL_GAS )
{
RadiusDamage(
centroid,
this,
this,
200,
this,
MOD_EXPLOSION,
350,
24 );
if (m_iBarrelType == BARREL_GAS) {
RadiusDamage(centroid, this, this, 200, this, MOD_EXPLOSION, 350, 24);
sModel = "models/fx/barrel_gas_destroyed.tik";
}
else if( m_iBarrelType == BARREL_WATER )
{
if( vPos[ 2 ] + 0.25f * maxs[ 2 ] <= fFluidTop )
{
sModel = "models/fx/barrel_water_destroyed.tik";
}
else
{
sModel = "models/fx/barrel_empty_destroyed.tik";
}
}
else if( m_iBarrelType == BARREL_OIL )
{
if( vPos[ 2 ] + 0.25f * maxs[ 2 ] > fFluidTop )
{
sModel = "models/fx/barrel_empty_destroyed.tik";
}
else
{
RadiusDamage(
centroid,
this,
this,
200,
this,
MOD_EXPLOSION,
350,
24 );
sModel = "models/fx/barrel_gas_destroyed.tik";
} else if (m_iBarrelType == BARREL_WATER) {
if (vPos[2] + 0.25f * maxs[2] <= fFluidTop) {
sModel = "models/fx/barrel_water_destroyed.tik";
} else {
sModel = "models/fx/barrel_empty_destroyed.tik";
}
} else if (m_iBarrelType == BARREL_OIL) {
if (vPos[2] + 0.25f * maxs[2] > fFluidTop) {
sModel = "models/fx/barrel_empty_destroyed.tik";
} else {
RadiusDamage(centroid, this, this, 200, this, MOD_EXPLOSION, 350, 24);
sModel = "models/fx/barrel_oil_destroyed.tik";
}
}
else
{
sModel = "models/fx/barrel_empty_destroyed.tik";
}
sModel = "models/fx/barrel_oil_destroyed.tik";
}
} else {
sModel = "models/fx/barrel_empty_destroyed.tik";
}
Animate *exp = new Animate;
Animate *exp = new Animate;
// Spawn an explosion effect
exp->edict->s.renderfx |= RF_DONTDRAW;
exp->setModel( sModel );
// Spawn an explosion effect
exp->edict->s.renderfx |= RF_DONTDRAW;
exp->setModel(sModel);
vPos = origin + ( maxs + mins ) * 0.5f;
vPos = origin + (maxs + mins) * 0.5f;
exp->setAngles( Vector( -90, 0, 0 ) );
exp->setOrigin( vPos );
exp->NewAnim( "idle" );
exp->setAngles(Vector(-90, 0, 0));
exp->setOrigin(vPos);
exp->NewAnim("idle");
exp->PostEvent( EV_Remove, 0.1f );
exp->Unregister( STRING_DEATH );
exp->PostEvent(EV_Remove, 0.1f);
exp->Unregister(STRING_DEATH);
}
+46 -53
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.
@@ -22,73 +22,66 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// barrels.h : Barrels
#ifndef __BARRELOBJECT_H__
#define __BARRELOBJECT_H__
#pragma once
#include "entity.h"
#define BARREL_INDESTRUCTABLE 1
#define MAX_BARREL_LEAKS 4
#define BARREL_INDESTRUCTABLE 1
#define MAX_BARREL_LEAKS 4
enum
{
BARREL_EMPTY,
BARREL_OIL,
BARREL_WATER,
BARREL_GAS
enum {
BARREL_EMPTY,
BARREL_OIL,
BARREL_WATER,
BARREL_GAS
};
class BarrelObject : public Entity {
int m_iBarrelType;
float m_fFluidAmount;
float m_fHeightFluid;
qboolean m_bLeaksActive[ MAX_BARREL_LEAKS ];
Vector m_vLeaks[ MAX_BARREL_LEAKS ];
Vector m_vLeakNorms[ MAX_BARREL_LEAKS ];
Vector m_vJitterAngles;
Vector m_vStartAngles;
float m_fJitterScale;
float m_fLastEffectTime;
float m_fDamageSoundTime;
class BarrelObject : public Entity
{
int m_iBarrelType;
float m_fFluidAmount;
float m_fHeightFluid;
qboolean m_bLeaksActive[MAX_BARREL_LEAKS];
Vector m_vLeaks[MAX_BARREL_LEAKS];
Vector m_vLeakNorms[MAX_BARREL_LEAKS];
Vector m_vJitterAngles;
Vector m_vStartAngles;
float m_fJitterScale;
float m_fLastEffectTime;
float m_fDamageSoundTime;
public:
CLASS_PROTOTYPE( BarrelObject );
CLASS_PROTOTYPE(BarrelObject);
BarrelObject();
BarrelObject();
int PickBarrelLeak( void );
int PickBarrelLeak(void);
void BarrelSetup( Event *ev );
void BarrelSetType( Event *ev );
void BarrelThink( Event *ev );
void BarrelDamaged( Event *ev );
void BarrelKilled( Event *ev );
void BarrelSetup(Event *ev);
void BarrelSetType(Event *ev);
void BarrelThink(Event *ev);
void BarrelDamaged(Event *ev);
void BarrelKilled(Event *ev);
void Archive( Archiver& arc ) override;
void Archive(Archiver& arc) override;
};
inline void BarrelObject::Archive
(
Archiver& arc
)
inline void BarrelObject::Archive(Archiver& arc)
{
Entity::Archive( arc );
Entity::Archive(arc);
arc.ArchiveInteger( &m_iBarrelType );
arc.ArchiveFloat( &m_fFluidAmount );
arc.ArchiveFloat( &m_fHeightFluid );
arc.ArchiveVector( &m_vJitterAngles );
arc.ArchiveVector( &m_vStartAngles );
arc.ArchiveFloat( &m_fJitterScale );
arc.ArchiveFloat( &m_fLastEffectTime );
arc.ArchiveFloat( &m_fDamageSoundTime );
arc.ArchiveInteger(&m_iBarrelType);
arc.ArchiveFloat(&m_fFluidAmount);
arc.ArchiveFloat(&m_fHeightFluid);
arc.ArchiveVector(&m_vJitterAngles);
arc.ArchiveVector(&m_vStartAngles);
arc.ArchiveFloat(&m_fJitterScale);
arc.ArchiveFloat(&m_fLastEffectTime);
arc.ArchiveFloat(&m_fDamageSoundTime);
for( int i = MAX_BARREL_LEAKS - 1; i >= 0; i-- )
{
arc.ArchiveBoolean( &m_bLeaksActive[ i ] );
arc.ArchiveVector( &m_vLeaks[ i ] );
arc.ArchiveVector( &m_vLeakNorms[ i ] );
}
for (int i = MAX_BARREL_LEAKS - 1; i >= 0; i--) {
arc.ArchiveBoolean(&m_bLeaksActive[i]);
arc.ArchiveVector(&m_vLeaks[i]);
arc.ArchiveVector(&m_vLeakNorms[i]);
}
}
#endif // __BARRELOBJECT_H__
+2 -5
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.
@@ -20,8 +20,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __BASEIMP_H__
#define __BASEIMP_H__
#pragma once
#ifdef __cplusplus
extern "C" {
@@ -86,5 +85,3 @@ void CacheResource( const char *name );
#ifdef __cplusplus
}
#endif
#endif
Loaded 100 of 453 files, more files were not shown because too many files have changed in this diff. Show more