Compare commits

...
981 Commits
Author SHA1 Message Date
smallmodel 08d97e0277 Added snd_miles source files 2024-01-07 23:50:02 +01:00
smallmodel 21d0675035 Using vec3_t instead of a pointer to float 2024-01-07 23:42:32 +01:00
smallmodel 1dfb81917c Added public driver functions 2024-01-07 23:38:57 +01:00
smallmodel af8c92f090 Added public OPENAL driver declarations 2024-01-07 23:36:32 +01:00
smallmodel 04e0242422 Added source files for OpenAL FAKK (unimplemented) 2024-01-07 20:10:53 +01:00
pryon 110ffc3a01 Implement UIField (#90)
* Implement UIField

* Formatting and naming fixes

- Ran clang-format on previously modified files
- Replaced ifdef guards with `#pragma once`
- Changed wording in comments above OPM-only changes for easier searchability
2024-01-04 23:51:16 +01:00
smallmodel 6b4a8bd627 Fixed jumpstart modheight not working on AA 2024-01-02 23:32:06 +01:00
smallmodel 0d851fdb68 Players now get correct weapons depending on the target game version 2024-01-02 18:38:21 +01:00
smallmodel 5064f2c16d Added g_target_game 2024-01-02 18:30:46 +01:00
smallmodel ac46d0eef0 Added sv_minplayers variable 2024-01-02 18:14:13 +01:00
smallmodel 70c71b69ee Added a feature to let each team have their own objective location 2024-01-02 00:52:25 +01:00
smallmodel 4487113c58 Fixed dlight image name 2024-01-01 23:52:38 +01:00
smallmodel 983f5b9ca4 Fixed UI sounds 2024-01-01 23:17:09 +01:00
smallmodel 13612d3de9 r_fastdlights is not a cheat-protected cvar 2024-01-01 22:52:08 +01:00
smallmodel 6317ca7183 Fixed the origin of cone emitters 2024-01-01 22:33:05 +01:00
smallmodel 2b96aac1c8 PointToSelectionPoint: the p parameter must be a constant 2024-01-01 21:57:49 +01:00
smallmodel a6b75aefa4 Implemented UIMultiLineEdit 2024-01-01 20:34:50 +01:00
smallmodel 7dc72b435e Formatted multiline edit source file 2024-01-01 15:57:44 +01:00
smallmodel 5a586f4700 Implemented UIHorizScroll 2024-01-01 15:45:40 +01:00
smallmodel ef50a5f2cd Prepared UIHorizScroll for implementation 2024-01-01 15:01:23 +01:00
smallmodel c2c3f6aa1b Implemented miniconsole 2024-01-01 14:53:16 +01:00
smallmodel 9c8ca98e68 Added anisotropic filtering 2024-01-01 14:25:02 +01:00
smallmodel 3a18c9f327 Fixed PrintJustified virtual parameter 2024-01-01 01:53:23 +01:00
smallmodel 9438f6497d Added partial implementations 2024-01-01 01:50:10 +01:00
smallmodel 5c3c3f8e70 Finished View3D implementation (implemented PrintSound, LocationPrint, DrawSubtitleOverlay, and CenterPrint) 2024-01-01 01:42:44 +01:00
smallmodel 3d3c99cd22 Formatted cl_uiview3d source files 2024-01-01 00:32:31 +01:00
smallmodel b3464e620e Updated features implementation 2023-12-31 23:43:30 +01:00
smallmodel 72a38b0b68 Implemented UIDialog 2023-12-31 23:43:22 +01:00
smallmodel 46e7f29820 Fixed dialog bad cancel command 2023-12-31 23:43:05 +01:00
smallmodel cb36015a38 Updated features implementation 2023-12-31 23:15:22 +01:00
smallmodel 66cb10a3bf Added a fix that reset the viewangles if it is NaN 2023-12-31 23:14:22 +01:00
smallmodel bfdd99a028 Added m_parent to get values from parent 2023-12-31 23:13:24 +01:00
smallmodel 63ef75222e Added isVirtual and getVirtualScale 2023-12-31 23:12:40 +01:00
smallmodel 072ba0a38f Fixed fullbright light not setting the colors correctly 2023-12-31 22:15:19 +01:00
smallmodel 576869bda0 Fixed UIFakkLabel::Draw() implementation 2023-12-31 22:02:59 +01:00
smallmodel 0d556b1b40 Implemented cl_invrender 2023-12-31 22:02:47 +01:00
smallmodel 0cd217b484 Fixed RB_Sphere_SetupGlobals() setting up sphere in leafs when there is no world loaded 2023-12-31 21:53:13 +01:00
smallmodel 907255837e Added INV_ALIGN_NONE 2023-12-31 15:35:00 +01:00
smallmodel ebf33349a3 Added EV_ClearInvItemReference declaration 2023-12-31 15:34:53 +01:00
smallmodel ea6920b711 Added CL_Key_ForceCommand 2023-12-31 15:34:45 +01:00
smallmodel 53a47d470a Implemented cl_inv 2023-12-31 14:19:57 +01:00
smallmodel 7fe7b6ce79 Formatted cl_inv* source files 2023-12-31 13:32:46 +01:00
smallmodel 0110704abd Fixed after a map change when setting sv_maxclients 2023-12-31 01:17:16 +01:00
smallmodel aca23fc62f Fixed call vote button not working 2023-12-31 01:01:38 +01:00
smallmodel c0a284927e Fixed vote item name being empty 2023-12-31 00:53:26 +01:00
smallmodel 2d911c37a4 Added vote commands for cgame 2023-12-31 00:39:43 +01:00
smallmodel 1e7af27227 Fixed DM map selection having the incorrect map path 2023-12-31 00:38:41 +01:00
smallmodel 06678a8b0a Added UI_MultiplayerMainMenuWidgetsUpdate from mohaas/mohaab 2023-12-31 00:38:22 +01:00
smallmodel e1706610c4 Fixed versions for mohaas server 2023-12-30 23:52:25 +01:00
smallmodel 7bb940d819 Implemented LAN game list 2023-12-30 23:03:56 +01:00
smallmodel b4e0120428 Using ioquake3 code for IPv6 support and network fixes 2023-12-30 23:03:49 +01:00
smallmodel db1013d926 Use clc.connectStartTime instead of clc.connectTime 2023-12-30 22:59:57 +01:00
smallmodel 759dacd345 Added com_gamename 2023-12-30 21:36:54 +01:00
smallmodel 903fd28953 set cls.bNewLocalServerInfo to tell when there are new local servers 2023-12-30 21:10:27 +01:00
smallmodel 6c520babf0 Make sure to register the material for each GetMaterial() call 2023-12-30 21:09:23 +01:00
smallmodel 9bb2fda6df Fixed events declaration 2023-12-30 19:50:15 +01:00
smallmodel d48b37ece1 Implemented UIGlobalGameList 2023-12-30 19:18:59 +01:00
smallmodel f4164e84e1 Made fields and methods protected instead of private 2023-12-30 19:18:54 +01:00
smallmodel 33aabadaf5 Implemented FAKK Load game class 2023-12-30 19:09:48 +01:00
smallmodel e815fda908 Fixed save's comment being set to the filename 2023-12-30 19:09:31 +01:00
smallmodel fe04adee1d Formatted source files 2023-12-30 17:36:01 +01:00
smallmodel 115647a8c0 Use ApplyPlayerModel/GetPlayerModel from mohaab 2.40 2023-12-30 17:23:30 +01:00
smallmodel ddd70eadf6 Exported PM_FilenameToDisplayname and PM_DisplaynameT 2023-12-30 17:23:11 +01:00
smallmodel 319e00214e Refactored DeactivateCurrentSmart 2023-12-30 17:11:25 +01:00
smallmodel 6bdcfc2b6f Fixed PassEventToWidget improperly passing events to widgets not matching the name 2023-12-30 17:11:12 +01:00
smallmodel ae0a2238da Set mouse position with player model 2023-12-30 16:55:06 +01:00
smallmodel a69f9fe88b Implemented UI player model picker 2023-12-30 16:54:57 +01:00
smallmodel 696b57f990 Formatted uWinMan source file 2023-12-30 16:54:46 +01:00
smallmodel 998c1b78c7 Added all picker models from mohaa 1.0 up to mohaab 2.40 2023-12-30 14:10:06 +01:00
smallmodel 8c207f094d Implemented PMPickerItem and added name parameter to FileSelected/FileChosen methods 2023-12-30 02:22:41 +01:00
smallmodel 09c9c0ef51 Added UI map rotation from BT 2.40 2023-12-30 01:59:03 +01:00
smallmodel 8cd571c96c Implemented all UIListBox methods and implemented Draw() from BT 2.40 2023-12-30 01:50:12 +01:00
smallmodel 979af2925d Fixed hide commands and show commands not executing properly 2023-12-30 01:09:11 +01:00
smallmodel f092eab842 Added InsertItem() and setCurrentItem() for UIListBox 2023-12-30 00:03:21 +01:00
smallmodel 3d4832ca85 Formatted uilistbox source files 2023-12-30 00:01:14 +01:00
smallmodel b120fc6f2f Fixed sorting being wrong 2023-12-29 23:03:08 +01:00
smallmodel c299ad92aa Improver UI_DMMapSelect_f for SH/BT 2023-12-29 22:06:49 +01:00
smallmodel 956cd59385 Implemented MP map picker 2023-12-29 22:06:36 +01:00
smallmodel acbd802790 Make COM_IsMapValid always return true from now 2023-12-29 21:59:23 +01:00
smallmodel c4bcecf5e0 Added COM_IsMapValid 2023-12-29 21:24:23 +01:00
smallmodel 09949251ac Implemented cl_uisoundpicker 2023-12-29 20:23:42 +01:00
smallmodel 43218f1685 Use a const str& reference 2023-12-29 20:19:28 +01:00
smallmodel eb7d01b3e7 Implemented cl_uimaprunner 2023-12-29 20:18:04 +01:00
smallmodel c58e6d58b4 Filter "_sml" maps for maplist 2023-12-29 20:05:36 +01:00
smallmodel 3a892e1a47 Implemented file picker class 2023-12-29 20:05:29 +01:00
smallmodel 5bb487e1fa Set default parameter for fontname 2023-12-29 20:04:57 +01:00
smallmodel 4ae091be4b Added a slash at the end of the scripts folder name 2023-12-29 19:56:34 +01:00
smallmodel 7654ab6be6 FS_ListFilteredFiles: Fixed subdirectory listing and added support for searching multiple extensions 2023-12-29 19:56:23 +01:00
smallmodel 193cc9dc10 Added FS_FileTime (unimplemented) 2023-12-29 18:59:06 +01:00
smallmodel a6d268e1a1 Added subdirectory and directory search support for FS_ListFilteredFiles 2023-12-29 18:27:41 +01:00
smallmodel 7822e94e61 Formatted picker source files 2023-12-29 14:38:55 +01:00
smallmodel eb663fdbc1 Fixed a crash due to subtitle when there is no player 2023-12-28 21:08:07 +01:00
smallmodel c738a40c05 Fixed links 2023-12-28 21:03:58 +01:00
smallmodel 2ca3443b7f Moved Playing with bots section to getting_started_running.md doc 2023-12-28 21:02:05 +01:00
smallmodel 06be4c03fa Use htmlpreview to open the g_allclasses.html file 2023-12-28 20:59:43 +01:00
smallmodel 32d77f4a7d Split README into multiple docs 2023-12-28 20:54:05 +01:00
smallmodel d217b1d561 Fixed some events having wrong parameters for documentation 2023-12-28 20:50:47 +01:00
smallmodel 0167f0a3a4 Using Added in OPM comments 2023-12-28 20:35:33 +01:00
smallmodel 4304ad0faa Fixed weapon attachment not correcting properly 2023-12-28 19:16:54 +01:00
smallmodel 3be17376e4 Fixed wrong landmine defuse direction 2023-12-28 18:55:43 +01:00
smallmodel 0b4fd4c17e Fixed isabandoned returning 1 if the player has a landmine 2023-12-28 18:53:32 +01:00
smallmodel 66c4499b2e Fixed ScriptThreadLabel::Execute with other/owner param 2023-12-28 18:30:15 +01:00
smallmodel cde13177a4 Don't set the ground entity in Entity::droptofloor 2023-12-28 18:22:10 +01:00
smallmodel 9fce2575ab Commented out the code that makes triggers only respond to killed/activate messages 2023-12-28 18:21:58 +01:00
smallmodel 8f8e92c8c3 Don't cound the number of shots if the owner is the world 2023-12-28 17:47:18 +01:00
smallmodel 8683d317fe Set origin2 and player's num shots fired when placing landmine 2023-12-28 17:45:53 +01:00
smallmodel 1178c619bc Fixed variables not being restored properly 2023-12-28 17:31:36 +01:00
smallmodel 2fa568eb01 CL_KeyEvent must not handle GUI mouse events, as it's the job of the UIWindowManager 2023-12-28 17:26:32 +01:00
smallmodel d62242d653 use PRINT_WARNING instead of PRINT_DEVELOPER when an image couldn't be found 2023-12-28 17:25:51 +01:00
smallmodel 991bf2f1f5 Fixed m_firstResponder being nulled out in UIWindowManager::getFirstResponder() 2023-12-28 17:21:56 +01:00
smallmodel 2f241343ff Don't accept the bind for null and pause keys 2023-12-28 17:21:32 +01:00
smallmodel 035de09c15 Formatted cl_keys.cpp source file 2023-12-28 17:21:02 +01:00
smallmodel d3a4407391 Make sure to not service a view event if the first responder is NULL 2023-12-28 13:04:29 +01:00
smallmodel 395c16ce24 Fixed bind label selection 2023-12-28 12:50:40 +01:00
smallmodel f7accc01ad Fixed bind selection and highlight 2023-12-28 12:47:27 +01:00
smallmodel 3733154e63 Fixed alternate binding not working properly 2023-12-28 01:29:46 +01:00
smallmodel 2ef95ddba9 Fixed improper binding and text location 2023-12-28 01:29:33 +01:00
smallmodel 043f8cba22 Implemented UIFakkBindList and UIFakkBindListLabel 2023-12-28 01:12:43 +01:00
smallmodel 09ab172630 Added UIBindButton events 2023-12-28 01:12:19 +01:00
smallmodel c23a182bec Added bindlistener events 2023-12-28 01:11:17 +01:00
smallmodel c321470382 Implemented CL_LoadBind 2023-12-27 22:53:49 +01:00
smallmodel 932bdd402c Implemented UIBindButton 2023-12-27 22:47:01 +01:00
smallmodel 3692671f49 Implemented bind_t and bindlistener 2023-12-27 20:19:58 +01:00
smallmodel 1cd4c35a79 Bumped version number 2023-12-27 18:54:57 +01:00
smallmodel c0f7a48649 Formatted ui source files 2023-12-27 18:54:20 +01:00
smallmodel c1258f160b Do not clear sv_fps cvar when restarting/switching map 2023-12-27 18:43:37 +01:00
smallmodel bdb9feb7c5 Updated README 2023-12-27 18:18:45 +01:00
smallmodel 830cbe7af2 Fixed issues with animation when sv_fps was above 20 2023-12-27 18:04:41 +01:00
smallmodel 4eb83c0766 Fixed weapon attachments not being detached 2023-12-27 16:29:00 +01:00
smallmodel 210f2fef77 Formatted source file 2023-12-27 16:28:28 +01:00
smallmodel d19a6160d2 Call SetWeaponAnim() instead of NewAnim() for weapon animation 2023-12-27 16:25:37 +01:00
smallmodel cd773cf73f Set last active weapon only if the weapon is not an inventory item 2023-12-27 16:13:12 +01:00
smallmodel f3b9a10f7a Detach weapons already attached to the attach tag only if the current weapon attach tag is valid 2023-12-27 15:54:55 +01:00
smallmodel 709283ff33 Fixed MAX_ACTIVE_WEAPONS check (out of bounds) 2023-12-27 15:49:33 +01:00
smallmodel fae261d7da UI game message fix 2023-12-27 15:43:28 +01:00
smallmodel 6b5e527b6b Fixed callvote line breaks 2023-12-27 15:38:17 +01:00
smallmodel b7005a310e Fixed callvote still executing kick with an invalid player 2023-12-27 15:14:08 +01:00
smallmodel edd25b9264 Readded support for supporting configstrings in multiple chunks 2023-12-27 15:13:42 +01:00
smallmodel 65a8b03ee4 Fixed infinite loop in SV_SendConfigstring when sending multiple chunks 2023-12-27 15:13:17 +01:00
smallmodel 0044ec0ac0 Increased MAX_CMD_LINE for testing purposes 2023-12-27 15:11:17 +01:00
smallmodel 73111d854d Fixed an infinite loop bug when selecting the previous/next weapon 2023-12-27 14:07:57 +01:00
smallmodel 065ab98175 Added a comment in CondMinChargeTime about the crash fix 2023-12-27 14:07:34 +01:00
smallmodel cbeaeba828 Use IsSubclassOfWeapon() and IsSubclassOfPlayer() 2023-12-27 14:06:22 +01:00
smallmodel 7af2a9444e Updated paragraph about bug reports 2023-12-26 18:40:54 +01:00
smallmodel f476f3690a Another README update 2023-12-26 12:22:37 +01:00
smallmodel fae02da4b1 Updated README 2023-12-26 12:14:38 +01:00
smallmodel b0e4e29ce3 Merge pull request #88 from pryon/misc-fixes
Misc fixes
2023-12-20 19:34:26 +01:00
pryon 11f7728b9d Move strdup'd string cleanup to uipopup_describe's dtor 2023-12-20 17:52:02 +01:00
pryon 7510b05d25 Properly free memory allocated by strdup calls 2023-12-18 19:56:26 +01:00
pryon e467f91262 Fix pulldown menu labels showing raw cvar values 2023-12-18 17:49:01 +01:00
pryon b03afb899d Add thirdparties dir and generated parser/lexer files to .gitignore 2023-12-18 17:46:52 +01:00
pryon ec71ff3c3c Implement UIPopupMenu (#87)
* Implement UIPopupMenu

* Use `std::fmax` for floats
2023-12-17 22:51:18 +01:00
smallmodel 02ce50ace2 Treat "not all control paths return a value" warning as an error 2023-12-07 18:32:10 +01:00
smallmodel 4a4a552a05 Fixed crash due to corrupted stack values 2023-12-07 18:04:57 +01:00
pryon 5b3615d262 Implement UIPulldownMenuContainer (#86)
* Implement UIPulldownMenuContainer

* Review suggestions:
 - remove unnecessary extern declarations
 - add comment about a possible memleak
2023-12-05 23:27:27 +01:00
pryon 2821488c93 Implement UIPulldownMenu (#85)
* Implement UIPulldownMenu

* Remove unnecessary value-type member initialization
2023-12-05 19:50:41 +01:00
smallmodel 9814887b10 Don't execute Git if the source directory is not a working Git repo 2023-11-29 19:04:24 +01:00
smallmodel 3f86381541 Only allow builds on branches (and not tags), as tags are built during the deployment 2023-11-29 18:18:30 +01:00
smallmodel 7736966dc1 Fixed the README 2023-11-29 18:17:14 +01:00
smallmodel 60faa9dd9b Updated the version number 2023-11-29 17:57:47 +01:00
smallmodel 75f8f86f86 Fixed compilation error on some compilers 2023-11-29 00:08:35 +01:00
smallmodel 0ee1307e75 Fixed missing m_Thread archive 2023-11-28 20:26:40 +01:00
smallmodel f0c38305b5 Fixed defaultEntry having a NULL value even if there are elements 2023-11-28 20:13:55 +01:00
smallmodel e07dda6991 Fixed defaultEntry not being initialized after archiving 2023-11-28 20:10:23 +01:00
smallmodel b10ce9a426 Added GetKey() / SetKey() in con_set's Entry, so ScriptVariable can override it and set the key appropriately 2023-11-28 19:50:19 +01:00
smallmodel 2ac2800ecb Only archive used variables on the local VM stack 2023-11-28 19:14:09 +01:00
smallmodel e59200a7de Fixed cSpline archiving bad values 2023-11-27 20:35:23 +01:00
smallmodel a7902a8837 Added FollowPathRelativeYaw and NormalAngles 2023-11-27 20:30:36 +01:00
smallmodel 615726cc75 Added FollowPathRelativeYaw 2023-11-27 20:22:37 +01:00
smallmodel 839abf6076 Added missing variables to archive 2023-11-27 20:20:00 +01:00
smallmodel c7c8d4580d Added missed archived variables and using a ScriptThreadLabel instead of an event for the killed handler 2023-11-27 20:07:57 +01:00
smallmodel 2cc47e10f9 Added missing iNextLandTime archived variable 2023-11-27 20:06:19 +01:00
smallmodel 8fc5dacebf Removed bBindChilds unused variable + added more variables to archive 2023-11-27 20:06:05 +01:00
smallmodel cb23f3bb70 Added missing weapon_class archived variable 2023-11-27 20:05:36 +01:00
smallmodel d7350d8629 Added Clear() method in ScriptThreadLabel 2023-11-27 20:05:21 +01:00
smallmodel ac6b5ef1f7 Fixed wrong area portal writing 2023-11-27 19:37:29 +01:00
smallmodel 7fdd26c59e Added m_fHealRate archived variable 2023-11-27 19:37:26 +01:00
smallmodel fad555308b Archive ScriptVM and ScriptThread appropriately 2023-11-27 19:30:40 +01:00
smallmodel 969255c48e Fixed areaPortals being broken after reading from archive 2023-11-26 20:44:21 +01:00
smallmodel 433305617c IsAlive: check if the given listener is an actual entity 2023-11-26 20:38:14 +01:00
smallmodel 5418d84c7e Fixed m_fpsTiki being uninitialized when archiving 2023-11-26 20:36:23 +01:00
smallmodel cca37e3dfe Added and using SAVEGAME_STRUCT_VERSION 2023-11-26 20:33:07 +01:00
smallmodel 0e9d83ee14 Added a check to debug the total of archived items 2023-11-26 20:31:58 +01:00
smallmodel ecbf7f6caa Fixed Archive method not calling parent class archive method 2023-11-26 20:00:12 +01:00
smallmodel 5a3638fa68 Better for loop clarity 2023-11-26 19:55:07 +01:00
smallmodel 111088b540 Formatted document 2023-11-26 19:54:07 +01:00
smallmodel ba1703ebf0 When loading an entity from archive, set the model only if the entity allows model to be archived 2023-11-26 19:49:51 +01:00
smallmodel 825df20a72 Fixed game being stuck on mission stats screen in single-player 2023-11-26 19:30:54 +01:00
smallmodel 0a42fd79d2 Clear radar on cgame shutdown 2023-11-26 19:30:28 +01:00
smallmodel e50a041c12 SimpleEntity subclass flags name now starts with ECF_ prefix 2023-11-16 23:17:06 +01:00
smallmodel ce0e9fe77e Added portable turret anim blends + fixed anim blends 2023-11-16 23:03:04 +01:00
smallmodel 5105dcce04 Updated version patch number 2023-11-15 23:17:37 +01:00
smallmodel 58b4a9a676 Added bullet alpha (from moh 2.0 and above) 2023-11-15 21:02:34 +01:00
smallmodel 1146c834fb Fixed bad bullet coords being sent 2023-11-15 21:02:23 +01:00
smallmodel 9068264132 Make sure to remove the view model and detach the player when the turret gun is being removed 2023-11-15 20:42:16 +01:00
smallmodel 59ac8ea437 Clear the partial immobile flag when initializing the player's physics 2023-11-15 20:41:41 +01:00
smallmodel afafacaeec Fixed bullet tracer issues with multiple bullets 2023-11-15 20:41:35 +01:00
smallmodel baf451d2a2 Cleaned up bg_public 2023-11-15 20:39:09 +01:00
smallmodel d588012168 Don't use ANIM_MASK 2023-11-15 19:45:58 +01:00
smallmodel a3ed25cb2e Use WEAPON_CLASS_ITEM1 instead of raw 256 constant value 2023-11-15 19:36:29 +01:00
smallmodel c399f45841 Weapon::SetItemSlot() fixed missing bitwise negate 2023-11-15 19:36:09 +01:00
smallmodel 6a6eeae4ee Updated README 2023-11-14 18:53:40 +01:00
smallmodel 65f36505d1 Updated README 2023-11-14 18:05:50 +01:00
smallmodel b852980842 Fixed bullet tracer speed 2023-11-14 17:55:08 +01:00
smallmodel d351ced78b Added comment for sv_pure 2023-11-14 17:54:53 +01:00
smallmodel 4cd45c63c4 Return fs_gamedir in FS_GetCurrentGameDir() 2023-11-14 17:39:12 +01:00
smallmodel de16a72aed Using droperror instead of print 2023-11-14 17:31:49 +01:00
smallmodel 4b29c63fc9 Added ioq3 features like bans 2023-11-14 17:30:17 +01:00
smallmodel 770e832592 Added Com_strCompare and player name completion 2023-11-14 17:17:36 +01:00
smallmodel 14f9acdb57 Fixed "spin" event name 2023-11-14 14:09:52 +01:00
smallmodel 573a6f5bd5 Updated README 2023-11-14 14:06:57 +01:00
smallmodel 8c64b7aa89 Clear charge start time on respawn 2023-11-14 14:06:39 +01:00
smallmodel 8d49f8935c Added mode parm for IS_WEAPONCLASS_READY_TO_FIRE
This fixes issues with animation being stuck on secondary grenade charge
2023-11-14 14:04:37 +01:00
smallmodel ff8ec63e95 Call IsRepeatType() instead of checking the animFlags 2023-11-14 14:03:23 +01:00
smallmodel 771ee1b5a9 Forward-declare Event and Listener to omit some warnings 2023-11-14 01:08:09 +01:00
smallmodel 096692fec8 Fixed usage of 2D vector array 2023-11-14 01:07:23 +01:00
smallmodel d29454b44d Use %zu instead of %d 2023-11-14 01:06:52 +01:00
smallmodel 30a1ccb2e2 Made stateString const char* 2023-11-14 01:04:22 +01:00
smallmodel ea1b411cc0 Forward-declare skelHeaderGame_s and skelAnimFrame_s to omit some warnings 2023-11-14 01:02:27 +01:00
smallmodel 7794ee8aea Mark Archive() method 'override' 2023-11-14 00:54:20 +01:00
smallmodel 99a9022b53 Fixed Italian player not switching to the Breda weapon after spawning 2023-11-14 00:50:35 +01:00
smallmodel 1255964e6b Added a fix that prevent players from equipping weapons from the other team 2023-11-14 00:49:32 +01:00
smallmodel 37de859bee Fixed field var breaking code position on exception 2023-11-14 00:16:09 +01:00
smallmodel 990aa5cdb2 Initialize m_iBadPlaceIndex to 0 2023-11-14 00:06:26 +01:00
smallmodel befcedcf58 Fixed OPCODE_STORE_FIELD_REF incorrectly not skipping field on exception
It would cause invalid opcode afterwards.
2023-11-14 00:06:23 +01:00
smallmodel eeb697570d Fixed collapse index still being processed with SKB files (would cause crashes) 2023-11-14 00:04:42 +01:00
smallmodel 6410567e9a Initialize obfuscation mapping (still unimplemented) 2023-11-13 23:44:04 +01:00
smallmodel bde7242cc7 Added more screenshots 2023-11-13 23:31:22 +01:00
smallmodel e8aad97975 Fixed alignment issue on ARM CPUs 2023-11-13 23:28:42 +01:00
smallmodel 0662359776 Implemented DamageEvent() / EventGetActivator()
For example, the script in the training map waittill damage on the crate's trigger for bullets, DamageEvent() will unregister the damage event
2023-11-13 22:20:16 +01:00
smallmodel 5568d160ab Fixed uninitialized shader variable in CG_DrawCrosshair() 2023-11-13 22:18:38 +01:00
smallmodel defa297a56 Fixed debug lines being always drawn 2023-11-13 20:39:03 +01:00
smallmodel 782c37c4fe Updated version number 2023-11-13 20:38:49 +01:00
smallmodel 6f03c88ad5 Formatted playerbot source file 2023-11-13 20:33:06 +01:00
smallmodel 3ec980c8ec Fixed bots being blocked 2023-11-13 20:31:50 +01:00
smallmodel c0a50eb2ff Fixed infinite spectator switch loop 2023-11-13 20:31:41 +01:00
smallmodel f73e4b6f22 Check if the turret is valid before detaching remote owner 2023-11-13 20:30:51 +01:00
smallmodel 096972827e Fixed half of archived entities being deleted during restart 2023-11-13 19:35:46 +01:00
smallmodel 08c040d4ea Reset smoke sprites during restart 2023-11-13 19:34:13 +01:00
smallmodel 6d8b6b5f29 Fixed objectives text 2023-11-13 19:25:52 +01:00
smallmodel 410f1c0ed8 Only include listener.h when compiling C++ 2023-11-13 18:36:20 +01:00
smallmodel cb73cfd57b Fixed "unknown game mode" error 2023-11-13 18:23:26 +01:00
smallmodel 8cb8a7f370 Fixed objectives being wrong 2023-11-13 18:23:15 +01:00
smallmodel 8c893acfff Don't spawn the initial player if the game isn't single-player 2023-11-13 18:23:01 +01:00
smallmodel e453d1fa17 Added "none" for teamwin argument 2023-11-13 18:22:35 +01:00
smallmodel a7301ed7b6 Fixed teamwin not working on TOW and Liberation 2023-11-13 18:21:08 +01:00
smallmodel 42ebfd5394 Added ScriptSimpleStrafingGunfire and ScriptAimedStrafingGunfire from moh 2.0 and above 2023-11-13 17:46:33 +01:00
smallmodel cdf2f84b14 Added ScriptModelRealDamage class 2023-11-13 16:33:11 +01:00
smallmodel 2592aeab8b Fixed improper bullet path on wood and metal 2023-11-13 01:21:08 +01:00
smallmodel 34d4225ea0 Trigger must have CONTENTS_CLAYPIDGEON content mask set if it has DAMAGE spawnflag set when setting the model 2023-11-13 01:20:19 +01:00
smallmodel 17dcb4b00e Entity's clipmask must be MASK_SOLID 2023-11-13 00:58:33 +01:00
smallmodel eb1d096539 Fixed vehicle turret gun indefinitely shaking 2023-11-13 00:35:55 +01:00
smallmodel 05c74655be Fixed SimpleActor::SetPath not setting path correctly 2023-11-13 00:35:32 +01:00
smallmodel 3e0e0ba3b1 Fixed FindCover() wrong algorithm 2023-11-13 00:35:11 +01:00
smallmodel f90b6cd18c Fixed State_Turret_Wait() not checking if enemy can shoot, and fixed last enemy visible time not being set 2023-11-13 00:34:26 +01:00
smallmodel f0ecfcb708 Updated README 2023-11-12 21:51:09 +01:00
pryon 177702d027 Implement UISlider (#79)
* Implement UISlider

* Use proper enum type for the left and right arrow key constants
2023-11-12 16:39:22 +00:00
pryon 64429232f8 Add missing virtual calls to UIList methods (#80)
* Add missing virtual calls to UIList methods

* Add missing virtual call in UICheckBox::Draw
2023-11-12 16:39:04 +00:00
smallmodel d6b7fecb69 Refactored navigation with moh 2.0 features 2023-11-09 23:44:53 +01:00
smallmodel 51a0ee56aa Refactored FindNearestSniperNode() 2023-11-09 21:55:28 +01:00
smallmodel 2ed369568c Fixed AllocPathNode() and FreePathNode() not working as intended 2023-11-09 21:10:43 +01:00
smallmodel e5b7e16d1a Added AI_CONCEALMENT_MASK and use AI_LOW_WALL_ARC 2023-11-09 21:10:20 +01:00
smallmodel 4a9f676d5d Tidied up FindPathX methods 2023-11-09 21:01:30 +01:00
smallmodel 0e0da3d767 Added MASK_CORNER_NODE 2023-11-09 21:01:03 +01:00
smallmodel 343ce4a6a7 Using vec3_t type for start/end/position 2023-11-09 19:58:46 +01:00
smallmodel df8b854cb7 Cleaned up GeneratePath methods 2023-11-09 19:52:53 +01:00
smallmodel 831dc770d8 Added droptofloor() 2023-11-09 19:37:25 +01:00
smallmodel 8a9285c64f Cleaned up navigate source files and added low-wall arc 2023-11-09 19:31:20 +01:00
smallmodel 7e4e06b09d Fixed FinishReloading not working properly 2023-11-08 22:24:07 +01:00
smallmodel 96748b3fbc Fixed vote's last text position 2023-11-07 23:06:11 +01:00
smallmodel f1325048e9 Fixed crosshair's endpos friend test 2023-11-07 23:05:54 +01:00
smallmodel deee21eb68 Fixed vote string alignment position 2023-11-07 23:02:07 +01:00
smallmodel 2f43e5c5ea Fixed crosshair friend icon on mohaa 1.11 2023-11-07 23:01:49 +01:00
smallmodel 4766067edb Fixed crosshair incorrectly hiding 2023-11-07 22:54:05 +01:00
smallmodel bc54f22639 Crosshair is now handled by the cgame module 2023-11-07 22:44:13 +01:00
smallmodel 20c8c87e79 Draw vote and crosshair 2023-11-07 22:43:13 +01:00
smallmodel 3a5dcd6a3c Increased MAX_BUFFERS 2023-11-07 22:34:04 +01:00
smallmodel a5ba02c2bb Added crosshair variables 2023-11-07 19:30:46 +01:00
smallmodel e1554efc08 Fixed paused icon location 2023-11-07 19:20:52 +01:00
smallmodel 9d652dd41b Unpause if the game module doesn't allow pausing 2023-11-07 19:20:40 +01:00
smallmodel 22eadf2c08 Removed code that prevent pausing in debug builds 2023-11-07 19:20:26 +01:00
smallmodel d3f1b62208 Added pause command 2023-11-07 19:20:07 +01:00
smallmodel affc28ab79 Removed win32/unix folders (unused) 2023-11-07 18:57:34 +01:00
smallmodel 41be7f44ab Added comment 2023-11-06 20:45:57 +01:00
smallmodel 646c1f0f16 Fixed lightorigin and attach offset being badly calculated 2023-11-06 19:58:36 +01:00
smallmodel 3cea097b48 Added EV_Turret_SetMaxUseAngle and EV_Turret_SetStartYaw to TurretGun's event responses 2023-11-06 19:41:34 +01:00
smallmodel 786d72575e Fixed buggy sky rendering 2023-11-06 19:32:49 +01:00
smallmodel 6d9a794aaf Fixed assertion failed when numskins equals MAX_TIKI_SHADER 2023-11-06 19:17:03 +01:00
smallmodel 9e69df1e94 Check for valid model and anim num in **TIKI_Anim_NameForNum()** 2023-11-06 19:09:06 +01:00
smallmodel 72d4bb0206 Added more checks to avoid crashes 2023-11-06 18:59:18 +01:00
smallmodel f68e06a949 Use MAX_TIKI_ALIASES instead of the constant number (4095) 2023-11-06 18:30:11 +01:00
smallmodel f4da539d95 Use vec3_t type for coordinates/angles 2023-11-06 18:11:12 +01:00
smallmodel 17af75a9bb Formatted TIKI source files 2023-11-06 18:08:53 +01:00
smallmodel dcbb39d640 Formatted skeletor source files 2023-11-06 17:58:58 +01:00
smallmodel d0ba1df4e0 G_BroadcastAIEvent: ignore non-actor and non-bots 2023-11-05 21:02:07 +01:00
smallmodel 2b92869683 Moved eAIEvent enum to entity.h 2023-11-05 21:00:41 +01:00
smallmodel 379a4b0ce4 Fixed AI not being able to open doors 2023-11-05 20:58:37 +01:00
smallmodel d4c7d4a7e1 Avoid broadcasting to AI if the entity has notarget set 2023-11-05 20:58:25 +01:00
smallmodel dcac24c9e2 Fixed EventStopAtEnd() incorrectly stopping the vehicle 2023-11-05 20:39:04 +01:00
smallmodel 753589d840 Made TriggerSave only trigger once 2023-11-05 20:37:37 +01:00
smallmodel 382903c9e1 Added cSpline() constructor (sets points to 0) 2023-11-05 20:09:39 +01:00
smallmodel f29fec0b31 Formatted spline source file 2023-11-05 19:09:29 +01:00
smallmodel f9dc37d60a Fixed HudPrint using argument 0 instead of 1 for the message 2023-11-04 19:02:24 +01:00
smallmodel c5e48c67bb Return "unarmed" for item prefix/name that cannot be found 2023-11-04 19:02:08 +01:00
smallmodel cc62ebcffc Don't display an error for viewmodelanim fps tiki 2023-11-04 19:01:48 +01:00
smallmodel 0f36504959 Implemented vote options for cgame module 2023-11-04 18:43:10 +01:00
smallmodel 1fb8e25209 Use PRId64 and PRIu64 format specifier for sprintf in str with 64-bit int constructor 2023-11-04 00:41:06 +01:00
smallmodel 260876b1a2 Always print messages to console regardless of whether or not it's a game message / death message 2023-11-04 00:23:49 +01:00
smallmodel e4fc074f09 Formatted cl_ui source files 2023-11-04 00:22:35 +01:00
smallmodel 7899e5161e Add a newline at the end of dmmessage errors 2023-11-04 00:20:27 +01:00
smallmodel 95603b1142 Convert chat prefix for localization 2023-11-04 00:08:53 +01:00
smallmodel bf8e0eb812 Other player was not receiving the private message 2023-11-04 00:05:18 +01:00
smallmodel 0c04ffc1e8 Added and implemented InfoLandmark 2023-11-03 22:10:14 +01:00
smallmodel bd86acf118 EV_REMOVE should be -9.0 2023-11-03 22:07:43 +01:00
smallmodel 6caa16444e Return an str for battle language instead of const char* 2023-11-03 22:00:49 +01:00
smallmodel 94d4cbeb82 Enhanced Player's dmmessage implementation (say + voice) 2023-11-03 21:56:31 +01:00
smallmodel b31f4bc00c Added and implemented CG_xxxVote functions 2023-11-03 21:28:46 +01:00
smallmodel cf0808e119 Added client vote options code (partially implemented) 2023-11-03 21:09:18 +01:00
smallmodel 92333909fd Fixed commands being executed twice 2023-11-03 20:40:45 +01:00
smallmodel 9c68af92be Added more console commands to initialize 2023-11-02 20:23:45 +01:00
smallmodel bc5d7f5e93 Added "reloadmap" console command from moh 2.0 and above 2023-11-02 20:20:58 +01:00
smallmodel f2ba9a88be Reimplemented G_ScriptCmd() 2023-11-02 20:15:08 +01:00
smallmodel 81b711364e Use Event::Exists() instead of getting it, to see if an event exists 2023-11-02 20:14:34 +01:00
smallmodel 554e0c7fac Formatted gamecmds source files 2023-11-02 20:07:29 +01:00
smallmodel bd2c1c387b Added Event::Exists() to check if a given command name exists 2023-11-02 20:05:59 +01:00
smallmodel f19edac9ca Fixed audio spatialization
The yaw was inverted specifically for the Miles Sound System. But as the engine was never using Miles, the yaw mustn't be inverted
2023-11-02 19:57:46 +01:00
smallmodel 1698f6d1bf The return value of an event must be the first value 2023-11-02 19:53:26 +01:00
smallmodel 2c3180813a Fixed improper path lookahead 2023-11-02 19:33:10 +01:00
smallmodel a262fe5d9d Removed pAnimThread assert as it can be NULL 2023-11-02 19:11:44 +01:00
smallmodel a69249ee22 Fixed an issue where PathAvoidsSquadMates() would set bad coordinates for path 2023-11-02 19:11:29 +01:00
smallmodel 393c2a81d1 Check for indice bounds 2023-11-01 23:06:14 +01:00
smallmodel 3a6be342ce Added new ScriptModel functions from mohaas 2.0 and above 2023-11-01 22:35:07 +01:00
smallmodel 6616bfe53e Formatted document 2023-11-01 22:21:09 +01:00
smallmodel bafe60f48f Move must fail if the Actor wants to become a runner but the idle think state is neither Runner nor Patrol 2023-11-01 20:16:44 +01:00
smallmodel e306c415f0 Only move the client if there is no turret or if the turret doesn't allow user's aim 2023-11-01 20:15:44 +01:00
smallmodel 56a8c8d48d Set parm.owner, prevent to trigger non-use trigger with EV_USE, set projectile owner 2023-11-01 20:10:57 +01:00
smallmodel 421f1d39a4 SV_HitEntity must return true if something was hit 2023-11-01 20:09:46 +01:00
smallmodel 7c655944a5 Convert fields name to lower 2023-11-01 19:16:01 +01:00
smallmodel 0a27f37dc0 Set the last entity network time
This fixes Actor sometimes stuck on idle state
2023-11-01 18:03:29 +01:00
smallmodel 4695932ea1 Added StoppedNotify()
This fixes scripts waiting for another executing script which fixes Actor being stuck on some animations
2023-11-01 17:31:46 +01:00
smallmodel 7fe7a12167 In CreateThreadInternal and CreateScriptInternal, use GetScriptClass() directly from ScriptThread 2023-11-01 16:53:31 +01:00
smallmodel f9487b0ba3 Ignore CR in source line 2023-11-01 16:53:09 +01:00
smallmodel 7c5c34741c Added more script trace and initialize state to STATE_EXECUTION in ScriptVM constructor 2023-11-01 16:52:30 +01:00
smallmodel d09459f4bf Made Unpause() more explicit 2023-10-31 23:24:11 +01:00
smallmodel c0c6598151 Actor::WeaponSound() was not properly working 2023-10-31 23:23:29 +01:00
smallmodel f52fcc6f0e Process the parent of each entity correctly 2023-10-31 23:22:43 +01:00
smallmodel 2e9ef64bd2 g_timescripts misspell 2023-10-31 23:21:55 +01:00
smallmodel ff3ee39830 Fixed field name not showing in the exception message 2023-10-31 20:39:28 +01:00
smallmodel abd757f3bc Actor health must be above to 0 for NPC to count 2023-10-30 23:01:43 +01:00
smallmodel c741591a36 Syntax clarity 2023-10-30 23:00:21 +01:00
smallmodel 78c481d725 Added g_shownpc support 2023-10-30 23:00:07 +01:00
smallmodel b2ece37819 Added G_ClientDrawTags() 2023-10-30 22:59:39 +01:00
smallmodel a557b29ecf Removed useless SetDirty() call in ScriptMaster::SetTime() 2023-10-30 22:59:25 +01:00
smallmodel 1184843318 Set dirty timer in SetTime() 2023-10-30 22:59:04 +01:00
smallmodel dd1f8bd92a Compare with STATE_RUNNING instead 2023-10-30 22:46:59 +01:00
smallmodel 220c82954c Don't execute script thread now if paused 2023-10-30 22:46:50 +01:00
smallmodel 8879bacb1d Fixed Think_Curious() and LookAtCuriosity() small mistakes 2023-10-30 22:04:09 +01:00
smallmodel 5824022745 Added ScriptRemove 2023-10-30 22:03:37 +01:00
smallmodel 3ecb5bd06a Fixed WaitExecuteThreadInternal() waiting on the group instead of the thread 2023-10-30 21:59:47 +01:00
smallmodel 7de31a776b Added a check to avoid freeing a model that is used more than once 2023-10-29 20:40:37 +01:00
smallmodel 503320d13f Added modelOnly parameter to CG_ProcessConfigString + added votes 2023-10-29 20:40:07 +01:00
smallmodel bd263c5d22 Added condition to check for null model/animation and for out of bound animnum in TIKI_Frame_Commands() 2023-10-29 20:21:58 +01:00
smallmodel b0201aef5d Set number of arguments when constructing a new Event 2023-10-29 20:20:56 +01:00
smallmodel 31014808c8 Added and using AI_COVER_MASK 2023-10-29 20:20:19 +01:00
smallmodel 0906124867 Use CurrentThink() to get the current think 2023-10-28 00:01:57 +02:00
smallmodel 43bb5ce653 Fixed BroadcastEvent not returning true with 1 processed listener + Fixed UnregisterTarget not removing the name 2023-10-27 21:03:07 +02:00
smallmodel 7e66483b1a Added g_timescripts var 2023-10-27 21:02:25 +02:00
smallmodel f96b606a1a Fixed ScriptThread timing 2023-10-27 21:02:18 +02:00
smallmodel 30d26c3e44 Fixed register/unregistration 2023-10-27 20:42:01 +02:00
smallmodel 57e450a745 Thread state fix 2023-10-27 20:41:47 +02:00
smallmodel 24297bf396 Added timescript in ScriptMaster::ExecuteRunning() 2023-10-27 20:02:21 +02:00
smallmodel 481cd760a9 Added ScriptTrace/GetSourcePos 2023-10-27 20:00:48 +02:00
smallmodel 6d6043775e Use const unsigned char* for sourcepos 2023-10-27 19:59:29 +02:00
smallmodel bb97ec8933 Added GetSourceAt() with code pos 2023-10-27 19:59:15 +02:00
smallmodel dc028b87e4 Added const unsigned char* hashcode 2023-10-27 19:58:38 +02:00
smallmodel 0d1b7a9c8a Added int64 support 2023-10-27 19:58:29 +02:00
smallmodel a6e602af1d Renamed variables in ScriptClass::RemoveThread for more clarification 2023-10-26 20:18:50 +02:00
smallmodel 04a6012e5d Renamed thread parameters 2023-10-26 20:17:53 +02:00
smallmodel 0f7691c722 Reordered NotifyDelete switch statement for more clarity 2023-10-26 20:17:42 +02:00
smallmodel f01a0a17c1 Added script traces 2023-10-26 20:13:07 +02:00
smallmodel b291ab92b6 Fixed script class being always created even when a thread was started in the same group 2023-10-26 20:08:09 +02:00
smallmodel fb4bf4fcaa Fixed wrong value() for GetGameScript in CreateScriptInternal() 2023-10-26 20:07:49 +02:00
smallmodel 98816156d7 Delete created scriptclass / thread when there is an exception, in ScriptThreadLabel::Create() 2023-10-26 19:58:26 +02:00
smallmodel 92bfb4c426 Fixed clarity of conditions in Animate::UseSyncTime() 2023-10-26 19:57:39 +02:00
smallmodel cac883c4a0 Drop error to main menu if an hard script exception was encountered while executing running scripts 2023-10-24 23:18:44 +02:00
smallmodel 5a4fb90c96 Fixed THINKSTATE_ATTACK animation inside ChangeAnim() + weight should be 2.0 for ChangeMotionAnim() 2023-10-24 23:16:45 +02:00
smallmodel c4f9eb65ae Use SetWeight() and SetOnceType() instead of setting the frameinfo directly 2023-10-24 22:55:46 +02:00
smallmodel 9f5557b33c Initialize bHasThrowTarget 2023-10-24 22:55:22 +02:00
smallmodel 4d876fdf5d Fixed wrong state being ended in EndState() 2023-10-24 21:35:49 +02:00
smallmodel 978666c946 AssertValidSquad() in DisbandSquadMate() 2023-10-24 21:35:16 +02:00
smallmodel 9b9fa696e8 Added Waypoint and TempWaypoint constructor to set the SimpleEntity subclass type 2023-10-24 20:37:41 +02:00
smallmodel 088b22073c Formatted document 2023-10-24 20:36:53 +02:00
smallmodel 4f9831faa4 Formatted document 2023-10-24 20:27:18 +02:00
smallmodel 3373caa939 DebugNearestStartNode() should return a node only if node_count is higher than 0 2023-10-24 19:37:48 +02:00
smallmodel dc1be17b2a Added badPlaceTeam 2023-10-24 19:35:42 +02:00
smallmodel 64a3b04181 Fixed CM_SightTraceThroughBrush() implementation 2023-10-24 19:29:38 +02:00
smallmodel 57e1920b9c G_SightTrace: only return true if the result is true 2023-10-24 19:29:20 +02:00
smallmodel ddb6236eb9 simplified delta subtraction 2023-10-23 22:55:35 +02:00
smallmodel 4e4af590e5 Added m_pAnimThread assertion check 2023-10-23 22:55:09 +02:00
smallmodel a249f6b29b Fixed parm.previousthread not being actually set to the previous executing thread 2023-10-23 19:31:01 +02:00
smallmodel 7787729b24 Fixed standidentify scr file 2023-10-23 19:26:57 +02:00
smallmodel 45c8c704af Fixed ai_debugpath having an infinite line 2023-10-23 18:58:16 +02:00
smallmodel 31fde1ad94 Unreachable node fix 2023-10-23 18:57:56 +02:00
smallmodel bfb0fbd656 Fixed vision_distance being used even if it's 0 2023-10-23 18:57:44 +02:00
smallmodel 8afb7457c2 Fixed FindPotentialCover never setting found nodes 2023-10-23 17:28:52 +02:00
smallmodel 0ae1c8f771 Fixed origin_ratio uninitialized 2023-10-23 17:28:36 +02:00
smallmodel 6ff046ae29 When spawning pathnodes, use archived instance of pathnodes 2023-10-23 17:17:56 +02:00
smallmodel 6f9f845bb2 Set m_LoadIndex to 0 when loading archived nodes 2023-10-23 17:16:54 +02:00
smallmodel 00033c3a70 SPAWNFLAG_DETAIL must be 0x1000 2023-10-23 15:56:27 +02:00
smallmodel acf71610df Don't inhibit pathnodes 2023-10-23 15:56:14 +02:00
smallmodel 86e9ae343a Don't move to patorl current node with m_bPatrolWaitTrigger 2023-10-23 15:55:58 +02:00
smallmodel 9bbd546d4c Replaced glbs with g_local 2023-10-23 15:54:48 +02:00
smallmodel 31f2573b28 Fixed animations not playing correctly 2023-10-23 14:46:44 +02:00
smallmodel 4d7fcb77c2 Use ANIM_WEIGHT_MOTION enum 2023-10-23 14:46:17 +02:00
smallmodel da02a8c73a Fixed frame delta being wrong 2023-10-23 14:46:01 +02:00
smallmodel dd0b4505a6 Fixed bad pathing 2023-10-23 12:39:09 +02:00
smallmodel eaff26216a Added MASK_ACTORPATH 2023-10-23 12:23:47 +02:00
smallmodel e850dd1963 Make sure to prevent to transition to curious if curious isn't enabled (moh 2.30 feature) 2023-10-23 11:59:06 +02:00
smallmodel cf61ae0332 Fixed crash when driver's client is null 2023-10-22 21:16:07 +02:00
smallmodel 5cffe3fb05 Fixed infinite loop with ai_debugpath 2023-10-22 21:15:58 +02:00
smallmodel b996918d3b Formatted navigate source files 2023-10-22 21:06:43 +02:00
smallmodel 4a9f9a45c2 Fixed infinite loop in SimpleActor::ShortenPathToAvoidSquadMates() 2023-10-22 21:03:39 +02:00
smallmodel 3a75772005 Fixed g_mmove algorithm 2023-10-22 21:03:25 +02:00
smallmodel c196e31c6c Formatted g_mmove.cpp 2023-10-22 20:25:54 +02:00
smallmodel 60ceff5ae0 Initialize is_paused member variable 2023-10-22 20:16:46 +02:00
smallmodel 34a4a0c892 HandleKilled() didn't handle the last param 2023-10-22 20:16:36 +02:00
smallmodel 2a3c42d47b Fixed MINS/MAXS bounding box (especially for Actor) 2023-10-22 20:16:22 +02:00
smallmodel 0b1f796e0a Fixed format string 2023-10-22 20:16:10 +02:00
smallmodel 766d4d23bf Incremented MAX_LOOPBACK otherwise the client would drop the gamestate while loading 2023-10-22 19:47:43 +02:00
smallmodel 6860a1e992 Crash fix 2023-10-22 19:45:48 +02:00
smallmodel 70c628d759 Finalized actor_turret 2023-10-22 17:30:37 +02:00
smallmodel 6eff8bc273 Finalized actor_weaponless 2023-10-22 16:34:15 +02:00
smallmodel 0b1e8cdbf3 Finalized actor_runner 2023-10-22 16:28:06 +02:00
smallmodel 6f58b34f87 Finalized actor_patrol 2023-10-22 16:26:28 +02:00
smallmodel adf081ba3c Finalized actor_pain 2023-10-22 16:23:33 +02:00
smallmodel 6d4a9fde3f Finalized actor_noclip 2023-10-22 16:20:29 +02:00
smallmodel 5a5cc4ea17 Finalized actor_machinegunner 2023-10-22 16:14:52 +02:00
smallmodel 69df583508 Finalized actor_killed 2023-10-22 15:45:08 +02:00
smallmodel 18506d9932 Finalized actor_idle 2023-10-22 15:42:36 +02:00
smallmodel f076e7609e Finalized actor_grenade 2023-10-22 15:41:19 +02:00
smallmodel 0b0d053044 Implemented Projectile::SetMartyr 2023-10-22 15:41:13 +02:00
smallmodel ce7dfdd986 Fixed/finalized actor_dog 2023-10-22 15:03:12 +02:00
smallmodel 50e589f27c Finalized actor_disguise 2023-10-22 14:56:41 +02:00
smallmodel e904dafa38 Finalized actor_curious 2023-10-22 14:29:02 +02:00
smallmodel 6a210fa212 Finalized actor_cover source file 2023-10-21 17:18:49 +02:00
smallmodel ae33155ed3 Added cover states 2023-10-21 17:18:03 +02:00
smallmodel d3d44001ef Fixed CanSee implementation 2023-10-21 16:50:26 +02:00
smallmodel c2aec1ff57 Use named enums for actor states 2023-10-20 23:28:01 +02:00
smallmodel d5f08fe950 Added more states for turret 2023-10-20 23:25:39 +02:00
smallmodel bdf4df9fd0 Finished actor_curious 2023-10-20 23:03:27 +02:00
smallmodel 7481b0939e Finished actor_balcony 2023-10-20 23:03:17 +02:00
smallmodel 346e59f18a Finished actor_animcurious 2023-10-20 23:03:10 +02:00
smallmodel 4725aad3e9 Added more states 2023-10-20 23:02:53 +02:00
smallmodel 59fd1bfdb2 Fixed anim API 2023-10-19 23:15:57 +02:00
smallmodel 7546d91580 Fixed anim state 2023-10-19 23:15:45 +02:00
smallmodel c81df27470 Fixed alarm state 2023-10-19 23:15:36 +02:00
smallmodel bd6232d913 Added more actor state enums 2023-10-19 23:15:23 +02:00
smallmodel 7f6b73e60f Set client's server id acknowledge 2023-10-19 20:20:40 +02:00
smallmodel e3562f9e56 Added serverIdAcknowledge 2023-10-19 20:20:07 +02:00
smallmodel 40141c55de Fixed infinite loop in ShortenPathToAvoidSquadMates 2023-10-19 20:19:52 +02:00
smallmodel a6f6cbd9b5 Fixed a crash in FindCornerNodeForExactPath 2023-10-19 20:19:43 +02:00
smallmodel e9ffb4b9b5 Removed print code that causes crash 2023-10-19 20:19:33 +02:00
smallmodel 1f0418a9cd Fixed TIKI_LoadSetupCaseHeader() not using case value properly 2023-10-19 19:47:06 +02:00
smallmodel e76837b42c Fixed TIKI_GetHeadSkin() wrongly using headmodels 2023-10-19 19:46:12 +02:00
smallmodel 87be7068c9 Added MAX_SKELMODELS 2023-10-19 19:45:56 +02:00
smallmodel 49cb5af265 Shortened GetRandomHeadModel() and GetRandomHeadSkin() 2023-10-19 19:36:32 +02:00
smallmodel f0fe93429f Fixed headmodels/headskins never working 2023-10-19 19:36:07 +02:00
smallmodel c2461f1219 tiki nullity check 2023-10-19 19:35:48 +02:00
smallmodel f82b6b75ff Fixed DetectSmokeGrenades and LookAt crash 2023-10-18 20:00:32 +02:00
smallmodel 3486b590eb Fixed division by zero error when getting a random smoke sprite 2023-10-18 19:57:31 +02:00
smallmodel 5730af672c Fixed event return type 2023-10-18 19:53:04 +02:00
smallmodel 4daff05142 Fixed some methods not working as intended 2023-10-18 19:45:31 +02:00
smallmodel e930768c67 Implemented OpenActorStats and WriteActorStats 2023-10-18 19:34:35 +02:00
smallmodel 6f03e388bf Finished actor source file implementation from moh 2.0 and above 2023-10-18 19:23:55 +02:00
smallmodel 9b340e03c5 Added MASK_LOOK trace mask 2023-10-18 19:20:53 +02:00
smallmodel d5b61fe5cc Pathing fixes, leash fixes 2023-10-17 23:38:33 +02:00
smallmodel 5b46e48a17 Fixed grenade code (path, give), path leash, gun target 2023-10-17 20:38:58 +02:00
smallmodel 585221f7cc Added more eActorState_Turret values 2023-10-17 20:38:03 +02:00
smallmodel 77eb7a5259 Added position and forward parameters to Sentient::GunTarget() 2023-10-17 19:45:22 +02:00
smallmodel 77bfc4b599 Added bDesperate parameter to DecideToThrowGrenade 2023-10-17 19:44:48 +02:00
smallmodel 95bbfba1b8 Added MASK_GRENADEPATH 2023-10-17 18:03:29 +02:00
smallmodel 844a50dfd8 Added more comments in DoUse 2023-10-17 17:51:29 +02:00
smallmodel cd2fea5262 Implemented some but not all features from mohaas and mohaab + lighter implementations + fixed implementations 2023-10-16 23:42:30 +02:00
smallmodel 79d8b4bb0b Fixed wrong value for THINKSTATE_BADPLACE 2023-10-16 23:32:59 +02:00
smallmodel 531825545d Added MASK_AI_CANSEE 2023-10-16 23:32:46 +02:00
smallmodel daab5b9238 Fixed compile error 2023-10-16 00:31:50 +02:00
smallmodel ce59e5e6a7 Fixed mismatched anim methods up to Actor::EventSetSayAnim 2023-10-16 00:29:41 +02:00
smallmodel ea0c4b5060 Implemented actor_runandshoot 2023-10-15 21:53:40 +02:00
smallmodel 9b9908b660 Formatted actor_badplace source file 2023-10-15 20:53:20 +02:00
smallmodel 101894be37 Renamed THINKLEVEL_NORMAL to THINKLEVEL_IDLE 2023-10-15 20:52:06 +02:00
smallmodel 3e314251f2 Implemented actor_badplace 2023-10-15 20:51:11 +02:00
smallmodel 1995c75006 Added eActorState with reserved enums for m_State values 2023-10-15 20:44:44 +02:00
pryon ff85986c44 Fully implement UIList (#78) 2023-10-15 20:23:58 +02:00
smallmodel 9131297d43 Implemented Actor::Archive from mohaas/mohaab 2023-10-15 20:06:37 +02:00
smallmodel 301f3091d1 Fixed whole SimpleActor implementation 2023-10-15 19:52:19 +02:00
smallmodel b59bd449d4 Removed useless Clear() in GetScriptValue() 2023-10-15 19:52:02 +02:00
smallmodel 5e510ef0e2 Fixed ActorPath algorithm 2023-10-15 17:52:00 +02:00
smallmodel c7c3fcd0e0 Use a const float* for PathDelta() 2023-10-15 17:50:28 +02:00
smallmodel a5532ad67b Fixed Actor Enemy system 2023-10-15 17:11:20 +02:00
smallmodel 290cd5501c Obfuscation should be 0 by default 2023-10-15 16:12:01 +02:00
smallmodel 8d1b1410cd Fixed EventSetAimTarget, MoveXX methods and implemented DetectSmokeGrenades 2023-10-15 15:08:01 +02:00
smallmodel df9aead324 In EventSetMood, check for Bored/Nervous/Curious/Alert 2023-10-15 14:03:44 +02:00
smallmodel 851fd240d3 Fixed StartAnimation() constant value 2023-10-15 14:01:48 +02:00
smallmodel 2da03c89d1 Fixed MovePath/MovePathGoal 2023-10-15 14:01:13 +02:00
smallmodel 89cd12d2c1 Fixed CurrentPathDir and CurrentPathGoal return value 2023-10-15 13:43:49 +02:00
smallmodel e21d2a0adb Fixed compile errors 2023-10-14 21:53:17 +02:00
smallmodel 2fad64b08a Reimplemented some methods, added some flags and moved methods to the correct source file 2023-10-14 21:21:45 +02:00
smallmodel 97fd147fbe Fixed SetDesiredYawDir/SetDesiredYawDest 2023-10-14 21:20:59 +02:00
smallmodel 0f01f6af11 Reimplemented actor CanSee/CanShoot/EnemyInFOV 2023-10-14 20:33:50 +02:00
smallmodel a9892c88be Fixed WithinDistance/DistanceTo const and implemented AreasConnected 2023-10-14 20:26:38 +02:00
smallmodel f1d76a042d Added WithinFarplaneDistance 2023-10-14 20:23:35 +02:00
smallmodel 77d4e5d051 Fixed MASK_CANSEE value 2023-10-14 20:23:24 +02:00
smallmodel 7041acfd51 Added visual obfuscation feature (not implemented yet) 2023-10-14 19:56:06 +02:00
smallmodel b27bfbe189 Formatted g_public source file 2023-10-14 19:12:57 +02:00
smallmodel 1c10e7a63d Fixed G_ObfuscationForSmokeSprites parameters 2023-10-14 19:11:48 +02:00
smallmodel 0a7c324d48 setOriginEvent: clear 4th origin history and update bad places. + handle ANIM_MODE_ATTACHED when moving 2023-10-14 18:59:35 +02:00
smallmodel c81d247fbb Reimplemented Actor::UpdateBoneControllers 2023-10-14 18:40:53 +02:00
smallmodel 82294b7b2e Correctly implemented GetMoveInfo 2023-10-14 15:02:07 +02:00
smallmodel d80f55d5bf Added MASK_MOVEINFO 2023-10-14 14:33:55 +02:00
smallmodel 7930cda277 Added and use eAnimMode enum 2023-10-14 14:18:56 +02:00
smallmodel 7870db7202 Made m_groundPlaneNormal a vec3_t 2023-10-14 14:08:52 +02:00
smallmodel 407538fd85 Moved MINS/MAXS to bg_pmove 2023-10-14 13:31:19 +02:00
smallmodel 1a293420c0 Fixed voicetype event 2023-10-14 13:30:35 +02:00
smallmodel 1e94cdd8ca Added AI_EVENT_BADPLACE 2023-10-14 01:16:50 +02:00
smallmodel 7a2311d6e6 Added BadPlace and RunAndShoot state initialization 2023-10-14 01:06:47 +02:00
smallmodel e686937ae9 Added actor_runandshoot source file 2023-10-14 00:54:52 +02:00
smallmodel 8dca8988fe InitRunAndShoot spelling 2023-10-14 00:54:47 +02:00
smallmodel c890ac5944 Added actor_badplace source file 2023-10-14 00:45:51 +02:00
smallmodel 56e52fda80 Implemented Actor::Landed 2023-10-14 00:44:59 +02:00
smallmodel e7786b3192 Added DBCS methods for UIFont 2023-10-13 23:22:13 +02:00
smallmodel 4cc3a84e98 Make the driver non-solid instead of the tank if it's a player 2023-10-13 21:31:47 +02:00
smallmodel 6e0b048ae7 End remote control for all linked turrets (this removes the user camera) 2023-10-13 21:16:56 +02:00
smallmodel 115786798d Remove the user camera when ending the remote control 2023-10-13 21:16:37 +02:00
smallmodel 376db9e9e6 Fixed turret's user camera not being removed when the turret is removed 2023-10-13 21:15:40 +02:00
smallmodel 8abdb80e85 Fixed crashes when spectating, and fixed spectate not working properly under some conditions 2023-10-13 21:15:02 +02:00
smallmodel 656f212608 Fixed tank's driver not being able to remote control the turret under some circumstances 2023-10-13 21:09:47 +02:00
smallmodel 60e07cc4ff Fixed wrong const string values 2023-10-13 19:57:21 +02:00
smallmodel e132c0a015 Player camera view fix
- Add PMF_DAMAGE_ANGLES when camera show quakes
- Fixed spectating angles
- Fixed a crash that can occur if current_torso is NULL
2023-10-13 19:52:12 +02:00
smallmodel 8e63526f2a Camera must calculate m_bShowquakes manually, only if protocol is below version 15 2023-10-13 19:33:32 +02:00
smallmodel a5b7c774c1 Added more clarity for PMF_DAMAGE_ANGLES 2023-10-13 19:33:03 +02:00
smallmodel 130a5bb8c4 Fixed indentation 2023-10-13 19:14:42 +02:00
smallmodel 3802dd9984 Added Camera::ShowQuakes() 2023-10-13 19:14:37 +02:00
smallmodel 7d37397222 Formatted camera source files 2023-10-13 19:11:51 +02:00
smallmodel 932454d7b2 Removed MASK_DAMAGEMODEL, using MASK_SOLID instead 2023-10-13 19:11:14 +02:00
smallmodel 5d2e6c46aa Use MASK_SOLID instead of MASK_DAMAGEMODEL 2023-10-13 19:07:44 +02:00
smallmodel 38089195be Set default fov to 80 and initialize fov fadetime, follow fade time and showquakes fields 2023-10-13 19:07:23 +02:00
smallmodel 85a6c1d145 Implemented Get/SetNationality, IsOnFloor, EventAnimScript_Attached, VirtualEyePosition and FriendlyInLineOfFire 2023-10-12 23:20:57 +02:00
smallmodel 85d034b7fb Added eActorNationality enum from mohaab 2023-10-12 23:16:18 +02:00
smallmodel 82b5468fb4 Implemented Actor destructor 2023-10-12 21:31:22 +02:00
smallmodel 89759c44af Moved some methods to inline + added EV_NoAnimLerp 2023-10-12 21:30:53 +02:00
smallmodel 6f66a1d1c3 Moved Container::Archive to archive.h source file to avoid compilation errors 2023-10-12 20:45:49 +02:00
smallmodel d4bac185f6 Added next enemy time field from moh 2.0 and above 2023-10-12 20:36:08 +02:00
smallmodel 658bba576e Moved methods 2023-10-12 20:35:57 +02:00
smallmodel 31f3c25b18 Implemented Archive with only arc parameter 2023-10-12 20:30:17 +02:00
smallmodel 4a1f149051 Formatted actor source files 2023-10-12 20:18:22 +02:00
smallmodel c55a78b8b4 Moved location of actor methods 2023-10-12 20:17:18 +02:00
smallmodel 3dbf957304 Include scriptthread 2023-10-12 20:06:00 +02:00
smallmodel 8f98f49f1b Renamed source file 2023-10-12 20:05:10 +02:00
smallmodel 0a8322960b Added methods from moh 2.0 and above 2023-10-12 19:57:46 +02:00
smallmodel 63d73c6f86 Added EF_NO_LERP entity flag 2023-10-12 19:57:41 +02:00
smallmodel f8cbbe78a2 Reordered methods 2023-10-12 19:54:00 +02:00
smallmodel 2bb09503c6 Added SimpleActor destructor (it deletes the anim thread) 2023-10-12 19:45:16 +02:00
smallmodel ba313decd1 Formatted simpleactor source files 2023-10-12 19:44:17 +02:00
smallmodel 0d6847c76c Initialize new member fields 2023-10-12 19:42:20 +02:00
smallmodel 7b721c7849 Added fields and methods from mohaas and mohaab 2023-10-12 19:21:41 +02:00
smallmodel 1fb073fd6a Added IsDisabled() 2023-10-12 19:04:47 +02:00
smallmodel 484272aed4 Added OpenActorStats and WriteActorStats (unimplemented) 2023-10-12 18:58:04 +02:00
smallmodel 57422ce793 Formatted actor source files 2023-10-12 18:19:22 +02:00
smallmodel ba855cd064 Added events moved actor methods to the correct source files 2023-10-11 22:49:06 +02:00
smallmodel 39ac9f7de6 Added more const strings from 2.0 and above 2023-10-11 19:31:31 +02:00
smallmodel 4368035da4 Remove the weapon from owner when being destroyed 2023-10-09 19:32:08 +02:00
smallmodel 4391912ee3 Implemented Door::ShowInfo, correctly implemented Door::FieldTouched + minor fixes 2023-10-08 20:56:15 +02:00
smallmodel fc17536f55 Use CONTENTS_WEAPONCLIP for stickybomb when using it 2023-10-08 20:45:34 +02:00
smallmodel 3bae4338c3 Updated README 2023-10-08 20:22:10 +02:00
smallmodel f59bdd6b9f Fully implemented ProjectileGenerator classes + Fixed ThrobbingBox code 2023-10-08 20:21:00 +02:00
smallmodel 03f3676b00 Use correct values for fields 2023-10-08 19:13:16 +02:00
smallmodel e0d7079745 Implemented VehicleWheelsX4 2023-10-08 19:11:23 +02:00
smallmodel b7f421481f Implemented VehicleWheelsX2 2023-10-08 18:52:09 +02:00
smallmodel 3506cb3f94 Fixed vlink's origin being incorrectly set 2023-10-08 18:28:01 +02:00
pryon 7280acee42 Implement UICheckBox (#77)
* Implement UICheckBox

* Remove UICheckBox destructor and unnecessary `str` initializations
2023-10-08 18:03:14 +02:00
smallmodel d757fa6306 Renamed world.cpp and world.h to worldspawn.cpp and worldspawn.h 2023-10-08 00:08:47 +02:00
smallmodel 475fc92629 Fixed str() being passed as an instance for variadic arguments 2023-10-07 23:50:16 +02:00
smallmodel f24303dd78 Use a correct implementation for fSign() 2023-10-07 23:49:49 +02:00
smallmodel 180a20f561 Made wheel_s a struct 2023-10-07 21:56:43 +02:00
smallmodel 2e5ca5b9dc Return an empty string if the item name is not in the prefix list 2023-10-07 14:19:42 +02:00
smallmodel decee20fd8 Fixed GetSentientOwner() not returning the owner if not remote controlled 2023-10-06 22:33:59 +02:00
smallmodel 3d9a60c415 Turn off vehicle sound entities when the tank is idle 2023-10-06 22:12:19 +02:00
smallmodel a4a7002867 ScriptSlave::SetModelEvent: Corrected the case where the model is invalid 2023-10-06 20:18:18 +02:00
smallmodel 96c9a014e6 When getting string from event, store it in an str to avoid potential undefined behavior due to str destruction 2023-10-06 20:13:31 +02:00
smallmodel 11b4471be9 Remove linked turrets of the tandem turret being destroyed 2023-10-06 19:55:36 +02:00
smallmodel 17aea205f7 m_HeadTurret must be initialized to self, fixed SwitchToLinkedTurret() never working, and made IsActiveTurret() return correctly 2023-10-06 19:47:59 +02:00
smallmodel 739f54ed87 Use EV_TakeDamage on pTurret instead, and process all pending events 2023-10-06 19:46:47 +02:00
smallmodel 01be5bee72 Ignore user control when in autopilot 2023-10-04 20:13:00 +02:00
smallmodel dfcf0da710 Added vehicle waittills 2023-10-04 19:17:57 +02:00
smallmodel f47fb87d1b Fixed vehicle path not working properly 2023-10-04 19:17:48 +02:00
smallmodel bd639ba936 Added "info_vehiclepoint" class ID for VehiclePoint 2023-10-04 19:17:26 +02:00
smallmodel e784e62a4e Fixed damage event method
- Don't damage if health is already 0 or below
- Check for immunity
- Error if attacker or inflictor is NULL
- Don't apply velocity for vehicles
- Set the minimum mass to 20 and momentum to 1000
- Still process pain when in godmode
2023-10-04 00:33:27 +02:00
smallmodel e4425dcbf8 Make sure to check if vehicle or turret is valid before locking 2023-10-04 00:25:55 +02:00
smallmodel 0dcffe8771 Fixed means of death strings 2023-10-03 18:40:38 +02:00
smallmodel 2b27f6c452 Formatted document 2023-10-03 18:35:06 +02:00
smallmodel 3ba3c728bc By default, a Vehicle must be removed on death 2023-10-03 18:32:31 +02:00
smallmodel 7193198af2 Set the owner for SmokeGrenades 2023-10-03 18:32:09 +02:00
smallmodel 6691afd160 Use the correct clipmask for VehicleCollisionEntity 2023-10-03 18:30:35 +02:00
smallmodel 59fb220197 Added setOwner/getOwner 2023-10-03 18:30:19 +02:00
smallmodel ff7651d4c8 Fixed a crash when a window breaks on mohaa mode 2023-10-03 18:04:12 +02:00
smallmodel b02abb1f18 Fixed issue when the string is escaped with a newline 2023-10-03 17:54:23 +02:00
smallmodel 9f42da4686 Hide tempmodel when it is outside of the min/max distance range 2023-10-03 17:04:26 +02:00
smallmodel 58e3056374 Fixed coordinates displaying twice in the console 2023-10-03 17:02:36 +02:00
smallmodel 3142865fef Added MacOS support 2023-10-03 17:02:23 +02:00
smallmodel 06e3497a57 Fixed issues with tempmodel origin 2023-10-03 17:02:07 +02:00
smallmodel e49833737d Fixed label showing when stat alpha is 0 2023-10-03 12:21:24 +02:00
smallmodel 7eedc5fef8 Fixed Rend_SetColor() with m_local_alpha 2023-10-03 01:51:31 +02:00
smallmodel c442942022 Using text outlines 2023-10-03 01:49:59 +02:00
smallmodel 2c2652ed1d Fixed outline color 2023-10-03 01:41:35 +02:00
smallmodel 97bcc07aab Made m_bOutlinedText a protected member 2023-10-03 00:54:45 +02:00
smallmodel 001704b22e Implemented LayoutPlayerStatAlpha and LayoutStatbarShader_Marker 2023-10-03 00:48:41 +02:00
smallmodel f1d9cd93ce Added events from moh 2.0 and above 2023-10-02 21:13:48 +02:00
smallmodel 49aa2aa858 Implemented UILabel from moh 2.0 and above 2023-10-02 21:11:48 +02:00
smallmodel 6274d9a1e9 Added UI_StartLocalSoundDialog, UI_FadeSound and UI_StopAll imports 2023-10-02 21:11:32 +02:00
smallmodel 5fa9d91401 Added S_StartLocalSoundChannel 2023-10-02 21:11:16 +02:00
smallmodel 9acb803ffe Implemented getMaxWidthIndex and PrintOutlinedJustified from moh 2.0 2023-10-02 20:38:48 +02:00
smallmodel 105924bca3 Formatted document 2023-10-02 20:18:24 +02:00
smallmodel 5f12be2037 Formatted source files 2023-10-02 19:18:25 +02:00
smallmodel 13931c40cb Added playerstatalpha and statbar_shader_marker from 2.0 2023-10-02 19:16:12 +02:00
smallmodel ada5d614c5 Added comments about versions 2023-10-02 18:49:46 +02:00
smallmodel 7323d51219 Emitter fixes 2023-10-02 18:47:02 +02:00
smallmodel f5071f2667 Fixed out of temp model warning spam 2023-10-02 18:46:45 +02:00
smallmodel 0ca0a81644 Fixed DriverUse and FindExitPosition 2023-10-02 18:46:31 +02:00
smallmodel e1bd69b467 Added SetVehicle / GetTurret / SetTurret 2023-10-02 18:09:55 +02:00
smallmodel b17494519e Tempmodel fixes 2023-10-02 13:41:00 +02:00
smallmodel 13555f505c newEnt's parent entity must be ENTITYNUM_NONE in AddTempModels() 2023-10-02 12:45:51 +02:00
smallmodel 2a65f53084 TagSpawnLinked must initialize the spawnthing origin to the entity's origin 2023-10-02 12:45:34 +02:00
smallmodel 71fe83083e Fixed crash when trying to play non pvs sound with a null alias 2023-10-02 12:13:22 +02:00
smallmodel 0ddb5c859f Fixed CalculateAnimationData using wrong angles for vehicle suspension movement 2023-10-02 12:07:59 +02:00
smallmodel f7b12d5108 Removed unused events 2023-10-02 12:07:26 +02:00
smallmodel baa8f4334b Implemented CG_ClientCommands 2023-10-02 12:07:12 +02:00
smallmodel 24a211b190 Formatted document 2023-10-02 11:56:35 +02:00
smallmodel 6e82f254b7 Formatted document 2023-10-02 11:51:08 +02:00
smallmodel fbfedcf8d6 Fixed vehicle suspensions 2023-10-02 02:15:56 +02:00
smallmodel 5b06a0c2a4 Small code reduction 2023-10-02 02:15:12 +02:00
smallmodel f3204b0845 Fixed animation playing sometimes not being correct 2023-10-02 02:13:42 +02:00
smallmodel 334314a137 Fixed crash when the owner is NULL 2023-10-02 01:45:19 +02:00
smallmodel 8ecc8122b8 Fixed tank turning too fast 2023-10-02 01:11:09 +02:00
smallmodel eb9a119dfe Fixed MoveVehicle not moving correctly 2023-10-02 00:46:37 +02:00
smallmodel 313ece62f7 Fixed turret not turning properly 2023-10-02 00:16:12 +02:00
smallmodel 5799bcceb2 Fixed buffer overflow for szBlah 2023-10-02 00:07:54 +02:00
smallmodel 61e7571388 Added a crash fix in AttachDriverSlot() 2023-10-02 00:07:44 +02:00
smallmodel 6cfd99e40a Fixed AttachPassengerSlot not attaching correctly and call DriverAdded() after attaching the driver 2023-10-02 00:07:30 +02:00
smallmodel b3bdd9d563 Enabled UpdateNormals() 2023-10-01 23:09:55 +02:00
smallmodel 5bec3d8471 sv_maxclients must be initialized to 1 by default 2023-10-01 23:09:26 +02:00
smallmodel 711e46ecfb Added commented code that prevent playing mohaa maps in mohaas/mohaab 2023-10-01 23:08:07 +02:00
smallmodel ddd127352f Initialize svs.numSnapshotEntities in SV_ChangeMaxClients 2023-10-01 23:07:38 +02:00
smallmodel 784fd825bb Formatted level source file 2023-10-01 22:49:10 +02:00
smallmodel 673a42242d Formatted source files 2023-10-01 22:47:25 +02:00
smallmodel 3317345d92 Use a const string for target name 2023-10-01 22:45:41 +02:00
smallmodel 7958ba38d8 Fixed angles being wrong when the vehicle starts + fixed turret slot initial angles, use MAX_CORNERS instead of MAX_SOUND_ENTITIES and fixed UpdateNormals() angles 2023-10-01 21:16:50 +02:00
smallmodel 2dd7e0c03f use a vec3_t for VehicleTurretGun::SetBaseOrientation and use GetTagBarrel() for m_iBarrelTag 2023-10-01 21:15:37 +02:00
smallmodel b94f021567 Refactored setModel() 2023-10-01 21:00:32 +02:00
smallmodel cf50c5b535 Measure SpawnInternal time 2023-10-01 21:00:11 +02:00
smallmodel 1b71169565 Removed non-fgame module code (as g_spawn is only used for fgame) 2023-10-01 20:57:28 +02:00
smallmodel 30f2b9d5ed Formatted document 2023-10-01 20:56:51 +02:00
smallmodel 999d6a449b Fixed toPitch() with zero coordinates 2023-10-01 14:46:06 +02:00
smallmodel a65aa2a0d0 Fixed CrossProduct being wrong due to parameters being modified while doing the operation 2023-10-01 14:45:24 +02:00
smallmodel 36fc0b6e8a Formatted document 2023-10-01 14:21:23 +02:00
smallmodel f97362cdb1 Added MASK_VEHICLE_TIRES 2023-10-01 14:11:49 +02:00
smallmodel 6398484459 Fixed Vehicle::Postthink ignoring g_vehicle 2023-10-01 13:43:42 +02:00
smallmodel 07e8c6feaa Fully implemented cMoveGrid 2023-10-01 13:42:16 +02:00
smallmodel faf351a496 SurfIsOffScreen must only process faces + removed assertion 2023-10-01 11:36:54 +02:00
smallmodel cd9315852e Fixed num not being set when writing to memory archiver in commandthing_t::ArchiveToMemory 2023-09-30 11:57:04 +02:00
smallmodel 8c8487231a Fixed P_DeleteViewModel when the viewmodel is NULL 2023-09-27 23:55:27 +02:00
smallmodel 65ebdf0862 Commented out UpdateNormals() till a solution is found 2023-09-27 23:51:12 +02:00
smallmodel 9704362501 Initialize m_bAnimMove 2023-09-27 23:49:23 +02:00
smallmodel f0e87cd85a Prefixed TIKI import functions 2023-09-27 23:21:34 +02:00
smallmodel f6e6bf1d6b Implemented SlidePush, MoveVehicle and Postthink 2023-09-27 23:20:09 +02:00
smallmodel 4b4e8f806b Fixed vlink angles in Postthink 2023-09-27 23:17:14 +02:00
smallmodel 4141cee13f Added MASK_MOVEVEHICLE 2023-09-27 20:22:33 +02:00
smallmodel b2ee346f68 Formatted documents 2023-09-27 20:10:16 +02:00
smallmodel 2220f1ff05 Fixed vehicle move code 2023-09-27 20:01:08 +02:00
smallmodel 7ba48dd666 Made code lighter 2023-09-27 19:35:24 +02:00
smallmodel 2a48e2fd27 Formatted document 2023-09-27 19:24:41 +02:00
smallmodel 63a24c4448 Reimplemented a few methods (from moh 2.0 and above) 2023-09-26 23:51:12 +02:00
smallmodel 787df3362b Fixed v_angle not being set in SetViewAngles + floor view angles 2023-09-26 20:51:25 +02:00
smallmodel 5ad0f60ee3 G_TestEntityPosition must check for sentient instead of player 2023-09-26 20:50:00 +02:00
smallmodel d42f92361a Fixed slot notsolid/solid for bound entities, for player and for weapons 2023-09-26 20:49:00 +02:00
smallmodel 0693db3ef5 Fixed Vehicle::VehicleDestroyed 2023-09-26 20:33:23 +02:00
smallmodel fafb0e2793 Initialize max speed in EventDriveInternal and use cVehicleSpline instead of cSpline<4, 512> 2023-09-26 20:31:13 +02:00
smallmodel 0a4819d172 Using FindExitPosition() when detaching from driver, turret or passenger 2023-09-26 20:27:59 +02:00
smallmodel ee03f32a3e FindExitPosition() must return a boolean value 2023-09-26 20:14:39 +02:00
smallmodel f4e01917a2 Set turrets target name on initialization + Fixed DetachTurretSlot exit angles + use FindExitPosition() in AttachTurretSlot() 2023-09-26 20:08:25 +02:00
smallmodel eed9b36c9f Added GetRawRemoteOwner() 2023-09-26 20:06:31 +02:00
smallmodel 055192c2a8 Implemented Vehicle::AutoPilot from moh >= 2.0 and above 2023-09-26 19:44:03 +02:00
smallmodel cca39108dc Added cVehicleSpline as an alias to cSpline<4, 512> 2023-09-26 19:43:42 +02:00
smallmodel b1bbd5e366 Implemented mohaas/mohaab methods 2023-09-25 23:17:20 +02:00
smallmodel afb718f01f Removed vm, using m_bAnimMove instead 2023-09-25 21:18:43 +02:00
smallmodel 653b4e0ab7 Added methods, events and fields from moh 2.0 and above 2023-09-24 23:47:28 +02:00
smallmodel c3d228a9f5 Fixed float vote options 2023-09-24 23:37:26 +02:00
smallmodel 15e10caca0 Fixed useless statement 2023-09-24 23:37:18 +02:00
smallmodel 46efa85441 Fixed switch/case no default value 2023-09-24 23:37:03 +02:00
smallmodel bb42456653 Marked overridden methods as "override" 2023-09-24 23:36:30 +02:00
smallmodel 38bf80aa52 Export EV_Turret_SetMaxUseAngle 2023-09-24 23:20:43 +02:00
smallmodel c5c2aa5348 Fully implemented VehicleTank 2023-09-24 19:14:50 +02:00
smallmodel 1e67aeb667 Added AnimMoveVehicle 2023-09-24 18:42:23 +02:00
smallmodel 9ac7bccba5 Added GetUserViewAngles / SetUserViewAngles 2023-09-24 18:42:13 +02:00
smallmodel 610b82cfb7 Added Vehicle::DriverAdded and NUM_VEHICLE_TIRES 2023-09-24 17:47:31 +02:00
smallmodel c8144539d0 Fully implemented VehicleTurretGun 2023-09-24 17:19:23 +02:00
smallmodel 60f83597ee Added HasVehicle() virtual method 2023-09-24 16:38:06 +02:00
smallmodel 46c0c6085d Fixed GetMuzzlePosition using wrong parameters 2023-09-24 16:37:50 +02:00
smallmodel 36d4c4af61 Added MASK_TRANSPARENT 2023-09-24 16:37:36 +02:00
smallmodel 7406c3dc23 Implemented basic VehicleTurretGun methods 2023-09-24 01:14:35 +02:00
smallmodel 24bb15ce29 Renamed SOUND_STATE to SOUND_STATE_TURRET to avoid conflict with Vehicle's SOUND_STATE 2023-09-24 01:07:22 +02:00
smallmodel f3ad05dc85 Added GetVehicle 2023-09-24 00:27:51 +02:00
smallmodel bbae3223cb Fixed virtual methods 2023-09-23 23:13:34 +02:00
smallmodel 8cedb24d31 Using m_SwitchLabel 2023-09-23 23:13:21 +02:00
smallmodel 528414dfef Added new fields from moh >= 2.0 2023-09-23 22:34:08 +02:00
smallmodel 6e1c58e343 Implemented VehicleTurretGunTandem 2023-09-23 21:42:40 +02:00
smallmodel 002e935193 Fixed match start time being wrong and fixed AllowRespawn() 2023-09-23 19:49:44 +02:00
smallmodel e26d7d346a IsReady() should also check for dead 2023-09-23 19:38:17 +02:00
smallmodel 5d917f2578 Made IsDead() const 2023-09-23 19:38:04 +02:00
smallmodel 8aecff1879 Added CTeamSpawnClock and ported fixes from moh >= 2.0 2023-09-23 19:37:55 +02:00
smallmodel 718672119e Fixed roundactive being wrongly set to false 2023-09-23 18:37:33 +02:00
smallmodel 6ec7482662 Implemented FixedTurret 2023-09-23 18:30:59 +02:00
smallmodel 5f3ea7c634 Removed m_countdown 2023-09-23 18:30:45 +02:00
smallmodel 1c813a59d0 Added m_bRoundActive and RoundActive() 2023-09-23 18:30:19 +02:00
smallmodel a66236fc3d Added QUAKED sections 2023-09-23 17:58:14 +02:00
smallmodel ef9b7022df Added World::Archive 2023-09-22 21:04:18 +02:00
smallmodel ad7efce855 VehicleTankTandem 2023-09-20 20:57:58 +02:00
smallmodel 78a9990c3a Implemented DrivableVehicleTandem 2023-09-20 20:57:35 +02:00
smallmodel 422b9eb6c0 Added DamageModel from moh 2.0 2023-09-20 00:02:38 +02:00
smallmodel 703eb271f9 Added MASK_DAMAGEMODEL 2023-09-20 00:01:12 +02:00
smallmodel 2aca32c44a Added "isopen" door event + Renamed Door's class ID to "NormalDoor" 2023-09-19 21:24:00 +02:00
smallmodel 56c30bddb1 Added DrivableVehicleTandem 2023-09-19 21:15:55 +02:00
smallmodel 1179b50ad1 Added VehicleTankTandem 2023-09-19 21:12:57 +02:00
smallmodel 6ad44441a6 Made UpdateTurretSlot a virtual method 2023-09-19 21:12:31 +02:00
smallmodel 2455c09475 Added VehicleTurretGunTandem + more methods from moh 2.40 2023-09-19 21:02:22 +02:00
smallmodel 7a1e07e72a Made ApplyFireKickback() and ReadyToFire() virtual 2023-09-19 21:01:41 +02:00
smallmodel aa8e95885a Formatted document 2023-09-19 21:01:18 +02:00
smallmodel 54bae94ad9 Use Weapon::SetItemSlot when updating stats, instead of setting weapon_class manually 2023-09-19 20:18:27 +02:00
smallmodel 98b7e01069 Implemented Weapon::SetItemSlot 2023-09-19 20:18:13 +02:00
smallmodel 12c7707bc3 Unused variable removal 2023-09-19 20:08:53 +02:00
smallmodel a8a2c7e345 Use result from GetVAngles() in Player::GetViewangles() event 2023-09-19 20:08:35 +02:00
smallmodel 6c7542ec0c Fixed weapon muzzle position 2023-09-18 23:45:17 +02:00
smallmodel 5ec56cbe77 Implemented turret code from mohaas/mohaab 2.40 2023-09-18 23:36:03 +02:00
smallmodel 6b79770783 Fixed HashCode for command_t (must be case-insensitive) 2023-09-18 23:35:11 +02:00
smallmodel e125a83625 Added MASK_GUNTARGET 2023-09-18 23:34:46 +02:00
smallmodel d05b47e996 Fixed SetupVoteOptions not checking length for -1 2023-09-18 23:34:24 +02:00
smallmodel e1093d0c0c Using vec3_t instead of Vector for Weapon::GetMuzzlePosition() 2023-09-18 21:19:08 +02:00
smallmodel 25690648d6 Fixed inventory item having wrong weapon class set, and added support for portable turret 2023-09-17 19:54:45 +02:00
smallmodel 5c3c4f6288 Added and implemented CarryableTurret and PortableTurret 2023-09-17 19:48:20 +02:00
smallmodel 9dec5e9e54 Added fields from mohaas/mohaab 2023-09-17 19:47:02 +02:00
smallmodel ae1fa808da Export DPrintf2 and DebugPrintf for server 2023-09-17 19:34:19 +02:00
smallmodel ed6839dc99 Export DebugPrintf for client 2023-09-17 19:34:10 +02:00
smallmodel e95d71da0d Added Com_DPrintf2 and Com_DebugPrintf 2023-09-17 19:33:17 +02:00
smallmodel 128c8f3c06 Added Sys_DebugPrint 2023-09-17 19:31:37 +02:00
smallmodel 04f61a1af7 Added UI_PrintConsole() and UI_PrintDeveloperConsole() declarations 2023-09-17 19:29:59 +02:00
smallmodel 974e86b698 Fixed weapon being detached even if the holster tag is an empty string 2023-09-17 19:08:11 +02:00
smallmodel 12c03384b2 Fixed item being removed incorrectly 2023-09-17 19:07:46 +02:00
smallmodel 99ba912d7b Fixed radius in Level::GetNearestBadPlace() 2023-09-17 17:12:04 +02:00
smallmodel 7607932216 Added MASK_CARRYABLETURRET 2023-09-17 17:11:44 +02:00
smallmodel acc9c241a3 Added const specifier for Weapon::IsCarryableTurret() 2023-09-17 16:27:58 +02:00
smallmodel 5f5055f4fc Added Sentient::SetHolsteredByCode 2023-09-17 16:27:18 +02:00
smallmodel fc3749e008 Added Event() constructor that accepts another event and the number of arguments 2023-09-17 16:26:48 +02:00
smallmodel 155734370c Using Archive algorithm from mohaas/mohaab 2023-09-14 00:19:55 +02:00
smallmodel 1095e3d509 call arc.Close() after checking if it was Loading 2023-09-14 00:19:17 +02:00
smallmodel f7bfa47f2e Made ScriptVariable classes part of LightClass 2023-09-13 23:51:33 +02:00
smallmodel 9f6ef14ea1 GetCompiledScript should remain unused 2023-09-13 21:32:58 +02:00
smallmodel 15de08556e Formatted document 2023-09-13 19:46:39 +02:00
smallmodel e7dfa8fcfe Fixed command buffer not being able to hold the last character 2023-09-13 00:07:51 +02:00
smallmodel 7a67dc5dfd Implemented bad places 2023-09-13 00:00:42 +02:00
smallmodel 7eb8ef42b7 Update smoke sprites and bad places every frame 2023-09-12 23:59:51 +02:00
smallmodel c9c7a4beed Implemented PathSearch::UpdatePathwaysForBadPlace 2023-09-12 23:59:38 +02:00
smallmodel bcf3aad1b2 Added PointToSegmentDistanceSquared 2023-09-12 23:35:22 +02:00
smallmodel ad75363028 Added more variables to archive for Level 2023-09-12 21:48:08 +02:00
smallmodel f4ec3939a5 Weapon::Shoot(): process default value in switch/case for firemode 2023-09-12 21:47:51 +02:00
smallmodel aead97d29d Implemented landmarks from mohaab 2023-09-12 21:39:19 +02:00
smallmodel f468305a2c Level::Init(): Remove archived entities, reset health queue, initialize vote and free landmarks 2023-09-12 20:37:01 +02:00
smallmodel a962f469eb Added health queue 2023-09-12 20:33:49 +02:00
smallmodel 63e025cc02 Fixed 1022 characters command limit for SV_SendServerCommand (must be MAX_STRING_CHARS) 2023-09-12 20:14:58 +02:00
smallmodel b2d332f152 SV_GameSendServerCommand: Allocate the buffer dynamically on stack
This fixes long commands not being sent
2023-09-12 20:13:37 +02:00
smallmodel e160cf240c Fixed vote not working properly 2023-09-12 20:12:09 +02:00
smallmodel 19a4f70c44 Made ExecuteConsoleCommand accept a const char* instead 2023-09-12 00:19:08 +02:00
smallmodel dcca3901d5 Initialize more Level variables 2023-09-12 00:18:09 +02:00
smallmodel 0ee4ffbfbc Implemented vote system (from mohaas/mohaab) 2023-09-12 00:07:10 +02:00
smallmodel 776bc781cd Added ExecuteConsoleCommand() game import 2023-09-11 21:41:39 +02:00
smallmodel b1bb79e19f Added Player::HasVotedYes() and Player::HasVotedNo() 2023-09-11 21:28:05 +02:00
smallmodel 76c69b7bd1 Implemented Player::CallVote from mohaas/mohaab 2023-09-11 20:45:30 +02:00
smallmodel 15a25a412f Removed m_voteCommand and added m_nextVoteTime 2023-09-11 20:45:07 +02:00
smallmodel b511d89dcc Fixed farplane entity dist check when it is 0 2023-09-11 00:06:21 +02:00
smallmodel 9512ae7aeb Added TurretGun methods from mohaas/mohaab 2023-09-11 00:02:10 +02:00
smallmodel 5db086e470 Made GetMuzzlePosition a virtual method 2023-09-10 23:54:30 +02:00
smallmodel d63f668291 Updated README 2023-09-09 23:24:29 +02:00
smallmodel 35c72a9570 Added more packages to install in docker images 2023-09-09 23:14:16 +02:00
smallmodel b29f62ddd4 Fixed EventSetTurret crashing when the listener is NULL 2023-09-09 20:58:58 +02:00
smallmodel 525dc17573 Ignore NULL tiki
This fixes frequent crashes with NULL models
2023-09-09 20:53:59 +02:00
smallmodel 4d8ed24833 Fixed TIKI_ParseAnimations incorrectly returning 2023-09-09 20:49:08 +02:00
smallmodel aa15d996e0 Removed AnimOnce 2023-09-09 20:41:36 +02:00
smallmodel 0ec846945d Use edict->tiki instead of calling gi.modeltiki (which can crash because of an empty model string) 2023-09-09 20:41:03 +02:00
smallmodel 03ff158e76 Fixed crash when setting actor's patrol node 2023-09-09 20:02:02 +02:00
smallmodel b3371b2d63 Fixed static models collapse array being wrong
This would cause static models to disappear
2023-09-09 17:56:47 +02:00
smallmodel ed64d03bf5 Fixed dlclose() not working when compiled by GCC 2023-09-09 17:54:04 +02:00
smallmodel 3d936dede1 Don't change the protocol when in special game 2023-09-09 16:46:51 +02:00
smallmodel 33e9c5b1ea Formatted source files 2023-09-09 16:46:42 +02:00
smallmodel 078c90bbc9 Create a ScriptThread directly rather than calling Director.CreateScriptThread
This avoids exception when called by ScriptThreadLabel::Execute(). Because Execute() doesn't have try/catch, the program would crash.
2023-09-09 16:42:15 +02:00
smallmodel 2caf2cad5a Fixed improper usage of alloca()
alloca() can cause a stack overflow when it is called multiple times
2023-09-07 20:20:18 +02:00
smallmodel 5dec21dd43 Include <utility> for std::move 2023-09-07 20:01:07 +02:00
smallmodel 36aa9bd802 Don't replace Z_Malloc, Z_TagMalloc and Z_Free in debug memory mode 2023-09-07 19:48:08 +02:00
smallmodel bed2f15a72 Initialize more members for UIWidget
m_scaleCvar was not initialized to NULL, which could cause crashes
fadeSequence was not initialized
2023-09-07 19:32:35 +02:00
smallmodel f949f1e88d Fixed offset of block in Free() with _DEBUG_MEMBLOCK 2023-09-07 19:31:17 +02:00
smallmodel 8af202bd5f Fixed compilation errors with DEBUG_MEMORY on Linux because of CRT 2023-09-07 19:29:24 +02:00
smallmodel 67556a88f1 Fixed errors when compiling with DEBUG_MEMORY 2023-09-07 19:06:06 +02:00
smallmodel 4f8573784d Removed con_set inheritance from con_arrayset 2023-09-07 18:58:27 +02:00
smallmodel c5a46be23e Optimized calls to Event() (avoid allocating a new Event when it can be reused) 2023-09-07 18:22:07 +02:00
smallmodel 47a3c0bf55 Optimized event name
Use a static char*, instead of an allocated str
2023-09-07 18:05:49 +02:00
smallmodel e8d2a2a461 Instantiate AnimationEvent on stack rather than dynamically allocating it. Optimized cmd name for client commands 2023-09-07 17:33:35 +02:00
smallmodel 7b72a3fba4 Fixed MemArchiver improperly working 2023-09-06 23:34:16 +02:00
smallmodel dda79e7f27 Moved some tempmodels code to cg_tempmodels.cpp and implemented FreeSomeTempModels() 2023-09-06 23:25:48 +02:00
smallmodel 9a104566ba Added MemArchive feature from mohaas/mohaab 2023-09-06 23:11:43 +02:00
smallmodel b4d8982341 Implemented CG_ArchiveVSSGlobals() 2023-09-06 20:54:58 +02:00
smallmodel 5ea3fc28f7 Added FS_ListFilteredFiles, FS_FreeFileList, R_GetModelName and R_GetShaderName to client game imports 2023-09-06 20:31:50 +02:00
smallmodel 0bbf39660e Added R_GetShaderName and R_GetModelName 2023-09-06 20:31:28 +02:00
smallmodel 791f38762b Added MemArchiver::ArchiveSize 2023-09-06 19:58:19 +02:00
smallmodel c296b909c7 Fixed iTagR initialization 2023-09-06 00:00:50 +02:00
smallmodel 9c7a54f8fc Added and implemented MemArchiver class 2023-09-05 23:57:51 +02:00
smallmodel 4289eab72b Don't define MemArchiver in cg_archive.h 2023-09-05 23:57:18 +02:00
smallmodel 7b0dbc7445 Save the client game state in SV_ArchiveLevelFile 2023-09-05 20:33:02 +02:00
smallmodel 02db904336 Made CG_SaveStateToBuffer and CG_LoadStateToBuffer use a size_t 2023-09-05 20:31:24 +02:00
smallmodel 55140fee3a Replaced #ifdef CLIENT with #ifndef DEDICATED 2023-09-05 20:22:01 +02:00
smallmodel 96d881a1f1 Made ui_public.h compilable to C code 2023-09-05 20:18:05 +02:00
smallmodel 260a95c05e Added S_SaveData (unimplemented) 2023-09-05 20:17:51 +02:00
smallmodel 99d633587f Renamed S_StopAllSounds to S_StopAllSounds2 2023-09-05 20:17:38 +02:00
smallmodel cf2f0256a2 Moved UI_SetupFiles to ui_public.h 2023-09-05 20:00:54 +02:00
smallmodel dae8e8dfbd Fixed archive not always archiving soundsystemsavegame_t 2023-09-05 19:53:57 +02:00
smallmodel 6d2d35e82d Fixed compile errors on newer versions of clang 2023-09-05 19:39:57 +02:00
smallmodel 5e23a6b640 Added DEBUG_MEM_BLOCK cmake definition to debug MEM_BlockAlloc code 2023-09-04 22:19:01 +02:00
smallmodel f2ec502dc2 Fixed str allocation 2023-09-04 22:06:13 +02:00
smallmodel be04f31256 Replaced eventInfo_t with DataNode
DataNode is now used only at initialization time and is destroyed after initialization
2023-09-04 21:38:58 +02:00
smallmodel 85dd881c97 Removed usage of HeapAlloc/HeapFree 2023-09-04 21:24:48 +02:00
smallmodel 0ef2dccd90 Don't replace cgi.Malloc and cgi.Free with malloc/free 2023-09-04 21:24:17 +02:00
smallmodel 000ec39c81 Added non-pvs landing sound 2023-09-03 22:13:03 +02:00
smallmodel 3160c6ee0b Added _client_sound
Replaced SoundThisFrame by ClientSound
Process client commands with animation events that start with `_client_`
2023-09-03 22:12:45 +02:00
smallmodel 9da403e534 Increased MAX_NONPVS_SOUNDS 2023-09-03 22:11:26 +02:00
smallmodel f19c3408e1 Fixed footonground using right foot 2023-09-03 00:07:40 +02:00
smallmodel 38c0e09e8a Call UpdateFootsteps() even on multiplayer 2023-09-03 00:07:17 +02:00
smallmodel 2be4f7cdaf Fixed EV_Client_Landing event name 2023-09-03 00:07:06 +02:00
smallmodel cd48272fbb Implemented server-side footstep simulation 2023-09-02 23:53:46 +02:00
smallmodel a5a146bb02 Added and using Entity::PlayNonPvsSound 2023-09-02 23:51:37 +02:00
smallmodel c901bcf321 Call Sys_PrintBackTrace() directly from Sys_SigHandler() 2023-09-01 22:53:08 +02:00
smallmodel 8f3142e532 Display the header/footer before printing the backtrace 2023-09-01 22:52:52 +02:00
smallmodel 88438d6db4 Removed signal handlers from g_main.cpp as it's handled by the main app directly 2023-09-01 22:49:58 +02:00
smallmodel 7348734070 Fixed m_bFootOnGround values being set incorrectly 2023-09-01 22:49:53 +02:00
smallmodel a99a4a3a2b Clear the top value of a return command, if the listener is NULL 2023-08-30 23:34:29 +02:00
smallmodel 7bc8c3ab5b Fixed crate overlapping warning (when crates are actually not overlapping) 2023-08-30 23:33:42 +02:00
smallmodel 2a58fbdd22 Formatted document 2023-08-30 23:33:00 +02:00
smallmodel d102f5a88a set EV_LINKDOORS to -6.0f instead of -5.0f 2023-08-30 23:32:36 +02:00
smallmodel 8227f7125b Added SetDoorType and ShowInfo 2023-08-30 23:29:23 +02:00
smallmodel 673535dc08 Clear aliases in CL_Vid_Restart_f 2023-08-30 21:54:15 +02:00
smallmodel 9750489d07 Don't play sound if current_entity is NULL 2023-08-30 21:54:01 +02:00
smallmodel 53c6224ed0 Set ENGINE_VERSION to 3.0 2023-08-30 21:53:40 +02:00
smallmodel f84794acbe Added sv_pure support from ioq3 and mohaas/mohaab 2023-08-30 20:35:47 +02:00
smallmodel 9e535e509a Fixed snapshot ignoring "snaps" value from client 2023-08-30 19:59:45 +02:00
smallmodel 489210424f Fixed SVC_Status infinite loop with names longer than 16 2023-08-30 19:36:38 +02:00
smallmodel 394abbdb6f Fixed IPv6 not working with connect command 2023-08-30 19:36:17 +02:00
smallmodel 5fdeb92429 Readded openmohaa to version string 2023-08-30 01:08:09 +02:00
smallmodel 11cc39e41b Fixed pain animation playing indefinitely 2023-08-30 01:07:52 +02:00
smallmodel b3d5851fdc Fixed optimization not working when a player is visible near a wall 2023-08-30 01:07:32 +02:00
smallmodel 5c25839bab Added a feature that plays sound to clients not seeing entities (like not seeing other players) 2023-08-29 22:05:48 +02:00
smallmodel fbd314b447 Fixed pitch being used instead of volume 2023-08-29 22:04:18 +02:00
smallmodel 86888a32d4 Added SV_ClientSound 2023-08-29 21:55:24 +02:00
smallmodel 37c2d22b10 Added Frame_Commands_Client 2023-08-29 20:25:11 +02:00
smallmodel 19758ef75d Fixed entity optimization
Added a feature to always optimize players who don't see another player
2023-08-29 20:01:51 +02:00
smallmodel 519ccc90f7 Added sv_netoptimize_vistime 2023-08-29 20:00:27 +02:00
smallmodel b592d15d1f Added netoptimize enum types 2023-08-29 20:00:13 +02:00
smallmodel 78d70a892c Fixed leanAngle being never 0 2023-08-29 20:00:03 +02:00
smallmodel dbcf4c1800 Use GT_SINGLE_PLAYER instead of comparing non-zero 2023-08-29 18:48:36 +02:00
smallmodel cbd4630b3c SV_MasterHeartbeat: Use MAX_HEARTBEAT_TIME instead of the constant 2023-08-29 18:48:09 +02:00
smallmodel 92fdfe3f35 Moved MIN_HEARTBEAT_TIME and MAX_HEARTBEAT_TIME to sv_gqueryreporting.h 2023-08-29 18:45:46 +02:00
smallmodel 8b563e5232 Fixed heartbeat being always sent every frame 2023-08-29 08:17:23 +02:00
smallmodel aeb4875fa5 Commented out call to WSACleanup() (as it is already handled by the engine) 2023-08-29 01:08:33 +02:00
smallmodel 5ebb9c61f9 Removed call to NET_Init (already called from main()) 2023-08-29 01:08:09 +02:00
smallmodel c0e5b8fe15 Entities visibility enhancement
Implemented SV_WorldTrace(), SV_ClientIsVisibleTrace(), EntityDistCheck() and SV_ClientIsVisible()
Entities also will be hidden when:
- Their parent are not sent to clients
- They don't have a model
- They are behind t he farplane
- Clients can't see eachother with sv_netoptimize
2023-08-29 00:44:33 +02:00
smallmodel f852efea7d Added cvars 2023-08-29 00:04:07 +02:00
smallmodel 664ae905bb Fixed lastRadarTime and lastVisCheckTime fields 2023-08-29 00:03:44 +02:00
smallmodel 243b0fd109 Added sv_netprofile, sv_netprofileoverlay, sv_netoptimize and g_netoptimize 2023-08-29 00:03:28 +02:00
smallmodel 43b0944403 Added centroid in entityShared_t and removed currentOrigin 2023-08-29 00:03:07 +02:00
smallmodel ecc3c9f7b4 Renamed SVF_HIDEOWNER to SVF_SENT 2023-08-28 23:00:58 +02:00
smallmodel 296249b203 Fixed wrong SVF flags 2023-08-28 22:13:16 +02:00
smallmodel 8c1145bb9f Clear all unsupported farplane fields in protocol below version 15 2023-08-28 20:59:02 +02:00
smallmodel 7ad18a68f8 Rendering fog fixes
Fixed wrong fog flag being used (must be GLS_FOG) in RB_SetupFog().
R_SetupFrustum():
- Use skybox farplane and farplane bias
- RB_SetupFog() is now the only function who handle fog activation

RE_RenderScene():
- Set renderTerrain, skybox_farplane and farplane_bias parameters
- Set color overrides
- Use farclip when necessary

RB_StageIteratorLightmappedMultitextureUnfogged(): Fixed issue with fog being reset
2023-08-28 20:50:32 +02:00
smallmodel 99ba396c24 Make sure to not error out if the map checksum isn't used. Also fixed cg.farclipOverride, must be -1 if the server is a mohaa server 2023-08-28 20:46:48 +02:00
smallmodel f88e9960f2 Use the map's checksum only if the server has sv_mapChecksum exported 2023-08-28 20:45:10 +02:00
smallmodel b53466ea0d Fixed cheats variable being improperly configured 2023-08-28 20:44:33 +02:00
smallmodel 2afda6a470 Check the map checksum in CG_GameStateReceived 2023-08-28 20:29:18 +02:00
smallmodel acc8081ef2 Added checksum return parameter in CL_CM_LoadMap for cgame 2023-08-28 20:28:59 +02:00
smallmodel 7433677ead CG_Init(): clear fog overrides 2023-08-28 20:22:43 +02:00
smallmodel 4132f7efe6 Fixed farplane
Animated farplane is cleared when setting the farplane
Fixed farclip_override and farplane_color_override being mixed up
2023-08-28 20:22:06 +02:00
smallmodel 56e0f5797e Don't iterate the sky when tr.farclip is set 2023-08-28 19:52:12 +02:00
smallmodel 54c142ce78 Flag mistake, now using GLS_MULTITEXTURE_ENV instead of GLS_FOG_WHITE 2023-08-28 19:46:31 +02:00
smallmodel c106aeef2b Clear fog when drawing 2D window 2023-08-28 19:45:54 +02:00
smallmodel 66bde85807 Added GLS_COLOR_MASK and GLS_FOG_BITS 2023-08-28 19:45:40 +02:00
smallmodel 08363511a7 farclip must be an integer 2023-08-28 18:36:03 +02:00
smallmodel d6b93b712c Fixed sound location when in camera view + subtract refdef viewangles when PMF_DAMAGE_ANGLES is set 2023-08-28 18:35:47 +02:00
smallmodel a85d6d0f4c Added PMF_DAMAGE_ANGLES for mohaas/mohaab 2023-08-28 18:34:50 +02:00
smallmodel 2c1f341099 Initialize cg.farplaneColorOverride values to -1 2023-08-28 17:53:47 +02:00
smallmodel 52bb709ca5 Implemented CG_SetupFog() and CG_SetupPortalSky()
CG_SetupFog() must be called by CG_CalcViewValues()
CG_SetupPortalSky() must be called in CG_DrawActiveFrame()
2023-08-28 17:53:35 +02:00
smallmodel 24ea958748 Added R_ClearRealDlights() declaration 2023-08-28 17:45:11 +02:00
smallmodel b6143ce54c Better fog rendering
Implemented RB_SetupFog()
2023-08-28 17:36:57 +02:00
smallmodel 463ea7d34b Using viewParms.isPortalSky 2023-08-28 17:36:34 +02:00
smallmodel 1015302a7f Remove GLS_FOG_ENABLED if stateBits has GLS_FOG_WHITE 2023-08-28 17:36:19 +02:00
smallmodel c73f5917f8 Removed image->UseCount 2023-08-28 17:36:01 +02:00
smallmodel 9315cfa488 Added mohaas/mohaab variables 2023-08-28 17:35:54 +02:00
smallmodel 0f58b5780a Fixed fall damage on mohaas/mohaab
Use a percentage of the health instead
2023-08-28 15:49:28 +02:00
smallmodel edd5f07d48 Added healrate support (from mohaas) 2023-08-28 15:49:07 +02:00
smallmodel a7f258f2b1 Fixed health not healing with the healrate 2023-08-28 15:48:12 +02:00
smallmodel 65dcb72cba Fixed AmmoPickup not sending a message to the player 2023-08-28 15:41:06 +02:00
smallmodel 4885c536c8 Fixed wrong RB_CHECKOVERFLOW call (maybe #67) 2023-08-28 15:20:31 +02:00
smallmodel b6204dab78 Added LOD support 2023-08-28 02:32:33 +02:00
smallmodel 5b5951483a Added GetLodCutoff() and GetToolLodCutoff() 2023-08-28 02:26:36 +02:00
smallmodel 194d53569f Added foliage AFunc 2023-08-28 00:51:43 +02:00
smallmodel 5e8b54be7e Added new cvars from mohaas/mohaab 2023-08-27 23:24:06 +02:00
smallmodel 8dc91e413e Commented out GLS_MULTITEXTURE_ENV since it was removed in mohaas 2023-08-27 23:18:48 +02:00
smallmodel 57cf513b39 Added $bumpmap and normalmap (from mohaab) 2023-08-27 23:18:32 +02:00
smallmodel bb1326860b Added normalmap fields 2023-08-27 23:18:21 +02:00
smallmodel 136838e40b Fixed R_ColorShiftLightingBytes()
The lighting bytes must use tr.overbrightShift instead of tr.overbrightBits.
This makes the rendering more colorful
2023-08-27 22:18:09 +02:00
smallmodel 30d9483504 Decreased SHADERNUM and STATICMODEL shift values
When the number of shaders reached >1023, some surfaces started to be have random shaders started on them
The number of sorted shaders in a single game can now be up to 2048
2023-08-27 22:17:16 +02:00
smallmodel 05d3c50866 Stage fixes
Initialize animation phase to 0
Made CollapseMultitexture() work for more shaders
2023-08-27 22:15:08 +02:00
smallmodel d5e93d863a Set ps.walking in CG_TransitionSnapshot() instead 2023-08-27 19:53:29 +02:00
smallmodel d3f93aae15 Interpolate fLeanAngle #66 2023-08-27 19:32:38 +02:00
smallmodel 963e4aa7ec Restore saved Cgame state if the server is different (clear it otherwise) 2023-08-27 19:31:45 +02:00
smallmodel 5a250ea247 Fill cent->snapShotTime 2023-08-27 19:30:08 +02:00
smallmodel bc8d8aafc0 Fixed the viewmodel not being normal when no prediction is active 2023-08-27 19:14:23 +02:00
smallmodel f67ab4ec7f Fixed HUD being hidden when in camera (like MG42) 2023-08-27 18:56:37 +02:00
smallmodel cf9af20fbd Console history and wheel scroll
Implemented KeyEvent() for both UIConsole and UIDMConsole
Added a call to AddHistory() in UIConsole::KeyEnter()
2023-08-27 18:55:49 +02:00
smallmodel 3be2a3eb79 Made m_caret a size_t 2023-08-27 18:49:39 +02:00
smallmodel 7dfd18f4fb setTopItem(): don't set value below 0 2023-08-27 18:40:58 +02:00
smallmodel 05fc960338 Implemented getCount(), getPosition() and setPosition()
Fixed IteratePrev() being wrong
2023-08-27 18:40:38 +02:00
smallmodel 21d41ce14b Use facfont-20 for objective font 2023-08-27 17:48:18 +02:00
smallmodel 1562ba3f97 Fixed CG_ImpactMark being wrong with fSScale and fTScale 2023-08-27 17:48:10 +02:00
smallmodel 2798e73707 Fixed CG_CastFootShadow not working if only one of the red/green/blue channels was below 0.01 2023-08-27 17:47:49 +02:00
smallmodel 89aeee4269 TIKI_LoadSetupCase: reworked case integer values 2023-08-27 17:29:04 +02:00
smallmodel d50302fa41 Fixed tiki radius being wrong 2023-08-27 17:28:25 +02:00
smallmodel 8efae54450 Removed zero vectors assert in ProjectPointOnPlane(), it was removed since F.A.K.K 2 2023-08-27 17:13:12 +02:00
smallmodel 2785a72789 Fixed R_GatherLightSources crash 2023-08-27 17:01:53 +02:00
smallmodel ac55a44761 Implemented CG_CastFootShadow, CG_CastSimpleFeetShadow
Reimplemented CG_EntityShadow
2023-08-27 17:01:40 +02:00
smallmodel 42f1a286a8 Added MASK_FOOTSHADOW 2023-08-27 16:33:51 +02:00
smallmodel 241fa5d485 Fixed backtrace always showing 0x0 2023-08-26 21:16:48 +02:00
smallmodel e87f9c5710 Removed calls to NET_Init() as this function is already called from main() 2023-08-26 21:14:35 +02:00
smallmodel c95a6ee3fd Cleaned code up 2023-08-26 21:13:14 +02:00
smallmodel 10b954cb1a Added MAX_KEYVALUES_LENGTH 2023-08-26 21:12:32 +02:00
smallmodel cf7914b6f8 Fixed compiler warning about void* to int 2023-08-26 20:23:00 +02:00
smallmodel e58e048f00 Added comment 2023-08-26 20:22:39 +02:00
smallmodel b92cd8a64f Fixed player info for SVC_Status
Fixed "protocol" always returning 17 for SVC_Info
Fixed server not processing gamespy queries (not appearing in the master list)
2023-08-26 18:18:30 +02:00
smallmodel 317aead26d Replaced 1350 with MAX_INFO_STRING
Fixed wrong gamespy query being processed
2023-08-26 18:17:55 +02:00
smallmodel e93780c66c Fixed players_callback always returning players when there are none
Fixed gcd_think() crashing if it wasn't initialized
2023-08-26 18:17:28 +02:00
smallmodel af8990acf0 Added SV_ProcessGamespyQueries() declaration 2023-08-26 18:16:35 +02:00
smallmodel e41dcf03ad Added CVAR_SERVERINFO flag to "protocol"
Removed CVAR_SERVERINFO flag from "com_protocol" (useless)
2023-08-26 18:15:39 +02:00
smallmodel 0209e8f782 Fixed call to GSICancelAvailableCheck() causing socket 0 (STDIN) to be closed, any read() afterwards would hang 2023-08-26 16:18:57 +02:00
smallmodel 50d935171e Updated README 2023-08-25 23:25:04 +02:00
smallmodel 86ee9089e9 Include cg_radar.h 2023-08-25 23:22:44 +02:00
smallmodel ba6fe112bb Using Sys_LoadDll to load modules. Sys_LoadDll uses the binary path instead of the current working directory 2023-08-25 23:00:05 +02:00
smallmodel 15860a7795 Windows NT and Linux being both multi-user system, the homepath now defaults to %APPDATA%\openmohaa (Windows NT) and ~/openmohaa (unix) 2023-08-25 22:58:55 +02:00
smallmodel 78b3ad8075 As modules concern all 3 versions of the game, they're now installed in the root directory 2023-08-25 22:57:31 +02:00
smallmodel f61bda330e Set homepath to "openmohaa" (win32) and ".openmohaa" (unix) 2023-08-25 22:55:27 +02:00
smallmodel 5c9fceea2c Use sizeof sockaddr_in instead of 16 2023-08-25 22:55:22 +02:00
smallmodel 32cceebc47 Use the Git abbreviated commit hash for the product version 2023-08-24 23:33:29 +02:00
smallmodel 9d921df733 Added Git abbreviated commit hash 2023-08-24 23:33:19 +02:00
smallmodel 428f8c183d Put the extension before the platform string 2023-08-24 23:33:07 +02:00
smallmodel 45aae54b32 Renamed "Base" to "Allied Assault" 2023-08-24 23:32:40 +02:00
smallmodel d9ca73bc4c Updated README 2023-08-24 23:20:01 +02:00
smallmodel c2e24da9bd Initialize tracerspeed to 1 (this fixes turret bullets on mohaas/mohaab) 2023-08-24 23:19:49 +02:00
smallmodel c6ae5ed551 Added gamespy cd key authorization code (mohaas/mohaab only) 2023-08-24 23:19:21 +02:00
smallmodel 0f86a5ee8a Fixed "gamename" on mohaab
Use GS_GetCurrentGameName() and GS_GetCurrentGameVersion() in basic_callback
Using DF_ALLOW_LEAN_MOVEMENT instead of raw dmflags
2023-08-23 23:50:40 +02:00
smallmodel 803e53869b Set qr_custom_handler to NULL instead of 0 2023-08-23 23:49:25 +02:00
smallmodel a4fc25cca8 Increased the version number 2023-08-23 23:48:58 +02:00
smallmodel 28fbcf5628 Removed player printf destructor
Remove EF_PLAYER entflags from the Player destructor
2023-08-21 23:44:33 +02:00
smallmodel 3ea73febe4 Fixed spectate num 2023-08-21 23:33:23 +02:00
smallmodel 9eb3b3e1c3 Fixed infinite loop in SetPlayerSpectate() 2023-08-21 21:38:44 +02:00
smallmodel 48e1c39320 Fixed crash due do bad wrong delete after new[]
Fixed crash in ActorPath::ReFindPath when m_path is renewed
2023-08-21 21:38:32 +02:00
smallmodel fe38c7650f Updated the version number 2023-08-21 00:31:14 +02:00
smallmodel 5e2f5010f8 Fixed demo recording with different protocols 2023-08-21 00:20:04 +02:00
smallmodel efce4703ca Initialize demo_protocols from the com_protocol integer value 2023-08-21 00:19:46 +02:00
smallmodel 94ab4a5ac5 Moved MSG_ReadServerFrameTime and MSG_WriteServerFrameTime to qcommon/msg.cpp 2023-08-21 00:09:00 +02:00
smallmodel 58321be1ce sv_fps must have CVAR_SAVEGAME and CVAR_SERVERINFO 2023-08-21 00:08:08 +02:00
509 changed files with 113325 additions and 135128 deletions

No files matched your search

+2
View File
@@ -2,6 +2,8 @@ name: Build
on:
push:
branches:
- '*'
pull_request:
workflow_call:
+2 -1
View File
@@ -44,5 +44,6 @@ profile
*.suo
.vs
out
code_unfinished/*
thirdparties/
code/parser/generated/*
+20 -11
View File
@@ -11,17 +11,33 @@ if(TARGET_GAME_TYPE)
endif()
set(TARGET_BASE_GAME "main")
set(TARGET_BASE_GAME "./")
set(CMAKE_DEBUG_POSTFIX "-dbg")
if(MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# 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")
add_compile_options(-Wno-comment)
# Treat no return type as error
add_compile_options(-Werror=return-type)
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
# Ignore warnings for code like 'assert("Assert string")'
add_compile_options(-Wno-pointer-bool-conversion)
endif()
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
# which will cause undefined behavior and crashes due to memory corruption
add_compile_options(-fno-gnu-unique)
endif()
if(DEBUG_MEMORY)
add_definitions(-D_DEBUG_MEM)
endif()
@@ -47,6 +63,7 @@ ENDIF()
IF(CMAKE_BUILD_TYPE MATCHES Debug)
add_definitions(-D_DEBUG)
# NOTE: The following may mess up function importation
#if(UNIX)
# # Enable all exports so all functions name can be seen during executable crash
# set(CMAKE_ENABLE_EXPORTS ON)
@@ -73,6 +90,7 @@ target_compile_features(omohaaded PUBLIC c_variadic_macros)
target_link_libraries(omohaaded PRIVATE omohserver)
target_link_libraries(omohaaded PRIVATE syslib)
target_link_libraries(omohaaded PRIVATE qcommon qcommon_standalone)
# 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}")
@@ -110,15 +128,6 @@ if (NOT BUILD_NO_CLIENT)
set_target_properties(openmohaa PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
target_link_libraries(openmohaa PRIVATE jpeg8)
if (USE_OPENAL)
# Try to use OpenAL
find_package(OpenAL)
if (OPENAL_FOUND)
target_compile_definitions(openmohaa PRIVATE USE_OPENAL=1)
target_include_directories(openmohaa PRIVATE ${OPENAL_INCLUDE_DIR})
target_link_libraries(openmohaa PRIVATE ${OPENAL_LIBRARY})
endif()
endif()
if (MSVC)
target_link_options(openmohaa PRIVATE "/MANIFEST:NO")
+23 -91
View File
@@ -15,116 +15,48 @@
|_|
```
## Current State
## Intro
OpenMoHAA is still under development. The single-player campaign is not yet functional due to AI not being fully implemented, and due to the script engine having a few issues. But the `training` map can be played from start to end. The current focus is on multiplayer.
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).
## Running
## Getting started
Backup existing mohaa files, **cgamex86.dll** and **gamex86.dll** (set their extension to **.bak**)
- [Installing OpenMoHAA](docs/getting_started_installation.md)
- [Running OpenMoHAA and using expansion assets](docs/getting_started_running.md)
a) extract archive to your MOHAA installation directory.
## Current state
-or-
### Multiplayer
b) Copy all pak*.pk3 files and the sound/ directory from your **MOHAA/main** directory into openmohaa's 'main' directory.
The Multiplayer part is almost fully stable.
If you have problems running the game :
Server admins can use OpenMoHAA to [host](docs/getting_started_installation.md#server) a mohaa/mohaas/mohaab server. Bugs must be reported by creating a new [issue](https://github.com/openmoh/openmohaa/issues) on the OpenMoHAA GitHub project. Players can use OpenMoHAA to [play](docs/getting_started_installation.md#client) on a mohaa/mohaas/mohaab server.
You may need to install Microsoft Visual C++ 2015/2017/2019/2022 Redistributable from
All game modes including `Tug-of-War` from Medal of Honor: Spearhead, and `Liberation` from Medal of Honor: Breakthrough are implemented and are working as intended. Mods like `Freeze-Tag` are working as well.
https://learn.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist?view=msvc-170
### Single-player
You can now start a local OpenMOHAA server or play on a server.
The `training` map can be played from start to end. The single-player campaign is not fully functional, but at least AI can breathe, talk, run, and shoot.
**Medal of Honor: Allied Assault Spearhead** and **Medal of Honor: Allied Assault Breakthrough** are supported in OpenMoHAA using the `com_target_game` variable. To play an expansion, append the following command-line arguments to the executable:
## Features
- `+set com_target_game 1` for Spearhead (mohaas/mohta)
- `+set com_target_game 2` for Breakthrough (mohaab/mohtt)
On Windows, you can create a shortcut to OpenMoHAA with these command-line arguments.
The default value of `com_target_game` is 0 for the base game.
With `com_target_game`, OpenMoHAA will support the network protocol accordingly
### Playing with bots
OpenMoHAA has a basic bot system that emulates real players. The maximum number of bots is defined by the `sv_maxbots` variable, and the number of initial bots is defined by the `sv_numbots` variable. Bots can also be added or removed using the `addbot` and `removebot` commands.
This feature is a great way to test the gameplay and mods.
## Builds
### Server
The server version can be built successfully, but some features are not functional. For example, the Actor and Vehicle systems are almost fully implemented, but they are not yet stable. This means that they may not work as expected and could cause crashes.
Overall, the server and the fgame components are almost fully implemented, but they may not be completely stable. There could be some minor bugs (and rare crashes), but the game should be playable.
### Client
The client version of OpenMoHAA has undergone partial implementation, with the cgame module being nearly completed. Credits to the SDK of **Heavy Metal: F.A.K.K. 2** both the cgame and fgame modules.
The current operational status for each component is as follow:
| Component | Full | Almost | Half | Early | Bad | Not working | Comment |
|-------------------------|------|--------|------|-------|-----|-------------|-------------------------------------------------------------------|
| Audio | | | | | x | | Very basic implementation from Quake III |
| CG Module | | x | | | | | Missing FX, Marks and decals |
| Client | | x | | | | | Missing GameSpy, server list, binds, map picker, ... |
| Collision | x | | | | | | |
| Model/TIKI/Skeletor | x | | | | | | |
| Renderer | | x | | | | | Missing ghost, marks, sphere lights, sky portal, sun flare, swipe |
| Server | | x | | | | | Probably a few bugs remaining |
| Server module (fgame) | | x | | | | | Actor, vehicle, and few gameplay bugs |
| UI | | | x | | | | Has core features only (menu, widgets, console, hud, urc loading) |
- [What's working and what's not](docs/features_implementation.md)
- [New features](docs/features.md)
- [Scripting commands](https://htmlpreview.github.io/?https://github.com/openmoh/openmohaa/blob/main/docs/features_g_allclasses.html)
## Compiling
OpenMoHAA supports any architecture, thanks to the CMake build system and cross-platform code/libraries. While the most common little-Endian architectures (arm, aarch64, x86, x86_64) have been tested and confirmed to work, big-Endian architectures should be supported as well; however, they remain untested.
The following tools are required for all platforms:
- CMake >= 3.5
- Flex and Bison
- A C++11 compiler is also required.
The installation directory can be set to the MOHAA directory.
By default, the build will produce both the client and dedicated server versions. The client build can be excluded by appending `-DBUILD_NO_CLIENT=1` to the CMake command-line arguments. Using this parameter will result in only the server portion being built.
### Linux
These are the tools required on Linux :
- Clang >= 3.3 or GCC >= 4.8.1
**clang-3.5** and **gcc-4.8.5** should work (tested on Ubuntu 16.04). Use the latest possible version of those compilers.
SDL2 library is required (libsdl2-dev).
1 line install command with latest clang version : `sudo apt-get install -y ninja-build cmake make clang-15 lld-15 flex bison libsdl2-dev`
Example with **CMake**, **clang-15** and **ninja-build** installed:
```sh
mkdir .cmake && cd .cmake
cmake -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15 -G Ninja
```
### Windows
Visual Studio (2019 or 2022) is generally preferred.
Flex and Bison can be downloaded from here: https://github.com/lexxmark/winflexbison/releases/tag/v2.5.25
Append `-DFLEX_EXECUTABLE=...\win_flex.exe -DBISON_EXECUTABLE=...\win_bison.exe` to the CMake command-line to use the package from the link above.
- See [Compiling OpenMoHAA](docs/compiling.md)
## Screenshots
| | |
|-------------------------------------------------------------------------------|----------------------------------------------------------------------|
| ![](docs/images/opmtt-x86_64_0.56.0_1.png "Playing on a Breakthrough server") | ![](docs/images/opmtt-x86_64_0.56.0_2.png) |
| ![](docs/images/opmtt-x86_64_0.56.0_3.png) | ![](docs/images/opm-arm_53_tt_1.png "OpenMoHAA on Raspberry Pi 4 B") |
| ![](docs/images/opm-x86_64_0.58.0_1.png "Playing Freeze-Tag mode with bots") | ![](docs/images/opm-x86_64_0.58.0_2.png "Single-Player training") |
| | |
|-----------------------------------------------------------------------------------|----------------------------------------------------------------------------|
| ![](docs/images/v0.60.0-x86_64/mohdm1_1.png) | ![](docs/images/v0.60.0-x86_64/training_1.png) |
| ![](docs/images/v0.60.0-x86_64/flughafen_1.png) | ![](docs/images/v0.60.0-x86_64/flughafen_2.png) |
| ![](docs/images/v0.60.0-x86_64/mohdm2_1.png "Playing Freeze-Tag mode with bots") | ![](docs/images/v0.60.0-x86_64/training_3.png "Single-Player training") |
*More screenshots [here](docs/images)*
## Third party
+1 -1
View File
@@ -18,7 +18,7 @@ set(SOURCES_SHARED
"../script/scriptvariable.cpp"
)
file(GLOB_RECURSE SOURCES_BG "../fgame/bg_misc.cpp" "../fgame/bg_pmove.cpp" "../fgame/bg_slidemove.cpp")
file(GLOB_RECURSE SOURCES_BG "../fgame/bg_misc.cpp" "../fgame/bg_pmove.cpp" "../fgame/bg_slidemove.cpp" "../fgame/bg_voteoptions.cpp")
file(GLOB_RECURSE SOURCES_CGAME "./*.c" "./*.cpp")
add_library(cgame SHARED ${SOURCES_CGAME} ${SOURCES_BG})
+142 -10
View File
@@ -22,43 +22,175 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cg_local.h"
#include "cg_archive.h"
#include "cg_commands.h"
#include "memarchiver.h"
#include "../qcommon/tiki.h"
void CG_ArchiveStuff(MemArchiver& archiver, int svsTime)
{
// FIXME: unimplemented
archiver.SetBaseTime(svsTime);
commandManager.ArchiveToMemory(archiver);
CG_ArchiveVSSGlobals(archiver);
}
void CG_SaveStateToBuffer(void** out, int svsTime)
size_t CG_SaveStateToBuffer(void** out, int svsTime)
{
// FIXME: unimplemented
MemArchiver archiver;
size_t size;
archiver.SetupForWriting(0x200000);
CG_ArchiveStuff(archiver, svsTime);
size = archiver.BufferSize();
if (size && out) {
*out = archiver.ConfiscateBuffer();
}
return size;
}
void CG_LoadStateToBuffer(void* state, int size, int svsTime)
qboolean CG_LoadStateToBuffer(void* state, size_t size, int svsTime)
{
// FIXME: unimplemented
MemArchiver archiver;
archiver.SetupForReading((byte*)state, size);
CG_ArchiveStuff(archiver, svsTime);
return archiver.FinishedReading();
}
void CG_ArchiveStringContainer(MemArchiver& archiver, Container<str>* container)
{
// FIXME: unimplemented
int num;
int i;
if (archiver.IsReading()) {
str tmp;
archiver.ArchiveInteger(&num);
container->ClearObjectList();
for (i = 0; i < num; i++) {
archiver.ArchiveString(&tmp);
container->AddObject(tmp);
}
} else {
num = container->NumObjects();
archiver.ArchiveInteger(&num);
for (i = 0; i < num; i++) {
str& tmp = container->ObjectAt(i + 1);
archiver.ArchiveString(&tmp);
}
}
}
void CG_ArchiveTikiPointer(MemArchiver& archiver, dtiki_t** pTiki)
{
// FIXME: unimplemented
str tmp;
if (archiver.IsReading()) {
archiver.ArchiveString(&tmp);
if (tmp.length()) {
*pTiki = cgi.R_Model_GetHandle(cgi.R_RegisterModel(tmp.c_str()));
} else {
*pTiki = NULL;
}
} else {
if (*pTiki) {
tmp = (*pTiki)->name;
}
archiver.ArchiveString(&tmp);
}
}
void CG_ArchiveModelHandle(MemArchiver& archiver, qhandle_t* handle)
{
// FIXME: unimplemented
str tmp;
if (archiver.IsReading()) {
archiver.ArchiveString(&tmp);
if (tmp.length()) {
*handle = cgi.R_RegisterModel(tmp.c_str());
} else {
*handle = NULL;
}
} else {
if (*handle) {
tmp = cgi.R_GetModelName(*handle);
} else {
tmp = "";
}
archiver.ArchiveString(&tmp);
}
}
void CG_ArchiveShaderHandle(MemArchiver& archiver, qhandle_t* handle)
{
// FIXME: unimplemented
str tmp;
if (archiver.IsReading()) {
archiver.ArchiveString(&tmp);
if (tmp.length()) {
*handle = cgi.R_RegisterShader(tmp.c_str());
} else {
*handle = NULL;
}
} else {
if (*handle) {
tmp = cgi.R_GetShaderName(*handle);
} else {
tmp = "";
}
archiver.ArchiveString(&tmp);
}
}
void CG_ArchiveRefEntity(MemArchiver& archiver, refEntity_t* ref)
{
// FIXME: unimplemented
archiver.ArchiveRaw(&ref->reType, sizeof(ref->reType));
archiver.ArchiveInteger(&ref->renderfx);
CG_ArchiveModelHandle(archiver, &ref->hModel);
CG_ArchiveModelHandle(archiver, &ref->hOldModel);
archiver.ArchiveVec3(ref->lightingOrigin);
archiver.ArchiveInteger(&ref->parentEntity);
archiver.ArchiveVec3(ref->axis[0]);
archiver.ArchiveVec3(ref->axis[1]);
archiver.ArchiveVec3(ref->axis[2]);
archiver.ArchiveBoolean(&ref->nonNormalizedAxes);
archiver.ArchiveVec3(ref->origin);
archiver.ArchiveRaw(ref->frameInfo, 192);
archiver.ArchiveFloat(&ref->actionWeight);
archiver.ArchiveShort(&ref->wasframe);
archiver.ArchiveFloat(&ref->scale);
archiver.ArchiveVec3(ref->oldorigin);
archiver.ArchiveInteger(&ref->skinNum);
CG_ArchiveShaderHandle(archiver, &ref->customShader);
archiver.ArchiveRaw(ref->shaderRGBA, 4);
archiver.ArchiveFloat(ref->shaderTexCoord);
archiver.ArchiveFloat(&ref->shaderTexCoord[1]);
archiver.ArchiveFloat(&ref->shaderTime);
archiver.ArchiveInteger(&ref->entityNumber);
archiver.ArchiveRaw(ref->surfaces, 32);
archiver.ArchiveFloat(ref->shader_data);
archiver.ArchiveFloat(&ref->shader_data[1]);
ref->bone_tag = NULL;
ref->bone_quat = NULL;
ref->of = NULL;
ref->nf = NULL;
CG_ArchiveTikiPointer(archiver, &ref->tiki);
archiver.ArchiveInteger(&ref->bonestart);
archiver.ArchiveInteger(&ref->morphstart);
archiver.ArchiveBoolean(&ref->hasMorph);
archiver.ArchiveFloat(&ref->radius);
archiver.ArchiveFloat(&ref->rotation);
}
+3 -5
View File
@@ -30,15 +30,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "../qcommon/container.h"
#include "../qcommon/str.h"
class MemArchiver {
};
class MemArchiver;
extern "C" {
#endif
void CG_SaveStateToBuffer(void** out, int svsTime);
void CG_LoadStateToBuffer(void* state, int size, int svsTime);
size_t CG_SaveStateToBuffer(void** out, int svsTime);
qboolean CG_LoadStateToBuffer(void* state, size_t size, int svsTime);
#ifdef __cplusplus
void CG_ArchiveStuff(MemArchiver& archiver, int svsTime);
+1143 -306
View File
File diff suppressed because it is too large. Load diff
+94 -19
View File
@@ -116,6 +116,7 @@ TIKI file, similar to ScriptMaster in the server game dll.
class spawnthing_t;
class specialeffect_t;
class MemArchiver;
typedef enum {
NOT_RANDOM,
@@ -181,6 +182,9 @@ public:
float decal_orientation;
float decal_radius;
float spin_rotation;
public:
void ArchiveToMemory(MemArchiver& archiver);
};
inline cg_common_data::cg_common_data()
@@ -249,6 +253,9 @@ public:
spawnthing_t *m_spawnthing;
void (*touchfcn)(ctempmodel_t *ct, trace_t *trace);
public:
void ArchiveToMemory(MemArchiver& archiver);
};
inline ctempmodel_t::ctempmodel_t()
@@ -315,8 +322,44 @@ public:
int lastPhysicsTime;
int lastLightingTime;
qboolean lastValid;
public:
cvssource_t();
public:
void ArchiveToMemory(MemArchiver& archiver);
};
inline cvssource_t::cvssource_t()
: next(NULL)
, prev(NULL)
, stnext(NULL)
, stindex(0)
, lastRadius(0)
, lastDensity(0)
, lastColor {0}
, lastLighting {0}
, newRadius(0)
, newDensity(0)
, newColor {0}
, newLighting {0}
, ooRadius(0)
, startAlpha(0)
, roll(0)
, lifeTime(0)
, collisionmask(0)
, parent(0)
, flags(0)
, flags2(0)
, smokeType(0)
, typeInfo(0)
, fadeMult(0)
, scaleMult(0)
, lastPhysicsTime(0)
, lastLightingTime(0)
, lastValid(qfalse)
{}
class cvssourcestate_t
{
public:
@@ -387,6 +430,9 @@ public:
protected:
qboolean usedNumbers[256];
virtual void RemoveEntity(int entnum);
public:
void ArchiveToMemory(MemArchiver& archiver);
};
inline enttracker_t::enttracker_t()
@@ -437,6 +483,9 @@ public:
Vector oldorigin;
qboolean active;
qboolean lerp_emitter;
public:
void ArchiveToMemory(MemArchiver& archiver);
};
// emitterthing_t is used to keep track of the last time and emitter was updated
@@ -452,6 +501,9 @@ public:
emittertime_t *GetEmitTime(int entnum);
virtual void RemoveEntity(int entnum);
qboolean startoff;
public:
void ArchiveToMemory(MemArchiver& archiver);
};
inline void emitterthing_t::RemoveEntity(int entnum)
@@ -510,18 +562,23 @@ public:
int entity_number;
int command_number;
int last_command_time;
public:
void ArchiveToMemory(MemArchiver& archiver);
};
// This class is used for keeping track of the last time an entity executed a
// particular command. A command number must be assigned externally by the user
class commandthing_t : public enttracker_t
{
Container<commandtime_t *> m_commandtimes; // A list of entity numbers and the last time they
// executed a command
Container<commandtime_t> m_commandtimes; // A list of entity numbers and the last time they
// executed a command
public:
commandtime_t *GetLastCommandTime(int entnum, int commandnum);
virtual void RemoveEntity(int entnum);
void ArchiveToMemory(MemArchiver& archiver);
};
inline void commandthing_t::RemoveEntity(int entnum)
@@ -532,7 +589,7 @@ inline void commandthing_t::RemoveEntity(int entnum)
count = m_commandtimes.NumObjects();
for (num = count; num >= 1; num--) {
ct = m_commandtimes.ObjectAt(num);
ct = &m_commandtimes.ObjectAt(num);
if (ct->entity_number == entnum) {
m_commandtimes.RemoveObjectAt(num);
}
@@ -543,28 +600,27 @@ inline void commandthing_t::RemoveEntity(int entnum)
inline commandtime_t *commandthing_t::GetLastCommandTime(int entnum, int commandnum)
{
int num, count;
commandtime_t *ct;
int num, count;
// Search for this entity number
count = m_commandtimes.NumObjects();
for (num = 1; num <= count; num++) {
ct = m_commandtimes.ObjectAt(num);
commandtime_t *ct = &m_commandtimes.ObjectAt(num);
if ((ct->entity_number == entnum) && (ct->command_number == commandnum)) {
return ct;
}
}
// Add a new entry if we didn't find it
ct = new commandtime_t;
ct->entity_number = entnum;
ct->command_number = commandnum;
ct->last_command_time = 0;
commandtime_t ct;
ct.entity_number = entnum;
ct.command_number = commandnum;
ct.last_command_time = 0;
m_commandtimes.AddObject(ct);
return ct;
return &m_commandtimes.ObjectAt(m_commandtimes.NumObjects());
}
class spawnthing_t : public emitterthing_t
@@ -625,6 +681,9 @@ public:
void (*touchfcn)(ctempmodel_t *ct, trace_t *trace);
str GetModel(void);
void SetModel(str model);
public:
void ArchiveToMemory(MemArchiver& archiver);
};
inline void spawnthing_t::SetModel(str model)
@@ -824,8 +883,8 @@ private:
void SetClampVel(Event *ev);
void SetClampVelAxis(Event *ev);
ctempmodel_t *AllocateTempModel(void);
qboolean TempModelPhysics(ctempmodel_t *p, float ftime, float time2, float scale);
qboolean TempModelRealtimeEffects(ctempmodel_t *p, float ftime, float time2, float scale);
qboolean TempModelPhysics(ctempmodel_t *p, float ftime, float scale);
qboolean TempModelRealtimeEffects(ctempmodel_t *p, float ftime, float scale);
qboolean LerpTempModel(refEntity_t *newEnt, ctempmodel_t *p, float frac);
void SpawnEffect(int count, int timealive);
void SpawnTempModel(int count);
@@ -871,13 +930,13 @@ public:
void UpdateEmitter(dtiki_t *tiki, vec3_t axis[3], int entity_number, int parent_number, Vector entity_origin);
void UpdateBeam(dtiki_t *tiki, int entity_number, spawnthing_t *beamthing);
void PlaySound(
str sound_name,
str sound_name,
const vec3_t origin = NULL,
int channel = CHAN_AUTO,
float volume = -1,
float min_distance = -1,
float pitch = -1,
int argstype = 0
int channel = CHAN_AUTO,
float volume = -1,
float min_distance = -1,
float pitch = -1,
int argstype = 0
);
spawnthing_t *InitializeSpawnthing(spawnthing_t *ep);
@@ -891,6 +950,7 @@ public:
void InitializeEmitters(void);
void RemoveClientEntity(int number, dtiki_t *tiki, centity_t *cent, ctempmodel_t *p = NULL);
void ClearSwipes(void);
void FreeSpawnthing(spawnthing_t *sp);
void ResetTempModels(void);
void SpawnTempModel(int count, spawnthing_t *sp);
@@ -921,6 +981,21 @@ public:
void ResetTreadMarkSources(Event *ev);
void InitializeRainCvars();
void InitializeBeams();
//
// archive stuff
//
int IdForTempModel(const ctempmodel_t *model);
ctempmodel_t *TempModelForId(int id);
int IdForSpawnThing(const spawnthing_t *sp);
spawnthing_t *SpawnThingForId(int id);
int IdForVssSource(const cvssource_t *source);
cvssource_t *VssSourceForId(int id);
void ArchiveTempModelPointerToMemory(MemArchiver& archiver, ctempmodel_t **model);
void ArchiveSpawnThingPointerToMemory(MemArchiver& archiver, spawnthing_t **sp);
void ArchiveVssSourcePointerToMemory(MemArchiver& archiver, cvssource_t **source);
void ArchiveToMemory(MemArchiver& archiver);
};
class EmitterLoader : public Listener
+60 -50
View File
@@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// text commands typed in at the local console, or executed by a key binding
#include "cg_local.h"
#include "../fgame/bg_voteoptions.h"
void CG_TargetCommand_f(void);
@@ -339,56 +340,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 },
};
/*
+169 -6
View File
@@ -323,8 +323,12 @@ static void CG_DrawPauseIcon()
}
w = cgi.R_GetShaderWidth(handle);
h = cgi.R_GetShaderHeight(handle);
x = w / 4;
y = cgs.glconfig.vidHeight - (1.25f * h);
if (cg.snap && cg.snap->ps.blend[3] > 0) {
y = cgs.glconfig.vidHeight * 0.45f - h / 2.f;
} else {
y = cgs.glconfig.vidHeight * 0.75f - h / 2.f;
}
x = (cgs.glconfig.vidWidth - w) / 2.f;
cgi.R_SetColor(colorWhite);
cgi.R_DrawStretchPic(x, y, w, h, 0, 0, 1, 1, handle);
@@ -682,11 +686,11 @@ void CG_DrawObjectives()
iTotalNumLines = 0;
for (i = CS_OBJECTIVES; i < CS_OBJECTIVES + MAX_OBJECTIVES; ++i) {
CG_ProcessConfigString(i);
CG_ProcessConfigString(i, qfalse);
}
iCurrentObjective = atoi(CG_ConfigString(CS_CURRENT_OBJECTIVE));
fTimeDelta = cg.ObjectivesAlphaTime - cg.time;
iCurrentObjective = atoi(CG_ConfigString(CS_CURRENT_OBJECTIVE));
fTimeDelta = cg.ObjectivesAlphaTime - cg.time;
cg.ObjectivesCurrentAlpha = cg.ObjectivesDesiredAlpha;
if (fTimeDelta > 0) {
cg.ObjectivesCurrentAlpha =
@@ -1083,7 +1087,7 @@ void CG_DrawSpectatorView_ver_15()
iClientNum = cg.snap->ps.stats[STAT_INFOCLIENT];
sprintf(buf, "%s : %i", cg.clientinfo[iClientNum].name, cg.snap->ps.stats[STAT_INFOCLIENT_HEALTH]);
hShader = 0;
hShader = 0;
color[0] = 0.5;
color[1] = 1.0;
color[2] = 0.5;
@@ -1165,6 +1169,163 @@ void CG_DrawSpectatorView()
}
}
void CG_DrawCrosshair()
{
centity_t *friendEnt;
qhandle_t shader;
vec3_t forward;
vec3_t end;
vec3_t mins, maxs;
trace_t trace;
float x, y;
float width, height;
shader = NULL;
if (!cg_hud->integer || !ui_crosshair->integer) {
return;
}
if (!cg.snap) {
return;
}
if ((cg.snap->ps.pm_flags & PMF_NO_LEAN) || (cg.snap->ps.pm_flags & PMF_INTERMISSION)) {
return;
}
if (!cg.snap->ps.stats[STAT_CROSSHAIR]
&& (!cg.snap->ps.stats[STAT_INZOOM] || cg.snap->ps.stats[STAT_INZOOM] > 30)) {
return;
}
if (cgs.gametype != GT_FFA) {
AngleVectorsLeft(cg.refdefViewAngles, forward, NULL, NULL);
VectorMA(cg.refdef.vieworg, 8192, forward, end);
VectorClear(mins);
VectorClear(maxs);
CG_Trace(&trace, cg.refdef.vieworg, mins, maxs, end, 9999, MASK_SOLID, qfalse, qtrue, "CG_DrawCrosshair");
// ENTITYNUM_WORLD check added in OPM
if ((trace.entityNum != ENTITYNUM_NONE && trace.entityNum != ENTITYNUM_WORLD)
&& trace.entityNum != cg.snap->ps.clientNum) {
int myFlags;
friendEnt = &cg_entities[trace.entityNum];
if (cgs.gametype != GT_SINGLE_PLAYER) {
myFlags = cg_entities[cg.snap->ps.clientNum].currentState.eFlags & EF_ANY_TEAM;
} else {
// the player will always be considered as an allied
// in single-player
myFlags = EF_ALLIES;
}
if (((myFlags & EF_ALLIES) && (friendEnt->currentState.eFlags & EF_ALLIES))
|| ((myFlags & EF_AXIS) && (friendEnt->currentState.eFlags & EF_AXIS))) {
// friend
if (cg.snap->ps.stats[STAT_CROSSHAIR]) {
shader = cgi.R_RegisterShader(cg_crosshair_friend->string);
}
} else {
// enemy
if (cg.snap->ps.stats[STAT_CROSSHAIR]) {
shader = cgi.R_RegisterShader(cg_crosshair->string);
}
}
} else {
if (cg.snap->ps.stats[STAT_CROSSHAIR]) {
shader = cgi.R_RegisterShader(cg_crosshair->string);
}
}
} else {
// FFA
if (cg.snap->ps.stats[STAT_CROSSHAIR]) {
shader = cgi.R_RegisterShader(cg_crosshair->string);
}
}
if (shader) {
width = cgi.R_GetShaderWidth(shader);
height = cgi.R_GetShaderHeight(shader);
x = (cgs.glconfig.vidWidth - width) * 0.5f;
y = (cgs.glconfig.vidHeight - height) * 0.5f;
cgi.R_SetColor(NULL);
cgi.R_DrawStretchPic(x, y, width, height, 0, 0, 1, 1, shader);
}
}
void CG_DrawVote()
{
const char *text;
int seconds;
int percentYes;
int percentNo;
int percentUndecided;
float x, y;
vec4_t col;
if (!cgs.voteTime) {
return;
}
if (cgs.voteRefreshed) {
cgs.voteRefreshed = qfalse;
}
seconds = (30000 - (cg.time - cgs.voteTime)) / 1000 + 1;
if (seconds < 0) {
seconds = 0;
}
percentYes = cgs.numVotesYes * 100 / (cgs.numUndecidedVotes + cgs.numVotesNo + cgs.numVotesYes);
percentNo = cgs.numVotesNo * 100 / (cgs.numUndecidedVotes + cgs.numVotesNo + cgs.numVotesYes);
percentUndecided = cgs.numUndecidedVotes * 100 / (cgs.numUndecidedVotes + cgs.numVotesNo + cgs.numVotesYes);
x = 8;
y = (cgs.glconfig.vidHeight > 480) ? (cgs.glconfig.vidHeight * 0.725f) : (cgs.glconfig.vidHeight * 0.75f);
cgi.R_SetColor(NULL);
text = va("%s: %s", cgi.LV_ConvertString("Vote Running"), cgs.voteString);
cgi.R_DrawString(cgs.media.attackerFont, text, x, y, -1, qfalse);
y += 12;
text =
va("%s: %isec %s: %i%% %s: %i%% %s: %i%%",
cgi.LV_ConvertString("Time"),
seconds,
cgi.LV_ConvertString("Yes"),
percentYes,
cgi.LV_ConvertString("No"),
percentNo,
cgi.LV_ConvertString("Undecided"),
percentUndecided);
cgi.R_DrawString(cgs.media.attackerFont, text, x, y, -1, qfalse);
if (cg.snap && !cg.snap->ps.voted) {
col[0] = 0.5;
col[1] = 1.0;
col[2] = 0.5;
col[3] = 1.0;
cgi.R_SetColor(col);
y += 12;
text = cgi.LV_ConvertString("Vote now, it's your patriotic duty!");
cgi.R_DrawString(cgs.media.attackerFont, text, x, y, -1, qfalse);
y += 12;
text = cgi.LV_ConvertString("To vote Yes, press F1. To vote No, press F2.");
cgi.R_DrawString(cgs.media.attackerFont, text, x, y, -1, qfalse);
cgi.R_SetColor(NULL);
}
}
/*
==============
CG_Draw2D
@@ -1183,5 +1344,7 @@ void CG_Draw2D(void)
CG_DrawPlayerTeam();
CG_DrawPlayerEntInfo();
CG_UpdateAttackerDisplay();
CG_DrawVote();
CG_DrawInstantMessageMenu();
CG_DrawCrosshair();
}
+22 -1
View File
@@ -35,6 +35,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cg_public.h"
#ifdef __cplusplus
class MemArchiver;
extern "C" {
#endif
@@ -394,8 +396,19 @@ extern "C" {
int maxclients;
int cinematic;
int mapChecksum;
qboolean useMapChecksum;
char mapname[MAX_QPATH];
//
// vote
//
int voteTime;
int numVotesYes;
int numVotesNo;
int numUndecidedVotes;
qboolean voteRefreshed;
char voteString[1024];
//
// locally derived information from gamestate
//
@@ -458,6 +471,9 @@ extern "C" {
extern cvar_t *cg_hud;
extern cvar_t *cg_huddraw_force;
extern cvar_t *cg_drawsvlag;
extern cvar_t *cg_crosshair;
extern cvar_t *cg_crosshair_friend;
extern cvar_t *ui_crosshair;
extern cvar_t *vm_offset_max;
extern cvar_t *vm_offset_speed;
extern cvar_t *vm_sway_front;
@@ -488,7 +504,7 @@ extern "C" {
//
// cg_main.c
//
void CG_ProcessConfigString(int num);
void CG_ProcessConfigString(int num, qboolean modelOnly);
const char *CG_ConfigString(int index);
void CG_AddToTeamChat(const char *str);
void CG_NewClientinfo(int clientNum);
@@ -530,6 +546,8 @@ extern "C" {
// cg_tempmodels.cpp
//
extern cvar_t *cg_showtempmodels;
extern cvar_t *cg_max_tempmodels;
extern cvar_t *cg_reserve_tempmodels;
extern cvar_t *cg_detail;
extern cvar_t *cg_effectdetail;
extern cvar_t *cg_effect_physicsrate;
@@ -911,6 +929,9 @@ qboolean CG_LightStyleColor(int style, int realtime, vec4_t color, qboolean clam
//
// cg_volumetricsmoke.cpp
void CG_ResetVSSSources(void);
#ifdef __cplusplus
void CG_ArchiveVSSGlobals(MemArchiver& archiver);
#endif
void CG_AddVSSSources(void);
extern cvar_t *vss_draw;
+198 -122
View File
@@ -80,6 +80,9 @@ cvar_t *cg_acidtrip;
cvar_t *cg_hud;
cvar_t *cg_huddraw_force;
cvar_t *cg_drawsvlag;
cvar_t *cg_crosshair;
cvar_t *cg_crosshair_friend;
cvar_t *ui_crosshair;
cvar_t *vm_offset_max;
cvar_t *vm_offset_speed;
cvar_t *vm_sway_front;
@@ -159,6 +162,15 @@ void CG_RegisterCvars(void)
cg_hud = cgi.Cvar_Get("cg_hud", "0", 0);
cg_huddraw_force = cgi.Cvar_Get("cg_huddraw_force", "0", CVAR_SAVEGAME);
cg_drawsvlag = cgi.Cvar_Get("cg_drawsvlag", "1", CVAR_ARCHIVE);
cg_crosshair = cgi.Cvar_Get("cg_crosshair", "textures/hud/crosshair", CVAR_ARCHIVE);
if (cg_protocol >= PROTOCOL_MOHTA_MIN) {
cg_crosshair_friend = cgi.Cvar_Get("cg_crosshair_friend", "textures/hud/crosshair_friend", CVAR_ARCHIVE);
} else {
// on 1.11 and below, fallback to standard crosshair
// as it doesn't have crosshair_friend texture
cg_crosshair_friend = cgi.Cvar_Get("cg_crosshair_friend", "textures/hud/crosshair", CVAR_ARCHIVE);
}
ui_crosshair = cgi.Cvar_Get("ui_crosshair", "1", CVAR_ARCHIVE);
vm_offset_max = cgi.Cvar_Get("vm_offset_max", "8.0", 0);
vm_offset_speed = cgi.Cvar_Get("vm_offset_speed", "8.0", 0);
vm_sway_front = cgi.Cvar_Get("vm_sway_front", "0.1", 0);
@@ -233,91 +245,48 @@ void CG_RegisterSounds(void)
Com_Printf("-------------UBERDIALOG DONE---------------\n\n");
}
/*
================
CG_IsHandleUnique
Check if the model handle is unique
================
*/
static qboolean CG_IsHandleUnique(int num) {
qhandle_t handle;
int i;
int numRef;
numRef = 0;
handle = cgs.model_draw[num];
for (i = 0; i < MAX_MODELS; i++) {
if (cgs.model_draw[i] == handle) {
numRef++;
if (numRef >= 2) {
return qfalse;
}
}
}
return qtrue;
}
/*
================
CG_ProcessConfigString
================
*/
void CG_ProcessConfigString(int num)
void CG_ProcessConfigString(int num, qboolean modelOnly)
{
const char *str = CG_ConfigString(num);
int i;
const char* str;
int i;
switch (num) {
case CS_RAIN_DENSITY:
cg.rain.density = atof(str);
return;
case CS_RAIN_SPEED:
cg.rain.speed = atof(str);
return;
case CS_RAIN_SPEEDVARY:
cg.rain.speed_vary = atoi(str);
return;
case CS_RAIN_SLANT:
cg.rain.slant = atoi(str);
return;
case CS_RAIN_LENGTH:
cg.rain.length = atof(str);
return;
case CS_RAIN_MINDIST:
cg.rain.min_dist = atof(str);
return;
case CS_RAIN_WIDTH:
cg.rain.width = atof(str);
return;
case CS_RAIN_SHADER:
if (cg.rain.numshaders) {
for (i = 0; i < cg.rain.numshaders; i++) {
sprintf(cg.rain.shader[i], "%s%i", str, i);
}
} else {
strcpy(cg.rain.shader[0], str);
}
return;
case CS_RAIN_NUMSHADERS:
cg.rain.numshaders = atoi(str);
if (cg.rain.numshaders) {
for (i = 0; i < cg.rain.numshaders; i++) {
sprintf(cg.rain.shader[i], "%s%i", str, i);
}
}
return;
}
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"));
}
switch (num) {
case CS_MUSIC:
cgi.MUSIC_NewSoundtrack(str);
return;
case CS_WARMUP:
cg.matchStartTime = atoi(str);
return;
case CS_FOGINFO:
CG_ParseFogInfo(str);
return;
case CS_SKYINFO:
sscanf(str, "%f %d", &cg.sky_alpha, &cg.sky_portal);
return;
case CS_SERVERINFO:
CG_ParseServerinfo();
return;
case CS_LEVEL_START_TIME:
cgs.levelStartTime = atoi(str);
return;
case CS_MATCHEND:
cgs.matchEndTime = atoi(str);
return;
}
str = CG_ConfigString(num);
if (num >= CS_MODELS && num < CS_MODELS + MAX_MODELS) {
qhandle_t hOldModel = cgs.model_draw[num - CS_MODELS];
if (str && str[0]) {
if (str && str[0] && !modelOnly) {
qhandle_t hModel = cgi.R_RegisterServerModel(str);
dtiki_t *tiki;
@@ -334,43 +303,142 @@ void CG_ProcessConfigString(int num)
}
} else {
// clear out the model
if (hOldModel) {
if (hOldModel && CG_IsHandleUnique(hOldModel)) {
// Handle uniqueness added in OPM
cgi.R_UnregisterServerModel(hOldModel);
}
cgs.model_draw[num - CS_MODELS] = 0;
}
} else if (num >= CS_SOUNDS && num < CS_SOUNDS + MAX_SOUNDS) {
size_t len = strlen(str);
if (len) {
qboolean streamed;
char buf[1024];
strcpy(buf, str);
}
streamed = buf[len - 1] != '0';
buf[len - 1] = 0;
if (buf[0] != '*') {
cgs.sound_precache[num - CS_SOUNDS] = cgi.S_RegisterSound(buf, streamed);
if (!modelOnly) {
switch (num) {
case CS_RAIN_DENSITY:
cg.rain.density = atof(str);
return;
case CS_RAIN_SPEED:
cg.rain.speed = atof(str);
return;
case CS_RAIN_SPEEDVARY:
cg.rain.speed_vary = atoi(str);
return;
case CS_RAIN_SLANT:
cg.rain.slant = atoi(str);
return;
case CS_RAIN_LENGTH:
cg.rain.length = atof(str);
return;
case CS_RAIN_MINDIST:
cg.rain.min_dist = atof(str);
return;
case CS_RAIN_WIDTH:
cg.rain.width = atof(str);
return;
case CS_RAIN_SHADER:
if (cg.rain.numshaders) {
for (i = 0; i < cg.rain.numshaders; i++) {
sprintf(cg.rain.shader[i], "%s%i", str, i);
}
} else {
strcpy(cg.rain.shader[0], str);
}
}
} else if (num >= CS_LIGHTSTYLES && num < CS_LIGHTSTYLES + MAX_LIGHTSTYLES) {
CG_SetLightStyle(num - CS_LIGHTSTYLES, str);
} else if (num >= CS_PLAYERS && num < CS_PLAYERS + MAX_CLIENTS) {
const char *value;
value = Info_ValueForKey(str, "name");
if (value) {
strncpy(cg.clientinfo[num - CS_PLAYERS].name, value, sizeof(cg.clientinfo[num - CS_PLAYERS].name));
} else {
strncpy(
cg.clientinfo[num - CS_PLAYERS].name, "UnnamedSoldier", sizeof(cg.clientinfo[num - CS_PLAYERS].name)
);
return;
case CS_RAIN_NUMSHADERS:
cg.rain.numshaders = atoi(str);
if (cg.rain.numshaders) {
for (i = 0; i < cg.rain.numshaders; i++) {
sprintf(cg.rain.shader[i], "%s%i", str, i);
}
}
return;
}
value = Info_ValueForKey(str, "team");
if (value) {
cg.clientinfo[num - CS_PLAYERS].team = atoi(value);
} else {
cg.clientinfo[num - CS_PLAYERS].team = TEAM_NONE;
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"));
}
switch (num) {
case CS_MUSIC:
cgi.MUSIC_NewSoundtrack(str);
return;
case CS_WARMUP:
cg.matchStartTime = atoi(str);
return;
case CS_FOGINFO:
cg.farclipOverride = 0;
cg.farplaneColorOverride[0] = -1;
cg.farplaneColorOverride[1] = -1;
cg.farplaneColorOverride[2] = -1;
CG_ParseFogInfo(str);
return;
case CS_SKYINFO:
sscanf(str, "%f %d", &cg.sky_alpha, &cg.sky_portal);
return;
case CS_SERVERINFO:
CG_ParseServerinfo();
return;
case CS_LEVEL_START_TIME:
cgs.levelStartTime = atoi(str);
return;
case CS_VOTE_TIME:
cgs.voteTime = atoi(str);
cgs.voteRefreshed = qtrue;
break;
case CS_VOTE_STRING:
Q_strncpyz(cgs.voteString, str, sizeof(cgs.voteString));
break;
case CS_VOTE_YES:
cgs.numVotesYes = atoi(str);
cgs.voteRefreshed = qtrue;
break;
case CS_VOTE_NO:
cgs.numVotesNo = atoi(str);
cgs.voteRefreshed = qtrue;
break;
case CS_VOTE_UNDECIDED:
cgs.numUndecidedVotes = atoi(str);
cgs.voteRefreshed = qtrue;
break;
case CS_MATCHEND:
cgs.matchEndTime = atoi(str);
return;
}
if (num >= CS_SOUNDS && num < CS_SOUNDS + MAX_SOUNDS) {
size_t len = strlen(str);
if (len) {
qboolean streamed;
char buf[1024];
strcpy(buf, str);
streamed = buf[len - 1] != '0';
buf[len - 1] = 0;
if (buf[0] != '*') {
cgs.sound_precache[num - CS_SOUNDS] = cgi.S_RegisterSound(buf, streamed);
}
}
} else if (num >= CS_LIGHTSTYLES && num < CS_LIGHTSTYLES + MAX_LIGHTSTYLES) {
CG_SetLightStyle(num - CS_LIGHTSTYLES, str);
} else if (num >= CS_PLAYERS && num < CS_PLAYERS + MAX_CLIENTS) {
const char *value;
value = Info_ValueForKey(str, "name");
if (value) {
strncpy(cg.clientinfo[num - CS_PLAYERS].name, value, sizeof(cg.clientinfo[num - CS_PLAYERS].name));
} else {
strncpy(
cg.clientinfo[num - CS_PLAYERS].name, "UnnamedSoldier", sizeof(cg.clientinfo[num - CS_PLAYERS].name)
);
}
value = Info_ValueForKey(str, "team");
if (value) {
cg.clientinfo[num - CS_PLAYERS].team = atoi(value);
} else {
cg.clientinfo[num - CS_PLAYERS].team = TEAM_NONE;
}
}
}
}
@@ -423,14 +491,14 @@ void CG_PrepRefresh(void)
cgs.media.binocularsOverlayShader = cgi.R_RegisterShaderNoMip("textures/hud/binocularsoverlay");
cgs.media.hudDrawFont = cgi.R_LoadFont("verdana-14");
cgs.media.attackerFont = cgi.R_LoadFont("facfont-20");
cgs.media.objectiveFont = cgi.R_LoadFont("courier-16");
cgs.media.objectiveFont = cgi.R_LoadFont("facfont-20"); // was courier-16 before 2.0
cgs.media.objectivesBackShader = cgi.R_RegisterShaderNoMip("textures/hud/objectives_backdrop");
cgs.media.checkedBoxShader = cgi.R_RegisterShaderNoMip("textures/objectives/filledbox");
cgs.media.uncheckedBoxShader = cgi.R_RegisterShaderNoMip("textures/objectives/emptybox");
// go through all the configstrings and process them
for (i = CS_SYSTEMINFO + 1; i < MAX_CONFIGSTRINGS; i++) {
CG_ProcessConfigString(i);
CG_ProcessConfigString(i, qfalse);
}
}
@@ -469,6 +537,7 @@ Displays the info screen while loading media
void CG_GameStateReceived(void)
{
const char *s;
int checksum;
// clear everything
memset(&cg, 0, sizeof(cg));
@@ -495,7 +564,10 @@ void CG_GameStateReceived(void)
CG_ParseServerinfo();
// load the new map
cgi.CM_LoadMap(cgs.mapname);
cgi.CM_LoadMap(cgs.mapname, &checksum);
if (cgs.useMapChecksum && checksum != cgs.mapChecksum && cgs.gametype != GT_SINGLE_PLAYER) {
cgi.Error(ERR_DROP, "Client/Server map checksum mismatch: %x/%x", checksum, cgs.mapChecksum);
}
CG_InitMarks();
@@ -539,16 +611,6 @@ void CG_ServerRestarted(void)
CG_InitializeObjectives();
}
void *CG_Malloc(int size)
{
return malloc(size);
}
void CG_Free(void *ptr)
{
free(ptr);
}
/*
=================
CG_Init
@@ -559,10 +621,6 @@ Called after every level change or subsystem restart
void CG_Init(clientGameImport_t *imported, int serverMessageNum, int serverCommandSequence, int clientNum)
{
cgi = *imported;
#if _DEBUG
cgi.Malloc = &CG_Malloc;
cgi.Free = &CG_Free;
#endif
cg_protocol = cgi.Cvar_Get("com_protocol", "", 0)->integer;
CG_InitCGMessageAPI(&cge);
@@ -570,6 +628,11 @@ void CG_Init(clientGameImport_t *imported, int serverMessageNum, int serverComma
memset(&cg, 0, sizeof(cg));
memset(&cgs, 0, sizeof(cgs));
// clear fog values
cg.farclipOverride = 0;
cg.farplaneColorOverride[0] = -1;
cg.farplaneColorOverride[1] = -1;
cg.farplaneColorOverride[2] = -1;
cg.clientNum = clientNum;
cgs.processedSnapshotNum = serverMessageNum;
@@ -626,11 +689,14 @@ Called before every level change or subsystem restart
void CG_Shutdown(void)
{
L_ShutdownEvents();
// Shutdown radar
cgi.CL_InitRadar(NULL, NULL, -1);
// some mods may need to do cleanup work here,
// like closing files or archiving session data
// hide the stats screen
cgi.UI_HideMenu("StatsScreen", 1);
cgi.UI_HideMenu("StatsScreen", qtrue);
// reset the scoreboard
CG_PrepScoreBoardInfo();
@@ -788,10 +854,20 @@ void CG_ParseFogInfo_ver_15(const char *str)
void CG_ParseFogInfo_ver_6(const char *str)
{
cg.farclipOverride = 0.0;
//
// clear all unsupported fields in protocol below version 15
//
// don't set the farplane_bias 0, otherwise the renderer will set a minimum value
cg.farplane_bias = 0.001f;
cg.skyboxFarplane = 0;
cg.skyboxSpeed = 0;
cg.renderTerrain = qtrue;
cg.farclipOverride = -1.0;
cg.farplaneColorOverride[0] = -1.0;
cg.farplaneColorOverride[1] = -1.0;
cg.farplaneColorOverride[2] = -1.0;
sscanf(
str,
"%d %f %f %f %f",
+2 -2
View File
@@ -685,9 +685,9 @@ void CG_ImpactMark(
// create the full polygon
for (i = 0; i < 3; i++) {
originalPoints[0][i] = origin[i] - fSScale2 * info.axis[1][i] - fTScale2 * info.axis[2][i];
originalPoints[1][i] = origin[i] + fSScale3 * info.axis[1][i] - fTScale3 * info.axis[2][i];
originalPoints[1][i] = origin[i] + fSScale3 * info.axis[1][i] - fTScale2 * info.axis[2][i];
originalPoints[2][i] = origin[i] + fSScale3 * info.axis[1][i] + fTScale3 * info.axis[2][i];
originalPoints[3][i] = origin[i] - fSScale2 * info.axis[1][i] + fTScale2 * info.axis[2][i];
originalPoints[3][i] = origin[i] - fSScale2 * info.axis[1][i] + fTScale3 * info.axis[2][i];
}
// get the fragments
+286 -20
View File
@@ -180,6 +180,226 @@ void CG_PlayerTeamIcon(refEntity_t *pModel, entityState_t *pPlayerState)
}
}
/*
===============
CG_CastFootShadow
Cast complex foot shadow using lights
===============
*/
void CG_CastFootShadow(const vec_t* vLightPos, vec_t* vLightIntensity, int iTag, refEntity_t* model)
{
int i;
float fAlpha;
float fLength;
float fWidth;
float fAlphaOfs;
float fOfs;
float fPitchCos;
vec3_t vPos;
vec3_t vEnd;
vec3_t vDelta;
vec3_t vLightAngles;
trace_t trace;
orientation_t oFoot;
VectorCopy(model->origin, vPos);
oFoot = cgi.TIKI_Orientation(model, iTag);
VectorMA(oFoot.origin, 2, oFoot.axis[1], vEnd);
for (i = 0; i < 3; i++) {
VectorMA(vPos, vEnd[i], model->axis[i], vPos);
}
if (cg_shadowdebug->integer)
{
vec3_t vDir;
//
// show debug lines
//
memset(vDir, 0, sizeof(vDir));
for (i = 0; i < 3; ++i) {
VectorMA(vDir, oFoot.axis[0][i], model->axis[i], vDir);
}
VectorMA(vPos, 32.0, vDir, vEnd);
cgi.R_DebugLine(vPos, vEnd, 1.0, 0.0, 0.0, 1.0);
memset(vDir, 0, sizeof(vDir));
for (i = 0; i < 3; ++i) {
VectorMA(vDir, oFoot.axis[1][i], model->axis[i], vDir);
}
VectorMA(vPos, 32.0, vDir, vEnd);
cgi.R_DebugLine(vPos, vEnd, 0.0, 1.0, 0.0, 1.0);
memset(vDir, 0, sizeof(vDir));
for (i = 0; i < 3; ++i) {
VectorMA(vDir, oFoot.axis[2][i], model->axis[i], vDir);
}
VectorMA(vPos, 32.0, vDir, vEnd);
cgi.R_DebugLine(vPos, vEnd, 0.0, 0.0, 1.0, 1.0);
}
// calculate the direction
VectorSubtract(vLightPos, vPos, vDelta);
VectorNormalizeFast(vDelta);
vectoangles(vDelta, vLightAngles);
// normalize to 180 degrees
if (vLightAngles[0] > 180) {
vLightAngles[0] -= 360;
}
if (vLightAngles[0] > -5.7319679) {
// FIXME: what is -5.7319679?
return;
}
fPitchCos = cos(DEG2RAD(vLightAngles[0]));
if (fPitchCos > 0.955) {
fAlpha = 1.0 - (fPitchCos - 0.955) * 25;
} else {
fAlpha = 1.0;
}
fLength = fPitchCos * fPitchCos * 32.0 + fPitchCos * 8.0 + 10.0;
fOfs = 0.5 - (-4.1 / tan(DEG2RAD(vLightAngles[0])) + 4.0 - fLength) / fLength * 0.5;
VectorMA(vPos, -96.0, vDelta, vEnd);
CG_Trace(&trace, vPos, vec3_origin, vec3_origin, vEnd, 0, MASK_FOOTSHADOW, qfalse, qtrue, "CG_CastFootShadow");
if (cg_shadowdebug->integer)
{
cgi.R_DebugLine(vPos, vLightPos, 0.75, 0.75, 0.5, 1.0);
cgi.R_DebugLine(vPos, vEnd, 1.0, 1.0, 1.0, 1.0);
}
if (trace.fraction == 1.0) {
return;
}
trace.fraction -= 0.0427f;
if (trace.fraction < 0) {
trace.fraction = 0;
}
fWidth = 10.f - (1.f - trace.fraction) * 6.f;
fAlphaOfs = (1.f - trace.fraction) * fAlpha;
fAlpha = Q_max(vLightIntensity[0], Q_max(vLightIntensity[1], vLightIntensity[2]));
if (fAlpha < 0.1) {
vLightIntensity[0] *= 0.1 / fAlpha * fAlphaOfs;
vLightIntensity[1] *= 0.1 / fAlpha * fAlphaOfs;
vLightIntensity[2] *= 0.1 / fAlpha * fAlphaOfs;
} else {
vLightIntensity[0] *= fAlphaOfs;
vLightIntensity[1] *= fAlphaOfs;
vLightIntensity[2] *= fAlphaOfs;
}
fAlpha = Q_max(vLightIntensity[0], Q_max(vLightIntensity[1], vLightIntensity[2]));
if (fAlpha > 0.6) {
vLightIntensity[0] *= 0.6 / fAlpha;
vLightIntensity[1] *= 0.6 / fAlpha;
vLightIntensity[2] *= 0.6 / fAlpha;
}
if (vLightIntensity[0] <= 0.01 && vLightIntensity[1] <= 0.01 && vLightIntensity[2] <= 0.01) {
return;
}
CG_ImpactMark(
cgs.media.footShadowMarkShader,
trace.endpos,
trace.plane.normal,
vLightAngles[1],
fWidth,
fLength,
vLightIntensity[0],
vLightIntensity[1],
vLightIntensity[2],
1.0,
qfalse,
qtrue,
qfalse,
qfalse,
0.5,
fOfs
);
}
/*
===============
CG_CastSimpleFeetShadow
Cast basic feet shadow
===============
*/
void CG_CastSimpleFeetShadow(const trace_t* pTrace, float fWidth, float fAlpha, int iRightTag, int iLeftTag, const dtiki_t* tiki, refEntity_t* model)
{
int i;
float fShadowYaw;
float fLength;
vec3_t vPos, vRightPos, vLeftPos;
vec3_t vDelta;
orientation_t oFoot;
//
// right foot
//
VectorCopy(pTrace->endpos, vRightPos);
oFoot = cgi.TIKI_Orientation(model, iRightTag);
VectorMA(oFoot.origin, 3, oFoot.axis[1], vPos);
for (i = 0; i < 3; i++) {
VectorMA(vRightPos, vPos[i], model->axis[i], vRightPos);
}
VectorMA(vRightPos, -2, oFoot.axis[1], vRightPos);
//
// left foot
//
VectorCopy(pTrace->endpos, vLeftPos);
oFoot = cgi.TIKI_Orientation(model, iLeftTag);
VectorMA(oFoot.origin, 3, oFoot.axis[1], vPos);
for (i = 0; i < 3; i++) {
VectorMA(vLeftPos, vPos[i], model->axis[i], vLeftPos);
}
VectorAdd(vRightPos, vLeftPos, vPos);
VectorScale(vPos, 0.5, vPos);
VectorSubtract(vRightPos, vLeftPos, vDelta);
VectorMA(vLeftPos, 0.5, vDelta, vPos);
// get the facing yaw
fShadowYaw = vectoyaw(vDelta);
fLength = VectorNormalize(vDelta) * 0.5 + 12;
if (fLength < fWidth * 0.7) {
fLength = fWidth * 0.7;
}
// add the mark
CG_ImpactMark(
cgs.media.shadowMarkShader,
vPos,
pTrace->plane.normal,
fShadowYaw,
fWidth * 0.7,
fLength,
fAlpha,
fAlpha,
fAlpha,
1.0,
qfalse,
qtrue,
qfalse,
qfalse,
0.5,
0.5
);
}
/*
===============
CG_EntityShadow
@@ -193,9 +413,15 @@ Returns the Z component of the surface being shadowed
qboolean CG_EntityShadow(centity_t *cent, refEntity_t *model)
{
int iTagL, iTagR;
float alpha;
float fWidth;
vec3_t end;
vec3_t vMins, vMaxs;
vec3_t vSize;
trace_t trace;
float alpha, radius;
iTagR = -1;
if (cg_shadows->integer == 0) {
return qfalse;
@@ -206,10 +432,31 @@ qboolean CG_EntityShadow(centity_t *cent, refEntity_t *model)
return qfalse;
}
// no shadows when invisible
// if ( cent->currentState.powerups & ( 1 << PW_INVIS ) ) {
// return qfalse;
// }
if (cg_shadows->integer == 2 && (model->renderfx & RF_SHADOW_PRECISE)) {
iTagL = cgi.Tag_NumForName(model->tiki, "Bip01 L Foot");
if (iTagL != -1) {
iTagR = cgi.Tag_NumForName(model->tiki, "Bip01 R Foot");
}
if (iTagR != -1) {
int iNumLights, iCurrLight;
vec3_t avLightPos[16], avLightIntensity[16];
iNumLights = Q_clamp(cg_shadowscount->integer, 1, 8);
iNumLights = cgi.R_GatherLightSources(model->origin, avLightPos, avLightIntensity, iNumLights);
if (iNumLights)
{
for (iCurrLight = 0; iCurrLight < iNumLights; iCurrLight++)
{
CG_CastFootShadow(avLightPos[iCurrLight], avLightIntensity[iCurrLight], iTagL, model);
CG_CastFootShadow(avLightPos[iCurrLight], avLightIntensity[iCurrLight], iTagR, model);
}
// shadow was casted properly
return qtrue;
}
}
}
// send a trace down from the player to the ground
VectorCopy(model->origin, end);
@@ -222,29 +469,46 @@ qboolean CG_EntityShadow(centity_t *cent, refEntity_t *model)
return qfalse;
}
if ((cg_shadows->integer == 2) && (model->renderfx & RF_SHADOW_PRECISE)) {
// since 2.0: no shadow if solid
if (trace.startsolid || trace.allsolid) {
return qfalse;
}
if ((cg_shadows->integer == 3) && (model->renderfx & RF_SHADOW_PRECISE)) {
return qtrue;
}
//
// get the bounds of the current frame
//
radius = model->scale * cgi.R_ModelRadius(model->hModel);
if (radius < 1) {
fWidth = model->scale * cgi.R_ModelRadius(model->hModel);
if (fWidth < 1) {
return qfalse;
}
// fade the shadow out with height
alpha = (1.0 - trace.fraction) * 0.8f;
alpha = (1.0 - trace.fraction) * 0.65f;
if ((cg_shadows->integer == 3) && (model->renderfx & RF_SHADOW_PRECISE)) {
if (model->shaderRGBA[3] == 255) {
model->shaderRGBA[3] = alpha * 255;
if (model->renderfx & RF_SHADOW_PRECISE) {
iTagL = cgi.Tag_NumForName(model->tiki, "Bip01 L Foot");
if (iTagL != -1) {
iTagR = cgi.Tag_NumForName(model->tiki, "Bip01 R Foot");
}
if (iTagR != -1) {
if (cg_shadows->integer == 2) {
alpha *= 0.6f;
}
CG_CastSimpleFeetShadow(&trace, fWidth, alpha, iTagR, iTagL, model->tiki, model);
return qtrue;
}
return qtrue;
}
cgi.R_ModelBounds(model->hModel, vMins, vMaxs);
VectorSubtract(vMaxs, vMins, vSize);
VectorScale(vSize, 0.6f, vSize);
// add the mark as a temporary, so it goes directly to the renderer
// without taking a spot in the cg_marks array
CG_ImpactMark(
@@ -252,15 +516,15 @@ qboolean CG_EntityShadow(centity_t *cent, refEntity_t *model)
trace.endpos,
trace.plane.normal,
cent->lerpAngles[YAW],
radius,
radius,
vSize[1],
vSize[0],
alpha,
alpha,
alpha,
1,
qfalse,
qtrue,
qtrue,
qfalse,
qfalse,
0.5f,
0.5f
@@ -316,10 +580,12 @@ void CG_AttachEntity(
orientation_t or ;
vec3_t tempAxis[3];
vec3_t vOrigin;
vec3_t vDeltaLightOrg;
or = cgi.TIKI_Orientation(parent, tagnum);
//cgi.Printf( "th = %d %.2f %.2f %.2f\n", tikihandle, or.origin[ 0 ], or.origin[ 1 ], or.origin[ 2 ] );
VectorSubtract(entity->lightingOrigin, entity->origin, vDeltaLightOrg);
VectorCopy(parent->origin, entity->origin);
for (i = 0; i < 3; i++) {
@@ -337,14 +603,14 @@ void CG_AttachEntity(
VectorCopy(entity->origin, entity->oldorigin);
if (use_angles) {
MatrixMultiply(entity->axis, parent->axis, tempAxis);
MatrixMultiply(or.axis, tempAxis, entity->axis);
MatrixMultiply(entity->axis, or.axis, tempAxis);
MatrixMultiply(tempAxis, parent->axis, entity->axis);
}
entity->scale *= parent->scale;
entity->renderfx |= (parent->renderfx & ~(RF_FLAGS_NOT_INHERITED | RF_LIGHTING_ORIGIN));
MatrixTransformVectorRight(entity->axis, entity->lightingOrigin, vOrigin);
MatrixTransformVectorRight(entity->axis, vDeltaLightOrg, vOrigin);
VectorAdd(entity->origin, vOrigin, entity->lightingOrigin);
}
+183 -224
View File
@@ -37,6 +37,7 @@ typedef struct {
vec3_t *i_vEnd;
int i_iNumBullets;
qboolean iLarge;
float alpha;
int iTracerVisible;
qboolean bIgnoreEntities;
} bullet_tracer_t;
@@ -60,21 +61,22 @@ static vec3_t flesh_impact_pos[MAX_IMPACTS];
static vec3_t flesh_impact_norm[MAX_IMPACTS];
static int flesh_impact_large[MAX_IMPACTS];
void CG_MakeBulletHoleSound(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, trace_t* pPreTrace) {
int iSurfType;
float fVolume;
str sSoundName;
vec3_t vFrom, vDest;
void CG_MakeBulletHoleSound(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, trace_t *pPreTrace)
{
int iSurfType;
float fVolume;
str sSoundName;
vec3_t vFrom, vDest;
trace_t trace;
if (pPreTrace) {
trace = *pPreTrace;
}
else {
} else {
VectorMA(i_vPos, 2.0f, i_vNorm, vFrom);
VectorMA(i_vPos, -4.0f, i_vNorm, vDest);
CG_Trace(&trace, vFrom, vec_zero, vec_zero, vDest, ENTITYNUM_NONE, MASK_SHOT, qfalse, qtrue, "CG_MakeBulletHole");
CG_Trace(
&trace, vFrom, vec_zero, vec_zero, vDest, ENTITYNUM_NONE, MASK_SHOT, qfalse, qtrue, "CG_MakeBulletHole"
);
}
iSurfType = trace.surfaceFlags & MASK_SURF_TYPE;
@@ -149,9 +151,12 @@ void CG_MakeBulletHoleSound(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarg
commandManager.PlaySound(sSoundName, vFrom, -1, fVolume, -1.f, -1.f, 1);
}
static void CG_MakeBulletHoleType(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, int iEffectNum, float fRadius, qboolean bMakeSound) {
static void CG_MakeBulletHoleType(
const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, int iEffectNum, float fRadius, qboolean bMakeSound
)
{
if (bMakeSound) {
str sBulletHole = "snd_bh_";
str sBulletHole = "snd_bh_";
float fVolume;
switch (iEffectNum) {
@@ -221,14 +226,15 @@ static void CG_MakeBulletHoleType(const vec3_t i_vPos, const vec3_t i_vNorm, int
sfxManager.MakeEffect_Normal(iEffectNum, i_vPos, i_vNorm);
}
static void CG_MakeBulletHole(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, trace_t *pPreTrace, qboolean bMakeSound)
static void
CG_MakeBulletHole(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, trace_t *pPreTrace, qboolean bMakeSound)
{
int iSurfType;
int iEffect;
float fRadius;
str sEffectModel;
str sBulletHole;
vec3_t vFrom, vDest;
int iSurfType;
int iEffect;
float fRadius;
str sEffectModel;
str sBulletHole;
vec3_t vFrom, vDest;
trace_t trace;
if (pPreTrace) {
@@ -236,7 +242,9 @@ static void CG_MakeBulletHole(const vec3_t i_vPos, const vec3_t i_vNorm, int iLa
} else {
VectorMA(i_vPos, 2.0f, i_vNorm, vFrom);
VectorMA(i_vPos, -4.0f, i_vNorm, vDest);
CG_Trace(&trace, vFrom, vec_zero, vec_zero, vDest, ENTITYNUM_NONE, MASK_SHOT, qfalse, qtrue, "CG_MakeBulletHole");
CG_Trace(
&trace, vFrom, vec_zero, vec_zero, vDest, ENTITYNUM_NONE, MASK_SHOT, qfalse, qtrue, "CG_MakeBulletHole"
);
}
iSurfType = trace.surfaceFlags & MASK_SURF_TYPE;
@@ -249,7 +257,7 @@ static void CG_MakeBulletHole(const vec3_t i_vPos, const vec3_t i_vNorm, int iLa
}
VectorAdd(trace.endpos, trace.plane.normal, vFrom);
fRadius = 2.0f;
fRadius = 2.0f;
sBulletHole = "bhole_";
switch (iSurfType) {
@@ -347,36 +355,48 @@ static void CG_MakeBubbleTrail(const vec3_t i_vStart, const vec3_t i_vEnd, int i
{
vec3_t vDir;
vec3_t vPos;
float fDist;
float fMove;
float fDist;
float fMove;
VectorSubtract(i_vEnd, i_vStart, vDir);
fDist = VectorNormalize(vDir);
VectorCopy(i_vStart, vPos);
fMove = random() * 8.f;
fMove = random() * 8.f * alpha;
fDist -= fMove;
while (fDist > 0.f) {
VectorMA(vPos, fMove, vDir, vPos);
sfxManager.MakeEffect_Angles(32, vPos, vec_zero);
fMove = 16.f + crandom() * 8.f;
fMove = 16.f + crandom() * 8.f * alpha;
fDist -= fMove;
}
}
static void CG_BulletTracerEffect(const vec3_t i_vStart, const vec3_t i_vEnd)
static void CG_BulletTracerEffect(const vec3_t i_vStart, const vec3_t i_vEnd, int iLarge, float alpha)
{
int iLife;
int iTracerLength;
float fLength, fDist;
int iLife;
int iTracerLength;
float fLength, fDist;
vec4_t fTracerColor;
vec3_t vDir, vNewStart;
float alphaMult;
float scale;
iTracerLength = 450.0f + random() * 150.f;
VectorSubtract(i_vEnd, i_vStart, vDir);
fLength = VectorNormalize(vDir);
if (iLarge > 1) {
alphaMult = random() * 0.2f + 0.9f;
scale = iLarge * 2;
} else {
alphaMult = 1;
scale = 1;
}
fDist = 450.0f + random() * 150.f;
if (fLength < fDist + 150.f) {
float fFrac;
@@ -384,13 +404,15 @@ static void CG_BulletTracerEffect(const vec3_t i_vStart, const vec3_t i_vEnd)
return;
}
fFrac = fLength / (fDist + 150.0);
fFrac = fLength / (fDist + 150.0);
iTracerLength = (int)((float)iTracerLength * fFrac + 0.5f);
fDist *= fFrac;
}
iLife = (int)((fLength - fDist) / 12000.f * 1000.f);
if (iLife < 20) iLife = 20;
iLife = (int)((fLength - fDist) / 12000.f * 1000.f / (alpha * alphaMult));
if (iLife < 20) {
iLife = 20;
}
VectorMA(i_vStart, fDist, vDir, vNewStart);
fTracerColor[0] = 1.f;
@@ -427,53 +449,54 @@ static void CG_BulletTracerEffect(const vec3_t i_vStart, const vec3_t i_vEnd)
}
static void CG_MakeBulletTracerInternal(
const vec3_t i_vBarrel,
const vec3_t i_vStart,
const vec3_t *i_vEnd,
int i_iNumBullets,
qboolean iLarge,
int iTracerVisible,
qboolean bIgnoreEntities
const vec3_t i_vBarrel,
const vec3_t i_vStart,
const vec3_t *i_vEnd,
int i_iNumBullets,
qboolean iLarge,
int iTracerVisible,
qboolean bIgnoreEntities,
float alpha
)
{
vec3_t vPos;
int iBullet;
int iContinueCount;
int iDist;
int iHeadDist;
int iTravelDist;
float fLen, fDist;
trace_t trace;
qboolean bStartInWater, bInWater;
qboolean bBulletDone;
qboolean bMadeTracer;
vec3_t vDir;
vec3_t vTrailStart;
vec3_t vTraceStart;
vec3_t vTraceEnd;
vec3_t vTmp;
int iNumImpacts;
trace_t tImpacts[128];
float fImpSndDistRA;
vec3_t vPos;
int iBullet;
int iContinueCount;
int iDist;
int iHeadDist;
int iTravelDist;
float fLen, fDist;
trace_t trace;
qboolean bStartInWater, bInWater;
qboolean bBulletDone;
qboolean bMadeTracer;
vec3_t vDir;
vec3_t vTrailStart;
vec3_t vTraceStart;
vec3_t vTraceEnd;
vec3_t vTmp;
int iNumImpacts;
trace_t tImpacts[128];
float fImpSndDistRA;
static float fImpSndDistLA;
float fImpSndDistRB;
float fImpSndDistLB;
int iImpSndIndexRA;
int iImpSndIndexRB;
int iImpSndIndexLB;
float fVolume;
float fPitch;
float fZingDistA, fZingDistB, fZingDistC;
vec3_t vZingPosA, vZingPosB, vZingPosC;
float fImpSndDistRB;
float fImpSndDistLB;
int iImpSndIndexRA;
int iImpSndIndexRB;
int iImpSndIndexLB;
float fVolume;
float fPitch;
float fZingDistA, fZingDistB, fZingDistC;
vec3_t vZingPosA, vZingPosB, vZingPosC;
fZingDistB = 9999.0;
fZingDistA = 9999.0;
fZingDistC = 9999.0;
fZingDistB = 9999.0;
fZingDistA = 9999.0;
fZingDistC = 9999.0;
iNumImpacts = 0;
// check to see if it starts in water
bStartInWater = (cgi.CM_PointContents(i_vStart, 0) & CONTENTS_FLUID) != 0;
for (iBullet = 0; iBullet < i_iNumBullets; iBullet++) {
bInWater = bStartInWater;
VectorCopy(i_vBarrel, vTrailStart);
@@ -481,8 +504,8 @@ static void CG_MakeBulletTracerInternal(
fLen = VectorNormalize(vDir);
trace.fraction = 0;
iDist = (int)fLen + 32;
bBulletDone = qfalse;
iDist = (int)fLen + 32;
bBulletDone = qfalse;
iContinueCount = 0;
if (bStartInWater) {
@@ -501,8 +524,7 @@ static void CG_MakeBulletTracerInternal(
if (iDist > BULLET_TRAVEL_DIST) {
iTravelDist += BULLET_TRAVEL_DIST;
iDist -= BULLET_TRAVEL_DIST;
}
else {
} else {
iTravelDist += iDist;
iDist = 0;
}
@@ -513,16 +535,7 @@ static void CG_MakeBulletTracerInternal(
while (trace.fraction < 1) {
if (bIgnoreEntities) {
cgi.CM_BoxTrace(
&trace,
vTraceStart,
vTraceEnd,
vec_zero,
vec_zero,
0,
MASK_SHOT,
qfalse
);
cgi.CM_BoxTrace(&trace, vTraceStart, vTraceEnd, vec_zero, vec_zero, 0, MASK_SHOT, qfalse);
if (trace.fraction == 1.0f) {
trace.entityNum = ENTITYNUM_NONE;
@@ -533,8 +546,7 @@ static void CG_MakeBulletTracerInternal(
if (trace.startsolid) {
trace.entityNum = ENTITYNUM_WORLD;
}
}
else {
} else {
CG_Trace(
&trace,
vTraceStart,
@@ -556,35 +568,29 @@ static void CG_MakeBulletTracerInternal(
VectorNormalizeFast(trace.plane.normal);
}
if (!bInWater && trace.fraction < 1.0f && iNumImpacts <= 127)
{
if (!bInWater && trace.fraction < 1.0f && iNumImpacts <= 127) {
memcpy(&tImpacts[iNumImpacts], &trace, sizeof(trace_t));
iNumImpacts++;
}
if (iTracerVisible && !bMadeTracer)
{
CG_BulletTracerEffect(vTrailStart, trace.endpos);
if (iTracerVisible && !bMadeTracer) {
CG_BulletTracerEffect(vTrailStart, trace.endpos, iLarge, alpha);
bMadeTracer = qtrue;
}
if (trace.fraction < 1.0f) {
if (((trace.surfaceFlags & (SURF_HINT | SURF_NODLIGHT | SURF_SNOW | SURF_FOLIAGE | SURF_DIRT)) || (trace.contents & CONTENTS_WATER))
&& iContinueCount < 5)
{
if (bInWater)
{
if (((trace.surfaceFlags & (SURF_HINT | SURF_NODLIGHT | SURF_SNOW | SURF_FOLIAGE | SURF_DIRT))
|| (trace.contents & CONTENTS_WATER))
&& iContinueCount < 5) {
if (bInWater) {
VectorSubtract(trace.endpos, vDir, vTmp);
if (!(trace.contents & CONTENTS_FLUID)
&& !(trace.surfaceFlags & SURF_PUDDLE)
&& !(cgi.CM_PointContents(vTmp, 0) & CONTENTS_FLUID))
{
CG_MakeBubbleTrail(vTrailStart, trace.endpos, iLarge);
if (!(trace.contents & CONTENTS_FLUID) && !(trace.surfaceFlags & SURF_PUDDLE)
&& !(cgi.CM_PointContents(vTmp, 0) & CONTENTS_FLUID)) {
CG_MakeBubbleTrail(vTrailStart, trace.endpos, iLarge, alpha);
VectorCopy(trace.endpos, vTrailStart);
bInWater = qfalse;
}
}
else if ((trace.contents & CONTENTS_FLUID) || (trace.surfaceFlags & SURF_PUDDLE)) {
} else if ((trace.contents & CONTENTS_FLUID) || (trace.surfaceFlags & SURF_PUDDLE)) {
VectorCopy(trace.endpos, vTrailStart);
bInWater = qtrue;
}
@@ -593,11 +599,9 @@ static void CG_MakeBulletTracerInternal(
VectorAdd(vTraceStart, vTraceStart, trace.endpos);
iContinueCount++;
}
else
{
} else {
trace.fraction = 1.0f;
bBulletDone = qtrue;
bBulletDone = qtrue;
}
}
}
@@ -605,14 +609,14 @@ static void CG_MakeBulletTracerInternal(
}
if (bInWater) {
CG_MakeBubbleTrail(vTraceStart, trace.endpos, iLarge);
CG_MakeBubbleTrail(vTraceStart, trace.endpos, iLarge, alpha);
}
if (iTracerVisible) {
iTracerVisible--;
}
fLen = ProjectPointOnLine(i_vStart, i_vEnd[iBullet], cg.SoundOrg, vPos);
fLen = ProjectPointOnLine(i_vStart, i_vEnd[iBullet], cg.SoundOrg, vPos);
iHeadDist = (int)Distance(vPos, cg.SoundOrg);
if (iHeadDist > 255) {
continue;
@@ -629,7 +633,7 @@ static void CG_MakeBulletTracerInternal(
if (fLen < 0.f) {
VectorCopy(i_vStart, vPos);
} else if(fDist >= fLen) {
} else if (fDist >= fLen) {
VectorCopy(i_vEnd[iBullet], vPos);
}
@@ -652,11 +656,11 @@ static void CG_MakeBulletTracerInternal(
}
if (iNumImpacts > 2) {
fImpSndDistRA = 9999.0f;
fImpSndDistRB = 9999.0f;
fImpSndDistRA = 9999.0f;
fImpSndDistRB = 9999.0f;
iImpSndIndexRA = 0;
iImpSndIndexRB = 0;
fImpSndDistLB = 9999.0f;
fImpSndDistLB = 9999.0f;
iImpSndIndexLB = 0;
for (iBullet = 0; iBullet < iNumImpacts; iBullet++) {
@@ -671,27 +675,23 @@ static void CG_MakeBulletTracerInternal(
VectorSubtract(tImpacts[iImpSndIndexLB].endpos, cg.SoundOrg, vTmp);
iHeadDist = VectorLength(vTmp);
if (DotProduct(vTmp, cg.SoundAxis[1]) <= 0.f)
{
if (DotProduct(vTmp, cg.SoundAxis[1]) <= 0.f) {
if (iHeadDist < 9999.0f || iHeadDist < fImpSndDistLB) {
if (iHeadDist < 9999.0f) {
fImpSndDistRA = iHeadDist;
fImpSndDistLB = 9999.0;
fImpSndDistRA = iHeadDist;
fImpSndDistLB = 9999.0;
iImpSndIndexRA = iBullet;
} else if (iHeadDist < fImpSndDistLB) {
fImpSndDistLB = iHeadDist;
}
}
}
else
{
if (iHeadDist < fImpSndDistRA || iHeadDist < fImpSndDistRB)
{
} else {
if (iHeadDist < fImpSndDistRA || iHeadDist < fImpSndDistRB) {
if (iHeadDist < fImpSndDistRA) {
iImpSndIndexRB = iImpSndIndexRA;
iImpSndIndexRA = iBullet;
} else if (iHeadDist < fImpSndDistRB) {
fImpSndDistRB = iHeadDist;
fImpSndDistRB = iHeadDist;
iImpSndIndexRB = iBullet;
}
}
@@ -720,11 +720,7 @@ static void CG_MakeBulletTracerInternal(
} else {
for (iBullet = 0; iBullet < iNumImpacts; iBullet++) {
CG_MakeBulletHole(
tImpacts[iBullet].endpos,
tImpacts[iBullet].plane.normal,
iNumImpacts,
&tImpacts[iBullet],
qtrue
tImpacts[iBullet].endpos, tImpacts[iBullet].plane.normal, iNumImpacts, &tImpacts[iBullet], qtrue
);
}
}
@@ -732,10 +728,10 @@ static void CG_MakeBulletTracerInternal(
if (fZingDistA < 9999.0f) {
if (iLarge) {
fVolume = 1.0f;
fPitch = 0.8f;
fPitch = 0.8f;
} else {
fVolume = 0.8f;
fPitch = 1.0f;
fPitch = 1.0f;
}
commandManager.PlaySound("snd_b_zing", vZingPosA, -1, fVolume, -1.0f, fPitch, 1);
@@ -774,13 +770,14 @@ static void CG_MakeBulletTracer(
bullet_tracer->i_vEnd = &bullet_tracer_bullets[bullet_tracers_count];
bullet_tracer->i_iNumBullets = i_iNumBullets;
for (i = 0; i < i_iNumBullets; ++i) {
bullet_tracer_bullets[bullet_tracers_count][0] = (*i_vEnd)[i];
bullet_tracer_bullets[bullet_tracers_count][1] = (*i_vEnd)[i + 1];
bullet_tracer_bullets[bullet_tracers_count++][2] = (*i_vEnd)[i + 2];
for (i = 0; i < i_iNumBullets; i++, bullet_tracers_count++) {
bullet_tracer_bullets[bullet_tracers_count][0] = i_vEnd[i][0];
bullet_tracer_bullets[bullet_tracers_count][1] = i_vEnd[i][1];
bullet_tracer_bullets[bullet_tracers_count][2] = i_vEnd[i][2];
}
bullet_tracer->iLarge = iLarge;
bullet_tracer->alpha = alpha;
bullet_tracer->iTracerVisible = iTracerVisible;
bullet_tracer->bIgnoreEntities = bIgnoreEntities;
}
@@ -797,7 +794,8 @@ void CG_AddBulletTracers()
bullet_tracers[i].i_iNumBullets,
bullet_tracers[i].iLarge,
bullet_tracers[i].iTracerVisible,
bullet_tracers[i].bIgnoreEntities
bullet_tracers[i].bIgnoreEntities,
bullet_tracers[i].alpha
);
}
@@ -807,26 +805,24 @@ void CG_AddBulletTracers()
void CG_AddBulletImpacts()
{
int i;
int iHeadDist;
float fVolume;
float fImpSndDistRA;
int i;
int iHeadDist;
float fVolume;
float fImpSndDistRA;
static float fImpSndDistLA = 9999.f;
float fImpSndDistRB;
float fImpSndDistLB;
int iImpSndIndexRA;
int iImpSndIndexRB;
int iImpSndIndexLB;
vec3_t vTmp;
str sSoundName;
float fImpSndDistRB;
float fImpSndDistLB;
int iImpSndIndexRA;
int iImpSndIndexRB;
int iImpSndIndexLB;
vec3_t vTmp;
str sSoundName;
if (wall_impact_count)
{
if (wall_impact_count > 4)
{
fImpSndDistRA = fImpSndDistLA;
fImpSndDistRB = fImpSndDistLA;
fImpSndDistLB = fImpSndDistLA;
if (wall_impact_count) {
if (wall_impact_count > 4) {
fImpSndDistRA = fImpSndDistLA;
fImpSndDistRB = fImpSndDistLA;
fImpSndDistLB = fImpSndDistLA;
iImpSndIndexRA = 0;
iImpSndIndexRB = 0;
iImpSndIndexLB = 0;
@@ -834,33 +830,28 @@ void CG_AddBulletImpacts()
for (i = 0; i < wall_impact_count; i++) {
VectorSubtract(wall_impact_pos[i], cg.SoundOrg, vTmp);
iHeadDist = VectorLength(vTmp);
if (DotProduct(vTmp, cg.SoundAxis[1]) > 0.f)
{
if (iHeadDist < fImpSndDistRA || iHeadDist < fImpSndDistRB)
{
if (DotProduct(vTmp, cg.SoundAxis[1]) > 0.f) {
if (iHeadDist < fImpSndDistRA || iHeadDist < fImpSndDistRB) {
if (iHeadDist < fImpSndDistRA) {
fImpSndDistRB = fImpSndDistRA;
fImpSndDistRA = iHeadDist;
fImpSndDistRB = fImpSndDistRA;
fImpSndDistRA = iHeadDist;
iImpSndIndexRB = iImpSndIndexRA;
iImpSndIndexRA = i;
} else if (iHeadDist < fImpSndDistRB) {
fImpSndDistRB = iHeadDist;
fImpSndDistRB = iHeadDist;
iImpSndIndexRB = i;
}
}
}
else
{
if (iHeadDist < fImpSndDistLA || iHeadDist < fImpSndDistLB)
{
} else {
if (iHeadDist < fImpSndDistLA || iHeadDist < fImpSndDistLB) {
if (iHeadDist < fImpSndDistLA) {
fImpSndDistRA = iHeadDist;
fImpSndDistLB = fImpSndDistLA;
fImpSndDistRA = iHeadDist;
fImpSndDistLB = fImpSndDistLA;
iImpSndIndexLB = 0;
iImpSndIndexRA = i;
} else if (iHeadDist < fImpSndDistLB) {
fImpSndDistLB = iHeadDist;
fImpSndDistLB = iHeadDist;
iImpSndIndexLB = i;
}
}
@@ -908,8 +899,7 @@ void CG_AddBulletImpacts()
if (wall_impact_type[iImpSndIndexRB] == 2 || wall_impact_type[iImpSndIndexRB] == 3) {
sSoundName = "snd_bh_metal";
}
else {
} else {
sSoundName = "snd_bh_wood";
}
@@ -942,26 +932,15 @@ void CG_AddBulletImpacts()
if (wall_impact_type[0] == 2 || wall_impact_type[0] == 3) {
sSoundName = "snd_bh_metal";
}
else {
} else {
sSoundName = "snd_bh_wood";
}
commandManager.PlaySound(sSoundName, wall_impact_pos[0], -1, fVolume, -1, -1, 1);
sfxManager.MakeEffect_Normal(
wall_impact_type[0],
wall_impact_pos[0],
wall_impact_norm[0]
);
sfxManager.MakeEffect_Normal(wall_impact_type[0], wall_impact_pos[0], wall_impact_norm[0]);
} else {
CG_MakeBulletHole(
wall_impact_pos[0],
wall_impact_norm[0],
wall_impact_large[0],
NULL,
qtrue
);
CG_MakeBulletHole(wall_impact_pos[0], wall_impact_norm[0], wall_impact_large[0], NULL, qtrue);
}
}
@@ -969,15 +948,13 @@ void CG_AddBulletImpacts()
if (wall_impact_type[iImpSndIndexLB]) {
if (wall_impact_large[iImpSndIndexLB]) {
fVolume = 1.f;
}
else {
} else {
fVolume = 0.75f;
}
if (wall_impact_type[iImpSndIndexLB] == 2 || wall_impact_type[iImpSndIndexLB] == 3) {
sSoundName = "snd_bh_metal";
}
else {
} else {
sSoundName = "snd_bh_wood";
}
@@ -998,45 +975,31 @@ void CG_AddBulletImpacts()
);
}
}
}
else
{
} else {
for (i = 0; i < wall_impact_count; i++) {
CG_MakeBulletHole(
wall_impact_pos[i],
wall_impact_norm[i],
wall_impact_large[i],
NULL,
qtrue
);
CG_MakeBulletHole(wall_impact_pos[i], wall_impact_norm[i], wall_impact_large[i], NULL, qtrue);
}
}
wall_impact_count = 0;
}
if (flesh_impact_count)
{
if (flesh_impact_count > 1)
{
fImpSndDistRA = 9999.0;
if (flesh_impact_count) {
if (flesh_impact_count > 1) {
fImpSndDistRA = 9999.0;
iImpSndIndexRA = 0;
for (i = 0; i < flesh_impact_count; i++) {
VectorSubtract(wall_impact_pos[i], cg.SoundOrg, vTmp);
iHeadDist = VectorLength(vTmp);
if (DotProduct(vTmp, cg.SoundAxis[1]) > 0.f)
{
if (iHeadDist < fImpSndDistRA)
{
fImpSndDistRA = iHeadDist;
if (DotProduct(vTmp, cg.SoundAxis[1]) > 0.f) {
if (iHeadDist < fImpSndDistRA) {
fImpSndDistRA = iHeadDist;
iImpSndIndexRA = i;
}
}
else if (iHeadDist < fImpSndDistLA)
{
fImpSndDistRA = iHeadDist;
} else if (iHeadDist < fImpSndDistLA) {
fImpSndDistRA = iHeadDist;
iImpSndIndexRA = i;
}
}
@@ -1105,8 +1068,7 @@ void CG_MakeExplosionEffect(const vec3_t vPos, int iType)
fRadius = 0;
break;
case SURF_SNOW:
switch (iBaseEffect)
{
switch (iBaseEffect) {
case SFX_EXP_TANK_BASE:
iSurfEffect = SFX_EXP_TANK_SNOW;
break;
@@ -1122,7 +1084,7 @@ void CG_MakeExplosionEffect(const vec3_t vPos, int iType)
iBaseEffect = -1;
break;
}
fRadius = 0;
fRadius = 0;
break;
case SURF_CARPET:
iSurfEffect = SFX_EXP_GREN_CARPET;
@@ -1147,8 +1109,7 @@ void CG_MakeExplosionEffect(const vec3_t vPos, int iType)
fRadius = 0;
break;
case SURF_DIRT:
switch (iBaseEffect)
{
switch (iBaseEffect) {
case SFX_EXP_TANK_BASE:
iSurfEffect = SFX_EXP_TANK_DIRT;
break;
@@ -1164,15 +1125,14 @@ void CG_MakeExplosionEffect(const vec3_t vPos, int iType)
iBaseEffect = -1;
break;
}
fRadius = 0;
fRadius = 0;
break;
case SURF_GRILL:
iSurfEffect = SFX_EXP_GREN_GRILL;
fRadius = 0;
break;
case SURF_GRASS:
switch (iBaseEffect)
{
switch (iBaseEffect) {
case SFX_EXP_TANK_BASE:
iSurfEffect = SFX_EXP_TANK_DIRT;
break;
@@ -1190,8 +1150,7 @@ void CG_MakeExplosionEffect(const vec3_t vPos, int iType)
fRadius = 0;
break;
case SURF_ROCK:
switch (iBaseEffect)
{
switch (iBaseEffect) {
case SFX_EXP_TANK_BASE:
iSurfEffect = SFX_EXP_TANK_STONE;
break;
+6
View File
@@ -25,6 +25,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// interpolating between snapshots from the server or locally predicting
// ahead the client's movement. It also handles local physics interaction,
// like fragments bouncing off walls
//
// ADDITIONS:
// - CG_InterpolatePlayerState() footer: Interpolate the lean angles
#include "cg_local.h"
@@ -405,6 +408,9 @@ static void CG_InterpolatePlayerState(qboolean grabAngles)
}
out->velocity[i] = prev->ps.velocity[i] + f * (next->ps.velocity[i] - prev->ps.velocity[i]);
}
// interpolate the lean angle
out->fLeanAngle = LerpAngle(prev->ps.fLeanAngle, next->ps.fLeanAngle, f);
}
/*
+7 -3
View File
@@ -137,6 +137,8 @@ functions exported to the main executable
void (*FS_FreeFile)(void *buf);
int (*FS_WriteFile)(const char *qpath, const void *buffer, int size);
void (*FS_WriteTextFile)(const char *qpath, const void *buffer, int size);
char** (*FS_ListFilteredFiles)(const char* path, const char* extension, const char* filter, qboolean wantSubs, int* numfiles, qboolean allowNonPureFilesOnDisk);
void (*FS_FreeFileList)(char **list);
// add commands to the local console as if they were typed in
// for map changing, etc. The command is not executed immediately,
// but will be executed in order the next time console commands
@@ -163,7 +165,7 @@ functions exported to the main executable
void (*SendClientCommand)(const char *s);
// CM functions
void (*CM_LoadMap)(const char *name);
void (*CM_LoadMap)(const char *name, int* checksum);
clipHandle_t (*CM_InlineModel)(int index); // 0 = world, 1+ = bmodels
int (*CM_NumInlineModels)(void);
int (*CM_PointContents)(const vec3_t p, int headnode);
@@ -283,9 +285,11 @@ functions exported to the main executable
qhandle_t (*R_RegisterModel)(const char *name);
qhandle_t (*R_SpawnEffectModel)(const char *name, vec3_t pos, vec3_t axis[3]);
qhandle_t (*R_RegisterServerModel)(const char *name);
const char * (*R_GetModelName)(qhandle_t hModel);
void (*R_UnregisterServerModel)(qhandle_t hModel);
qhandle_t (*R_RegisterShader)(const char *name);
qhandle_t (*R_RegisterShaderNoMip)(const char *name);
const char* (*R_GetShaderName)(qhandle_t hShader);
void (*R_AddRefEntityToScene)(const refEntity_t *ent, int parentEntityNumber);
void (*R_AddRefSpriteToScene)(const refEntity_t *ent);
void (*R_AddLightToScene)(const vec3_t origin, float intensity, float r, float g, float b, int type);
@@ -499,8 +503,8 @@ functions exported to the main executable
//
void (*CG_ReadNonPVSClient)(radarUnpacked_t* radarUnpacked);
void (*CG_UpdateRadar)();
void (*CG_SaveStateToBuffer)(void** out, int svsTime);
void (*CG_LoadStateToBuffer)(void** state, int size, int svsTime);
size_t (*CG_SaveStateToBuffer)(void** out, int svsTime);
qboolean (*CG_LoadStateToBuffer)(void* state, size_t size, int svsTime);
void (*CG_CleanUpTempModels)();
// FIXME
+59 -13
View File
@@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// cg_servercmds.c -- text commands sent by the server
#include "cg_local.h"
#include "../fgame/bg_voteoptions.h"
static const char *IsWeaponAllowed(int dmFlags, int flags)
{
@@ -112,6 +113,7 @@ void CG_ParseServerinfo(void)
char map[MAX_QPATH];
char *spawnpos;
const char *version;
const char *mapChecksumStr;
info = CG_ConfigString(CS_SERVERINFO);
cgs.gametype = atoi(Info_ValueForKey(info, "g_gametype"));
@@ -135,12 +137,23 @@ void CG_ParseServerinfo(void)
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"));
cgi.Cvar_Set("cg_obj_axistext1", Info_ValueForKey(info, "cg_obj_axistext1"));
cgi.Cvar_Set("cg_obj_axistext2", Info_ValueForKey(info, "cg_obj_axistext2"));
cgi.Cvar_Set("cg_obj_axistext3", Info_ValueForKey(info, "cg_obj_axistext3"));
cgi.Cvar_Set("cg_obj_alliedtext4", Info_ValueForKey(info, "g_obj_alliedtext4"));
cgi.Cvar_Set("cg_obj_alliedtext5", Info_ValueForKey(info, "g_obj_alliedtext5"));
cgi.Cvar_Set("cg_obj_axistext1", Info_ValueForKey(info, "g_obj_axistext1"));
cgi.Cvar_Set("cg_obj_axistext2", Info_ValueForKey(info, "g_obj_axistext2"));
cgi.Cvar_Set("cg_obj_axistext3", Info_ValueForKey(info, "g_obj_axistext3"));
cgi.Cvar_Set("cg_obj_axistext4", Info_ValueForKey(info, "g_obj_axistext4"));
cgi.Cvar_Set("cg_obj_axistext5", Info_ValueForKey(info, "g_obj_axistext5"));
cgi.Cvar_Set("cg_scoreboardpic", Info_ValueForKey(info, "g_scoreboardpic"));
cgi.Cvar_Set("cg_scoreboardpicover", Info_ValueForKey(info, "g_scoreboardpicover"));
cgs.mapChecksum = atoi(Info_ValueForKey(info, "sv_mapChecksum"));
mapChecksumStr = Info_ValueForKey(info, "sv_mapChecksum");
if (mapChecksumStr && mapChecksumStr[0]) {
cgs.mapChecksum = atoi(mapChecksumStr);
cgs.useMapChecksum = qtrue;
} else {
cgs.mapChecksum = 0;
cgs.useMapChecksum = qfalse;
}
mapname = Info_ValueForKey(info, "mapname");
@@ -184,17 +197,13 @@ CG_ConfigStringModified
================
*/
static void CG_ConfigStringModified(void)
static void CG_ConfigStringModified(int num, qboolean modelOnly)
{
int num;
num = atoi(cgi.Argv(1));
// get the gamestate from the client system, which will have the
// new configstring already integrated
cgi.GetGameState(&cgs.gameState);
CG_ProcessConfigString(num);
CG_ProcessConfigString(num, modelOnly);
}
/*
@@ -275,7 +284,7 @@ The string has been tokenized and can be retrieved with
Cmd_Argc() / Cmd_Argv()
=================
*/
static void CG_ServerCommand(void)
static void CG_ServerCommand(qboolean modelOnly)
{
const char *cmd;
@@ -287,7 +296,11 @@ static void CG_ServerCommand(void)
}
if (!strcmp(cmd, "cs")) {
CG_ConfigStringModified();
CG_ConfigStringModified(atoi(cgi.Argv(1)), modelOnly);
return;
}
if (modelOnly) {
return;
}
@@ -364,6 +377,28 @@ static void CG_ServerCommand(void)
return;
}
if (!strcmp(cmd, "voteresult")) {
cmd = cgi.Argv(1);
if (*cmd) {
strcmp(cmd, "passed");
}
}
if (!strcmp(cmd, "vo0")) {
CG_VoteOptions_StartReadFromServer(cgi.Argv(1));
return;
}
if (!strcmp(cmd, "vo1")) {
CG_VoteOptions_ContinueReadFromServer(cgi.Argv(1));
return;
}
if (!strcmp(cmd, "vo2")) {
CG_VoteOptions_FinishReadFromServer(cgi.Argv(1));
return;
}
cgi.Printf("Unknown client game command: %s\n", cmd);
}
@@ -377,9 +412,20 @@ with this this snapshot.
*/
void CG_ExecuteNewServerCommands(int latestSequence, qboolean differentServer)
{
int lastServerCommandSequence;
lastServerCommandSequence = cgs.serverCommandSequence;
while (cgs.serverCommandSequence < latestSequence) {
if (cgi.GetServerCommand(++cgs.serverCommandSequence, differentServer)) {
CG_ServerCommand();
CG_ServerCommand(qtrue);
}
}
cgs.serverCommandSequence = lastServerCommandSequence;
while (cgs.serverCommandSequence < latestSequence) {
if (cgi.GetServerCommand(++cgs.serverCommandSequence, differentServer)) {
CG_ServerCommand(qfalse);
}
}
}
+16
View File
@@ -23,8 +23,12 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// DESCRIPTION:
// things that happen on snapshot transition, not necessarily every
// single frame
//
// ADDITIONS:
// - CG_TransitionSnapshot() footer: set ps.walking to true if the ps has a ground entity
#include "cg_local.h"
#include "cg_radar.h"
#include "tiki.h"
/*
@@ -206,6 +210,9 @@ static void CG_TransitionSnapshot(qboolean differentServer)
cent->teleported = qfalse;
}
CG_TransitionEntity(cent);
// remember time of snapshot this entity was last updated in
cent->snapShotTime = cg.snap->serverTime;
}
for (i = 0; i < cg.snap->number_of_sounds; i++) {
@@ -243,6 +250,15 @@ static void CG_TransitionSnapshot(qboolean differentServer)
CG_TransitionPlayerState(ps, ops);
}
}
if (differentServer) {
cgi.CL_RestoreSavedCgameState();
} else {
cgi.CL_ClearSavedCgameState();
}
// this allows the view model to still look normal when the player is on ground
cg.snap->ps.walking = cg.snap->ps.groundEntityNum != ENTITYNUM_NONE;
}
/*
+221 -118
View File
@@ -28,6 +28,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "tiki.h"
cvar_t *cg_showtempmodels;
cvar_t *cg_max_tempmodels;
cvar_t *cg_reserve_tempmodels;
cvar_t *cg_detail;
cvar_t *cg_effectdetail;
cvar_t *cg_effect_physicsrate;
@@ -86,6 +88,83 @@ void ClientGameCommandManager::FreeTempModel(ctempmodel_t *p)
m_free_tempmodels = p;
}
//===============
// FreeAllTempModels
//===============
void ClientGameCommandManager::FreeAllTempModels(void)
{
ctempmodel_t *p, *next;
// Go through all the temp models and run the physics if necessary,
// then add them to the ref
p = m_active_tempmodels.prev;
for (; p != &m_active_tempmodels; p = next) {
// grab next now, so if the local entity is freed we still have it
next = p->prev;
FreeTempModel(p);
}
}
//===============
// FreeSomeTempModels
//===============
void ClientGameCommandManager::FreeSomeTempModels(void)
{
ctempmodel_t* model;
int count = 0;
unsigned int i;
unsigned int numToFree;
if (!m_free_tempmodels) {
return;
}
for (model = m_active_tempmodels.prev; model != &m_active_tempmodels; model = model->prev) {
count++;
}
if (cg_reserve_tempmodels->integer <= (cg_max_tempmodels->integer - count)) {
// nothing to free
return;
}
numToFree = cg_reserve_tempmodels->integer - (cg_max_tempmodels->integer - count);
for (i = 0; i < numToFree; i++) {
FreeTempModel(m_active_tempmodels.prev);
}
}
//===============
// FreeSpawnthing
//===============
void ClientGameCommandManager::FreeSpawnthing(spawnthing_t* sp)
{
ctempmodel_t* model;
ctempmodel_t* prev;
if (sp->numtempmodels) {
for (model = m_active_tempmodels.prev; model != &m_active_tempmodels; model = prev) {
prev = model->prev;
if (model->m_spawnthing == sp) {
FreeTempModel(model);
}
}
} else {
m_emitters.RemoveObject(sp);
if (sp == m_spawnthing) {
m_spawnthing = NULL;
}
delete sp;
}
}
//===============
// ResetTempModels
//===============
void ClientGameCommandManager::ResetTempModels(void)
{
// Go through all the active tempmodels and free them
@@ -99,6 +178,7 @@ void ClientGameCommandManager::ResetTempModels(void)
}
static int lastTempModelFrameTime = 0;
int next_tempmodel_warning = 0;
void CG_ResetTempModels(void)
{
@@ -128,9 +208,23 @@ void ClientGameCommandManager::InitializeTempModels(void)
void ClientGameCommandManager::InitializeTempModelCvars(void)
{
cg_showtempmodels = cgi.Cvar_Get("cg_showtempmodels", "0", 0);
cg_detail = cgi.Cvar_Get("detail", "1", 1);
cg_effectdetail = cgi.Cvar_Get("cg_effectdetail", "0.2", 1);
cg_effect_physicsrate = cgi.Cvar_Get("cg_effect_physicsrate", "10", 1);
cg_detail = cgi.Cvar_Get("detail", "1", CVAR_ARCHIVE);
cg_effectdetail = cgi.Cvar_Get("cg_effectdetail", "0.2", CVAR_ARCHIVE);
cg_effect_physicsrate = cgi.Cvar_Get("cg_effect_physicsrate", "10", CVAR_ARCHIVE);
cg_max_tempmodels = cgi.Cvar_Get("cg_max_tempmodels", "1100", CVAR_ARCHIVE);
cg_reserve_tempmodels = cgi.Cvar_Get("cg_reserve_tempmodels", "200", CVAR_ARCHIVE);
if (cg_max_tempmodels->integer > MAX_TEMPMODELS) {
// 2.40 sets the integer value directly rather than calling Cvar_Set()
//cg_max_tempmodels->integer = MAX_TEMPMODELS
cgi.Cvar_Set("cg_max_tempmodels", va("%i", MAX_TEMPMODELS));
}
if (cg_reserve_tempmodels->integer * 5 > cg_max_tempmodels->integer) {
// 2.40 sets the integer value directly rather than calling Cvar_Set()
//cg_reserve_tempmodels->integer = cg_max_tempmodels->integer / 5;
cgi.Cvar_Set("cg_reserve_tempmodels", va("%i", cg_max_tempmodels->integer / 5));
}
}
//===============
@@ -141,6 +235,7 @@ void ClientGameCommandManager::AnimateTempModel(ctempmodel_t *p, Vector origin,
int numframes;
int deltatime;
int frametime;
float prev;
// This code is for animating tempmodels that are spawned from the client
// side
@@ -165,10 +260,18 @@ void ClientGameCommandManager::AnimateTempModel(ctempmodel_t *p, Vector origin,
// Go through all the frames, and process any commands associated with the
// tempmodel as well
prev = deltatime;
while (deltatime >= frametime) {
deltatime -= frametime;
p->lastAnimTime += frametime;
p->ent.wasframe = (p->ent.wasframe + 1) % numframes;
CG_ProcessEntityCommands(p->ent.wasframe, p->ent.frameInfo[0].index, -1, &p->ent, NULL);
if (deltatime == prev) {
break;
}
prev = deltatime;
}
}
@@ -208,9 +311,10 @@ void ClientGameCommandManager::UpdateSwarm(ctempmodel_t *p)
}
}
qboolean ClientGameCommandManager::TempModelRealtimeEffects(ctempmodel_t *p, float ftime, float dtime, float scale)
qboolean ClientGameCommandManager::TempModelRealtimeEffects(ctempmodel_t *p, float ftime, float scale)
{
float fade, fadein;
float dtime;
byte tempColor[4];
if (p->cgd.flags & (T_FADE | T_SCALEUPDOWN)) {
@@ -362,9 +466,19 @@ void ClientGameCommandManager::OtherTempModelEffects(ctempmodel_t *p, Vector ori
vec3_t axis[3];
if (p->number != -1) {
refEntity_t *old_entity;
dtiki_t *old_tiki;
int oldnum;
float oldscale;
// Set the axis
AnglesToAxis(p->cgd.angles, axis);
old_entity = current_entity;
old_tiki = current_tiki;
oldnum = current_entity_number;
oldscale = current_scale;
current_scale = newEnt->scale;
current_entity = newEnt;
current_tiki = p->cgd.tiki;
@@ -380,14 +494,23 @@ void ClientGameCommandManager::OtherTempModelEffects(ctempmodel_t *p, Vector ori
commandManager.ProcessEvent(ev);
}
current_entity_number = -1;
current_tiki = NULL;
current_entity = NULL;
current_scale = -1;
current_entity_number = oldnum;
current_tiki = old_tiki;
current_entity = old_entity;
current_scale = oldscale;
}
if (p->cgd.flags2 & T2_ALIGNSTRETCH) {
Vector vDelta;
float fScale;
vDelta = p->cgd.origin - p->cgd.oldorigin;
fScale = vDelta.length() * p->cgd.scale2;
VectorScale(newEnt->axis[0], fScale, newEnt->axis[0]);
}
}
qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t *p, float ftime, float time2, float scale)
qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t *p, float ftime, float scale)
{
int dtime;
Vector parentOrigin(0, 0, 0);
@@ -406,37 +529,41 @@ qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t *p, float ftime
// Update based on swarm
if (p->cgd.flags & T_SWARM) {
p->cgd.origin += ftime * p->cgd.velocity * scale;
p->cgd.origin += p->cgd.velocity * ftime * scale;
}
// Update the orign and the angles based on velocities first
if (p->cgd.flags2 & (T2_MOVE | T2_ACCEL)) {
p->cgd.origin = p->cgd.origin + (p->cgd.velocity * ftime * scale) + (time2 * p->cgd.accel);
else if (p->cgd.flags2 & (T2_MOVE | T2_ACCEL)) {
p->cgd.origin += p->cgd.velocity * ftime * scale;
}
// If linked to the parent or hardlinked, get the parent's origin
if ((p->cgd.flags & (T_PARENTLINK | T_HARDLINK)) && (p->cgd.parent != ENTITYNUM_NONE)) {
centity_t *pc;
centity_t* pc;
refEntity_t* e;
pc = &cg_entities[p->cgd.parent];
if (pc->currentValid) {
refEntity_t *e;
e = cgi.R_GetRenderEntity(p->cgd.parent);
if (!e) {
return false;
}
parentOrigin = e->origin;
vectoangles(e->axis[0], parentAngles);
} else {
if (!pc->currentValid) {
return false;
}
} else if (p->cgd.flags & T_SWARM) {
e = cgi.R_GetRenderEntity(p->cgd.parent);
if (!e) {
return false;
}
parentOrigin = e->origin;
vectoangles(e->axis[0], parentAngles);
}
else if (p->cgd.flags & T_SWARM) {
p->cgd.parentOrigin = p->cgd.velocity + p->cgd.accel * ftime * scale;
}
if (p->cgd.flags2 & T2_WATERONLY) {
if (!(cgi.CM_PointContents(p->cgd.origin, 0) & (CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA))) {
return false;
}
}
// Align the object along it's traveling vector
if (p->cgd.flags & T_ALIGN) {
p->cgd.angles = p->cgd.velocity.toAngles();
@@ -457,12 +584,12 @@ qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t *p, float ftime
p->cgd.angles[1] = AngleMod(p->cgd.angles[1]);
p->cgd.angles[2] = AngleMod(p->cgd.angles[2]);
// Add in parent angles
tempangles = p->cgd.angles + parentAngles;
// Convert to axis
if ((p->cgd.flags & (T_ALIGN | T_RANDOMROLL | T_PARENTLINK | T_HARDLINK | T_ANGLES))
|| (p->cgd.flags2 & T2_AMOVE)) {
// Add in parent angles
tempangles = p->cgd.angles + parentAngles;
AnglesToAxis(tempangles, p->ent.axis);
}
@@ -503,25 +630,9 @@ qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t *p, float ftime
}
if (p->cgd.flags2 & T2_CLAMP_VEL) {
if (p->cgd.velocity.x < p->cgd.minVel.x) {
p->cgd.velocity.x = p->cgd.minVel.x;
}
if (p->cgd.velocity.y < p->cgd.minVel.y) {
p->cgd.velocity.y = p->cgd.minVel.y;
}
if (p->cgd.velocity.z < p->cgd.minVel.z) {
p->cgd.velocity.z = p->cgd.minVel.z;
}
if (p->cgd.velocity.x > p->cgd.maxVel.x) {
p->cgd.velocity.x = p->cgd.maxVel.x;
}
if (p->cgd.velocity.y > p->cgd.maxVel.y) {
p->cgd.velocity.y = p->cgd.maxVel.y;
}
if (p->cgd.velocity.z > p->cgd.maxVel.z) {
p->cgd.velocity.z = p->cgd.maxVel.z;
}
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) {
@@ -530,25 +641,9 @@ qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t *p, float ftime
localVelocity.y = DotProduct(p->cgd.velocity, p->ent.axis[1]);
localVelocity.z = DotProduct(p->cgd.velocity, p->ent.axis[2]);
if (localVelocity.x < p->cgd.minVel.x) {
localVelocity.x = p->cgd.minVel.x;
}
if (localVelocity.y < p->cgd.minVel.y) {
localVelocity.y = p->cgd.minVel.y;
}
if (localVelocity.z < p->cgd.minVel.z) {
localVelocity.z = p->cgd.minVel.z;
}
if (localVelocity.x > p->cgd.maxVel.x) {
localVelocity.x = p->cgd.maxVel.x;
}
if (localVelocity.y > p->cgd.maxVel.y) {
localVelocity.y = p->cgd.maxVel.y;
}
if (localVelocity.z > p->cgd.maxVel.z) {
localVelocity.z = p->cgd.maxVel.z;
}
localVelocity.x = Q_clamp_float(localVelocity.x, p->cgd.minVel.x, p->cgd.maxVel.x);
localVelocity.y = Q_clamp_float(localVelocity.y, p->cgd.minVel.y, p->cgd.maxVel.y);
localVelocity.z = Q_clamp_float(localVelocity.z, p->cgd.minVel.z, p->cgd.maxVel.z);
p->cgd.velocity.x = DotProduct(localVelocity, p->ent.axis[0]);
p->cgd.velocity.y = DotProduct(localVelocity, p->ent.axis[1]);
@@ -559,14 +654,6 @@ qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t *p, float ftime
// FIXME: vss wind
}
} else {
if (p->touchfcn) {
p->touchfcn(p, &trace);
}
if (p->cgd.flags & T_DIETOUCH) {
return false;
}
Vector normal;
// Set the origin
@@ -581,14 +668,14 @@ qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t *p, float ftime
trace.endpos,
trace.plane.normal,
p->cgd.decal_orientation,
p->cgd.decal_radius,
p->cgd.color[0],
p->cgd.color[1],
p->cgd.color[2],
p->cgd.alpha,
p->cgd.flags & T_FADE,
p->cgd.decal_radius,
p->cgd.flags2 & T2_TEMPORARY_DECAL,
p->cgd.lightstyle,
qtrue,
p->cgd.flags & T_FADEIN
);
@@ -610,9 +697,10 @@ qboolean ClientGameCommandManager::TempModelPhysics(ctempmodel_t *p, float ftime
dot = p->cgd.velocity * normal;
p->cgd.velocity = p->cgd.velocity + ((-2 * dot) * normal);
p->cgd.velocity *= p->cgd.bouncefactor;
p->cgd.avelocity *= -p->cgd.bouncefactor;
// check for stop
if (trace.plane.normal[2] > 0 && p->cgd.velocity[2] < 40) {
if (trace.plane.normal[2] > 0 && p->cgd.velocity[2] < 45) {
p->cgd.velocity = Vector(0, 0, 0);
p->cgd.avelocity = Vector(0, 0, 0);
p->cgd.flags &= ~T_WAVE;
@@ -685,7 +773,7 @@ qboolean ClientGameCommandManager::LerpTempModel(refEntity_t *newEnt, ctempmodel
// Add the parent ent's origin to the local origin
VectorAdd(newEnt->origin, parentOrigin, newEnt->origin);
} else {
if (p->cgd.flags2 & (T2_MOVE | T2_ACCEL)) {
if (p->cgd.flags2 & (T2_MOVE | T2_ACCEL) || (p->cgd.flags & T_SWARM)) {
// Lerp the ent's origin
for (i = 0; i < 3; i++) {
newEnt->origin[i] = p->lastEnt.origin[i] + frac * (p->ent.origin[i] - p->lastEnt.origin[i]);
@@ -741,16 +829,17 @@ void ClientGameCommandManager::AddTempModels(void)
refEntity_t *old_ent;
// To counteract cg.time going backwards
if (lastTempModelFrameTime) {
if ((cg.time < lastTempModelFrameTime) || (cg.time - lastTempModelFrameTime > TOO_MUCH_TIME_PASSED)) {
p = m_active_tempmodels.prev;
for (; p != &m_active_tempmodels; p = next) {
next = p->prev;
p->lastPhysicsTime = cg.time;
}
lastTempModelFrameTime = cg.time;
return;
if (lastTempModelFrameTime && ((cg.time < lastTempModelFrameTime) || (cg.time - lastTempModelFrameTime > TOO_MUCH_TIME_PASSED))) {
p = m_active_tempmodels.prev;
for (; p != &m_active_tempmodels; p = next) {
next = p->prev;
p->lastPhysicsTime = cg.time;
}
lastTempModelFrameTime = cg.time;
return;
}
if (lastTempModelFrameTime) {
frameTime = cg.time - lastTempModelFrameTime;
} else {
frameTime = 0;
@@ -763,6 +852,7 @@ void ClientGameCommandManager::AddTempModels(void)
}
memset(&newEnt, 0, sizeof(newEnt));
newEnt.parentEntity = ENTITYNUM_NONE;
// Set this frame time for the next one
effectTime = (float)frameTime / 1000.0f;
effectTime2 = effectTime * effectTime;
@@ -793,7 +883,7 @@ void ClientGameCommandManager::AddTempModels(void)
current_tiki = p->cgd.tiki;
current_entity_number = p->number;
TempModelRealtimeEffects(p, effectTime, effectTime2, scale);
TempModelRealtimeEffects(p, effectTime, scale);
if (p->lastPhysicsTime) {
mstime = cg.time - p->lastPhysicsTime;
@@ -808,8 +898,7 @@ void ClientGameCommandManager::AddTempModels(void)
if ((mstime >= physics_rate) || (p->cgd.flags2 & T2_PHYSICS_EVERYFRAME)) {
ftime = mstime / 1000.0f;
time2 = ftime * ftime;
ret = TempModelPhysics(p, ftime, time2, scale);
ret = TempModelPhysics(p, ftime, scale);
if (!ret) {
FreeTempModel(p);
@@ -823,14 +912,8 @@ void ClientGameCommandManager::AddTempModels(void)
// Calculate the lerp value based on the time passed since last physics
// time of this tempmodel
lerpfrac = (float)(cg.time - p->lastPhysicsTime) / (float)physics_rate;
// Clamp
if (lerpfrac > 1) {
lerpfrac = 1;
}
if (lerpfrac < 0) {
lerpfrac = 0;
}
lerpfrac = Q_clamp_float(lerpfrac, 0, 1);
// Increment the time this tempmodel has been alive
p->aliveTime += frameTime;
@@ -843,11 +926,10 @@ void ClientGameCommandManager::AddTempModels(void)
// Run physics if the lastEnt is not valid to get a valid lerp
if (!p->lastEntValid) {
float t, t2;
float t;
t = physics_rate / 1000.0f;
t2 = t * t;
ret = TempModelPhysics(p, t, t2, scale);
ret = TempModelPhysics(p, t, scale);
if (!ret) {
FreeTempModel(p);
continue;
@@ -872,12 +954,12 @@ void ClientGameCommandManager::AddTempModels(void)
}
if (p->cgd.flags & T_WAVE) {
Vector origin;
vec3_t origin;
float axis[3][3];
origin = Vector(p->m_spawnthing->linked_origin) + Vector(p->m_spawnthing->linked_axis[0]) * newEnt.origin[0]
+ Vector(p->m_spawnthing->linked_axis[1]) * newEnt.origin[1]
+ Vector(p->m_spawnthing->linked_axis[2]) * newEnt.origin[2];
VectorMA(p->m_spawnthing->linked_origin, newEnt.origin[0], p->m_spawnthing->linked_axis[0], origin);
VectorMA(origin, newEnt.origin[1], p->m_spawnthing->linked_axis[1], origin);
VectorMA(origin, newEnt.origin[2], p->m_spawnthing->linked_axis[2], origin);
VectorCopy(origin, newEnt.origin);
@@ -891,7 +973,10 @@ void ClientGameCommandManager::AddTempModels(void)
newEnt.reType = p->ent.reType;
newEnt.shaderTime = p->ent.shaderTime;
newEnt.frameInfo[0] = p->ent.frameInfo[0];
newEnt.frameInfo[0].index = p->ent.frameInfo[0].index;
newEnt.frameInfo[0].weight = 1.0;
newEnt.frameInfo[0].time = 0.0;
newEnt.wasframe = p->ent.wasframe;
newEnt.actionWeight = 1.0;
newEnt.entityNumber = ENTITYNUM_NONE;
@@ -901,6 +986,9 @@ void ClientGameCommandManager::AddTempModels(void)
OtherTempModelEffects(p, newEnt.origin, &newEnt);
VectorCopy(newEnt.origin, newEnt.lightingOrigin);
newEnt.radius = 4.0;
// Add to the ref
if (p->cgd.flags & T_DLIGHT) {
// Tempmodel is a Dynamic Light
@@ -960,6 +1048,14 @@ void ClientGameCommandManager::SpawnTempModel(int mcount)
Vector delta;
Vector start;
Vector vForward, vLeft, vUp;
float fDist;
delta = m_spawnthing->cgd.origin - cg.refdef.vieworg;
fDist = delta * delta * (cg.refdef.fov_x * cg.refdef.fov_x / 6400.0);
if (fDist >= m_spawnthing->fMaxRangeSquared || fDist < m_spawnthing->fMinRangeSquared) {
// don't draw above the distance
return;
}
if (current_entity) {
current_entity_scale = current_entity->scale;
@@ -1003,7 +1099,11 @@ void ClientGameCommandManager::SpawnTempModel(int mcount)
p = AllocateTempModel();
if (!p) {
cgi.DPrintf("Out of tempmodels\n");
if (cgi.Milliseconds() >= next_tempmodel_warning) {
// make sure to not spam the console with this message
cgi.DPrintf("Out of tempmodels\n");
next_tempmodel_warning = cgi.Milliseconds() + 1000;
}
return;
}
@@ -1027,9 +1127,11 @@ void ClientGameCommandManager::SpawnTempModel(int mcount)
// Set up the origin of the tempmodel
if (m_spawnthing->cgd.flags & T_SPHERE) {
// Create a random forward vector so the particles burst out in a
// sphere
newForward = Vector(crandom(), crandom(), crandom());
do {
// Create a random forward vector so the particles burst out in a
// sphere
newForward = Vector(crandom(), crandom(), crandom());
} while (newForward * newForward > 1.0);
} else if (m_spawnthing->cgd.flags & T_CIRCLE) {
if (m_spawnthing->sphereRadius != 0) // Offset by the radius
{
@@ -1049,7 +1151,9 @@ void ClientGameCommandManager::SpawnTempModel(int mcount)
// vector pointing back to the origin
Vector dir, end;
dir = Vector(crandom(), crandom(), crandom());
do {
dir = Vector(crandom(), crandom(), crandom());
} while (dir * dir > 1.0);
end = m_spawnthing->cgd.origin + dir * m_spawnthing->sphereRadius * current_entity_scale;
VectorCopy(end, p->cgd.origin);
@@ -1078,10 +1182,9 @@ void ClientGameCommandManager::SpawnTempModel(int mcount)
cosa = cos(fAngle);
p->cgd.origin = start + vForward * fHeight;
p->cgd.origin += start + vLeft * (cosa * fRadius);
p->cgd.origin += start + vUp * (sina * fRadius);
} else if (m_spawnthing->sphereRadius != 0) // Offset in a spherical pattern
{
p->cgd.origin += vLeft * (cosa * fRadius);
p->cgd.origin += vUp * (sina * fRadius);
} else if (m_spawnthing->sphereRadius != 0) { // Offset in a spherical pattern
Vector dir, end;
dir = Vector(crandom(), crandom(), crandom());
@@ -1092,7 +1195,7 @@ void ClientGameCommandManager::SpawnTempModel(int mcount)
VectorCopy(end, p->cgd.origin);
newForward = dir;
} else {
VectorCopy(m_spawnthing->cgd.origin, p->cgd.origin);
VectorCopy(start, p->cgd.origin);
}
if (m_spawnthing->cgd.flags & T_SWARM && !(m_spawnthing->cgd.flags & (T_HARDLINK | T_PARENTLINK))) {
+1 -1
View File
@@ -189,7 +189,7 @@ void CG_InstaMessageGroupE_f(void)
void CG_HudPrint_f(void)
{
cgi.Printf("\x1%s", cgi.Argv(0));
cgi.Printf("\x1%s", cgi.Argv(1));
}
int CG_CheckCaptureKey(int key, qboolean down, unsigned int time)
+127 -7
View File
@@ -504,6 +504,44 @@ static int CG_CalcFov(void)
return inwater;
}
/*
===============
CG_SetupFog
Prepares fog values for rendering
===============
*/
void CG_SetupFog() {
cg.refdef.farplane_distance = cg.farplane_distance;
cg.refdef.farplane_bias = cg.farplane_bias;
cg.refdef.farplane_color[0] = cg.farplane_color[0];
cg.refdef.farplane_color[1] = cg.farplane_color[1];
cg.refdef.farplane_color[2] = cg.farplane_color[2];
cg.refdef.farplane_cull = cg.farplane_cull;
cg.refdef.skybox_farplane = cg.skyboxFarplane;
cg.refdef.renderTerrain = cg.renderTerrain;
cg.refdef.farclipOverride = cg.farclipOverride;
cg.refdef.farplaneColorOverride[0] = cg.farplaneColorOverride[0];
cg.refdef.farplaneColorOverride[1] = cg.farplaneColorOverride[1];
cg.refdef.farplaneColorOverride[2] = cg.farplaneColorOverride[2];
}
/*
===============
CG_SetupPortalSky
Sets portalsky values for rendering
===============
*/
void CG_SetupPortalSky() {
cg.refdef.sky_alpha = cg.sky_alpha;
cg.refdef.sky_portal = cg.sky_portal;
VectorCopy(cg.sky_axis[0], cg.refdef.sky_axis[0]);
VectorCopy(cg.sky_axis[1], cg.refdef.sky_axis[1]);
VectorCopy(cg.sky_axis[2], cg.refdef.sky_axis[2]);
VectorMA(cg.sky_origin, cg.skyboxSpeed, cg.refdef.vieworg, cg.refdef.sky_origin);
}
/*
===============
CG_CalcViewValues
@@ -520,6 +558,7 @@ static int CG_CalcViewValues(void)
// calculate size of 3D view
CG_CalcVrect();
CG_SetupFog();
// setup fog and far clipping plane
cg.refdef.farplane_distance = cg.farplane_distance;
@@ -604,7 +643,9 @@ static int CG_CalcViewValues(void)
// Set the aural axis of the player
VectorCopy(cg.refdefViewAngles, SoundAngles);
// yaw is purposely inverted because of the miles sound system
SoundAngles[YAW] = -SoundAngles[YAW];
// Commented out in OPM
// Useless as SDL audio/AL is used
//SoundAngles[YAW] = -SoundAngles[YAW];
AnglesToAxis(SoundAngles, cg.SoundAxis);
// decide on third person view
@@ -623,6 +664,11 @@ static int CG_CalcViewValues(void)
// Set the aural axis to the camera's angles
VectorCopy(cg.camera_angles, cg.refdefViewAngles);
if (cg_protocol >= PROTOCOL_MOHTA_MIN && (ps->pm_flags & PMF_DAMAGE_ANGLES)) {
// Handle camera shake
VectorSubtract(cg.refdefViewAngles, cg.predicted_player_state.damage_angles, cg.refdefViewAngles);
}
if (ps->camera_posofs[0] || ps->camera_posofs[1] || ps->camera_posofs[2]) {
vec3_t vAxis[3], vOrg;
AnglesToAxis(cg.refdefViewAngles, vAxis);
@@ -633,6 +679,9 @@ static int CG_CalcViewValues(void)
// copy view values
VectorCopy(cg.refdef.vieworg, cg.currentViewPos);
VectorCopy(cg.refdefViewAngles, cg.currentViewAngles);
// since 2.0: also copy location data for sound
VectorCopy(cg.refdef.vieworg, cg.SoundOrg);
AnglesToAxis(cg.refdefViewAngles, cg.SoundAxis);
}
// position eye reletive to origin
@@ -774,10 +823,46 @@ void CG_DrawActiveFrame(int serverTime, int frameTime, stereoFrame_t stereoView,
CG_ScoresDown_f();
} else if (cg.bIntermissionDisplay) {
if (cg.nextSnap) {
if (cgi.Cvar_Get("g_success", "", 0)->integer) {
cgi.UI_ShowMenu("StatsScreen_Success", qfalse);
if (cg_protocol >= PROTOCOL_MOHTA_MIN) {
cvar_t* pMission = cgi.Cvar_Get("g_mission", "", CVAR_ARCHIVE);
if (cgi.Cvar_Get("g_success", "", 0)->integer) {
switch (pMission->integer)
{
default:
case 0:
cgi.UI_ShowMenu("mission_success_1", 0);
cgi.Cvar_Set("g_t2l1", "1");
break;
case 2:
cgi.UI_ShowMenu("mission_success_2", 0);
cgi.Cvar_Set("g_t3l1", "1");
break;
case 3:
cgi.UI_ShowMenu("mission_success_3", 0);
break;
}
} else {
switch (pMission->integer)
{
default:
case 0:
cgi.UI_ShowMenu("mission_failed_1", 0);
break;
case 2:
cgi.UI_ShowMenu("mission_failed_2", 0);
break;
case 3:
cgi.UI_ShowMenu("mission_failed_3", 0);
break;
}
}
} else {
cgi.UI_ShowMenu("StatsScreen_Failed", qfalse);
if (cgi.Cvar_Get("g_success", "", 0)->integer) {
cgi.UI_ShowMenu("StatsScreen_Success", qfalse);
} else {
cgi.UI_ShowMenu("StatsScreen_Failed", qfalse);
}
}
}
} else {
@@ -789,10 +874,44 @@ void CG_DrawActiveFrame(int serverTime, int frameTime, stereoFrame_t stereoView,
if (cgs.gametype != GT_SINGLE_PLAYER) {
CG_ScoresUp_f();
} else {
if (cgi.Cvar_Get("g_success", "", 0)->integer) {
cgi.UI_ShowMenu("StatsScreen_Success", qfalse);
if (cg_protocol >= PROTOCOL_MOHTA_MIN) {
cvar_t* pMission = cgi.Cvar_Get("g_mission", "", CVAR_ARCHIVE);
if (cgi.Cvar_Get("g_success", "", 0)->integer) {
switch (pMission->integer)
{
default:
case 0:
cgi.UI_HideMenu("mission_success_1", CVAR_ARCHIVE);
break;
case 2:
cgi.UI_HideMenu("mission_success_2", CVAR_ARCHIVE);
break;
case 3:
cgi.UI_HideMenu("mission_success_3", CVAR_ARCHIVE);
break;
}
} else {
switch (pMission->integer)
{
default:
case 0:
cgi.UI_HideMenu("mission_failed_1", CVAR_ARCHIVE);
break;
case 2:
cgi.UI_HideMenu("mission_failed_2", CVAR_ARCHIVE);
break;
case 3:
cgi.UI_HideMenu("mission_failed_3", CVAR_ARCHIVE);
break;
}
}
} else {
cgi.UI_ShowMenu("StatsScreen_Failed", qfalse);
if (cgi.Cvar_Get("g_success", "", 0)->integer) {
cgi.UI_HideMenu("StatsScreen_Success", qfalse);
} else {
cgi.UI_HideMenu("StatsScreen_Failed", qfalse);
}
}
}
@@ -806,6 +925,7 @@ void CG_DrawActiveFrame(int serverTime, int frameTime, stereoFrame_t stereoView,
}
// finish up the rest of the refdef
CG_SetupPortalSky();
cg.refdef.time = cg.time;
memcpy(cg.refdef.areamask, cg.snap->areamask, sizeof(cg.refdef.areamask));
+6
View File
@@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cg_local.h"
#include "cg_commands.h"
#include "memarchiver.h"
const char *cg_vsstypes[] = {
"default",
@@ -214,6 +215,11 @@ void CG_ResetVSSSources()
lastVSSFrameTime = cg.time;
}
void CG_ArchiveVSSGlobals(MemArchiver& archiver)
{
archiver.ArchiveTime(&lastVSSFrameTime);
}
void ClientGameCommandManager::InitializeVSSSources()
{
int i;
+241
View File
@@ -0,0 +1,241 @@
/*
===========================================================================
Copyright (C) 2023 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
===========================================================================
*/
#include "cg_local.h"
#include "memarchiver.h"
#include "../qcommon/vector.h"
#include "../qcommon/str.h"
MemArchiver::MemArchiver()
{
state = MEMARC_WRITING;
buffer = 0;
allocatedSize = 0;
bufferSize = 0;
}
MemArchiver::~MemArchiver()
{
if (state == MEMARC_WRITING && buffer) {
cgi.Free(buffer);
}
}
void MemArchiver::SetupForWriting(size_t initialSize)
{
state = MEMARC_WRITING;
buffer = (byte*)cgi.Malloc(initialSize);
allocatedSize = initialSize;
bufferSize = 0;
}
void MemArchiver::SetupForReading(byte* buffer, size_t size)
{
state = MEMARC_READING;
buffer = buffer;
allocatedSize = size;
bufferSize = 0;
}
void MemArchiver::SetBaseTime(unsigned int time)
{
svsTime = time;
}
size_t MemArchiver::BufferSize() const
{
return bufferSize;
}
byte* MemArchiver::ConfiscateBuffer()
{
byte* confiscatedBuffer = buffer;
buffer = NULL;
allocatedSize = 0;
bufferSize = 0;
return confiscatedBuffer;
}
bool MemArchiver::IsReading() const
{
return !IsWriting();
}
bool MemArchiver::IsWriting() const
{
return state == MEMARC_WRITING;
}
bool MemArchiver::FinishedReading() const
{
return bufferSize == allocatedSize;
}
void MemArchiver::ArchiveByte(byte* value)
{
ArchiveRaw(value, sizeof(byte));
}
void MemArchiver::ArchiveBoolean(qboolean* value)
{
ArchiveRaw(value, sizeof(qboolean));
}
void MemArchiver::ArchiveChar(char* value)
{
ArchiveRaw(value, sizeof(char));
}
void MemArchiver::ArchiveUChar(unsigned char* value)
{
ArchiveRaw(value, sizeof(unsigned char));
}
void MemArchiver::ArchiveShort(short* value)
{
ArchiveRaw(value, sizeof(short));
}
void MemArchiver::ArchiveInteger(int* value)
{
ArchiveRaw(value, sizeof(int));
}
void MemArchiver::ArchiveSize(size_t* value)
{
ArchiveRaw(value, sizeof(size_t));
}
void MemArchiver::ArchiveFloat(float* value)
{
ArchiveRaw(value, sizeof(float));
}
void MemArchiver::ArchiveVec3(vec3_t value)
{
ArchiveRaw(value, sizeof(vec3_t));
}
void MemArchiver::ArchiveVector(Vector* value)
{
ArchiveFloat(&value->x);
ArchiveFloat(&value->y);
ArchiveFloat(&value->z);
}
void MemArchiver::ArchiveString(str* value)
{
char tmp[4096];
int current = 0;
if (IsReading()) {
for (current = 0; current < 4096; current++) {
ArchiveReadRaw(&tmp[current], sizeof(char));
if (!tmp[current]) {
break;
}
}
if (current == 4096) {
tmp[current - 1] = 0;
}
*value = tmp;
} else {
ArchiveWriteRaw(value->c_str(), value->length() + 1);
}
}
void MemArchiver::ArchiveTime(int* value)
{
int time;
if (IsReading()) {
ArchiveReadRaw(&time, sizeof(time));
if (time) {
time += svsTime;
}
*value = time;
} else {
time = *value;
if (time) {
time -= svsTime;
}
ArchiveWriteRaw(&time, sizeof(time));
}
}
void MemArchiver::ArchiveRaw(void* buffer, size_t size)
{
if (IsReading()) {
ArchiveReadRaw(buffer, size);
} else {
ArchiveWriteRaw(buffer, size);
}
}
void MemArchiver::ArchiveReadRaw(void* buffer, size_t size)
{
if (!size) {
return;
}
if (size + this->bufferSize > this->allocatedSize) {
Com_Error(ERR_DROP, "MemArchiver: tried to read past end of buffer");
}
memcpy(buffer, this->buffer + this->bufferSize, size);
this->bufferSize += size;
}
void MemArchiver::ArchiveWriteRaw(const void* buffer, size_t size)
{
if (!size) {
return;
}
if (size + this->bufferSize > this->allocatedSize) {
if (!this->allocatedSize) {
this->allocatedSize = 1024;
this->buffer = (byte*)cgi.Malloc(this->allocatedSize);
} else {
byte* newBuffer;
do {
this->allocatedSize *= 2;
} while (size + this->bufferSize > this->allocatedSize);
newBuffer = (byte*)cgi.Malloc(this->allocatedSize);
memcpy(newBuffer, this->buffer, this->bufferSize);
cgi.Free(this->buffer);
this->buffer = newBuffer;
}
}
memcpy(this->buffer + this->bufferSize, buffer, size);
this->bufferSize += size;
}
+72
View File
@@ -0,0 +1,72 @@
/*
===========================================================================
Copyright (C) 2023 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
===========================================================================
*/
// DESCRIPTION:
// In-memory archiver
#include "cg_local.h"
class Vector;
class str;
typedef enum {
MEMARC_WRITING,
MEMARC_READING
} archiverState_e;
class MemArchiver {
public:
MemArchiver();
~MemArchiver();
void SetupForWriting(size_t initialSize);
void SetupForReading(byte* buffer, size_t size);
void SetBaseTime(unsigned int time);
size_t BufferSize() const;
byte* ConfiscateBuffer();
bool IsReading() const;
bool IsWriting() const;
bool FinishedReading() const;
void ArchiveByte(byte* value);
void ArchiveBoolean(qboolean* value);
void ArchiveChar(char* value);
void ArchiveUChar(unsigned char* value);
void ArchiveShort(short* value);
void ArchiveInteger(int* value);
void ArchiveSize(size_t* value);
void ArchiveFloat(float* value);
void ArchiveVec3(vec3_t value);
void ArchiveVector(Vector* value);
void ArchiveString(str* value);
void ArchiveTime(int* value);
void ArchiveRaw(void* buffer, size_t size);
void ArchiveReadRaw(void* buffer, size_t size);
void ArchiveWriteRaw(const void* buffer, size_t size);
private:
archiverState_e state;
byte* buffer;
size_t bufferSize;
size_t allocatedSize;
int svsTime;
};
+28 -1
View File
@@ -8,7 +8,6 @@ file(GLOB_RECURSE SOURCES_UILIB "../uilib/*.c*")
# Made as an interface and not static, as static only links used methods
add_library(omohclient INTERFACE)
target_sources(omohclient INTERFACE ${SOURCES_CLIENT} ${SOURCES_UILIB})
target_compile_definitions(omohclient INTERFACE APP_MODULE)
target_compile_features(omohclient INTERFACE cxx_nullptr)
target_compile_features(omohclient INTERFACE c_variadic_macros)
@@ -18,5 +17,33 @@ target_link_libraries(omohclient INTERFACE gcd)
# Sound stuff
target_compile_definitions(omohclient INTERFACE USE_CODEC_MP3)
if (USE_SOUND_NEW)
# Try to use OpenAL
find_package(OpenAL)
if (OPENAL_FOUND)
target_compile_definitions(omohclient INTERFACE USE_SOUND_NEW=1)
if (MSVC)
target_include_directories(omohclient INTERFACE ${OPENAL_INCLUDE_DIR}/AL)
else()
target_include_directories(omohclient INTERFACE ${OPENAL_INCLUDE_DIR})
endif()
target_link_libraries(omohclient INTERFACE ${OPENAL_LIBRARY})
endif()
list(FILTER SOURCES_CLIENT EXCLUDE REGEX "./snd_([a-zA-Z0-9_]+)\.c$")
endif()
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()
endif()
target_sources(omohclient INTERFACE ${SOURCES_CLIENT} ${SOURCES_UILIB})
add_subdirectory("../libmad-0.15.1b" "./libmad")
target_link_libraries(omohclient INTERFACE libmad)
+4
View File
@@ -334,6 +334,9 @@ writing the actual data can begin
*/
qboolean CL_OpenAVIForWriting( const char *fileName )
{
return qfalse;
// Removed in OPM
#if 0
if( afd.fileOpen )
return qfalse;
@@ -425,6 +428,7 @@ qboolean CL_OpenAVIForWriting( const char *fileName )
afd.fileOpen = qtrue;
return qtrue;
#endif
}
/*
+42 -7
View File
@@ -395,8 +395,8 @@ Set up argc/argv for the given command
===================
*/
qboolean CL_GetServerCommand( int serverCommandNumber, qboolean differentServer ) {
char *s;
char *cmd;
char *s;
char *cmd;
static char bigConfigString[BIG_INFO_STRING];
// if we have irretrievably lost a reliable command, drop the connection
@@ -421,9 +421,39 @@ qboolean CL_GetServerCommand( int serverCommandNumber, qboolean differentServer
Com_DPrintf( "serverCommand: %i : %s\n", serverCommandNumber, s );
}
Cmd_TokenizeString( s );
Cmd_TokenizeString(s);
cmd = Cmd_Argv(0);
// Readded in OPM (from ioquake)
// Configstring big buffer
if (!strcmp(cmd, "bcs0")) {
Com_sprintf(bigConfigString, BIG_INFO_STRING, "cs %s \"%s", Cmd_Argv(1), Cmd_Argv(2));
return qfalse;
}
if (!strcmp(cmd, "bcs1")) {
s = Cmd_Argv(2);
if (strlen(bigConfigString) + strlen(s) >= BIG_INFO_STRING) {
Com_Error(ERR_DROP, "bcs exceeded BIG_INFO_STRING");
}
strcat(bigConfigString, s);
return qfalse;
}
if (!strcmp(cmd, "bcs2")) {
s = Cmd_Argv(2);
if (strlen(bigConfigString) + strlen(s) + 1 >= BIG_INFO_STRING) {
Com_Error(ERR_DROP, "bcs exceeded BIG_INFO_STRING");
}
strcat(bigConfigString, s);
strcat(bigConfigString, "\"");
s = bigConfigString;
// reparse
Cmd_TokenizeString(s);
cmd = Cmd_Argv(0);
}
return CL_ProcessServerCommand(s, cmd, differentServer);
}
@@ -435,10 +465,10 @@ CL_CM_LoadMap
Just adds default parameters that cgame doesn't need to know about
====================
*/
void CL_CM_LoadMap( const char *mapname ) {
int checksum;
CM_LoadMap( mapname, qtrue, &checksum );
void CL_CM_LoadMap( const char *mapname, int *checksum ) {
CM_LoadMap( mapname, qtrue, checksum );
// prepare world vis data
re.SetWorldVisData(CM_VisibilityPointer());
}
/*
@@ -580,6 +610,7 @@ void CL_InitCGameDLL( clientGameImport_t *cgi, clientGameExport_t **cge ) {
cgi->Printf = Com_Printf;
cgi->DPrintf = Com_DPrintf;
cgi->DebugPrintf = Com_DebugPrintf;
cgi->Malloc = CL_CG_Malloc;
cgi->Free = CL_CG_Free;
@@ -605,6 +636,8 @@ void CL_InitCGameDLL( clientGameImport_t *cgi, clientGameExport_t **cge ) {
cgi->FS_FreeFile = FS_FreeFile;
cgi->FS_WriteFile = FS_WriteFile;
cgi->FS_WriteTextFile = FS_WriteTextFile;
cgi->FS_ListFilteredFiles = FS_ListFilteredFiles;
cgi->FS_FreeFileList = FS_FreeFileList;
cgi->SendConsoleCommand = Cbuf_AddText;
@@ -676,9 +709,11 @@ void CL_InitCGameDLL( clientGameImport_t *cgi, clientGameExport_t **cge ) {
cgi->R_RegisterModel = re.RegisterModel;
cgi->R_SpawnEffectModel = re.SpawnEffectModel;
cgi->R_RegisterServerModel = re.RegisterServerModel;
cgi->R_GetModelName = re.GetModelName;
cgi->R_UnregisterServerModel = re.UnregisterServerModel;
cgi->R_RegisterShader = re.RegisterShader;
cgi->R_RegisterShaderNoMip = re.RegisterShaderNoMip;
cgi->R_GetShaderName = re.GetShaderName;
cgi->R_AddRefEntityToScene = re.AddRefEntityToScene;
cgi->R_AddRefSpriteToScene = re.AddRefSpriteToScene;
+9 -2
View File
@@ -1091,6 +1091,8 @@ static void RoQReset( void ) {
static void RoQInterrupt(void)
{
// Removed in OPM
#if 0
byte *framedata;
short sbuf[32768];
int ssize;
@@ -1214,6 +1216,7 @@ 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
}
/******************************************************************************
@@ -1397,6 +1400,9 @@ 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;
@@ -1478,6 +1484,7 @@ int CIN_PlayCinematic( const char *arg, int x, int y, int w, int h, int systemBi
RoQShutdown();
return -1;
#endif
}
void CIN_SetExtents (int handle, int x, int y, int w, int h) {
@@ -1612,7 +1619,7 @@ void CL_PlayCinematic_f(void) {
bits |= CIN_loop;
}
S_StopAllSounds( qtrue );
S_StopAllSounds2( qtrue );
CL_handle = CIN_PlayCinematic( arg, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, bits );
if (CL_handle >= 0) {
@@ -1639,7 +1646,7 @@ void SCR_RunCinematic (void)
void SCR_StopCinematic(void) {
if (CL_handle >= 0 && CL_handle < MAX_VIDEO_HANDLES) {
CIN_StopCinematic(CL_handle);
S_StopAllSounds( qtrue );
S_StopAllSounds2( qtrue );
CL_handle = -1;
}
}
+8
View File
@@ -575,6 +575,14 @@ void CL_MouseMove( usercmd_t *cmd ) {
cl.viewangles[PITCH] += m_pitch->value * my;
else
cmd->forwardmove = ClampChar(cmd->forwardmove - m_forward->value * my);
if (!isfinite(cl.viewangles[PITCH]) || !isfinite(cl.viewangles[YAW])) {
Com_Printf("Invalid client viewangles encountered!\n");
Com_Printf("cgameSensitivity: %f - mx: %f - my: %f - m_pitch: %f - m_yaw: %f", cgameSensitivity, mx, my, m_pitch->value, m_yaw->value);
Com_Printf("Resetting client viewangles");
cl.viewangles[PITCH] = 0;
cl.viewangles[YAW] = 0;
}
}
/*
+973 -130
View File
File diff suppressed because it is too large. Load diff
+173 -150
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -20,175 +20,198 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __CL_INV_H__
#define __CL_INV_H__
#pragma once
typedef enum { INV_MOVE_NONE, INV_MOVE_BOB, INV_MOVE_SPIN } inv_move_type;
typedef enum { INV_CASCADE_LEFT, INV_CASCADE_RIGHT } inv_cascade_type;
typedef enum { INV_HUDANGLES_BASE, INV_HUDANGLES_COMPASS, INV_HUDANGLES_COMPASS_NEEDLE } inv_hudangles_type;
typedef enum {
INV_MOVE_NONE,
INV_MOVE_BOB,
INV_MOVE_SPIN
} inv_move_type;
class item_properties_t : public Class {
public:
float scale;
Vector angles;
Vector angledeltas;
Vector rotateoffset;
Vector offset;
inv_move_type move;
str model;
str anim;
};
typedef enum {
INV_ALIGN_NONE,
INV_ALIGN_LEFT,
INV_ALIGN_RIGHT
} inv_align_type;
class inventory_item_t : public Class {
public:
str name;
str ammoname;
int equip;
int width;
int height;
int barwidth;
int barheight;
int baroffsetY;
int baroffsetX;
float modelWindowX;
float modelWindowY;
float modelWindowWidth;
float modelWindowHeight;
bool selShaderOnTop;
bool checkammo;
str command;
inv_hudangles_type anglesType;
item_properties_t hudprops;
item_properties_t invprops;
UIReggedMaterial *bgshader;
UIReggedMaterial *barshader;
UIReggedMaterial *selshader;
};
typedef enum {
INV_CASCADE_LEFT,
INV_CASCADE_RIGHT
} inv_cascade_type;
class inventory_type_t {
public:
str name;
bool bg_tile;
UIReggedMaterial *texture;
UIReggedMaterial *bg;
UIReggedMaterial *hoverTexture;
UIReggedMaterial *selTexture;
Container<inventory_item_t *> items;
typedef enum {
INV_HUDANGLES_BASE,
INV_HUDANGLES_COMPASS,
INV_HUDANGLES_COMPASS_NEEDLE
} inv_hudangles_type;
int IndexOfItemPtr( inventory_item_t *item );
};
inline
int inventory_type_t::IndexOfItemPtr( inventory_item_t *item )
class item_properties_t : public Class
{
for( int i = items.NumObjects(); i > 0; i-- )
{
if( items.ObjectAt( i ) == item )
{
return i;
}
}
public:
float scale;
Vector angles;
Vector angledeltas;
Vector rotateoffset;
Vector offset;
inv_move_type move;
str model;
str anim;
};
return 0;
class inventory_item_t : public Class
{
public:
str name;
str ammoname;
int equip;
int width;
int height;
int barwidth;
int barheight;
int baroffsetY;
int baroffsetX;
float modelWindowX;
float modelWindowY;
float modelWindowWidth;
float modelWindowHeight;
bool selShaderOnTop;
bool checkammo;
str command;
inv_hudangles_type anglesType;
item_properties_t hudprops;
item_properties_t invprops;
UIReggedMaterial *bgshader;
UIReggedMaterial *barshader;
UIReggedMaterial *selshader;
};
class inventory_type_t
{
public:
str name;
bool bg_tile;
UIReggedMaterial *texture;
UIReggedMaterial *bg;
UIReggedMaterial *hoverTexture;
UIReggedMaterial *selTexture;
Container<inventory_item_t *> items;
int IndexOfItemPtr(inventory_item_t *item);
};
inline int inventory_type_t::IndexOfItemPtr(inventory_item_t *item)
{
for (int i = items.NumObjects(); i > 0; i--) {
if (items.ObjectAt(i) == item) {
return i;
}
}
return 0;
}
class inventory_t {
class inventory_t
{
public:
int typewidth;
int typeheight;
int horizoffset;
int vertoffset;
int align;
inv_cascade_type cascade;
str selectsound;
str rejectsound;
str changesound;
Container<inventory_type_t *> types;
int typewidth;
int typeheight;
int horizoffset;
int vertoffset;
inv_align_type align;
inv_cascade_type cascade;
str selectsound;
str rejectsound;
str changesound;
Container<inventory_type_t *> types;
void Clear() { types.ClearObjectList(); }
public:
inventory_t();
~inventory_t();
inventory_t(const inventory_t& other);
inventory_t& operator=(const inventory_t& other);
void Clear();
};
class invlistener : public Listener {
class invlistener : public Listener
{
protected:
inventory_t *inv;
inventory_type_t *curtype;
inventory_item_t *curitem;
int defaultWidth;
int defaultHeight;
int defaultBarWidth;
int defaultBarHeight;
int defaultBarOffsetX;
int defaultBarOffsetY;
inventory_t *inv;
inventory_type_t *curtype;
inventory_item_t *curitem;
int defaultWidth;
int defaultHeight;
int defaultBarWidth;
int defaultBarHeight;
int defaultBarOffsetX;
int defaultBarOffsetY;
public:
CLASS_PROTOTYPE( invlistener );
CLASS_PROTOTYPE(invlistener);
protected:
void verify_curitem( void );
void verify_curtype( void );
void verify_one_arg( Event *ev );
void verify_curitem(void);
void verify_curtype(void);
void verify_one_arg(Event *ev);
public:
invlistener( inventory_t *i );
invlistener();
invlistener(inventory_t *i);
invlistener();
bool Load( Script& script );
void InvSelectSound( Event *ev );
void InvRejectSound( Event *ev );
void InvChangeSound( Event *ev );
void InvWidth( Event *ev );
void InvHeight( Event *ev );
void InvHorizOffset( Event *ev );
void InvVertOffset( Event *ev );
void InvAlign( Event *ev );
void InvCascade( Event *ev );
void Typedef( Event *ev );
void OpenBrace( Event *ev );
void CloseBrace( Event *ev );
void ButtonShader( Event *ev );
void HoverShader( Event *ev );
void SelShader( Event *ev );
void Background( Event *ev );
void BackgroundTile( Event *ev );
void Width( Event *ev );
void Height( Event *ev );
void BarWidth( Event *ev );
void BarHeight( Event *ev );
void BarOffsetX( Event *ev );
void BarOffsetY( Event *ev );
void Item( Event *ev );
void Ammo( Event *ev );
void Equip( Event *ev );
void CheckAmmo( Event *ev );
void Command( Event *ev );
void BGShader( Event *ev );
void BarShader( Event *ev );
void SelItemShader( Event *ev );
void SelItemShaderOnTop( Event *ev );
void RotateOffset( Event *ev );
void Offset( Event *ev );
void Model( Event *ev );
void Anim( Event *ev );
void Scale( Event *ev );
void Angles( Event *ev );
void AngleDeltas( Event *ev );
void Move( Event *ev );
void ModelWindow( Event *ev );
void HudRotateOffset( Event *ev );
void HudOffset( Event *ev );
void HudModel( Event *ev );
void HudAnim( Event *ev );
void HudScale( Event *ev );
void HudAngles( Event *ev );
void HudAngleDeltas( Event *ev );
void HudMove( Event *ev );
void HudCompassAngles( Event *ev );
void HudCompassNeedleAngles( Event *ev );
bool Load(Script& script);
void InvSelectSound(Event *ev);
void InvRejectSound(Event *ev);
void InvChangeSound(Event *ev);
void InvWidth(Event *ev);
void InvHeight(Event *ev);
void InvHorizOffset(Event *ev);
void InvVertOffset(Event *ev);
void InvAlign(Event *ev);
void InvCascade(Event *ev);
void Typedef(Event *ev);
void OpenBrace(Event *ev);
void CloseBrace(Event *ev);
void ButtonShader(Event *ev);
void HoverShader(Event *ev);
void SelShader(Event *ev);
void Background(Event *ev);
void BackgroundTile(Event *ev);
void Width(Event *ev);
void Height(Event *ev);
void BarWidth(Event *ev);
void BarHeight(Event *ev);
void BarOffsetX(Event *ev);
void BarOffsetY(Event *ev);
void Item(Event *ev);
void Ammo(Event *ev);
void Equip(Event *ev);
void CheckAmmo(Event *ev);
void Command(Event *ev);
void BGShader(Event *ev);
void BarShader(Event *ev);
void SelItemShader(Event *ev);
void SelItemShaderOnTop(Event *ev);
void RotateOffset(Event *ev);
void Offset(Event *ev);
void Model(Event *ev);
void Anim(Event *ev);
void Scale(Event *ev);
void Angles(Event *ev);
void AngleDeltas(Event *ev);
void Move(Event *ev);
void ModelWindow(Event *ev);
void HudRotateOffset(Event *ev);
void HudOffset(Event *ev);
void HudModel(Event *ev);
void HudAnim(Event *ev);
void HudScale(Event *ev);
void HudAngles(Event *ev);
void HudAngleDeltas(Event *ev);
void HudMove(Event *ev);
void HudCompassAngles(Event *ev);
void HudCompassNeedleAngles(Event *ev);
};
bool CL_LoadInventory( const char *filename, inventory_t *inv );
inventory_item_t *CL_GetInvItemByName( inventory_t *inv, const char *name );
qboolean CL_HasInventoryItem( const char *name );
void CL_AmmoCount( const char *name, int *ammo_count, int *max_ammo_count );
#endif // __CL_INV_H__
bool CL_LoadInventory(const char *filename, inventory_t *inv);
inventory_item_t *CL_GetInvItemByName(inventory_t *inv, const char *name);
qboolean CL_HasInventoryItem(const char *name);
void CL_AmmoCount(const char *name, int *ammo_count, int *max_ammo_count);
File diff suppressed because it is too large. Load diff
+81 -58
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -20,79 +20,102 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __CL_INVRENDER_H__
#define __CL_INVRENDER_H__
#pragma once
class FakkInventory;
typedef enum { selectsound, rejectsound, changesound } invsound_t;
class FakkItemList : public UIWidget {
typedef enum {
selectsound,
rejectsound,
changesound
} invsound_t;
class FakkItemList : public UIWidget
{
protected:
inventory_type_t *type;
uipopup_describe m_describe[ 10 ];
inventory_item_t *m_hoveritem;
inventory_item_t *m_lastmenuitem;
FakkInventory *m_parent;
float m_hovertop;
inventory_type_t *type;
uipopup_describe m_describe[10];
inventory_item_t *m_hoveritem;
inventory_item_t *m_lastmenuitem;
FakkInventory *m_parent;
float m_hovertop;
public:
CLASS_PROTOTYPE( FakkItemList );
CLASS_PROTOTYPE(FakkItemList);
FakkItemList();
~FakkItemList();
FakkItemList();
~FakkItemList();
void VerifyItemUp( inventory_item_t *item, qboolean warpmouse );
void setType( inventory_type_t *t );
void Create( float x, float y, FakkInventory *parent );
bool HasAnyItems( void );
void Draw( void ) override;
void OnLeftMouseDown( Event *ev );
void OnRightMouseDown( Event *ev );
void OnLeftMouseUp( Event *ev );
void OnRightMouseUp( Event *ev );
void OnMouseMove( Event *ev );
void OnMouseEnter( Event *ev );
void OnMouseLeave( Event *ev );
void OnMenuKilled( Event *ev );
void EquipItem( Event *ev );
void VerifyItemUp(inventory_item_t *item, qboolean warpmouse);
void setType(inventory_type_t *t);
void Create(float x, float y, FakkInventory *parent);
bool HasAnyItems(void);
void Draw(void) override;
void OnLeftMouseDown(Event *ev);
void OnRightMouseDown(Event *ev);
void OnLeftMouseUp(Event *ev);
void OnRightMouseUp(Event *ev);
void OnMouseMove(Event *ev);
void OnMouseEnter(Event *ev);
void OnMouseLeave(Event *ev);
void OnMenuKilled(Event *ev);
void EquipItem(Event *ev);
inventory_item_t *getHoverItem() const;
};
class FakkInventory : public UIWidget {
class FakkInventory : public UIWidget
{
protected:
inventory_t *m_inv;
SafePtr<FakkItemList> m_currentlist;
inventory_type_t *m_currenttype;
int m_currentitemnum;
inventory_t *m_inv;
SafePtr<FakkItemList> m_currentlist;
inventory_type_t *m_currenttype;
int m_currentitemnum;
public:
CLASS_PROTOTYPE( FakkInventory );
protected:
void VerifyItemUp( inventory_item_t *item, qboolean warpmouse );
CLASS_PROTOTYPE(FakkInventory);
public:
FakkInventory();
~FakkInventory();
qboolean m_mouse_active;
void setInventory( inventory_t *i );
void Draw( void ) override;
void OnMouseMove( Event *ev );
void OnMouseLeave( Event *ev );
void OnMouseEnter( Event *ev );
void OnMouseDown( Event *ev );
void WarpTo( const char *name );
void WarpTo( int slotnum );
void NextItem( void );
void PrevItem( void );
qboolean isDying( void );
qboolean KeyEvent( int key, unsigned int time ) override;
void PlaySound( invsound_t type );
void Timeout( Event *ev );
void ChangeItem( int sign );
int FindFirstItem( int itemindex, int sign );
protected:
void VerifyTypeUp(inventory_type_t *t, qboolean warpmouse);
public:
FakkInventory();
~FakkInventory();
void setInventory(inventory_t *i);
void Draw(void) override;
void OnMouseMove(Event *ev);
void OnMouseLeave(Event *ev);
void OnMouseEnter(Event *ev);
void OnMouseDown(Event *ev);
void WarpTo(const char *name);
void WarpTo(int slotnum);
void NextItem(void);
void PrevItem(void);
qboolean isDying(void);
qboolean KeyEvent(int key, unsigned int time) override;
void PlaySound(invsound_t type);
void Timeout(Event *ev);
void ChangeItem(int sign);
int FindFirstItem(int itemindex, int sign);
};
void CL_Draw3DModel( float x, float y, float w, float h, qhandle_t model, vec3_t origin, vec3_t rotateoffset, vec3_t offset, vec3_t angle, vec3_t color, str anim );
qboolean UI_CloseInventory( void );
void CL_Draw3DModel(
float x,
float y,
float w,
float h,
qhandle_t model,
vec3_t origin,
vec3_t rotateoffset,
vec3_t offset,
vec3_t angle,
vec3_t color,
str anim
);
#endif // __CL_INVRENDER_H__
void UI_DoInventory(qboolean activate_mouse);
qboolean UI_CloseInventory(void);
+927 -915
View File
File diff suppressed because it is too large. Load diff
+380 -213
View File
File diff suppressed because it is too large. Load diff
+2 -36
View File
@@ -514,40 +514,6 @@ static void CL_ParseServerInfo(void)
sizeof(clc.sv_dlURL));
}
char* MSG_ReadGameStateChar_ver_15(msg_t* msg) {
return MSG_ReadScrambledBigString(msg);
}
float MSG_ReadServerFrameTime_ver_15(msg_t* msg) {
return MSG_ReadFloat(msg);
}
char* MSG_ReadGameStateChar_ver_6(msg_t* msg) {
return MSG_ReadString(msg);
}
float MSG_ReadServerFrameTime_ver_6(msg_t* msg) {
return 1.f / atof(Info_ValueForKey(cl.gameState.stringData + cl.gameState.stringOffsets[CS_SYSTEMINFO], "sv_fps"));
}
char* MSG_ReadGameStateChar(msg_t* msg) {
if (MSG_IsProtocolVersion15()) {
return MSG_ReadGameStateChar_ver_15(msg);
} else {
// smaller below version 15
return MSG_ReadGameStateChar_ver_6(msg);
}
}
float MSG_ReadServerFrameTime(msg_t* msg) {
if (MSG_IsProtocolVersion15()) {
return MSG_ReadServerFrameTime_ver_15(msg);
} else {
// smaller below version 15
return MSG_ReadServerFrameTime_ver_6(msg);
}
}
/*
==================
CL_ParseGamestate
@@ -591,7 +557,7 @@ void CL_ParseGamestate( msg_t *msg ) {
if (csNum < 0 || csNum >= MAX_CONFIGSTRINGS) {
Com_Error(ERR_DROP, "configstring > MAX_CONFIGSTRINGS");
}
s = MSG_ReadGameStateChar(msg);
s = MSG_ReadScrambledBigString(msg);
len = strlen(s);
if (len + 1 + cl.gameState.dataCount > MAX_GAMESTATE_CHARS) {
@@ -620,7 +586,7 @@ void CL_ParseGamestate( msg_t *msg ) {
clc.clientNum = MSG_ReadLong(msg);
// read the checksum feed
clc.checksumFeed = MSG_ReadLong( msg );
cls.serverFrameTime = MSG_ReadServerFrameTime(msg);
cls.serverFrameTime = MSG_ReadServerFrameTime(msg, &cl.gameState);
// parse serverId and other cvars
CL_SystemInfoChanged();
+3927 -4030
View File
File diff suppressed because it is too large. Load diff
+85 -68
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -20,112 +20,129 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __CL_UI_H__
#define __CL_UI_H__
#pragma once
#include "../uilib/ui_extern.h"
#include "../uilib/uiwidget.h"
typedef struct {
UIReggedMaterial *loading;
UIReggedMaterial *loading;
} static_media_t;
//
// cvars
//
extern cvar_t* ui_health_start;
extern cvar_t* ui_health_end;
extern cvar_t* sound_overlay;
extern cvar_t *ui_health_start;
extern cvar_t *ui_health_end;
extern cvar_t *sound_overlay;
//
// initialization
//
void CL_FillUIDef( void );
void CL_InitializeUI( void );
void CL_ShutdownUI( void );
void CL_FillUIDef(void);
void CL_InitializeUI(void);
void CL_ShutdownUI(void);
//
// general ui stuff
//
extern inventory_t client_inv;
extern bind_t client_bind;
extern cvar_t* cl_greenfps;
extern bind_t client_bind;
extern cvar_t *cl_greenfps;
const char *CvarGetForUI( const char *name, const char *defval );
void UI_ClearState( void );
void CL_BeginRegistration( void );
void CL_EndRegistration(void);
const char *CvarGetForUI(const char *name, const char *defval);
void UI_ClearState(void);
void CL_BeginRegistration(void);
void CL_EndRegistration(void);
//
// menu
//
extern Menu *ui_pLoadingMenu;
void UI_ShowMenu( const char *name, qboolean bForce );
void UI_HideMenu( const char *name, qboolean bForce );
void UI_ForceMenuOff( bool force );
void UI_PushMenu( const char *name );
void UI_ForceMenu( const char *name );
qboolean UI_BindActive( void );
void UI_SetReturnMenuToCurrent(void);
void UI_ActivateView3D( void );
void UI_MenuEscape( const char *name );
void UI_CreateScoreboard( void );
qboolean UI_MenuActive( void );
qboolean UI_MenuUp( void );
void UI_FocusMenuIfExists(void);
void UI_DrawConnect( void );
void UI_CreateDialog( const char *title, char *cvarname, const char *command, const char *cancelCommand, int width, int height, const char *shader, const char *okshader, const char *cancelshader );
void UI_ToggleDMConsole( int iMode );
void UI_ShowScoreboard_f( const char *pszMenuName );
void UI_HideScoreboard_f( void );
void UI_SetScoreBoardItem( int iItemNumber,
const char *pszData1, const char *pszData2, const char *pszData3, const char *pszData4,
const char *pszData5, const char *pszData6, const char *pszData7, const char *pszData8,
const vec4_t pTextColor, const vec4_t pBackColor, qboolean bIsHeader );
void UI_DeleteScoreBoardItems( int iMaxIndex );
void UI_ShowMenu(const char *name, qboolean bForce);
void UI_HideMenu(const char *name, qboolean bForce);
void UI_ForceMenuOff(bool force);
void UI_PushMenu(const char *name);
void UI_ForceMenu(const char *name);
qboolean UI_BindActive(void);
void UI_SetReturnMenuToCurrent(void);
void UI_ActivateView3D(void);
void UI_MenuEscape(const char *name);
void UI_CreateScoreboard(void);
qboolean UI_MenuActive(void);
qboolean UI_MenuUp(void);
void UI_FocusMenuIfExists(void);
void UI_DrawConnect(void);
void UI_CreateDialog(
const char *title,
char *cvarname,
const char *command,
const char *cancelCommand,
int width,
int height,
const char *shader,
const char *okshader,
const char *cancelshader
);
void UI_ToggleDMConsole(int iMode);
void UI_ShowScoreboard_f(const char *pszMenuName);
void UI_HideScoreboard_f(void);
void UI_SetScoreBoardItem(
int iItemNumber,
const char *pszData1,
const char *pszData2,
const char *pszData3,
const char *pszData4,
const char *pszData5,
const char *pszData6,
const char *pszData7,
const char *pszData8,
const vec4_t pTextColor,
const vec4_t pBackColor,
qboolean bIsHeader
);
void UI_DeleteScoreBoardItems(int iMaxIndex);
//
// ressources
//
void UI_BeginLoad( const char *pszMapName );
void UI_EndLoad( void );
void UI_AbortLoad( void );
void UI_BeginLoadResource( void );
void UI_EndLoadResource( void );
void UI_EndLoadResource( const char *name );
qboolean UI_IsResourceLoaded( const char *name );
void UI_RegisterLoadResource( const char *name );
void UI_ClearResource( void );
void UI_LoadResource( const char *name );
void UI_BeginLoad(const char *pszMapName);
void UI_EndLoad(void);
void UI_AbortLoad(void);
void UI_BeginLoadResource(void);
void UI_EndLoadResource(void);
void UI_EndLoadResource(const char *name);
qboolean UI_IsResourceLoaded(const char *name);
void UI_RegisterLoadResource(const char *name);
void UI_ClearResource(void);
void UI_LoadResource(const char *name);
//
// windows
//
void UI_DeactiveFloatingWindows( void );
void UI_DeactiveFloatingWindows(void);
//
// console
//
void UI_OpenConsole( void );
qboolean UI_ConsoleIsVisible( void );
qboolean UI_ConsoleIsOpen( void );
void UI_CloseConsole( void );
void UI_ToggleConsole( void );
void UI_OpenDMConsole( int iMode );
void UI_CloseDMConsole( void );
void UI_ToggleDMConsole( int iMode );
void UI_OpenDeveloperConsole( void );
void UI_CloseDeveloperConsole( void );
void UI_PrintConsole(const char* msg);
void UI_OpenConsole(void);
qboolean UI_ConsoleIsVisible(void);
qboolean UI_ConsoleIsOpen(void);
void UI_CloseConsole(void);
void UI_ToggleConsole(void);
void UI_OpenDMConsole(int iMode);
void UI_CloseDMConsole(void);
void UI_ToggleDMConsole(int iMode);
void UI_OpenDeveloperConsole(void);
void UI_CloseDeveloperConsole(void);
void UI_PrintConsole(const char *msg);
//
// callbacks
//
void UI_Update( void );
void UI_ServerLoaded( void );
void UI_ResolutionChange( void );
void UI_KeyEvent( int key, unsigned int time );
void UI_CharEvent( int ch );
#endif /* __CL_UI_H__ */
void UI_Update(void);
void UI_ServerLoaded(void);
void UI_ResolutionChange(void);
void UI_KeyEvent(int key, unsigned int time);
void UI_CharEvent(int ch);
+430 -182
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -24,281 +24,529 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
bind_t::bind_t()
{
// FIXME: stub
int i;
commandwidth = 100;
commandheight = 20;
primarykeywidth = 100;
primarykeyheight = 20;
alternatekeywidth = 100;
alternatekeyheight = 20;
fillwidth = 16;
fillmaterial = NULL;
for (i = 0; i < ARRAY_LEN(headermats); i++) {
headermats[i] = NULL;
}
}
bind_t::~bind_t()
{
Clear();
Clear();
}
void bind_t::Clear
(
void
)
void bind_t::Clear(void)
{
// FIXME: stub
for (int i = binds.NumObjects(); i > 0; i--) {
bind_item_t *bi;
bi = binds.ObjectAt(i);
binds.RemoveObjectAt(i);
if (bi) {
delete bi;
}
}
}
CLASS_DECLARATION( Listener, bindlistener, NULL )
{
{ NULL, NULL }
Event EV_Bind_Header
(
"header",
EV_DEFAULT,
"iss",
"column_num name material",
"Set the header of each column"
);
Event EV_Bind_Width
(
"bind_width",
EV_DEFAULT,
"i",
"width",
"Width of the bind menu"
);
Event EV_Bind_Height
(
"bind_height",
EV_DEFAULT,
"i",
"height",
"Height of the bind menu"
);
Event EV_Bind_FillWidth
(
"bind_fillwidth",
EV_DEFAULT,
"iS",
"width material",
"Width of the filling between widgets"
);
Event EV_Bind_CommandWidth
(
"bind_commandwidth",
EV_DEFAULT,
"i",
"width",
"Width of the command item"
);
Event EV_Bind_CommandHeight
(
"bind_commandheight",
EV_DEFAULT,
"i",
"height",
"Height of the command item"
);
Event EV_Bind_PrimaryKeyWidth
(
"bind_primarykeywidth",
EV_DEFAULT,
"i",
"width",
"Width of the primary key item"
);
Event EV_Bind_PrimaryKeyHeight
(
"bind_primarykeyheight",
EV_DEFAULT,
"i",
"height",
"Height of the primary key item"
);
Event EV_Bind_AlternateKeyWidth
(
"bind_alternatekeywidth",
EV_DEFAULT,
"i",
"width",
"Width of the alternate key item"
);
Event EV_Bind_AlternateKeyHeight
(
"bind_alternatekeyheight",
EV_DEFAULT,
"i",
"height",
"Height of the alternate key item"
);
Event EV_Bind_NewItem
(
"binditem",
EV_DEFAULT,
"ss",
"name command",
"Create a new bind item in the interface"
);
Event EV_Bind_Align
(
"align",
EV_DEFAULT,
"sSSSSS",
"arg1 arg2 arg3 arg4 arg5 arg6",
"Set the alignment on the bind menu"
);
Event EV_Bind_TitleForegroundColor
(
"titleforegroundcolor",
EV_DEFAULT,
"ffff",
"r g b a",
"Set the color for the title foreground"
);
Event EV_Bind_TitleBackgroundColor
(
"titlebackgroundcolor",
EV_DEFAULT,
"ffff",
"r g b a",
"Set the color for the title background"
);
Event EV_Bind_InactiveForegroundColor
(
"inactiveforegroundcolor",
EV_DEFAULT,
"ffff",
"r g b a",
"Set the color for the inactive button foreground"
);
Event EV_Bind_InactiveBackgroundColor
(
"inactivebackgroundcolor",
EV_DEFAULT,
"ffff",
"r g b a",
"Set the color for the inactive button background"
);
Event EV_Bind_ActiveForegroundColor
(
"activeforegroundcolor",
EV_DEFAULT,
"ffff",
"r g b a",
"Set the color for the active button foreground"
);
Event EV_Bind_ActiveBackgroundColor
(
"activebackgroundcolor",
EV_DEFAULT,
"ffff",
"r g b a",
"Set the color for the active button background"
);
Event EV_Bind_ActiveBorderColor
(
"activebordercolor",
EV_DEFAULT,
"ffff",
"r g b a",
"Set the color for the active button border"
);
Event EV_Bind_HighlightForegroundColor
(
"highlightforegroundcolor",
EV_DEFAULT,
"ffff",
"r g b a",
"Set the color for the highlighted button foreground"
);
Event EV_Bind_HighlightBackgroundColor
(
"highlightbackgroundcolor",
EV_DEFAULT,
"ffff",
"r g b a",
"Set the color for the highlighted button background"
);
Event EV_Bind_SelectForegroundColor
(
"selectforegroundcolor",
EV_DEFAULT,
"ffff",
"r g b a",
"Set the color for the selected button foreground"
);
Event EV_Bind_SelectBackgroundColor
(
"selectbackgroundcolor",
EV_DEFAULT,
"ffff",
"r g b a",
"Set the color for the selected button background"
);
Event EV_Bind_ChangeSound
(
"changesound",
EV_DEFAULT,
"s",
"soundname",
"Set the name of the sound to play when the highlighted item changes"
);
Event EV_Bind_ActiveSound
(
"activesound",
EV_DEFAULT,
"s",
"soundname",
"Set the name of the sound to play when the item is made active"
);
Event EV_Bind_EnterSound
(
"entersound",
EV_DEFAULT,
"s",
"soundname",
"Set the name of the sound to play when the key is entered"
);
CLASS_DECLARATION(Listener, bindlistener, NULL) {
{&EV_Bind_Width, &bindlistener::Width },
{&EV_Bind_Height, &bindlistener::Height },
{&EV_Bind_FillWidth, &bindlistener::FillWidth },
{&EV_Bind_CommandWidth, &bindlistener::CommandWidth },
{&EV_Bind_CommandHeight, &bindlistener::CommandHeight },
{&EV_Bind_PrimaryKeyWidth, &bindlistener::PrimaryKeyWidth },
{&EV_Bind_PrimaryKeyHeight, &bindlistener::PrimaryKeyHeight },
{&EV_Bind_AlternateKeyWidth, &bindlistener::AlternateKeyWidth },
{&EV_Bind_AlternateKeyHeight, &bindlistener::AlternateKeyHeight },
{&EV_Bind_Header, &bindlistener::Header },
{&EV_Bind_NewItem, &bindlistener::NewItem },
{&EV_Bind_Align, &bindlistener::Align },
{&EV_Bind_TitleForegroundColor, &bindlistener::TitleForegroundColor },
{&EV_Bind_TitleBackgroundColor, &bindlistener::TitleBackgroundColor },
{&EV_Bind_InactiveForegroundColor, &bindlistener::InactiveForegroundColor },
{&EV_Bind_InactiveBackgroundColor, &bindlistener::InactiveBackgroundColor },
{&EV_Bind_ActiveForegroundColor, &bindlistener::ActiveForegroundColor },
{&EV_Bind_ActiveBackgroundColor, &bindlistener::ActiveBackgroundColor },
{&EV_Bind_ActiveBorderColor, &bindlistener::ActiveBorderColor },
{&EV_Bind_HighlightForegroundColor, &bindlistener::HighlightForegroundColor},
{&EV_Bind_HighlightBackgroundColor, &bindlistener::HighlightBackgroundColor},
{&EV_Bind_SelectForegroundColor, &bindlistener::SelectForegroundColor },
{&EV_Bind_SelectBackgroundColor, &bindlistener::SelectBackgroundColor },
{&EV_Bind_ChangeSound, &bindlistener::ChangeSound },
{&EV_Bind_ActiveSound, &bindlistener::ActiveSound },
{&EV_Bind_EnterSound, &bindlistener::EnterSound },
{NULL, NULL }
};
bindlistener::bindlistener()
bindlistener::bindlistener() {}
bindlistener::bindlistener(bind_t *b)
{
bind = b;
}
bindlistener::bindlistener
(
bind_t *b
)
void bindlistener::Header(Event *ev)
{
bind = b;
int num;
num = ev->GetInteger(1) - 1;
if (num > ARRAY_LEN(bind_t::headers)) {
return;
}
bind->headers[num] = ev->GetString(2);
if (ev->NumArgs() > 2) {
bind->headermats[num] = uWinMan.RegisterShader(ev->GetString(3));
}
}
bool bindlistener::Load
(
Script& script
)
void bindlistener::ChangeSound(Event *ev)
{
// FIXME: stub
return false;
bind->changesound = ev->GetString(1);
}
void bindlistener::Header
(
Event *ev
)
void bindlistener::ActiveSound(Event *ev)
{
// FIXME: stub
bind->activesound = ev->GetString(1);
}
void bindlistener::Width
(
Event *ev
)
void bindlistener::EnterSound(Event *ev)
{
// FIXME: stub
bind->entersound = ev->GetString(1);
}
void bindlistener::FillWidth
(
Event *ev
)
void bindlistener::SelectForegroundColor(Event *ev)
{
// FIXME: stub
bind->selectfgcolor.r = ev->GetFloat(1);
bind->selectfgcolor.g = ev->GetFloat(2);
bind->selectfgcolor.b = ev->GetFloat(3);
bind->selectfgcolor.a = ev->GetFloat(4);
}
void bindlistener::Height
(
Event *ev
)
void bindlistener::SelectBackgroundColor(Event *ev)
{
// FIXME: stub
bind->selectbgcolor.r = ev->GetFloat(1);
bind->selectbgcolor.g = ev->GetFloat(2);
bind->selectbgcolor.b = ev->GetFloat(3);
bind->selectbgcolor.a = ev->GetFloat(4);
}
void bindlistener::CommandWidth
(
Event *ev
)
void bindlistener::TitleForegroundColor(Event *ev)
{
// FIXME: stub
bind->titlefgcolor.r = ev->GetFloat(1);
bind->titlefgcolor.g = ev->GetFloat(2);
bind->titlefgcolor.b = ev->GetFloat(3);
bind->titlefgcolor.a = ev->GetFloat(4);
}
void bindlistener::CommandHeight
(
Event *ev
)
void bindlistener::TitleBackgroundColor(Event *ev)
{
// FIXME: stub
bind->titlebgcolor.r = ev->GetFloat(1);
bind->titlebgcolor.g = ev->GetFloat(2);
bind->titlebgcolor.b = ev->GetFloat(3);
bind->titlebgcolor.a = ev->GetFloat(4);
}
void bindlistener::PrimaryKeyWidth
(
Event *ev
)
void bindlistener::ActiveBorderColor(Event *ev)
{
// FIXME: stub
bind->activebordercolor.r = ev->GetFloat(1);
bind->activebordercolor.g = ev->GetFloat(2);
bind->activebordercolor.b = ev->GetFloat(3);
bind->activebordercolor.a = ev->GetFloat(4);
}
void bindlistener::PrimaryKeyHeight
(
Event *ev
)
void bindlistener::ActiveForegroundColor(Event *ev)
{
// FIXME: stub
bind->activefgcolor.r = ev->GetFloat(1);
bind->activefgcolor.g = ev->GetFloat(2);
bind->activefgcolor.b = ev->GetFloat(3);
bind->activefgcolor.a = ev->GetFloat(4);
}
void bindlistener::AlternateKeyWidth
(
Event *ev
)
void bindlistener::ActiveBackgroundColor(Event *ev)
{
// FIXME: stub
bind->activebgcolor.r = ev->GetFloat(1);
bind->activebgcolor.g = ev->GetFloat(2);
bind->activebgcolor.b = ev->GetFloat(3);
bind->activebgcolor.a = ev->GetFloat(4);
}
void bindlistener::AlternateKeyHeight
(
Event *ev
)
void bindlistener::InactiveForegroundColor(Event *ev)
{
// FIXME: stub
bind->inactivefgcolor.r = ev->GetFloat(1);
bind->inactivefgcolor.g = ev->GetFloat(2);
bind->inactivefgcolor.b = ev->GetFloat(3);
bind->inactivefgcolor.a = ev->GetFloat(4);
}
void bindlistener::NewItem
(
Event *ev
)
void bindlistener::InactiveBackgroundColor(Event *ev)
{
// FIXME: stub
bind->inactivebgcolor.r = ev->GetFloat(1);
bind->inactivebgcolor.g = ev->GetFloat(2);
bind->inactivebgcolor.b = ev->GetFloat(3);
bind->inactivebgcolor.a = ev->GetFloat(4);
}
void bindlistener::Align
(
Event *ev
)
void bindlistener::HighlightForegroundColor(Event *ev)
{
// FIXME: stub
bind->highlightfgcolor.r = ev->GetFloat(1);
bind->highlightfgcolor.g = ev->GetFloat(2);
bind->highlightfgcolor.b = ev->GetFloat(3);
bind->highlightfgcolor.a = ev->GetFloat(4);
}
void bindlistener::TitleForegroundColor
(
Event *ev
)
void bindlistener::HighlightBackgroundColor(Event *ev)
{
// FIXME: stub
bind->highlightbgcolor.r = ev->GetFloat(1);
bind->highlightbgcolor.g = ev->GetFloat(2);
bind->highlightbgcolor.b = ev->GetFloat(3);
bind->highlightbgcolor.a = ev->GetFloat(4);
}
void bindlistener::TitleBackgroundColor
(
Event *ev
)
void bindlistener::Align(Event *ev)
{
// FIXME: stub
int i;
for (i = 1; i <= ev->NumArgs(); i++) {
str align = ev->GetString(i);
if (!str::icmp(align, "left")) {
bind->align |= WA_LEFT;
} else if (!str::icmp(align, "right")) {
bind->align |= WA_RIGHT;
} else if (!str::icmp(align, "top")) {
bind->align |= WA_TOP;
} else if (!str::icmp(align, "bottom")) {
bind->align |= WA_BOTTOM;
} else if (!str::icmp(align, "centerx")) {
bind->align |= WA_CENTERX;
} else if (!str::icmp(align, "centery")) {
bind->align |= WA_CENTERY;
}
}
}
void bindlistener::InactiveForegroundColor
(
Event *ev
)
void bindlistener::NewItem(Event *ev)
{
// FIXME: stub
bind_item_t *bt;
UIReggedMaterial *mat = NULL;
if (ev->NumArgs() > 2) {
mat = uWinMan.RegisterShader(ev->GetString(3));
}
str n = ev->GetString(1);
str c = ev->GetString(2);
bt = new bind_item_t;
bt->name = n;
bt->command = c;
bt->nameMaterial = mat;
bind->binds.AddObject(bt);
}
void bindlistener::InactiveBackgroundColor
(
Event *ev
)
void bindlistener::Width(Event *ev)
{
// FIXME: stub
bind->width = ev->GetInteger(1);
}
void bindlistener::ActiveForegroundColor
(
Event *ev
)
void bindlistener::Height(Event *ev)
{
// FIXME: stub
bind->height = ev->GetInteger(1);
}
void bindlistener::ActiveBackgroundColor
(
Event *ev
)
void bindlistener::FillWidth(Event *ev)
{
// FIXME: stub
bind->fillwidth = ev->GetInteger(1);
if (ev->NumArgs() > 1) {
bind->fillmaterial = uWinMan.RegisterShader(ev->GetString(2));
}
}
void bindlistener::ActiveBorderColor
(
Event *ev
)
void bindlistener::CommandWidth(Event *ev)
{
// FIXME: stub
bind->commandwidth = ev->GetInteger(1);
}
void bindlistener::HighlightForegroundColor
(
Event *ev
)
void bindlistener::CommandHeight(Event *ev)
{
// FIXME: stub
bind->commandheight = ev->GetInteger(1);
}
void bindlistener::HighlightBackgroundColor
(
Event *ev
)
void bindlistener::PrimaryKeyWidth(Event *ev)
{
// FIXME: stub
bind->primarykeywidth = ev->GetInteger(1);
}
void bindlistener::SelectForegroundColor
(
Event *ev
)
void bindlistener::PrimaryKeyHeight(Event *ev)
{
// FIXME: stub
bind->primarykeyheight = ev->GetInteger(1);
}
void bindlistener::SelectBackgroundColor
(
Event *ev
)
void bindlistener::AlternateKeyWidth(Event *ev)
{
// FIXME: stub
bind->alternatekeywidth = ev->GetInteger(1);
}
void bindlistener::ChangeSound
(
Event *ev
)
void bindlistener::AlternateKeyHeight(Event *ev)
{
// FIXME: stub
bind->alternatekeyheight = ev->GetInteger(1);
}
void bindlistener::ActiveSound
(
Event *ev
)
bool bindlistener::Load(Script& script)
{
// FIXME: stub
str token;
str errortext;
while (script.TokenAvailable(true)) {
token = script.GetToken(true);
if (!token.length() || !ValidEvent(token)) {
throw "invalid token";
}
Event *event = new Event(token);
while (script.TokenAvailable(false)) {
event->AddToken(script.GetToken(false));
}
ProcessEvent(event);
}
return true;
}
void bindlistener::EnterSound
(
Event *ev
)
bool CL_LoadBind(const char *filename, bind_t *bind)
{
// FIXME: stub
Script script;
bind->Clear();
bindlistener listener(bind);
script.LoadFile(filename);
// Load the bind file
return listener.Load(script);
}
+82 -88
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -20,115 +20,109 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __CL_UIBIND_H__
#define __CL_UIBIND_H__
#pragma once
class bind_item_t {
class bind_item_t
{
public:
str name;
str command;
UIReggedMaterial *nameMaterial;
str name;
str command;
UIReggedMaterial *nameMaterial;
bind_item_t();
bind_item_t( str name, str command, UIReggedMaterial *nameMaterial );
bind_item_t();
bind_item_t(str name, str command, UIReggedMaterial *nameMaterial);
};
inline
bind_item_t::bind_item_t()
inline bind_item_t::bind_item_t()
{
nameMaterial = NULL;
nameMaterial = NULL;
}
inline
bind_item_t::bind_item_t
(
str name,
str command,
UIReggedMaterial *nameMaterial
)
inline bind_item_t::bind_item_t(str name, str command, UIReggedMaterial *nameMaterial)
{
this->name = name;
this->command = command;
this->nameMaterial = nameMaterial;
this->name = name;
this->command = command;
this->nameMaterial = nameMaterial;
}
class bind_t {
class bind_t
{
public:
int width;
int height;
int fillwidth;
int commandwidth;
int commandheight;
int primarykeywidth;
int primarykeyheight;
int alternatekeywidth;
int alternatekeyheight;
int align;
UColor titlebgcolor;
UColor titlefgcolor;
UColor activefgcolor;
UColor activebgcolor;
UColor activebordercolor;
UColor inactivefgcolor;
UColor inactivebgcolor;
UColor highlightfgcolor;
UColor highlightbgcolor;
UColor selectfgcolor;
UColor selectbgcolor;
str changesound;
str activesound;
str entersound;
str headers[ 3 ];
UIReggedMaterial *headermats[ 3 ];
UIReggedMaterial *fillmaterial;
Container<bind_item_t *> binds;
int width;
int height;
int fillwidth;
int commandwidth;
int commandheight;
int primarykeywidth;
int primarykeyheight;
int alternatekeywidth;
int alternatekeyheight;
int align;
UColor titlebgcolor;
UColor titlefgcolor;
UColor activefgcolor;
UColor activebgcolor;
UColor activebordercolor;
UColor inactivefgcolor;
UColor inactivebgcolor;
UColor highlightfgcolor;
UColor highlightbgcolor;
UColor selectfgcolor;
UColor selectbgcolor;
str changesound;
str activesound;
str entersound;
str headers[3];
UIReggedMaterial *headermats[3];
UIReggedMaterial *fillmaterial;
Container<bind_item_t *> binds;
public:
bind_t();
~bind_t();
bind_t();
~bind_t();
void Clear( void );
void Clear(void);
};
class bindlistener : public Listener {
class bindlistener : public Listener
{
protected:
bind_t *bind;
bind_t *bind;
public:
CLASS_PROTOTYPE( bindlistener );
CLASS_PROTOTYPE(bindlistener);
public:
bindlistener();
bindlistener( bind_t *b );
bindlistener();
bindlistener(bind_t *b);
bool Load( Script& script );
void Header( Event *ev );
void Width( Event *ev );
void FillWidth( Event *ev );
void Height( Event *ev );
void CommandWidth( Event *ev );
void CommandHeight( Event *ev );
void PrimaryKeyWidth( Event *ev );
void PrimaryKeyHeight( Event *ev );
void AlternateKeyWidth( Event *ev );
void AlternateKeyHeight( Event *ev );
void NewItem( Event *ev );
void Align( Event *ev );
void TitleForegroundColor( Event *ev );
void TitleBackgroundColor( Event *ev );
void InactiveForegroundColor( Event *ev );
void InactiveBackgroundColor( Event *ev );
void ActiveForegroundColor( Event *ev );
void ActiveBackgroundColor( Event *ev );
void ActiveBorderColor( Event *ev );
void HighlightForegroundColor( Event *ev );
void HighlightBackgroundColor( Event *ev );
void SelectForegroundColor( Event *ev );
void SelectBackgroundColor( Event *ev );
void ChangeSound( Event *ev );
void ActiveSound( Event *ev );
void EnterSound( Event *ev );
bool Load(Script& script);
void Header(Event *ev);
void Width(Event *ev);
void FillWidth(Event *ev);
void Height(Event *ev);
void CommandWidth(Event *ev);
void CommandHeight(Event *ev);
void PrimaryKeyWidth(Event *ev);
void PrimaryKeyHeight(Event *ev);
void AlternateKeyWidth(Event *ev);
void AlternateKeyHeight(Event *ev);
void NewItem(Event *ev);
void Align(Event *ev);
void TitleForegroundColor(Event *ev);
void TitleBackgroundColor(Event *ev);
void InactiveForegroundColor(Event *ev);
void InactiveBackgroundColor(Event *ev);
void ActiveForegroundColor(Event *ev);
void ActiveBackgroundColor(Event *ev);
void ActiveBorderColor(Event *ev);
void HighlightForegroundColor(Event *ev);
void HighlightBackgroundColor(Event *ev);
void SelectForegroundColor(Event *ev);
void SelectBackgroundColor(Event *ev);
void ChangeSound(Event *ev);
void ActiveSound(Event *ev);
void EnterSound(Event *ev);
};
#endif
bool CL_LoadBind(const char* filename, bind_t* bind);
+209 -27
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -22,72 +22,254 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cl_ui.h"
CLASS_DECLARATION( USignal, FilePickerClass, NULL )
class FilePickerItem : public UIListCtrlItem
{
{ NULL, NULL }
str strings[3];
public:
FilePickerItem(const str& fileName, const str& date, const str& size);
int getListItemValue(int which) const override;
griditemtype_t getListItemType(int which) const override;
str getListItemString(int which) const override;
void DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) override;
qboolean IsHeaderEntry() const override;
};
CLASS_DECLARATION(USignal, FilePickerClass, NULL) {
{&EV_UIListBase_ItemSelected, &FilePickerClass::FileSelected },
{&EV_UIListBase_ItemDoubleClicked, &FilePickerClass::FileChosen },
{&W_Deactivated, &FilePickerClass::OnDeactivated},
{NULL, NULL }
};
FilePickerClass::FilePickerClass()
{
// FIXME: stub
window = new UIFloatingWindow();
window->Create(
NULL,
UIRect2D((cls.glconfig.vidWidth - 400) / 2, (cls.glconfig.vidHeight - 300) / 2, 400, 300),
"File Picker",
UColor(0.15f, 0.195f, 0.278f),
UHudColor
);
window->Connect(this, W_Deactivated, W_Deactivated);
listbox = new UIListCtrl();
listbox->InitFrame(window->getChildSpace(), window->getChildSpace()->getClientFrame(), 0);
listbox->setBackgroundColor(UColor(0.02f, 0.07f, 0.005f), true);
listbox->setForegroundColor(UHudColor);
listbox->AddColumn("File Name", 0, 175, false, false);
listbox->AddColumn("Date", 1, 125, false, false);
listbox->AddColumn("Size", 2, 100, true, false);
listbox->Connect(this, EV_UIListBase_ItemDoubleClicked, EV_UIListBase_ItemDoubleClicked);
listbox->Connect(this, EV_UIListBase_ItemSelected, EV_UIListBase_ItemSelected);
listbox->AllowActivate(true);
// Added in 2.0
// Don't localize elements
listbox->SetDontLocalize();
}
FilePickerClass::~FilePickerClass()
{
// FIXME: stub
if (listbox) {
delete listbox;
listbox = NULL;
}
if (window) {
delete window;
window = NULL;
}
}
void FilePickerClass::SetupFiles( void )
void FilePickerClass::Setup(
const char *root_directory, const char *current_directory, const char *ext, const char *ignore_files
)
{
// FIXME: stub
Initialize(root_directory, current_directory, ext, ignore_files);
}
void FilePickerClass::GotoParentDirectory( void )
void FilePickerClass::Initialize(
const char *root_directory, const char *current_directory, const char *ext, const char *ignore_files
)
{
// FIXME: stub
rootDirectory = root_directory;
if (rootDirectory.length() > 1 && rootDirectory[rootDirectory.length() - 1] != '/') {
rootDirectory += "/";
}
currentDirectory = current_directory;
if (currentDirectory.length() > 1 && currentDirectory[currentDirectory.length() - 1] != '/') {
currentDirectory += "/";
}
extension = ext;
ignoredFiles = ignore_files;
SetupFiles();
}
void FilePickerClass::GotoSubDirectory( str subdir )
void FilePickerClass::GotoParentDirectory(void)
{
// FIXME: stub
int i;
if (currentDirectory == rootDirectory) {
return;
}
for (i = currentDirectory.length() - 2; i > 0; i--) {
if (currentDirectory[i] == '/') {
break;
}
}
if (currentDirectory[i] == '/') {
i++;
}
currentDirectory = str(currentDirectory, 0, i);
// refresh files
SetupFiles();
}
void FilePickerClass::Initialize( const char *root_directory, const char *current_directory, const char *ext )
void FilePickerClass::GotoSubDirectory(str subdir)
{
// FIXME: stub
currentDirectory += subdir + "/";
// refresh files
SetupFiles();
}
void FilePickerClass::CloseWindow( void )
void FilePickerClass::SetupFiles(void)
{
// FIXME: stub
str mappath;
str work;
char **filenames;
int numfiles;
int i;
char date[128];
char size[128];
listbox->DeleteAllItems();
if (currentDirectory != rootDirectory) {
// create the parent directory item
listbox->AddItem(new FilePickerItem("..", "", ""));
}
// retrieve directories
filenames = FS_ListFiles(currentDirectory, "/", qfalse, &numfiles);
for (i = 0; i < numfiles; i++) {
const char *filename = filenames[i];
if (filename[0] == '.' || !strlen(filename)) {
continue;
}
work = "[";
work += filename;
work += "]";
FS_FileTime(currentDirectory + filename, date, size);
listbox->AddItem(new FilePickerItem(work, date, size));
}
FS_FreeFileList(filenames);
filenames = FS_ListFiles(currentDirectory, extension, qfalse, &numfiles);
for (i = 0; i < numfiles; i++) {
const char *filename = filenames[i];
if (ignoredFiles.length() && strstr(filename, ignoredFiles)) {
// Added in 2.0
// Check for ignored files
continue;
}
work = filename;
FS_FileTime(currentDirectory + work, date, size);
listbox->AddItem(new FilePickerItem(work, date, size));
}
FS_FreeFileList(filenames);
window->setTitle(currentDirectory);
}
void FilePickerClass::FileSelected( Event *ev )
void FilePickerClass::FileSelected(const str& currentDirectory, const str& partialName, const str& fullname) {}
void FilePickerClass::FileSelected(Event *ev)
{
// FIXME: stub
str name = listbox->GetItem(listbox->getCurrentItem())->getListItemString(0);
if (*name != '[' && *name != '.') {
FileSelected(currentDirectory, name, currentDirectory + name);
}
uii.Snd_PlaySound("sound/menu/scroll.wav");
}
void FilePickerClass::FileSelected( str &currentDirectory, str &partialName, str &fullname )
void FilePickerClass::FileChosen(const str& currentDirectory, const str& partialName, const str& fullname) {}
void FilePickerClass::FileChosen(Event *ev)
{
// FIXME: stub
str filename = listbox->GetItem(listbox->getCurrentItem())->getListItemString(0);
if (*filename == '[') {
uii.Snd_PlaySound("sound/menu/scroll.wav");
GotoSubDirectory(str(filename, 1, filename.length() - 1));
} else if (*filename == '.') {
GotoParentDirectory();
} else {
uii.Snd_PlaySound("sound/menu/apply.wav");
FileChosen(currentDirectory, filename, currentDirectory + filename);
}
}
void FilePickerClass::FileChosen( Event *ev )
void FilePickerClass::CloseWindow(void)
{
// FIXME: stub
PostEvent(EV_Remove, 0);
}
void FilePickerClass::FileChosen( str &currentDirectory, str &partialName, str &fullname )
void FilePickerClass::OnDeactivated(Event *ev)
{
// FIXME: stub
CloseWindow();
}
void FilePickerClass::OnDeactivated( Event *ev )
FilePickerItem::FilePickerItem(const str& fileName, const str& date, const str& size)
{
// FIXME: stub
strings[0] = fileName;
strings[1] = date;
strings[2] = size;
}
void FilePickerClass::Setup( const char *root_directory, const char *current_directory, const char *ext )
int FilePickerItem::getListItemValue(int which) const
{
// FIXME: stub
return atoi(strings[which]);
}
griditemtype_t FilePickerItem::getListItemType(int which) const
{
return griditemtype_t::TYPE_STRING;
}
str FilePickerItem::getListItemString(int which) const
{
return strings[which];
}
void FilePickerItem::DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) {}
qboolean FilePickerItem::IsHeaderEntry() const
{
return qfalse;
}
+26 -25
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -20,40 +20,41 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __CL_UIFILEPICKER_H__
#define __CL_UIFILEPICKER_H__
#pragma once
class UIListCtrl;
class FilePickerClass : public USignal {
UIFloatingWindow *window;
UIListCtrl *listbox;
str currentDirectory;
str rootDirectory;
str extension;
class FilePickerClass : public USignal
{
UIFloatingWindow *window;
UIListCtrl *listbox;
str currentDirectory;
str rootDirectory;
str extension;
// Added in 2.0
str ignoredFiles;
public:
CLASS_PROTOTYPE( FilePickerClass );
CLASS_PROTOTYPE(FilePickerClass);
private:
void SetupFiles( void );
void GotoParentDirectory( void );
void GotoSubDirectory( str subdir );
void Initialize( const char *root_directory, const char *current_directory, const char *ext );
void SetupFiles(void);
void GotoParentDirectory(void);
void GotoSubDirectory(str subdir);
// ignore_files parameter, added in 2.0
void Initialize(const char *root_directory, const char *current_directory, const char *ext, const char* ignore_files);
protected:
void CloseWindow( void );
void FileSelected( Event *ev );
virtual void FileSelected( str &currentDirectory, str &partialName, str &fullname );
void FileChosen( Event *ev );
virtual void FileChosen( str &currentDirectory, str &partialName, str &fullname );
void OnDeactivated( Event *ev );
void CloseWindow(void);
void FileSelected(Event *ev);
virtual void FileSelected(const str& currentDirectory, const str& partialName, const str& fullname);
void FileChosen(Event *ev);
virtual void FileChosen(const str& currentDirectory, const str& partialName, const str& fullname);
void OnDeactivated(Event *ev);
public:
FilePickerClass();
~FilePickerClass();
FilePickerClass();
~FilePickerClass();
void Setup( const char *root_directory, const char *current_directory, const char *ext );
void Setup(const char *root_directory, const char *current_directory, const char *ext, const char* ignore_files = NULL);
};
#endif /* __CL_UIFILEPICKER_H__ */
+183 -17
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -21,44 +21,210 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "cl_ui.h"
#include "../qcommon/localization.h"
CLASS_DECLARATION( UIListCtrl, UILANGameClass, NULL )
class LANGameItem : public UIListCtrlItem
{
{ NULL, NULL }
str strings[5];
public:
LANGameItem();
LANGameItem(
const str& hostName, const str& mapName, const str& players, const str& gameTypeString, const str& ping
);
int getListItemValue(int which) const override;
griditemtype_t getListItemType(int which) const override;
str getListItemString(int which) const override;
void DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) override;
qboolean IsHeaderEntry() const override;
};
Event EV_LANGame_JoinGame
(
"joingame",
EV_DEFAULT,
NULL,
NULL,
"Join the currently selected server"
);
CLASS_DECLARATION(UIListCtrl, UILANGameClass, NULL) {
{&EV_UIListBase_ItemSelected, &UILANGameClass::SelectServer},
{&EV_UIListBase_ItemDoubleClicked, &UILANGameClass::JoinServer },
{&EV_LANGame_JoinGame, &UILANGameClass::JoinServer },
{NULL, NULL }
};
UILANGameClass::UILANGameClass()
{
// FIXME: stub
Connect(this, EV_UIListBase_ItemDoubleClicked, EV_UIListBase_ItemDoubleClicked);
Connect(this, EV_UIListBase_ItemSelected, EV_UIListBase_ItemSelected);
AllowActivate(true);
setHeaderFont("facfont-20");
m_iLastUpdateTime = 0;
m_noservers_mat = uWinMan.RegisterShader("textures/menu/noservers");
}
void UILANGameClass::SetupServers( void )
void UILANGameClass::Draw(void)
{
// FIXME: stub
if (cls.bNewLocalServerInfo) {
SetupServers();
}
UIListCtrl::Draw();
if (!getNumItems() && m_noservers_mat) {
float x, y, w, h;
w = re.GetShaderWidth(m_noservers_mat->GetMaterial()) * m_vVirtualScale[0];
h = re.GetShaderHeight(m_noservers_mat->GetMaterial()) * m_vVirtualScale[1];
UIRect2D frame = getClientFrame();
x = (frame.size.width - w) * 0.5f;
y = (frame.size.height - h) * 0.5f;
re.DrawStretchPic(x, y, w, h, 0, 0, 1, 1, m_noservers_mat->GetMaterial());
}
if (m_iLastUpdateTime && m_iLastUpdateTime < cls.realtime) {
Cvar_Set("cl_langamerefreshstatus", "Ready");
m_iLastUpdateTime = 0;
}
}
void UILANGameClass::Draw( void )
void UILANGameClass::UpdateUIElement(void)
{
// FIXME: stub
float width;
RemoveAllColumns();
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);
uWinMan.ActivateControl(this);
SetupServers();
}
void UILANGameClass::SelectServer( Event *ev )
void UILANGameClass::SetupServers(void)
{
// FIXME: stub
int i;
LANGameItem *pItem;
const serverInfo_t *pServerInfo;
for (i = 1; i <= cls.numlocalservers; i++) {
pServerInfo = &cls.localServers[i - 1];
if (i > getNumItems()) {
pItem = new LANGameItem();
AddItem(pItem);
} else {
pItem = static_cast<LANGameItem *>(GetItem(i));
}
*pItem = LANGameItem(
pServerInfo->hostName,
pServerInfo->mapName,
va("%02i/%02i", pServerInfo->clients, pServerInfo->maxClients),
pServerInfo->gameTypeString,
str(pServerInfo->ping)
);
}
while (cls.numlocalservers < getNumItems()) {
DeleteItem(getNumItems());
}
cls.bNewLocalServerInfo = false;
m_iLastUpdateTime = 0;
}
void UILANGameClass::JoinServer( Event *ev )
void UILANGameClass::SelectServer(Event *ev)
{
// FIXME: stub
const serverInfo_t& serverInfo = cls.localServers[getCurrentItem() - 1];
static const char info[] = "\xFF\xFF\xFF\xFF\x02getinfo xxx";
Com_Printf("Requesting updated info from server...\n");
Cvar_Set("cl_langamerefreshstatus", "Requesting updated info from server...");
NET_SendPacket(NS_CLIENT, sizeof(info), info, serverInfo.adr);
m_iLastUpdateTime = cls.realtime + 3000;
}
qboolean UILANGameClass::KeyEvent( int key, unsigned int time )
void UILANGameClass::JoinServer(Event *ev)
{
// FIXME: stub
return qfalse;
if (!getCurrentItem()) {
return;
}
const serverInfo_t& serverInfo = cls.localServers[getCurrentItem() - 1];
UI_SetReturnMenuToCurrent();
CL_Connect(NET_AdrToString(serverInfo.adr), netadrtype_t::NA_UNSPEC);
}
void UILANGameClass::UpdateUIElement( void )
qboolean UILANGameClass::KeyEvent(int key, unsigned int time)
{
// FIXME: stub
switch (key) {
case K_ENTER:
case K_KP_ENTER:
JoinServer(NULL);
return true;
case K_UPARROW:
if (getCurrentItem() > 1) {
TrySelectItem(getCurrentItem() - 1);
SelectServer(NULL);
}
return false;
case K_DOWNARROW:
if (getCurrentItem() < getNumItems()) {
TrySelectItem(getCurrentItem() + 1);
SelectServer(NULL);
}
return false;
}
return UIListBase::KeyEvent(key, time);
}
LANGameItem::LANGameItem() {}
LANGameItem::LANGameItem(
const str& hostName, const str& mapName, const str& players, const str& gameTypeString, const str& ping
)
{
strings[0] = hostName;
strings[1] = mapName;
strings[2] = players;
strings[3] = gameTypeString;
strings[4] = ping;
}
int LANGameItem::getListItemValue(int which) const
{
return atoi(strings[which]);
}
griditemtype_t LANGameItem::getListItemType(int which) const
{
return griditemtype_t::TYPE_STRING;
}
str LANGameItem::getListItemString(int which) const
{
return strings[which];
}
void LANGameItem::DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) {}
qboolean LANGameItem::IsHeaderEntry() const
{
return qfalse;
}
+14 -16
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -20,29 +20,27 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __CL_UILANGAME_H__
#define __CL_UILANGAME_H__
#pragma once
class UILANGameClass : public UIListCtrl {
class UILANGameClass : public UIListCtrl
{
protected:
int m_iLastUpdateTime;
UIReggedMaterial *m_noservers_mat;
int m_iLastUpdateTime;
UIReggedMaterial *m_noservers_mat;
public:
CLASS_PROTOTYPE( UILANGameClass );
CLASS_PROTOTYPE(UILANGameClass);
private:
void SetupServers( void );
void SetupServers(void);
protected:
void Draw( void ) override;
void SelectServer( Event *ev );
void JoinServer( Event *ev );
qboolean KeyEvent( int key, unsigned int time ) override;
void UpdateUIElement( void ) override;
void Draw(void) override;
void SelectServer(Event *ev);
void JoinServer(Event *ev);
qboolean KeyEvent(int key, unsigned int time) override;
void UpdateUIElement(void) override;
public:
UILANGameClass();
UILANGameClass();
};
#endif /* __CL_UILANGAME_H__ */
+314 -25
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -21,63 +21,352 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "cl_ui.h"
#include "../qcommon/localization.h"
CLASS_DECLARATION( UIListCtrl, UIFAKKLoadGameClass, NULL )
class FAKKLoadGameItem : public UIListCtrlItem
{
{ NULL, NULL }
str strings[4];
public:
FAKKLoadGameItem(const str& missionName, const str& elapsedTime, const str& dateTime, const str& fileName);
int getListItemValue(int which) const override;
griditemtype_t getListItemType(int which) const override;
str getListItemString(int which) const override;
void DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) override;
qboolean IsHeaderEntry() const override;
};
static UIFAKKLoadGameClass *loadgame_ui = NULL;
Event EV_FAKKLoadGame_LoadGame
(
"loadgame",
EV_DEFAULT,
NULL,
NULL,
"Load the currently selected game"
);
Event EV_FAKKLoadGame_RemoveGame
(
"removegame",
EV_DEFAULT,
NULL,
NULL,
"Delete the currently selected game"
);
Event EV_FAKKLoadGame_DeleteGame
(
"deletegame",
EV_DEFAULT,
NULL,
NULL,
"Delete the currently selected game... for real"
);
Event EV_FAKKLoadGame_NoDeleteGame
(
"nodeletegame",
EV_DEFAULT,
NULL,
NULL,
"Delete the currently selected game... for real"
);
Event EV_FAKKLoadGame_SaveGame
(
"savegame",
EV_DEFAULT,
NULL,
NULL,
"Save the currently selected game"
);
CLASS_DECLARATION(UIListCtrl, UIFAKKLoadGameClass, NULL) {
{&EV_UIListBase_ItemSelected, &UIFAKKLoadGameClass::SelectGame },
{&EV_UIListBase_ItemDoubleClicked, &UIFAKKLoadGameClass::LoadGame },
{&EV_FAKKLoadGame_RemoveGame, &UIFAKKLoadGameClass::RemoveGame },
{&EV_FAKKLoadGame_DeleteGame, &UIFAKKLoadGameClass::DeleteGame },
{&EV_FAKKLoadGame_NoDeleteGame, &UIFAKKLoadGameClass::NoDeleteGame},
{&EV_FAKKLoadGame_LoadGame, &UIFAKKLoadGameClass::LoadGame },
{&EV_FAKKLoadGame_SaveGame, &UIFAKKLoadGameClass::SaveGame },
{NULL, NULL }
};
UIFAKKLoadGameClass::UIFAKKLoadGameClass()
{
// FIXME: stub
Connect(this, EV_UIListBase_ItemDoubleClicked, EV_UIListBase_ItemDoubleClicked);
Connect(this, EV_UIListBase_ItemSelected, EV_UIListBase_ItemSelected);
AllowActivate(false);
m_bRemovePending = false;
setHeaderFont("facfont-20");
loadgame_ui = this;
}
void UIFAKKLoadGameClass::SelectGame( Event *ev )
UIFAKKLoadGameClass::~UIFAKKLoadGameClass()
{
// FIXME: stub
loadgame_ui = NULL;
}
void UIFAKKLoadGameClass::LoadGame( Event *ev )
void UIFAKKLoadGameClass::UpdateUIElement(void)
{
// FIXME: stub
float width;
RemoveAllColumns();
width = getClientFrame().size.width;
AddColumn(Sys_LV_CL_ConvertString("Mission"), 0, width * 0.555, false, false);
AddColumn(Sys_LV_CL_ConvertString("Elapsed Time"), 1, width * 0.17f, true, true);
AddColumn(Sys_LV_CL_ConvertString("Date & Time Logged"), 2, width * 0.275f, true, true);
uWinMan.ActivateControl(this);
SetupFiles();
}
void UIFAKKLoadGameClass::SaveGame( Event *ev )
void UIFAKKLoadGameClass::SetupFiles(void)
{
// FIXME: stub
char **filenames;
int numfiles;
int i;
const char *searchFolder = Com_GetArchiveFolder();
// cleanup
DeleteAllItems();
filenames = FS_ListFiles(searchFolder, "ssv", qfalse, &numfiles);
for (i = 0; i < numfiles; i++) {
const char *filename;
str work;
str gametime;
str date;
fileHandle_t f;
savegamestruct_t save;
filename = filenames[i];
work = searchFolder;
work += "/";
work += filename;
FS_FOpenFileRead(work, &f, qfalse, qtrue);
if (!f) {
continue;
}
FS_Read(&save, sizeof(savegamestruct_t), f);
FS_FCloseFile(f);
if (save.version != SAVEGAME_STRUCT_VERSION) {
// wrong save game version
continue;
}
gametime = (save.mapTime / 1000);
date = save.time;
AddItem(new FAKKLoadGameItem(save.comment, gametime, date, save.saveName));
}
FS_FreeFileList(filenames);
// sort by date
SortByColumn(2);
// select the first item
TrySelectItem(1);
SelectGame(NULL);
}
void UIFAKKLoadGameClass::RemoveGame( Event *ev )
void UIFAKKLoadGameClass::SelectGame(Event *ev)
{
// FIXME: stub
UIWidget *wid;
const char *shotName;
if (getCurrentItem() > 0) {
shotName = Com_GetArchiveFileName(GetItem(getCurrentItem())->getListItemString(3), "tga");
} else {
shotName = "textures/menu/no_saved_games.tga";
}
wid = findSibling("LoadSaveShot");
if (!wid) {
return;
}
wid->setMaterial(uWinMan.RefreshShader(shotName));
}
void UIFAKKLoadGameClass::DeleteGame( Event *ev )
void UIFAKKLoadGameClass::RemoveGame(Event *ev)
{
// FIXME: stub
if (m_bRemovePending || getCurrentItem() <= 0) {
return;
}
Cbuf_ExecuteText(
EXEC_NOW,
"dialog \"\" \"\" \"widgetcommand LoadSaveList deletegame\" \"widgetcommand LoadSaveList nodeletegame\" 256 64 "
"confirm_delete menu_button_trans menu_button_trans\n"
);
m_bRemovePending = true;
}
void UIFAKKLoadGameClass::NoDeleteGame( Event *ev )
void UIFAKKLoadGameClass::NoDeleteGame(Event *ev)
{
// FIXME: stub
m_bRemovePending = false;
}
qboolean UIFAKKLoadGameClass::KeyEvent( int key, unsigned int time )
void UIFAKKLoadGameClass::DeleteGame(Event *ev)
{
// FIXME: stub
return qfalse;
str name;
cvar_t *var;
m_bRemovePending = false;
if (getCurrentItem() <= 0) {
return;
}
name = GetItem(getCurrentItem())->getListItemString(3);
var = Cvar_Get("g_lastsave", "", 0);
if (!strcmp(name, var->string)) {
// Make sure the last save is not the save being deleted
Cvar_Set("g_lastsave", "");
}
Com_WipeSavegame(name);
SetupFiles();
}
void UIFAKKLoadGameClass::UpdateUIElement( void )
void UIFAKKLoadGameClass::LoadGame(Event *ev)
{
// FIXME: stub
char cmdString[266];
str name;
if (getCurrentItem() <= 0) {
return;
}
name = GetItem(getCurrentItem())->getListItemString(3);
// Execute the command
Com_sprintf(cmdString, sizeof(cmdString), "loadgame %s\n", name.c_str());
Cbuf_AddText(cmdString);
}
void UIFAKKLoadGameClass::SetupFiles( void )
void UIFAKKLoadGameClass::SaveGame(Event *ev)
{
// FIXME: stub
Cbuf_ExecuteText(EXEC_NOW, "savegame");
}
void UI_SetupFiles( void ) {
// FIXME: stub
qboolean UIFAKKLoadGameClass::KeyEvent(int key, unsigned int time)
{
switch (key) {
case K_DEL:
RemoveGame(NULL);
return qtrue;
case K_ENTER:
case K_KP_ENTER:
LoadGame(NULL);
return qtrue;
case K_UPARROW:
if (getCurrentItem() > 1) {
TrySelectItem(getCurrentItem() - 1);
SelectGame(NULL);
return qtrue;
}
break;
case K_DOWNARROW:
if (getCurrentItem() < getNumItems()) {
TrySelectItem(getCurrentItem() + 1);
SelectGame(NULL);
return qtrue;
}
break;
default:
return UIListBase::KeyEvent(key, time);
}
return qfalse;
}
void UI_SetupFiles(void)
{
if (loadgame_ui && loadgame_ui->getShow()) {
loadgame_ui->SetupFiles();
}
}
FAKKLoadGameItem::FAKKLoadGameItem(
const str& missionName, const str& elapsedTime, const str& dateTime, const str& fileName
)
{
strings[0] = missionName;
strings[1] = elapsedTime;
strings[2] = dateTime;
strings[3] = fileName;
}
int FAKKLoadGameItem::getListItemValue(int which) const
{
return atoi(strings[which]);
}
griditemtype_t FAKKLoadGameItem::getListItemType(int which) const
{
return griditemtype_t::TYPE_STRING;
}
str FAKKLoadGameItem::getListItemString(int which) const
{
str itemstring;
switch (which) {
case 0:
case 3:
itemstring = strings[which];
break;
case 1:
{
int numseconds;
int numseconds_hours;
// hours
numseconds = atol(strings[1]);
itemstring += (numseconds / 3600);
itemstring += ":";
// minutes
numseconds_hours = numseconds % 3600;
if (numseconds_hours / 60 <= 9) {
itemstring += "0";
}
itemstring += (numseconds_hours / 60);
itemstring += ":";
// seconds
if (numseconds_hours / 60 <= 9) {
itemstring += "0";
}
itemstring += (numseconds_hours % 60);
}
break;
case 2:
{
time_t time;
char buffer[2048];
time = atol(strings[2]);
strftime(buffer, sizeof(buffer), "%a %b %d %H:%M:%S %Y", localtime(&time));
itemstring = buffer;
}
break;
}
return itemstring;
}
void FAKKLoadGameItem::DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) {}
qboolean FAKKLoadGameItem::IsHeaderEntry() const
{
return qfalse;
}
+18 -28
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -20,38 +20,28 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __CL_UILOADSAVE_H__
#define __CL_UILOADSAVE_H__
#pragma once
class UIFAKKLoadGameClass : public UIListCtrl {
bool m_bRemovePending;
class UIFAKKLoadGameClass : public UIListCtrl
{
bool m_bRemovePending;
public:
CLASS_PROTOTYPE( UIFAKKLoadGameClass );
CLASS_PROTOTYPE(UIFAKKLoadGameClass);
protected:
void SelectGame( Event *ev );
void LoadGame( Event *ev );
void SaveGame( Event *ev );
void RemoveGame( Event *ev );
void DeleteGame( Event *ev );
void NoDeleteGame( Event *ev );
qboolean KeyEvent( int key, unsigned int time ) override;
void UpdateUIElement( void ) override;
void SelectGame(Event *ev);
void LoadGame(Event *ev);
void SaveGame(Event *ev);
void RemoveGame(Event *ev);
void DeleteGame(Event *ev);
void NoDeleteGame(Event *ev);
qboolean KeyEvent(int key, unsigned int time) override;
void UpdateUIElement(void) override;
public:
UIFAKKLoadGameClass();
UIFAKKLoadGameClass();
~UIFAKKLoadGameClass();
void SetupFiles( void );
void SetupFiles(void);
};
#ifdef __cplusplus
extern "C" {
#endif
void UI_SetupFiles( void );
#ifdef __cplusplus
}
#endif
#endif
+449
View File
@@ -0,0 +1,449 @@
/*
===========================================================================
Copyright (C) 2023 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
===========================================================================
*/
#include "cl_ui.h"
#include "cl_uimaprotationsetup.h"
Event EV_MapListBox_RefreshMapList
(
"RefreshMapList",
EV_DEFAULT,
NULL,
NULL,
"Refreshes the map list."
);
Event EV_MapRotationListBox_RefreshRotationList
(
"RefreshRotationList",
EV_DEFAULT,
NULL,
NULL,
"Refreshed the map rotation list."
);
CLASS_DECLARATION(UIListBox, UIMapRotationListBox, NULL) {
{&EV_MapRotationListBox_RefreshRotationList, &UIMapRotationListBox::RefreshRotationList},
{NULL, NULL }
};
UIMapRotationListBox::UIMapRotationListBox() {}
void UIMapRotationListBox::RefreshRotationList(Event *ev)
{
DeleteAllItems();
PopulateRotationList();
}
void UIMapRotationListBox::PopulateRotationList()
{
cvar_t *filter;
cvar_t *maplistVar;
const char *token;
char mapBuffer[1024];
filter = Cvar_Get("g_maprotation_filter", "ffa", 0);
if (!Q_stricmp(filter->string, "obj")) {
maplistVar = Cvar_Get("ui_maplist_obj", "", 0);
} else if (!Q_stricmp(filter->string, "tow")) {
maplistVar = Cvar_Get("ui_maplist_tow", "", 0);
} else if (!Q_stricmp(filter->string, "lib")) {
maplistVar = Cvar_Get("ui_maplist_lib", "", 0);
} else if (!Q_stricmp(filter->string, "team")) {
maplistVar = Cvar_Get("ui_maplist_team", "", 0);
} else if (!Q_stricmp(filter->string, "round")) {
maplistVar = Cvar_Get("ui_maplist_round", "", 0);
} else {
maplistVar = Cvar_Get("ui_maplist_ffa", "", 0);
}
strcpy(mapBuffer, maplistVar->string);
for (token = strtok(mapBuffer, " /"); token; token = strtok(NULL, " /")) {
if (!Q_stricmp(token, "dm")) {
continue;
}
if (!Q_stricmp(token, "obj")) {
continue;
}
if (!Q_stricmp(token, "lib")) {
continue;
}
AddItem(token, NULL);
}
}
CLASS_DECLARATION(UIListBox, UIMapListBox, NULL) {
{&EV_MapListBox_RefreshMapList, &UIMapListBox::RefreshMapList},
{NULL, NULL }
};
UIMapListBox::UIMapListBox() {}
void UIMapListBox::RefreshMapList(Event *ev)
{
DeleteAllItems();
PopulateMapList();
}
void UIMapListBox::PopulateMapList()
{
cvar_t *filter;
char **filenames;
int numfiles;
str path;
int i;
bool bTugOfWar = false;
bool bObjective = false;
bool bLiberation = false;
filter = Cvar_Get("g_maprotation_filter", "ffa", 0);
if (!Q_stricmp(filter->string, "lib")) {
path = "maps/lib/";
bLiberation = true;
} else if (!Q_stricmp(filter->string, "obj") || !Q_stricmp(filter->string, "tow")) {
path = "maps/obj/";
if (!Q_stricmp(filter->string, "tow")) {
bTugOfWar = true;
} else {
bObjective = true;
}
} else {
path = "maps/dm/";
}
filenames = FS_ListFiles(path, ".bsp", qfalse, &numfiles);
for (i = 0; i < numfiles; i++) {
const char *filename = filenames[i];
const char *token;
char mapName[256];
char tokenized[256];
bool bHasMP = false;
bool bHasTOW = false;
bool bHasLib = false;
strcpy(mapName, filename);
mapName[strlen(mapName) - 4] = 0;
if (!COM_IsMapValid(mapName)) {
continue;
}
if (bTugOfWar || bLiberation) {
strcpy(tokenized, mapName);
for (token = strtok(tokenized, "_"); token; token = strtok(NULL, "_")) {
if (bLiberation) {
if (!Q_stricmp(token, "MP")) {
bHasMP = true;
}
if (!Q_stricmp(token, "LIB")) {
bHasLib = true;
}
if (bHasMP && bHasLib) {
AddItem(mapName, NULL);
break;
}
}
if (bTugOfWar) {
if (!Q_stricmp(token, "MP")) {
bHasMP = true;
}
if (!Q_stricmp(token, "TOW")) {
bHasTOW = true;
}
if (bHasMP && bHasTOW) {
AddItem(mapName, NULL);
break;
}
}
}
} else if (bObjective) {
strcpy(tokenized, mapName);
for (token = strtok(tokenized, "_"); token; token = strtok(NULL, "_")) {
if (!Q_stricmp(token, "obj")) {
AddItem(mapName, NULL);
break;
}
}
if (!Q_stricmp(mapName, "mp_ship_lib")) {
AddItem(mapName, NULL);
}
} else {
AddItem(mapName, NULL);
}
}
if (bObjective) {
path = "maps/lib/";
filenames = FS_ListFiles(path, ".bsp", qfalse, &numfiles);
for (i = 0; i < numfiles; i++) {
const char *filename = filenames[i];
const char *token;
char mapName[256];
char tokenized[256];
strcpy(mapName, filename);
mapName[strlen(mapName) - 4] = 0;
strcpy(tokenized, mapName);
token = strtok(tokenized, "_");
if (!Q_stricmp(token, "obj") || !Q_stricmp(mapName, "mp_ship_lib")) {
AddItem(mapName, NULL);
break;
}
}
}
if (!bTugOfWar && !bObjective && !bLiberation) {
int type;
for (type = 0; type < 2; type++) {
if (type == 0) {
path = "maps/obj/";
} else {
path = "maps/lib/";
}
filenames = FS_ListFiles(path, ".bsp", qfalse, &numfiles);
for (i = 0; i < numfiles; i++) {
const char *filename = filenames[i];
char mapName[256];
strcpy(mapName, filename);
mapName[strlen(mapName) - 4] = 0;
if (!COM_IsMapValid(mapName)) {
continue;
}
if (!Q_stricmp(mapName, "obj_team2") || !Q_stricmp(mapName, "obj_team4")) {
continue;
}
AddItem(mapName, NULL);
}
}
}
}
CLASS_DECLARATION(UIButton, UIAddToRotationButton, NULL) {
{&W_LeftMouseUp, &UIAddToRotationButton::Released},
{NULL, NULL }
};
void UIAddToRotationButton::Released(Event *ev)
{
UIListBox *mapList;
UIListBox *rotationList;
size_t prefixLength;
int i;
mapList = static_cast<UIListBox *>(uWinMan.FindWidget("Map List"));
rotationList = static_cast<UIListBox *>(uWinMan.FindWidget("Rotation List"));
if (Cvar_Get("g_maprotation_filter", "ffa", 0)) {
prefixLength = strlen("obj/") + 1;
} else {
prefixLength = 1;
}
if (mapList && rotationList) {
size_t mapLength = 0;
int item = mapList->getCurrentItem();
for (i = 1; i <= rotationList->getNumItems(); i++) {
str text = rotationList->getItemText(i);
mapLength += text.length();
}
if (item) {
str text = mapList->getItemText(item);
if (prefixLength + mapLength + text.length() < 256) {
rotationList->AddItem(text, NULL);
}
}
}
UIButtonBase::Released(ev);
}
CLASS_DECLARATION(UIButton, UIRemoveFromRotationButton, NULL) {
{&W_LeftMouseUp, &UIRemoveFromRotationButton::Released},
{NULL, NULL }
};
void UIRemoveFromRotationButton::Released(Event *ev)
{
UIListBox *list;
list = static_cast<UIListBox *>(uWinMan.FindWidget("Rotation List"));
if (list) {
list->DeleteItem(list->getCurrentItem());
}
UIButtonBase::Released(ev);
}
CLASS_DECLARATION(UIButton, UIRotationApplyButton, NULL) {
{&W_LeftMouseUp, &UIRotationApplyButton::Released},
{NULL, NULL }
};
void UIRotationApplyButton::Released(Event *ev)
{
UIListBox *list;
cvar_t *filter;
str cvarName;
str maplistStr;
int i;
bool bObjective = false;
bool bLiberation = false;
filter = Cvar_Get("g_maprotation_filter", "ffa", 0);
if (!Q_stricmp(filter->string, "obj")) {
cvarName = "ui_maplist_obj";
bObjective = true;
} else if (!Q_stricmp(filter->string, "tow")) {
cvarName = "ui_maplist_obj";
bObjective = true;
} else if (!Q_stricmp(filter->string, "lib")) {
cvarName = "ui_maplist_lib";
bLiberation = true;
} else if (!Q_stricmp(filter->string, "team")) {
cvarName = "ui_maplist_team";
} else if (!Q_stricmp(filter->string, "round")) {
cvarName = "ui_maplist_round";
} else {
cvarName = "ui_maplist_ffa";
}
Cvar_Set(cvarName, "");
list = static_cast<UIListBox *>(uWinMan.FindWidget("Rotation List"));
if (list) {
for (i = 1; i <= list->getNumItems(); i++) {
const char *token;
str text = list->getItemText(i);
char map[256];
bool bHasTOW = false, bHasObj = false, bHasLib = false, bHasShip = false;
strcpy(map, text);
for (token = strtok(map, "_"); token; token = strtok(NULL, "_")) {
if (!Q_stricmp(token, "TOW")) {
bHasTOW = true;
break;
}
if (!Q_stricmp(token, "obj")) {
bHasObj = true;
break;
}
if (!Q_stricmp(token, "lib")) {
bHasLib = true;
break;
}
if (!Q_stricmp(token, "ship")) {
bHasShip = true;
break;
}
}
if (bHasShip) {
maplistStr += "lib/";
} else if (bObjective || bHasTOW || bHasObj) {
maplistStr += "obj/";
} else if (bHasLib || bLiberation) {
maplistStr += "lib/";
} else {
maplistStr += "dm/";
}
maplistStr += text;
maplistStr += " ";
if (i == 1) {
Cvar_Set("ui_dmmap", maplistStr);
}
}
}
Cvar_Set(cvarName, maplistStr);
UIButtonBase::Released(ev);
}
CLASS_DECLARATION(UIButton, UIRotationMoveItemUpButton, NULL) {
{&W_LeftMouseUp, &UIRotationMoveItemUpButton::Released},
{NULL, NULL }
};
void UIRotationMoveItemUpButton::Released(Event *ev)
{
UIListBox *list;
int item;
list = static_cast<UIListBox *>(uWinMan.FindWidget("Rotation List"));
item = list->getCurrentItem();
if (item < list->getNumItems() && list->getNumItems() > 1) {
str text = list->getItemText(item + 1);
list->DeleteItem(list->getCurrentItem() - 1);
list->InsertItem(text, item);
list->setCurrentItem(item - 1);
}
UIButtonBase::Released(ev);
}
CLASS_DECLARATION(UIButton, UIRotationMoveItemDownButton, NULL) {
{&W_LeftMouseUp, &UIRotationMoveItemDownButton::Released},
{NULL, NULL }
};
void UIRotationMoveItemDownButton::Released(Event *ev)
{
UIListBox *list;
int item;
list = static_cast<UIListBox *>(uWinMan.FindWidget("Rotation List"));
item = list->getCurrentItem();
if (item < list->getNumItems() && list->getNumItems() > 1) {
str text = list->getItemText(item + 1);
list->DeleteItem(list->getCurrentItem() + 1);
list->InsertItem(text, item);
list->setCurrentItem(item + 1);
}
UIButtonBase::Released(ev);
}
+87
View File
@@ -0,0 +1,87 @@
/*
===========================================================================
Copyright (C) 2023 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
===========================================================================
*/
#pragma once
#include "../uilib/uilistbox.h"
class UIMapRotationListBox : public UIListBox
{
CLASS_PROTOTYPE(UIMapRotationListBox);
public:
UIMapRotationListBox();
void RefreshRotationList(Event *ev);
void PopulateRotationList();
};
class UIMapListBox : public UIListBox
{
CLASS_PROTOTYPE(UIMapListBox);
public:
UIMapListBox();
void RefreshMapList(Event *ev);
void PopulateMapList();
};
class UIAddToRotationButton : public UIButton
{
CLASS_PROTOTYPE(UIAddToRotationButton);
public:
void Released(Event *ev);
};
class UIRemoveFromRotationButton : public UIButton
{
CLASS_PROTOTYPE(UIRemoveFromRotationButton);
public:
void Released(Event *ev);
};
class UIRotationApplyButton : public UIButton
{
CLASS_PROTOTYPE(UIRotationApplyButton);
public:
void Released(Event *ev);
};
class UIRotationMoveItemUpButton : public UIButton
{
CLASS_PROTOTYPE(UIRotationMoveItemUpButton);
public:
void Released(Event *ev);
};
class UIRotationMoveItemDownButton : public UIButton
{
CLASS_PROTOTYPE(UIRotationMoveItemDownButton);
public:
void Released(Event *ev);
};
+84 -24
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -22,47 +22,107 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cl_ui.h"
CLASS_DECLARATION( FilePickerClass, MapRunnerClass, NULL )
{
{ NULL, NULL }
CLASS_DECLARATION(FilePickerClass, MapRunnerClass, NULL) {
{NULL, NULL}
};
void MapRunnerClass::FileChosen( str &currentDirectory, str &partialName, str &fullname )
void MapRunnerClass::FileChosen(const str& currentDirectory, const str& partialName, const str& fullname)
{
// FIXME: stub
str newName;
newName = "spmap " + str(fullname, 5, fullname.length() - 4) + "\n";
// insert the command
Cbuf_AddText(newName);
CloseWindow();
}
CLASS_DECLARATION( FilePickerClass, ViewSpawnerClass, NULL )
{
{ NULL, NULL }
CLASS_DECLARATION(FilePickerClass, UIPickFileClass, NULL) {
{NULL, NULL}
};
void ViewSpawnerClass::FileChosen( str &currentDirectory, str &partialName, str &fullname )
UIPickFileClass::UIPickFileClass()
{
// FIXME: stub
retobj = NULL;
retevent = NULL;
}
CLASS_DECLARATION( FilePickerClass, LODSpawnerClass, NULL )
UIPickFileClass::~UIPickFileClass()
{
{ NULL, NULL }
if (retevent) {
delete retevent;
}
}
void UIPickFileClass::FileChosen(const str& currentDirectory, const str& partialName, const str& fullname)
{
if (!retobj || !retevent) {
CloseWindow();
return;
}
retevent->AddString(fullname);
retobj->ProcessEvent(retevent);
retevent = NULL;
retobj = NULL;
CloseWindow();
}
void PickFile(const char *name, Listener *obj, Event& event)
{
UIPickFileClass *picker;
str currentpath;
int i;
picker = new UIPickFileClass();
picker->retevent = new Event(event);
picker->retobj = obj;
if (name && *name && strchr(name, '/')) {
currentpath = name;
for (i = currentpath.length(); i > 0; i--) {
if (currentpath[i] == '/') {
break;
}
}
currentpath = str(currentpath, 0, i + 1);
} else {
currentpath = "";
}
picker->Setup("", currentpath, ".*");
}
CLASS_DECLARATION(FilePickerClass, ViewSpawnerClass, NULL) {
{NULL, NULL}
};
void LODSpawnerClass::FileChosen( str &currentDirectory, str &partialName, str &fullname )
void ViewSpawnerClass::FileChosen(const str& currentDirectory, const str& partialName, const str& fullname)
{
// FIXME: stub
str newName;
newName = "viewspawn " + fullname + "\n";
// insert the command
Cbuf_AddText(newName);
CloseWindow();
}
CLASS_DECLARATION( FilePickerClass, UIPickFileClass, NULL )
{
{ NULL, NULL }
CLASS_DECLARATION(FilePickerClass, LODSpawnerClass, NULL) {
{NULL, NULL}
};
void UIPickFileClass::FileChosen( str &currentDirectory, str &partialName, str &fullname )
void LODSpawnerClass::FileChosen(const str& currentDirectory, const str& partialName, const str& fullname)
{
// FIXME: stub
}
str newName;
void PickFile( const char *name, Listener *obj, Event& event )
{
// FIXME: stub
newName = "lod_spawn " + fullname + "\n";
// insert the command
Cbuf_AddText(newName);
CloseWindow();
}
+24 -20
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -20,40 +20,44 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __CL_UIMAPRUNNER_H__
#define __CL_UIMAPRUNNER_H__
#pragma once
class MapRunnerClass : public FilePickerClass {
class MapRunnerClass : public FilePickerClass
{
public:
CLASS_PROTOTYPE( MapRunnerClass );
CLASS_PROTOTYPE(MapRunnerClass);
void FileChosen( str &currentDirectory, str &partialName, str &fullname ) override;
void FileChosen(const str& currentDirectory, const str& partialName, const str& fullname) override;
};
class ViewSpawnerClass : public FilePickerClass {
class ViewSpawnerClass : public FilePickerClass
{
public:
CLASS_PROTOTYPE( ViewSpawnerClass );
CLASS_PROTOTYPE(ViewSpawnerClass);
void FileChosen( str &currentDirectory, str &partialName, str &fullname ) override;
void FileChosen(const str& currentDirectory, const str& partialName, const str& fullname) override;
};
class LODSpawnerClass : public FilePickerClass {
class LODSpawnerClass : public FilePickerClass
{
public:
CLASS_PROTOTYPE( LODSpawnerClass );
CLASS_PROTOTYPE(LODSpawnerClass);
void FileChosen( str &currentDirectory, str &partialName, str &fullname ) override;
void FileChosen(const str& currentDirectory, const str& partialName, const str& fullname) override;
};
class UIPickFileClass : public FilePickerClass {
class UIPickFileClass : public FilePickerClass
{
public:
Listener *retobj;
Event *retevent;
Listener *retobj;
Event *retevent;
CLASS_PROTOTYPE( UIPickFileClass );
CLASS_PROTOTYPE(UIPickFileClass);
void FileChosen( str &currentDirectory, str &partialName, str &fullname ) override;
UIPickFileClass();
~UIPickFileClass();
void FileChosen(const str& currentDirectory, const str& partialName, const str& fullname) override;
};
void PickFile( const char *name, Listener *obj, Event& event );
#endif /* __CL_UIMAPRUNNER_H__ */
void PickFile(const char *name, Listener *obj, Event& event);
+138 -27
View File
@@ -22,68 +22,179 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cl_ui.h"
CLASS_DECLARATION( UIWidget, FakkMiniconsole, NULL )
{
{ NULL, NULL }
Event EV_Minicon_Goin("_minicon_goin", EV_DEFAULT, NULL, NULL, "Event to make the miniconsole disappear");
CLASS_DECLARATION(UIWidget, FakkMiniconsole, NULL) {
{&W_SizeChanged, &FakkMiniconsole::OnSizeChanged},
{&EV_Minicon_Goin, &FakkMiniconsole::MoveInEvent },
{NULL, NULL }
};
FakkMiniconsole::FakkMiniconsole()
{
// FIXME: stub
m_maxlines = 0;
m_reallyshown = true;
m_boxstate = boxstate_t::box_in;
m_boxtime = uid.time;
m_movespeed = 500;
}
void FakkMiniconsole::VerifyBoxOut( void )
void FakkMiniconsole::setShowState(void)
{
// FIXME: stub
if (m_reallyshown) {
setShow(m_boxstate != boxstate_t::box_in);
} else {
setShow(false);
}
}
void FakkMiniconsole::ChangeBoxState( boxstate_t state )
void FakkMiniconsole::setRealShow(bool b)
{
// FIXME: stub
m_reallyshown = b;
setShowState();
}
void FakkMiniconsole::HandleBoxMoving( void )
void FakkMiniconsole::VerifyBoxOut(void)
{
// FIXME: stub
PostMoveinEvent();
if (m_boxstate && m_boxstate != boxstate_t::box_out) {
ChangeBoxState(box_moving_out);
}
}
void FakkMiniconsole::PostMoveinEvent( void )
void FakkMiniconsole::Print(const char *text)
{
// FIXME: stub
str *lastline;
const char *p;
if (!m_lines.NumObjects()) {
m_lines.AddObject({});
}
lastline = &m_lines.ObjectAt(m_lines.NumObjects());
if (*text) {
for (p = text; *p; p++) {
if (*p != '\n') {
*lastline += *p;
} else {
m_lines.AddObject({});
lastline = &m_lines.ObjectAt(m_lines.NumObjects());
}
}
}
if (lastline && lastline->length() > 128) {
Print("\n");
}
if (m_maxlines < 0) {
m_maxlines = 1;
}
while (m_lines.NumObjects() > this->m_maxlines) {
m_lines.RemoveObjectAt(1);
}
VerifyBoxOut();
}
void FakkMiniconsole::setShowState( void )
void FakkMiniconsole::PostMoveinEvent(void)
{
// FIXME: stub
if (m_boxstate != boxstate_t::box_out) {
return;
}
CancelEventsOfType(EV_Minicon_Goin);
PostEvent(new Event(EV_Minicon_Goin), 5.f);
}
void FakkMiniconsole::OnSizeChanged( Event *ev )
void FakkMiniconsole::OnSizeChanged(Event *ev)
{
// FIXME: stub
m_maxlines = m_frame.size.height / m_font->getHeight(false);
}
void FakkMiniconsole::Print( const char *text )
void FakkMiniconsole::MoveInEvent(Event *ev)
{
// FIXME: stub
ChangeBoxState(boxstate_t::box_moving_in);
}
void FakkMiniconsole::Create( const UISize2D& size, const UColor& fore, const UColor& back, float alpha )
void FakkMiniconsole::HandleBoxMoving(void)
{
// FIXME: stub
int delta;
UIRect2D newRect;
if (m_boxstate == boxstate_t::box_out || m_boxstate == boxstate_t::box_in) {
return;
}
delta = m_movespeed * (uid.time - m_boxtime) / 1000;
m_boxtime = 1000 * delta / m_movespeed + m_boxtime;
switch (m_boxstate) {
case boxstate_t::box_moving_in:
newRect = UIRect2D(delta + m_frame.pos.x, m_frame.pos.y, m_frame.size.width, m_frame.size.height);
if (newRect.pos.x >= uid.vidWidth) {
newRect.pos.x = uid.vidWidth;
ChangeBoxState(boxstate_t::box_in);
}
break;
case boxstate_t::box_moving_out:
newRect = UIRect2D(-delta + m_frame.pos.x, m_frame.pos.y, m_frame.size.width, m_frame.size.height);
if (newRect.pos.x <= uid.vidWidth - newRect.size.width) {
newRect.pos.x = uid.vidWidth - newRect.size.width;
ChangeBoxState(boxstate_t::box_out);
}
break;
default:
ChangeBoxState(boxstate_t::box_in);
break;
}
setFrame(newRect);
}
void FakkMiniconsole::MoveInEvent( Event *ev )
void FakkMiniconsole::Draw(void)
{
// FIXME: stub
float aty;
int i;
HandleBoxMoving();
m_font->setColor(m_foreground_color);
aty = m_frame.size.height - m_font->getHeight(false);
for (i = m_lines.NumObjects(); i > 0; i--) {
if (-m_font->getHeight(false) >= aty) {
break;
}
m_font->Print(0, aty, m_lines.ObjectAt(i), -1, false);
aty -= m_font->getHeight(false);
}
}
void FakkMiniconsole::Draw( void )
void FakkMiniconsole::Create(const UISize2D& size, const UColor& fore, const UColor& back, float alpha)
{
// FIXME: stub
InitFrame(NULL, uid.vidWidth, 0, size.width, size.height, 0);
setBackgroundColor(back, true);
setForegroundColor(fore);
setBackgroundAlpha(alpha);
Connect(this, W_SizeChanged, W_SizeChanged);
OnSizeChanged(NULL);
m_movespeed = size.width * 3;
setShowState();
}
void FakkMiniconsole::setRealShow( bool b )
void FakkMiniconsole::ChangeBoxState(boxstate_t state)
{
// FIXME: stub
m_boxstate = state;
m_boxtime = uid.time;
setShowState();
if (state == boxstate_t::box_out) {
PostMoveinEvent();
}
}
+23 -25
View File
@@ -20,38 +20,36 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __CL_UIMINICON_H__
#define __CL_UIMINICON_H__
#pragma once
class FakkMiniconsole : public UIWidget {
class FakkMiniconsole : public UIWidget
{
protected:
Container<str> m_lines;
int m_maxlines;
bool m_reallyshown;
bool m_boxmovingout;
boxstate_t m_boxstate;
int m_boxtime;
int m_movespeed;
Container<str> m_lines;
int m_maxlines;
bool m_reallyshown;
bool m_boxmovingout;
boxstate_t m_boxstate;
int m_boxtime;
int m_movespeed;
public:
CLASS_PROTOTYPE( FakkMiniconsole );
CLASS_PROTOTYPE(FakkMiniconsole);
protected:
void VerifyBoxOut( void );
void ChangeBoxState( boxstate_t state );
void HandleBoxMoving( void );
void PostMoveinEvent( void );
void setShowState( void );
void VerifyBoxOut(void);
void ChangeBoxState(boxstate_t state);
void HandleBoxMoving(void);
void PostMoveinEvent(void);
void setShowState(void);
public:
FakkMiniconsole();
FakkMiniconsole();
void OnSizeChanged( Event *ev );
void Print( const char *text );
void Create( const UISize2D& size, const UColor& fore, const UColor& back, float alpha );
void MoveInEvent( Event *ev );
void Draw( void ) override;
void setRealShow( bool b );
void OnSizeChanged(Event *ev);
void Print(const char *text);
void Create(const UISize2D& size, const UColor& fore, const UColor& back, float alpha);
void MoveInEvent(Event *ev);
void Draw(void) override;
void setRealShow(bool b);
};
#endif
+291 -27
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -21,73 +21,337 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "cl_ui.h"
#include "../qcommon/localization.h"
CLASS_DECLARATION( USignal, MpMapPickerClass, NULL )
class MpMapPickerItem : public UIListCtrlItem
{
{ NULL, NULL }
str m_string;
// Added in 2.0
str m_directory;
public:
MpMapPickerItem(const str& string, const str& directory);
int getListItemValue(int which) const override;
griditemtype_t getListItemType(int which) const override;
str getListItemString(int which) const override;
void DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) override;
qboolean IsHeaderEntry() const override;
};
CLASS_DECLARATION(USignal, MpMapPickerClass, NULL) {
{&EV_UIListBase_ItemSelected, &MpMapPickerClass::FileSelected },
{&EV_UIListBase_ItemDoubleClicked, &MpMapPickerClass::FileChosen },
{&W_Deactivated, &MpMapPickerClass::OnDeactivated},
{NULL, NULL }
};
MpMapPickerClass::MpMapPickerClass()
{
// FIXME: stub
window = new UIFloatingWindow();
window->Create(
NULL,
UIRect2D((cls.glconfig.vidWidth - 300) / 2, (cls.glconfig.vidHeight - 200) / 2, 300, 200),
"Select a Map",
UColor(0.15f, 0.195f, 0.278f),
UHudColor
);
window->setFont("facfont-20");
window->PassEventToWidget("closebutton", new Event(EV_Widget_Disable));
window->PassEventToWidget("minimizebutton", new Event(EV_Widget_Disable));
window->Connect(this, W_Deactivated, W_Deactivated);
listbox = new UIListCtrl();
listbox->InitFrame(window->getChildSpace(), window->getChildSpace()->getClientFrame(), 0);
listbox->SetDrawHeader(false);
listbox->setFont("facfont-20");
listbox->FrameInitialized();
listbox->AddColumn(Sys_LV_CL_ConvertString("Select a Map"), 0, 400, false, false);
listbox->Connect(this, EV_UIListBase_ItemDoubleClicked, EV_UIListBase_ItemDoubleClicked);
listbox->Connect(this, EV_UIListBase_ItemSelected, EV_UIListBase_ItemSelected);
listbox->AllowActivate(true);
// Added in 2.0
// Don't localize elements
listbox->SetDontLocalize();
}
MpMapPickerClass::~MpMapPickerClass()
{
// FIXME: stub
if (listbox) {
delete listbox;
listbox = NULL;
}
if (window) {
delete window;
window = NULL;
}
}
void MpMapPickerClass::SetupFiles( void )
void MpMapPickerClass::Setup(const char *root_directory, const char *current_directory, const char *game_type)
{
// FIXME: stub
Initialize(root_directory, current_directory, game_type);
}
void MpMapPickerClass::GotoParentDirectory( void )
void MpMapPickerClass::Initialize(const char *root_directory, const char *current_directory, const char *game_type)
{
// FIXME: stub
rootDirectory = root_directory;
if (rootDirectory.length() > 1 && rootDirectory[rootDirectory.length() - 1] != '/') {
rootDirectory += "/";
}
currentDirectory = current_directory;
if (currentDirectory.length() > 1 && currentDirectory[currentDirectory.length() - 1] != '/') {
currentDirectory += "/";
}
if (game_type) {
gameType = game_type;
}
SetupFiles();
}
void MpMapPickerClass::GotoSubDirectory( str subdir )
void MpMapPickerClass::GotoParentDirectory(void)
{
// FIXME: stub
uintptr_t i;
if (currentDirectory == rootDirectory) {
return;
}
for (i = currentDirectory.length() - 2; i > 0; i--) {
if (currentDirectory[i] == '/') {
break;
}
}
if (currentDirectory[i] == '/') {
i++;
}
currentDirectory = str(currentDirectory, 0, i);
// refresh files
SetupFiles();
}
void MpMapPickerClass::Initialize( const char *root_directory, const char *current_directory )
void MpMapPickerClass::GotoSubDirectory(str subdir)
{
// FIXME: stub
currentDirectory += subdir + "/";
// refresh files
SetupFiles();
}
void MpMapPickerClass::CloseWindow( void )
void MpMapPickerClass::SetupFiles(void)
{
// FIXME: stub
char **filenames;
int numfiles;
int i;
char mapname[128];
bool bTugOfWar = false, bObjective = false, bLiberation = false;
listbox->DeleteAllItems();
if (gameType == "tow") {
bTugOfWar = true;
} else if (gameType == "obj") {
bObjective = true;
} else if (gameType == "lib") {
bLiberation = true;
} else {
// retrieve directories
filenames = FS_ListFiles(rootDirectory, ".bsp", qfalse, &numfiles);
for (i = 0; i < numfiles; i++) {
const char *filename = filenames[i];
strcpy(mapname, filename);
mapname[strlen(mapname) - 4] = 0;
if (COM_IsMapValid(mapname)) {
listbox->AddItem(new MpMapPickerItem(mapname, rootDirectory));
}
}
FS_FreeFileList(filenames);
}
if (currentDirectory.length()) {
if (currentDirectory == "maps/-/") {
SetupSecondaryFiles(currentDirectory, bTugOfWar, bObjective, bLiberation);
} else {
SetupSecondaryFiles("maps/obj/", bTugOfWar, bObjective, bLiberation);
SetupSecondaryFiles("maps/lib/", bTugOfWar, bObjective, bLiberation);
}
}
listbox->SortByColumn(0);
}
void MpMapPickerClass::FileSelected( Event *ev )
void MpMapPickerClass::SetupSecondaryFiles(const char *path, bool bTugOfWar, bool bObjective, bool bLiberation)
{
// FIXME: stub
char **filenames;
int numfiles;
int i;
char mapname[128];
char string[1024];
filenames = FS_ListFiles(path, ".bsp", qfalse, &numfiles);
for (i = 0; i < numfiles; i++) {
const char *filename = filenames[i];
const char *token;
strcpy(mapname, filename);
mapname[strlen(mapname) - 4] = 0;
if (!COM_IsMapValid(mapname)) {
continue;
}
if (bTugOfWar || bObjective || bLiberation) {
bool bHasMP = false, bHasTOW = false, bHasLib = false;
strcpy(string, mapname);
for (token = strtok(string, "_"); token; token = strtok(NULL, "_")) {
if (bObjective) {
if (!Q_stricmp(token, "obj")) {
listbox->AddItem(new MpMapPickerItem(mapname, path));
} else if (!Q_stricmp(token, "ship")) {
listbox->AddItem(new MpMapPickerItem(mapname, path));
}
}
if (bTugOfWar) {
if (!Q_stricmp(token, "MP")) {
bHasMP = true;
}
if (!Q_stricmp(token, "TOW")) {
bHasTOW = true;
}
if (bHasMP && bHasTOW) {
listbox->AddItem(new MpMapPickerItem(mapname, path));
}
}
if (bLiberation) {
if (!Q_stricmp(token, "MP")) {
bHasMP = true;
}
if (!Q_stricmp(token, "LIB")) {
bHasLib = true;
}
if (bHasMP && bHasLib) {
listbox->AddItem(new MpMapPickerItem(mapname, path));
}
}
}
} else {
if (!Q_stricmp(mapname, "obj_team2") || !Q_stricmp(mapname, "obj_team4")) {
continue;
}
listbox->AddItem(new MpMapPickerItem(mapname, path));
}
}
FS_FreeFileList(filenames);
}
void MpMapPickerClass::FileSelected( str& currentDirectory, str& partialName, str& fullname )
void MpMapPickerClass::FileSelected(const str& currentDirectory, const str& partialName, const str& fullname)
{
// FIXME: stub
FileChosen(currentDirectory, partialName, fullname);
}
void MpMapPickerClass::FileChosen( Event *ev )
void MpMapPickerClass::FileSelected(Event *ev)
{
// FIXME: stub
if (!listbox->getCurrentItem()) {
return;
}
uii.Snd_PlaySound("sound/menu/apply.wav");
UIListCtrlItem* item = listbox->GetItem(listbox->getCurrentItem());
str name = item->getListItemString(0);
str directory = item->getListItemString(1);
FileSelected(directory, name, directory + name);
}
void MpMapPickerClass::FileChosen( str& currentDirectory, str& partialName, str& fullname )
void MpMapPickerClass::FileChosen(const str& currentDirectory, const str& partialName, const str& fullname)
{
// FIXME: stub
const char *pszFilename;
str sCommand;
pszFilename = fullname.c_str();
sCommand = va("ui_dmmap %s\n", pszFilename + 5);
Cbuf_AddText(sCommand);
CloseWindow();
}
void MpMapPickerClass::OnDeactivated( Event *ev )
void MpMapPickerClass::FileChosen(Event *ev)
{
// FIXME: stub
if (!listbox->getCurrentItem()) {
return;
}
uii.Snd_PlaySound("sound/menu/apply.wav");
UIListCtrlItem* item = listbox->GetItem(listbox->getCurrentItem());
str name = item->getListItemString(0);
str directory = item->getListItemString(1);
FileSelected(directory, name, directory + name);
}
void MpMapPickerClass::Setup( const char *root_directory, const char *current_directory )
void MpMapPickerClass::CloseWindow(void)
{
// FIXME: stub
PostEvent(EV_Remove, 0);
}
void MpMapPickerClass::OnDeactivated(Event *ev)
{
CloseWindow();
}
MpMapPickerItem::MpMapPickerItem(const str& string, const str& directory)
{
m_string = string;
m_directory = directory;
}
int MpMapPickerItem::getListItemValue(int which) const
{
return atoi(m_string);
}
griditemtype_t MpMapPickerItem::getListItemType(int which) const
{
return griditemtype_t::TYPE_STRING;
}
str MpMapPickerItem::getListItemString(int which) const
{
switch (which) {
default:
case 0:
return m_string;
case 1:
return m_directory;
}
}
void MpMapPickerItem::DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) {}
qboolean MpMapPickerItem::IsHeaderEntry() const
{
return qfalse;
}
+25 -24
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -20,39 +20,40 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __CL_UIMPMAPPICKER_H__
#define __CL_UIMPMAPPICKER_H__
#pragma once
class UIFloatingWindow;
class MpMapPickerClass : public USignal {
UIFloatingWindow *window;
UIListCtrl *listbox;
str currentDirectory;
str rootDirectory;
class MpMapPickerClass : public USignal
{
UIFloatingWindow *window;
UIListCtrl *listbox;
str currentDirectory;
str rootDirectory;
str gameType;
public:
CLASS_PROTOTYPE( MpMapPickerClass );
CLASS_PROTOTYPE(MpMapPickerClass);
private:
void SetupFiles( void );
void GotoParentDirectory( void );
void GotoSubDirectory( str subdir );
void Initialize( const char *root_directory, const char *current_directory );
void SetupFiles(void);
void SetupSecondaryFiles(const char *path, bool bTugOfWar, bool bObjective, bool bLiberation);
void GotoParentDirectory(void);
void GotoSubDirectory(str subdir);
void Initialize(const char *root_directory, const char *current_directory, const char *game_type);
protected:
void CloseWindow( void );
void FileSelected( Event *ev );
virtual void FileSelected( str& currentDirectory, str& partialName, str& fullname );
void FileChosen( Event *ev );
virtual void FileChosen( str& currentDirectory, str& partialName, str& fullname );
void OnDeactivated( Event *ev );
void CloseWindow(void);
void FileSelected(Event *ev);
virtual void FileSelected(const str& currentDirectory, const str& partialName, const str& fullname);
void FileChosen(Event *ev);
virtual void FileChosen(const str& currentDirectory, const str& partialName, const str& fullname);
void OnDeactivated(Event *ev);
public:
MpMapPickerClass();
~MpMapPickerClass();
MpMapPickerClass();
~MpMapPickerClass();
void Setup( const char *root_directory, const char *current_directory );
// game_type was added in 2.0
void Setup(const char *root_directory, const char *current_directory, const char *game_type = NULL);
};
#endif /* __CL_UIMPMAPPICKER_H__ */
+322 -23
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -22,62 +22,361 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cl_ui.h"
CLASS_DECLARATION( USignal, PlayerModelPickerClass, NULL )
class PMPickerItem : public UIListCtrlItem
{
{ NULL, NULL }
str m_string;
public:
PMPickerItem(const str& string);
int getListItemValue(int which) const override;
griditemtype_t getListItemType(int which) const override;
str getListItemString(int which) const override;
void DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) override;
qboolean IsHeaderEntry() const override;
};
typedef struct {
const char *fileName;
const char *displayName;
} PMPickerModel_t;
static const PMPickerModel_t pickerModels[] = {
// 2.0 skins
{"allied_101st_captain", "US - 101st Airborne Captain" },
{"allied_101st_infantry", "US - 101st Airborne Private 1" },
{"allied_101st_scout", "US - 101st Airborne Private 2" },
{"allied_501st_pir_scout", "US - 501st Paratrooper 1" },
{"allied_501st_pir_soldier", "US - 501st Paratrooper 2" },
// 1.0 skins
{"allied_airborne", "US - 501st Paratrooper 3" },
// Readded in OPM (was removed in 2.0)
{"allied_manon", "US - Manon" },
// 2.0 skins
{"allied_british_6th_airborne_captain", "UK - 6th Airborne Captain" },
{"allied_british_6th_airborne_paratrooper", "UK - 6th Airborne Paratrooper" },
// 1.0 skins
{"allied_pilot", "US - Army Pilot" },
// 2.0 skins
{"allied_russian_corporal", "RA - Corporal" },
{"allied_russian_crazy_boris", "RA - Crazy Boris" },
{"allied_russian_recon_scout", "RA - Junior Lieutenant" },
{"allied_russian_recon_soldier", "RA - Black Sea Petty Officer" },
// 1.0 skins
{"allied_sas", "UK - SAS Officer" },
{"american_army", "US - Soldier" },
{"american_ranger", "US - Ranger" },
// 1.0 skins
{"german_afrika_officer", "DE - Afrika Officer" },
{"german_afrika_private", "DE - Afrika Private" },
// 2.0 skins
{"german_ardennes_artillery_commander", "DE - Artillery Commander" },
{"german_dday_colonel", "DE - Normandy Colonel" },
// 1.0 skins
{"german_elite_officer", "DE - Elite Officer" },
{"german_elite_sentry", "DE - Elite Sentry" },
{"german_kradshutzen", "DE - Kradshutzen" },
{"german_panzer_grenadier", "DE - Panzer Grenadier" },
{"german_panzer_obershutze", "DE - Panzer Obershutze" },
{"german_panzer_shutze", "DE - Panzer Shutze" },
{"german_panzer_tankcommander", "DE - Panzer Tank Commander" },
{"german_scientist", "DE - German Scientist" },
// Those skins were superseded by german_waffenss
{"german_waffen_officer", "DE - Waffen Officer" },
{"german_waffen_shutze", "DE - Waffen Shutze" },
// 1.0 skins
{"german_waffenss_officer", "DE - Waffen Officer" },
{"german_waffenss_shutze", "DE - Waffen Shutze" },
{"german_wehrmacht_officer", "DE - Wehrmacht Officer" },
{"german_wehrmacht_soldier", "DE - Wehrmacht Soldier" },
{"german_winter_1", "DE - Winter Infantry 1" },
{"german_winter_2", "DE - Winter Infantry 2" },
{"german_worker", "DE - German Mechanic" },
// 2.11 skins
{"allied_british_tank_corporal", "UK - 6th Royal Tank Regiment" },
{"allied_russian_seaman", "RA - Red Navy Seaman" },
{"german_Panzer_Corporal", "DE - 1st Panzer Regiment" },
{"allied_technician", "US - Air Force Technician" },
{"german_stukageschwader", "DE - Stukageschwader" },
// 2.30 skins
{"It_AX_Ital_Vol", "IT - 10th Army XXI Corps" },
{"SC_AX_Ital_Inf", "IT - 6th Army 202nd Coastal Div"},
{"SC_AX_Ital_Inf2", "IT - 114th Inf Regiment" },
{"SC_AX_ITAL_PARA", "IT - Paracadutista Militare" },
// 2.40 skins
{"allied_Wheathers", "US - General Wheathers" },
{"allied_US_Tank", "US - II Corps Tank Commander" },
{"allied_US_Mask", "US - II Corps Infantry" },
{"allied_british_Cmd", "UK - 10th Corps" },
{"allied_british_Tank", "UK - 8th Army" },
{NULL, NULL }
};
const char *PM_FilenameToDisplayname(const char *fileName)
{
int i;
for (i = 0; pickerModels[i].fileName; i++) {
const PMPickerModel_t& model = pickerModels[i];
if (!Q_stricmp(model.fileName, fileName)) {
return model.displayName;
}
}
return fileName;
}
const char *PM_DisplaynameToFilename(const char *displayName)
{
int i;
for (i = 0; pickerModels[i].fileName; i++) {
const PMPickerModel_t& model = pickerModels[i];
if (!Q_stricmp(model.displayName, displayName)) {
return model.fileName;
}
}
return displayName;
}
CLASS_DECLARATION(USignal, PlayerModelPickerClass, NULL) {
{&EV_UIListBase_ItemSelected, &PlayerModelPickerClass::FileSelected },
{&EV_UIListBase_ItemDoubleClicked, &PlayerModelPickerClass::FileChosen },
{&UIFloatingWindow::W_ClosePressed, &PlayerModelPickerClass::OnDeactivated},
{&W_Deactivated, &PlayerModelPickerClass::OnDeactivated},
{NULL, NULL }
};
PlayerModelPickerClass::PlayerModelPickerClass()
{
// FIXME: stub
window = new UIFloatingWindow();
window->Create(
NULL,
UIRect2D((cls.glconfig.vidWidth - 400) / 2, (cls.glconfig.vidHeight - 300) / 2, 400, 300),
"Player Model Select...",
UColor(0.15f, 0.195f, 0.278f),
UHudColor
);
window->setFont("facfont-20");
window->PassEventToWidget("closebutton", new Event(EV_Widget_Disable));
window->PassEventToWidget("minimizebutton", new Event(EV_Widget_Disable));
window->Connect(this, W_Deactivated, W_Deactivated);
listbox = new UIListCtrl();
listbox->InitFrame(window->getChildSpace(), window->getChildSpace()->getClientFrame(), 0);
listbox->SetDrawHeader(false);
listbox->setFont("facfont-20");
listbox->FrameInitialized();
listbox->AddColumn("Player Model", 0, 400, false, false);
listbox->Connect(this, EV_UIListBase_ItemDoubleClicked, EV_UIListBase_ItemDoubleClicked);
listbox->Connect(this, EV_UIListBase_ItemSelected, EV_UIListBase_ItemSelected);
listbox->AllowActivate(true);
// Added in 2.0
// Don't localize elements
listbox->SetDontLocalize();
m_bGermanModels = false;
}
PlayerModelPickerClass::~PlayerModelPickerClass()
{
// FIXME: stub
if (listbox) {
delete listbox;
listbox = NULL;
}
if (window) {
delete window;
window = NULL;
}
}
void PlayerModelPickerClass::SetupFiles( void )
void PlayerModelPickerClass::Setup(const char *root_directory, const char *current_directory, qboolean bGermanModels)
{
// FIXME: stub
Initialize(root_directory, current_directory, bGermanModels);
}
void PlayerModelPickerClass::Initialize( const char *root_directory, const char *current_directory, qboolean bGermanModels )
void PlayerModelPickerClass::Initialize(
const char *root_directory, const char *current_directory, qboolean bGermanModels
)
{
// FIXME: stub
rootDirectory = root_directory;
m_bGermanModels = bGermanModels;
if (rootDirectory.length() > 1 && rootDirectory[rootDirectory.length() - 1] != '/') {
rootDirectory += "/";
}
currentDirectory = current_directory;
if (currentDirectory.length() > 1 && currentDirectory[currentDirectory.length() - 1] != '/') {
currentDirectory += "/";
}
SetupFiles();
}
void PlayerModelPickerClass::CloseWindow( void )
void PlayerModelPickerClass::SetupFiles(void)
{
// FIXME: stub
str mappath;
char work[128];
char **filenames;
const char *displayName;
int numfiles;
int i;
int iLen;
qboolean bIsGerman;
// cleanup
listbox->DeleteAllItems();
if (m_bGermanModels) {
window->setTitle("Select Your Axis Player Model");
} else {
window->setTitle("Select Your Allied Player Model");
}
filenames = FS_ListFiles(currentDirectory, ".tik", qfalse, &numfiles);
for (i = 0; i < numfiles; i++) {
Q_strncpyz(work, filenames[i], sizeof(work));
if (strstr(work, "_fps")) {
// ignore view models
continue;
}
if (work[0] == '_') {
// ignore hidden models
continue;
}
// allied_manon readded in OPM
//if (!Q_stricmpn(work, "allied_manon")) {
// continue;
//}
bIsGerman = !Q_stricmpn(work, "german", 6u) || !Q_stricmpn(work, "axis", 4u) || !Q_stricmpn(work, "it", 2u)
|| !Q_stricmpn(work, "sc", 2u);
if (m_bGermanModels != bIsGerman) {
continue;
}
// strip the extension
work[strlen(work) - 4] = 0;
displayName = PM_FilenameToDisplayname(work);
listbox->AddItem(new PMPickerItem(displayName));
}
FS_FreeFileList(filenames);
listbox->SortByColumn(0);
}
void PlayerModelPickerClass::FileSelected( Event *ev )
void PlayerModelPickerClass::FileSelected(
const str& name, const str& currentDirectory, const str& partialName, const str& fullname
)
{
// FIXME: stub
FileChosen(name, currentDirectory, partialName, fullname);
}
void PlayerModelPickerClass::FileSelected( str& currentDirectory, str& partialName, str& fullname )
void PlayerModelPickerClass::FileSelected(Event *ev)
{
// FIXME: stub
str name;
char donotshowssindeorfr[64];
str fullname;
name = listbox->GetItem(listbox->getCurrentItem())->getListItemString(0);
fullname = PM_DisplaynameToFilename(name);
if (!Q_stricmpn(fullname, "german_waffen_", 14)) {
Q_strncpyz(donotshowssindeorfr, "german_waffen_", sizeof(donotshowssindeorfr));
Q_strcat(donotshowssindeorfr, sizeof(donotshowssindeorfr), fullname.c_str() + 14);
} else {
Q_strncpyz(donotshowssindeorfr, fullname, sizeof(donotshowssindeorfr));
}
FileSelected(name, currentDirectory, fullname, currentDirectory + donotshowssindeorfr);
}
void PlayerModelPickerClass::FileChosen( Event *ev )
void PlayerModelPickerClass::FileChosen(
const str& name, const str& currentDirectory, const str& partialName, const str& fullname
)
{
// FIXME: stub
str sCommand;
if (m_bGermanModels) {
sCommand += "ui_dm_playergermanmodel \"" + name;
sCommand += "\" ; ui_dm_playergermanmodel_set " + partialName;
sCommand += " ; ui_disp_playergermanmodel " + fullname + ".tik";
} else {
sCommand += "ui_dm_playermodel \"" + name;
sCommand += "\" ; ui_dm_playermodel_set " + partialName;
sCommand += " ; ui_disp_playermodel " + fullname + ".tik";
}
sCommand += "\n";
Cbuf_AddText(sCommand);
CloseWindow();
}
void PlayerModelPickerClass::FileChosen( str& currentDirectory, str& partialName, str& fullname )
void PlayerModelPickerClass::FileChosen(Event *ev)
{
// FIXME: stub
str name;
char donotshowssindeorfr[64];
str fullname;
name = listbox->GetItem(listbox->getCurrentItem())->getListItemString(0);
fullname = PM_DisplaynameToFilename(name);
if (!Q_stricmpn(fullname, "german_waffen_", 14)) {
Q_strncpyz(donotshowssindeorfr, "german_waffen_", sizeof(donotshowssindeorfr));
Q_strcat(donotshowssindeorfr, sizeof(donotshowssindeorfr), fullname.c_str() + 14);
} else {
Q_strncpyz(donotshowssindeorfr, fullname, sizeof(donotshowssindeorfr));
}
FileChosen(name, currentDirectory, fullname, currentDirectory + donotshowssindeorfr);
}
void PlayerModelPickerClass::OnDeactivated( Event *ev )
void PlayerModelPickerClass::CloseWindow(void)
{
// FIXME: stub
PostEvent(EV_Remove, 0);
}
void PlayerModelPickerClass::Setup( const char *root_directory, const char *current_directory, qboolean bGermanModels )
void PlayerModelPickerClass::OnDeactivated(Event *ev)
{
// FIXME: stub
CloseWindow();
}
PMPickerItem::PMPickerItem(const str& string)
{
m_string = string;
}
int PMPickerItem::getListItemValue(int which) const
{
return atoi(m_string);
}
griditemtype_t PMPickerItem::getListItemType(int which) const
{
return griditemtype_t::TYPE_STRING;
}
str PMPickerItem::getListItemString(int which) const
{
return m_string;
}
void PMPickerItem::DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont *pFont) {}
qboolean PMPickerItem::IsHeaderEntry() const
{
return qfalse;
}
+26 -22
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -20,37 +20,41 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __CL_UIPLAYERMODELPICKER_H__
#define __CL_UIPLAYERMODELPICKER_H__
#pragma once
class UIFloatingWindow;
class PlayerModelPickerClass : public USignal {
UIFloatingWindow *window;
UIListCtrl *listbox;
str currentDirectory;
str rootDirectory;
qboolean m_bGermanModels;
class PlayerModelPickerClass : public USignal
{
UIFloatingWindow *window;
UIListCtrl *listbox;
str currentDirectory;
str rootDirectory;
qboolean m_bGermanModels;
public:
CLASS_PROTOTYPE( PlayerModelPickerClass );
CLASS_PROTOTYPE(PlayerModelPickerClass);
private:
void SetupFiles( void );
void Initialize( const char *root_directory, const char *current_directory, qboolean bGermanModels );
void SetupFiles(void);
void Initialize(const char *root_directory, const char *current_directory, qboolean bGermanModels);
protected:
void CloseWindow( void );
void FileSelected( Event *ev );
virtual void FileSelected( str& currentDirectory, str& partialName, str& fullname );
void FileChosen( Event *ev );
virtual void FileChosen( str& currentDirectory, str& partialName, str& fullname );
void OnDeactivated( Event *ev );
void CloseWindow(void);
void FileSelected(Event *ev);
// The name parameter was added in 2.0.
virtual void FileSelected(const str& name, const str& currentDirectory, const str& partialName, const str& fullname);
void FileChosen(Event *ev);
// The name parameter was added in 2.0.
virtual void FileChosen(const str& name, const str& currentDirectory, const str& partialName, const str& fullname);
void OnDeactivated(Event *ev);
public:
PlayerModelPickerClass();
~PlayerModelPickerClass();
PlayerModelPickerClass();
~PlayerModelPickerClass();
void Setup( const char *root_directory, const char *current_directory, qboolean bGermanModels );
void Setup(const char *root_directory, const char *current_directory, qboolean bGermanModels);
};
#endif /* __CL_UIPLAYERMODELPICKER_H__ */
const char* PM_FilenameToDisplayname(const char* fileName);
const char* PM_DisplaynameToFilename(const char* displayName);
+69 -35
View File
@@ -79,6 +79,7 @@ struct ServerListInstance {
};
class FAKKServerListItem : public UIListCtrlItem {
UIFAKKServerList* m_parent; // Added in OPM
str m_strings[6];
str m_sVersion;
bool m_bDifferentVersion;
@@ -94,7 +95,7 @@ public:
int m_iGameSpyPort;
public:
FAKKServerListItem(str string1, str string2, str string3, str string4, str string5, str string6, str ver);
FAKKServerListItem(UIFAKKServerList* parent, str string1, str string2, str string3, str string4, str string5, str string6, str ver);
griditemtype_t getListItemType(int index) const override;
int getListItemValue(int i) const override;
@@ -125,8 +126,9 @@ ServerListInstance g_ServerListInst[2];
void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, void* param1, void* param2);
static void AddFilter(char* filter, const char* value);
FAKKServerListItem::FAKKServerListItem(str string1, str string2, str string3, str string4, str string5, str string6, str ver)
FAKKServerListItem::FAKKServerListItem(UIFAKKServerList* parent, str string1, str string2, str string3, str string4, str string5, str string6, str ver)
{
m_parent = parent;
m_strings[0] = string1;
m_strings[1] = string2;
m_strings[2] = string3;
@@ -164,84 +166,95 @@ void FAKKServerListItem::setListItemString(int i, str sNewString)
void FAKKServerListItem::DrawListItem(int iColumn, const UIRect2D& drawRect, bool bSelected, UIFont* pFont)
{
static cvar_t *pColoringType = Cvar_Get("cl_browserdetailedcolors", "0", CVAR_ARCHIVE);
UIRect2D newRect = drawRect;
vec2_t virtualScale = { 1.f, 1.f };
/*
if (m_parent->isVirtual()) {
virtualScale[0] = uid.vidWidth / 640.f;
virtualScale[1] = uid.vidHeight / 480.f;
newRect.size.width *= uid.vidWidth / 1024;
newRect.size.height *= uid.vidHeight / 768;
}
*/
if (!pColoringType->integer) {
if (IfQueryFailed() || (IsDifferentVersion() && IsQueried())) {
if (bSelected) {
DrawBox(drawRect, UColor(0.2f, 0.0f, 0.0f), 1.0);
DrawBox(newRect, UColor(0.2f, 0.0f, 0.0f), 1.0);
pFont->setColor(UColor(0.9f, 0.0f, 0.0f));
} else {
DrawBox(drawRect, UColor(0.1f, 0.0f, 0.0f), 1.0);
DrawBox(newRect, UColor(0.1f, 0.0f, 0.0f), 1.0);
pFont->setColor(UColor(0.55f, 0.0f, 0.0f));
}
} else if (IsQueried()) {
if (bSelected) {
DrawBox(drawRect, UColor(0.2f, 0.18f, 0.015f), 1.0);
DrawBox(newRect, UColor(0.2f, 0.18f, 0.015f), 1.0);
pFont->setColor(UColor(0.9f, 0.8f, 0.6f));
} else {
DrawBox(drawRect, UColor(0.02f, 0.07f, 0.004f), 1.0);
DrawBox(newRect, UColor(0.02f, 0.07f, 0.004f), 1.0);
pFont->setColor(UHudColor);
}
} else {
if (bSelected) {
DrawBox(drawRect, UColor(0.15f, 0.18f, 0.18f), 1.0);
DrawBox(newRect, UColor(0.15f, 0.18f, 0.18f), 1.0);
pFont->setColor(UColor(0.6f, 0.7f, 0.8f));
} else {
DrawBox(drawRect, UColor(0.005f, 0.07f, 0.02f), 1.0);
DrawBox(newRect, UColor(0.005f, 0.07f, 0.02f), 1.0);
pFont->setColor(UColor(0.05f, 0.5f, 0.6f));
}
}
pFont->Print(
drawRect.pos.x + 1.0,
drawRect.pos.y,
newRect.pos.x / virtualScale[0] + 1.0,
newRect.pos.y / virtualScale[1],
getListItemString(iColumn).c_str(),
-1,
qfalse
false //m_parent->isVirtual()
);
} else {
if (IsDifferentVersion()) {
if (IsQueried()) {
if (bSelected) {
DrawBox(drawRect, UColor(0.25f, 0.0f, 0.0f), 1.0);
DrawBox(newRect, UColor(0.25f, 0.0f, 0.0f), 1.0);
pFont->setColor(UColor(0.0f, 0.5f, 0.0f));
} else {
DrawBox(drawRect, UColor(0.005f, 0.07f, 0.02f), 1.0);
DrawBox(newRect, UColor(0.005f, 0.07f, 0.02f), 1.0);
pFont->setColor(UColor(0.0f, 0.35f, 0.0f));
}
} else {
if (bSelected) {
DrawBox(drawRect, UColor(0.25f, 0.0f, 0.0f), 1.0);
DrawBox(newRect, UColor(0.25f, 0.0f, 0.0f), 1.0);
pFont->setColor(UColor(0.5f, 0.6f, 0.7f));
} else {
DrawBox(drawRect, UColor(0.15f, 0.0f, 0.0f), 1.0);
DrawBox(newRect, UColor(0.15f, 0.0f, 0.0f), 1.0);
pFont->setColor(UColor(0.05f, 0.4f, 0.5f));
}
}
} else if (IsQueried()) {
if (bSelected) {
DrawBox(drawRect, UColor(0.2f, 0.18f, 0.015f), 1.0);
DrawBox(newRect, UColor(0.2f, 0.18f, 0.015f), 1.0);
pFont->setColor(UColor(0.9f, 0.8f, 0.6f));
} else {
DrawBox(drawRect, UColor(0.02f, 0.07f, 0.005f), 1.0);
DrawBox(newRect, UColor(0.02f, 0.07f, 0.005f), 1.0);
pFont->setColor(UHudColor);
}
} else {
if (bSelected) {
DrawBox(drawRect, UColor(0.15f, 0.18f, 0.18f), 1.0);
DrawBox(newRect, UColor(0.15f, 0.18f, 0.18f), 1.0);
pFont->setColor(UColor(0.6f, 0.7f, 0.8f));
} else {
DrawBox(drawRect, UColor(0.005f, 0.07f, 0.02f), 1.0);
DrawBox(newRect, UColor(0.005f, 0.07f, 0.02f), 1.0);
pFont->setColor(UColor(0.05f, 0.5f, 0.6f));
}
if (IfQueryFailed()) {
DrawBox(
UIRect2D(
drawRect.pos.x,
drawRect.pos.y + drawRect.size.height * 0.5 - 1.0 + drawRect.pos.y,
drawRect.size.width,
drawRect.size.height * 0.5 - 1.0 + drawRect.pos.y
newRect.pos.x,
newRect.pos.y + newRect.size.height * 0.5 - 1.0 + newRect.pos.y,
newRect.size.width,
newRect.size.height * 0.5 - 1.0 + newRect.pos.y
),
URed,
0.3f
@@ -249,19 +262,19 @@ void FAKKServerListItem::DrawListItem(int iColumn, const UIRect2D& drawRect, boo
}
pFont->Print(
drawRect.pos.x + 1.0,
drawRect.pos.y,
newRect.pos.x / virtualScale[0] + 1.0,
newRect.pos.y / virtualScale[1],
getListItemString(iColumn).c_str(),
-1,
qfalse
false //m_parent->isVirtual()
);
if (IsDifferentVersion()) {
DrawBox(
UIRect2D(
drawRect.pos.x,
drawRect.pos.y + drawRect.size.height * 0.5 - 1.0 + drawRect.pos.y,
drawRect.size.width,
newRect.pos.x,
newRect.pos.y + newRect.size.height * 0.5 - 1.0 + newRect.pos.y,
newRect.size.width,
1.0
),
URed,
@@ -730,6 +743,14 @@ void UIFAKKServerList::UpdateServer( Event *ev )
FAKKServerListItem* item = (FAKKServerListItem*)GetItem(getCurrentItem());
ServerListAuxUpdate(m_serverList[0], item->m_sIP.c_str(), item->m_iGameSpyPort, true, GQueryType::qt_status);
if (com_target_game->integer >= target_game_e::TG_MOHTT) {
const cvar_t* dm_omit_spearhead = Cvar_Get("dm_omit_spearhead", "0", CVAR_ARCHIVE);
// check for Spearhead
if (!dm_omit_spearhead->integer) {
ServerListAuxUpdate(m_serverList[1], item->m_sIP.c_str(), item->m_iGameSpyPort, true, GQueryType::qt_status);
}
}
}
int UIFAKKServerList::ServerCompareFunction( const UIListCtrlItem *i1, const UIListCtrlItem *i2, int columnname )
@@ -1009,7 +1030,7 @@ void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, v
return;
}
Cvar_Set("dm_serverstatusbar", va("%i", param2));
Cvar_Set("dm_serverstatusbar", va("%i", (int)(uintptr_t)param2));
}
if (msg == LIST_PROGRESS)
@@ -1019,23 +1040,36 @@ void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, v
str sServerName;
str sPlayers;
const char* pszGameVer;
const char* pszGameVerNumber;
pszHostName = ServerGetStringValue(server, "hostname", "(NONE)");
bDiffVersion = false;
pszGameVer = ServerGetStringValue(server, "gamever", "1.00");
pszGameVerNumber = pszGameVer;
if (pszGameVerNumber[0] == 'd') {
// demo server
pszGameVerNumber++;
}
if (com_target_game->integer >= target_game_e::TG_MOHTT) {
if (iServerType == target_game_e::TG_MOHTT) {
if (fabs(atof(pszGameVer) - com_target_version->value) > 0.1f) {
//if (fabs(atof(pszGameVerNumber) - com_target_version->value) > 0.1f) {
// bDiffVersion = true;
//}
if (fabs(atof(pszGameVerNumber)) < 2.3f) {
bDiffVersion = true;
}
} else {
if (fabs(atof(pszGameVer) - com_target_version->value) > 0.3f) {
//if (fabs(atof(pszGameVerNumber) - com_target_version->value) > 0.3f) {
// bDiffVersion = true;
//}
if (fabs(atof(pszGameVerNumber)) < 2.1f) {
bDiffVersion = true;
}
}
} else {
if (fabs(atof(pszGameVer) - com_target_version->value) > 0.1f) {
if (fabs(atof(pszGameVerNumber) - com_target_version->value) > 0.1f) {
bDiffVersion = true;
}
}
@@ -1056,7 +1090,7 @@ void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, v
}
if (i > uiServerList->getNumItems() || !pNewServerItem) {
pNewServerItem = new FAKKServerListItem("?", sAddress, "?", "?/?", "?", "?", "?");
pNewServerItem = new FAKKServerListItem(uiServerList, "?", sAddress, "?", "?/?", "?", "?", "?");
pNewServerItem->m_sIP = ServerGetAddress(server);
pNewServerItem->m_uiRealIP = iRealIP;
pNewServerItem->m_iGameSpyPort = iGameSpyPort;
@@ -1154,7 +1188,7 @@ void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, v
continue;
}
pNewServerItem = new FAKKServerListItem("?", sAddress, "?", "?/?", "?", "?", "?");
pNewServerItem = new FAKKServerListItem(uiServerList, "?", sAddress, "?", "?/?", "?", "?", "?");
pNewServerItem->m_sIP = ServerGetAddress(arrayServer);
pNewServerItem->m_uiRealIP = iRealIP;
pNewServerItem->m_iPort = PORT_SERVER;
+29 -9
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -22,22 +22,42 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cl_ui.h"
CLASS_DECLARATION( FilePickerClass, SoundPickerClass, NULL )
{
{ NULL, NULL }
CLASS_DECLARATION(FilePickerClass, SoundPickerClass, NULL) {
{NULL, NULL}
};
SoundPickerClass::SoundPickerClass()
{
// FIXME: stub
str soundpath;
str currentpath;
const char *varValue;
int i;
soundpath = "sound";
varValue = UI_GetCvarString("ui_pickedsound", NULL);
if (varValue && *varValue) {
currentpath = varValue;
for (i = currentpath.length(); i > 0; i--) {
if (currentpath[i] == '/') {
break;
}
}
currentpath = str(currentpath, 0, i + 1);
} else {
currentpath = soundpath;
}
}
void SoundPickerClass::FileSelected( str &currentDirectory, str &partialName, str &fullname )
void SoundPickerClass::FileSelected(const str& currentDirectory, const str& partialName, const str& fullname)
{
uii.Snd_PlaySound(fullname);
}
void SoundPickerClass::FileChosen( str &currentDirectory, str &partialName, str &fullname )
void SoundPickerClass::FileChosen(const str& currentDirectory, const str& partialName, const str& fullname)
{
uii.Cvar_Set("ui_pickedsound", fullname);
CloseWindow();
}
+8 -10
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -20,17 +20,15 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __CL_UISOUNDPICKER_H__
#define __CL_UISOUNDPICKER_H__
#pragma once
class SoundPickerClass : public FilePickerClass {
class SoundPickerClass : public FilePickerClass
{
public:
CLASS_PROTOTYPE( SoundPickerClass );
CLASS_PROTOTYPE(SoundPickerClass);
SoundPickerClass();
SoundPickerClass();
void FileSelected( str &currentDirectory, str &partialName, str &fullname ) override;
void FileChosen( str &currentDirectory, str &partialName, str &fullname ) override;
void FileSelected(const str& currentDirectory, const str& partialName, const str& fullname) override;
void FileChosen(const str& currentDirectory, const str& partialName, const str& fullname) override;
};
#endif /* __CL_UISOUNDPICKER_H__ */
+1210 -1162
View File
File diff suppressed because it is too large. Load diff
+73 -70
View File
@@ -20,85 +20,88 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __CL_UISTD_H__
#define __CL_UISTD_H__
#pragma once
typedef enum {
L_STATBAR_NONE,
L_STATBAR_HORIZONTAL,
L_STATBAR_VERTICAL,
L_STATBAR_VERTICAL_REVERSE,
L_STATBAR_VERTICAL_STAGGER_EVEN,
L_STATBAR_VERTICAL_STAGGER_ODD,
L_STATBAR_CIRCULAR,
L_STATBAR_NEEDLE,
L_STATBAR_ROTATOR,
L_STATBAR_COMPASS,
L_STATBAR_SPINNER,
L_STATBAR_HEADING_SPINNER
L_STATBAR_NONE,
L_STATBAR_HORIZONTAL,
L_STATBAR_VERTICAL,
L_STATBAR_VERTICAL_REVERSE,
L_STATBAR_VERTICAL_STAGGER_EVEN,
L_STATBAR_VERTICAL_STAGGER_ODD,
L_STATBAR_CIRCULAR,
L_STATBAR_NEEDLE,
L_STATBAR_ROTATOR,
L_STATBAR_COMPASS,
L_STATBAR_SPINNER,
L_STATBAR_HEADING_SPINNER
} statbar_orientation_t;
class UIFakkLabel : public UILabel {
extern Event EV_ClearInvItemReference;
class UIFakkLabel : public UILabel
{
protected:
SafePtr<inventory_item_t> m_lastitem;
int m_lastitemindex;
int m_stat;
int m_stat_configstring;
int m_maxstat;
int m_itemindex;
int m_inventoryrendermodelindex;
str m_sDrawModelName;
qboolean m_rendermodel;
statbar_orientation_t m_statbar_or;
float m_statbar_min;
float m_statbar_max;
float m_lastfrac;
float m_flashtime;
vec3_t m_offset;
vec3_t m_rotateoffset;
vec3_t m_angles;
float m_scale;
str m_anim;
UIReggedMaterial *m_statbar_material;
UIReggedMaterial *m_statbar_material_flash;
SafePtr<inventory_item_t> m_lastitem;
int m_lastitemindex;
int m_stat;
int m_stat_alpha;
int m_stat_configstring;
int m_maxstat;
int m_itemindex;
int m_inventoryrendermodelindex;
str m_sDrawModelName;
qboolean m_rendermodel;
statbar_orientation_t m_statbar_or;
float m_statbar_min;
float m_statbar_max;
float m_lastfrac;
float m_flashtime;
vec3_t m_offset;
vec3_t m_rotateoffset;
vec3_t m_angles;
float m_scale;
str m_anim;
UIReggedMaterial *m_statbar_material;
UIReggedMaterial *m_statbar_material_flash;
UIReggedMaterial *m_statbar_material_marker;
public:
CLASS_PROTOTYPE( UIFakkLabel );
CLASS_PROTOTYPE(UIFakkLabel);
UIFakkLabel();
UIFakkLabel();
void LayoutPlayerStat( Event *ev );
void LayoutPlayerStatConfigstring( Event *ev );
void LayoutMaxPlayerStat( Event *ev );
void LayoutItemIndex( Event *ev );
void InventoryRenderModelIndex( Event *ev );
void LayoutModelName( Event *ev );
void ClearInvItemReference( Event *ev );
void LayoutStatbar( Event *ev );
void LayoutStatbarShader( Event *ev );
void LayoutStatbarTileShader( Event *ev );
void LayoutStatbarShader_Flash( Event *ev );
void LayoutStatbarEndAngles( Event *ev );
void LayoutStatbarNeedleWidth( Event *ev );
void LayoutStatbarRotatorSize( Event *ev );
void LayoutStatbarTileShader_Flash( Event *ev );
void LayoutRenderModel( Event *ev );
void LayoutRenderModelOffset( Event *ev );
void LayoutRenderModelRotateOffset( Event *ev );
void LayoutRenderModelAngles( Event *ev );
void LayoutRenderModelScale( Event *ev );
void LayoutRenderModelAnim( Event *ev );
void LayoutPlayerStat(Event *ev);
void LayoutPlayerStatAlpha(Event *ev); // Added in 2.0
void LayoutPlayerStatConfigstring(Event *ev);
void LayoutMaxPlayerStat(Event *ev);
void LayoutItemIndex(Event *ev);
void InventoryRenderModelIndex(Event *ev);
void LayoutModelName(Event *ev);
void ClearInvItemReference(Event *ev);
void LayoutStatbar(Event *ev);
void LayoutStatbarShader(Event *ev);
void LayoutStatbarTileShader(Event *ev);
void LayoutStatbarShader_Flash(Event *ev);
void LayoutStatbarShader_Marker(Event *ev); // Added in 2.0
void LayoutStatbarEndAngles(Event *ev);
void LayoutStatbarNeedleWidth(Event *ev);
void LayoutStatbarRotatorSize(Event *ev);
void LayoutStatbarTileShader_Flash(Event *ev);
void LayoutRenderModel(Event *ev);
void LayoutRenderModelOffset(Event *ev);
void LayoutRenderModelRotateOffset(Event *ev);
void LayoutRenderModelAngles(Event *ev);
void LayoutRenderModelScale(Event *ev);
void LayoutRenderModelAnim(Event *ev);
void DrawStatbar( float frac );
void DrawStatCircle( float frac );
void DrawStatNeedle( float frac );
void DrawStatRotator( float frac );
void DrawStatCompass( float frac );
void DrawStatSpinner( float frac );
void StatCircleTexCoord( float fAng, vec3_t vTexCoord );
void DrawStatbar(float frac);
void DrawStatCircle(float frac);
void DrawStatNeedle(float frac);
void DrawStatRotator(float frac);
void DrawStatCompass(float frac);
void DrawStatSpinner(float frac);
void StatCircleTexCoord(float fAng, vec3_t vTexCoord);
void Draw( void ) override;
void Draw(void) override;
};
#endif
+513 -362
View File
@@ -21,424 +21,575 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "cl_ui.h"
#include "../qcommon/localization.h"
CLASS_DECLARATION( UIWidget, View3D, NULL )
{
{ &W_Activated, &View3D::OnActivate },
{ &W_Deactivated, &View3D::OnDeactivate },
{ &W_LeftMouseDown, &View3D::Pressed },
{ NULL, NULL }
CLASS_DECLARATION(UIWidget, View3D, NULL) {
{&W_Activated, &View3D::OnActivate },
{&W_Deactivated, &View3D::OnDeactivate},
{&W_LeftMouseDown, &View3D::Pressed },
{NULL, NULL }
};
#define MAX_SUBTITLES 4
cvar_t* subs[MAX_SUBTITLES];
cvar_t* teams[MAX_SUBTITLES];
float fadeTime[MAX_SUBTITLES];
float subLife[MAX_SUBTITLES];
float alpha[MAX_SUBTITLES];
char oldStrings[MAX_SUBTITLES][2048];
cvar_t *subs[MAX_SUBTITLES];
cvar_t *teams[MAX_SUBTITLES];
float fadeTime[MAX_SUBTITLES];
float subLife[MAX_SUBTITLES];
float alpha[MAX_SUBTITLES];
char oldStrings[MAX_SUBTITLES][2048];
View3D::View3D()
{
// set as transparent
setBackgroundColor(UClear, true);
// no border
setBorderStyle(border_none);
AllowActivate(true);
// set as transparent
setBackgroundColor(UClear, true);
// no border
setBorderStyle(border_none);
AllowActivate(true);
m_printfadetime = 0.0;
m_print_mat = NULL;
m_locationprint = qfalse;
m_printfadetime = 0.0;
m_print_mat = NULL;
m_locationprint = qfalse;
}
void View3D::Draw
(
void
)
void View3D::UpdateLocationPrint(int x, int y, const char *s, float alpha)
{
if (clc.state != CA_DISCONNECTED) {
SCR_DrawScreenField();
}
set2D();
re.SavePerformanceCounters();
Draw2D();
m_printstring = s;
m_printalpha = alpha;
m_printfadetime = 4000.0;
m_x_coord = x;
m_y_coord = y;
m_locationprint = qtrue;
}
void View3D::DrawLetterbox
(
void
)
void View3D::UpdateCenterPrint(const char *s, float alpha)
{
float frac;
vec4_t col;
m_printstring = s;
col[0] = col[1] = col[2] = 0;
col[3] = 1;
if (s[0] == '@') {
m_print_mat = uWinMan.RegisterShader(s + 1);
} else {
m_print_mat = NULL;
}
frac = cl.snap.ps.stats[STAT_LETTERBOX] / 32767.0;
if (frac > 0.0) {
m_letterbox_active = true;
re.SetColor(col);
re.DrawBox(0.0, 0.0, m_screenframe.size.width, m_screenframe.size.height);
re.DrawBox(0.0, m_screenframe.size.height - m_screenframe.size.height * frac, m_screenframe.size.width, m_screenframe.size.height);
} else {
m_letterbox_active = false;
}
m_printalpha = alpha;
m_printfadetime = 4000.0;
m_locationprint = qfalse;
}
void View3D::DrawFades
(
void
)
void View3D::PrintSound(int channel, const char *name, float vol, int rvol, float pitch, float base, int& line)
{
if (cl.snap.ps.blend[3] > 0) {
re.SetColor(cl.snap.ps.blend);
if (cl.snap.ps.stats[STAT_ADDFADE]) {
re.AddBox(0.0, 0.0, m_screenframe.size.width, m_screenframe.size.height);
} else {
re.DrawBox(0.0, 0.0, m_screenframe.size.width, m_screenframe.size.height);
}
}
char buf[255];
float x;
float xStep;
float height;
height = m_font->getHeight(false);
xStep = height;
x = 0;
sprintf(buf, "%d", channel);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, false);
x += xStep + xStep;
sprintf(buf, "%s", name);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, false);
x += xStep * 30.0;
sprintf(buf, "vol:%.2f", vol);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, false);
x += xStep * 8;
sprintf(buf, "rvol:%.2f", (float)(rvol / 128.f));
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, false);
x += xStep * 5;
sprintf(buf, "pit:%.2f", pitch);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, false);
x += xStep * 5;
sprintf(buf, "base:%d", (int)base);
m_font->Print(x, height * line + m_frame.pos.y, buf, -1, false);
line++;
}
void View3D::Draw2D
(
void
)
void View3D::Pressed(Event *ev)
{
if (!cls.no_menus) {
DrawFades();
}
DrawLetterbox();
if ((cl_debuggraph->integer || cl_timegraph->integer) && !cls.no_menus)
{
SCR_DrawDebugGraph();
}
else if (!cls.no_menus)
{
if (cge) {
cge->CG_Draw2D();
}
if (m_locationprint) {
LocationPrint();
} else {
CenterPrint();
}
if (!cls.no_menus)
{
DrawSoundOverlay();
DrawSubtitleOverlay();
}
}
if (fps->integer && !cls.no_menus)
{
DrawFPS();
DrawProf();
}
IN_MouseOff();
OnActivate(ev);
}
void View3D::DrawFPS
(
void
)
void View3D::OnDeactivate(Event *ev)
{
char string[128];
setFont("verdana-14");
if (fps->integer == 2)
{
re.SetColor(UBlack);
re.DrawBox(
0.0,
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 4.0,
m_frame.pos.x + m_frame.size.width,
m_font->getHeight(qfalse) * 4.0
);
}
sprintf(string, "FPS %4.1f", currentfps);
if (currentfps > 23.94) {
if (cl_greenfps->integer) {
m_font->setColor(UGreen);
} else {
m_font->setColor(UWhite);
}
} else if (currentfps > 18.0) {
m_font->setColor(UYellow);
} else {
// low fps
m_font->setColor(URed);
}
m_font->Print(
m_font->getHeight(qfalse) * 10.0,
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 3.0,
string,
-1,
qfalse
);
// Draw elements count
if (cl_greenfps->integer) {
m_font->setColor(UGreen);
}
else {
m_font->setColor(UWhite);
}
sprintf(string, "wt%5d wv%5d cl%d", cls.world_tris, cls.world_verts, cls.character_lights);
m_font->Print(
m_font->getHeight(qfalse) * 10.0,
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 2.0,
string,
-1,
qfalse
);
sprintf(string, "t%5d v%5d Mtex%5.2f", cls.total_tris, cls.total_verts, (float)cls.total_texels * 0.00000095367432);
m_font->Print(
m_font->getHeight(qfalse) * 10.0,
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse),
string,
-1,
qfalse
);
m_font->setColor(UBlack);
cls.keyCatchers |= KEYCATCH_UI;
}
void View3D::DrawProf
(
void
)
void View3D::OnActivate(Event *ev)
{
// Normal empty function
}
void View3D::PrintSound
(
int channel,
const char *name,
float vol,
int rvol,
float pitch,
float base,
int& line
)
{
// FIXME: unimplemented
}
void View3D::DrawSoundOverlay
(
void
)
{
setFont("verdana-14");
m_font->setColor(UWhite);
if (sound_overlay->integer) {
Com_Printf("sound_overlay isn't supported with OpenAL/SDL right now.\n");
Cvar_Set("sound_overlay", "0");
}
}
void View3D::CenterPrint
(
void
)
{
// FIXME: unimplemented
}
void View3D::LocationPrint
(
void
)
{
// FIXME: unimplemented
}
void View3D::OnActivate
(
Event *ev
)
{
UIWidget* wid;
UList<UIWidget*> widgets;
UIWidget *wid;
UList<UIWidget *> widgets;
UI_CloseInventory();
cls.keyCatchers &= ~KEYCATCH_UI;
for (wid = getParent()->getFirstChild(); wid; wid = getParent()->getNextChild(wid))
{
if (wid->getAlwaysOnBottom() && wid != this) {
widgets.AddTail(wid);
}
}
for (wid = getParent()->getFirstChild(); wid; wid = getParent()->getNextChild(wid)) {
if (wid->getAlwaysOnBottom() && wid != this) {
widgets.AddTail(wid);
}
}
widgets.IterateFromHead();
while (widgets.IsCurrentValid())
{
widgets.getCurrent()->BringToFrontPropogated();
widgets.IterateNext();
}
widgets.IterateFromHead();
while (widgets.IsCurrentValid()) {
widgets.getCurrent()->BringToFrontPropogated();
widgets.IterateNext();
}
}
void View3D::OnDeactivate
(
Event *ev
)
void View3D::LocationPrint(void)
{
cls.keyCatchers |= KEYCATCH_UI;
fonthorzjustify_t horiz;
fontvertjustify_t vert;
int x, y;
const char *p;
float alpha;
UIRect2D frame;
if (!m_printfadetime) {
m_locationprint = false;
return;
}
horiz = FONT_JUSTHORZ_LEFT;
vert = FONT_JUSTVERT_TOP;
p = Sys_LV_CL_ConvertString(m_printstring);
if (m_printfadetime > 3250) {
alpha = 1.f - (m_printfadetime - 3250.f) / 750.f * m_printalpha;
} else if (m_printfadetime >= 750) {
alpha = 1.f;
} else {
alpha = m_printfadetime / 750.f * m_printalpha;
}
alpha = Q_clamp_float(alpha, 0, 1);
x = m_x_coord / 640.f * m_screenframe.size.width;
y = (480 - m_font->getHeight(false) - m_y_coord) / 480.f * m_screenframe.size.height;
if (m_x_coord == -1) {
horiz = FONT_JUSTHORZ_CENTER;
x = 0;
}
if (m_y_coord == -1) {
vert = FONT_JUSTVERT_CENTER;
y = 0;
}
m_font->setColor(UColor(0, 0, 0, alpha));
frame = getClientFrame();
m_font->PrintJustified(
UIRect2D(frame.pos.x + x + 1, frame.pos.y + y + 1, frame.size.width, frame.size.height),
horiz,
vert,
p,
m_bVirtual ? m_vVirtualScale : NULL
);
m_font->setColor(UColor(1, 1, 1, alpha));
frame = getClientFrame();
m_font->PrintJustified(
UIRect2D(frame.pos.x + x, frame.pos.y + y, frame.size.width, frame.size.height),
horiz,
vert,
p,
m_bVirtual ? m_vVirtualScale : NULL
);
m_font->setColor(UBlack);
m_printfadetime -= cls.frametime;
if (m_printfadetime < 0) {
m_printfadetime = 0;
}
}
void View3D::DrawSubtitleOverlay
(
void
)
qboolean View3D::LetterboxActive(void)
{
// FIXME: unimplemented
}
void View3D::ClearCenterPrint
(
void
)
{
m_printfadetime = 0.0;
}
void View3D::UpdateCenterPrint
(
const char *s,
float alpha
)
{
m_printstring = s;
if (s[0] == '@') {
m_print_mat = uWinMan.RegisterShader(s + 1);
} else {
m_print_mat = NULL;
}
m_printalpha = alpha;
m_printfadetime = 4000.0;
m_locationprint = qfalse;
}
void View3D::UpdateLocationPrint
(
int x,
int y,
const char *s,
float alpha
)
{
m_printstring = s;
m_printalpha = alpha;
m_printfadetime = 4000.0;
m_x_coord = x;
m_y_coord = y;
m_locationprint = qtrue;
}
qboolean View3D::LetterboxActive
(
void
)
{
return m_letterbox_active;
return m_letterbox_active;
}
float avWidth = 0.0;
void View3D::InitSubtitle
(
void
)
void View3D::InitSubtitle(void)
{
float totalWidth;
float totalWidth;
for (int i = 0; i < 4; i++) {
subs[i] = Cvar_Get(va("subtitle%d", i), "", 0);
teams[i] = Cvar_Get(va("subteam%d", i), "0", 0);
strcpy(oldStrings[i], subs[i]->string);
fadeTime[i] = 4000.0;
subLife[i] = 4000.0;
}
for (int i = 0; i < 4; i++) {
subs[i] = Cvar_Get(va("subtitle%d", i), "", 0);
teams[i] = Cvar_Get(va("subteam%d", i), "0", 0);
strcpy(oldStrings[i], subs[i]->string);
fadeTime[i] = 4000.0;
subLife[i] = 4000.0;
}
totalWidth = 0.0;
for (char j = 'A'; j <= 'Z'; j++) {
totalWidth += m_font->getCharWidth(j);
}
totalWidth = 0.0;
for (char j = 'A'; j <= 'Z'; j++) {
totalWidth += m_font->getCharWidth(j);
}
avWidth = totalWidth / 26.0;
avWidth = totalWidth / 26.0;
}
void View3D::FrameInitialized
(
void
)
void View3D::FrameInitialized(void)
{
Connect(this, W_Activated, W_Activated);
Connect(this, W_Deactivated, W_Deactivated);
Connect(this, W_Activated, W_Activated);
Connect(this, W_Deactivated, W_Deactivated);
}
void View3D::Pressed
(
Event *ev
)
void View3D::DrawSubtitleOverlay(void)
{
IN_MouseOff();
OnActivate(ev);
cvar_t *subAlpha;
int i;
float minX, maxY;
int line;
subAlpha = Cvar_Get("subAlpha", "0.5", 0);
setFont("facfont-20");
m_font->setColor(URed);
for (i = 0; i < MAX_SUBTITLES; i++) {
if (strcmp(oldStrings[i], subs[i]->string)) {
fadeTime[i] = 2500 * ((strlen(subs[i]->string) / 68) + 1.f) + 1500;
subLife[i] = fadeTime[i];
Q_strncpyz(oldStrings[i], subs[i]->string, sizeof(oldStrings[i]));
}
if (fadeTime[i] > subLife[i] - 750.f) {
alpha[i] = 1.f - (fadeTime[i] - (subLife[i] - 750.f)) / 750.f;
} else if (fadeTime[i] < 750) {
alpha[i] = fadeTime[i] / 750.f;
} else {
alpha[i] = 1.f;
}
fadeTime[i] -= cls.frametime;
if (fadeTime[i] < 0) {
// Clear the subtitle
fadeTime[i] = 0;
oldStrings[i][0] = 0;
Cvar_Set(va("subtitle%d", i), "");
}
}
minX = m_screenframe.size.height - m_font->getHeight(false) * 10;
maxY = (m_frame.pos.x + m_frame.size.width) - (m_frame.pos.x + m_frame.size.width) * 0.2f;
line = 0;
for (i = 0; i < MAX_SUBTITLES; i++) {
if (m_font->getWidth(subs[i]->string, sizeof(oldStrings[i])) > maxY) {
char buf[2048];
char *c;
char *end;
char *start;
float total;
int blockcount;
c = buf;
strcpy(buf, subs[i]->string);
total = 0;
end = NULL;
start = buf;
while (*c) {
blockcount = m_font->DBCSGetWordBlockCount(c, -1);
if (!blockcount) {
break;
}
total += m_font->getWidth(c, blockcount);
c += blockcount;
if (total > maxY) {
total = 0;
if (end < start) {
Com_Printf("ERROR - word longer than possible line\n");
break;
}
m_font->setColor(UColor(0, 0, 0, alpha[i] * subAlpha->value));
m_font->Print(18, m_font->getHeight(false) * line + minX + 1.f, start, -1, false);
m_font->setColor(UColor(1, 1, 1, alpha[i] * subAlpha->value));
m_font->Print(20, m_font->getHeight(false) * line + minX, start, -1, false);
start = end + 1;
c = end + 1;
line++;
}
}
m_font->setColor(UColor(0, 0, 0, alpha[i] * subAlpha->value));
m_font->Print(18, m_font->getHeight(false) * line + minX + 1.f, start, -1, qfalse);
m_font->setColor(UColor(1, 1, 1, alpha[i] * subAlpha->value));
m_font->Print(20, m_font->getHeight(false) * line + minX, start, -1, qfalse);
line++;
} else {
m_font->setColor(UColor(0, 0, 0, alpha[i] * subAlpha->value));
m_font->Print(18, m_font->getHeight(false) * line + minX + 1.f, subs[i]->string, -1, qfalse);
m_font->setColor(UColor(1, 1, 1, alpha[i] * subAlpha->value));
m_font->Print(20, m_font->getHeight(false) * line + minX, subs[i]->string, -1, qfalse);
line++;
}
}
}
CLASS_DECLARATION( UIWidget, ConsoleView, NULL )
void View3D::DrawSoundOverlay(void)
{
{ NULL, NULL }
setFont("verdana-14");
m_font->setColor(UWhite);
// FIXME: TODO
if (sound_overlay->integer) {
Com_Printf("sound_overlay isn't supported with OpenAL/SDL right now.\n");
Cvar_Set("sound_overlay", "0");
}
}
void View3D::DrawProf(void)
{
// Normal empty function
}
void View3D::DrawLetterbox(void)
{
float frac;
vec4_t col;
col[0] = col[1] = col[2] = 0;
col[3] = 1;
frac = cl.snap.ps.stats[STAT_LETTERBOX] / 32767.0;
if (frac > 0.0) {
m_letterbox_active = true;
re.SetColor(col);
re.DrawBox(0.0, 0.0, m_screenframe.size.width, m_screenframe.size.height);
re.DrawBox(
0.0,
m_screenframe.size.height - m_screenframe.size.height * frac,
m_screenframe.size.width,
m_screenframe.size.height
);
} else {
m_letterbox_active = false;
}
}
void View3D::DrawFades(void)
{
if (cl.snap.ps.blend[3] > 0) {
re.SetColor(cl.snap.ps.blend);
if (cl.snap.ps.stats[STAT_ADDFADE]) {
re.AddBox(0.0, 0.0, m_screenframe.size.width, m_screenframe.size.height);
} else {
re.DrawBox(0.0, 0.0, m_screenframe.size.width, m_screenframe.size.height);
}
}
}
void View3D::DrawFPS(void)
{
char string[128];
setFont("verdana-14");
if (fps->integer == 2) {
re.SetColor(UBlack);
re.DrawBox(
0.0,
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 4.0,
m_frame.pos.x + m_frame.size.width,
m_font->getHeight(qfalse) * 4.0
);
}
sprintf(string, "FPS %4.1f", currentfps);
if (currentfps > 23.94) {
if (cl_greenfps->integer) {
m_font->setColor(UGreen);
} else {
m_font->setColor(UWhite);
}
} else if (currentfps > 18.0) {
m_font->setColor(UYellow);
} else {
// low fps
m_font->setColor(URed);
}
m_font->Print(
m_font->getHeight(qfalse) * 10.0,
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 3.0,
string,
-1,
qfalse
);
// Draw elements count
if (cl_greenfps->integer) {
m_font->setColor(UGreen);
} else {
m_font->setColor(UWhite);
}
sprintf(string, "wt%5d wv%5d cl%d", cls.world_tris, cls.world_verts, cls.character_lights);
m_font->Print(
m_font->getHeight(qfalse) * 10.0,
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse) * 2.0,
string,
-1,
qfalse
);
sprintf(string, "t%5d v%5d Mtex%5.2f", cls.total_tris, cls.total_verts, (float)cls.total_texels * 0.00000095367432);
m_font->Print(
m_font->getHeight(qfalse) * 10.0,
m_frame.pos.y + m_frame.size.height - m_font->getHeight(qfalse),
string,
-1,
qfalse
);
m_font->setColor(UBlack);
}
void View3D::Draw2D(void)
{
if (!cls.no_menus) {
DrawFades();
}
DrawLetterbox();
if ((cl_debuggraph->integer || cl_timegraph->integer) && !cls.no_menus) {
SCR_DrawDebugGraph();
} else if (!cls.no_menus) {
if (cge) {
cge->CG_Draw2D();
}
if (m_locationprint) {
LocationPrint();
} else {
CenterPrint();
}
if (!cls.no_menus) {
DrawSoundOverlay();
DrawSubtitleOverlay();
}
}
if (fps->integer && !cls.no_menus) {
DrawFPS();
DrawProf();
}
}
void View3D::Draw(void)
{
if (clc.state != CA_DISCONNECTED) {
SCR_DrawScreenField();
}
set2D();
re.SavePerformanceCounters();
Draw2D();
}
void View3D::ClearCenterPrint(void)
{
m_printfadetime = 0.0;
}
void View3D::CenterPrint(void)
{
float alpha;
const char *p;
qhandle_t mat;
float x, y;
float w, h;
if (!m_printfadetime) {
return;
}
p = Sys_LV_CL_ConvertString(m_printstring);
if (m_printfadetime > 3250) {
alpha = 1.f - (m_printfadetime - 3250.f) / 750.f * m_printalpha;
} else if (m_printfadetime >= 750) {
alpha = 1.f;
} else {
alpha = m_printfadetime / 750.f * m_printalpha;
}
alpha = Q_clamp_float(alpha, 0, 1);
if (!m_print_mat) {
UIRect2D frame;
m_font->setColor(UColor(0, 0, 0, alpha));
frame = getClientFrame();
m_font->PrintJustified(
UIRect2D(frame.pos.x + 1, frame.pos.y + 1, frame.size.width, frame.size.height),
m_iFontAlignmentHorizontal,
m_iFontAlignmentVertical,
p,
m_bVirtual ? m_vVirtualScale : NULL
);
m_font->setColor(UColor(1, 1, 1, alpha));
frame = getClientFrame();
m_font->PrintJustified(
frame, m_iFontAlignmentHorizontal, m_iFontAlignmentVertical, p, m_bVirtual ? m_vVirtualScale : NULL
);
m_font->setColor(UBlack);
} else if ((mat = m_print_mat->GetMaterial())) {
vec4_t col {alpha, alpha, alpha, alpha};
re.SetColor(col);
w = re.GetShaderWidth(mat);
h = re.GetShaderHeight(mat);
x = (m_frame.pos.x + m_frame.size.width - w) * 0.5f;
y = (m_frame.pos.y + m_frame.size.height - h) * 0.5f;
re.DrawStretchPic(x, y, w, h, 0, 0, 1, 1, mat);
}
m_printfadetime -= cls.frametime;
if (m_printfadetime < 0) {
m_printfadetime = 0;
}
}
CLASS_DECLARATION(UIWidget, ConsoleView, NULL) {
{NULL, NULL}
};
void ConsoleView::Draw
(
void
)
{
// FIXME: unimplemented
}
void ConsoleView::Draw(void) {}
+37 -38
View File
@@ -20,55 +20,54 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __CL_UIVIEW3D__
#define __CL_UIVIEW3D__
#pragma once
class View3D : public UIWidget {
float m_printfadetime;
float m_printalpha;
str m_printstring;
UIReggedMaterial *m_print_mat;
qboolean m_locationprint;
int m_x_coord;
int m_y_coord;
qboolean m_letterbox_active;
class View3D : public UIWidget
{
float m_printfadetime;
float m_printalpha;
str m_printstring;
UIReggedMaterial *m_print_mat;
qboolean m_locationprint;
int m_x_coord;
int m_y_coord;
qboolean m_letterbox_active;
public:
CLASS_PROTOTYPE( View3D );
CLASS_PROTOTYPE(View3D);
protected:
void Draw( void ) override;
void DrawLetterbox( void );
void DrawFades( void );
void Draw2D( void );
void DrawFPS( void );
void DrawProf( void );
void PrintSound( int channel, const char *name, float vol, int rvol, float pitch, float base, int& line );
void DrawSoundOverlay( void );
void CenterPrint( void );
void LocationPrint( void );
void OnActivate( Event *ev );
void OnDeactivate( Event *ev );
void DrawSubtitleOverlay( void );
void Draw(void) override;
void DrawLetterbox(void);
void DrawFades(void);
void Draw2D(void);
void DrawFPS(void);
void DrawProf(void);
void PrintSound(int channel, const char *name, float vol, int rvol, float pitch, float base, int& line);
void DrawSoundOverlay(void);
void CenterPrint(void);
void LocationPrint(void);
void OnActivate(Event *ev);
void OnDeactivate(Event *ev);
void DrawSubtitleOverlay(void);
public:
View3D();
View3D();
void ClearCenterPrint( void );
void UpdateCenterPrint( const char *s, float alpha );
void UpdateLocationPrint( int x, int y, const char *s, float alpha );
qboolean LetterboxActive( void );
void InitSubtitle( void );
void FrameInitialized( void ) override;
virtual void Pressed( Event *ev );
void ClearCenterPrint(void);
void UpdateCenterPrint(const char *s, float alpha);
void UpdateLocationPrint(int x, int y, const char *s, float alpha);
qboolean LetterboxActive(void);
void InitSubtitle(void);
void FrameInitialized(void) override;
virtual void Pressed(Event *ev);
};
class ConsoleView : public UIWidget {
class ConsoleView : public UIWidget
{
public:
CLASS_PROTOTYPE( ConsoleView );
CLASS_PROTOTYPE(ConsoleView);
protected:
void Draw( void ) override;
void Draw(void) override;
};
#endif /* __CL_UIVIEW3D__ */
+4 -7
View File
@@ -21,8 +21,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// client.h -- primary header for client
#ifndef __CLIENT_H__
#define __CLIENT_H__
#pragma once
#include "../qcommon/q_shared.h"
#include "../qcommon/qcommon.h"
@@ -321,7 +320,7 @@ typedef struct {
serverInfo_t globalServers[MAX_GLOBAL_SERVERS];
// additional global servers
int numGlobalServerAddresses;
serverAddress_t globalServerAddresses[MAX_GLOBAL_SERVERS];
netadr_t globalServerAddresses[MAX_GLOBAL_SERVERS];
int numfavoriteservers;
serverInfo_t favoriteServers[MAX_OTHER_SERVERS];
@@ -352,7 +351,7 @@ typedef struct {
clientAnim_t anim;
stopWatch_t stopwatch;
void* savedCgameState;
int savedCgameStateSize;
size_t savedCgameStateSize;
char gcdResponse[73];
int unknown3_0;
int currentRate;
@@ -471,7 +470,7 @@ void CL_AddReliableCommand(const char *cmd, qboolean isDisconnectCmd);
void CL_StartHunkUsers( qboolean rendererOnly );
void CL_Connect( const char *server );
void CL_Connect( const char *server, netadrtype_t family );
void CL_Disconnect_f (void);
void CL_GetChallengePacket (void);
@@ -690,5 +689,3 @@ void CL_InitConsoleCommands( void );
#ifdef __cplusplus
}
#endif
#endif // __CLIENT_H__
+1
View File
@@ -58,6 +58,7 @@ typedef struct {
void S_ChannelFree_Callback(channel_t* v);
void S_LoadData(soundsystemsavegame_t* pSave);
void S_SaveData(soundsystemsavegame_t* pSave);
#ifdef __cplusplus
}
+31 -2
View File
@@ -22,10 +22,16 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "../snd_local.h"
#if !defined(USE_SOUND_NEW) || !USE_SOUND_NEW
void S_Init2()
{
S_Init();
SND_setup();
// HACK: S_RegisterSound returns 0 when unsuccessful, or it returns the the sfx handle
// But the first sfx handle is also 0...
S_RegisterSound("sound/null.wav", qfalse);
}
/*
@@ -55,7 +61,7 @@ void S_AddLoopingSound(const vec3_t origin, const vec3_t velocity, sfxHandle_t s
S_StopAllSounds
=================
*/
void S_StopAllSounds(qboolean stop_music)
void S_StopAllSounds2(qboolean stop_music)
{
// Call the original function
S_StopAllSounds();
@@ -83,12 +89,29 @@ void S_Respatialize(int entityNum, const vec3_t origin,
{
S_Respatialize(entityNum, origin, axis, 0);
}
/*
=================
S_StartLocalSoundChannel
=================
*/
void S_StartLocalSound(const char* sound_name, qboolean force_load)
{
sfxHandle_t h;
h = S_RegisterSound(sound_name, qfalse);
if (h) {
S_StartLocalSound(h, CHAN_LOCAL_SOUND);
}
}
/*
=================
S_StartLocalSound
=================
*/
void S_StartLocalSound(const char* sound_name, qboolean force_load)
void S_StartLocalSoundChannel(const char* sound_name, qboolean force_load, int channel)
{
// FIXME: unimplemented
}
@@ -423,3 +446,9 @@ void S_ChannelFree_Callback(channel_t* v) {
void S_LoadData(soundsystemsavegame_t* pSave) {
// FIXME: unimplemented
}
void S_SaveData(soundsystemsavegame_t* pSave) {
// FIXME: unimplemented
}
#endif
+2 -1
View File
@@ -30,8 +30,8 @@ void S_Respatialize(int entityNum, const vec3_t origin, vec3_t axis[3]);
sfxHandle_t S_RegisterSound(const char* sample, qboolean compressed, qboolean streamed);
void S_AddLoopingSound(const vec3_t origin, const vec3_t velocity, sfxHandle_t sfxHandle, float volume, float minDist, float maxDist, float pitch, int flags);
void S_StartLocalSound(const char* name, qboolean force_load);
void S_StartLocalSoundChannel(const char* sound_name, qboolean force_load, int channel);
void S_StartSound(const vec3_t origin, int entNum, int entChannel, sfxHandle_t sfxHandle, float volume, float minDist, float pitch, float maxDist, qboolean streamed);
void S_StopAllSounds(qboolean stop_music);
void S_ClearLoopingSounds(void);
qboolean S_IsSoundRegistered(const char* name);
void S_Init2();
@@ -65,6 +65,7 @@ void MUSIC_UpdateMusicVolumes(void);
void MUSIC_CheckForStoppedSongs(void);
void S_StopSound(int entnum, int channel);
void S_StopAllSounds2(qboolean stop_music);
float S_GetSoundTime(sfxHandle_t handle);
void S_SetGlobalAmbientVolumeLevel(float volume);
void S_SetReverb(int reverb_type, float reverb_level);
+3 -1
View File
@@ -1581,7 +1581,9 @@ qboolean S_Base_Init( soundInterface_t *si ) {
if ( r ) {
s_soundStarted = 1;
s_soundMuted = 1;
// Fixed in OPM
// The UI must be able to play sounds
// s_soundMuted = 1;
// s_numSfx = 0;
Com_Memset(sfxHash, 0, sizeof(sfx_t *)*LOOP_HASH);
+232
View File
@@ -0,0 +1,232 @@
/*
===========================================================================
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
===========================================================================
*/
#if USE_SOUND_NEW
#include "snd_local.h"
#include "snd_openal_new.h"
typedef struct {
vec3_t origin;
vec3_t velocity;
sfx_t *sfx;
int mergeFrame;
} loopSound_t;
# define MAX_SFX 1400
# define MAX_SFX_INFOS 1000
# define MAX_LOOP_SOUNDS 64
qboolean s_bLastInitSound = qfalse;
qboolean s_bSoundStarted = qfalse;
qboolean s_bSoundPaused = qfalse;
qboolean s_bTryUnpause = qfalse;
int s_iListenerNumber = 0;
float s_fAmbientVolume = 1.f;
int number_of_sfx_infos = 0;
cvar_t *s_volume;
cvar_t *s_loadas8bit;
cvar_t *s_khz;
cvar_t *s_show;
cvar_t *s_testsound;
cvar_t *s_separation;
cvar_t *s_musicVolume;
cvar_t *s_ambientVolume;
sfx_info_t sfx_infos[MAX_SFX_INFOS];
sfx_t s_knownSfx[MAX_SFX];
int s_numSfx;
s_entity_t s_entity[MAX_GENTITIES];
static int s_registrationSequence;
static qboolean s_inRegistration;
cvar_t *s_mixPreStep;
cvar_t *s_dialogscale;
int numLoopSounds;
loopSound_t loopSounds[MAX_LOOP_SOUNDS];
void S_SoundInfo_f()
{
// FIXME: unimplemented
}
void S_SoundDump_f()
{
// FIXME: unimplemented
}
void S_Init(qboolean full_startup)
{
// FIXME: unimplemented
}
void S_Shutdown(qboolean full_shutdown)
{
// FIXME: unimplemented
}
qboolean S_NameExists(const char *name)
{
// FIXME: unimplemented
return qfalse;
}
sfx_t *S_FindName(const char *name, int sequenceNumber)
{
// FIXME: unimplemented
return NULL;
}
void S_BeginRegistration()
{
// FIXME: unimplemented
}
void S_DefaultSound(sfx_t *sfx)
{
// FIXME: unimplemented
}
qboolean S_IsSoundRegistered(const char *name)
{
// FIXME: unimplemented
return qfalse;
}
sfxHandle_t S_RegisterSound(const char *name, int streamed, qboolean force_load)
{
// FIXME: unimplemented
return 0;
}
float S_GetSoundTime(sfxHandle_t handle)
{
// FIXME: unimplemented
return 0;
}
void S_EndRegistration()
{
// FIXME: unimplemented
}
void S_UpdateEntity(int entityNum, const vec3_t origin, const vec3_t vel, qboolean use_listener)
{
// FIXME: unimplemented
}
void S_SetGlobalAmbientVolumeLevel(float volume)
{
// FIXME: unimplemented
}
void S_StartSound(
const vec3_t origin,
int entnum,
int entchannel,
sfxHandle_t sfxHandle,
float volume,
float min_dist,
float pitch,
float maxDist,
int streamed
)
{
// FIXME: unimplemented
}
void S_StartLocalSound(const char *sound_name, qboolean force_load)
{
// FIXME: unimplemented
}
void S_StartLocalSoundChannel(const char *sound_name, qboolean force_load, soundChannel_t channel)
{
// FIXME: unimplemented
}
void S_StopAllSounds(qboolean stop_music)
{
// FIXME: unimplemented
}
void S_ClearLoopingSounds()
{
// FIXME: unimplemented
}
void S_AddLoopingSound(
const vec3_t origin,
const vec3_t velocity,
sfxHandle_t sfxHandle,
float volume,
float min_dist,
float max_dist,
float pitch,
int flags
)
{
// FIXME: unimplemented
}
void S_Respatialize(int entityNum, const vec3_t head, vec3_t axis[3])
{
// FIXME: unimplemented
}
void S_Update()
{
// FIXME: unimplemented
}
void S_StopSound(int entnum, int channel)
{
// FIXME: unimplemented
}
void S_SetReverb(int reverb_type, float reverb_level)
{
// FIXME: unimplemented
}
void S_Play()
{
// FIXME: unimplemented
}
void S_SoundList()
{
// FIXME: unimplemented
}
void S_ClearSoundBuffer()
{
// TODO: Remove once AL is fully implemented
}
#endif
+6
View File
@@ -27,6 +27,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "../qcommon/qcommon.h"
#include "snd_public.h"
#if !defined(USE_SOUND_NEW) || !USE_SOUND_NEW
#define PAINTBUFFER_SIZE 4096 // this is in samples
#define SND_CHUNK_SIZE 1024 // samples
@@ -281,3 +283,7 @@ void S_PaintChannelFrom16_altivec( portable_samplepair_t paintbuffer[PAINTBUFFER
#ifdef __cplusplus
}
#endif
#else
# include "snd_local_new.h"
#endif
+164
View File
@@ -0,0 +1,164 @@
/*
===========================================================================
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
===========================================================================
*/
#pragma once
#include "../qcommon/q_shared.h"
#include "../qcommon/qcommon.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
int format;
float rate;
float width;
int channels;
int samples;
int dataofs;
int datasize;
} wavinfo_t;
typedef struct sfx_s {
int iFlags;
int length;
int width;
byte *data;
char name[64];
int registration_sequence;
int sfx_info_index;
float time_length;
wavinfo_t info;
unsigned int buffer;
} sfx_t;
typedef struct {
unsigned short wFormatTag;
unsigned short nChannels;
unsigned int nSamplesPerSec;
unsigned int nAvgBytesPerSec;
unsigned short nBlockAlign;
unsigned short wBitsPerSample;
unsigned short cbSize;
} wavinfo_x_t;
typedef struct {
char name[64];
int loop_start;
int loop_end;
int max_number_playing;
float max_factor;
} sfx_info_t;
typedef struct {
vec3_t position;
vec3_t velocity;
int time;
qboolean use_listener;
} s_entity_t;
typedef struct {
char alias[32];
char path[64];
int mood_num;
int flags;
float volume;
float fadetime;
int current_pos;
int current_state;
} song_t;
typedef struct {
int iFlags;
char szName[64];
} sfxsavegame_t;
typedef struct {
qboolean bPlaying;
int iStatus;
sfxsavegame_t sfx;
int iEntNum;
int iEntChannel;
vec3_t vOrigin;
float fVolume;
int iBaseRate;
float fNewPitchMult;
float fMinDist;
float fMaxDist;
int iStartTime;
int iTime;
int iNextCheckObstructionTime;
int iEndTime;
int iFlags;
int iOffset;
int iLoopCount;
} channelbasesavegame_t;
typedef struct {
channelbasesavegame_t Channels[96];
} soundsystemsavegame_t;
// The current sound driver.
// Currently OPENAL
#define SOUND_DRIVER OPENAL
sfx_t *S_FindName(const char *name, int sequenceNumber);
void S_DefaultSound(sfx_t *sfx);
void S_LoadData(soundsystemsavegame_t *pSave);
void S_SaveData(soundsystemsavegame_t *pSave);
void S_ClearSoundBuffer();
#define S_StopAllSounds2 S_StopAllSounds
//
// Driver-specific functions
//
#define S_Call_SndDriver(driver, func) S_##driver##_##func
#define S_Call_SndDriverX(driver, func) S_Call_SndDriver(driver, func)
#define S_Driver_Init S_Call_SndDriverX(SOUND_DRIVER, Init)
#define S_Driver_StartSound S_Call_SndDriverX(SOUND_DRIVER, StartSound)
#define S_Driver_AddLoopingSound S_Call_SndDriverX(SOUND_DRIVER, AddLoopingSound)
#define S_Driver_ClearLoopingSounds S_Call_SndDriverX(SOUND_DRIVER, ClearLoopingSounds)
#define S_Driver_StopSound S_Call_SndDriverX(SOUND_DRIVER, StopSound)
#define S_Driver_StopAllSounds S_Call_SndDriverX(SOUND_DRIVER, StopAllSounds)
#define S_Driver_Respatialize S_Call_SndDriverX(SOUND_DRIVER, Respatialize)
#define S_Driver_SetReverb S_Call_SndDriverX(SOUND_DRIVER, SetReverb)
#define S_Driver_Update S_Call_SndDriverX(SOUND_DRIVER, Update)
#ifdef __cplusplus
}
#endif
@@ -1,29 +1,25 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2024 the OpenMoHAA team
This file is part of Quake III Arena source code.
This file is part of OpenMoHAA source code.
Quake III Arena source code is free software; you can redistribute it
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.
Quake III Arena source code is distributed in the hope that it will be
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 Foobar; if not, write to the Free Software
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "../qcommon/vm_local.h"
void VM_Compile( vm_t *vm, vmHeader_t *header ) {}
int VM_CallCompiled( vm_t *vm, int *args ) {}
// See the header file for information
#include "snd_miles_new.h"
@@ -1,38 +1,28 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2024 the OpenMoHAA team
This file is part of Quake III Arena source code.
This file is part of OpenMoHAA source code.
Quake III Arena source code is free software; you can redistribute it
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.
Quake III Arena source code is distributed in the hope that it will be
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 Foobar; if not, write to the Free Software
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#if !( defined __linux__ || defined __FreeBSD__ )
#error You should include this file only on Linux/FreeBSD platforms
#endif
#ifndef __GLW_LINUX_H__
#define __GLW_LINUX_H__
//
// This file exists in the original source code.
// But this driver won't be implemented, as OpenAL is a better sound system!
//
typedef struct
{
void *OpenGLLib; // instance of OpenGL library
FILE *log_fp;
} glwstate_t;
extern glwstate_t glw_state;
#endif
#pragma once
+757
View File
@@ -0,0 +1,757 @@
/*
===========================================================================
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
===========================================================================
*/
#if USE_SOUND_NEW
# include "snd_local.h"
# include "snd_openal_new.h"
typedef struct {
char *funcname;
void **funcptr;
bool required;
} extensions_table_t;
# define MAX_MUSIC_SONGS 16
static int s_iNextLoopingWarning = 0;
static int s_iReverbType = 0;
static float s_fReverbLevel = 0;
static bool s_bReverbChanged = false;
static bool s_bFading = false;
static float s_fFadeVolume = 1.f;
cvar_t *s_milesdriver;
cvar_t *s_openaldevice;
cvar_t *s_reverb;
cvar_t *s_show_cpu;
cvar_t *s_show_num_active_sounds;
cvar_t *s_show_sounds;
cvar_t *s_speaker_type;
cvar_t *s_obstruction_cal_time;
cvar_t *s_lastSoundTime;
static float reverb_table[] = {
0.5f, 0.25f, 0.417f, 0.653f, 0.208f, 0.5f, 0.403f, 0.5f, 0.5f,
0.361f, 0.5f, 0.153f, 0.361f, 0.44400001f, 0.25f, 0.111f, 0.111f, 0.19400001f,
1.0f, 0.097000003f, 0.208f, 0.65200001f, 1.0f, 0.875f, 0.139f, 0.486f,
};
static vec3_t vec_zero = {0, 0, 0};
int s_iNumMilesAudioProviders = 0;
bool s_bProvidersEmunerated = false;
static bool al_initialized = false;
static bool al_use_reverb = false;
static float al_current_volume = 0;
static unsigned int al_frequency = 22050;
static void *al_context_id = NULL;
static ALCdevice *al_device = NULL;
static ALboolean (*_alutLoadMP3_LOKI)(unsigned int buffer, const byte *data, int length);
static void (*_alReverbScale_LOKI)();
static void (*_alReverbDelay_LOKI)();
static qboolean music_active = qfalse;
int music_current_mood = 0;
int music_fallback_mood = 0;
float old_music_volume = 1.f;
float music_volume = 1.f;
float new_music_volume = 1.f;
float music_volume_fade_time = 0;
long int music_volume_start_time = 0;
int music_volume_direction = 0;
int music_volume_changed = 0;
int music_loaded = 0;
int music_numsongs = 0;
int music_currentsong = 0;
song_t music_songs[MAX_MUSIC_SONGS];
openal_internal_t openal;
static float s_fFadeStartTime;
static float s_fFadeStopTime;
static char current_soundtrack[128];
static void __alDieIfError(char *file)
{
// FIXME: unimplemented
}
static void S_OPENAL_NukeSource(ALuint *srcptr)
{
// FIXME: unimplemented
}
static void S_OPENAL_NukeBuffer(ALuint *bufptr)
{
// FIXME: unimplemented
}
static void S_OPENAL_NukeChannel(openal_channel *channel)
{
// FIXME: unimplemented
}
static void S_OPENAL_NukeContext()
{
// FIXME: unimplemented
}
static bool S_OPENAL_InitContext()
{
// FIXME: unimplemented
return false;
}
static bool S_OPENAL_InitExtensions()
{
// FIXME: unimplemented
return false;
}
static bool S_OPENAL_InitChannel(int idx, openal_channel *chan)
{
// FIXME: unimplemented
return false;
}
qboolean S_OPENAL_Init()
{
// FIXME: unimplemented
return qfalse;
}
void S_OPENAL_Shutdown()
{
// FIXME: unimplemented
}
void S_FadeSound(float fTime)
{
// FIXME: unimplemented
}
float S_GetBaseVolume()
{
// FIXME: unimplemented
return 0;
}
qboolean S_NeedFullRestart()
{
// FIXME: unimplemented
return qfalse;
}
void S_PrintInfo()
{
// FIXME: unimplemented
}
static void S_DumpStatus(const char *pszChanName, int iChanNum, openal_channel *channel)
{
// FIXME: unimplemented
}
void S_DumpInfo()
{
// FIXME: unimplemented
}
static void S_OPENAL_Pitch()
{
// FIXME: unimplemented
}
static bool S_OPENAL_LoadMP3(const char *_path, openal_channel *chan)
{
// FIXME: unimplemented
return false;
}
static void S_OPENAL_PlayMP3()
{
// FIXME: unimplemented
}
static void S_OPENAL_StopMP3()
{
// FIXME: unimplemented
}
void MUSIC_Pause()
{
// FIXME: unimplemented
}
void MUSIC_Unpause()
{
// FIXME: unimplemented
}
void S_PauseSound()
{
// FIXME: unimplemented
}
void S_UnpauseSound()
{
// FIXME: unimplemented
}
static qboolean S_OPENAL_ShouldPlay(sfx_t *pSfx)
{
// FIXME: unimplemented
return qfalse;
}
static qboolean S_OPENAL_ShouldStart(const vec3_t vOrigin, float fMinDist, float fMaxDist)
{
// FIXME: unimplemented
return qfalse;
}
static int S_OPENAL_PickChannelBase(int iEntNum, int iEntChannel, int iFirstChannel, int iLastChannel)
{
// FIXME: unimplemented
return 0;
}
static int S_OPENAL_PickChannel3D(int iEntNum, int iEntChannel)
{
// FIXME: unimplemented
return 0;
}
static int S_OPENAL_PickChannel2D(int iEntNum, int iEntChannel)
{
// FIXME: unimplemented
return 0;
}
static int S_OPENAL_PickChannel2DStreamed(int iEntNum, int iEntChannel)
{
// FIXME: unimplemented
return 0;
}
void callbackServer(int entnum, int channel_number, const char *name)
{
// FIXME: unimplemented
}
static void S_OPENAL_Start2DSound(
const vec3_t vOrigin,
int iEntNum,
int iEntChannel,
sfx_t *pSfx,
float fVolume,
float fMinDistance,
float fPitch,
float fMaxDistance
)
{
// FIXME: unimplemented
}
void S_OPENAL_StartSound(
const vec3_t vOrigin,
int iEntNum,
int iEntChannel,
sfxHandle_t sfxHandle,
float fVolume,
float fMinDist,
float fPitch,
float fMaxDist,
qboolean bStreamed
)
{
// FIXME: unimplemented
}
void S_OPENAL_AddLoopingSound(
const vec3_t vOrigin,
const vec3_t vVelocity,
sfxHandle_t sfxHandle,
float fVolume,
float fMinDist,
float fMaxDist,
float fPitch,
int iFlags
)
{
// FIXME: unimplemented
}
void S_OPENAL_StopLoopingSound(openal_loop_sound_t *pLoopSound)
{
// FIXME: unimplemented
}
void S_OPENAL_ClearLoopingSounds()
{
// FIXME: unimplemented
}
void S_OPENAL_StopLoopingSounds()
{
// FIXME: unimplemented
}
void S_OPENAL_StopSound(int iEntNum)
{
// FIXME: unimplemented
}
void S_OPENAL_StopAllSounds(qboolean bStopMusic)
{
// FIXME: unimplemented
}
static int S_OPENAL_Start2DLoopSound(
openal_loop_sound_t *pLoopSound, float fVolume, float fVolumeToPlay, float fMinDistance, const vec3_t vLoopOrigin
)
{
// FIXME: unimplemented
return 0;
}
static int S_OPENAL_Start3DLoopSound(
openal_loop_sound_t *pLoopSound,
float fVolumeToPlay,
float fMinDistance,
float fMaxDistance,
const vec3_t vLoopOrigin,
const vec3_t vListenerOrigin
)
{
// FIXME: unimplemented
return 0;
}
static bool S_OPENAL_UpdateLoopSound(
openal_loop_sound_t *pLoopSound,
float fVolumeToPlay,
float fMinDistance,
float fMaxDistance,
const vec3_t vListenerOrigin,
const vec3_t vTempAxis,
const vec3_t vLoopOrigin
)
{
// FIXME: unimplemented
return false;
}
void S_OPENAL_AddLoopSounds(const vec3_t vTempAxis)
{
// FIXME: unimplemented
}
void S_OPENAL_Respatialize(int iEntNum, const vec3_t vHeadPos, const vec3_t vAxis[3])
{
// FIXME: unimplemented
}
static int S_OPENAL_SpatializeStereoSound(const vec3_t listener_origin, const vec3_t listener_left, const vec3_t origin)
{
// FIXME: unimplemented
return 0;
}
static void S_OPENAL_reverb(int iChannel, int iReverbType, float fReverbLevel)
{
// FIXME: unimplemented
}
void S_OPENAL_SetReverb(int iType, float fLevel)
{
// FIXME: unimplemented
}
void S_OPENAL_Update()
{
// FIXME: unimplemented
}
qboolean S_IsSoundPlaying(int channel_number, const char *sfxName)
{
// FIXME: unimplemented
return qfalse;
}
static void S_StoreBase(channelbasesavegame_t *pBase, openal_channel *pChannel)
{
// FIXME: unimplemented
}
static void
S_StartSoundFromBase(channelbasesavegame_t *pBase, openal_channel *pChannel, sfx_t *pSfx, bool bStartUnpaused)
{
// FIXME: unimplemented
}
static void S_LoadBase(channelbasesavegame_t *pBase, openal_channel *pChannel, bool bStartUnpaused)
{
// FIXME: unimplemented
}
void S_SaveData(soundsystemsavegame_t *pSave)
{
// FIXME: unimplemented
}
void S_ReLoad(soundsystemsavegame_t *pSave)
{
// FIXME: unimplemented
}
static void S_InitBase(channelbasesavegame_t *pBase)
{
// FIXME: unimplemented
}
void S_LoadData(soundsystemsavegame_t *pSave)
{
// FIXME: unimplemented
}
void openal_channel::set_velocity(float v0, float v1, float v2)
{
// FIXME: unimplemented
}
void openal_channel::set_position(float v0, float v1, float v2)
{
// FIXME: unimplemented
}
void openal_channel::set_gain(float gain)
{
// FIXME: unimplemented
}
void openal_channel::set_no_3d()
{
// FIXME: unimplemented
}
void openal_channel::set_3d()
{
// FIXME: unimplemented
}
void openal_channel::play()
{
// FIXME: unimplemented
}
void openal_channel::pause()
{
// FIXME: unimplemented
}
void openal_channel::stop()
{
// FIXME: unimplemented
}
ALint openal_channel::get_state()
{
// FIXME: unimplemented
return 0;
}
bool openal_channel::is_free()
{
// FIXME: unimplemented
return false;
}
bool openal_channel::is_paused()
{
// FIXME: unimplemented
return false;
}
bool openal_channel::is_playing()
{
// FIXME: unimplemented
return false;
}
void openal_channel::force_free()
{
// FIXME: unimplemented
}
bool openal_channel::set_sfx(sfx_t *pSfx)
{
// FIXME: unimplemented
return false;
}
void openal_channel::start_sample()
{
// FIXME: unimplemented
}
void openal_channel::stop_sample()
{
// FIXME: unimplemented
}
void openal_channel::resume_sample()
{
// FIXME: unimplemented
}
void openal_channel::end_sample()
{
// FIXME: unimplemented
}
void openal_channel::set_sample_pan(S32 pan)
{
// FIXME: unimplemented
}
void openal_channel::set_sample_playback_rate(S32 rate)
{
// FIXME: unimplemented
}
S32 openal_channel::sample_playback_rate()
{
// FIXME: unimplemented
return 0;
}
S32 openal_channel::sample_volume()
{
// FIXME: unimplemented
return 0;
}
U32 openal_channel::sample_offset()
{
// FIXME: unimplemented
return 0;
}
U32 openal_channel::sample_ms_offset()
{
// FIXME: unimplemented
return 0;
}
U32 openal_channel::sample_loop_count()
{
// FIXME: unimplemented
return 0;
}
void openal_channel::set_sample_offset(U32 offset)
{
// FIXME: unimplemented
}
void openal_channel::set_sample_ms_offset(U32 offset)
{
// FIXME: unimplemented
}
void openal_channel::set_sample_loop_count(S32 count)
{
// FIXME: unimplemented
}
void openal_channel::set_sample_loop_block(S32 start_offset, S32 end_offset)
{
// FIXME: unimplemented
}
U32 openal_channel::sample_status()
{
// FIXME: unimplemented
return 0;
}
qboolean MUSIC_LoadSoundtrackFile(const char *filename)
{
// FIXME: unimplemented
return qfalse;
}
qboolean MUSIC_SongValid(const char *mood)
{
// FIXME: unimplemented
return qfalse;
}
qboolean MUSIC_Loaded()
{
// FIXME: unimplemented
return qfalse;
}
void Music_Update()
{
// FIXME: unimplemented
}
void MUSIC_SongEnded()
{
// FIXME: unimplemented
}
void MUSIC_NewSoundtrack(const char *name)
{
// FIXME: unimplemented
}
void MUSIC_UpdateMood(int current, int fallback)
{
// FIXME: unimplemented
}
void MUSIC_UpdateVolume(float volume, float fade_time)
{
// FIXME: unimplemented
}
void MUSIC_StopAllSongs()
{
// FIXME: unimplemented
}
void MUSIC_FreeAllSongs()
{
// FIXME: unimplemented
}
qboolean MUSIC_Playing()
{
// FIXME: unimplemented
return qfalse;
}
int MUSIC_FindSong(const char *name)
{
// FIXME: unimplemented
return 0;
}
void S_loadsoundtrack()
{
// FIXME: unimplemented
}
const char *S_CurrentSoundtrack()
{
// FIXME: unimplemented
return NULL;
}
void S_PlaySong()
{
// FIXME: unimplemented
}
int MUSIC_CurrentSongChannel()
{
// FIXME: unimplemented
return 0;
}
void MUSIC_StopChannel(int channel_number)
{
// FIXME: unimplemented
}
qboolean MUSIC_PlaySong(const char *alias)
{
// FIXME: unimplemented
return qfalse;
}
void MUSIC_UpdateMusicVolumes()
{
// FIXME: unimplemented
}
void MUSIC_CheckForStoppedSongs()
{
// FIXME: unimplemented
}
void S_TriggeredMusic_SetupHandle(const char *pszName, int iLoopCount, int iOffset, qboolean autostart)
{
// FIXME: unimplemented
}
void S_TriggeredMusic_Start()
{
// FIXME: unimplemented
}
void S_TriggeredMusic_StartLoop()
{
// FIXME: unimplemented
}
void S_TriggeredMusic_Stop()
{
// FIXME: unimplemented
}
void S_TriggeredMusic_Pause()
{
// FIXME: unimplemented
}
void S_TriggeredMusic_Unpause()
{
// FIXME: unimplemented
}
void S_TriggeredMusic_PlayIntroMusic()
{
// FIXME: unimplemented
}
void S_StopMovieAudio()
{
// FIXME: unimplemented
}
void S_SetupMovieAudio(const char *pszMovieName)
{
// FIXME: unimplemented
}
int S_CurrentMoviePosition()
{
// FIXME: unimplemented
return 0;
}
#endif
+170
View File
@@ -0,0 +1,170 @@
/*
===========================================================================
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
===========================================================================
*/
#pragma once
#include "qal.h"
#undef OPENAL
typedef int S32;
typedef unsigned int U32;
typedef enum {
FADE_NONE,
FADE_IN,
FADE_OUT
} fade_t;
typedef struct {
vec3_t vOrigin;
vec3_t vRelativeOrigin;
vec3_t vVelocity;
sfx_t *pSfx;
qboolean bPlaying;
int iChannel;
float fVolume;
float fPitch;
int iStartTime;
qboolean bInUse;
qboolean bCombine;
float fBaseVolume;
float fMinDist;
float fMaxDist;
int iFlags;
} openal_loop_sound_t;
struct openal_channel {
sfx_t *pSfx;
int iEntNum;
int iEntChannel;
vec3_t vOrigin;
float fVolume;
int iBaseRate;
float fNewPitchMult;
float fMinDist;
float fMaxDist;
int iStartTime;
int iTime;
int iEndTime;
int iFlags;
int iPausedOffset;
int song_number;
fade_t fading;
int fade_time;
int fade_start_time;
ALuint source;
ALuint buffer;
ALubyte *bufferdata;
void play();
void stop();
void pause();
void set_no_3d();
void set_3d();
ALint get_state();
void set_gain(float gain);
void set_velocity(float v0, float v1, float v2);
void set_position(float v0, float v1, float v2);
bool is_free();
bool is_paused();
bool is_playing();
void force_free();
bool set_sfx(sfx_t *pSfx);
void start_sample();
void stop_sample();
void resume_sample();
void end_sample();
void set_sample_pan(S32 pan);
void set_sample_playback_rate(S32 pan);
S32 sample_playback_rate();
S32 sample_volume();
U32 sample_offset();
U32 sample_ms_offset();
U32 sample_loop_count();
void set_sample_offset(U32 offset);
void set_sample_ms_offset(U32 offset);
void set_sample_loop_count(S32 count);
void set_sample_loop_block(S32 start_offset, S32 end_offset);
U32 sample_status();
};
struct openal_internal_t {
openal_channel chan_3D[32];
openal_channel chan_2D[32];
openal_channel chan_2D_stream[32];
openal_channel chan_song[2];
openal_channel chan_mp3;
openal_channel chan_trig_music;
openal_channel chan_movie;
openal_channel *channel[101];
openal_loop_sound_t loop_sounds[64];
openal_channel movieChannel;
sfx_t movieSFX;
char tm_filename[64];
int tm_loopcount;
};
#ifdef __cplusplus
extern "C" {
#endif
qboolean S_OPENAL_Init();
void S_OPENAL_StartSound(
const vec3_t vOrigin,
int iEntNum,
int iEntChannel,
sfxHandle_t sfxHandle,
float fVolume,
float fMinDist,
float fPitch,
float fMaxDist,
qboolean bStreamed
);
void S_OPENAL_AddLoopingSound(
const vec3_t vOrigin,
const vec3_t vVelocity,
sfxHandle_t sfxHandle,
float fVolume,
float fMinDist,
float fMaxDist,
float fPitch,
int iFlags
);
void S_OPENAL_ClearLoopingSounds();
void S_OPENAL_StopSound(int iEntNum);
void S_OPENAL_StopAllSounds(qboolean bStopMusic);
void S_OPENAL_Respatialize(int iEntNum, const vec3_t vHeadPos, const vec3_t vAxis[3]);
void S_OPENAL_SetReverb(int iType, float fLevel);
void S_OPENAL_Update();
#ifdef __cplusplus
}
#endif
+73
View File
@@ -20,6 +20,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#if !defined(USE_SOUND_NEW) || !USE_SOUND_NEW
#ifdef __cplusplus
extern "C" {
#endif
@@ -89,3 +91,74 @@ void S_MasterGain(float gain);
#endif
#include "new/snd_public_new.h"
#else
#ifdef __cplusplus
extern "C" {
#endif
void S_SoundInfo_f();
void S_SoundDump_f();
void S_Init(qboolean full_startup);
void S_Shutdown(qboolean full_shutdown);
qboolean S_NameExists(const char* name);
void S_BeginRegistration();
qboolean S_IsSoundRegistered(const char* name);
sfxHandle_t S_RegisterSound(const char* name, int streamed, qboolean force_load);
float S_GetSoundTime(sfxHandle_t handle);
void S_EndRegistration();
void S_UpdateEntity(int entityNum, const vec3_t origin, const vec3_t vel, qboolean use_listener);
void S_SetGlobalAmbientVolumeLevel(float volume);
void S_StartSound(const vec3_t origin, int entnum, int entchannel, sfxHandle_t sfxHandle, float volume, float min_dist, float pitch, float maxDist, int streamed);
void S_StartLocalSound(const char* sound_name, qboolean force_load);
void S_StartLocalSoundChannel(const char* sound_name, qboolean force_load, soundChannel_t channel);
void S_StopAllSounds(qboolean stop_music);
void S_ClearLoopingSounds();
void S_AddLoopingSound(const vec3_t origin, const vec3_t velocity, sfxHandle_t sfxHandle, float volume, float min_dist, float max_dist, float pitch, int flags);
void S_Respatialize(int entityNum, const vec3_t head, vec3_t axis[3]);
void S_Update();
void S_StopSound(int entnum, int channel);
void S_SetReverb(int reverb_type, float reverb_level);
void S_Play();
void S_SoundList();
qboolean S_IsSoundPlaying(int channel_number, const char* sfxName);
void S_FadeSound(float fTime);
qboolean MUSIC_LoadSoundtrackFile(const char* filename);
qboolean MUSIC_SongValid(const char* mood);
qboolean MUSIC_Loaded();
void Music_Update();
void MUSIC_SongEnded();
void MUSIC_NewSoundtrack(const char* name);
void MUSIC_UpdateMood(int current, int fallback);
void MUSIC_UpdateVolume(float volume, float fade_time);
void MUSIC_StopAllSongs();
void MUSIC_FreeAllSongs();
qboolean MUSIC_Playing();
int MUSIC_FindSong(const char* name);
void S_loadsoundtrack();
const char* S_CurrentSoundtrack();
void S_PlaySong();
int MUSIC_CurrentSongChannel();
void MUSIC_StopChannel(int channel_number);
qboolean MUSIC_PlaySong(const char* alias);
void MUSIC_UpdateMusicVolumes();
void MUSIC_CheckForStoppedSongs();
void S_TriggeredMusic_SetupHandle(const char* pszName, int iLoopCount, int iOffset, qboolean autostart);
void S_TriggeredMusic_Start();
void S_TriggeredMusic_StartLoop();
void S_TriggeredMusic_Stop();
void S_TriggeredMusic_Pause();
void S_TriggeredMusic_Unpause();
void S_TriggeredMusic_PlayIntroMusic();
void S_StopMovieAudio();
void S_SetupMovieAudio(const char* pszMovieName);
int S_CurrentMoviePosition();
#ifdef __cplusplus
}
#endif
#endif
+1 -1
View File
@@ -120,7 +120,7 @@ bool UConnection::SendEvent
ptr = m_listeners.ObjectAt( i );
if( ptr )
{
Event *e = new Event( m_events.ObjectAt( i ) );
Event *e = new Event( *m_events.ObjectAt( i ) );
for( j = 1; j < numargs; j++ )
{
+41 -1
View File
@@ -21,6 +21,46 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "DrivableVehicleTandem.h"
#include "vehicleturret.h"
// FIXME: unimplemented
CLASS_DECLARATION(DrivableVehicle, DrivableVehicleTandem, "DrivableVehicleTandem") {
{NULL, NULL}
};
DrivableVehicleTandem::DrivableVehicleTandem()
{
}
DrivableVehicleTandem::~DrivableVehicleTandem()
{
}
void DrivableVehicleTandem::SpawnTurret(Event* ev)
{
VehicleTurretGunTandem* pTurret = new VehicleTurretGunTandem();
int slot;
pTurret->SetBaseOrientation(orientation, NULL);
pTurret->setModel(ev->GetString(2));
slot = ev->GetInteger(1);
AttachTurretSlot(slot, pTurret, vec_zero, NULL);
pTurret->SetVehicleOwner(this);
pTurret->PostEvent(EV_TakeDamage, EV_POSTSPAWN);
UpdateTurretSlot(slot);
pTurret->ProcessPendingEvents();
}
void DrivableVehicleTandem::UpdateTurretSlot(int iSlot)
{
DrivableVehicle::UpdateTurretSlot(iSlot);
if (Turrets[iSlot].ent && Turrets[iSlot].ent->isSubclassOf(VehicleTurretGunTandem)) {
VehicleTurretGunTandem* pTurret = static_cast<VehicleTurretGunTandem*>(Turrets[iSlot].ent.Pointer());
pTurret->UpdateLinkedTurret();
}
}
+14
View File
@@ -21,3 +21,17 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "vehicle.h"
class DrivableVehicleTandem : public DrivableVehicle {
private:
CLASS_PROTOTYPE(DrivableVehicleTandem);
public:
DrivableVehicleTandem();
~DrivableVehicleTandem();
void SpawnTurret(Event* ev) override;
void UpdateTurretSlot(int iSlot) override;
};
+1449 -414
View File
File diff suppressed because it is too large. Load diff
+17 -4
View File
@@ -32,10 +32,11 @@ typedef enum {
} eController;
#define PT_SPAWNFLAG_PLAY_FIRE_SOUND 1
#define PT_SPAWNFLAG_PLAY_MOTION_SOUND 2
#define PT_SPAWNFLAG_TARGET_RANDOM 4
#define PT_SPAWNFLAG_TURN_ON 8
#define PT_SPAWNFLAG_SET_YAW 16
#define PT_SPAWNFLAG_SET_ROLL 32
#define PT_SPAWNFLAG_ROTATE_YAW 16
#define PT_SPAWNFLAG_ROTATE_ROLL 32
#define PT_SPAWNFLAG_TARGET_PLAYER 64
#define PT_SPAWNFLAG_HIDDEN 128
@@ -101,20 +102,28 @@ public:
bool ShouldStartOn() const;
bool ShouldHideModel() const;
bool ShouldPlayFireSound() const;
bool ShouldPlayMotionSound() const;
bool ShouldRotateYaw() const;
bool ShouldRotateRoll() const;
void EventIsTurnedOn(Event *ev);
void EventGetTargetEntity(Event *ev);
void EventLaunchSound(Event *ev);
void SetTarget(Event *ev);
void SetTarget(Entity* ent);
void OnInitialize(Event *ev);
void TurnOff(Event *ev);
void TurnOn(Event *ev);
bool ShouldTargetRandom() const;
void ChooseTarget();
Entity* ChooseTarget();
void GetLocalTargets();
bool ShouldTargetPlayer() const;
void GetTargetPos(Entity *target);
Vector GetTargetPos(Entity *target);
void GetMuzzlePos(Vector& pos);
void Fire();
void TryLaunchSound();
void SetWeaponAnim(const char* name, Event* ev);
void EventAccuracy(Event *ev);
void EventMaxDelay(Event *ev);
void EventMinDelay(Event *ev);
@@ -154,6 +163,7 @@ public:
void PlayPreImpactSound(Event *ev);
void SetProjectileModel(Event *ev);
float EstimateImpactTime(const Vector& targetOrigin, const Vector& fromOrigin, float speed) const;
bool Attack(int count) override;
void Archive(Archiver& arc) override;
};
@@ -196,6 +206,7 @@ public:
void SetBulletRange(Event *ev);
bool Attack(int count) override;
bool TickWeaponAnim();
void TickCycle(Event *ev) override;
void Archive(Archiver& arc) override;
};
@@ -238,6 +249,8 @@ public:
ThrobbingBox_Explosive();
bool ShouldDoExplosion();
void SetExplosionOffset(Event *ev);
void SetExplosionEffect(Event *ev);
void SetTriggered(Event *ev);
+99 -12
View File
@@ -114,19 +114,105 @@ void TOWObjectiveMan::TakeOverObjective(eController controller, eController cont
}
}
Event EV_SetController("ControlledBy", EV_DEFAULT, "i", "ControlledBy", "Sets the team controlling the objective");
Event EV_TakeOver(
"TakeOver", EV_DEFAULT, "i", "TeamNum", "Sets the team controlling the objective. 0 = Axis, 1 = Allies"
//---------------------------------------------------------------------------------------------
/*QUAKED func_TOWObjective (1.0 0.0 1.0) (-12 -12 -12) (12 12 12) StartOn Respawner
This object is an extension of the standard objective object. It is used for Tug of War
Maps.
object used to simplify placing objectives. You may optionally connect this object to the
target you want to use for the compass position....
Checkboxes:
StartOn - check this if you want this objective to be displayed when the level first loads
Respawner - check this if the objective is the respawn point for a team. If you set this
you must set ControlledBy to a valid team and not Neutral.
Parameters:
ControlledBy 0 = Axis, 1 = Allies, 2 = Neutral
AxisObjNum 1 - 5. Set the objective number for the axis. This will associate the objective with
the check box for the corresponding text in the score screen.
AlliesObjNum 1 - 5. Set the objective number for the allies. This will associate the objective with
the check box for the corresponding text in the score screen.
ObjectiveNbr <nObjNbr=0> Please ignore this for now.
Events:
TurnOn
TurnOff
Complete
Text <sNewText>
SetCurrent
SetController <ControlledBy> - This will set the starting controller default is neutral. See ControlledBy var above.
//---------------------------------------------------------------------------------------------
*/
Event EV_SetController
(
"ControlledBy",
EV_DEFAULT,
"i",
"ControlledBy",
"Sets the team controlling the objective",
EV_NORMAL
);
Event EV_SetAxisObjNum("AxisObjNum", EV_DEFAULT, "i", "AxisObjNum", "Sets the objective number for the axis team");
Event EV_SetAlliesObjNum(
"AlliesObjNum", EV_DEFAULT, "i", "AlliesObjNum", "Sets the objective number for the allies team"
Event EV_TakeOver
(
"TakeOver",
EV_DEFAULT,
"i",
"TeamNum",
"Sets the team controlling the objective. 0 = Axis, 1 = Allies",
EV_NORMAL
);
static Event EV_Initialize("initialize", EV_DEFAULT, 0, 0, "Initialize object");
static Event EV_SetCurrent(
"SetCurrent", EV_DEFAULT, "i", "TeamNum", "Set this objective as the current objective for the specified team."
Event EV_SetAxisObjNum
(
"AxisObjNum",
EV_DEFAULT,
"i",
"AxisObjNum",
"Sets the objective number for the axis team",
EV_NORMAL
);
Event EV_SetAlliesObjNum
(
"AlliesObjNum",
EV_DEFAULT,
"i",
"AlliesObjNum",
"Sets the objective number for the allies team",
EV_NORMAL
);
static Event EV_Initialize
(
"initialize",
EV_DEFAULT,
0,
0,
"Initialize object",
EV_NORMAL
);
static Event EV_SetCurrent
(
"SetCurrent",
EV_DEFAULT,
"i",
"TeamNum",
"Set this objective as the current objective for the specified team.",
EV_NORMAL
);
Event EV_GetController
(
"ControlledBy",
EV_DEFAULT,
0,
0,
"Objective controller",
EV_GETTER
);
Event EV_GetController("ControlledBy", EV_DEFAULT, 0, 0, "Objective controller", EV_GETTER);
CLASS_DECLARATION(Objective, TOWObjective, "func_towobjective") {
{&EV_SetController, &TOWObjective::SetController },
@@ -195,6 +281,7 @@ void TOWObjective::TakeOver(Event *ev)
}
g_TOWObjectiveMan.TakeOverObjective(m_eController, controller);
m_eController = controller;
if (m_bNoRespawnForLeading) {
//
@@ -216,8 +303,8 @@ void TOWObjective::SetAxisObjNum(Event *ev)
void TOWObjective::OnInitialize(Event *ev)
{
m_sAlliesObjName = "tow_allied_obj" + str(m_iAlliesObjNum);
m_sAxisObjName = "tow_allied_obj" + str(m_iAxisObjNum);
m_sAlliesObjName = "tow_allied_obj" + str(m_iAlliesObjNum);
m_sAxisObjName = "tow_axis_obj" + str(m_iAxisObjNum);
switch (m_eController) {
case CONTROLLER_ALLIES:
+4 -7
View File
@@ -45,12 +45,11 @@ VehicleCollisionEntity::VehicleCollisionEntity
m_pOwner = ent;
takedamage = DAMAGE_YES;
edict->s.renderfx &= ~RF_DONTDRAW;
edict->r.svFlags &= ~SVF_NOCLIENT;
showModel();
setMoveType( MOVETYPE_PUSH );
setSolidType(SOLID_NOT);
edict->clipmask |= MASK_CLIP;
edict->clipmask |= MASK_VEHICLE;
edict->s.eFlags |= EF_LINKANGLES;
}
@@ -72,9 +71,7 @@ void VehicleCollisionEntity::EventDamage
Event *ev
)
{
Event *event = new Event( ev );
m_pOwner->ProcessEvent( event );
m_pOwner->ProcessEvent(*ev);
}
void VehicleCollisionEntity::Solid
+124 -96
View File
@@ -28,131 +28,159 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
cVehicleSlot::cVehicleSlot()
{
prev_takedamage = ( damage_t )-1;
prev_solid = ( solid_t )-1;
prev_contents = -1;
prev_takedamage = (damage_t)-1;
prev_solid = (solid_t)-1;
prev_contents = -1;
}
void cVehicleSlot::NotSolid
(
void
)
void cVehicleSlot::NotSolid(void)
{
if( !( flags & FL_SWIM ) )
{
return;
}
int i;
if( !ent )
{
return;
}
if (!(flags & SLOT_BUSY)) {
return;
}
// Save previous values
prev_takedamage = ent->takedamage;
prev_solid = ent->edict->solid;
prev_contents = ent->edict->r.contents;
ent->takedamage = DAMAGE_NO;
ent->setSolidType( SOLID_NOT );
if (!ent) {
return;
}
// Save previous values
prev_takedamage = ent->takedamage;
prev_solid = ent->edict->solid;
prev_contents = ent->edict->r.contents;
ent->takedamage = DAMAGE_NO;
ent->setSolidType(SOLID_NOT);
for (i = 0; i < ent->numchildren; i++) {
Entity *sub = G_GetEntity(ent->children[i]);
if (sub && !sub->IsSubclassOfWeapon()) {
sub->setSolidType(SOLID_NOT);
}
}
if (!ent->IsSubclassOfPlayer()) {
ent->setSolidType(SOLID_NOT);
}
}
void cVehicleSlot::Solid
(
void
)
void cVehicleSlot::Solid(void)
{
if( !( flags & FL_SWIM ) )
{
return;
}
int i;
if( !ent )
{
return;
}
if (!(flags & FL_SWIM)) {
return;
}
// Restore previous values
ent->takedamage = prev_takedamage;
ent->setSolidType( prev_solid );
ent->edict->r.contents = prev_contents;
if (!ent) {
return;
}
// Save previous values
prev_takedamage = ( damage_t )-1;
prev_solid = ( solid_t )-1;
prev_contents = -1;
// Restore previous values
ent->takedamage = prev_takedamage;
ent->setSolidType(prev_solid);
ent->setContents(prev_contents);
// Save previous values
prev_takedamage = (damage_t)-1;
prev_solid = (solid_t)-1;
prev_contents = -1;
for (i = 0; i < ent->numchildren; i++) {
Entity *sub = G_GetEntity(ent->children[i]);
if (sub && !sub->IsSubclassOfWeapon()) {
sub->setSolidType(SOLID_BBOX);
}
}
}
cTurretSlot::cTurretSlot()
{
owner_prev_takedamage = ( damage_t )-1;
owner_prev_solid = ( solid_t )-1;
owner_prev_contents = -1;
owner_prev_takedamage = (damage_t)-1;
owner_prev_solid = (solid_t)-1;
owner_prev_contents = -1;
}
void cTurretSlot::NotSolid
(
void
)
void cTurretSlot::NotSolid(void)
{
if( !( flags & FL_SWIM ) )
{
return;
}
int i;
if( !ent )
{
return;
}
if (!(flags & FL_SWIM)) {
return;
}
cVehicleSlot::NotSolid();
if (!ent) {
return;
}
if( ent->IsSubclassOfTurretGun() )
{
TurretGun *turret = ( TurretGun * )ent.Pointer();
Entity *owner = turret->GetOwner();
// Save previous values
prev_takedamage = ent->takedamage;
prev_solid = ent->edict->solid;
prev_contents = ent->edict->r.contents;
if( owner )
{
owner_prev_takedamage = owner->takedamage;
owner_prev_solid = owner->edict->solid;
owner_prev_contents = owner->edict->r.contents;
ent->takedamage = DAMAGE_NO;
ent->setSolidType(SOLID_NOT);
owner->takedamage = DAMAGE_NO;
owner->setSolidType( SOLID_NOT );
}
}
if (ent->IsSubclassOfTurretGun()) {
TurretGun *turret = static_cast<TurretGun *>(ent.Pointer());
Entity *owner = turret->GetOwner();
if (owner) {
owner_prev_takedamage = owner->takedamage;
owner_prev_solid = owner->edict->solid;
owner_prev_contents = owner->edict->r.contents;
owner->takedamage = DAMAGE_NO;
owner->setSolidType(SOLID_NOT);
}
}
for (i = 0; i < ent->numchildren; i++) {
Entity *sub = G_GetEntity(ent->children[i]);
if (sub && !sub->IsSubclassOfWeapon()) {
sub->setSolidType(SOLID_NOT);
}
}
}
void cTurretSlot::Solid
(
void
)
void cTurretSlot::Solid(void)
{
if( !( flags & FL_SWIM ) )
{
return;
}
int i;
if( !ent )
{
return;
}
if (!(flags & FL_SWIM)) {
return;
}
cVehicleSlot::NotSolid();
if (!ent) {
return;
}
if( ent->IsSubclassOfTurretGun() )
{
TurretGun *turret = ( TurretGun * )ent.Pointer();
Entity *owner = turret->GetOwner();
// Restore previous values
ent->takedamage = prev_takedamage;
ent->setSolidType(prev_solid);
if( owner )
{
owner->takedamage = owner_prev_takedamage;
owner->setSolidType( owner_prev_solid );
// Save previous values
prev_takedamage = (damage_t)-1;
prev_solid = (solid_t)-1;
owner_prev_takedamage = ( damage_t )-1;
owner_prev_solid = ( solid_t )-1;
}
}
if (ent->IsSubclassOfTurretGun()) {
TurretGun *turret = static_cast<TurretGun *>(ent.Pointer());
Entity *owner = turret->GetOwner();
if (owner) {
owner->takedamage = owner_prev_takedamage;
owner->setSolidType(owner_prev_solid);
owner_prev_takedamage = (damage_t)-1;
owner_prev_solid = (solid_t)-1;
}
}
for (i = 0; i < ent->numchildren; i++) {
Entity *sub = G_GetEntity(ent->children[i]);
if (sub && !sub->IsSubclassOfWeapon()) {
sub->setSolidType(SOLID_BBOX);
}
}
}
+41 -50
View File
@@ -23,78 +23,69 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// VehicleSlot.h
//
#ifndef __VEHICLESLOT_H__
#define __VEHICLESLOT_H__
#pragma once
#include "g_local.h"
#include "class.h"
#include "entity.h"
#define SLOT_FREE 1
#define SLOT_BUSY 2
#define SLOT_UNUSED 4
#define SLOT_FREE 1
#define SLOT_BUSY 2
#define SLOT_UNUSED 4
class cVehicleSlot : public Class {
class cVehicleSlot : public Class
{
public:
SafePtr<Entity> ent;
int flags;
int boneindex;
int enter_boneindex;
SafePtr<Entity> ent;
int flags;
int boneindex;
int enter_boneindex;
private:
damage_t prev_takedamage;
solid_t prev_solid;
int prev_contents;
protected:
damage_t prev_takedamage;
solid_t prev_solid;
int prev_contents;
public:
cVehicleSlot();
cVehicleSlot();
virtual void NotSolid( void );
virtual void Solid( void );
void Archive( Archiver& arc ) override;
virtual void NotSolid(void);
virtual void Solid(void);
void Archive(Archiver &arc) override;
};
inline
void cVehicleSlot::Archive
(
Archiver& arc
)
inline void cVehicleSlot::Archive(Archiver& arc)
{
Class::Archive( arc );
Class::Archive(arc);
arc.ArchiveSafePointer( &ent );
arc.ArchiveInteger( &flags );
arc.ArchiveInteger( &boneindex );
arc.ArchiveInteger( &enter_boneindex );
ArchiveEnum( prev_takedamage, damage_t );
ArchiveEnum( prev_solid, solid_t );
arc.ArchiveInteger( &prev_contents );
arc.ArchiveSafePointer(&ent);
arc.ArchiveInteger(&flags);
arc.ArchiveInteger(&boneindex);
arc.ArchiveInteger(&enter_boneindex);
ArchiveEnum(prev_takedamage, damage_t);
ArchiveEnum(prev_solid, solid_t);
arc.ArchiveInteger(&prev_contents);
}
class cTurretSlot : public cVehicleSlot {
damage_t owner_prev_takedamage;
solid_t owner_prev_solid;
int owner_prev_contents;
class cTurretSlot : public cVehicleSlot
{
damage_t owner_prev_takedamage;
solid_t owner_prev_solid;
int owner_prev_contents;
public:
cTurretSlot();
cTurretSlot();
void NotSolid( void ) override;
void Solid( void ) override;
void Archive( Archiver& arc ) override;
void NotSolid(void) override;
void Solid(void) override;
void Archive(Archiver& arc) override;
};
inline
void cTurretSlot::Archive
(
Archiver& arc
)
inline void cTurretSlot::Archive(Archiver& arc)
{
cVehicleSlot::Archive( arc );
cVehicleSlot::Archive(arc);
ArchiveEnum( owner_prev_takedamage, damage_t );
ArchiveEnum( owner_prev_solid, solid_t );
arc.ArchiveInteger( &owner_prev_contents );
ArchiveEnum(owner_prev_takedamage, damage_t);
ArchiveEnum(owner_prev_solid, solid_t);
arc.ArchiveInteger(&owner_prev_contents);
}
#endif // __VEHICLESLOT_H__
+494 -74
View File
@@ -23,127 +23,547 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "vehicle.h"
#include "vehicleturret.h"
#include "player.h"
#include "g_phys.h"
CLASS_DECLARATION(DrivableVehicle, VehicleTank, "VehicleTank")
{
{ &EV_Damage, &VehicleTank::EventDamage },
{ NULL, NULL }
CLASS_DECLARATION(DrivableVehicle, VehicleTank, "VehicleTank") {
{&EV_Damage, &VehicleTank::EventDamage},
{NULL, NULL }
};
VehicleTank::VehicleTank()
{
entflags |= FL_ROTATEDBOUNDS;
entflags |= FL_ROTATEDBOUNDS;
}
VehicleTank::~VehicleTank()
{
entflags &= ~FL_ROTATEDBOUNDS;
entflags &= ~FL_ROTATEDBOUNDS;
}
qboolean VehicleTank::Drive(usercmd_t *ucmd)
{
Vector i;
Vector j;
Vector k;
Vector vTmp;
Vector i;
Vector j;
Vector k;
Vector vTmp;
vTmp = velocity;
VectorNormalize(vTmp);
vTmp = velocity;
vTmp.normalize();
if (!driver.ent || !driver.ent->client)
{
return qfalse;
}
if (!driver.ent || !driver.ent->isClient()) {
return qfalse;
}
if (!drivable)
{
driver.ent->client->ps.pm_flags |= PMF_FROZEN;
ucmd->forwardmove = 0;
ucmd->rightmove = 0;
ucmd->upmove = 0;
return qfalse;
}
if (!drivable) {
driver.ent->client->ps.pm_flags |= PMF_FROZEN;
ucmd->forwardmove = 0;
ucmd->rightmove = 0;
ucmd->upmove = 0;
return qfalse;
}
moveimpulse = ucmd->forwardmove * (vTmp.length() + 1.0);
m_bIsBraking = ucmd->forwardmove >> 31;
if (!m_bAutoPilot) {
//
// ignore client's control if the vehicle is in auto-pilot mode
//
moveimpulse = ucmd->forwardmove * (vTmp.length() + 1.0);
m_bIsBraking = ucmd->forwardmove < 0;
m_fAccelerator += ucmd->forwardmove * 0.005;
// acceleration must be an alpha value between [0, 1]
m_fAccelerator = Q_clamp_float(m_fAccelerator, 0, 1);
m_fAccelerator += ucmd->forwardmove * 0.005;
turnimpulse = -ucmd->rightmove;
jumpimpulse = ucmd->upmove;
}
if (m_fAccelerator < 0)
{
m_fAccelerator = 0.0;
}
VehicleTurretGun *vtg = (VehicleTurretGun *)Turrets[0].ent.Pointer();
turnimpulse = -ucmd->rightmove;
if (vtg && vtg->IsSubclassOfVehicleTurretGun() && driver.ent->IsSubclassOfSentient()) {
vtg->RemoteControl(ucmd, (Sentient *)driver.ent.Pointer());
VehicleTurretGun *vtg = (VehicleTurretGun *)Turrets[0].ent.Pointer();
if (vtg && vtg->IsSubclassOfVehicleTurretGun() && driver.ent->IsSubclassOfSentient())
{
vtg->RemoteControl(ucmd, (Sentient *)driver.ent.Pointer());
if (ucmd->upmove)
turnimpulse -= AngleSubtract(angles[1], vtg->angles[1]);
}
return qtrue;
if (ucmd->upmove) {
turnimpulse -= AngleSubtract(angles[1], vtg->angles[1]);
}
}
return qtrue;
}
void VehicleTank::EventDamage(Event *ev)
{
int mod;
mod = ev->GetInteger(9);
int mod;
mod = ev->GetInteger(9);
if (mod > MOD_VEHICLE && mod != MOD_SHOTGUN && mod != MOD_GRENADE)
{
Vehicle::EventDamage(ev);
if (g_gametype->integer == GT_SINGLE_PLAYER)
{
Player *p = (Player *)driver.ent.Pointer();
if (p)
{
if (p->IsSubclassOfPlayer())
{
p->m_iNumHitsTaken++;
}
}
}
}
if (g_gametype->integer == GT_TOW && !dmManager.RoundActive()) {
return;
}
switch (mod) {
case MOD_BULLET:
case MOD_BASH:
case MOD_FAST_BULLET:
case MOD_VEHICLE:
case MOD_SHOTGUN:
case MOD_GRENADE:
return;
}
Vehicle::EventDamage(ev);
if (g_gametype->integer == GT_SINGLE_PLAYER) {
Player *p = (Player *)driver.ent.Pointer();
if (p) {
if (p->IsSubclassOfPlayer()) {
p->m_iNumHitsTaken++;
}
}
}
}
void VehicleTank::Think()
{
flags |= FL_POSTTHINK;
flags |= FL_POSTTHINK;
}
void VehicleTank::Postthink()
{
// FIXME: STUB
float turn;
Vector i, j, k;
Vector normalsum;
Vector temp;
Vector pitch, roll;
Vector acceleration;
Vector atmp, atmp2, aup;
VehicleBase *v, *last;
float drivespeed;
Vector primal_angles, primal_origin;
Vector vTmp;
Vector vAddedAngles;
Vector n_angles;
float dot;
Vector newvel, flatvel;
Vector anglediff;
primal_angles = angles;
primal_origin = origin;
if (!g_vehicle->integer || edict->s.renderfx & RF_DONTDRAW) {
// don't process physics
return;
}
if (m_pCollisionEntity) {
// use the collision entity for collision
setSolidType(SOLID_NOT);
m_pCollisionEntity->Solid();
}
prev_velocity = velocity;
SetSlotsNonSolid();
if (m_bAnimMove) {
AnimMoveVehicle();
} else {
if (!m_bMovementLocked) {
FactorOutAnglesOffset();
FactorOutOriginOffset();
}
MoveVehicle();
}
SetSlotsSolid();
if (m_vOldMins != vec_zero && m_vOldMaxs != vec_zero) {
mins = m_vOldMins;
maxs = m_vOldMaxs;
} else if (mins != vec_zero && maxs != vec_zero) {
m_vOldMins = mins;
m_vOldMaxs = maxs;
}
if (m_bAnimMove) {
moveimpulse = velocity.length() * level.frametime;
turnimpulse = avelocity[1] * level.frametime;
} else 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;
UpdateBones();
UpdateShaderOffset();
UpdateTires();
UpdateNormals();
temp = angles;
temp.AngleVectorsLeft(&i, &j, &k);
velocity[0] *= 0.925f;
velocity[1] *= 0.925f;
turn = turnangle / 200.0;
flatvel = orientation[0];
velocity += flatvel * currentspeed;
flatvel[2] = 0;
dot = velocity * flatvel;
dot = Q_clamp_float(dot, -speed, speed);
newvel = flatvel * dot;
velocity[0] = newvel[0];
velocity[1] = newvel[1];
avelocity *= 0.05f;
if (dot < 350) {
dot = 350;
}
avelocity.y += turn * dot;
angles += avelocity * level.frametime;
setAngles(angles);
if (Turrets[0].ent && Turrets[0].ent->IsSubclassOfVehicleTurretGun() && driver.ent
&& driver.ent->IsSubclassOfSentient()) {
VehicleTurretGun *pTurret = static_cast<VehicleTurretGun *>(Turrets[0].ent.Pointer());
if (jumpimpulse != 0) {
pTurret->SetUserViewAngles(pTurret->GetUserViewAngles() - Vector(0, avelocity[1] * level.frametime, 0));
}
}
drivespeed = acceleration * orientation[0];
UpdateSound();
if (AssertRotation(angles, primal_angles) != true) {
angles = primal_angles;
}
CalculateAnglesOffset(acceleration);
CalculateOriginOffset();
last_origin = origin;
anglediff = (angles - primal_angles) * level.frametime;
if (anglediff.x > 180 || anglediff.x < -180) anglediff.x = 0;
if (anglediff.y > 180 || anglediff.y < -180) anglediff.y = 0;
if (anglediff.z > 180 || anglediff.z < -180) anglediff.z = 0;
if (anglediff.x > -1 || anglediff.x < 1) anglediff.x = 0;
if (anglediff.y > -1 || anglediff.y < 1) anglediff.y = 0;
if (anglediff.z > -1 || anglediff.z < 1) anglediff.z = 0;
avelocity = anglediff;
if (!m_bAnimMove && !m_bMovementLocked) {
FactorInOriginOffset();
FactorInAnglesOffset(&vAddedAngles);
}
CalculateAnimationData(vAddedAngles, m_vOriginOffset + m_vOriginOffset2);
if (m_pCollisionEntity) {
Vector vaDelta;
SetSlotsNonSolid();
vaDelta[0] = angledist(angles[0] - m_pCollisionEntity->angles[0]);
vaDelta[1] = angledist(angles[1] - m_pCollisionEntity->angles[1]);
vaDelta[2] = angledist(angles[2] - m_pCollisionEntity->angles[2]);
m_pCollisionEntity->Solid();
G_PushMove(m_pCollisionEntity, origin - primal_origin, vaDelta);
G_TouchTriggers(m_pCollisionEntity);
SetSlotsSolid();
m_pCollisionEntity->setOrigin(origin);
m_pCollisionEntity->setAngles(angles);
}
SetupVehicleSoundEntities();
i = orientation[0];
j = orientation[1];
k = orientation[2];
//
// update slots
//
for (int ii = 0; ii < MAX_PASSENGERS; ii++) {
UpdatePassengerSlot(ii);
}
for (int ii = 0; ii < MAX_TURRETS; ii++) {
UpdateTurretSlot(ii);
}
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();
if (m_pCollisionEntity) {
setSolidType(SOLID_NOT);
m_pCollisionEntity->Solid();
} else {
setSolidType(SOLID_BBOX);
setContents(CONTENTS_UNKNOWN2);
}
if ((driver.flags & SLOT_BUSY) && driver.ent) {
if (driver.ent->IsSubclassOfPlayer()) {
driver.ent->takedamage = DAMAGE_YES;
// Fixed in OPM.
// It's probably a mistake in moh 2.0 and above,
// the tank was non-solid with a player driver,
// instead of the driver being non-solid.
//setSolidType(SOLID_NOT);
driver.ent->setSolidType(SOLID_NOT);
} else {
driver.ent->takedamage = DAMAGE_NO;
driver.ent->setSolidType(SOLID_NOT);
}
}
}
void VehicleTank::CalculateOriginOffset()
{
// FIXME: STUB
int index;
Vector vTireAvg;
Vector vMissHit;
Vector temp;
int iNum = 0;
Vector acceleration;
Vector oldoffset;
oldoffset = m_vOriginOffset;
m_vOriginOffset += m_vOriginOffset2;
m_vOriginOffset2 = vec_zero;
for (index = 0; index < NUM_VEHICLE_TIRES; index++) {
if (m_bTireHit[index]) {
vTireAvg += origin - m_vTireEnd[index];
iNum++;
} else {
vMissHit = Corners[index];
}
}
if (m_iNumNormals > 0 && iNum == NUM_VEHICLE_TIRES - 1) {
Vector point;
temp = m_vNormalSum * (1.f / m_iNumNormals);
temp.normalize();
ProjectPointOnPlane(point, vMissHit, temp);
vTireAvg += point;
iNum++;
}
if (iNum == NUM_VEHICLE_TIRES) {
vec3_t vOriginCornerOffset;
vTireAvg *= 1.f / NUM_VEHICLE_TIRES;
MatrixTransformVector(m_vOriginCornerOffset, orientation, vOriginCornerOffset);
vTireAvg -= vOriginCornerOffset;
m_vOriginOffset2 += vTireAvg;
}
//m_vOriginOffset2 += vec_zero;
m_vOriginOffset -= m_vOriginOffset2;
if (!isfinite(m_vOriginOffset[0]) || !isfinite(m_vOriginOffset[1]) || !isfinite(m_vOriginOffset[2])) {
m_vOriginOffset = oldoffset;
}
}
void VehicleTank::UpdateSound()
{
// FIXME: STUB
float pitch = 1.f;
float volume = 1.f;
if (level.time < m_fNextSoundState) {
return;
}
pitch = (velocity.length() - m_fSoundMinSpeed) / (m_fSoundMaxSpeed - m_fSoundMinSpeed);
pitch = Q_clamp_float(pitch, 0, 1);
pitch = (m_fSoundMaxPitch - m_fSoundMinPitch) * pitch + m_fSoundMinPitch;
volume = (velocity.length() - m_fVolumeMinSpeed) / (m_fVolumeMaxSpeed - m_fVolumeMinSpeed);
volume = Q_clamp_float(volume, 0, 1);
volume = (m_fVolumeMaxPitch - m_fVolumeMinPitch) * volume + m_fVolumeMinPitch;
if (level.intermissiontime) {
m_eSoundState = ST_OFF;
}
switch (m_eSoundState) {
case ST_OFF:
StopLoopSound();
TurnOffVehicleSoundEntities();
m_fNextSoundState = level.time;
if (driver.ent || m_bAutoPilot) {
m_eSoundState = ST_OFF_TRANS_IDLE;
}
break;
case ST_OFF_TRANS_IDLE:
m_fNextSoundState = level.time;
m_eSoundState = ST_IDLE;
Sound(m_sSoundSet + "snd_on", CHAN_AUTO);
LoopSound(m_sSoundSet + "snd_idle");
break;
case ST_IDLE_TRANS_OFF:
m_fNextSoundState = level.time;
m_eSoundState = ST_OFF;
Sound(m_sSoundSet + "snd_off", CHAN_AUTO);
StopLoopSound();
break;
case ST_IDLE:
m_fNextSoundState = level.time;
if (driver.ent || m_bAutoPilot) {
if (fabs(velocity * orientation[0]) > 150) {
m_eSoundState = ST_IDLE_TRANS_RUN;
} else if (fabs(turnimpulse) > 1) {
m_eSoundState = ST_IDLE_TRANS_TURN;
}
} else {
m_eSoundState = ST_IDLE_TRANS_OFF;
}
LoopSound(m_sSoundSet + "snd_idle");
TurnOffVehicleSoundEntities();
break;
case ST_IDLE_TRANS_RUN:
m_fNextSoundState = level.time;
m_eSoundState = ST_RUN;
Sound(m_sSoundSet + "snd_revup", CHAN_AUTO);
Sound(m_sSoundSet + "snd_shift", CHAN_AUTO);
LoopSound(m_sSoundSet + "snd_run", volume, -1, -1, pitch);
break;
case ST_RUN:
m_fNextSoundState = level.time;
if (fabs(velocity * orientation[0]) < 150) {
m_eSoundState = ST_RUN_TRANS_IDLE;
}
TurnOnVehicleSoundEntities();
LoopSound(m_sSoundSet + "snd_run", volume, -1, -1, pitch);
break;
case ST_RUN_TRANS_IDLE:
m_fNextSoundState = level.time;
m_eSoundState = ST_IDLE;
Sound(m_sSoundSet + "snd_revdown", CHAN_AUTO);
LoopSound(m_sSoundSet + "snd_idle");
break;
case ST_IDLE_TRANS_TURN:
m_fNextSoundState = level.time;
m_eSoundState = ST_TURN;
Sound(m_sSoundSet + "snd_revup", CHAN_AUTO);
Sound(m_sSoundSet + "snd_shift", CHAN_AUTO);
LoopSound(m_sSoundSet + "snd_run", volume, -1, -1, pitch);
break;
case ST_TURN:
m_fNextSoundState = level.time;
if (fabs(turnimpulse) < 1) {
m_eSoundState = ST_TURN_TRANS_IDLE;
}
LoopSound(m_sSoundSet + "snd_run", volume, -1, -1, pitch);
break;
case ST_TURN_TRANS_IDLE:
m_fNextSoundState = level.time;
m_eSoundState = ST_IDLE;
Sound(m_sSoundSet + "snd_revdown", CHAN_AUTO);
LoopSound(m_sSoundSet + "snd_idle");
break;
default:
m_fNextSoundState = level.time;
m_eSoundState = ST_OFF;
break;
}
}
void VehicleTank::AttachDriverSlot(Event* ev)
//
// Fixed in OPM:
// 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
/*
void VehicleTank::AttachDriverSlot(Event *ev)
{
Vehicle::AttachDriverSlot(ev);
Vehicle::AttachDriverSlot(ev);
VehicleTurretGun *vtg = (VehicleTurretGun *)Turrets[0].ent.Pointer();
if (!driver.ent) {
//
// Added in OPM.
// original mohaa doesn't check if driver.ent is valid, which can cause crash if the attached entity is null.
// on single-player, it would crash while loading m5l2a when sv_maxclients is above 1.
// The reason of the crash is that attachdriverslot is called with $player which can be NULL on prespawn.
// $player is not created on prespawn when sv_maxclients is above 1
//
return;
}
if (vtg && vtg->IsSubclassOfVehicleTurretGun() && driver.ent->IsSubclassOfSentient())
{
vtg->SetOwner((Sentient *)driver.ent.Pointer());
Think();
Postthink();
vtg->Think();
}
VehicleTurretGun *vtg = (VehicleTurretGun *)Turrets[0].ent.Pointer();
if (vtg && vtg->IsSubclassOfVehicleTurretGun() && driver.ent->IsSubclassOfSentient()) {
vtg->SetRemoteOwner(static_cast<Sentient *>(driver.ent.Pointer()));
Think();
Postthink();
vtg->Think();
}
}
*/
void VehicleTank::AttachDriverSlot(int slot, Entity* ent, Vector vExitPosition)
{
Vehicle::AttachDriverSlot(slot, ent, vExitPosition);
if (!driver.ent) {
//
// Added in OPM.
// original mohaa doesn't check if driver.ent is valid, which can cause crash if the attached entity is null.
// on single-player, it would crash while loading m5l2a when sv_maxclients is above 1.
// The reason of the crash is that attachdriverslot is called with $player which can be NULL on prespawn.
// $player is not created on prespawn when sv_maxclients is above 1
//
return;
}
VehicleTurretGun* vtg = static_cast<VehicleTurretGun*>(Turrets[0].ent.Pointer());
if (vtg && vtg->IsSubclassOfVehicleTurretGun() && driver.ent->IsSubclassOfSentient()) {
vtg->SetRemoteOwner(static_cast<Sentient*>(driver.ent.Pointer()));
Think();
Postthink();
vtg->Think();
}
}
void VehicleTank::DriverAdded()
{
int i;
for (i = 0; i < MAX_TURRETS; i++) {
if (Turrets[i].flags & SLOT_BUSY && Turrets[i].ent && Turrets[i].ent->IsSubclassOfVehicleTurretGun()) {
VehicleTurretGun *pTurret = static_cast<VehicleTurretGun *>(Turrets[i].ent.Pointer());
pTurret->TurretHasBeenMounted();
}
}
}
+641 -38
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2018 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -22,64 +22,667 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "vehicle.h"
#include "player.h"
#include "debuglines.h"
#include "g_phys.h"
CLASS_DECLARATION(DrivableVehicle, VehicleWheelsX2, "VehicleWheelsX2")
{
{ &EV_Damage, &VehicleWheelsX2::EventDamage },
{ &EV_Killed, &VehicleWheelsX2::Killed },
{ NULL, NULL }
CLASS_DECLARATION(DrivableVehicle, VehicleWheelsX2, "VehicleWheelsX2") {
{&EV_Damage, &VehicleWheelsX2::EventDamage},
{&EV_Killed, &VehicleWheelsX2::Killed },
{NULL, NULL }
};
VehicleWheelsX2::VehicleWheelsX2()
{
m_iGear = 1;
m_iRPM = 0;
gravity = 1.0;
m_fDifferentialRatio = 4.8800001f;
m_fGearEfficiency = 0.69999999f;
m_fGearRatio[0] = -2.9400001f;
m_fGearRatio[1] = 2.9400001f;
m_fGearRatio[2] = 1.9400001f;
m_fGearRatio[3] = 1.0f;
m_fAccelerator = 0.0f;
m_bAutomatic = qtrue;
m_bBackSlipping = qfalse;
m_bFrontSlipping = qfalse;
gravity = 1.0;
m_fDifferentialRatio = 4.88f;
m_fGearEfficiency = 0.7f;
m_fGearRatio[0] = -2.95f;
m_fGearRatio[1] = 2.95f;
m_fGearRatio[2] = 1.95f;
m_fGearRatio[3] = 1.0f;
m_iGear = 1;
m_iRPM = 0;
m_fAccelerator = 0.0f;
m_bAutomatic = qtrue;
m_bBackSlipping = qfalse;
m_bFrontSlipping = qfalse;
}
void VehicleWheelsX2::UpdateVariables(Vector *acceleration, Vector *vpn, Vector *vup, Vector *vright, Vector *t_vpn, Vector *t_vup, Vector *t_vright)
void VehicleWheelsX2::Killed(Event *ev)
{
// FIXME: STUB
deadflag = DEAD_DEAD;
}
float VehicleWheelsX2::TorqueLookup(int rpm)
{
if (rpm <= 2099)
return 100.0;
if (rpm > 3599)
return 0.0;
return (100 * (3600 - rpm)) * 0.001;
if (rpm < 2100) {
return 100.0;
} else if (rpm >= 3600) {
return 0.0;
} else {
return (100 * (3600 - rpm)) / 1000.f;
}
}
void VehicleWheelsX2::UpdateVariables(
Vector *acceleration, Vector *vpn, Vector *vup, Vector *vright, Vector *t_vpn, Vector *t_vup, Vector *t_vright
)
{
int i;
Vector vNewCG;
Vector vBoxSize;
float longspeed;
Vector _i, _j, _k;
Vector r_i, r_j, r_k;
Vector r_velocity;
float dots[4];
r_velocity = velocity;
m_bIsSkidding = false;
vBoxSize = maxs - mins;
SetControllerAngles(0, Vector(0, turnangle, 0));
SetControllerAngles(1, Vector(0, turnangle, 0));
vNewCG = localorigin;
if (vNewCG != m_vCG) {
m_vCG = vNewCG;
vNewCG -= localorigin;
m_fWheelBase = vBoxSize.x;
m_fWheelFrontDist = vBoxSize.x * 0.5 - vNewCG.x;
m_fWheelBackDist = vBoxSize.x * -0.5 + vNewCG.x;
m_fTrackWidth = vBoxSize.y;
}
Vector vNewVpn = angles;
vNewVpn.AngleVectorsLeft(&r_i, &r_j, &r_k);
vNewVpn.y += turnangle;
vNewVpn.AngleVectorsLeft(&_i, &_j, &_k);
dots[3] = r_velocity * *vpn * 0.02;
dots[2] = r_velocity * *vright * 0.02;
dots[1] = r_velocity * *t_vpn * 0.02;
dots[0] = r_velocity * *t_vright * 0.02;
m_sWheels[0].fTraction = 0.8f;
m_sWheels[1].fTraction = 0.9f;
m_sWheels[0].fYawOffset = 0;
m_sWheels[1].fYawOffset = DEG2RAD(turnangle);
m_sWheels[0].fLongDist = m_fWheelBackDist * 0.02;
m_sWheels[1].fLongDist = m_fWheelFrontDist * 0.02;
m_sWheels[0].fLatDist = m_fTrackWidth * -0.02;
m_sWheels[1].fLatDist = m_fTrackWidth * 0.02;
// initialize the wheels
for (i = 0; i < 2; i++) {
m_sWheels[i].fLongForce = 0;
m_sWheels[i].fForce = 0;
m_sWheels[i].vLongForce = vec_zero;
m_sWheels[i].vLatForce = vec_zero;
m_sWheels[i].vForce = vec_zero;
m_sWheels[i].vVelocity = vec_zero;
m_sWheels[i].bSkidding = false;
m_sWheels[i].bSpinning = false;
m_sWheels[i].fTorque = 0;
m_sWheels[i].fLatTorque = 0;
m_sWheels[i].fLongTorque = 0;
}
for (i = 0; i < 2; i++) {
Vector p1, p3, p4;
Vector vTp, vTr, vTu;
vec3_t p2;
p3 = Corners[i];
p3.normalize();
vectoangles(p3, p2);
p1 = vec_zero;
p1[1] = angles[1] + p2[1] + 90;
p1.AngleVectorsLeft(&vTp, &vTr, &vTu);
m_sWheels[i].vVelocity = vTp * RAD2DEG(m_vAngularVelocity.y) * fabs(m_sWheels[i].fLongDist) * level.frametime;
G_LineWidth(5.0);
G_DebugLine(
origin + Corners[i][0] * r_i + Corners[i][1] * r_j,
origin + Corners[i][0] * r_i + Corners[i][1] * r_j + m_sWheels[i].vVelocity * 50,
0.7f,
0.5f,
1.0f,
1.0f
);
p1 = vec_zero;
p1[1] = angles[1] + RAD2DEG(m_sWheels[i].fYawOffset);
p1.AngleVectorsLeft(&vTp, &vTr, &vTu);
m_sWheels[i].vOrientation = vTp;
G_LineWidth(5.0);
G_DebugLine(
origin + Corners[i][0] * r_i + Corners[i][1] * r_j,
origin + Corners[i][0] * r_i + Corners[i][1] * r_j + m_sWheels[i].vOrientation * 50,
0.7f,
0.0f,
1.0f,
1.0f
);
}
Vector start, end;
Vector boxoffset;
Vector t_mins(-8, -8, -8);
Vector t_maxs(8, 8, 8);
trace_t trace;
start = origin + *vpn * (m_vCG[0] - localorigin[0]) + *vright * (m_vCG[1] - localorigin[1])
+ *vup * (m_vCG[2] - localorigin[2]);
end = start;
end[2] -= maxtracedist;
trace = G_Trace(start, t_mins, t_maxs, end, this, MASK_SOLID, qfalse, "Vehicle::PostThink Corners");
m_fInertia = m_fMass * 100;
m_fWheelFrontLoad = m_fMass * 9.81 * fabs(m_fWheelFrontDist / m_fWheelBase);
m_fWheelBackLoad = m_fMass * 9.81 * fabs(m_fWheelBackDist / m_fWheelBase);
longspeed = m_vAcceleration.length() * 0.02 * m_fMass / m_fWheelBase;
m_fWheelFrontLoad -= longspeed;
m_fWheelBackLoad += longspeed;
m_sWheels[0].fLoad = m_fWheelBackLoad;
m_sWheels[1].fLoad = m_fWheelFrontLoad;
float fMassShifted = m_fTireRadius * M_PI;
m_fTireRotationalSpeed = dots[3] / (fMassShifted + fMassShifted);
m_iRPM = m_fTireRotationalSpeed * m_fGearRatio[m_iGear] * m_fDifferentialRatio * 10;
m_fMaxTraction =
TorqueLookup(m_iRPM) * m_fGearRatio[m_iGear] * m_fDifferentialRatio * m_fGearEfficiency / m_fTireRadius;
m_fTractionForce = m_fAccelerator * m_fMaxTraction;
if (m_bIsBraking && dots[3] > 0) {
m_fTractionForce = -fSign(dots[3]) * 1000 * dots[3];
}
for (i = 0; i < 2; i++) {
float maxgrip;
maxgrip = m_sWheels[i].fTraction * m_sWheels[i].fLoad * 9.81;
if (m_fTractionForce > maxgrip) {
m_fTractionForce = maxgrip * 0.6;
m_sWheels[i].bSpinning = true;
m_sWheels[i].bSkidding = true;
Com_Printf("Skidding!\n");
}
if (m_fTractionForce < -maxgrip) {
m_fTractionForce = -maxgrip * 0.6;
m_sWheels[i].bSkidding = true;
Com_Printf("Skidding!\n");
}
m_sWheels[i].fLongForce = this->m_sWheels[i].fLongForce + m_fTractionForce;
m_sWheels[i].vLongForce += m_sWheels[i].vOrientation * m_sWheels[i].fLongForce;
}
m_vResistance[0] =
-(velocity[0] * 0.02 * m_fRollingResistance + velocity[0] * 0.02 * m_fDrag * fabs(velocity[0] * 0.02));
m_vResistance[1] =
-(velocity[1] * 0.02 * m_fRollingResistance + velocity[1] * 0.02 * m_fDrag * fabs(velocity[1] * 0.02));
m_vResistance[2] =
-(velocity[2] * 0.02 * m_fRollingResistance + velocity[2] * 0.02 * m_fDrag * fabs(velocity[2] * 0.02));
m_fBrakingPerformance = -m_fRollingResistance - *vpn * Vector(0, 0, -1) * m_fMass;
if (dots[3] == 0) {
m_fBrakingPerformance = 0;
} else {
m_fBrakingPerformance = (dots[3] - (m_fTireRotationalSpeed * m_fTireRadius - m_fBrakingPerformance)) / dots[3];
m_fBrakingPerformance = (1.0 - m_fBrakingPerformance) * -(-m_fFrontBrakingForce - m_fBackBrakingForce);
}
if (r_velocity.length() * 0.02 > 0.01) {
m_fTangForce = 0;
m_vTangForce = vec_zero;
for (i = 0; i < 2; i++) {
Vector va, vr;
Vector vVel;
Vector v1, v2;
va = angles;
va.x = 0;
va.y += RAD2DEG(m_sWheels[i].fYawOffset);
va.z = 0;
va.AngleVectorsLeft(NULL, &vr, NULL);
vVel = m_sWheels[i].vVelocity + velocity;
// get the direction
v1 = vVel;
v1.normalize();
// get the angles
vectoangles(v1, v2);
m_sWheels[i].fSlipAngle = DEG2RAD(angledist(va.y - v2.y));
m_sWheels[i].fGripCoef = m_sWheels[i].fSlipAngle * 0.15;
m_sWheels[i].fGripCoef = Q_clamp_float(m_sWheels[i].fGripCoef, -1.2f, 1.2f);
m_sWheels[i].fLatForce += m_sWheels[i].fGripCoef * m_sWheels[i].fLoad * 9.81;
if (m_sWheels[i].fLoad * 2 * m_sWheels[i].fTraction < fabs(m_sWheels[i].fLatForce)) {
m_sWheels[i].fLatForce = m_sWheels[i].fLatForce / 9.81;
m_sWheels[i].bSkidding = true;
Com_Printf("Skidding %i!\n", i);
}
m_sWheels[i].vLatForce += vr * m_sWheels[i].fLatForce;
G_LineWidth(3.0);
G_DebugLine(
origin + Corners[i][0] * r_i + Corners[i][1] * r_j,
origin + Corners[i][0] * r_i + Corners[i][1] * r_j + m_sWheels[i].vLatForce * 50 * (1.0 / m_fMass),
0.7f,
0.5f,
0.2f,
1.0f
);
}
} else {
m_fTangForce = 0;
m_vTangForce = vec_zero;
}
m_vForce = vec_zero;
for (i = 0; i < 2; i++) {
m_sWheels[i].vForce = m_sWheels[i].vLatForce + m_sWheels[i].vLongForce;
m_vForce += m_sWheels[i].vForce;
}
m_vForce += m_vResistance;
G_LineWidth(5.0);
G_DebugLine(origin, origin + m_vTangForce * (1.0 / m_fMass) * 50, 1.0, 0.0, 1.0, 1.0);
m_vAcceleration = m_vForce * (1.0 / m_fMass) * 50;
m_fTorque = 0;
for (i = 0; i < 2; i++) {
m_sWheels[i].fTorque += m_sWheels[i].fLongTorque + m_sWheels[i].fLatTorque;
m_fTorque += m_sWheels[i].fTorque;
}
m_vAngularAcceleration[1] = angledist(RAD2DEG(m_fTorque));
m_vAngularVelocity += m_vAngularAcceleration * level.frametime;
m_vAngularVelocity *= 0.825f;
avelocity = m_vAngularVelocity;
if (m_bAutomatic) {
//
// set the gear
//
if (m_iRPM >= 2100 && m_iGear <= 2) {
m_iGear++;
}
if (m_iRPM <= 600 && m_iGear > 1) {
m_iGear--;
}
}
prev_moveimpulse = moveimpulse;
}
void VehicleWheelsX2::Think()
{
vmove_t vm;
vmove_t vm;
flags |= FL_POSTTHINK;
prev_velocity = velocity;
flags |= FL_POSTTHINK;
prev_velocity = velocity;
SetMoveInfo(&vm);
VmoveSingle(&vm);
GetMoveInfo(&vm);
SetMoveInfo(&vm);
VmoveSingle(&vm);
GetMoveInfo(&vm);
}
void VehicleWheelsX2::Postthink()
{
// FIXME: STUB
}
float turn;
Vector i, j, k;
int index;
trace_t trace;
Vector normalsum;
Vector normalsum_Front;
int numnormals_Front;
Vector normalsum_Back;
int numnormals_Back;
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;
void VehicleWheelsX2::Killed(Event* ev)
{
deadflag = DEAD_DEAD;
}
primal_angles = angles;
if (drivable) {
currentspeed = moveimpulse;
turnangle = turnangle * 0.25f + turnimpulse;
turnangle = Q_clamp_float(turnangle, -maxturnrate, maxturnrate);
if (turnangle > maxturnrate) {
turnangle = maxturnrate;
} else if (turnangle < -maxturnrate) {
turnangle = -maxturnrate;
} else if (fabs(turnangle) < 2) {
turnangle = 0;
}
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;
angles[0] = 0;
angles[2] = 0;
temp[0] = angles[0];
temp[1] = angles[1];
temp[2] = angles[2];
temp.AngleVectorsLeft(&i, &j, &k);
j = vec_zero - j;
index = 0;
numnormals_Front = 0;
numnormals_Back = 0;
for (index = 0; index < 4; index++) {
Vector start, end;
Vector boxoffset;
Vector t_mins(-8, -8, -8);
Vector t_maxs(8, 8, 8);
boxoffset = Corners[index];
start = origin + i * boxoffset[0] + j * boxoffset[1] + k * boxoffset[2];
end = start;
end[2] -= maxtracedist;
trace = G_Trace(start, mins, maxs, end, this, MASK_SOLID, qfalse, "Vehicle::PostThink Corners");
if (trace.fraction != 1 && !trace.startsolid) {
if (index > 2) {
normalsum_Front += trace.plane.normal;
numnormals_Front++;
} else {
normalsum_Back += trace.plane.normal;
numnormals_Back++;
}
normalsum += trace.plane.normal;
}
}
if (angles[2] < 60 || angles[2] > 300) {
if (numnormals_Front > 1) {
m_vFrontNormal = normalsum_Front * (1.0 / numnormals_Front);
temp = m_vFrontNormal;
m_vFrontAngles[0] = -temp.CrossProduct(temp, j).toPitch();
// no yaw
m_vFrontAngles[1] = 0;
temp = m_vFrontNormal;
m_vFrontAngles[2] = temp.CrossProduct(temp, i).toPitch();
}
if (numnormals_Back > 1) {
m_vBackNormal = normalsum_Back * (1.0 / numnormals_Back);
temp = m_vBackNormal;
m_vBackAngles[0] = -temp.CrossProduct(temp, j).toPitch();
// no yaw
m_vBackAngles[1] = 0;
temp = m_vBackNormal;
m_vBackAngles[2] = temp.CrossProduct(temp, i).toPitch();
}
if (numnormals_Front + numnormals_Back > 1) {
m_vBaseNormal = (normalsum_Front + normalsum_Back) * (1.0 / numnormals_Front + numnormals_Back);
temp = m_vBaseNormal;
m_vBaseAngles[0] = -temp.CrossProduct(temp, j).toPitch();
// no yaw
m_vBaseAngles[1] = 0;
temp = m_vBaseNormal;
m_vBaseAngles[2] = temp.CrossProduct(temp, i).toPitch();
}
}
n_angles = m_vBaseAngles - angles;
n_angles[0] = angledist(n_angles[0]);
n_angles[1] = angledist(n_angles[1]);
n_angles[2] = angledist(n_angles[2]);
angles[0] += n_angles[0] * 4.5 * level.frametime;
angles[2] += n_angles[2] * 4.5 * level.frametime;
m_vPrevNormal = m_vBaseNormal;
if (currentspeed < 0 && velocity * i > 0) {
m_fFrontBrakingForce = 0.2f;
m_fBackBrakingForce = 0.1f;
} else {
m_fFrontBrakingForce = 0;
m_fBackBrakingForce = 0;
}
turn = turnangle * 0.005;
Vector _i, _j, _k;
Vector vNewVpn = angles;
vNewVpn.y += turnangle;
vNewVpn.AngleVectorsLeft(&_i, &_j, &_k);
UpdateVariables(&acceleration, &i, &j, &k, &_i, &_j, &_k);
m_vAngles = angles;
if (currentspeed < 0 && velocity * i > 0) {
currentspeed = 0;
}
normalsum = vec_zero;
for (index = 0; index < 4; index++) {
Vector start, end;
Vector boxoffset;
Vector t_mins(-8, -8, -8);
Vector t_maxs(8, 8, 8);
boxoffset = Corners[index];
start = origin + i * boxoffset[0] + j * boxoffset[1] + k * boxoffset[2] + Vector(0, 0, 10);
end = start;
end[2] -= maxtracedist;
trace = G_Trace(start, mins, maxs, end, this, MASK_SOLID, qfalse, "Vehicle::PostThink Corners");
if (trace.fraction != 1.0) {
float fCoef;
if (index > 2) {
fCoef = m_fWheelFrontLoad / (m_fWheelFrontDist / m_fWheelBase * m_fMass);
fCoef = Q_clamp_float(fCoef, 0, 1);
normalsum += _i * currentspeed * fCoef;
normalsum += i * currentspeed * (1.0 - fCoef);
} else {
fCoef = m_fWheelBackLoad / (m_fWheelBackDist / m_fWheelBase * m_fMass);
fCoef = Q_clamp_float(fCoef, 0, 1);
normalsum += i * currentspeed * fCoef;
normalsum += _i * currentspeed * (1.0 - fCoef);
}
}
}
AnglesToAxis(angles, orientation);
vmove_t vm;
SetMoveInfo(&vm);
m_sMoveGrid->SetMoveInfo(&vm);
m_sMoveGrid->SetOrientation(orientation);
if (m_sMoveGrid->CheckStuck()) {
angles = primal_angles;
AnglesToAxis(angles, orientation);
}
if (groundentity && (angles[2] < 60 || angles[2] > 300)) {
float dot;
Vector newvel, flatvel;
velocity[0] *= 0.925f;
velocity[1] *= 0.925f;
newvel = orientation[0];
velocity += newvel * currentspeed;
newvel[2] = 0;
dot = velocity * newvel;
dot = Q_clamp_float(dot, -speed, speed);
if (dot > speed) {
dot = speed;
} else if (dot < -speed) {
dot = -speed;
} else if (fabs(dot) < 20) {
dot = 0;
}
flatvel = newvel * dot;
velocity[0] = flatvel[0];
velocity[1] = flatvel[1];
velocity[2] += jumpimpulse * dot;
avelocity *= 0.05f;
if (steerinplace) {
if (dot < 350) {
dot = 350;
}
avelocity.y += turn * dot;
} else {
avelocity.y += turn * dot;
}
} else {
if (angles[2] > 60) {
angles[2]; // FIXME: ??
}
velocity += m_vAcceleration * level.frametime;
}
angles += avelocity * level.frametime;
setAngles(angles);
prev_origin = origin;
}
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_idle";
} else {
sound_name = "snd_backward";
}
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);
}
}
vTmp = (angles - primal_angles) * level.frametime;
if (vTmp.x > 180 || vTmp.x < -180) {
vTmp.x = 0;
}
if (vTmp.y > 180 || vTmp.y < -180) {
vTmp.y = 0;
}
if (vTmp.z > 180 || vTmp.z < -180) {
vTmp.z = 0;
}
if (vTmp.x > -1 || vTmp.x < 1) {
vTmp.x = 0;
}
if (vTmp.y > -1 || vTmp.y < 1) {
vTmp.y = 0;
}
if (vTmp.z > -1 || vTmp.z < 1) {
vTmp.z = 0;
}
avelocity = vTmp;
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);
}
}
}
+653 -42
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2018 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -22,69 +22,680 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "vehicle.h"
#include "player.h"
#include "debuglines.h"
#include "g_phys.h"
CLASS_DECLARATION(DrivableVehicle, VehicleWheelsX4, "VehicleWheelsX4")
{
{ &EV_Damage, &VehicleWheelsX4::EventDamage },
{ &EV_Killed, &VehicleWheelsX4::Killed },
{ NULL, NULL }
CLASS_DECLARATION(DrivableVehicle, VehicleWheelsX4, "VehicleWheelsX4") {
{&EV_Damage, &VehicleWheelsX4::EventDamage},
{&EV_Killed, &VehicleWheelsX4::Killed },
{NULL, NULL }
};
VehicleWheelsX4::VehicleWheelsX4()
{
m_iGear = 1;
m_iRPM = 0;
gravity = 1.0;
m_fDifferentialRatio = 4.8800001f;
m_fGearEfficiency = 0.69999999f;
m_fGearRatio[0] = -2.9400001f;
m_fGearRatio[1] = 2.9400001f;
m_fGearRatio[2] = 1.9400001f;
m_fGearRatio[3] = 1.0f;
m_fAccelerator = 0.0f;
m_bBackSlipping = qfalse;
m_bAutomatic = qtrue;
m_bFrontSlipping = qfalse;
gravity = 1.0;
m_fDifferentialRatio = 4.88f;
m_fGearEfficiency = 0.7f;
m_fGearRatio[0] = -2.95f;
m_fGearRatio[1] = 2.95f;
m_fGearRatio[2] = 1.95f;
m_fGearRatio[3] = 1.0f;
m_iGear = 1;
m_iRPM = 0;
m_fAccelerator = 0.0f;
m_bAutomatic = qtrue;
m_bBackSlipping = qfalse;
m_bFrontSlipping = qfalse;
}
void VehicleWheelsX4::UpdateVariables(Vector *acceleration, Vector *vpn, Vector *vup, Vector *vright, Vector *t_vpn, Vector *t_vup, Vector *t_vright)
void VehicleWheelsX4::UpdateVariables(
Vector *acceleration, Vector *vpn, Vector *vup, Vector *vright, Vector *t_vpn, Vector *t_vup, Vector *t_vright
)
{
// FIXME: STUB
int i;
Vector vNewCG;
Vector vBoxSize;
float longspeed;
Vector _i, _j, _k;
Vector r_i, r_j, r_k;
Vector r_velocity;
float dots[4];
r_velocity = velocity;
m_bIsSkidding = false;
vBoxSize = maxs - mins;
SetControllerAngles(0, Vector(0, turnangle, 0));
SetControllerAngles(1, Vector(0, turnangle, 0));
vNewCG = localorigin;
if (vNewCG != m_vCG) {
m_vCG = vNewCG;
vNewCG -= localorigin;
m_fWheelBase = vBoxSize.x;
m_fWheelFrontDist = vBoxSize.x * 0.5 - vNewCG.x;
m_fWheelBackDist = vBoxSize.x * -0.5 + vNewCG.x;
m_fTrackWidth = vBoxSize.y;
}
Vector vNewVpn = angles;
vNewVpn.AngleVectorsLeft(&r_i, &r_j, &r_k);
vNewVpn.y += turnangle;
vNewVpn.AngleVectorsLeft(&_i, &_j, &_k);
dots[3] = r_velocity * *vpn * 0.02;
dots[2] = r_velocity * *vright * 0.02;
dots[1] = r_velocity * *t_vpn * 0.02;
dots[0] = r_velocity * *t_vright * 0.02;
m_sWheels[0].fTraction = 0.8f;
m_sWheels[1].fTraction = 0.9f;
m_sWheels[2].fTraction = 0.8f;
m_sWheels[3].fTraction = 0.9f;
m_sWheels[0].fYawOffset = 0;
m_sWheels[1].fYawOffset = DEG2RAD(turnangle);
m_sWheels[2].fYawOffset = 0;
m_sWheels[3].fYawOffset = DEG2RAD(turnangle);
m_sWheels[0].fLongDist = m_fWheelBackDist * 0.02;
m_sWheels[1].fLongDist = m_fWheelFrontDist * 0.02;
m_sWheels[2].fLongDist = m_fWheelBackDist * 0.02;
m_sWheels[3].fLongDist = m_fWheelFrontDist * 0.02;
m_sWheels[0].fLatDist = m_fTrackWidth * 0.5 * -0.02;
m_sWheels[1].fLatDist = m_fTrackWidth * 0.5 * 0.02;
m_sWheels[2].fLatDist = m_fTrackWidth * 0.5 * -0.02;
m_sWheels[3].fLatDist = m_fTrackWidth * 0.5 * 0.02;
// initialize the wheels
for (i = 0; i < 4; i++) {
m_sWheels[i].fLongForce = 0;
m_sWheels[i].fForce = 0;
m_sWheels[i].vLongForce = vec_zero;
m_sWheels[i].vLatForce = vec_zero;
m_sWheels[i].vForce = vec_zero;
m_sWheels[i].vVelocity = vec_zero;
m_sWheels[i].bSkidding = false;
m_sWheels[i].bSpinning = false;
m_sWheels[i].fTorque = 0;
m_sWheels[i].fLatTorque = 0;
m_sWheels[i].fLongTorque = 0;
}
for (i = 0; i < 4; i++) {
Vector p1, p3, p4;
Vector vTp, vTr, vTu;
vec3_t p2;
p3 = Corners[i];
p3.normalize();
vectoangles(p3, p2);
p1 = vec_zero;
p1[1] = angles[1] + p2[1] + 90;
p1.AngleVectorsLeft(&vTp, &vTr, &vTu);
m_sWheels[i].vVelocity = vTp * RAD2DEG(m_vAngularVelocity.y) * fabs(m_sWheels[i].fLongDist) * level.frametime;
G_LineWidth(5.0);
G_DebugLine(
origin + Corners[i][0] * r_i + Corners[i][1] * r_j,
origin + Corners[i][0] * r_i + Corners[i][1] * r_j + m_sWheels[i].vVelocity * 50,
0.7f,
0.5f,
1.0f,
1.0f
);
p1 = vec_zero;
p1[1] = angles[1] + RAD2DEG(m_sWheels[i].fYawOffset);
p1.AngleVectorsLeft(&vTp, &vTr, &vTu);
m_sWheels[i].vOrientation = vTp;
G_LineWidth(5.0);
G_DebugLine(
origin + Corners[i][0] * r_i + Corners[i][1] * r_j,
origin + Corners[i][0] * r_i + Corners[i][1] * r_j + m_sWheels[i].vOrientation * 50,
0.7f,
0.0f,
1.0f,
1.0f
);
}
Vector start, end;
Vector boxoffset;
Vector t_mins(-8, -8, -8);
Vector t_maxs(8, 8, 8);
trace_t trace;
start = origin + *vpn * (m_vCG[0] - localorigin[0]) + *vright * (m_vCG[1] - localorigin[1])
+ *vup * (m_vCG[2] - localorigin[2]);
end = start;
end[2] -= maxtracedist;
trace = G_Trace(start, t_mins, t_maxs, end, this, MASK_SOLID, qfalse, "Vehicle::PostThink Corners");
m_fInertia = m_fMass * 100;
m_fWheelFrontLoad = m_fMass * 9.81 * fabs(m_fWheelFrontDist / m_fWheelBase);
m_fWheelBackLoad = m_fMass * 9.81 * fabs(m_fWheelBackDist / m_fWheelBase);
longspeed = m_vAcceleration.length() * 0.02 * m_fMass / m_fWheelBase;
m_fWheelFrontLoad -= longspeed;
m_fWheelBackLoad += longspeed;
m_sWheels[0].fLoad = m_fWheelBackLoad / 2.0;
m_sWheels[1].fLoad = m_fWheelBackLoad / 2.0;
m_sWheels[2].fLoad = m_fWheelFrontLoad / 2.0;
m_sWheels[3].fLoad = m_fWheelFrontLoad / 2.0;
float fMassShifted = m_fTireRadius * M_PI;
m_fTireRotationalSpeed = dots[3] / (fMassShifted + fMassShifted);
m_iRPM = m_fTireRotationalSpeed * m_fGearRatio[m_iGear] * m_fDifferentialRatio * 10;
m_fMaxTraction =
TorqueLookup(m_iRPM) * m_fGearRatio[m_iGear] * m_fDifferentialRatio * m_fGearEfficiency / m_fTireRadius;
m_fTractionForce = m_fAccelerator * m_fMaxTraction;
if (m_bIsBraking && dots[3] > 0) {
m_fTractionForce = -fSign(dots[3]) * 1000 * dots[3];
}
for (i = 0; i < 4; i++) {
float maxgrip;
maxgrip = m_sWheels[i].fTraction * m_sWheels[i].fLoad * 9.81;
if (m_fTractionForce > maxgrip) {
m_fTractionForce = maxgrip * 0.6;
m_sWheels[i].bSpinning = true;
m_sWheels[i].bSkidding = true;
Com_Printf("Skidding!\n");
}
if (m_fTractionForce < -maxgrip) {
m_fTractionForce = -maxgrip * 0.6;
m_sWheels[i].bSkidding = true;
Com_Printf("Skidding!\n");
}
m_sWheels[i].fLongForce = this->m_sWheels[i].fLongForce + m_fTractionForce;
m_sWheels[i].vLongForce += m_sWheels[i].vOrientation * m_sWheels[i].fLongForce;
}
m_vResistance[0] =
-(velocity[0] * 0.02 * m_fRollingResistance + velocity[0] * 0.02 * m_fDrag * fabs(velocity[0] * 0.02));
m_vResistance[1] =
-(velocity[1] * 0.02 * m_fRollingResistance + velocity[1] * 0.02 * m_fDrag * fabs(velocity[1] * 0.02));
m_vResistance[2] =
-(velocity[2] * 0.02 * m_fRollingResistance + velocity[2] * 0.02 * m_fDrag * fabs(velocity[2] * 0.02));
m_fBrakingPerformance = -m_fRollingResistance - *vpn * Vector(0, 0, -1) * m_fMass;
if (dots[3] == 0) {
m_fBrakingPerformance = 0;
} else {
m_fBrakingPerformance = (dots[3] - (m_fTireRotationalSpeed * m_fTireRadius - m_fBrakingPerformance)) / dots[3];
m_fBrakingPerformance = (1.0 - m_fBrakingPerformance) * -(-m_fFrontBrakingForce - m_fBackBrakingForce);
}
if (r_velocity.length() * 0.02 > 0.01) {
m_fTangForce = 0;
m_vTangForce = vec_zero;
for (i = 0; i < 2; i++) {
Vector va, vr;
Vector vVel;
Vector v1, v2;
va = angles;
va.x = 0;
va.y += RAD2DEG(m_sWheels[i].fYawOffset);
va.z = 0;
va.AngleVectorsLeft(NULL, &vr, NULL);
vVel = m_sWheels[i].vVelocity + velocity;
// get the direction
v1 = vVel;
v1.normalize();
// get the angles
vectoangles(v1, v2);
m_sWheels[i].fSlipAngle = DEG2RAD(angledist(va.y - v2.y));
m_sWheels[i].fGripCoef = m_sWheels[i].fSlipAngle * 0.15;
m_sWheels[i].fGripCoef = Q_clamp_float(m_sWheels[i].fGripCoef, -1.2f, 1.2f);
m_sWheels[i].fLatForce += m_sWheels[i].fGripCoef * m_sWheels[i].fLoad * 9.81;
if (m_sWheels[i].fLoad * 2 * m_sWheels[i].fTraction < fabs(m_sWheels[i].fLatForce)) {
m_sWheels[i].fLatForce = m_sWheels[i].fLatForce / 9.81;
m_sWheels[i].bSkidding = true;
Com_Printf("Skidding %i!\n", i);
}
m_sWheels[i].vLatForce += vr * m_sWheels[i].fLatForce;
G_LineWidth(3.0);
G_DebugLine(
origin + Corners[i][0] * r_i + Corners[i][1] * r_j,
origin + Corners[i][0] * r_i + Corners[i][1] * r_j + m_sWheels[i].vLatForce * 50 * (1.0 / m_fMass),
0.7f,
0.5f,
0.2f,
1.0f
);
}
} else {
m_fTangForce = 0;
m_vTangForce = vec_zero;
}
m_vForce = vec_zero;
for (i = 0; i < 4; i++) {
m_sWheels[i].vForce = m_sWheels[i].vLatForce + m_sWheels[i].vLongForce;
m_vForce += m_sWheels[i].vForce;
}
m_vForce += m_vResistance;
G_LineWidth(5.0);
G_DebugLine(origin, origin + m_vTangForce * (1.0 / m_fMass) * 50, 1.0, 0.0, 1.0, 1.0);
m_vAcceleration = m_vForce * (1.0 / m_fMass) * 50;
m_fTorque = 0;
for (i = 0; i < 4; i++) {
m_sWheels[i].fTorque += m_sWheels[i].fLongTorque + m_sWheels[i].fLatTorque;
m_fTorque += m_sWheels[i].fTorque;
}
m_vAngularAcceleration[1] = angledist(RAD2DEG(m_fTorque));
m_vAngularVelocity += m_vAngularAcceleration * level.frametime;
m_vAngularVelocity *= 0.825f;
avelocity = m_vAngularVelocity;
if (m_bAutomatic) {
//
// set the gear
//
if (m_iRPM >= 2100 && m_iGear <= 2) {
m_iGear++;
}
if (m_iRPM <= 600 && m_iGear > 1) {
m_iGear--;
}
}
prev_moveimpulse = moveimpulse;
}
void VehicleWheelsX4::Killed(Event *ev)
{
deadflag = DEAD_DEAD;
}
float VehicleWheelsX4::TorqueLookup(int rpm)
{
if (rpm <= 2099)
return 20.0;
if (rpm > 3599)
return 0.0;
return (20 * (3600 - rpm)) * 0.001;
if (rpm <= 2099) {
return 20.0;
}
if (rpm > 3599) {
return 0.0;
}
return (20 * (3600 - rpm)) * 0.001;
}
void VehicleWheelsX4::Think()
{
vmove_t vm;
flags |= FL_POSTTHINK;
prev_velocity = velocity;
vmove_t vm;
flags |= FL_POSTTHINK;
angles -= m_vAnglesOffset;
origin -= m_vOriginOffset;
prev_velocity = velocity;
mins = m_vOldMins;
maxs = m_vOldMaxs;
angles -= m_vAnglesOffset;
origin -= m_vOriginOffset;
SetMoveInfo(&vm);
VmoveSingle(&vm);
GetMoveInfo(&vm);
mins = m_vOldMins;
maxs = m_vOldMaxs;
SetMoveInfo(&vm);
VmoveSingle(&vm);
GetMoveInfo(&vm);
}
void VehicleWheelsX4::Postthink()
{
// FIXME: STUB
}
float turn;
Vector i, j, k;
int index;
trace_t trace;
Vector normalsum;
Vector normalsum_Front;
int numnormals_Front;
Vector normalsum_Back;
int numnormals_Back;
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;
void VehicleWheelsX4::Killed(Event* ev)
{
deadflag = DEAD_DEAD;
primal_angles = angles;
if (drivable) {
if (m_bAutoPilot) {
AutoPilot();
} else {
moveimpulse *= 0.825f;
turnimpulse *= 0.825f;
}
currentspeed = moveimpulse;
turnangle = turnangle * 0.25f + turnimpulse;
turnangle = Q_clamp_float(turnangle, -maxturnrate, maxturnrate);
if (turnangle > maxturnrate) {
turnangle = maxturnrate;
} else if (turnangle < -maxturnrate) {
turnangle = -maxturnrate;
} else if (fabs(turnangle) < 2) {
turnangle = 0;
}
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;
angles[0] = 0;
angles[2] = 0;
temp[0] = angles[0];
temp[1] = angles[1];
temp[2] = angles[2];
temp.AngleVectorsLeft(&i, &j, &k);
j = vec_zero - j;
index = 0;
numnormals_Front = 0;
numnormals_Back = 0;
for (index = 0; index < 4; index++) {
Vector start, end;
Vector boxoffset;
Vector t_mins(-8, -8, -8);
Vector t_maxs(8, 8, 8);
boxoffset = Corners[index];
start = origin + i * boxoffset[0] + j * boxoffset[1] + k * boxoffset[2];
end = start;
end[2] -= maxtracedist;
trace = G_Trace(start, mins, maxs, end, this, MASK_SOLID, qfalse, "Vehicle::PostThink Corners");
if (trace.fraction != 1 && !trace.startsolid) {
if (index > 2) {
normalsum_Front += trace.plane.normal;
numnormals_Front++;
} else {
normalsum_Back += trace.plane.normal;
numnormals_Back++;
}
normalsum += trace.plane.normal;
}
}
if (angles[2] < 60 || angles[2] > 300) {
if (numnormals_Front > 1) {
m_vFrontNormal = normalsum_Front * (1.0 / numnormals_Front);
temp = m_vFrontNormal;
m_vFrontAngles[0] = -temp.CrossProduct(temp, j).toPitch();
// no yaw
m_vFrontAngles[1] = 0;
temp = m_vFrontNormal;
m_vFrontAngles[2] = temp.CrossProduct(temp, i).toPitch();
}
if (numnormals_Back > 1) {
m_vBackNormal = normalsum_Back * (1.0 / numnormals_Back);
temp = m_vBackNormal;
m_vBackAngles[0] = -temp.CrossProduct(temp, j).toPitch();
// no yaw
m_vBackAngles[1] = 0;
temp = m_vBackNormal;
m_vBackAngles[2] = temp.CrossProduct(temp, i).toPitch();
}
if (numnormals_Front + numnormals_Back > 1) {
m_vBaseNormal = (normalsum_Front + normalsum_Back) * (1.0 / numnormals_Front + numnormals_Back);
temp = m_vBaseNormal;
m_vBaseAngles[0] = -temp.CrossProduct(temp, j).toPitch();
// no yaw
m_vBaseAngles[1] = 0;
temp = m_vBaseNormal;
m_vBaseAngles[2] = temp.CrossProduct(temp, i).toPitch();
}
}
n_angles = m_vBaseAngles - angles;
n_angles[0] = angledist(n_angles[0]);
n_angles[1] = angledist(n_angles[1]);
n_angles[2] = angledist(n_angles[2]);
angles[0] += n_angles[0] * 4.5 * level.frametime;
angles[2] += n_angles[2] * 4.5 * level.frametime;
m_vPrevNormal = m_vBaseNormal;
if (currentspeed < 0 && velocity * i > 0) {
m_fFrontBrakingForce = 0.2f;
m_fBackBrakingForce = 0.1f;
} else {
m_fFrontBrakingForce = 0;
m_fBackBrakingForce = 0;
}
turn = turnangle * 0.005;
Vector _i, _j, _k;
Vector vNewVpn = angles;
vNewVpn.y += turnangle;
vNewVpn.AngleVectorsLeft(&_i, &_j, &_k);
UpdateVariables(&acceleration, &i, &j, &k, &_i, &_j, &_k);
m_vAngles = angles;
if (currentspeed < 0 && velocity * i > 0) {
currentspeed = 0;
}
normalsum = vec_zero;
for (index = 0; index < 4; index++) {
Vector start, end;
Vector boxoffset;
Vector t_mins(-8, -8, -8);
Vector t_maxs(8, 8, 8);
boxoffset = Corners[index];
start = origin + i * boxoffset[0] + j * boxoffset[1] + k * boxoffset[2] + Vector(0, 0, 10);
end = start;
end[2] -= maxtracedist;
trace = G_Trace(start, mins, maxs, end, this, MASK_SOLID, qfalse, "Vehicle::PostThink Corners");
if (trace.fraction != 1.0) {
float fCoef;
if (index > 2) {
fCoef = m_fWheelFrontLoad / (m_fWheelFrontDist / m_fWheelBase * m_fMass);
fCoef = Q_clamp_float(fCoef, 0, 1);
normalsum += _i * currentspeed * fCoef;
normalsum += i * currentspeed * (1.0 - fCoef);
} else {
fCoef = m_fWheelBackLoad / (m_fWheelBackDist / m_fWheelBase * m_fMass);
fCoef = Q_clamp_float(fCoef, 0, 1);
normalsum += i * currentspeed * fCoef;
normalsum += _i * currentspeed * (1.0 - fCoef);
}
}
}
AnglesToAxis(angles, orientation);
vmove_t vm;
SetMoveInfo(&vm);
m_sMoveGrid->SetMoveInfo(&vm);
m_sMoveGrid->SetOrientation(orientation);
if (m_sMoveGrid->CheckStuck()) {
angles = primal_angles;
AnglesToAxis(angles, orientation);
}
m_fForwardForce = acceleration * i * 0.1;
m_fBackForce += -m_vAnglesOffset[0] * m_fBouncyCoef;
m_fBackForce *= m_fSpringyCoef;
m_vAnglesOffset[0] += m_fForwardForce + m_fBackForce * 12.0 * level.frametime;
m_vAnglesOffset[0] = Q_clamp_float(m_vAnglesOffset[0], m_fYawMin, m_fYawMax);
m_fLeftForce += acceleration * j * 0.1;
m_fRightForce += -m_vAnglesOffset[2] * m_fBouncyCoef;
m_fRightForce *= m_fSpringyCoef;
m_vAnglesOffset[2] += (m_fLeftForce + m_fRightForce) * 12.0 * level.frametime;
m_vAnglesOffset[2] = Q_clamp_float(m_vAnglesOffset[2], m_fRollMin, m_fRollMax);
m_fDownForce = acceleration[2];
m_fUpForce += -m_vOriginOffset[2] * m_fBouncyCoef;
m_fUpForce *= m_fSpringyCoef;
m_vAnglesOffset[2] += (m_fDownForce + m_fUpForce) * 12.0 * level.frametime;
m_vAnglesOffset[2] = Q_clamp_float(m_vAnglesOffset[2], m_fZMin, m_fZMax);
if (groundentity && (angles[2] < 60 || angles[2] > 300)) {
velocity += m_vAcceleration * level.frametime;
} else {
if (angles[2] > 60) {
angles[2]; // FIXME: ??
}
velocity += m_vAcceleration * level.frametime;
}
angles += avelocity * level.frametime;
setAngles(angles);
prev_origin = origin;
}
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_idle";
} else {
sound_name = "snd_backward";
}
LoopSound(sound_name);
}
i = orientation[0];
j = orientation[1];
k = orientation[2];
last_origin = origin;
vTmp = (angles - primal_angles) * level.frametime;
if (vTmp.x > 180 || vTmp.x < -180) {
vTmp.x = 0;
}
if (vTmp.y > 180 || vTmp.y < -180) {
vTmp.y = 0;
}
if (vTmp.z > 180 || vTmp.z < -180) {
vTmp.z = 0;
}
if (vTmp.x > -1 || vTmp.x < 1) {
vTmp.x = 0;
}
if (vTmp.y > -1 || vTmp.y < 1) {
vTmp.y = 0;
}
if (vTmp.z > -1 || vTmp.z < 1) {
vTmp.z = 0;
}
avelocity = vTmp;
origin += m_vOriginOffset;
setOrigin(origin);
angles += m_vAnglesOffset;
setAngles(angles);
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);
}
}
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();
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);
}
}
}
+10937 -13867
View File
File diff suppressed because it is too large. Load diff
+1920 -1346
View File
File diff suppressed because it is too large. Load diff
+35 -45
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -24,52 +24,42 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitAim
(
GlobalFuncs_t *func
)
void Actor::InitAim(GlobalFuncs_t *func)
{
func->BeginState = &Actor::Begin_Aim;
func->ThinkState = &Actor::Think_Aim;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle;
func->ShowInfo = &Actor::ShowInfo_Aim;
func->IsState = &Actor::IsIdleState;
}
void Actor::Begin_Aim
(
void
)
{
m_csMood = STRING_ALERT;
m_csIdleMood = STRING_NERVOUS;
ClearPath();
}
void Actor::Think_Aim
(
void
)
{
if( !RequireThink() )
return;
UpdateEyeOrigin();
NoPoint();
m_pszDebugState = "";
Anim_Aim();
if( m_aimNode )
{
AimAtAimNode();
}
CheckForThinkStateTransition();
PostThink( true );
func->BeginState = &Actor::Begin_Aim;
func->ThinkState = &Actor::Think_Aim;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle;
func->ShowInfo = &Actor::ShowInfo_Aim;
func->IsState = &Actor::IsIdleState;
}
void Actor::ShowInfo_Aim
(
void
)
void Actor::Begin_Aim(void)
{
ShowInfo_AimNode();
m_csMood = STRING_ALERT;
m_csIdleMood = STRING_NERVOUS;
ClearPath();
}
void Actor::Think_Aim(void)
{
if (!RequireThink()) {
return;
}
UpdateEyeOrigin();
NoPoint();
m_pszDebugState = "";
Anim_Aim();
if (m_aimNode) {
AimAtAimNode();
}
CheckForThinkStateTransition();
PostThink(true);
}
void Actor::ShowInfo_Aim(void)
{
ShowInfo_AimNode();
}
+73 -110
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -24,143 +24,106 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitAlarm
(
GlobalFuncs_t *func
)
void Actor::InitAlarm(GlobalFuncs_t *func)
{
func->BeginState = &Actor::Begin_Alarm;
func->EndState = &Actor::End_Alarm;
func->ThinkState = &Actor::Think_Alarm;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack;
func->IsState = &Actor::IsAttackState;
func->BeginState = &Actor::Begin_Alarm;
func->EndState = &Actor::End_Alarm;
func->ThinkState = &Actor::Think_Alarm;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack;
func->IsState = &Actor::IsAttackState;
}
void Actor::Begin_Alarm
(
void
)
void Actor::Begin_Alarm(void)
{
DoForceActivate();
DoForceActivate();
m_csMood = STRING_ALERT;
m_csIdleMood = STRING_NERVOUS;
m_csMood = STRING_ALERT;
m_csIdleMood = STRING_NERVOUS;
if( m_AlarmNode )
{
SetPath( m_AlarmNode, "Actor::Begin_Alarm", 0 );
if (!m_AlarmNode) {
State_Alarm_StartThread();
return;
}
if( PathExists() )
{
TransitionState(601, 0);
}
else
{
TransitionState(600, 0);
parm.movefail = true;
}
}
else
{
SetLeashHome( origin );
TransitionState(600, 0);
m_AlarmThread.Execute( this );
}
SetPath(m_AlarmNode, "Actor::Begin_Alarm", 0);
if (PathExists()) {
TransitionState(ACTOR_STATE_ALARM_MOVE, 0);
} else {
TransitionState(ACTOR_STATE_ALARM_IDLE, 0);
parm.movefail = true;
}
}
void Actor::End_Alarm
(
void
)
void Actor::End_Alarm(void)
{
parm.movefail = true;
parm.movefail = true;
}
void Actor::State_Alarm_StartThread
(
void
)
void Actor::State_Alarm_StartThread(void)
{
if( m_AlarmNode )
SetLeashHome( m_AlarmNode->origin );
else
SetLeashHome( origin );
SetLeashHome(m_AlarmNode ? m_AlarmNode->origin : origin);
// Added in 2.30.
// Execute the pre-alarm thread
m_PreAlarmThread.Execute(this);
TransitionState(600, 0);
m_AlarmThread.Execute();
TransitionState(ACTOR_STATE_ALARM_IDLE, 0);
m_AlarmThread.Execute(this);
}
void Actor::State_Alarm_Move
(
void
)
void Actor::State_Alarm_Move(void)
{
if( PathExists() )
{
if( PathComplete() )
{
Anim_Aim();
AimAtTargetPos();
}
else
{
Anim_RunToAlarm( 2 );
FaceMotion();
}
}
else
{
TransitionState(600, 0);
parm.movefail = true;
if (!PathExists()) {
TransitionState(ACTOR_STATE_ALARM_IDLE, 0);
parm.movefail = true;
Anim_Aim();
AimAtTargetPos();
}
Anim_Aim();
AimAtTargetPos();
} else if (PathComplete()) {
Anim_Aim();
AimAtTargetPos();
State_Alarm_StartThread();
} else {
Anim_RunToAlarm(ANIM_MODE_PATH);
FaceMotion();
}
}
void Actor::State_Alarm_Idle
(
void
)
void Actor::State_Alarm_Idle(void)
{
AimAtTargetPos();
SetThink(THINKSTATE_ATTACK, THINK_TURRET);
Anim_Aim();
AimAtTargetPos();
SetThink(THINKSTATE_ATTACK, THINK_TURRET);
}
void Actor::Think_Alarm
(
void
)
void Actor::Think_Alarm(void)
{
if( !RequireThink() )
return;
if (!RequireThink()) {
return;
}
parm.movefail = false;
parm.movefail = false;
UpdateEyeOrigin();
NoPoint();
UpdateEyeOrigin();
NoPoint();
if( m_State == 600 )
{
m_pszDebugState = "idle";
State_Alarm_Idle();
}
else if( m_State == 601 )
{
m_pszDebugState = "move";
State_Alarm_Move();
}
else
{
Com_Printf( "Actor::Think_Alarm: invalid think state %i\n", m_State );
}
switch (m_State) {
case ACTOR_STATE_ALARM_IDLE:
m_pszDebugState = "idle";
State_Alarm_Idle();
break;
case ACTOR_STATE_ALARM_MOVE:
m_pszDebugState = "move";
State_Alarm_Move();
break;
default:
Com_Printf("Actor::Think_Alarm: invalid think state %i\n", m_State);
break;
}
}
void Actor::FinishedAnimation_Alarm
(
void
)
void Actor::FinishedAnimation_Alarm(void)
{
// not needed
return;
// not needed
return;
}
+48 -63
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -24,81 +24,66 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitAnim
(
GlobalFuncs_t *func
)
void Actor::InitAnim(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_Anim;
func->BeginState = &Actor::Begin_Anim;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle;
func->FinishedAnimation = &Actor::FinishedAnimation_Anim;
func->ShowInfo = &Actor::ShowInfo_Anim;
func->IsState = &Actor::IsIdleState;
func->ThinkState = &Actor::Think_Anim;
func->BeginState = &Actor::Begin_Anim;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle;
func->FinishedAnimation = &Actor::FinishedAnimation_Anim;
func->ShowInfo = &Actor::ShowInfo_Anim;
func->IsState = &Actor::IsIdleState;
}
void Actor::Begin_Anim
(
void
)
void Actor::Begin_Anim(void)
{
m_csMood = m_csIdleMood;
ClearPath();
StopTurning();
TransitionState(1000, 0);
m_csMood = m_csIdleMood;
ClearPath();
StopTurning();
TransitionState(ACTOR_STATE_ANIMATION_INITIAL, 0);
}
void Actor::Think_Anim
(
void
)
void Actor::Think_Anim(void)
{
if (RequireThink())
{
UpdateEyeOrigin();
IdlePoint();
IdleLook();
if (m_State == 1000)
{
m_bNextForceStart = true;
if (!RequireThink()) {
return;
}
m_bAnimScriptSet = false;
m_pszDebugState = "initial";
TransitionState(1001, 0);
}
else if (m_State == 1001)
{
m_bNextForceStart = false;
m_pszDebugState = "main";
}
m_eNextAnimMode = m_AnimMode;
m_csNextAnimString = m_csAnimScript;
UpdateEyeOrigin();
IdlePoint();
IdleLook();
CheckForThinkStateTransition();
IdleTurn();
PostThink(false);
}
if (m_State == ACTOR_STATE_ANIMATION_INITIAL) {
m_pszDebugState = "initial";
m_bAnimScriptSet = false;
StartAnimation(m_AnimMode, m_csAnimScript);
TransitionState(ACTOR_STATE_ANIMATION_MAIN, 0);
} else if (m_State == ACTOR_STATE_ANIMATION_MAIN) {
m_bNextForceStart = false;
m_pszDebugState = "main";
DesiredAnimation(m_AnimMode, m_csAnimScript);
}
CheckForThinkStateTransition();
IdleTurn();
PostThink(false);
}
void Actor::FinishedAnimation_Anim
(
void
)
void Actor::FinishedAnimation_Anim(void)
{
if (!m_bAnimScriptSet)
{
if (m_bNoIdleAfterAnim)
m_csAnimScript = STRING_ANIM_CONTINUE_LAST_ANIM_SCR;
else
SetThinkIdle(THINK_IDLE);
Unregister(STRING_ANIMDONE);
}
if (m_bAnimScriptSet) {
return;
}
if (m_bNoIdleAfterAnim) {
m_csAnimScript = STRING_ANIM_CONTINUE_LAST_ANIM_SCR;
} else {
SetThinkIdle(THINK_IDLE);
}
Unregister(STRING_ANIMDONE);
}
void Actor::ShowInfo_Anim
(
void
)
void Actor::ShowInfo_Anim(void)
{
Com_Printf("anim script: %s, anim mode %d\n", Director.GetString(m_csAnimScript).c_str(), m_AnimMode);
Com_Printf("anim script: %s, anim mode %d\n", Director.GetString(m_csAnimScript).c_str(), m_AnimMode);
}
+103 -191
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -23,289 +23,201 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// actor_animapi.cpp: Base actor animation script
#include "actor.h"
#include "scriptthread.h"
const_str SimpleActor::GetRunAnim
(
void
)
const_str SimpleActor::GetRunAnim(void)
{
if( m_csCurrentPosition != STRING_PRONE && ( m_csCurrentPosition < STRING_PRONE || m_csCurrentPosition > STRING_CROUCHRUN ) )
return STRING_ANIM_RUN_SCR;
else
return STRING_ANIM_CROUCH_RUN_SCR;
if (m_csCurrentPosition == STRING_PRONE) {
return STRING_ANIM_CROUCH_RUN_SCR;
}
if (m_csCurrentPosition >= STRING_PRONE && m_csCurrentPosition <= STRING_CROUCHRUN && m_csCurrentPosition >= STRING_CROUCH) {
return STRING_ANIM_CROUCH_RUN_SCR;
} else {
return STRING_ANIM_RUN_SCR;
}
}
const_str SimpleActor::GetWalkAnim
(
void
)
const_str SimpleActor::GetWalkAnim(void)
{
if( m_csCurrentPosition != STRING_PRONE && ( m_csCurrentPosition < STRING_PRONE || m_csCurrentPosition > STRING_CROUCHRUN ) )
return STRING_ANIM_WALK_SCR;
else
return STRING_ANIM_CROUCH_WALK_SCR;
if (m_csCurrentPosition == STRING_PRONE) {
return STRING_ANIM_CROUCH_WALK_SCR;
}
if (m_csCurrentPosition >= STRING_PRONE && m_csCurrentPosition <= STRING_CROUCHRUN && m_csCurrentPosition >= STRING_CROUCH) {
return STRING_ANIM_CROUCH_WALK_SCR;
} else {
return STRING_ANIM_WALK_SCR;
}
}
void SimpleActor::Anim_Attack
(
void
)
void SimpleActor::Anim_Attack(void)
{
DesiredAnimation(1, m_AttackHandler);
DesiredAnimation(ANIM_MODE_NORMAL, m_AttackHandler);
}
void SimpleActor::Anim_Sniper
(
void
)
void SimpleActor::Anim_Suppress(void)
{
DesiredAnimation(1, m_SniperHandler);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_SUPPRESS_SCR);
}
void SimpleActor::Anim_Aim
(
void
)
void SimpleActor::Anim_Sniper(void)
{
DesiredAnimation(1, STRING_ANIM_AIM_SCR);
DesiredAnimation(ANIM_MODE_NORMAL, m_SniperHandler);
}
void SimpleActor::Anim_Shoot
(
void
)
void SimpleActor::Anim_Aim(void)
{
DesiredAnimation(1, STRING_ANIM_SHOOT_SCR);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_AIM_SCR);
}
void SimpleActor::Anim_Idle
(
void
)
void SimpleActor::Anim_Shoot(void)
{
DesiredAnimation(1, STRING_ANIM_IDLE_SCR);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_SHOOT_SCR);
}
void SimpleActor::Anim_Crouch
(
void
)
void SimpleActor::Anim_Idle(void)
{
DesiredAnimation(1, STRING_ANIM_CROUCH_SCR);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_IDLE_SCR);
}
void SimpleActor::Anim_Prone
(
void
)
void SimpleActor::Anim_Crouch(void)
{
DesiredAnimation(1, STRING_ANIM_PRONE_SCR);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_CROUCH_SCR);
}
void SimpleActor::Anim_Stand
(
void
)
void SimpleActor::Anim_Prone(void)
{
DesiredAnimation(1, STRING_ANIM_STAND_SCR);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_PRONE_SCR);
}
void SimpleActor::Anim_Cower
(
void
)
void SimpleActor::Anim_Stand(void)
{
DesiredAnimation(1, STRING_ANIM_COWER_SCR);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_STAND_SCR);
}
void SimpleActor::Anim_Killed
(
void
)
void SimpleActor::Anim_Cower(void)
{
Com_Printf("m_eAnimMode Anim_Killed \n");
DesiredAnimation(1, m_DeathHandler);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_COWER_SCR);
}
void SimpleActor::Anim_StartPain
(
void
)
void SimpleActor::Anim_Killed(void)
{
Com_Printf("m_eAnimMode Anim_StartPain \n");
StartAnimation(1, m_PainHandler);
DesiredAnimation(ANIM_MODE_NORMAL, m_DeathHandler);
}
void SimpleActor::Anim_Pain
(
void
)
void SimpleActor::Anim_StartPain(void)
{
ContinueAnimation();
StartAnimation(ANIM_MODE_NORMAL, m_PainHandler);
}
void SimpleActor::Anim_CrouchRunTo
(
int eAnimMode
)
void SimpleActor::Anim_Pain(void)
{
DesiredAnimation(eAnimMode, STRING_ANIM_CROUCH_RUN_SCR);
ContinueAnimation();
}
void SimpleActor::Anim_CrouchWalkTo
(
int eAnimMode
)
void SimpleActor::Anim_CrouchRunTo(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_CROUCH_WALK_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_CROUCH_RUN_SCR);
}
void SimpleActor::Anim_StandRunTo
(
int eAnimMode
)
void SimpleActor::Anim_CrouchWalkTo(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_RUN_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_CROUCH_WALK_SCR);
}
void SimpleActor::Anim_StandWalkTo
(
int eAnimMode
)
void SimpleActor::Anim_StandRunTo(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_WALK_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_RUN_SCR);
}
void SimpleActor::Anim_RunTo
(
int eAnimMode
)
void SimpleActor::Anim_StandWalkTo(int eAnimMode)
{
DesiredAnimation(eAnimMode, GetRunAnim());
DesiredAnimation(eAnimMode, STRING_ANIM_WALK_SCR);
}
void SimpleActor::Anim_WalkTo
(
int eAnimMode
)
void SimpleActor::Anim_RunTo(int eAnimMode)
{
DesiredAnimation(eAnimMode, GetWalkAnim());
DesiredAnimation(eAnimMode, GetRunAnim());
}
void SimpleActor::Anim_RunAwayFiring
(
int eAnimMode
)
void SimpleActor::Anim_RunAwayFiring(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_RUNAWAYFIRING_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_RUNAWAYFIRING_SCR);
}
void SimpleActor::Anim_RunToShooting
(
int eAnimMode
)
void SimpleActor::Anim_RunToShooting(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_RUN_SHOOT_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_RUN_SHOOT_SCR);
}
void SimpleActor::Anim_RunToAlarm
(
int eAnimMode
)
void SimpleActor::Anim_RunToAlarm(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_ALARM_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_ALARM_SCR);
}
void SimpleActor::Anim_RunToCasual
(
int eAnimMode
)
void SimpleActor::Anim_RunToCasual(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_CASUAL_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_CASUAL_SCR);
}
void SimpleActor::Anim_RunToCover
(
int eAnimMode
)
void SimpleActor::Anim_RunToCover(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_COVER_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_COVER_SCR);
}
void SimpleActor::Anim_RunToDanger
(
int eAnimMode
)
void SimpleActor::Anim_RunToDanger(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_DANGER_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_DANGER_SCR);
}
void SimpleActor::Anim_RunToDive
(
int eAnimMode
)
void SimpleActor::Anim_RunToDive(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_DIVE_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_DIVE_SCR);
}
void SimpleActor::Anim_RunToFlee
(
int eAnimMode
)
void SimpleActor::Anim_RunToFlee(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_FLEE_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_FLEE_SCR);
}
void SimpleActor::Anim_RunToInOpen
(
int eAnimMode
)
void SimpleActor::Anim_RunToInOpen(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_INOPEN_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_INOPEN_SCR);
}
void SimpleActor::Anim_Emotion
(
eEmotionMode eEmotMode
)
void SimpleActor::Anim_WalkTo(int eAnimMode)
{
m_eEmotionMode = eEmotMode;
DesiredAnimation(eAnimMode, GetWalkAnim());
}
void SimpleActor::Anim_Say
(
const_str csSayAnimScript,
int iMinTimeSinceLastSay,
bool bCanInterrupt
)
void SimpleActor::Anim_Emotion(eEmotionMode eEmotMode)
{
if (!m_bSayAnimSet || bCanInterrupt)
{
if (level.inttime > m_iVoiceTime + iMinTimeSinceLastSay)
{
ScriptThreadLabel label;
label.TrySetScript(csSayAnimScript);
label.Execute(this);
}
}
m_eEmotionMode = eEmotMode;
}
void SimpleActor::Anim_FullBody
(
const_str csFullBodyAnim,
int eAnimMode
)
void SimpleActor::Anim_Say(const_str csSayAnimScript, int iMinTimeSinceLastSay, bool bCanInterrupt)
{
if( m_csAnimName == csFullBodyAnim )
{
DesiredAnimation(eAnimMode, STRING_ANIM_FULLBODY_SCR);
}
else
{
m_csAnimName = csFullBodyAnim;
StartAnimation(eAnimMode, STRING_ANIM_FULLBODY_SCR);
}
if (m_bSayAnimSet && !bCanInterrupt) {
return;
}
if (level.inttime <= iMinTimeSinceLastSay + m_iVoiceTime) {
return;
}
ScriptThreadLabel label;
label.TrySetScript(csSayAnimScript);
label.Create(this)->Execute();
}
void SimpleActor::Anim_FullBody(const_str csFullBodyAnim, int eAnimMode)
{
if (m_csAnimName == csFullBodyAnim) {
DesiredAnimation(eAnimMode, STRING_ANIM_FULLBODY_SCR);
} else {
m_csAnimName = csFullBodyAnim;
StartAnimation(eAnimMode, STRING_ANIM_FULLBODY_SCR);
}
}
+32 -41
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -24,56 +24,47 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitAnimCurious
(
GlobalFuncs_t *func
)
void Actor::InitAnimCurious(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_AnimCurious;
func->BeginState = &Actor::Begin_AnimCurious;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Curious;
func->FinishedAnimation = &Actor::FinishedAnimation_Anim;
func->ShowInfo = &Actor::ShowInfo_Anim;
func->IsState = &Actor::IsCuriousState;
func->ThinkState = &Actor::Think_AnimCurious;
func->BeginState = &Actor::Begin_AnimCurious;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Curious;
func->FinishedAnimation = &Actor::FinishedAnimation_Anim;
func->ShowInfo = &Actor::ShowInfo_Anim;
func->IsState = &Actor::IsCuriousState;
}
void Actor::Begin_AnimCurious
(
void
)
void Actor::Begin_AnimCurious(void)
{
DoForceActivate();
DoForceActivate();
m_csMood = STRING_CURIOUS;
StartAnimation(m_AnimMode, m_csAnimScript);
StopTurning();
m_iCuriousTime = level.inttime;
m_csMood = STRING_CURIOUS;
m_iCuriousTime = level.inttime;
StopTurning();
StartAnimation(m_AnimMode, m_csAnimScript);
}
void Actor::Think_AnimCurious
(
void
)
void Actor::Think_AnimCurious(void)
{
if( !RequireThink() )
return;
if (!RequireThink()) {
return;
}
UpdateEyeOrigin();
m_pszDebugState = "";
LookAtCuriosity();
TimeOutCurious();
DesiredAnimation(m_AnimMode, m_csAnimScript);
CheckForThinkStateTransition();
PostThink( false );
UpdateEyeOrigin();
m_pszDebugState = "";
LookAtCuriosity();
TimeOutCurious();
DesiredAnimation(m_AnimMode, m_csAnimScript);
CheckForThinkStateTransition();
PostThink(false);
}
void Actor::FinishedAnimation_AnimCurious
(
void
)
void Actor::FinishedAnimation_AnimCurious(void)
{
if( m_State == 1101 )
{
TransitionState(1100, 0);
}
if (m_State == ACTOR_STATE_CURIOUS_RUNNING) {
TransitionState(ACTOR_STATE_CURIOUS_BEGIN, 0);
}
}
+84
View File
@@ -0,0 +1,84 @@
/*
===========================================================================
Copyright (C) 2023 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
===========================================================================
*/
// actor_badplace.cpp
#include "actor.h"
void Actor::InitBadPlace(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_BadPlace;
func->BeginState = &Actor::Begin_BadPlace;
func->EndState = &Actor::End_BadPlace;
func->ResumeState = &Actor::Begin_BadPlace;
func->SuspendState = &Actor::End_BadPlace;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_BadPlace;
func->IsState = &Actor::IsBadPlaceState;
}
void Actor::Begin_BadPlace(void)
{
DoForceActivate();
m_csMood = STRING_ALERT;
m_csIdleMood = STRING_NERVOUS;
badplace_t& badplace = level.m_badPlaces.ObjectAt(m_iBadPlaceIndex);
FindPathAway(badplace.m_vOrigin, origin - badplace.m_vOrigin, badplace.m_fRadius + 64);
}
void Actor::End_BadPlace(void)
{
m_iBadPlaceIndex = 0;
}
void Actor::Think_BadPlace(void)
{
if (m_bEnableEnemy) {
UpdateEnemy(200);
}
m_pszDebugState = "";
NoPoint();
if (!PathExists() || PathComplete() || !m_iBadPlaceIndex) {
m_iBadPlaceIndex = 0;
if (!m_Enemy || (m_Enemy->flags & FL_NOTARGET)) {
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE);
} else {
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE);
}
}
if (m_Enemy) {
m_pszDebugState = "badplace_shoot";
FaceEnemyOrMotion(m_iStateTime);
Anim_RunAwayFiring(ANIM_MODE_PATH);
} else {
m_pszDebugState = "badplace_run";
FaceMotion();
Anim_RunToInOpen(ANIM_MODE_PATH);
}
PostThink(false);
}
+322 -295
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -25,366 +25,393 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
#include "scriptexception.h"
void Actor::InitBalconyIdle
(
GlobalFuncs_t *func
)
void Actor::InitBalconyIdle(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_Idle;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle;
func->Pain = &Actor::Pain_Balcony;
func->Killed = &Actor::Killed_Balcony;
func->IsState = &Actor::IsIdleState;
func->ThinkState = &Actor::Think_Idle;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle;
func->Pain = &Actor::Pain_Balcony;
func->Killed = &Actor::Killed_Balcony;
func->IsState = &Actor::IsIdleState;
}
void Actor::InitBalconyCurious
(
GlobalFuncs_t *func
)
void Actor::InitBalconyCurious(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_Curious;
func->BeginState = &Actor::Begin_Curious;
func->EndState = &Actor::End_Curious;
func->ResumeState = &Actor::Resume_Curious;
func->SuspendState = &Actor::Suspend_Curious;
func->FinishedAnimation = &Actor::FinishedAnimation_Curious;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Curious;
func->IsState = &Actor::IsCuriousState;
func->Pain = &Actor::Pain_Balcony;
func->Killed = &Actor::Killed_Balcony;
func->ThinkState = &Actor::Think_Curious;
func->BeginState = &Actor::Begin_Curious;
func->EndState = &Actor::End_Curious;
func->ResumeState = &Actor::Resume_Curious;
func->SuspendState = &Actor::Suspend_Curious;
func->FinishedAnimation = &Actor::FinishedAnimation_Curious;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Curious;
func->IsState = &Actor::IsCuriousState;
func->Pain = &Actor::Pain_Balcony;
func->Killed = &Actor::Killed_Balcony;
}
void Actor::InitBalconyAttack
(
GlobalFuncs_t *func
)
void Actor::InitBalconyAttack(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_BalconyAttack;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack;
func->BeginState = &Actor::Begin_BalconyAttack;
func->FinishedAnimation = &Actor::FinishedAnimation_BalconyAttack;
func->Pain = &Actor::Pain_Balcony;
func->Killed = &Actor::Killed_Balcony;
func->IsState = &Actor::IsAttackState;
func->PostShoot = &Actor::State_Balcony_PostShoot;
func->ThinkState = &Actor::Think_BalconyAttack;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack;
func->BeginState = &Actor::Begin_BalconyAttack;
func->FinishedAnimation = &Actor::FinishedAnimation_BalconyAttack;
func->Pain = &Actor::Pain_Balcony;
func->Killed = &Actor::Killed_Balcony;
func->IsState = &Actor::IsAttackState;
func->PostShoot = &Actor::State_Balcony_PostShoot;
}
void Actor::InitBalconyDisguise
(
GlobalFuncs_t *func
)
void Actor::InitBalconyDisguise(GlobalFuncs_t *func)
{
func->IsState = &Actor::IsDisguiseState;
func->IsState = &Actor::IsDisguiseState;
}
void Actor::InitBalconyGrenade
(
GlobalFuncs_t *func
)
void Actor::InitBalconyGrenade(GlobalFuncs_t *func)
{
func->IsState = &Actor::IsGrenadeState;
func->IsState = &Actor::IsGrenadeState;
}
void Actor::InitBalconyPain
(
GlobalFuncs_t *func
)
void Actor::InitBalconyPain(GlobalFuncs_t *func)
{
func->BeginState = &Actor::Begin_Pain;
func->ThinkState = &Actor::Think_Pain;
func->FinishedAnimation = &Actor::FinishedAnimation_Pain;
func->Pain = &Actor::Pain_Balcony;
func->Killed = &Actor::Killed_Balcony;
func->IsState = &Actor::IsPainState;
func->BeginState = &Actor::Begin_Pain;
func->ThinkState = &Actor::Think_Pain;
func->FinishedAnimation = &Actor::FinishedAnimation_Pain;
func->Pain = &Actor::Pain_Balcony;
func->Killed = &Actor::Killed_Balcony;
func->IsState = &Actor::IsPainState;
}
void Actor::InitBalconyKilled
(
GlobalFuncs_t *func
)
void Actor::InitBalconyKilled(GlobalFuncs_t *func)
{
func->BeginState = &Actor::Begin_BalconyKilled;
func->EndState = &Actor::End_BalconyKilled;
func->ThinkState = &Actor::Think_BalconyKilled;
func->FinishedAnimation = &Actor::FinishedAnimation_BalconyKilled;
func->IsState = &Actor::IsKilledState;
func->BeginState = &Actor::Begin_BalconyKilled;
func->EndState = &Actor::End_BalconyKilled;
func->ThinkState = &Actor::Think_BalconyKilled;
func->FinishedAnimation = &Actor::FinishedAnimation_BalconyKilled;
func->IsState = &Actor::IsKilledState;
}
void Actor::Pain_Balcony
(
Event *ev
)
void Actor::Pain_Balcony(Event *ev)
{
SetThink( THINKSTATE_PAIN, THINK_BALCONY_PAIN);
HandlePain( ev );
SetThink(THINKSTATE_PAIN, THINK_BALCONY_PAIN);
HandlePain(ev);
}
void Actor::Killed_Balcony
(
Event *ev,
bool bPlayDeathAnim
)
void Actor::Killed_Balcony(Event *ev, bool bPlayDeathAnim)
{
ClearStates();
SetThink( THINKSTATE_KILLED, THINK_BALCONY_KILLED);
HandleKilled( ev, true );
ClearStates();
SetThink(THINKSTATE_KILLED, THINK_BALCONY_KILLED);
HandleKilled(ev, true);
if( !bPlayDeathAnim )
ScriptError( "cannot do 'bedead' on balcony guys" );
if (!bPlayDeathAnim) {
ScriptError("cannot do 'bedead' on balcony guys");
}
}
void Actor::Begin_BalconyAttack
(
void
)
void Actor::Begin_BalconyAttack(void)
{
TransitionState(200, 0);
TransitionState(ACTOR_STATE_BALCONY_ATTACK_FIND_ENEMY, 0);
}
void Actor::State_Balcony_PostShoot
(
void
)
void Actor::State_Balcony_PostShoot(void)
{
if( m_Enemy )
{
TransitionState(201, 0);
}
if (m_Enemy) {
TransitionState(ACTOR_STATE_BALCONY_ATTACK_TARGET, 0);
}
}
void Actor::State_Balcony_FindEnemy
(
void
)
void Actor::State_Balcony_FindEnemy(void)
{
m_bHasDesiredLookAngles = false;
Anim_Aim();
m_bHasDesiredLookAngles = false;
Anim_Aim();
if( CanSeeEnemy( 200 ) )
{
TransitionState(201, 0);
}
if (CanSeeEnemy(200)) {
TransitionState(ACTOR_STATE_BALCONY_ATTACK_TARGET, 0);
}
}
void Actor::State_Balcony_Target
(
void
)
void Actor::State_Balcony_Target(void)
{
Anim_Aim();
AimAtTargetPos();
Anim_Aim();
AimAtTargetPos();
if( level.inttime > m_iStateTime + 1000 )
{
if( CanSeeEnemy( 0 ) && CanShootEnemy( 0 ) )
{
TransitionState(202, 0);
}
else
{
ClearPath();
TransitionState(200, 0);
}
}
if (level.inttime > m_iStateTime + 1000) {
if (CanSeeEnemy(0) && CanShootEnemy(0)) {
TransitionState(ACTOR_STATE_BALCONY_ATTACK_SHOOT, 0);
} else {
ClearPath();
TransitionState(ACTOR_STATE_BALCONY_ATTACK_FIND_ENEMY, 0);
}
}
}
void Actor::State_Balcony_Shoot
(
void
)
void Actor::State_Balcony_Shoot(void)
{
Anim_Shoot();
AimAtTargetPos();
Anim_Shoot();
AimAtTargetPos();
}
void Actor::Think_BalconyAttack
(
void
)
void Actor::Think_BalconyAttack(void)
{
if( !RequireThink() )
return;
if (!RequireThink()) {
return;
}
UpdateEyeOrigin();
UpdateEnemy( 500 );
UpdateEyeOrigin();
UpdateEnemy(500);
if( !m_Enemy )
{
SetThinkState( THINKSTATE_IDLE, THINKLEVEL_NORMAL);
IdleThink();
return;
}
if (!m_Enemy) {
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE);
IdleThink();
return;
}
NoPoint();
NoPoint();
if( m_State == 201 )
{
m_pszDebugState = "target";
State_Balcony_Target();
}
else if( m_State == 202 )
{
m_pszDebugState = "shoot";
State_Balcony_Shoot();
}
else if( m_State == 200 )
{
m_pszDebugState = "findenemy";
State_Balcony_FindEnemy();
}
else
{
Com_Printf( "Actor::Think_BalconyAttack: invalid think state %i\n", m_State );
assert( 0 );
}
switch (m_State) {
case ACTOR_STATE_BALCONY_ATTACK_TARGET:
m_pszDebugState = "target";
State_Balcony_Target();
break;
case ACTOR_STATE_BALCONY_ATTACK_SHOOT:
m_pszDebugState = "shoot";
State_Balcony_Shoot();
break;
case ACTOR_STATE_BALCONY_ATTACK_FIND_ENEMY:
m_pszDebugState = "findenemy";
State_Balcony_FindEnemy();
break;
default:
Com_Printf("Actor::Think_BalconyAttack: invalid think state %i\n", m_State);
assert(0);
break;
}
PostThink( true );
PostThink(true);
}
void Actor::FinishedAnimation_BalconyAttack
(
void
)
void Actor::FinishedAnimation_BalconyAttack(void)
{
if( m_State == 202 )
State_Balcony_PostShoot();
if (m_State == ACTOR_STATE_BALCONY_ATTACK_SHOOT) {
State_Balcony_PostShoot();
}
}
void Actor::Begin_BalconyKilled
(
void
)
bool Actor::CalcFallPath(void)
{
ClearPath();
ResetBoneControllers();
mmove_t mm;
int currentPos = 0;
int loop;
vec3_t pos[200];
float startDeltaTime;
float nextTime;
vec3_t vRelDelta;
vec3_t vAbsDelta;
float animTime;
int anim;
int i;
float startTime;
PostEvent( EV_Actor_DeathEmbalm, 0.05f );
SetMoveInfo(&mm);
if( CalcFallPath() )
TransitionState(800, 0);
else
TransitionState(806, 0);
mm.tracemask &= ~(CONTENTS_BODY | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP | CONTENTS_BBOX);
mm.desired_speed = 80;
VectorCopy2D(orientation[0], mm.desired_dir);
anim = gi.Anim_NumForName(edict->tiki, "death_balcony_intro");
animTime = gi.Anim_Time(edict->tiki, anim);
startTime = 0.65f;
for (;;) {
MmoveSingle(&mm);
VectorCopy(mm.origin, pos[currentPos]);
currentPos++;
if (currentPos >= ARRAY_LEN(pos)) {
return false;
}
if (mm.hit_obstacle) {
break;
}
if (!mm.groundPlane) {
return false;
}
startTime -= level.frametime;
if (startTime < 0) {
return false;
}
}
for (startDeltaTime = 0.65f; startDeltaTime < animTime; startDeltaTime = nextTime) {
nextTime = startDeltaTime + level.frametime;
if (nextTime >= animTime - 0.01f) {
nextTime = animTime;
}
gi.Anim_DeltaOverTime(edict->tiki, anim, startDeltaTime, nextTime, vRelDelta);
MatrixTransformVector(vRelDelta, orientation, vAbsDelta);
VectorAdd(mm.origin, vAbsDelta, mm.origin);
VectorCopy(mm.origin, pos[currentPos]);
currentPos++;
if (currentPos >= ARRAY_LEN(pos)) {
return false;
}
}
loop = currentPos;
mm.desired_speed = 0;
mm.groundPlane = NULL;
mm.walking = false;
VectorSet(mm.velocity, 0, 0, -171);
do {
MmoveSingle(&mm);
VectorCopy(mm.origin, pos[currentPos]);
currentPos++;
if (currentPos >= ARRAY_LEN(pos)) {
return false;
}
if (mm.hit_obstacle) {
return false;
}
} while (!mm.groundPlane);
if (origin[2] - pos[currentPos - 1][2] < m_fBalconyHeight) {
return false;
}
m_pFallPath = (FallPath*)gi.Malloc(sizeof(FallPath) + sizeof(FallPath::pos) * (currentPos - 1));
m_pFallPath->length = currentPos;
m_pFallPath->currentPos = 0;
m_pFallPath->startTime = startTime;
m_pFallPath->loop = loop;
for (i = 0; i < currentPos; i++) {
VectorCopy(pos[i], m_pFallPath->pos[i]);
}
return true;
}
void Actor::End_BalconyKilled
(
void
)
void Actor::Begin_BalconyKilled(void)
{
if( m_pFallPath )
{
gi.Free(m_pFallPath);
m_pFallPath = NULL;
}
ClearPath();
ResetBoneControllers();
PostEvent(EV_Actor_DeathEmbalm, 0.05f);
if (CalcFallPath()) {
TransitionState(ACTOR_STATE_BALCONY_KILLED_BEGIN, 0);
} else {
TransitionState(ACTOR_STATE_BALCONY_KILLED_NORMAL, 0);
}
}
void Actor::Think_BalconyKilled
(
void
)
void Actor::End_BalconyKilled(void)
{
int animnum;
Unregister( STRING_ANIMDONE );
if( m_State == 805 )
{
m_pszDebugState = "end";
}
else
{
NoPoint();
m_bHasDesiredLookAngles = false;
StopTurning();
switch( m_State )
{
case 800:
m_bNextForceStart = true;
m_eNextAnimMode = 7;
m_pszDebugState = "begin";
m_csNextAnimString = STRING_ANIM_NO_KILLED_SCR;
animnum = gi.Anim_NumForName(edict->tiki, "death_balcony_intro");
ChangeMotionAnim();
m_bMotionAnimSet = true;
m_iMotionSlot = GetMotionSlot(0);
m_weightType[m_iMotionSlot] = 1;
m_weightCrossBlend[m_iMotionSlot] = 0.0;
m_weightBase[m_iMotionSlot] = 1.0;
NewAnim( animnum, m_iMotionSlot );
SetTime( m_iMotionSlot, m_pFallPath->startTime );
UpdateNormalAnimSlot( m_iMotionSlot );
TransitionState(801, 0);
break;
case 801:
m_bNextForceStart = false;
m_pszDebugState = "intro";
m_eNextAnimMode = 7;
m_csNextAnimString = STRING_ANIM_NO_KILLED_SCR;
break;
case 802:
m_pszDebugState = "loop";
Anim_FullBody( STRING_DEATH_BALCONY_LOOP, 7 );
break;
case 803:
TransitionState(804, 0);
StopAllAnimating();
case 804:
m_pszDebugState = "outtro";
Anim_FullBody( STRING_DEATH_BALCONY_OUTTRO, 1 );
break;
case 806:
m_pszDebugState = "normal";
Anim_Killed();
break;
default:
Com_Printf( "Actor::Think_BalconyKilled: invalid think state %i\n", m_State );
assert( 0 );
}
PostThink( false );
if( m_State >= 800 )
{
if( m_State == 801 )
{
if( m_pFallPath->currentPos >= m_pFallPath->length )
{
TransitionState(803, 0);
}
else if (m_pFallPath->currentPos >= m_pFallPath->loop)
{
TransitionState(802, 0);
}
}
else if( m_State == 802 )
{
if (m_pFallPath->currentPos >= m_pFallPath->length)
{
TransitionState(803, 0);
}
}
}
}
if (m_pFallPath) {
gi.Free(m_pFallPath);
m_pFallPath = NULL;
}
}
void Actor::FinishedAnimation_BalconyKilled
(
void
)
void Actor::Think_BalconyKilled(void)
{
if( m_State == 804 || m_State == 806 )
{
BecomeCorpse();
TransitionState(805, 0);
}
else if( m_State == 801 )
{
TransitionState(802, 0);
StopAllAnimating();
}
int animnum;
Unregister(STRING_ANIMDONE);
if (m_State == ACTOR_STATE_BALCONY_KILLED_END) {
m_pszDebugState = "";
return;
}
NoPoint();
ForwardLook();
switch (m_State) {
case ACTOR_STATE_BALCONY_KILLED_BEGIN:
m_bNextForceStart = true;
m_eNextAnimMode = ANIM_MODE_FALLING_PATH;
m_pszDebugState = "begin";
m_csNextAnimString = STRING_ANIM_NO_KILLED_SCR;
animnum = gi.Anim_NumForName(edict->tiki, "death_balcony_intro");
ChangeMotionAnim();
m_bMotionAnimSet = true;
m_iMotionSlot = GetMotionSlot(0);
m_weightType[m_iMotionSlot] = ANIM_WEIGHT_MOTION;
m_weightCrossBlend[m_iMotionSlot] = 0.0;
m_weightBase[m_iMotionSlot] = 1.0;
NewAnim(animnum, m_iMotionSlot);
SetTime(m_iMotionSlot, m_pFallPath->startTime);
UpdateNormalAnimSlot(m_iMotionSlot);
TransitionState(ACTOR_STATE_BALCONY_KILLED_INTRO, 0);
break;
case ACTOR_STATE_BALCONY_KILLED_INTRO:
m_bNextForceStart = false;
m_pszDebugState = "intro";
m_eNextAnimMode = ANIM_MODE_FALLING_PATH;
m_csNextAnimString = STRING_ANIM_NO_KILLED_SCR;
break;
case ACTOR_STATE_BALCONY_KILLED_LOOP:
m_pszDebugState = "loop";
Anim_FullBody(STRING_DEATH_BALCONY_LOOP, 7);
break;
case ACTOR_STATE_BALCONY_KILLED_LOOP_END:
TransitionState(804, 0);
StopAllAnimating();
case ACTOR_STATE_BALCONY_KILLED_OUTTRO:
m_pszDebugState = "outtro";
Anim_FullBody(STRING_DEATH_BALCONY_OUTTRO, 1);
break;
case ACTOR_STATE_BALCONY_KILLED_NORMAL:
m_pszDebugState = "normal";
Anim_Killed();
break;
default:
Com_Printf("Actor::Think_BalconyKilled: invalid think state %i\n", m_State);
assert(0);
}
PostThink(false);
if (m_State >= ACTOR_STATE_BALCONY_KILLED_BEGIN) {
if (m_State == ACTOR_STATE_BALCONY_KILLED_INTRO) {
if (m_pFallPath->currentPos >= m_pFallPath->length) {
TransitionState(ACTOR_STATE_BALCONY_KILLED_LOOP_END, 0);
}
else if (m_pFallPath->currentPos >= m_pFallPath->loop) {
TransitionState(ACTOR_STATE_BALCONY_KILLED_LOOP, 0);
}
} else if (m_State == ACTOR_STATE_BALCONY_KILLED_LOOP) {
if (m_pFallPath->currentPos >= m_pFallPath->length) {
TransitionState(ACTOR_STATE_BALCONY_KILLED_LOOP_END, 0);
}
}
}
}
void Actor::FinishedAnimation_BalconyKilled(void)
{
switch (m_State) {
case ACTOR_STATE_BALCONY_KILLED_OUTTRO:
case ACTOR_STATE_BALCONY_KILLED_NORMAL:
BecomeCorpse();
TransitionState(ACTOR_STATE_BALCONY_KILLED_END, 0);
break;
case ACTOR_STATE_BALCONY_KILLED_INTRO:
TransitionState(ACTOR_STATE_BALCONY_KILLED_LOOP, 0);
StopAllAnimating();
break;
}
}
+621 -827
View File
File diff suppressed because it is too large. Load diff
Loaded 100 of 509 files, more files were not shown because too many files have changed in this diff. Show more