Compare commits

...
1315 Commits
Author SHA1 Message Date
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
smallmodel 20282ffa56 Fixed +speed having inverted up/down 2023-08-20 14:44:46 +02:00
smallmodel ff4987cc81 Added more screenshots 2023-08-20 14:29:50 +02:00
smallmodel 80a22ca2ed Fixed pm error 2023-08-20 14:13:34 +02:00
smallmodel 51ca0a06a7 Fixed death message color on mohaas/mohaab 2023-08-20 14:11:34 +02:00
smallmodel 010794418c Fixed GetSpectateFollowOrientation using forward rather than right 2023-08-20 14:02:55 +02:00
smallmodel 51b5b2571a Set lean info per game for Pmove 2023-08-20 14:02:33 +02:00
smallmodel 182a677337 Script: use AngleVector rather than AngleVectorsLeft for angles methods 2023-08-20 14:02:04 +02:00
smallmodel 17f6c25bc7 Fixed leaning values in mohaas/mohaab 2023-08-20 13:54:25 +02:00
smallmodel 31d19cb0f6 Fixed score entries on FFA gametype 2023-08-20 13:27:09 +02:00
smallmodel 6c65bba279 Fixed MSG_WritePackedAnimTime not writing the animation time sometimes 2023-08-20 02:33:08 +02:00
smallmodel 8ae15be0de Create AnimationEvent with predefined args 2023-08-20 02:32:10 +02:00
smallmodel 11fb5ee2af Fixed removebot never working 2023-08-20 02:23:49 +02:00
smallmodel b68992e55e Added numArgs parameter 2023-08-20 02:23:41 +02:00
smallmodel 007a7681eb G_ClientDisconnect should print differently on mohaas/mohaab 2023-08-20 02:23:29 +02:00
smallmodel 7d4cdac52c Use WaitTillAllowed for waitTillTimeout, waitTillAny and WaitTillAnyTimeout 2023-08-20 01:46:38 +02:00
smallmodel 916f38e1b2 "roundstart" misspell 2023-08-20 01:43:59 +02:00
smallmodel 39ae88a2ab Remove "roundstart" waittill after the round has started 2023-08-20 01:43:37 +02:00
DJs3000 24f82e8e36 Add new arch (#61)
* Update q_platform.h

add e2k arch

* Update TargetArch.cmake

add e2k arch
2023-08-19 21:59:26 +00:00
smallmodel 247d09a09d Fixed strip on windows 2023-08-19 23:29:23 +02:00
smallmodel 030b291af1 Fixed library locations 2023-08-19 23:29:19 +02:00
smallmodel 9d0a5faed3 Fixed errors 2023-08-19 23:23:36 +02:00
smallmodel 261b15851f Fixed string() when no SDL 2023-08-19 23:10:48 +02:00
smallmodel 2929bd82a5 Removed func_expr as it's not used 2023-08-19 23:08:00 +02:00
smallmodel 4939927975 Fixed length decrease with an higher value 2023-08-19 23:07:47 +02:00
smallmodel f9ef6733b9 Fixed errors on CMake 3.5 2023-08-19 23:07:12 +02:00
smallmodel de08fe7ca3 Fixed linux compile error 2023-08-19 21:21:41 +02:00
smallmodel 482536ff1c Added g_bot.h file 2023-08-19 21:21:32 +02:00
smallmodel 3089cc8bc3 Avoid assigning the token to an str 2023-08-19 21:17:52 +02:00
smallmodel a307450e17 Made sourceLine argument optional to avoid string allocation 2023-08-19 21:12:03 +02:00
smallmodel 50cfc7e5ad Added STRING_VIEWMODELANIM_DONE 2023-08-19 21:06:25 +02:00
smallmodel 5b82cc4f11 Made Event::ErrorInternal const
Fixed ProcessEvent() not handling exceptions
2023-08-19 21:00:04 +02:00
smallmodel a83a76da95 Create an event with the argument count 2023-08-19 20:49:39 +02:00
smallmodel 2e4759ab1f Using m_RunLabel instead of trying to get the game script everytime 2023-08-19 20:49:20 +02:00
smallmodel af056d7646 Create an event with pcmd->num_args 2023-08-19 20:49:03 +02:00
smallmodel 46e57f0a1f Added maxDataSize so the event can be preallocated 2023-08-19 20:48:46 +02:00
smallmodel fe5473bc85 Added Set and SetScript with const_str
Fixed try/catch
2023-08-19 20:48:03 +02:00
smallmodel 1a03288144 SetFastData: Move the ScriptVariable instead of copying it 2023-08-19 20:47:36 +02:00
smallmodel 0c2326480b Avoid reallocation if the assigned ScriptVariable is the same as the other ScriptVariable 2023-08-19 20:47:14 +02:00
smallmodel 24f3b3bc93 Added anyValue union field 2023-08-19 20:46:42 +02:00
smallmodel 459aa89ca2 Check if sourceLength is -1 instead 2023-08-19 20:46:24 +02:00
smallmodel ec8eaacc69 Fixed "vstr" in the nextmap argument 2023-08-19 19:49:28 +02:00
smallmodel 84f55f627e Updated README 2023-08-19 19:41:53 +02:00
smallmodel a30f78e834 Prevent sv_maxbots + sv_maxclients from reaching MAX_CLIENTS 2023-08-19 19:35:20 +02:00
smallmodel d22cda594f Fixed TeamHitScoreLimit() (should use m_teamwins) 2023-08-19 19:34:57 +02:00
smallmodel 8cfa909b73 Reset bots on CleanUp
Fixed issues with WaitTill registration
2023-08-19 18:22:01 +02:00
smallmodel 86a6dd020f Check for WaitTillAllowed instead 2023-08-19 18:21:32 +02:00
smallmodel 556133fa11 Use STRING_ROUNDSTART instead of "roundstart" 2023-08-19 18:20:26 +02:00
smallmodel 4001de1dde Implemented WaitTillAllowed for all classes 2023-08-19 18:10:38 +02:00
smallmodel 7a57a25c58 Reworked the bot system 2023-08-19 17:58:54 +02:00
smallmodel d95cdcc142 Moved bot functions to g_bot.cpp 2023-08-19 16:03:42 +02:00
smallmodel d2a967e577 Don't use the explicit class name to access Entry_allocator 2023-08-19 15:48:50 +02:00
smallmodel 84adaa07e0 Removed reverse_label_list (use label_list enumeration instead) 2023-08-19 15:48:29 +02:00
smallmodel 2efeb7e972 Don't call Unregister with "delete" and "remove" in the destructor as UnregisterAll() will already do it
Don't call CancelPendingEvents() if the event system hasn't started
2023-08-19 15:39:59 +02:00
smallmodel b9655e3f19 Fixed memory leaks: free all memory allocated by the game module 2023-08-19 15:24:37 +02:00
smallmodel dce004ef13 Don't FreeAll() when destructing the block allocator, because it could be executed before containers destruction 2023-08-19 15:24:12 +02:00
smallmodel b9f1530eec G_ShutdownGame: shutdown events and deallocate game data 2023-08-19 15:23:48 +02:00
smallmodel 9b15b27f28 Removed CRT check debug flag 2023-08-19 13:36:54 +02:00
smallmodel ff2e64a742 Fixed a tiny mistake present in all mohaa versions, with a possible overflow in client index in PF_centerprintf and PF_locationprintf 2023-08-19 13:36:12 +02:00
smallmodel 4e38b803fb Fixed G_Random/G_CRandom 2023-08-19 13:32:32 +02:00
smallmodel 9825e1e6f2 Formatted source files 2023-08-19 03:02:30 +02:00
smallmodel b278f2eafa Var integer access fix 2023-08-19 03:00:19 +02:00
smallmodel 25912079db Return NULL for ulist::GetPosition 2023-08-19 03:00:07 +02:00
smallmodel b1753df1ed Reworked con_set and con_arrayset so that they have their own Entry class 2023-08-19 02:56:51 +02:00
smallmodel 03143d1341 Added a compilation flag to debug memory 2023-08-19 02:19:09 +02:00
smallmodel 843b49d56b Allow operator new and operator delete to be called when debugging memory 2023-08-19 02:19:01 +02:00
smallmodel 00644e7605 Alloc() and Free() will call malloc directly when debugging memory 2023-08-19 02:18:41 +02:00
smallmodel 93814bd05b Fixed Skel_Alloc and Skel_Free macros when debugging memory 2023-08-19 02:18:11 +02:00
smallmodel 438ed2c0ea Added a way to debug CRT heap (currently only on Windows with MSVC) 2023-08-19 02:17:45 +02:00
smallmodel 0310475957 Don't make "addbot", "removebot" and "bot" public commands 2023-08-19 02:17:12 +02:00
smallmodel 435bfe1271 Initialize angular_delta to 0 2023-08-19 01:38:38 +02:00
smallmodel 7ca532f0e4 FL_ANIMATE is 0x100000 2023-08-19 01:38:25 +02:00
smallmodel 8c3997f13b Implemented Projectile::Think from mohaas/mohaab 2023-08-19 01:32:54 +02:00
smallmodel d8ae1ce6b9 Added NULL to the end of SmokeGrenade event responses 2023-08-19 01:32:33 +02:00
smallmodel 5cb1e5de84 Fixed Vector_DotProduct returning wrong values 2023-08-19 01:02:18 +02:00
smallmodel 7fd2aff17b Fixed entity trace with no valid trace 2023-08-19 00:58:06 +02:00
smallmodel b9f3ee867b Fixed switch label with "default" case 2023-08-19 00:57:29 +02:00
smallmodel f16b992a97 Fixed assignments with case-insensitive event names 2023-08-19 00:57:19 +02:00
smallmodel 9ba5710412 Fixed variable comparison operators with VARIABLE_CHAR 2023-08-19 00:57:02 +02:00
smallmodel 7e6854f96b Fixed EventPointsWithinDist taking the wrong argument number for the distance 2023-08-19 00:35:48 +02:00
smallmodel aa25ef6c68 Removed EV_Player_UseHeld as there is already EV_GetUseHeld 2023-08-19 00:35:32 +02:00
smallmodel 9db1076603 Fixed VM_StepSlideMove using wrong start/end for gi.trace 2023-08-19 00:35:10 +02:00
smallmodel 7b39218af5 Fixed MASK_VEHICLE 2023-08-19 00:34:56 +02:00
smallmodel ba5b2adf94 Fixed rcon command not working 2023-08-19 00:34:47 +02:00
smallmodel ded7d941ea Call SetAngles(ev) when setting the angles 2023-08-19 00:34:27 +02:00
smallmodel 09ed4e4a1d Fixed grammar priorities of the unuary and complement 2023-08-19 00:34:14 +02:00
smallmodel 9b3aaa0f87 Using string+5 rather than string+(4+1) 2023-08-19 00:33:55 +02:00
smallmodel a274325f43 Fixed wrong bounce sound 2023-08-18 15:30:18 +02:00
smallmodel b0da0b8321 Removed nomonsters
Removed some serverinfo cvars
2023-08-18 15:25:26 +02:00
smallmodel a241ea20fa Removed nomonsters 2023-08-18 15:25:17 +02:00
smallmodel f8d5a5ecd2 Fixed TeamWin with the axis team 2023-08-18 15:13:47 +02:00
smallmodel f20b47ebc0 Fixed newlines when printing the teamwin 2023-08-18 15:10:35 +02:00
smallmodel de10ab8df3 Fixed "is preparing for deployment" message location on mohaas/mohaab 2023-08-18 15:10:23 +02:00
smallmodel 47c7c5a5e3 Renamed centerprint to stringToPrint 2023-08-18 15:10:10 +02:00
smallmodel 80ada3225d Fixed centerprint not working as intended 2023-08-18 15:09:32 +02:00
smallmodel a1745829b2 Added product extension, as breakthrough clients rely on the extension word (like "Spearhead") to set g_servertype variable 2023-08-18 14:54:17 +02:00
smallmodel b2853465ed Capitalize first letter in PRODUCT_EXTENSION 2023-08-18 14:53:39 +02:00
smallmodel c89091b4cd Send gamever and serverType in SVC_Info 2023-08-18 14:53:26 +02:00
smallmodel e5beb0d9b9 Explicitly use GT_SINGLE_PLAYER 2023-08-18 14:53:12 +02:00
smallmodel 80ab513d76 Fixed size() returning 0 when the type is VARIABLE_NONE (must return -1) 2023-08-18 14:14:32 +02:00
smallmodel 854136d85b Fixed spelling mistake 2023-08-18 14:14:11 +02:00
smallmodel 25c417187b Removed flex/bison source files from build
Flex/Bison must be used to generate those files
2023-08-18 01:46:16 +02:00
smallmodel e3e9328ba3 Fixed small mistake when comparing with nextTime 2023-08-18 01:46:00 +02:00
smallmodel 3cc0c41b7b Added ScriptArrayHolder constructor 2023-08-18 01:42:10 +02:00
smallmodel 697013bbbf Fixed grammar priorities with const array 2023-08-18 01:18:18 +02:00
smallmodel 0080d4b9a8 Using ScriptError 2023-08-18 01:18:07 +02:00
smallmodel 8c391ef880 set cvar_modifiedFlags to the difference between flags 2023-08-18 01:09:24 +02:00
smallmodel e6d3ca32f4 In CheckEndMatch, don't put any flag in cvars 2023-08-18 01:09:09 +02:00
smallmodel fab78f933e Using SHORT2ANGLE for ucmd angles 2023-08-17 22:44:27 +02:00
smallmodel 5cd7d89e72 Fixed wrong sv flags being used 2023-08-17 22:38:25 +02:00
smallmodel 15e8146306 Don't hide the HUD when in turret or vehicle 2023-08-17 22:38:09 +02:00
smallmodel 250f1d090e Fixed SanitizeName 2023-08-17 22:37:35 +02:00
smallmodel 03c5864034 Fixed secondarycharge animation 2023-08-17 22:37:09 +02:00
smallmodel 07b7f10912 Fixed UnlimitedAmmo() behavior (use the behavior from mohaas/mohaab) 2023-08-17 21:31:22 +02:00
smallmodel 0e1837db31 Fixed smoke and rifle grenade max ammo 2023-08-17 21:30:57 +02:00
smallmodel 070fe17473 G_PushEntity: use cylinder 2023-08-17 21:30:34 +02:00
smallmodel ba607a0aad Ignore the owner of the passEnt entity 2023-08-17 21:30:21 +02:00
smallmodel 2b38a0f48e Fixed wrong opcode for method event 2023-08-17 21:29:55 +02:00
smallmodel a1fb3b283c Remove clipmask flags for physics_on if it has second parameter specified 2023-08-17 20:13:58 +02:00
smallmodel 12e85aba45 Also check if the groundentity has no movetype 2023-08-17 20:05:30 +02:00
smallmodel 44fe18fef1 Added MASK_SCRIPT_SLAVE 2023-08-17 20:04:58 +02:00
smallmodel 28de2543ec Removed listenerVars as it can cause issues 2023-08-17 19:51:53 +02:00
smallmodel 4435984b81 Renamed label to m_Thread 2023-08-17 19:29:03 +02:00
smallmodel 1435489a43 Fixed floats with negative values 2023-08-17 19:17:16 +02:00
smallmodel 3d20b3a232 Using MASK_SHOT_TRIG for BulletAttack, so it touches triggers 2023-08-17 19:17:02 +02:00
smallmodel 97543622bf Added MASK_SHOT_TRIG
Fixed MASK_SHOT values
2023-08-17 19:16:49 +02:00
smallmodel a9374f068b Added a check to avoid packed from being out of bounds in MSG_PackCoord() 2023-08-17 18:24:50 +02:00
smallmodel d80e9d80e7 Fixed getcvar returning wrong values sometimes 2023-08-17 18:24:30 +02:00
smallmodel 4f757445c4 Set vehicle to be in godmode if the player is in godmode 2023-08-17 18:24:20 +02:00
smallmodel 2749ab92b2 trigger_hurt inherits from Trigger and not TriggerUse 2023-08-17 18:23:53 +02:00
smallmodel 011bee9f33 Implemented MSG_HandleCGMBufferOverflow
Fixed CGM buffer error for non-connected clients
2023-08-17 18:23:24 +02:00
smallmodel 1b86e60548 Implemented all mohaas/mohaab features like animated farplanes, skybox speed/farplane, etc. 2023-08-17 17:39:54 +02:00
smallmodel 23e01fc1a7 Make sure to set m_data.containerValue when copying the value 2023-08-17 17:39:26 +02:00
smallmodel 2c9c80d7bc Don't set the targetname if world doesn't exist
Prevent world from being retargeted
2023-08-17 17:39:12 +02:00
smallmodel 5146b1f36b Made SetTargetName virtual functions 2023-08-17 17:37:43 +02:00
smallmodel bc81fe78b2 Check if the ent is inside the hit entity (this fixes trigger_hurt issues in mp_stadt_dm 2023-08-17 16:10:29 +02:00
smallmodel 4de1b7c73b When showing entities number, add maxs.z offset 2023-08-17 16:09:46 +02:00
smallmodel 3c8c4e9f97 Call SetSize() directly from setModel() 2023-08-17 16:09:29 +02:00
smallmodel c366c10530 Fixed level/parm/game vars being overwritten 2023-08-17 16:09:09 +02:00
smallmodel 6f5106803d Made firstLeafBrush and firstLeafSurface as intptr_t, as sometimes it's an offset to an unrelated memory location (in 64-bit, it could be a very far away memory location) 2023-08-17 16:08:40 +02:00
smallmodel 55a6b7956a Changed event priorities 2023-08-17 16:07:51 +02:00
smallmodel 911d1f1706 Fixed OP_STORE_FIELD and OP_STORE_FIELD_REF 2023-08-17 16:07:38 +02:00
smallmodel 56fba733f3 Always cast targetlist to const array value, so the iteration remains untouched 2023-08-17 03:18:41 +02:00
smallmodel a3c65ef7e4 Fixed containerValue allocation (mustn't allocate a new one) 2023-08-17 03:18:19 +02:00
smallmodel 73bc196592 Fixed cmd execution while iterating over a target list 2023-08-17 03:04:01 +02:00
smallmodel 8487099264 Fixed crash due to improper ScriptPointer usage 2023-08-17 03:03:40 +02:00
smallmodel bdcd0dbd56 Fixed EventEnd copying and adding pointer value 2023-08-17 03:03:26 +02:00
smallmodel 3c2600648c Fixed "immediateremove" wrong spelling 2023-08-17 03:03:08 +02:00
smallmodel f1abfeced6 Fixed grammar for if/while/for statements with a single line and a semi-colon 2023-08-17 02:59:54 +02:00
smallmodel 99bce5a11a Fixed identifiers like "break_formation" being treated as "break" and "_formation" separately 2023-08-17 01:08:37 +02:00
smallmodel ab5a3604bf Fixed grammar like "$(value).field"
Fixed newline in if statements
Fixed if/else being ambiguous
2023-08-17 01:05:55 +02:00
smallmodel fab7d8539c Fixed an extremely nasty bug with libmad: mad.h defines SIZEOF_INT to 4, libmad c files don't include this mad.h file, which mean libmad c files will use 8-bytes int, and snd_codec_mp3.c will use 4-bytes int 2023-08-16 20:53:20 +02:00
smallmodel 0347a5ca0b Renamed MAX_CHANNELS to MAX_SKELETOR_CHANNELS to avoid conflict with sound channels (MAX_CHANNELS) 2023-08-16 20:51:19 +02:00
smallmodel 42ad1cb41c Removed libmad from includes 2023-08-16 20:50:26 +02:00
smallmodel 64e3c18fb9 Removed assertion (not present in mohaa) 2023-08-16 19:22:10 +02:00
smallmodel 7e113359b3 Fixed crash with healrate 2023-08-16 19:14:05 +02:00
smallmodel 467802c466 Fixed crash when loading savegame 2023-08-16 19:13:52 +02:00
smallmodel ce1b3aaee9 Fixed ArchiveAliases
Archive PathSearch
2023-08-16 19:13:38 +02:00
smallmodel 1a53bdd584 Implemented PathSearch::ArchiveDynamic 2023-08-16 18:48:38 +02:00
smallmodel 5521e7654d Fixed number of script classes being replaced by the number of threads, causing archive read to go wrong 2023-08-16 18:29:36 +02:00
smallmodel 73716dd624 Fixed silly mistake in the container archive function 2023-08-16 18:29:06 +02:00
smallmodel 840d23dcac Fixed sizeof(index) 2023-08-16 18:28:50 +02:00
smallmodel 525a0c7c82 Renamed and moved soundSystem_t to snd_local_new.h 2023-08-16 18:14:06 +02:00
smallmodel 46c35057fb Made omohserver an interface 2023-08-16 18:13:47 +02:00
smallmodel 6d03b9763a Using S_LoadData 2023-08-16 18:13:30 +02:00
smallmodel 9eaecb0a2a Fixed a crash when loading a script, on non-MSVC binaries 2023-08-16 16:07:42 +02:00
smallmodel c274af839e Updated README 2023-08-16 13:27:29 +02:00
smallmodel f9232840e4 Fixed sprint not working 2023-08-16 13:17:01 +02:00
smallmodel 3ea40fda82 Fixed runspeed values 2023-08-16 13:16:56 +02:00
smallmodel c357c2614a Added DEBUG_DROP_ASSERT CMake definition 2023-08-16 13:16:04 +02:00
smallmodel efed6d0eac Fixed script developer printf 2023-08-16 02:43:22 +02:00
smallmodel 244220f031 Fixed spawnpoint issues due to trace mask 2023-08-16 02:37:57 +02:00
smallmodel 7ce87575bc Added MASK_PLAYERSTART 2023-08-16 02:37:25 +02:00
smallmodel 401cfeda65 Make sure to not call CanSeeEnemy() if the enemy is NULL 2023-08-16 02:31:30 +02:00
smallmodel a45a8c7742 Fixed sentient linking/unlinking 2023-08-16 02:31:12 +02:00
smallmodel c80b360918 Fixed "ignoreclock" event name 2023-08-16 02:22:39 +02:00
smallmodel 8514ef6ef8 Fixed Objective::SetText event parameter 2023-08-16 02:18:23 +02:00
smallmodel 9b1dc34ea1 Fixed score data for mohaas/mohaab 2023-08-16 02:08:00 +02:00
smallmodel f5490321e7 Set default explosion to "fx/fx_explosion.tik" 2023-08-16 02:04:28 +02:00
smallmodel 1f4393e3b2 Call DM_Team::AddKills when the player got killed 2023-08-16 01:32:53 +02:00
smallmodel 8aa6a16a27 Export g_TOWObjectiveMan 2023-08-16 01:32:07 +02:00
smallmodel 286f553a54 Fixed uninitialized variable 2023-08-16 01:06:51 +02:00
smallmodel f0ec50e37b Implemented UIRadar::Draw() 2023-08-16 00:45:40 +02:00
smallmodel c1ee0332e3 Fixed parameter of Draw_StretchPic2 2023-08-16 00:45:26 +02:00
smallmodel d2737f2b40 Fixed CL_UnpackNonPVSClient not unpacking the clientNum 2023-08-16 00:45:12 +02:00
smallmodel 0d501ec38a Fixed CG_SameTeam always returning true 2023-08-16 00:44:44 +02:00
smallmodel d39e6421fe Call CG_UpdateRadarClient() in CG_AddCEntity 2023-08-16 00:44:30 +02:00
smallmodel c2125947ab Removed R_RegisterSkin 2023-08-16 00:20:16 +02:00
smallmodel 953a33a6ff Call CG_InitRadar and restore saved cgame state 2023-08-16 00:20:10 +02:00
smallmodel 883e7884c4 Updated README 2023-08-16 00:19:30 +02:00
smallmodel 508903c3b1 Moved console_spam_filter to Com_Init 2023-08-16 00:08:35 +02:00
smallmodel 9116063d3f Added CL_RestoreSavedCgameState and CL_RestoreSavedCgameState 2023-08-16 00:08:24 +02:00
smallmodel e2a0d2d01e Fixed function parameter 2023-08-16 00:07:45 +02:00
smallmodel 5343949254 Implemented Draw_StretchPic2 2023-08-15 23:52:22 +02:00
smallmodel c17454b124 Renamed bValid to teamShader 2023-08-15 23:24:23 +02:00
smallmodel 4f8dc5dc2a Added radar variables 2023-08-15 22:47:11 +02:00
smallmodel 0fea47bb69 Added Draw_StretchPic2 2023-08-15 22:44:37 +02:00
smallmodel 47665fcd70 Added CL_ReadNonPVSClient and CL_UnpackNonPVSClient 2023-08-15 22:22:35 +02:00
smallmodel 968b073338 Implemented client-game radar code 2023-08-15 22:21:44 +02:00
smallmodel 03582bb59a Added radars and radarShaders in cg_t 2023-08-15 22:21:24 +02:00
smallmodel 149d3ce2fc Added CL_InitRadar 2023-08-15 22:21:01 +02:00
smallmodel fe5e151d89 Added YawToAxis 2023-08-15 22:20:33 +02:00
smallmodel 06a7341eda Moved radarUnpacked_t from server.h to q_shared.h 2023-08-15 22:20:25 +02:00
smallmodel 456ed42e14 Implemented the radar system for non-pvs clients 2023-08-15 19:29:12 +02:00
smallmodel 2337f93df8 Added console_spam_filter 2023-08-15 19:28:38 +02:00
smallmodel ad675b05ac Better wording 2023-08-15 18:09:22 +02:00
smallmodel 44f6de9524 Added riscv and riscv64 2023-08-15 16:45:13 +02:00
smallmodel e25605b898 Updated README 2023-08-15 16:02:02 +02:00
smallmodel 919d14e329 Fixed README 2023-08-15 15:24:56 +02:00
smallmodel 8fc64cd1b1 Using libsdl-org/setup-sdl Github Actions 2023-08-15 15:16:00 +02:00
smallmodel 028a7d6125 Setup SDL for CodeQL 2023-08-15 13:35:16 +02:00
smallmodel 60b9a6e2e0 renamed to playerstart.h 2023-08-15 13:16:36 +02:00
smallmodel 9ad515335a Added g_utils.h 2023-08-15 13:04:18 +02:00
pryon 7593ea53f9 Fix generated executable/lib names missing the -dbg postfix on Visual Studio (#55)
* Fix generated executable/lib names missing the -dbg postfix on Visual Studio

* Spaces to tabs
2023-08-15 10:57:36 +00:00
smallmodel 07374ba1ed Compilation errors fixes 2023-08-15 12:47:49 +02:00
smallmodel 2deba01a5f Updated the README 2023-08-15 01:42:49 +02:00
smallmodel 3daee90b5b Moved functions from game.cpp/game.h to where they should be (g_main, g_utils) 2023-08-15 01:41:35 +02:00
smallmodel c4ba60afbd Added TRANS_BSP to G_BeginIntermission 2023-08-15 01:38:55 +02:00
smallmodel 81e9ce10cd Fixed warning spam if the default value is different 2023-08-15 01:27:54 +02:00
smallmodel c4738966fe Using g_utils.cpp from fakk 2023-08-15 01:27:35 +02:00
smallmodel 0eedc4e2f8 Fixed compilation warnings 2023-08-15 01:26:58 +02:00
smallmodel 14f9368575 Implemented all setters/getters
7 remaining important methods to implement
2023-08-15 00:24:07 +02:00
smallmodel 394546dee7 Added means of death strings 2023-08-14 23:37:14 +02:00
smallmodel e86e5c0d80 Renamed MOD_MINE to MOD_LANDMINE
Added MOD_AAGUN
2023-08-14 23:37:05 +02:00
smallmodel e0b5a62c4f Allow obj maps to be loaded in any game types 2023-08-14 20:44:46 +02:00
smallmodel 7fb42cf655 Fixed message printing on mohaas/mohaab 2023-08-14 20:44:28 +02:00
smallmodel 819f6bcf71 Using DM_Manager::CheckEndMatch() algorithm from mohaab 2.40 2023-08-14 20:35:23 +02:00
smallmodel ad47f8855b Implemented TOW Entities 2023-08-14 19:54:50 +02:00
smallmodel a50102ef52 Changed CONTROLLER_BOTH to CONTROLLER_DRAW
Added GetObjectiveIndex()
2023-08-14 19:53:35 +02:00
smallmodel 0b2a0634f5 Moved eController to Entities.h 2023-08-14 19:21:17 +02:00
smallmodel 8ea32fee31 Added Entities with all classes, methods and events (unimplemented) 2023-08-14 19:20:53 +02:00
smallmodel f0571385d5 Export events for AISpawnPoint 2023-08-14 19:00:16 +02:00
smallmodel 83318af532 Export EV_Weapon_SetProjectile 2023-08-14 17:43:28 +02:00
smallmodel 860c9b33ef Made AddObjective and SetCurrentObjective static 2023-08-14 15:02:25 +02:00
smallmodel ecbd6ae282 Renamed WITH_CLIENT to BUILD_NO_CLIENT 2023-08-14 13:31:42 +02:00
smallmodel 3ec799d150 Compiled parser 2023-08-14 03:15:48 +02:00
smallmodel 72715c1a85 Fixed CL_Disconnect being passed with arguments 2023-08-14 03:15:42 +02:00
smallmodel 16d262f6ee Fixed floats being interpreted as integers sometimes 2023-08-14 03:09:38 +02:00
smallmodel 49850940d6 Using objective flags enumeration 2023-08-14 02:39:32 +02:00
smallmodel e634fb5022 Using objective flags enum 2023-08-14 02:34:06 +02:00
smallmodel c0726f0634 Added objective status and flags enum 2023-08-14 02:33:59 +02:00
smallmodel 91dc3e5884 Fixed configstring index because of denormalization 2023-08-14 02:24:48 +02:00
smallmodel ba2c3ed5fd Fixed lean on protocols before 2.0 2023-08-14 02:12:30 +02:00
smallmodel 161f7e3313 Fixed wrong current objective
Added support for objective location per team
2023-08-14 02:11:26 +02:00
smallmodel f2f7afadef Don't resend the game state if the serverId is the same as the restarted server Id 2023-08-14 01:57:02 +02:00
smallmodel 0898bffb43 Fixed getboundkey1/getboundkey2 crashing when the key is null 2023-08-14 01:56:43 +02:00
smallmodel 99dc7bf7f2 Fixed CL_MapLoading always flushing 2023-08-14 01:56:25 +02:00
smallmodel 64acea9018 Call SV_CheckSaveGame in Com_Frame 2023-08-14 01:27:25 +02:00
smallmodel 8e05347ba0 Moved CL_FinishedIntro and SV_CheckSaveGame to qcommon.h 2023-08-14 01:27:13 +02:00
smallmodel 07e90d37ee Fixed bad angle 2023-08-14 00:22:25 +02:00
smallmodel 71bd04e5b2 Fixed weapon bullet trace
Fixed projectile being always removed in single-player mode
2023-08-14 00:22:05 +02:00
smallmodel 95510279ed Fixed trigger having no contents when a model is set 2023-08-14 00:21:44 +02:00
smallmodel f1502833b2 Fixed primary/secondary attacks not working 2023-08-13 23:21:11 +02:00
smallmodel e6448697d3 Let cg cleanup temp models
Fixed server restart
2023-08-13 23:20:51 +02:00
smallmodel 5a96d6dd96 Added snd_local_new for new local functions 2023-08-13 23:20:15 +02:00
smallmodel 8d6b3d0bd8 Added cg_archive and cg_radar (unimplemented) 2023-08-13 23:20:00 +02:00
smallmodel 1fd0cd097f Fixed the objective index 2023-08-13 22:08:10 +02:00
smallmodel 421126db38 Optimized ScriptVM::EventGoto 2023-08-13 22:07:33 +02:00
smallmodel 7258a2e972 Fixed CG_DrawObjectives stack overflow 2023-08-13 22:07:19 +02:00
smallmodel df66ab0339 Fixed EmitField bug
Clear the previous opcode when a new label is emitted
2023-08-13 21:55:22 +02:00
smallmodel c49d0c7afa Fixed iprintln(bold) not working properly with multiple arguments 2023-08-13 20:22:39 +02:00
smallmodel 421b3d6375 Fixed crouch on mohaa and mohaas/mohaab 2023-08-13 20:20:36 +02:00
smallmodel 11ef489225 Added basic implementation of sound callback
Implemented S_IsSoundPlaying
2023-08-13 20:20:17 +02:00
smallmodel e1da6797c5 Using S_FLAG_DO_CALLBACK 2023-08-13 20:19:51 +02:00
smallmodel 430c7d1a57 Fixed ScriptCheck always failing regardless of the g_scriptcheck value 2023-08-13 20:19:40 +02:00
smallmodel d3794c0dd9 Fixed bad event when using '$' key 2023-08-13 20:19:26 +02:00
smallmodel eef1368083 using g_gametype variable directly instead of using Cvar_VariableValue 2023-08-13 20:19:03 +02:00
smallmodel 6dfefa04f5 Fixed SV_AllowSaveGame always returning true 2023-08-13 20:18:46 +02:00
smallmodel 8b17d81545 Fixed variables improperly used on stack under some circumstances 2023-08-13 20:17:59 +02:00
smallmodel ec58ca0f13 Added S_FLAG_DO_CALLBACK 2023-08-13 20:17:33 +02:00
smallmodel 3fd87f90a2 Fixed objectives not showing properly 2023-08-13 20:17:23 +02:00
smallmodel 9f268b0f6a Using Director.Pause() instead 2023-08-13 17:59:59 +02:00
smallmodel f857116f75 Fixed script crashes 2023-08-13 17:59:49 +02:00
smallmodel ea78d96bc3 Fixed disabled view model animation
Fixed pmove viewheight
2023-08-13 17:59:41 +02:00
smallmodel 0be9e69833 Added protocol for pmove_t for PM_CheckDuck 2023-08-13 17:59:21 +02:00
smallmodel 8171641e3a Fixed "dmmessage" not being logged (it's a bug in all versions of mohaas/mohaab) 2023-08-13 16:13:08 +02:00
smallmodel ee6014a30f Fixed Player::CondCheckMovementSpeed returning wrong value (expects it to return true if below the weapon's max fire movement) 2023-08-13 16:11:59 +02:00
smallmodel 16c22a3ee5 Added "idle0", "idle1", "idle2" view model animations
Fixed respawn time after death
Fixed Sentient not switching to the primary weapon when spawning
Fixed weapon select not showing
Initialize all Player variables
Remove projectiles when switching teams
Set viewmodelanim to disabled when reaching the weapon's max fire movement
2023-08-13 16:11:25 +02:00
smallmodel 571e48fecf Call Weapon::Charge in Sentient::ChargeWeapon
Don't charge again if sentient is already charging weapon
2023-08-13 16:07:46 +02:00
smallmodel 973d7c5f34 Implemented Weapon::Charge
Cancel overcooked events in Weapon::ReleaseFire
2023-08-13 16:07:11 +02:00
smallmodel a1c5ca288a Renamed m_iOwnerTeam to m_iTeam
Implemented SetFuse, ArcToTarget, BecomeBomb, and DieInwater
Fixed projectile life being wrong when charging
2023-08-13 16:06:49 +02:00
smallmodel e330d00565 Added dmmessage monitoring 2023-08-13 14:19:14 +02:00
smallmodel 6feeb21e21 Fixed uninitialized angular delta variable 2023-08-13 14:19:05 +02:00
smallmodel bb5cf24d5f Fixed "isabandoned" mispelling 2023-08-13 03:34:28 +02:00
smallmodel 0dda70cca1 Fixed event parameters being wrong 2023-08-13 03:34:19 +02:00
smallmodel 5e83e03e33 Major grammar/lexer/compiler fixes 2023-08-13 03:34:09 +02:00
smallmodel d2b3f6c12b Added stub yacc / lex 2023-08-12 20:00:12 +02:00
smallmodel f5af33b181 Major script engine fixes 2023-08-12 19:59:40 +02:00
smallmodel 0da1ed8764 Fixed canseenoents having the wrong name 2023-08-12 19:59:17 +02:00
smallmodel 8aa6f29c4c Added all script functions from mohaas/mohaab 2023-08-12 14:02:43 +02:00
smallmodel 1b7a4442d3 Added no_fade parameter to G_BeginIntermission 2023-08-12 14:00:14 +02:00
smallmodel a163df993c Added MOD_MINE_EXPLOSION 2023-08-12 13:59:56 +02:00
smallmodel 2787007b9d Cleaned up class 2023-08-12 03:10:10 +02:00
smallmodel cea2c178b5 Fixed header 2023-08-12 03:05:06 +02:00
smallmodel 77a9cd5a9a Call Director.Unpause() to execute running scripts 2023-08-12 03:04:31 +02:00
smallmodel ec3259271e Removed THREAD_CONTEXT_SWITCH 2023-08-12 03:03:34 +02:00
smallmodel ae02abba3b Cleaned up ScriptMaster 2023-08-12 03:03:26 +02:00
smallmodel bf960f6f32 Cleaned up ScriptThread 2023-08-12 02:40:30 +02:00
smallmodel 66a1087099 Moved ScriptMaster methods here 2023-08-12 02:40:03 +02:00
smallmodel c1a431f857 Added all mohaas/mohaab features (SetWeaponIdleState, PingForMines, ForceLandmineMeasure, ForceDropWeapon and ForceDropHealth)
Set m_fDamageMultipliers depending on whether or not g_realismmode is set
Minor fixes in the sentient constructor
2023-08-12 00:49:07 +02:00
smallmodel dac5279a59 Archive is_paused and angular_delta 2023-08-12 00:47:39 +02:00
smallmodel a175ea27d7 Cleanup weapon class
Added ShowInfo, SetItemSlot and SetIdleState
2023-08-12 00:10:47 +02:00
smallmodel ddac42e21e Call Weapon::GetZoom() instead 2023-08-11 23:54:43 +02:00
smallmodel 34535ad415 Moved AnimationEvent from Animate to a separate source file 2023-08-11 21:48:25 +02:00
smallmodel c0597e441c Moved AnimationEvent from Animate to a separate source file
Implemented whole animate class from mohaas/mohaab
2023-08-11 21:30:47 +02:00
smallmodel 04b66684dd Added a function to get an animation's angular delta over time 2023-08-11 21:11:16 +02:00
smallmodel 244a2e66f9 Added TIKI_Anim_DeltaOverTime 2023-08-11 21:10:29 +02:00
smallmodel 55b737e730 Set global channel from local to -1 2023-08-11 21:10:14 +02:00
smallmodel 059dacf2a7 Added GetAngularDeltaOverTime() to return the animation's angular delta over time 2023-08-11 21:09:47 +02:00
smallmodel 41f7003747 Fixed SetPlayerView, SetupView, PlayerAngles
UpdateStats changes:
- Added support for allied and axis objective locations
- Vehicle health
- Healrate
- Secondary ammo
2023-08-11 03:13:36 +02:00
smallmodel 64ba900511 Use GetRemoteOwner() properly 2023-08-11 03:09:33 +02:00
smallmodel e371b4bbd3 Replaced unused stats 2023-08-11 03:09:19 +02:00
smallmodel aa44150525 Added some mohaas/mohaab methods (stubs) 2023-08-11 03:09:10 +02:00
smallmodel 3572be718a Use usercmd_s instead of usercmd_t 2023-08-11 03:08:56 +02:00
smallmodel a56d74814b Try to play pain animation in DamageFeedback 2023-08-11 01:58:22 +02:00
smallmodel 8d41b58635 Using hitloc enum instead of macros 2023-08-11 01:34:21 +02:00
smallmodel e80f326ee6 Proper implementation of DamageFeedback 2023-08-11 01:21:50 +02:00
smallmodel c5bd64912a Added MOVETYPE_PORTABLE_TURRET 2023-08-11 01:21:29 +02:00
smallmodel 8a808b616e Apply fall damage differently on mohaas/mohaab
Ignore world effects if no-cliping
2023-08-11 00:54:15 +02:00
smallmodel 91bb2f2e0b Enable god mode for the vehicle the player is in 2023-08-11 00:48:09 +02:00
smallmodel aa4e6a0651 Removed SpawnDamageEffect
DoUse: Call RemoveFromVehiclesAndTurretsInternal() directly
Use G_PMDrawTrace if sv_drawtrace is above 1
Set allow lean while moving
Disable movement prediction if player is glued onto something
Multiply the speed by the weapon movement speed
Added Teamkill warn and kick
Added support for invulnerability, sprint and team spawn
Added support for heal rate
Added talk icon
2023-08-11 00:43:40 +02:00
smallmodel 8e9ff2b289 Added G_PMDrawTrace 2023-08-11 00:13:29 +02:00
smallmodel d53ab8540e Fixed Unix compilation warnings/errors 2023-08-10 23:06:03 +02:00
smallmodel 7b133e5b2f Fixed const param 2023-08-10 23:04:47 +02:00
smallmodel 2b72959935 Call Obituary if there is also an inflictor
Clear pain animation when killed
Increment team kills count when a teammate was killed
2023-08-10 21:38:37 +02:00
smallmodel 82d0b62631 Implemented EndAnim_Pain 2023-08-10 21:37:53 +02:00
smallmodel 7205e27c8c Using death messages implementation from mohaas/mohaab 2023-08-10 21:26:28 +02:00
smallmodel c8d1248d86 Added MOD_MINE means of death 2023-08-10 21:26:07 +02:00
smallmodel 845e4556ef Added g_obituarylocation (openmohaa-specific parameter) 2023-08-10 21:23:10 +02:00
smallmodel a92bfbde40 Fixed variable names 2023-08-10 21:22:50 +02:00
smallmodel 999b6409b3 Fixed InitEdict, InitHealth
InitModel: IT/SC skins support, and voiceType fix
Respawn: Set invulnerability
2023-08-10 20:14:34 +02:00
smallmodel 0ae0be4047 Added more ammo to initialize
Added stopwatch parameter for mohaas/mohaab
Initialize mine variables in InitState
2023-08-10 19:36:14 +02:00
smallmodel fc7029c271 Added stopwatch type 2023-08-10 19:32:21 +02:00
smallmodel 307ee117bd Initialize invulnerability
Set the player view accordingly when choosing a spawn point
Don't set m_fDamageMultipliers in realism mode
Score isn't processed in single-player anymore
2023-08-10 19:14:51 +02:00
smallmodel 087d28eb9a Added GT_TOW and GT_LIBERATION for SelectSpawnPoint() 2023-08-10 19:11:39 +02:00
smallmodel 1deea345bc Renamed team to teamnum 2023-08-10 18:49:57 +02:00
smallmodel e0fa706f6c Implemented EquipWeapons, Stats, TickTeamSpawn, UserSelectWeapon, AllowTeamRespawn and EventKillAxis 2023-08-10 18:48:46 +02:00
smallmodel cf794d2b95 Added DF_OLD_SNIPER and DF_DISALLOW_KAR98_MORTAR 2023-08-10 18:42:13 +02:00
smallmodel 391e82bb92 Formatted source files 2023-08-10 18:41:49 +02:00
smallmodel 83a44b3158 Implemented RemoveFromVehiclesAndTurretsInternal 2023-08-10 17:01:55 +02:00
smallmodel 8cd0e6c5bf Added FixedTurret, PortableTurret and CarryableTurret (unimplemented) 2023-08-10 17:01:43 +02:00
smallmodel 619ab00035 Added player-specific methods 2023-08-10 17:01:19 +02:00
smallmodel 4ded5c3380 Added EV_Weapon_SetAmmoClipSize declaration 2023-08-10 17:00:51 +02:00
smallmodel 85fa2185f8 Added DetachRemoteOwner 2023-08-10 17:00:38 +02:00
smallmodel ab39259bbe Moved vote options stuff to bg_voteoptions.h 2023-08-10 17:00:17 +02:00
smallmodel 9bf2065d18 Implemented battle language methods and GetTeamDialogPrefix/GetNationalityPrefix 2023-08-10 14:18:40 +02:00
smallmodel ceb121d588 Added MASK_BATTLELANGUAGE 2023-08-10 14:14:50 +02:00
smallmodel e7dbc25ca0 Made entity parameter a constant instance 2023-08-10 14:14:39 +02:00
smallmodel 7386784765 Renamed clientPersistant_t to client_persistant_t
Named client_peristant_t fields correctly
2023-08-10 13:34:04 +02:00
smallmodel 9062952539 Implemented GiveNewWeaponsCheat, GetSpectateFollowOrientation, EnsurePlayerHasAllowedWeapons, SetPlayerSpectateRandom, RetrieveVoteOptions and GetNationalityPrefix
mohaas/mohaab fixes
2023-08-10 13:31:35 +02:00
smallmodel 9f0a479c3b added playerAnimSlot_t enum 2023-08-10 13:30:32 +02:00
smallmodel 517b9296dc Using sv_walkspeedmult instead of sv_walkspeed 2023-08-10 12:09:07 +02:00
smallmodel 3ca09613e1 Fixed string constants 2023-08-10 12:08:53 +02:00
smallmodel ba931cbedf Added all mohaas/mohaab cvars 2023-08-10 12:04:45 +02:00
smallmodel 090b354b23 Added all mohaas/mohaab events, methods (partially implemented) 2023-08-10 03:56:13 +02:00
smallmodel dd30bfde15 Set protocol from com_protocol 2023-08-10 03:55:50 +02:00
smallmodel 477735cb3d Cleanup player class
Added all mohaas/mohaab methods (partially implemented)
2023-08-10 03:46:28 +02:00
smallmodel 38599f2181 Added more cvars 2023-08-10 03:45:38 +02:00
smallmodel bd794fb286 Cleanup Level 2023-08-10 03:10:51 +02:00
smallmodel ce34b78113 Added CL_LV_ConvertString
Only CL messages are localized now (see comment)
2023-08-10 02:42:57 +02:00
smallmodel b8a87dc6ea Using dm_manager.h instead of dm_team.h 2023-08-10 02:31:48 +02:00
smallmodel 7bdc30936c Added G_SetClientConfigString 2023-08-10 02:31:09 +02:00
smallmodel 9e635a7207 Rearranged DM_Manager
Moved dm_team.cpp code to dm_manager.cpp
2023-08-10 02:31:01 +02:00
smallmodel e5626378ef Added m_bIgnoreClock 2023-08-10 01:42:24 +02:00
smallmodel 73921c116d Made FireWeapon and EventUseWeaponClass virtual methods 2023-08-10 01:42:06 +02:00
smallmodel d4b98ef9dd Added sprint, invulnerable and team spawn variables 2023-08-10 01:41:03 +02:00
smallmodel 40318f052a Set GAMEVERSION to OPENMOHAA 2023-08-09 23:49:47 +02:00
smallmodel a130f45c62 Added GetViewAngles, SetFov and GetFov
Removed SwingAngles
2023-08-09 23:49:38 +02:00
smallmodel e687d97660 Fixed compile errors 2023-08-09 23:48:37 +02:00
smallmodel e4a0406fc2 Removed Player::PlayerDone
Using Player::DeadBody with the event parameter
2023-08-09 23:11:39 +02:00
smallmodel ef18c389be Cleanup entity class
Added new parameter for CanSee
Added Entity::SafeSolid and Entity::Sink
2023-08-09 23:09:09 +02:00
smallmodel 85099801ab Call Player::DeadBody() with the event function instead 2023-08-09 22:09:04 +02:00
smallmodel 3472657f92 Added MASK_SAFESOLID 2023-08-09 22:08:37 +02:00
smallmodel c197513ff3 Fixed mismatched endif 2023-08-09 21:00:56 +02:00
smallmodel 9dca77c2cf Fixed setModel() virtual function 2023-08-09 20:58:36 +02:00
smallmodel f08a7fa21e Removed Player::useWeapon 2023-08-09 20:58:07 +02:00
smallmodel 2df56c810d Set Entity's entnum directly 2023-08-09 20:57:53 +02:00
smallmodel 8c6098f730 Removed SimpleEntity::SetTargetViewAngles() 2023-08-09 20:57:45 +02:00
smallmodel 1462d4f8d9 Removed StunAttack (useless) 2023-08-09 20:57:26 +02:00
smallmodel 5bd49304d7 Cleaned up SimpleEntity 2023-08-09 20:57:17 +02:00
smallmodel f52d648d6f Added InteractObject and ThrowObject 2023-08-09 20:49:43 +02:00
smallmodel 987af7eb81 Cleaned up Sentient class
Moved combat stuff to sentient_combat.cpp
Formatted source files
2023-08-09 19:45:39 +02:00
smallmodel f313b6a058 Formatted item source files 2023-08-09 16:54:38 +02:00
smallmodel 99b989bb63 Added DynItem
Removed unused features
Added remaining mohaa functions
2023-08-09 16:37:08 +02:00
smallmodel 7ebbba6ce5 Made Class::warning and Class::error const methods 2023-08-09 01:53:45 +02:00
smallmodel c2a6db15a6 Reordered and removed useless functions 2023-08-09 01:32:23 +02:00
smallmodel aa58bcf948 Using const_str for trigger 2023-08-09 00:54:06 +02:00
smallmodel fa5b030522 Cleaned up trigger source file 2023-08-09 00:42:09 +02:00
smallmodel 3e44049abf Removed unused trigger features 2023-08-08 23:51:46 +02:00
smallmodel 94c501e71b Formatted document 2023-08-08 23:46:45 +02:00
smallmodel 484b2a8900 Implemented TriggerAll 2023-08-08 23:35:01 +02:00
smallmodel e8ff4fb9a7 Fixed wrong TRIGGER_DAMAGE value 2023-08-08 23:06:28 +02:00
smallmodel b89e10fd5c Reordered conditions 2023-08-08 22:40:23 +02:00
smallmodel d86ea606eb Formatted source files 2023-08-04 00:21:19 +02:00
smallmodel 2135be12b8 Implemented all unimplemented conditions 2023-08-04 00:20:28 +02:00
smallmodel ae5d51f2e9 Reworked the player class
Added player_animation.cpp and player_conditionals.cpp
Renamed conditions functions and moved them to player_conditionals.cpp
2023-08-04 00:04:29 +02:00
smallmodel 6eaf25ff80 Using const for CurrentAnim() and CurrentTime() 2023-08-04 00:03:55 +02:00
smallmodel 17c371c15e Added Entity::BlocksAIMovement 2023-08-03 21:44:16 +02:00
smallmodel 13febc125e Renamed weapon to dm_primary 2023-08-03 21:44:05 +02:00
smallmodel b0f26acc18 Fixed max movement time 2023-08-03 21:43:50 +02:00
smallmodel 8ffa5f15e6 Implemented BulletAttack from mohaas/mohaab
Added more explosion effects
2023-08-03 21:43:38 +02:00
smallmodel f6bcc1ab86 Increased MAX_WEAPONS to 64 2023-08-03 20:14:33 +02:00
smallmodel a4d6442526 Call BulletAttack_Stat instead of putting everything in BulletAttack
Fixed some BulletAttack bugs
2023-08-02 23:09:18 +02:00
smallmodel b7fac3a5b0 Added BulletAttack_Stat 2023-08-02 21:58:47 +02:00
smallmodel 64ebf3ed05 Implemented all landmine related functions 2023-08-02 21:50:11 +02:00
smallmodel 9933612607 Added ScriptVariableList::VariableExists 2023-08-02 21:49:03 +02:00
smallmodel 22ff072b54 Made findKeyValue and findKeyEntry const 2023-08-02 21:48:54 +02:00
smallmodel 73b0a84ad0 Added MASK_LANDMINE_PLACE 2023-08-02 21:05:49 +02:00
smallmodel 7b03f953bf Added Level::RoundStarted 2023-08-02 21:02:19 +02:00
smallmodel 367d6ff6fc Added and implemented TriggerNoDamage, TriggerEntity and TriggerLandmine 2023-08-02 21:00:16 +02:00
smallmodel ca61fde54b Added ScriptThreadLabel::Execute() with safeptr listener, and optionally another listener 2023-08-02 20:59:54 +02:00
smallmodel f739588c73 Cleaned up Player class from all unused action anim
Added all mohaas/mohaab fields
Added m_sDmPrimary to get the player's primary weapon
2023-08-02 20:59:19 +02:00
smallmodel ce02d782c4 Removed Player::FindEnemyInFOV and Player::FindEnemyInFOVFromTagWithOffset (unused) 2023-08-02 20:59:15 +02:00
smallmodel a498b11e20 Added MASK_LANDMINE 2023-08-02 20:56:19 +02:00
smallmodel ffa5a91cd2 Added Landmine and Defuse fire types for Shoot
Added GetUseCrosshair()
2023-08-02 19:53:14 +02:00
smallmodel ae680ffd5d Added Landmine functions from mohaab
Added more parameters for BulletAttack and FakeBulletAttack from mohaas/mohaab
2023-08-02 19:52:04 +02:00
smallmodel 4c17d12fc6 Added new fire types
Added GetFireAnim()
Using m_sTagBarrel rather than an hardcoded tag name
2023-08-01 21:18:35 +02:00
smallmodel 0259f1a251 Reworked Weapon::ReadyToFire and Weapon::PickupWeapon with mohaas/mohaab features 2023-08-01 20:36:52 +02:00
smallmodel 04708aeb67 Fixed CurrentFrame() not found error 2023-08-01 19:59:32 +02:00
smallmodel a47eb1653e Override animation functions from entity 2023-08-01 19:59:19 +02:00
smallmodel 10fda39430 Added animation functions 2023-08-01 19:59:05 +02:00
smallmodel b2be03cce3 Initialize all weapon vars, including mohaas/mohaab variables 2023-08-01 19:31:25 +02:00
smallmodel 84ecf838d4 Optimized G_Command_ProcessFile a little bit 2023-08-01 19:31:08 +02:00
smallmodel c115796137 Optimized GetValue() so it moves value instead of copying it 2023-08-01 19:30:28 +02:00
smallmodel 7e054c8beb Implemented all mohaas/mohaab events 2023-07-31 23:41:53 +02:00
smallmodel e8df36998e Added mohaas/mohaab variables 2023-07-31 23:41:45 +02:00
smallmodel 0cc558f757 Added overcooked field 2023-07-31 23:41:01 +02:00
smallmodel 5c9bc074f4 Removed fov variable (was useless) 2023-07-31 23:40:39 +02:00
smallmodel d89175ebc8 Added "always" parameter for alias registration 2023-07-30 23:02:13 +02:00
smallmodel 727eb71995 Added all mohaas/mohaab entity events 2023-07-30 21:21:00 +02:00
smallmodel 3d48c00902 Added g_realismmode 2023-07-30 20:21:18 +02:00
smallmodel 963318264c Added SV_HitEntity from mohaab 2023-07-30 20:21:08 +02:00
smallmodel d9123799d6 Added CONTENTS_CLAYPIDGEON 2023-07-30 19:48:43 +02:00
smallmodel 6562bcb164 Added mohaas/mohaab weapon events (unimplemented) 2023-07-30 19:41:11 +02:00
smallmodel 4fa8af3b30 Smoke system implementation from mohaas/mohaab 2023-07-30 16:09:54 +02:00
smallmodel 3f4be4f8ef Added MASK_SMOKE_SPRITE 2023-07-30 16:09:36 +02:00
smallmodel 09c7badf4f Added g_debugsmoke cvar 2023-07-30 16:09:22 +02:00
smallmodel 7b9b371cf6 Added RotatePointAroundAxis 2023-07-30 15:42:59 +02:00
smallmodel 25e44e7a45 Added stub source files from mohaas/mohaab 2023-07-30 14:28:58 +02:00
smallmodel 51374729d3 Clear g_iInThinks each frame
Display the memory usage if the g_showmem cvar is set
2023-07-30 14:27:15 +02:00
smallmodel 5a19f7f574 Added LightClass 2023-07-30 14:26:52 +02:00
smallmodel 40ac8a1557 Added watchstring from mohaab 2023-07-30 14:09:22 +02:00
smallmodel ca42a3e08e Implemented View3D::DrawLetterbox, View3D::DrawFades, View3D::DrawSoundOverlay, View3D::ClearCenterPrint, View3D::UpdateCenterPrint, View3D::UpdateLocationPrint, View3D::LetterboxActive, View3D::InitSubtitle 2023-07-30 11:47:20 +02:00
smallmodel 3a04357b71 Fixed enum values and enum names 2023-07-30 11:40:50 +02:00
smallmodel 078223c1b6 Centerprint when screenshotting 2023-07-30 11:40:33 +02:00
smallmodel 3fe7cbf725 Fixed vertex colors spam 2023-07-30 11:38:59 +02:00
smallmodel d6059e42ba Export sound_overlay for View3D 2023-07-30 11:38:41 +02:00
smallmodel 02c1fbe4fc Export LV_ConvertString to ref 2023-07-30 11:38:31 +02:00
smallmodel 6f8fee47f2 Using const char* for LV_ConvertString 2023-07-30 11:38:18 +02:00
smallmodel 6c247b300e Updated README 2023-07-30 11:37:41 +02:00
smallmodel 3627760748 Removed parent entity not found message in CG_GetOrigin 2023-07-30 01:10:26 +02:00
smallmodel f3affb3d4c Implemented DontLocalize and FadeSequence from mohaas 2023-07-30 00:56:54 +02:00
smallmodel a86ed01ba3 Fixed shader tiling being bad with virtual scaling on mohaas/mohaab 2023-07-29 23:18:31 +02:00
smallmodel d40755eb7c Added MouseAwayCommand. (this fixes main menu with items staying hovered in mohaas/mohaab) 2023-07-29 23:18:22 +02:00
smallmodel ce7599cb02 Set column padding 2023-07-29 22:31:16 +02:00
smallmodel 68bf89c522 Fixed entity axis index crash (was using i instead of j) 2023-07-29 21:26:28 +02:00
smallmodel 0c5b57ee05 Fixed MASK_SURF_TYPE not matching all surfaces 2023-07-29 21:25:39 +02:00
smallmodel 69a10da52c Version number increment 2023-07-29 19:57:16 +02:00
smallmodel ab534623c4 Fixed crash due to trace.allSolid not being initialized 2023-07-29 19:56:54 +02:00
smallmodel ae4ea14b35 Fixed crash related to backEnd.currentEntity being null 2023-07-29 19:56:36 +02:00
smallmodel ea3c48af02 Fixed double-click not working 2023-07-29 19:41:29 +02:00
smallmodel 9df0c023ed Fixed the server list
Fully implemented the server list
Added support for mohaas/mohaab server list
2023-07-29 19:31:16 +02:00
smallmodel a5259ebc05 Using MASTER_SERVER_HOST macro 2023-07-29 19:30:39 +02:00
smallmodel add59ad12a Implemented UIListBase::TrySelectItem and UIListBase::KeyEvent 2023-07-29 19:30:22 +02:00
smallmodel 53eecb4d4c Fixed compare function being wrong 2023-07-29 19:29:52 +02:00
smallmodel 77fb47451c Added game_version cvar so it shows on the UI on mohaas/mohaab 2023-07-29 19:29:38 +02:00
smallmodel 80ae39c2a7 Fixed mouse wheel not working 2023-07-29 19:29:13 +02:00
smallmodel 118ce0d550 Implemented all unimplemented functions/methods 2023-07-29 00:47:05 +02:00
smallmodel dfd9afceba Added Cvar_VariableFloatValue 2023-07-28 22:34:29 +02:00
smallmodel 6f7eb93645 Export UI_SetReturnMenuToCurrent() 2023-07-28 22:34:22 +02:00
smallmodel a5268cbd24 Implemented FAKKServerListItem class
Implemented UIFAKKServerList::RefreshServerList, UIFAKKServerList::RefreshLANServerList, UIFAKKServerList::NewServerList, UIFAKKServerList::ServerCompareFunction and UIFAKKServerList::SortByColumn
2023-07-28 21:51:37 +02:00
smallmodel c732ed66b2 Set default alpha to 1.0 2023-07-28 21:45:19 +02:00
smallmodel 10981f706f Added functions to get game key, game name and game ID 2023-07-28 21:45:07 +02:00
smallmodel d61218d7e2 Fixed const parameters 2023-07-28 21:44:43 +02:00
smallmodel 615032bc25 Fixed cross-platform errors 2023-07-27 23:13:57 +02:00
smallmodel ea70be07a2 Added FAKKServerListItem class (with unimplemented methods) 2023-07-27 23:02:39 +02:00
smallmodel 1884d3d23c Using a const char* for ServerListAuxUpdate 2023-07-27 23:00:27 +02:00
smallmodel 3f036cca5e Added GameSpy server list 2023-07-27 22:43:51 +02:00
smallmodel 3e02fe340b Implemented UIFAKKServerList's constructor 2023-07-27 22:43:41 +02:00
smallmodel 50d62f1505 Exported EV_UIListBase_ItemDoubleClicked and EV_UIListBase_ItemSelected 2023-07-27 22:43:24 +02:00
smallmodel 60511ace99 Set maximum parallel job to 1 when publishing a new release 2023-07-25 23:59:20 +02:00
smallmodel aef54d05ae Incremented version number 2023-07-25 23:27:07 +02:00
smallmodel 15633626fe Implemented R_GatherLightSources, R_CheckAddLightToList and R_InsertLightIntoList 2023-07-25 22:01:28 +02:00
smallmodel d43b60c818 Don't lean while moving if alwaysAllowLean is not set 2023-07-25 20:59:52 +02:00
smallmodel 7941524aad Set alwaysAllowLean depending on the game version and the dmflags 2023-07-25 20:59:34 +02:00
smallmodel 3aa4a6157c Added PMF_NO_LEAN pmflags
Added alwaysAllowLean pmove_t field from mohta
2023-07-25 20:59:04 +02:00
smallmodel fc9cf41557 Implemented R_GetLightingGridValue (better lighting) 2023-07-25 20:03:07 +02:00
smallmodel 527131e513 R_LoadLightGrid: Set light grid size depending on the map version 2023-07-25 20:02:56 +02:00
smallmodel b79163f998 Fixed sqrt non-constant expression 2023-07-25 18:46:05 +02:00
smallmodel 121aaa164a Implemented sphere light 2023-07-24 20:18:14 +02:00
smallmodel 2522559a04 Implemented R_SphereInLeafs 2023-07-24 20:14:23 +02:00
smallmodel cf61471b2d Added MAX_REAL_LIGHTS 2023-07-24 20:14:16 +02:00
smallmodel 9ebdc6a238 Replaced 2 with RDF_HUD 2023-07-24 20:13:43 +02:00
smallmodel 0c65f5dab3 Incremented version number 2023-07-24 11:47:09 +02:00
515 changed files with 152382 additions and 187246 deletions

No files matched your search

+26 -44
View File
@@ -27,19 +27,6 @@ jobs:
name: "Building for platform linux-${{matrix.architecture.name}}"
runs-on: ubuntu-22.04
# container:
# image: ubuntu:22.04
# volumes:
# - ${{github.workspace}}:${{github.workspace}}
#
# steps:
# - name: Install required packages
# run: apt update && apt install -y clang-15 cmake ninja-build flex bison git
#
# - name: Install required cross-platform packages (${{ matrix.architecture.triple }})
# if: matrix.architecture.name != 'amd64'
# run: apt install -y gcc-12-${{ matrix.architecture.triple }} g++-12-${{ matrix.architecture.triple }}
steps:
- name: Settings
working-directory: ${{github.workspace}}
@@ -54,22 +41,18 @@ jobs:
- name: Install required cross-platform packages (${{ matrix.architecture.triple }})
if: matrix.architecture.name != 'amd64'
run: sudo apt install -y gcc-12-${{ matrix.architecture.triple }} g++-12-${{ matrix.architecture.triple }}
- name: Install dependencies
working-directory: ${{github.workspace}}
run: |
echo Using triple: ${{ matrix.architecture.triple }}
mkdir -p thirdparties && cd thirdparties
git clone --depth 1 --single-branch --branch SDL2 https://github.com/libsdl-org/SDL.git
cmake -B SDL-build \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_C_FLAGS=--target=${{ matrix.architecture.triple }} \
-DCMAKE_CXX_FLAGS=--target=${{ matrix.architecture.triple }} \
-DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/SDL-install' \
./SDL
cmake --build SDL-build --config Release
cmake --install SDL-build
# Setup SDL
- name: Set up SDL
id: sdl
uses: libsdl-org/setup-sdl@main
with:
version: sdl2-latest
build-type: Release
cmake-arguments: "-DCMAKE_C_COMPILER=clang
-DCMAKE_CXX_COMPILER=clang++
-DCMAKE_C_FLAGS=--target=${{ matrix.architecture.triple }}
-DCMAKE_CXX_FLAGS=--target=${{ matrix.architecture.triple }}"
- uses: actions/checkout@v3
with:
@@ -84,9 +67,7 @@ jobs:
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_C_FLAGS=--target=${{ matrix.architecture.triple }} \
-DCMAKE_CXX_FLAGS=--target=${{ matrix.architecture.triple }} \
-DGIT_REVISION_BUILD_NUMBER=${{ github.run_number }} \
-DSDL2_DIR='${{github.workspace}}/thirdparties/SDL-install/lib/cmake/SDL2' \
-DWITH_CLIENT=1" >> $GITHUB_ENV
-DGIT_REVISION_BUILD_NUMBER=${{ github.run_number }}" >> $GITHUB_ENV
- name: Configure CMake
working-directory: ${{github.workspace}}
@@ -111,7 +92,7 @@ jobs:
# Install to the directory defined in CMAKE_INSTALL_PREFIX
run: |
cmake --install ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
cp '${{github.workspace}}/thirdparties/SDL-install/lib/libSDL2.so' '${{github.workspace}}/install'
cp '${{steps.sdl.outputs.prefix}}/lib/libSDL2.so' '${{github.workspace}}/install'
- uses: actions/upload-artifact@v3
with:
@@ -138,14 +119,19 @@ jobs:
run: |
echo "CMAKE_BUILD_PARALLEL_LEVEL=$((Get-CimInstance Win32_ComputerSystem).NumberOfLogicalProcessors * 16)" >> $GITHUB_ENV
- name: Install required packages
# Setup SDL
- name: Set up SDL
id: sdl
uses: libsdl-org/setup-sdl@main
with:
version: sdl2-latest
build-type: Release
cmake-arguments: "-A ${{ matrix.architecture.config }}"
- name: Install Flex/Bison
working-directory: ${{github.workspace}}
run: |
mkdir thirdparties && cd thirdparties
git clone --depth 1 --single-branch --branch SDL2 https://github.com/libsdl-org/SDL.git
cmake -B SDL-build -A ${{ matrix.architecture.config }} -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/SDL-install' ./SDL
cmake --build SDL-build --config Release --parallel
cmake --install SDL-build
git clone --depth 1 --single-branch --branch v2.5.25 https://github.com/lexxmark/winflexbison.git
cmake -B winflexbison-build -DCMAKE_INSTALL_PREFIX='${{github.workspace}}/thirdparties/winflexbison-install' ./winflexbison
cmake --build winflexbison-build --config Release --parallel
@@ -161,13 +147,9 @@ jobs:
--log-level=VERBOSE `
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} `
-DCMAKE_INSTALL_PREFIX='${{github.workspace}}/install' `
-DCMAKE_C_COMPILER=clang `
-DCMAKE_CXX_COMPILER=clang++ `
-DGIT_REVISION_BUILD_NUMBER=${{ github.run_number }} `
-DSDL2_DIR='${{github.workspace}}/thirdparties/SDL-install/cmake' `
-DBISON_EXECUTABLE='${{github.workspace}}/thirdparties/winflexbison-install/win_bison.exe' `
-DFLEX_EXECUTABLE='${{github.workspace}}/thirdparties/winflexbison-install/win_flex.exe' `
-DWITH_CLIENT=1".Replace("`r", "").Replace("`n", "") >> $env:GITHUB_ENV
-DFLEX_EXECUTABLE='${{github.workspace}}/thirdparties/winflexbison-install/win_flex.exe'".Replace("`r", "").Replace("`n", "") >> $env:GITHUB_ENV
- name: Configure CMake
working-directory: ${{github.workspace}}
@@ -192,7 +174,7 @@ jobs:
# Install to the directory defined in CMAKE_INSTALL_PREFIX
run: |
cmake --install ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
Copy-Item "${{github.workspace}}/thirdparties/SDL-install/bin/*.dll" -Destination "${{github.workspace}}/install"
Copy-Item '${{steps.sdl.outputs.prefix}}/bin/*.dll' -Destination '${{github.workspace}}/install'
- uses: actions/upload-artifact@v3
with:
+7
View File
@@ -43,6 +43,13 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v3
# Setup SDL
- name: Set up SDL
id: sdl
uses: libsdl-org/setup-sdl@main
with:
version: sdl2-latest
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
+3
View File
@@ -18,6 +18,9 @@ jobs:
deploy_all:
strategy:
# Set the maximum number of parallel jobs to 1, to avoid a race-condition
# while creating a new release
max-parallel: 1
matrix:
target_os: [
'linux-amd64',
+20 -7
View File
@@ -11,7 +11,8 @@ 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)
@@ -21,6 +22,17 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
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()
IF("${TARGET_ARCH}" STREQUAL "i386")
set(TARGET_ARCH_SUFFIX "x86")
ELSE()
@@ -40,16 +52,14 @@ ELSE()
ENDIF()
IF(CMAKE_BUILD_TYPE MATCHES Debug)
set(TARGET_CONFIG_SUFFIX "-dbg")
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)
# message(STATUS "Enabling exports on Unix for backtrace")
#endif()
ELSE()
set(TARGET_CONFIG_SUFFIX "")
ENDIF()
# Common stuff
@@ -71,9 +81,11 @@ 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}${TARGET_CONFIG_SUFFIX}")
set_target_properties(omohaaded PROPERTIES OUTPUT_NAME "omohaaded${TARGET_BASE_SUFFIX}${TARGET_ARCH_SUFFIX}")
set_target_properties(omohaaded PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
if (MSVC)
target_link_options(omohaaded PRIVATE "/MANIFEST:NO")
@@ -82,7 +94,7 @@ endif()
INSTALL(TARGETS omohaaded DESTINATION "./")
if (WITH_CLIENT)
if (NOT BUILD_NO_CLIENT)
## Client app
add_subdirectory("code/renderer")
@@ -103,7 +115,8 @@ if (WITH_CLIENT)
### Gamespy dependency
target_include_directories(openmohaa PUBLIC "code/qcommon" "code/script" "code/gamespy" "code/server" "code/client" "code/uilib" "code/jpeg-8c")
set_target_properties(openmohaa PROPERTIES OUTPUT_NAME "openmohaa${TARGET_BASE_SUFFIX}${TARGET_ARCH_SUFFIX}${TARGET_CONFIG_SUFFIX}")
set_target_properties(openmohaa PROPERTIES OUTPUT_NAME "openmohaa${TARGET_BASE_SUFFIX}${TARGET_ARCH_SUFFIX}")
set_target_properties(openmohaa PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
target_link_libraries(openmohaa PRIVATE jpeg8)
if (USE_OPENAL)
+121 -43
View File
@@ -17,98 +17,182 @@
## Current State
OpenMoHAA is still in its early days. The singleplayer part is not working correctly, the current usage is multiplayer.
OpenMoHAA is still under development. The single-player campaign is not yet functional due to AI not being fully stable. But the `training` map can be played from start to end. The current focus is on multiplayer.
## Intro
The main goal of OpenMoHAA is to ensure the future and continuity of **Medal of Honor: Allied Assault**. It has always been a dream in the community to provide patches and security fixes for the game. Thanks to the ioquake3 project, F.A.K.K SDK and other quality tools, OpenMoHAA has already reached more than half of its goal: to create an open-source version of MoH:AA (based on version 2.40) that is fully compatible with the original game (in terms of protocol, assets, and scripts).
## Running
Backup existing mohaa files, **cgamex86.dll** and **gamex86.dll** (set their extension to **.bak**)
Ensure that you download the binaries compatible with your platform.
### Requirements
You may need to install Microsoft Visual C++ 2015/2017/2019/2022 Redistributable from https://learn.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist?view=msvc-170
### Client
a) extract archive to your MOHAA installation directory.
-or-
b) Copy all pak*.pk3 files and the sound/ directory from your **MOHAA/main** directory into openmohaa's 'main' directory.
b) extract archive somewhere on your hard drive, create a shortcut to openmohaa (or omohaaded), and set the start directory to your MOHAA installation directory.
If you have problems running the game :
### Server
You may need to install Microsoft Visual C++ 2015/2017/2019/2022 Redistributable from
Extract the archive to your MOHAA server installation directory. Then proceed like you would do with mohaa server:
https://learn.microsoft.com/en-US/cpp/windows/latest-supported-vc-redist?view=msvc-170
- `.\omohaaded.exe +exec server.cfg` on Windows
- `./omohaaded +exec server.cfg` on Linux
Only `omohaaded*` and `game*` binaries are required for the server version, other binaries can be omitted.
### Config file
The config file can be found in different locations depending on the platform:
- `%APPDATA%\openmohaa\<game_name>\configs\omconfig.cfg` on Windows
- `~/.openmohaa/<game_name>/configs/omconfig.cfg` on Linux
This has two advantages:
- On a multi-user system, each user will have their own configuration file
- It doesn't overwrite the existing MOHAA configuration in the MOHAA installation directory.
### Game selection
**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:
- `+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 (main).
With `com_target_game`, OpenMoHAA will support the network protocol accordingly.
You can now start a local OpenMOHAA server or play on a server.
To play expansions, append to the executable `+set com_target_game 1` for Spearhead, and `+set com_target_game 2` for Breakthrough. On windows you can make a shortcut.
### 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 successfully be built.
Some stuff are not working as intended, such as Actor or Vehicle. These systems are both almost fully implemented, but not really in stable state.
The server version can be built successfully, but some features are not functional. For example, the Actor system is almost fully implemented, but it is not yet stable. This means that Actor may not work as expected and could cause crashes.
Overall the server part and the game module are almost fully implemented, but the stability may vary, there may be some minor bugs and crashes.
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 is partially implemented and not stable currently. The cgame module is partially implemented as well, but is compatible with the original MOH:AA game. Credits to **Heavy Metal: F.A.K.K. 2**'s SDK for the cgame module.
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.
Here is the current working state for each part of the engine:
The current operational status for each component is as follow:
| Part name | Full | Almost | Half | Early | Bad | Not working | Comment |
| 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, ... |
| 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 |
| 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) |
**Medal of Honor: Allied Assault Spearhead** and **Medal of Honor: Allied Assault Breakthrough** are supported in OpenMoHAA with the `com_target_game` variable. See the **Running** section for the usage.
| Server module (fgame) | | x | | | | | Actor, and few gameplay bugs |
| UI | | | x | | | | Has core features only (menu, widgets, console, hud, urc loading) |
## Compiling
OpenMoHAA supports both x86 and x64 architectures, and although the target platform is Windows, it still can be compiled for other platforms, and even other architectures.
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.
These are the tools required for all platforms :
The following tools are required for all platforms:
- CMake >= 3.5
- Flex and Bison (currently not used)
- A C++11 compiler is required.
- Flex (>= 2.6.4) and Bison (>= 3.5.1)
- A C++11 compiler is also required.
The installation directory can be set to MOHAA directory.
The installation directory can be set to the MOHAA directory.
The client build can be built by adding `-DWITH_CLIENT=1` to the CMake command line. This will compile the cgame module and the full app with rendering, ui and sound suppport, alongside the dedicated server version.
By default, the build will produce both the client and dedicated server versions. The client can be omitted from the build 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 Unix :
- Clang >= 3.3 or GCC >= 4.8.1
These are the tools required on Linux :
- Clang >= 3.3 or GCC >= 4.8.5
- libsdl2-dev
**clang-3.5** and **gcc-4.8.5** should work (tested on Ubuntu 16.04). Use the latest possible version of those compilers.
**clang-3.5** and **gcc-4.8.5** should work (tested on Ubuntu 16.04), but the latest version should be used.
SDL2 library is required (libsdl2-dev).
Ubuntu 20.04 is the minimum version required to fully compile the project successfully.
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`
1 line install command with clang:
```sh
sudo apt-get install -y cmake ninja-build clang lld flex bison libsdl2-dev
```
Example with **CMake**, **clang-15** and **ninja-build** installed:
Example with **CMake** and **ninja-build** installed:
```sh
mkdir .cmake && cd .cmake
cmake -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15 -DWITH_CLIENT=1 -G Ninja
cmake -G Ninja ../
```
Other compilers can be specified by appending `-DCMAKE_C_COMPILER=/path/to/compiler -DCMAKE_CXX_COMPILER=path/to/compiler` to the CMake command-line.
### 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.
## 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") |
| | |
|-----------------------------------------------------------------------------------|----------------------------------------------------------------------------|
| ![](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)*
## Features
### Features added and not present in MOH:AA
#### Server-side
- Bots
- Spectate players in first-person
- Demo recording
- More script commands for mods
- Non-PVS optimization
##### Non-PVS optimization
For each client, the server optimizes by only sending them information about other players that they can see. Clients won't see other players they can't see.
Enable this feature with `set sv_netoptimize 2`.
#### Client-side and server-side
- Security fixes and features from ioquake3
- IPv6 support (from ioquake3)
### Objectives / planned features
This is a non-exhaustive list of objectives and planned features.
#### Server-side
- 100% compatibility with mohaa content
- More feature for mods
- Anticheat
- Stats system
- Multiple roles/abilities for server admins to reduce password-stealing
## Third party
@@ -116,20 +200,14 @@ Visual Studio (2019 or 2022) is generally preferred.
http://www.libsdl.org/
download Source code, compile
### OpenAL
https://www.openal.org/ download OpenAL soft source
run cmake on OpenAL, compile
https://www.openal.org/
### LibMAD
http://www.underbit.com/products/mad/
download source code, compile
### cURL
https://curl.se/
+24 -16
View File
@@ -1,36 +1,44 @@
set(archdetect_c_code "
#if defined(__i386) || defined(__i386__) || defined(_M_IX86)
#error cmake_ARCH x86
# error cmake_ARCH x86
#elif defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64)
#error cmake_ARCH x86_64
# error cmake_ARCH x86_64
#elif defined(__ppc64__) || defined(__powerpc64__)
#error cmake_ARCH ppc64
# error cmake_ARCH ppc64
#elif defined(__ppc__) || defined(__ppc) || defined(__powerpc__)
#error cmake_ARCH ppc
# error cmake_ARCH ppc
#elif defined __s390__
#error cmake_ARCH s390
# error cmake_ARCH s390
#elif defined __s390x__
#error cmake_ARCH s390x
# error cmake_ARCH s390x
#elif defined __ia64__
#error cmake_ARCH ia64
# error cmake_ARCH ia64
#elif defined __e2k__
# error cmake_ARCH e2k
#elif defined __alpha__
#error cmake_ARCH alpha
# error cmake_ARCH alpha
#elif defined __sparc__
#error cmake_ARCH sparc
# error cmake_ARCH sparc
#elif defined __arm__ || defined (_M_ARM)
#error cmake_ARCH arm
# error cmake_ARCH arm
#elif defined(__aarch64__) || defined(__ARM64__) || defined(_M_ARM64)
#error cmake_ARCH aarch64
# error cmake_ARCH aarch64
#elif defined __cris__
#error cmake_ARCH cris
# error cmake_ARCH cris
#elif defined __hppa__
#error cmake_ARCH hppa
# error cmake_ARCH hppa
#elif defined __mips__
#error cmake_ARCH mips
# error cmake_ARCH mips
#elif defined __sh__
#error cmake_ARCH sh
# error cmake_ARCH sh
#elif defined __riscv
# if __UINTPTR_MAX__ == __UINT64_MAX__
# error cmake_ARCH riscv64
# else
# error cmake_ARCH riscv
# endif
#else
#error cmake_ARCH unknown
# error cmake_ARCH unknown
#endif
")
+5 -5
View File
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.5)
project(fgame)
project(cgame)
# Shared source files for modules
set(SOURCES_SHARED
@@ -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})
@@ -28,13 +28,13 @@ target_compile_features(cgame PUBLIC c_variadic_macros)
target_link_libraries(cgame PUBLIC qcommon)
set_target_properties(cgame PROPERTIES PREFIX "${TARGET_PLATFORM_PREFIX}")
set_target_properties(cgame PROPERTIES OUTPUT_NAME "cgame${TARGET_ARCH_SUFFIX}${TARGET_CONFIG_SUFFIX}")
set_target_properties(cgame PROPERTIES OUTPUT_NAME "cgame${TARGET_ARCH_SUFFIX}")
set_target_properties(cgame PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TARGET_BASE_GAME}")
INSTALL(
TARGETS cgame
DESTINATION "${TARGET_BASE_GAME}"
ARCHIVE EXCLUDE_FROM_ALL
LIBRARY DESTINATION "${TARGET_BASE_GAME}"
RUNTIME DESTINATION "${TARGET_BASE_GAME}"
)
if(MSVC)
+196
View File
@@ -0,0 +1,196 @@
/*
===========================================================================
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 "cg_archive.h"
#include "cg_commands.h"
#include "memarchiver.h"
#include "../qcommon/tiki.h"
void CG_ArchiveStuff(MemArchiver& archiver, int svsTime)
{
archiver.SetBaseTime(svsTime);
commandManager.ArchiveToMemory(archiver);
CG_ArchiveVSSGlobals(archiver);
}
size_t CG_SaveStateToBuffer(void** out, int svsTime)
{
MemArchiver archiver;
size_t size;
archiver.SetupForWriting(0x200000);
CG_ArchiveStuff(archiver, svsTime);
size = archiver.BufferSize();
if (size && out) {
*out = archiver.ConfiscateBuffer();
}
return size;
}
qboolean CG_LoadStateToBuffer(void* state, size_t size, int svsTime)
{
MemArchiver archiver;
archiver.SetupForReading((byte*)state, size);
CG_ArchiveStuff(archiver, svsTime);
return archiver.FinishedReading();
}
void CG_ArchiveStringContainer(MemArchiver& archiver, Container<str>* container)
{
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)
{
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)
{
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)
{
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)
{
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);
}
+53
View File
@@ -0,0 +1,53 @@
/*
===========================================================================
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:
// Memory archiver
#pragma once
#ifdef __cplusplus
#include "../qcommon/container.h"
#include "../qcommon/str.h"
class MemArchiver;
extern "C" {
#endif
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);
void CG_ArchiveStringContainer(MemArchiver& archiver, Container<str>* container);
void CG_ArchiveTikiPointer(MemArchiver& archiver, dtiki_t** pTiki);
void CG_ArchiveModelHandle(MemArchiver& archiver, qhandle_t* handle);
void CG_ArchiveShaderHandle(MemArchiver& archiver, qhandle_t* handle);
void CG_ArchiveRefEntity(MemArchiver& archiver, refEntity_t* ref);
#endif
#ifdef __cplusplus
}
#endif
+1148 -301
View File
File diff suppressed because it is too large. Load diff
+95 -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,18 +930,19 @@ 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);
void SpawnEffect(int count, spawnthing_t *sp);
void FreeAllTempModels(void);
void FreeSomeTempModels(void);
void RestartAllEmitters(void);
void InitializeTempModels(void);
@@ -890,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);
@@ -920,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
+2 -2
View File
@@ -110,8 +110,8 @@ void CG_ScoresDown_f(void)
void CG_ScoresUp_f(void)
{
if (cgs.gametype == GT_SINGLE_PLAYER) {
if (!cg.scoresRequestTime) {
cg.scoresRequestTime = cg.time;
if (cg.scoresRequestTime) {
cg.scoresRequestTime = 0;
CG_SetDesiredObjectiveAlpha(0.0f);
}
+180 -16
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,15 +686,16 @@ 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;
if (fTimeDelta > 0.0) {
iCurrentObjective = atoi(CG_ConfigString(CS_CURRENT_OBJECTIVE));
fTimeDelta = cg.ObjectivesAlphaTime - cg.time;
cg.ObjectivesCurrentAlpha = cg.ObjectivesDesiredAlpha;
if (fTimeDelta > 0) {
cg.ObjectivesCurrentAlpha =
(cg.ObjectivesBaseAlpha - cg.ObjectivesDesiredAlpha) * sin(fTimeDelta * 0.0062831854)
+ cg.ObjectivesCurrentAlpha;
(cg.ObjectivesBaseAlpha - cg.ObjectivesDesiredAlpha) * sin(fTimeDelta / (M_PI * 50.f + 2.f))
+ cg.ObjectivesDesiredAlpha;
}
if (cg.ObjectivesCurrentAlpha < 0.02) {
@@ -702,12 +707,12 @@ void CG_DrawObjectives()
iNumLines[i] = 0;
for (ii = 0; ii < MAX_STRING_CHARS; ii++) {
if (cg.Objectives[i].text[ii] == 10) {
if (cg.Objectives[i].text[ii] == '\n') {
iTotalNumLines++;
iNumLines[ii]++;
iNumLines[i]++;
} else if (!cg.Objectives[i].text[ii]) {
iTotalNumLines++;
iNumLines[ii]++;
iNumLines[i]++;
break;
}
}
@@ -740,17 +745,17 @@ void CG_DrawObjectives()
for (i = 0; i < MAX_OBJECTIVES; ++i) {
qhandle_t hBoxShader;
if ((cg.Objectives[i].flags & 1) || !cg.Objectives[i].flags) {
if ((cg.Objectives[i].flags & OBJ_FLAG_HIDDEN) || !cg.Objectives[i].flags) {
continue;
}
if ((cg.Objectives[i].flags & 2) != 0) {
if ((cg.Objectives[i].flags & OBJ_FLAG_CURRENT) != 0) {
vColor[0] = 1.0;
vColor[1] = 1.0;
vColor[2] = 1.0;
vColor[3] = cg.ObjectivesCurrentAlpha;
hBoxShader = cgs.media.uncheckedBoxShader;
} else if ((cg.Objectives[i].flags & 4) != 0) {
} else if ((cg.Objectives[i].flags & OBJ_FLAG_COMPLETED) != 0) {
vColor[0] = 0.75;
vColor[1] = 0.75;
vColor[2] = 0.75;
@@ -763,7 +768,7 @@ void CG_DrawObjectives()
vColor[3] = cg.ObjectivesCurrentAlpha;
hBoxShader = cgs.media.uncheckedBoxShader;
}
if (i == iCurrentObjective && (cg.Objectives[i].flags & 4) == 0) {
if (i == iCurrentObjective && !(cg.Objectives[i].flags & OBJ_FLAG_COMPLETED)) {
vColor[0] = 1.0;
vColor[1] = 1.0;
vColor[2] = 0.0;
@@ -1082,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;
@@ -1164,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
@@ -1182,5 +1344,7 @@ void CG_Draw2D(void)
CG_DrawPlayerTeam();
CG_DrawPlayerEntInfo();
CG_UpdateAttackerDisplay();
CG_DrawVote();
CG_DrawInstantMessageMenu();
CG_DrawCrosshair();
}
+5 -2
View File
@@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// cg_ents.c -- present snapshot entities, happens every single frame
#include "cg_local.h"
#include "cg_radar.h"
/*
==========================================================================
@@ -551,7 +552,10 @@ void CG_AddCEntity(centity_t *cent)
break;
case ET_PLAYER:
CG_Player(cent);
CG_Splash(cent);
CG_Splash(cent);
CG_ModelAnim(cent, qfalse);
CG_UpdateRadarClient(cent);
break;
case ET_ITEM:
CG_ModelAnim(cent, qfalse);
break;
@@ -666,7 +670,6 @@ void CG_GetOrigin(centity_t *cent, vec3_t origin)
parent = cgi.R_GetRenderEntity(cent->currentState.parent);
if (!parent) {
cgi.DPrintf("CG_GetOrigin: Could not find parent entity\n");
return;
}
+26 -2
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
@@ -341,7 +343,9 @@ extern "C" {
// misc
crain_t rain;
clientInfo_t clientinfo[MAX_CLIENTS];
clientInfo_t clientinfo[MAX_CLIENTS];
radarClient_t radars[MAX_CLIENTS];
qhandle_t radarShaders[2];
} cg_t;
typedef struct {
@@ -392,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
//
@@ -456,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;
@@ -486,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);
@@ -519,6 +537,7 @@ extern "C" {
void CG_EndTiki(dtiki_t *tiki);
qboolean CG_Command_ProcessFile(const char *filename, qboolean quiet, dtiki_t *curTiki);
void CG_RestartCommandManager();
void CG_CleanUpTempModels();
qboolean CG_ProcessEntityCommands(int frame, int anim, int entnum, refEntity_t *ent, centity_t *cent);
void CG_ClientCommands(refEntity_t *ent, centity_t *cent, int slot);
float RandomizeRange(float start, float end);
@@ -527,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;
@@ -908,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;
+205 -122
View File
@@ -25,6 +25,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cg_local.h"
#include "cg_parsemsg.h"
#include "cg_archive.h"
#include "cg_radar.h"
#ifdef _WIN32
# include <windows.h>
@@ -78,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;
@@ -157,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);
@@ -231,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;
@@ -332,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;
}
}
}
}
@@ -421,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);
}
}
@@ -467,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));
@@ -493,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();
@@ -537,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
@@ -557,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);
@@ -568,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;
@@ -624,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();
@@ -677,6 +745,11 @@ clientGameExport_t *GetCGameAPI(void)
cge.CG_GetObjectiveAlpha = CG_GetObjectiveAlpha;
cge.CG_WeaponCommandButtonBits = CG_WeaponCommandButtonBits;
cge.CG_CheckCaptureKey = CG_CheckCaptureKey;
cge.CG_ReadNonPVSClient = CG_ReadNonPVSClient;
cge.CG_UpdateRadar = CG_UpdateRadar;
cge.CG_SaveStateToBuffer = CG_SaveStateToBuffer;
cge.CG_LoadStateToBuffer = CG_LoadStateToBuffer;
cge.CG_CleanUpTempModels = CG_CleanUpTempModels;
// FIXME
//cge.profStruct = NULL;
@@ -781,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;
+24
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);
}
/*
@@ -477,6 +483,24 @@ void CG_PredictPlayerState(void)
}
cg_pmove.noFootsteps = (cgs.dmflags & DF_NO_FOOTSTEPS) > 0;
if (cg_protocol >= PROTOCOL_MOHTA_MIN) {
// Leaning while moving is allowed in mohta and mohtt only with a specific dm flag bit set
cg_pmove.alwaysAllowLean = (cgs.dmflags & DF_ALLOW_LEAN_MOVEMENT) ? qtrue : qfalse;
cg_pmove.leanMax = 45.f;
cg_pmove.leanAdd = 6.f;
cg_pmove.leanRecoverSpeed = 8.5f;
cg_pmove.leanSpeed = 2.f;
} else {
cg_pmove.alwaysAllowLean = qtrue;
cg_pmove.leanMax = 40.f;
cg_pmove.leanAdd = 10.f;
cg_pmove.leanRecoverSpeed = 15.f;
cg_pmove.leanSpeed = 4.f;
}
cg_pmove.protocol = cg_protocol;
// save the state before the pmove so we can detect transitions
oldPlayerState = cg.predicted_player_state;
+21 -7
View File
@@ -23,8 +23,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// DESCRIPTION:
// client game public interfaces
#ifndef __CG_PUBLIC_H__
#define __CG_PUBLIC_H__
#pragma once
#include "../renderercommon/tr_types.h"
#ifdef __cplusplus
extern "C" {
@@ -67,7 +68,7 @@ extern "C" {
typedef struct stopWatch_s {
int iStartTime;
int iEndTime;
int eType;
} stopWatch_t;
typedef struct AliasList_s AliasList_t;
@@ -136,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
@@ -162,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);
@@ -282,10 +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_RegisterSkin)(const char *name);
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);
@@ -419,9 +423,12 @@ functions exported to the main executable
);
void (*UI_DeleteScoreBoardItems)(int maxIndex);
void (*UI_ToggleDMMessageConsole)(int consoleMode);
void (*CL_InitRadar)(radarClient_t* radars, qhandle_t* shaders, int clientNum); // Added in 2.0
dtiki_t *(*TIKI_FindTiki)(const char *path);
void (*LoadResource)(const char *name);
void (*FS_CanonicalFilename)(char *name);
void (*CL_RestoreSavedCgameState)();
void (*CL_ClearSavedCgameState)();
cvar_t *fsDebug;
hdelement_t *HudDrawElements;
@@ -491,6 +498,15 @@ functions exported to the main executable
int (*CG_WeaponCommandButtonBits)();
int (*CG_CheckCaptureKey)(int key, qboolean down, unsigned int time);
//
// Added in 2.0
//
void (*CG_ReadNonPVSClient)(radarUnpacked_t* radarUnpacked);
void (*CG_UpdateRadar)();
size_t (*CG_SaveStateToBuffer)(void** out, int svsTime);
qboolean (*CG_LoadStateToBuffer)(void* state, size_t size, int svsTime);
void (*CG_CleanUpTempModels)();
// FIXME
//prof_cgame_t* profStruct;
@@ -510,5 +526,3 @@ functions exported to the main executable
#ifdef __cplusplus
}
#endif
#endif // __CG_PUBLIC_H__
+168
View File
@@ -0,0 +1,168 @@
/*
===========================================================================
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 "cg_radar.h"
void CG_InitRadar()
{
int i;
cg.radarShaders[0] = cgi.R_RegisterShader("textures/hud/radar_allies.tga");
cg.radarShaders[1] = cgi.R_RegisterShader("textures/hud/radar_axis.tga");
for (i = 0; i < MAX_CLIENTS; i++)
{
cg.radars[i].time = 0;
cg.radars[i].lastSpeakTime = 0;
}
cgi.CL_InitRadar(cg.radars, cg.radarShaders, cg.snap->ps.clientNum);
}
bool CG_InTeamGame(centity_t *ent)
{
return ent->currentState.solid && cg.clientinfo[ent->currentState.number].team;
}
bool CG_SameTeam(centity_t *ent)
{
return cg.clientinfo[ent->currentState.number].team == cg.clientinfo[cg.snap->ps.clientNum].team;
}
bool CG_IsTeamGame()
{
return cgs.gametype >= GT_TEAM;
}
bool CG_ValidRadarClient(centity_t *ent)
{
if (!cg.snap) {
return qfalse;
}
if (!CG_IsTeamGame()) {
return false;
}
if (!CG_InTeamGame(&cg_entities[cg.snap->ps.clientNum])) {
return false;
}
if (!CG_InTeamGame(ent)) {
return false;
}
return CG_SameTeam(ent);
}
int CG_RadarIcon()
{
switch (cg.clientinfo[cg.snap->ps.clientNum].team)
{
case TEAM_ALLIES:
return 0;
default:
case TEAM_AXIS:
return 1;
}
}
void CG_UpdateRadarClient(centity_t* ent)
{
radarClient_t* radar;
radar = &cg.radars[ent->currentState.number];
if (!CG_ValidRadarClient(ent)) {
radar->time = 0;
return;
}
radar->time = cg.time;
radar->teamShader = CG_RadarIcon();
if (cg.snap->ps.clientNum == ent->currentState.number)
{
radar->origin[0] = cg.refdef.vieworg[0];
radar->origin[1] = cg.refdef.vieworg[1];
radar->axis[0] = cg.refdef.viewaxis[0][0];
radar->axis[1] = cg.refdef.viewaxis[0][1];
VectorNormalize2D(radar->axis);
}
else
{
float axis[2];
radar->origin[0] = ent->currentState.origin[0];
radar->origin[1] = ent->currentState.origin[1];
YawToAxis(ent->currentState.angles[1], axis);
radar->axis[0] = axis[0];
radar->axis[1] = axis[1];
VectorNormalize2D(radar->axis);
}
}
void CG_ReadNonPVSClient(radarUnpacked_t* radarUnpacked)
{
radarClient_t* radar;
float axis[2];
if (!CG_ValidRadarClient(&cg_entities[radarUnpacked->clientNum])) {
return;
}
radar = &cg.radars[radarUnpacked->clientNum];
radar->time = cg.time;
radar->teamShader = CG_RadarIcon();
// copy origin
radar->origin[0] = radarUnpacked->x;
radar->origin[1] = radarUnpacked->y;
// copy yaw
YawToAxis(radarUnpacked->yaw, axis);
radar->axis[0] = axis[0];
radar->axis[1] = axis[1];
VectorNormalize2D(radar->axis);
}
void CG_UpdateRadar()
{
int i;
for (i = 0; i < MAX_CLIENTS; i++)
{
if (cg.radars[i].time)
{
if (!CG_ValidRadarClient(&cg_entities[i])) {
cg.radars[i].time = 0;
}
}
}
}
void CG_RadarClientSpeaks(int num)
{
if (!CG_ValidRadarClient(&cg_entities[num])) {
return;
}
cg.radars[num].lastSpeakTime = cg.time;
}
+22 -18
View File
@@ -1,38 +1,42 @@
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
Copyright (C) 2023 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
// DESCRIPTION:
// Radar client
#pragma once
#include "cg_local.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef __GLW_LINUX_H__
#define __GLW_LINUX_H__
typedef struct
{
void *OpenGLLib; // instance of OpenGL library
FILE *log_fp;
} glwstate_t;
extern glwstate_t glw_state;
void CG_InitRadar();
void CG_UpdateRadarClient(centity_t* ent);
void CG_ReadNonPVSClient(radarUnpacked_t* radarUnpacked);
void CG_UpdateRadar();
void CG_RadarClientSpeaks(int num);
#ifdef __cplusplus
}
#endif
+80 -27
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);
}
/*
@@ -241,6 +250,13 @@ static void CG_Stopwatch_f()
if (cg_protocol >= PROTOCOL_MOHTA_MIN) {
cgi.stopWatch->iStartTime = atoi(cgi.Argv(1));
if (cgi.Argc() > 3) {
cgi.stopWatch->eType = atoi(cgi.Argv(3));
} else {
// Normal stop watch
cgi.stopWatch->eType = SWT_NORMAL;
}
} else {
// The base game has it wrong
cgi.stopWatch->iStartTime = 1000 * atoi(cgi.Argv(1));
@@ -268,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;
@@ -280,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;
}
@@ -291,19 +311,19 @@ static void CG_ServerCommand(void)
}
return;
} else if (!strcmp(cmd, "printdeathmsg")) {
const char *s1, *s2, *s3, *s4, *s5;
const char *s1, *s2, * attackerName, * victimName, *type;
const char *result1, *result2;
int hudColor;
result1 = NULL;
result2 = NULL;
s1 = cgi.Argv(1);
s2 = cgi.Argv(2);
s3 = cgi.Argv(3);
s4 = cgi.Argv(4);
s5 = cgi.Argv(5);
s1 = cgi.Argv(1);
s2 = cgi.Argv(2);
attackerName = cgi.Argv(3);
victimName = cgi.Argv(4);
type = cgi.Argv(5);
if (*s5 == tolower(*s5)) {
if (*type == tolower(*type)) {
hudColor = 4;
} else {
hudColor = 5;
@@ -315,16 +335,16 @@ static void CG_ServerCommand(void)
if (*s2 != 'x') {
result2 = cgi.LV_ConvertString(s2);
}
if (tolower(*s5) == 's') {
cgi.Printf("%c%s %s\n", hudColor, s4, result1);
} else if (tolower(*s5) == 'p') {
if (tolower(*type) == 's') {
cgi.Printf("%c%s %s\n", hudColor, victimName, result1);
} else if (tolower(*type) == 'p') {
if (*s2 == 'x') {
cgi.Printf("%c%s %s %s\n", hudColor, s4, result1, s3);
cgi.Printf("%c%s %s %s\n", hudColor, victimName, result1, attackerName);
} else {
cgi.Printf("%c%s %s %s%s\n", hudColor, s4, result1, s3, result2);
cgi.Printf("%c%s %s %s%s\n", hudColor, victimName, result1, attackerName, result2);
}
} else if (tolower(*s5) == 'w') {
cgi.Printf("%c%s %s\n", hudColor, s4, result1);
} else if (tolower(*type) == 'w') {
cgi.Printf("%c%s %s\n", hudColor, victimName, result1);
} else {
cgi.Printf("%s", cgi.Argv(1));
}
@@ -357,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);
}
@@ -370,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);
}
}
}
+19
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"
/*
@@ -161,6 +165,9 @@ void CG_SetInitialSnapshot(snapshot_t *snap)
cgi.MUSIC_UpdateMood(snap->ps.current_music_mood, snap->ps.fallback_music_mood);
cgi.MUSIC_UpdateVolume(snap->ps.music_volume, snap->ps.music_volume_fade_time);
cgi.S_SetReverb(snap->ps.reverb_type, snap->ps.reverb_level);
CG_InitRadar();
cgi.CL_RestoreSavedCgameState();
}
/*
@@ -203,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++) {
@@ -240,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;
}
/*
+218 -114
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);
@@ -1092,7 +1196,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));
+7
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;
@@ -287,6 +293,7 @@ qboolean VSS_SourcePhysics(cvssource_t *pSource, float ftime)
pSource->lastOrigin = pSource->newOrigin;
if (pSource->flags & 0x800) {
trace.allsolid = qfalse;
CG_ClipMoveToEntities(
pSource->newOrigin, vec3_origin, vec3_origin, pSource->newOrigin, -1, MASK_VOLUMETRIC_SMOKE, &trace, qfalse
);
+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;
};
+1 -2
View File
@@ -19,5 +19,4 @@ target_link_libraries(omohclient INTERFACE gcd)
target_compile_definitions(omohclient INTERFACE USE_CODEC_MP3)
add_subdirectory("../libmad-0.15.1b" "./libmad")
target_link_libraries(omohclient INTERFACE libmad)
target_include_directories(omohclient INTERFACE "../libmad-0.15.1b")
target_link_libraries(omohclient INTERFACE libmad)
+44 -12
View File
@@ -23,6 +23,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "client.h"
#include "cl_ui.h"
#include "cl_uiradar.h"
#include "../qcommon/tiki.h"
#include "../qcommon/localization.h"
#include "../qcommon/bg_compat.h"
@@ -434,10 +435,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());
}
/*
@@ -540,6 +541,29 @@ void CL_StartLocalSound(const char* soundName, qboolean forceLoad) {
S_StartLocalSound(soundName, qfalse );
}
/*
====================
CL_RestoreSavedCgameState
====================
*/
void CL_RestoreSavedCgameState() {
if (cls.savedCgameState) {
cge->CG_LoadStateToBuffer(&cls.savedCgameState, cls.savedCgameStateSize, cl.snap.serverTime);
}
}
/*
====================
CL_ClearSavedCgameState
====================
*/
void CL_ClearSavedCgameState() {
if (cls.savedCgameState) {
cls.savedCgameState = NULL;
cls.savedCgameStateSize = 0;
}
}
/*
====================
CL_InitCGameDLL
@@ -556,6 +580,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;
@@ -581,6 +606,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;
@@ -652,9 +679,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;
@@ -745,11 +774,14 @@ void CL_InitCGameDLL( clientGameImport_t *cgi, clientGameExport_t **cge ) {
cgi->UI_SetScoreBoardItem = UI_SetScoreBoardItem;
cgi->UI_DeleteScoreBoardItems = UI_DeleteScoreBoardItems;
cgi->UI_ToggleDMMessageConsole = UI_ToggleDMConsole;
cgi->CL_InitRadar = CL_InitRadar;
cgi->TIKI_FindTiki = TIKI_FindTiki;
cgi->LoadResource = UI_LoadResource;
cgi->FS_CanonicalFilename = FS_CanonicalFilename;
cgi->CL_RestoreSavedCgameState = CL_RestoreSavedCgameState;
cgi->CL_ClearSavedCgameState = CL_ClearSavedCgameState;
cgi->fsDebug = fs_debug;
cgi->HudDrawElements = cls.HudDrawElements;
@@ -904,8 +936,6 @@ qboolean CL_GameCommand( void ) {
return cge->CG_ConsoleCommand();
}
/*
=====================
CL_CGameRendering
@@ -920,6 +950,10 @@ void CL_CGameRendering( stereoFrame_t stereo ) {
cge->CG_DrawActiveFrame( cl.serverTime, cl.serverTime - cl.oldServerTime, stereo, clc.demoplaying );
cl.oldServerTime = cl.serverTime;
//
// Let cgame clean up temp models
//
cge->CG_CleanUpTempModels();
}
/*
@@ -1095,16 +1129,14 @@ void CL_SetCGameTime( void ) {
return;
}
// FIXME
//if( ( cl.snap.snapFlags ^ lastSnapFlags ) & SNAPFLAG_SERVERCOUNT ) {
// CL_ServerRestarted();
//} else {
if( ( cl.snap.snapFlags ^ lastSnapFlags ) & SNAPFLAG_SERVERCOUNT ) {
CL_ServerRestarted();
} else {
if( cl.snap.serverTime < cl.oldFrameServerTime ) {
assert( 0 );
Com_Error( ERR_DROP, "cl.snap.serverTime < cl.oldFrameServerTime" );
}
//}
}
cl.oldFrameServerTime = cl.snap.serverTime;
+2 -2
View File
@@ -1612,7 +1612,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 +1639,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;
}
}
+2 -2
View File
@@ -1051,8 +1051,8 @@ void CL_InitInput( void ) {
Cmd_AddCommand("-leanleft", IN_LeanLeftUp);
Cmd_AddCommand("+leanright", IN_LeanRightDown);
Cmd_AddCommand("-leanright", IN_LeanRightUp);
Cmd_AddCommand("+speed", IN_SpeedUp);
Cmd_AddCommand("-speed", IN_SpeedDown);
Cmd_AddCommand("+speed", IN_SpeedDown);
Cmd_AddCommand("-speed", IN_SpeedUp);
Cmd_AddCommand("+button0", IN_Button0Down);
Cmd_AddCommand("-button0", IN_Button0Up);
Cmd_AddCommand("+button1", IN_Button1Down);
+1 -1
View File
@@ -1153,7 +1153,7 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
}
}
if (!in_guimouse || key <= K_MOUSE3 || key > K_JOY1)
if (!in_guimouse || key <= K_MWHEELUP || key > K_JOY1)
{
// keys can still be used for bound actions
if (down && (key <= K_BACKSPACE || key == K_MOUSE4) &&
+105 -40
View File
@@ -26,6 +26,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cl_ui.h"
#include "../qcommon/tiki.h"
#include "../qcommon/cm_terrain.h"
#include "../qcommon/localization.h"
#include "../qcommon/bg_compat.h"
#include "../sys/sys_local.h"
#ifdef USE_RENDERER_DLL
#include "../sys/sys_loadlib.h"
@@ -102,6 +104,9 @@ cvar_t *cl_inGameVideo;
cvar_t *cl_serverStatusResendTime;
cvar_t *cl_trn;
cvar_t *cl_langamerefreshstatus;
cvar_t *cl_radar_icon_size;
cvar_t *cl_radar_speak_time;
cvar_t *cl_radar_blink_time;
cvar_t *cl_lanForcePackets;
@@ -362,14 +367,14 @@ void CL_Record_f( void ) {
if ( Cmd_Argc() == 2 ) {
s = Cmd_Argv(1);
Q_strncpyz( demoName, s, sizeof( demoName ) );
Com_sprintf (name, sizeof(name), "demos/%s.dm_%d", demoName, PROTOCOL_VERSION );
Com_sprintf (name, sizeof(name), "demos/%s.dm_%d", demoName, com_protocol->integer );
} else {
int number;
// scan for a free demo name
for ( number = 0 ; number <= 9999 ; number++ ) {
CL_DemoFilename( number, demoName );
Com_sprintf (name, sizeof(name), "demos/%s.dm_%d", demoName, PROTOCOL_VERSION );
Com_sprintf (name, sizeof(name), "demos/%s.dm_%d", demoName, com_protocol->integer );
if (!FS_FileExists(name))
break; // file doesn't exist
@@ -404,8 +409,8 @@ void CL_Record_f( void ) {
// NOTE, MRE: all server->client messages now acknowledge
MSG_WriteLong( &buf, clc.reliableSequence );
MSG_WriteByte (&buf, svc_gamestate);
MSG_WriteLong (&buf, clc.serverCommandSequence );
MSG_WriteByte ( &buf, svc_gamestate );
MSG_WriteLong ( &buf, clc.serverCommandSequence );
// configstrings
for ( i = 0 ; i < MAX_CONFIGSTRINGS ; i++ ) {
@@ -413,21 +418,20 @@ void CL_Record_f( void ) {
continue;
}
s = cl.gameState.stringData + cl.gameState.stringOffsets[i];
MSG_WriteByte (&buf, svc_configstring);
MSG_WriteShort (&buf, i);
MSG_WriteBigString (&buf, s);
MSG_WriteByte ( &buf, svc_configstring );
MSG_WriteShort ( &buf, CPT_DenormalizeConfigstring( i ) );
MSG_WriteScrambledBigString ( &buf, s );
}
// baselines
Com_Memset (&nullstate, 0, sizeof(nullstate));
MSG_GetNullEntityState(&nullstate);
for ( i = 0; i < MAX_GENTITIES ; i++ ) {
ent = &cl.entityBaselines[i];
if ( !ent->number ) {
continue;
}
MSG_WriteByte (&buf, svc_baseline);
// FIXME
MSG_WriteDeltaEntity (&buf, &nullstate, ent, qtrue, 0.0 );
MSG_WriteByte ( &buf, svc_baseline );
MSG_WriteDeltaEntity ( &buf, &nullstate, ent, qtrue, cls.serverFrameTime );
}
MSG_WriteByte( &buf, svc_EOF );
@@ -437,7 +441,10 @@ void CL_Record_f( void ) {
// write the client num
MSG_WriteLong(&buf, clc.clientNum);
// write the checksum feed
MSG_WriteLong(&buf, clc.checksumFeed);
MSG_WriteLong(&buf, clc.checksumFeed);
// write the server frametime to the client (only on TA/TT)
MSG_WriteServerFrameTime( &buf, cls.serverFrameTime );
// finished writing the client packet
MSG_WriteByte( &buf, svc_EOF );
@@ -592,7 +599,7 @@ void CL_ReadDemoMessage( void ) {
return;
}
buf.cursize = LittleLong( buf.cursize );
if ( buf.cursize == -1 ) {
if ( buf.cursize == (uint32_t)-1) {
CL_DemoCompleted ();
return;
}
@@ -794,7 +801,7 @@ void CL_FlushMemory( void ) {
// shutdown all the client stuff
CL_ShutdownCGame();
S_StopAllSounds( qtrue );
S_StopAllSounds2( qtrue );
UI_ClearState();
cls.rendererRegistered = qfalse;
}
@@ -816,6 +823,11 @@ void CL_MapLoading( qboolean flush, const char *pszMapName ) {
UI_ClearState();
UI_ForceMenuOff(false);
if (!flush) {
// Don't do anything if it's not flushingb
return;
}
if (pszMapName) {
// if we are already connected to the local host, stay connected
if (clc.state >= CA_CONNECTED && !Q_stricmp(cls.servername, "localhost")) {
@@ -856,7 +868,7 @@ void CL_ClearState( void )
CL_ShutdownCGame();
if( !com_sv_running->integer ) {
S_StopAllSounds( qtrue );
S_StopAllSounds2( qtrue );
}
UI_ClearState();
@@ -871,7 +883,7 @@ CL_UpdateGUID
update cl_guid using QKEY_FILE and optional prefix
====================
*/
static void CL_UpdateGUID( char *prefix, int prefix_len )
static void CL_UpdateGUID( const char *prefix, int prefix_len )
{
fileHandle_t f;
int len;
@@ -1198,7 +1210,7 @@ void CL_Disconnect_f( void ) {
CL_AbnormalDisconnect();
CL_FlushMemory();
CL_StartHunkUsers(qfalse);
S_StopAllSounds(1);
S_StopAllSounds2(1);
S_TriggeredMusic_PlayIntroMusic();
}
@@ -1230,12 +1242,12 @@ void CL_Reconnect_f( void ) {
/*
================
CL_Connect_f
CL_Connect
================
*/
void CL_Connect( const char *server ) {
char serverString[ 22 ];
void CL_Connect( const char *server, netadrtype_t family ) {
const char *serverString;
Cvar_Set( "ui_singlePlayerActive", "0" );
@@ -1263,21 +1275,24 @@ void CL_Connect( const char *server ) {
Q_strncpyz( cls.servername, server, sizeof( cls.servername ) );
if( !NET_StringToAdr( cls.servername, &clc.serverAddress, NA_IP ) ) {
if( !NET_StringToAdr( cls.servername, &clc.serverAddress, family ) ) {
Com_Printf( "Bad server address\n" );
clc.state = CA_DISCONNECTED;
UI_PushMenu("badserveraddy");
return;
}
if( clc.serverAddress.port == 0 ) {
clc.serverAddress.port = BigShort( PORT_SERVER );
}
Com_sprintf( serverString, sizeof( serverString ), "%i.%i.%i.%i:%i",
clc.serverAddress.ip[ 0 ], clc.serverAddress.ip[ 1 ],
clc.serverAddress.ip[ 2 ], clc.serverAddress.ip[ 3 ],
BigShort( clc.serverAddress.port ) );
serverString = NET_AdrToStringwPort(clc.serverAddress);
Com_Printf( "%s resolved to %s\n", cls.servername, serverString );
if (cl_guidServerUniq->integer)
CL_UpdateGUID(serverString, strlen(serverString));
else
CL_UpdateGUID(NULL, 0);
// if we aren't playing on a lan, we need to authenticate
// with the cd key
// wombat: no authorization in mohaa. need to send challenge to server though
@@ -1286,11 +1301,14 @@ void CL_Connect( const char *server ) {
}
else {
clc.state = CA_CONNECTING;
// Set a client challenge number that ideally is mirrored back by the server.
clc.challenge = (((unsigned int)rand() << 16) ^ (unsigned int)rand()) ^ Com_Milliseconds();
}
clc.connectTime = -99999; // CL_CheckForResend() will fire immediately
clc.connectPacketCount = 0;
clc.connectStartTime = 0;
clc.connectStartTime = cls.realtime;
// server connection string
Cvar_Set( "cl_currentServerAddress", server );
@@ -1303,17 +1321,36 @@ CL_Connect_f
================
*/
// we have our own server provided to us by mohaaaa.co.uk
void CL_Connect_f( void ) {
char *server;
void CL_Connect_f(void) {
const char *server;
int argc = Cmd_Argc();
netadrtype_t family = NA_UNSPEC;
if ( Cmd_Argc() != 2 ) {
Com_Printf( "usage: connect [server]\n");
return;
}
server = Cmd_Argv (1);
CL_Connect( server );
if (argc != 2 && argc != 3) {
Com_Printf("usage: connect [-4|-6] server\n");
return;
}
if (argc == 2)
server = Cmd_Argv(1);
else
{
if (!strcmp(Cmd_Argv(1), "-4"))
family = NA_IP;
else if (!strcmp(Cmd_Argv(1), "-6"))
family = NA_IP6;
else
Com_Printf("warning: only -4 or -6 as address type understood.\n");
server = Cmd_Argv(2);
}
CL_Connect( server, family );
}
/*
@@ -1331,7 +1368,7 @@ void CL_MenuConnect_f( void ) {
server = Cmd_Argv( 1 );
CL_Connect( Cvar_VariableString( server ) );
CL_Connect( Cvar_VariableString( server ), NA_UNSPEC );
}
/*
@@ -1351,7 +1388,7 @@ void CL_FastConnect_f( void ) {
Com_Printf( "Server %i - '%s'\n", i, NET_AdrToString( cls.localServers[ i ].adr ) );
}
CL_Connect( cls.localServers[ 0 ].hostName );
CL_Connect( cls.localServers[ 0 ].hostName, NA_UNSPEC );
Cbuf_AddText( "popmenu 0 ; wait 500 ; popmenu 0 ; wait 500 ; popmenu 0\n" );
endTime = 123456789;
}
@@ -1398,7 +1435,8 @@ void CL_Rcon_f( void ) {
message[1] = -1;
message[2] = -1;
message[3] = -1;
message[4] = 0;
message[4] = 2; // direction
message[5] = 0;
Q_strcat (message, MAX_RCON_MESSAGE, "rcon ");
@@ -1483,7 +1521,7 @@ void CL_Vid_Restart_f( void ) {
cls.vid_restart = qtrue;
// don't let them loop during the restart
S_StopAllSounds(qtrue);
S_StopAllSounds2(qtrue);
SV_ClearSvsTimeFixups();
@@ -1497,6 +1535,8 @@ void CL_Vid_Restart_f( void ) {
CL_InitRef();
// initialize the ui library
UI_ResolutionChange();
// clear aliases
Alias_Clear();
cls.rendererRegistered = qfalse;
@@ -1509,6 +1549,12 @@ void CL_Vid_Restart_f( void ) {
S_Init();
if (clc.state > CA_CONNECTED && clc.state != CA_CINEMATIC)
{
// send pure checksums
CL_SendPureChecksums();
}
cls.vid_restart = qfalse;
Com_Printf("----- finished CL_Vid_Restart_f ----\n");
}
@@ -1648,6 +1694,13 @@ void CL_DownloadsComplete( void ) {
Com_EventLoop();
CL_StartHunkUsers(qfalse);
// set pure checksums
CL_SendPureChecksums();
CL_WritePacket();
CL_WritePacket();
CL_WritePacket();
}
/*
@@ -2424,7 +2477,7 @@ void CL_Frame ( int msec ) {
if ( clc.state == CA_DISCONNECTED && !UI_MenuActive()
&& !com_sv_running->integer ) {
// if disconnected, bring up the menu
S_StopAllSounds( qtrue );
S_StopAllSounds2( qtrue );
UI_MenuEscape( "main" );
}
@@ -2640,6 +2693,15 @@ void *CL_RefMalloc(int size) {
return Z_TagMalloc( size, TAG_RENDERER );
}
/*
============
CL_RefFree
============
*/
void CL_RefFree(void* ptr) {
Z_Free(ptr);
}
/*
============
CL_RefClear
@@ -2796,8 +2858,9 @@ void CL_InitRef( void ) {
ri.Printf = CL_RefPrintf;
ri.Error = Com_Error;
ri.Milliseconds = CL_ScaledMilliseconds;
ri.LV_ConvertString = Sys_LV_CL_ConvertString;
ri.Malloc = CL_RefMalloc;
ri.Free = Z_Free;
ri.Free = CL_RefFree;
ri.Clear = CL_RefClear;
ri.Hunk_Clear = CL_RefStaticClear;
#ifdef HUNK_DEBUG
@@ -3125,7 +3188,7 @@ void CL_Init( void ) {
start = Sys_Milliseconds();
CL_ClearState ();
S_StopAllSounds( qtrue );
S_StopAllSounds2( qtrue );
clc.state = CA_DISCONNECTED; // no longer CA_UNINITIALIZED
Key_SetCatcher(KEYCATCH_UI);
@@ -3239,6 +3302,9 @@ void CL_Init( void ) {
cl_motdString = Cvar_Get( "cl_motdString", "", CVAR_ROM );
cl_langamerefreshstatus = Cvar_Get( "cl_langamerefreshstatus", "Ready", 0 );
cl_radar_icon_size = Cvar_Get("cl_radar_icon_size", "10", CVAR_ARCHIVE);
cl_radar_speak_time = Cvar_Get("cl_radar_speak_time", "3", CVAR_ARCHIVE);
cl_radar_blink_time = Cvar_Get("cl_radar_blink_time", "0.333", CVAR_ARCHIVE);
cg_gametype = Cvar_Get( "cg_gametype", "0", 0 );
cl_lanForcePackets = Cvar_Get ("cl_lanForcePackets", "1", CVAR_ARCHIVE);
@@ -3324,7 +3390,6 @@ void CL_Init( void ) {
Cvar_Set( "cl_running", "1" );
NET_Init();
S_Init2();
// fixme: should we leave it?
@@ -4247,7 +4312,7 @@ CL_ServerRestarted
==================
*/
void CL_ServerRestarted( void ) {
S_StopAllSounds( qfalse );
S_StopAllSounds2( qfalse );
UI_ServerLoaded();
UI_ClearState();
+68 -36
View File
@@ -194,6 +194,69 @@ void CL_ParsePacketEntities( msg_t *msg, clSnapshot_t *oldframe, clSnapshot_t *n
}
}
/*
================
CL_UnpackNonPVSClient
Unpack info about non-visible client.
================
*/
qboolean CL_UnpackNonPVSClient(int* packed, radarUnpacked_t* unpacked) {
int x, y;
int yaw;
qboolean bValid;
float range;
unpacked->clientNum = *packed & (MAX_CLIENTS - 1);
if (unpacked->clientNum == cl.snap.ps.clientNum) {
return qfalse;
}
x = ((*packed >> 6) & 0x7F) - (MAX_CLIENTS - 1);
y = ((*packed >> 13) & 0x7F) - (MAX_CLIENTS - 1);
yaw = (*packed >> 20) & 0x1F;
bValid = (*packed >> 25) & 1;
if (com_radar_range && com_radar_range->value) {
range = com_radar_range->value;
} else {
range = 0;
}
unpacked->x = x * range / 63.f;
unpacked->y = y * range / 63.f;
if (!bValid)
{
unpacked->x = x * range / 63.f * 1024;
unpacked->y = y * range / 63.f * 1024;
}
unpacked->yaw = yaw * 11.25f;
return qtrue;
}
/*
================
CL_ReadNonPVSClient
Reads packed info about non-visible client.
================
*/
void CL_ReadNonPVSClient(int radarInfo) {
radarUnpacked_t unpacked;
if (!cge) {
return;
}
if (CL_UnpackNonPVSClient(&radarInfo, &unpacked)) {
unpacked.x += cl.snap.ps.origin[0];
unpacked.y += cl.snap.ps.origin[1];
cge->CG_ReadNonPVSClient(&unpacked);
}
}
/*
================
@@ -332,6 +395,9 @@ void CL_ParseSnapshot( msg_t *msg ) {
}
cl.newSnapshots = qtrue;
// read radar info about invisible clients
CL_ReadNonPVSClient(cl.snap.ps.radarInfo);
}
@@ -448,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
@@ -525,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) {
@@ -554,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();
+3834 -4024
View File
File diff suppressed because it is too large. Load diff
+85 -66
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,110 +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 *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_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);
+1 -14
View File
@@ -20,8 +20,7 @@ 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;
@@ -43,15 +42,3 @@ public:
void SetupFiles( void );
};
#ifdef __cplusplus
extern "C" {
#endif
void UI_SetupFiles( void );
#ifdef __cplusplus
}
#endif
#endif
+133
View File
@@ -20,7 +20,22 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// cl_uiradar.cpp: draw teammates
// since 2.0
#include "cl_uiradar.h"
#include "client.h"
radarClient_t* g_radarClients;
qhandle_t* g_radarShaders;
int g_radarClientNum;
void CL_InitRadar(radarClient_t* radars, qhandle_t* shaders, int clientNum)
{
g_radarClients = radars;
g_radarShaders = shaders;
g_radarClientNum = clientNum;
}
CLASS_DECLARATION( UIWidget, UIRadar, NULL )
{
@@ -30,5 +45,123 @@ CLASS_DECLARATION( UIWidget, UIRadar, NULL )
UIRadar::UIRadar()
{
m_fRadius = 32.f;
g_radarClients = NULL;
}
UIRadar::~UIRadar()
{
}
void UIRadar::Draw(void)
{
radarClient_t* radar;
float inv;
float iconSize;
int blinkTime, speakTime;
float origin[2], axis[2];
float halfScale;
int i;
if (!g_radarClients) {
return;
}
if (!cl.snap.valid) {
return;
}
if (g_radarClientNum < 0) {
return;
}
cge->CG_UpdateRadar();
radar = &g_radarClients[g_radarClientNum];
if (!radar->time) {
return;
}
if (com_radar_range && com_radar_range->value > 0) {
inv = 1.f / com_radar_range->value;
} else {
inv = 0;
}
if (cl_radar_icon_size->value > 0) {
iconSize = cl_radar_icon_size->value;
} else {
iconSize = 0;
}
axis[0] = radar->axis[0];
axis[1] = radar->axis[1];
origin[0] = radar->origin[0];
origin[1] = radar->origin[1];
blinkTime = cl_radar_blink_time->value * 1000;
speakTime = cl_radar_speak_time->value * 1000;
if (blinkTime < 100) blinkTime = 100;
halfScale = iconSize * 0.5f;
for (i = 0; i < MAX_CLIENTS; i++) {
float delta[2];
float newOrg[2];
float screenOrg[2];
float length;
radar = &g_radarClients[i];
if (i == g_radarClientNum) {
continue;
}
if (!g_radarClients[i].time) {
continue;
}
if (cl.snap.serverTime - radar->time >= 5000) {
continue;
}
if (radar->lastSpeakTime) {
int delta = cl.snap.serverTime - radar->lastSpeakTime;
// make the icon blink
if (delta >= 0 && delta < speakTime && ((delta / blinkTime) % 2) == 0) {
continue;
}
}
radar->lastSpeakTime = 0;
delta[0] = radar->origin[0] - origin[0];
delta[1] = radar->origin[1] - origin[1];
newOrg[0] = -(delta[0] * axis[0] + delta[1] * axis[1]) * inv;
newOrg[1] = (delta[0] * axis[1] + delta[1] * -axis[0]) * inv;
length = VectorLength2D(newOrg);
if (length > 1)
{
newOrg[0] = -(delta[0] * axis[0] + delta[1] * axis[1]) * inv * (1.f / length);
newOrg[1] = (delta[0] * axis[1] + delta[1] * -axis[0]) * inv * (1.f / length);
}
screenOrg[0] = -((halfScale * (1.141f * newOrg[1] + m_vVirtualScale[0])) - ((1.f + newOrg[1]) * 0.5f * m_frame.size.width));
screenOrg[1] = -((halfScale * (1.141f * newOrg[0] + m_vVirtualScale[1])) - ((1.f + newOrg[0]) * 0.5f * m_frame.size.height));
uii.Rend_DrawPicStretched2(
screenOrg[0],
screenOrg[1],
m_vVirtualScale[0] * iconSize,
m_vVirtualScale[1] * iconSize,
0,
0,
1,
1,
radar->axis[0] * axis[0] - (-radar->axis[1] * axis[1]),
radar->axis[0] * axis[1] + (-radar->axis[1] * axis[0]),
g_radarShaders[radar->teamShader]
);
}
}
+6
View File
@@ -21,6 +21,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../uilib/uiwidget.h"
#include "../cgame/cg_public.h"
class UIRadar : public UIWidget {
public:
@@ -28,7 +29,12 @@ public:
public:
UIRadar();
~UIRadar();
void Draw(void) override;
private:
float m_fRadius;
};
void CL_InitRadar(radarClient_t* radars, qhandle_t* shaders, int clientNum);
File diff suppressed because it is too large. Load diff
+3 -6
View File
@@ -20,20 +20,19 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __CL_UISERVERLIST_H__
#define __CL_UISERVERLIST_H__
#pragma once
class UIFAKKServerList : public UIListCtrl {
protected:
// need a new struct instead of gamespy
void *m_serverList;
struct GServerListImplementation *m_serverList[2];
bool m_bHasList;
bool m_bLANListing;
public:
CLASS_PROTOTYPE( UIFAKKServerList );
bool m_bGettingList;
bool m_bGettingList[2];
bool m_bUpdatingList;
protected:
@@ -54,5 +53,3 @@ public:
void Draw( void ) override;
void SortByColumn( int column ) override;
};
#endif /* __CL_UISERVERLIST_H__ */
+1233 -1162
View File
File diff suppressed because it is too large. Load diff
+71 -70
View File
@@ -20,85 +20,86 @@ 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 {
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
+82 -13
View File
@@ -30,6 +30,15 @@ CLASS_DECLARATION( UIWidget, View3D, NULL )
{ 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];
View3D::View3D()
{
// set as transparent
@@ -66,7 +75,22 @@ void View3D::DrawLetterbox
)
{
// FIXME: stub
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
@@ -75,7 +99,14 @@ void View3D::DrawFades
)
{
// FIXME: stub
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::Draw2D
@@ -200,7 +231,7 @@ void View3D::DrawProf
)
{
// FIXME: stub
// Normal empty function
}
void View3D::PrintSound
@@ -215,7 +246,7 @@ void View3D::PrintSound
)
{
// FIXME: stub
// FIXME: unimplemented
}
void View3D::DrawSoundOverlay
@@ -224,7 +255,13 @@ void View3D::DrawSoundOverlay
)
{
// FIXME: stub
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
@@ -233,7 +270,7 @@ void View3D::CenterPrint
)
{
// FIXME: stub
// FIXME: unimplemented
}
void View3D::LocationPrint
@@ -242,7 +279,7 @@ void View3D::LocationPrint
)
{
// FIXME: stub
// FIXME: unimplemented
}
void View3D::OnActivate
@@ -287,7 +324,7 @@ void View3D::DrawSubtitleOverlay
)
{
// FIXME: stub
// FIXME: unimplemented
}
void View3D::ClearCenterPrint
@@ -296,7 +333,7 @@ void View3D::ClearCenterPrint
)
{
// FIXME: stub
m_printfadetime = 0.0;
}
void View3D::UpdateCenterPrint
@@ -306,7 +343,17 @@ void View3D::UpdateCenterPrint
)
{
// FIXME: stub
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
@@ -318,7 +365,12 @@ void View3D::UpdateLocationPrint
)
{
// FIXME: stub
m_printstring = s;
m_printalpha = alpha;
m_printfadetime = 4000.0;
m_x_coord = x;
m_y_coord = y;
m_locationprint = qtrue;
}
qboolean View3D::LetterboxActive
@@ -330,13 +382,30 @@ qboolean View3D::LetterboxActive
return m_letterbox_active;
}
float avWidth = 0.0;
void View3D::InitSubtitle
(
void
)
{
// FIXME: stub
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;
}
totalWidth = 0.0;
for (char j = 'A'; j <= 'Z'; j++) {
totalWidth += m_font->getCharWidth(j);
}
avWidth = totalWidth / 26.0;
}
void View3D::FrameInitialized
@@ -370,6 +439,6 @@ void ConsoleView::Draw
)
{
// FIXME: stub
// FIXME: unimplemented
}
+7 -6
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"
@@ -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;
@@ -437,6 +436,9 @@ extern cvar_t *cl_inGameVideo;
extern cvar_t *cl_lanForcePackets;
extern cvar_t *cl_langamerefreshstatus;
extern cvar_t *cl_radar_icon_size;
extern cvar_t *cl_radar_speak_time;
extern cvar_t *cl_radar_blink_time;
extern cvar_t *cl_autoRecordDemo;
extern cvar_t *cl_r_fullscreen;
@@ -468,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);
@@ -570,6 +572,7 @@ void CL_FavoriteServers_f( void );
void CL_Ping_f( void );
void CL_SaveShot_f( void );
void CL_Dialog_f( void );
void CL_ServerRestarted( void );
qboolean CL_UpdateVisiblePings_f( int source );
@@ -686,5 +689,3 @@ void CL_InitConsoleCommands( void );
#ifdef __cplusplus
}
#endif
#endif // __CLIENT_H__
+65
View File
@@ -0,0 +1,65 @@
/*
===========================================================================
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
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
int iFlags;
char szName[64];
} soundSfx_t;
typedef struct {
qboolean bPlaying;
int iStatus;
soundSfx_t sfx;
int iEntNum;
int iEntChannel;
float vOrigin[3];
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[MAX_CHANNELS];
} soundsystemsavegame_t;
void S_ChannelFree_Callback(channel_t* v);
void S_LoadData(soundsystemsavegame_t* pSave);
void S_SaveData(soundsystemsavegame_t* pSave);
#ifdef __cplusplus
}
#endif
+65 -7
View File
@@ -1,3 +1,25 @@
/*
===========================================================================
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 "../snd_local.h"
void S_Init2()
@@ -33,7 +55,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();
@@ -61,12 +83,23 @@ 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)
{
// FIXME: unimplemented
}
/*
=================
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
}
@@ -90,11 +123,16 @@ void S_StopSound(int entnum, int channel)
S_IsSoundPlaying
=================
*/
int S_IsSoundPlaying(int channelNumber, const char* name)
qboolean S_IsSoundPlaying(int channelNumber, const char* name)
{
// FIXME: unimplemented
STUB();
return 0;
channel_t* v;
if (channelNumber >= MAX_CHANNELS) {
return qfalse;
}
v = &s_channels[channelNumber];
return v->thesfx ? qtrue : qfalse;
}
/*
@@ -379,4 +417,24 @@ void S_FadeSound(float fTime)
void S_TriggeredMusic_PlayIntroMusic() {
// FIXME: unimplemented
}
}
void callbackServer(int entnum, int channel_number, const char* name) {
if (com_sv_running->integer) {
SV_SoundCallback(entnum, channel_number, name);
}
}
void S_ChannelFree_Callback(channel_t* v) {
if (v->entnum & S_FLAG_DO_CALLBACK) {
callbackServer(v->entnum & ~S_FLAG_DO_CALLBACK, v - s_channels, v->thesfx->soundName);
}
}
void S_LoadData(soundsystemsavegame_t* pSave) {
// FIXME: unimplemented
}
void S_SaveData(soundsystemsavegame_t* pSave) {
// FIXME: unimplemented
}
+25 -2
View File
@@ -1,3 +1,25 @@
/*
===========================================================================
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
#ifdef __cplusplus
@@ -8,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();
@@ -43,10 +65,11 @@ 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);
int S_IsSoundPlaying(int channelNumber, const char* name);
qboolean S_IsSoundPlaying(int channelNumber, const char* name);
void S_UpdateEntity(int entityNum, const vec3_t origin, const vec3_t velocity, qboolean use_listener);
void S_FadeSound(float fTime);
+1 -1
View File
@@ -31,7 +31,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "snd_codec.h"
// includes for the MP3 codec
#include <mad.h>
#include "../libmad-0.15.1b/synth.h"
#define MP3_SAMPLE_WIDTH 2
#define MP3_PCMSAMPLES_PERSLICE 32
+1
View File
@@ -181,6 +181,7 @@ void S_Base_SoundList( void ) {
void S_ChannelFree(channel_t *v) {
S_ChannelFree_Callback(v);
v->thesfx = NULL;
*(channel_t **)v = freelist;
freelist = (channel_t*)v;
+3
View File
@@ -21,6 +21,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// snd_local.h -- private sound definations
#pragma once
#include "../qcommon/q_shared.h"
#include "../qcommon/qcommon.h"
@@ -275,6 +276,8 @@ qboolean S_AL_Init( soundInterface_t *si );
void S_PaintChannelFrom16_altivec( portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE], int snd_vol, channel_t *ch, const sfx_t *sc, int count, int sampleOffset, int bufferOffset );
#endif
#include "new/snd_local_new.h"
#ifdef __cplusplus
}
#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++ )
{
+11 -4
View File
@@ -16,7 +16,14 @@ set(SOURCES_SHARED
"../qcommon/str.cpp"
)
file(GLOB_RECURSE SOURCES_GAME "./*.c*" "../parser/*.c*" "../script/*.c*")
file(
GLOB_RECURSE
SOURCES_GAME
"./*.c*"
"../script/*.c*"
"../parser/generated/*.c*"
"../parser/parsetree.cpp"
)
add_library(fgame SHARED ${SOURCES_GAME})
@@ -44,13 +51,13 @@ target_compile_features(fgame PUBLIC c_variadic_macros)
target_link_libraries(fgame PUBLIC qcommon)
set_target_properties(fgame PROPERTIES PREFIX "${TARGET_PLATFORM_PREFIX}")
set_target_properties(fgame PROPERTIES OUTPUT_NAME "game${TARGET_ARCH_SUFFIX}${TARGET_CONFIG_SUFFIX}")
set_target_properties(fgame PROPERTIES OUTPUT_NAME "game${TARGET_ARCH_SUFFIX}")
set_target_properties(fgame PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TARGET_BASE_GAME}")
INSTALL(
TARGETS fgame
DESTINATION "${TARGET_BASE_GAME}"
ARCHIVE EXCLUDE_FROM_ALL
LIBRARY DESTINATION "${TARGET_BASE_GAME}"
RUNTIME DESTINATION "${TARGET_BASE_GAME}"
)
if(MSVC)
+66
View File
@@ -0,0 +1,66 @@
/*
===========================================================================
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 "DrivableVehicleTandem.h"
#include "vehicleturret.h"
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();
}
}
+37
View File
@@ -0,0 +1,37 @@
/*
===========================================================================
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 "vehicle.h"
class DrivableVehicleTandem : public DrivableVehicle {
private:
CLASS_PROTOTYPE(DrivableVehicleTandem);
public:
DrivableVehicleTandem();
~DrivableVehicleTandem();
void SpawnTurret(Event* ev) override;
void UpdateTurretSlot(int iSlot) override;
};
File diff suppressed because it is too large. Load diff
+473
View File
@@ -0,0 +1,473 @@
/*
===========================================================================
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 "entity.h"
#include "animate.h"
typedef enum {
CONTROLLER_ALLIES,
CONTROLLER_AXIS,
CONTROLLER_DRAW
} 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_ROTATE_YAW 16
#define PT_SPAWNFLAG_ROTATE_ROLL 32
#define PT_SPAWNFLAG_TARGET_PLAYER 64
#define PT_SPAWNFLAG_HIDDEN 128
void ClearProjectileTargets();
class ProjectileTarget : public Entity
{
private:
int m_iTarget;
public:
CLASS_PROTOTYPE(ProjectileTarget);
ProjectileTarget();
void EventSetId(Event *ev);
int GetTarget() const;
};
#define MAX_PROJECTILE_GENERATOR_TARGETS 16
class ProjectileGenerator : public Animate
{
protected:
int m_iId;
int m_iCycles;
float m_fMinDuration;
float m_fMaxDuration;
int m_iMinNumShots;
int m_iMaxNumShots;
float m_fMinDelay;
float m_fMaxDelay;
float m_fAccuracy;
str m_sLaunchSound;
bool m_bFireOnStartUp;
qboolean m_bIsDonut;
float m_fArcDonut;
float m_fMinDonut;
float m_fMaxDonut;
float m_fCycleTime;
float m_fShotsPerSec;
float m_fCurrentTime;
int m_iTargetIndex;
float m_fLastShotTime;
int m_iAnimSlot;
bool m_bIsTurnedOn;
int m_iCurrentCycle;
Entity *m_pTarget;
Container<ProjectileTarget *> m_projectileTargets;
Entity *m_pCurrent;
Vector m_vTargetOrg;
public:
CLASS_PROTOTYPE(ProjectileGenerator);
ProjectileGenerator();
virtual void SetupNextCycle();
virtual void BeginCycle(Event *ev);
virtual void TickCycle(Event *ev);
virtual void EndCycle(Event *ev);
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;
Entity* ChooseTarget();
void GetLocalTargets();
bool ShouldTargetPlayer() const;
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);
void EventFireOnStartUp(Event *ev);
void EventMaxNumShots(Event *ev);
void EventMinNumShots(Event *ev);
void EventCycles(Event *ev);
void EventMaxDuration(Event *ev);
void EventMinDuration(Event *ev);
void SetWeaponModel(Event *ev);
void EventSetId(Event* ev);
void EventmaxDonut(Event* ev);
void EventminDonut(Event* ev);
void EventarcDonut(Event* ev);
void EventisDonut(Event* ev);
virtual bool Attack(int count);
void Archive(Archiver& arc) override;
};
class ProjectileGenerator_Projectile : public ProjectileGenerator
{
private:
str m_sProjectileModel;
str m_sPreImpactSound;
float m_fImpactSoundTime;
float m_fImpactSoundProbability;
public:
CLASS_PROTOTYPE(ProjectileGenerator_Projectile);
ProjectileGenerator_Projectile();
void SetPreImpactSoundProbability(Event *ev);
void SetPreImpactSoundTime(Event *ev);
void SetPreImpactSound(Event *ev);
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;
};
class ProjectileGenerator_Gun : public ProjectileGenerator
{
private:
float m_fBulletRange;
float m_fBulletDamage;
int m_iBulletCount;
Vector m_vBulletSpread;
int m_iTracerFrequency;
int m_iBulletLarge;
qboolean m_bFakeBullets;
int m_iMeansOfDeath;
float m_fBulletThroughWood;
float m_fBulletThroughMetal;
float m_iBulletKnockback;
int m_iAttackCount;
float m_fFireDelay;
float m_fTracerSpeed;
public:
CLASS_PROTOTYPE(ProjectileGenerator_Gun);
ProjectileGenerator_Gun();
void SetFireDelay(Event *ev);
void SetMeansOfDeath(Event *ev);
void SetBulletThroughWood(Event *ev);
void SetBulletThroughMetal(Event *ev);
void SetBulletKnockback(Event *ev);
void SetTracerSpeed(Event *ev);
void SetBulletLarge(Event *ev);
void SetFakeBullets(Event *ev);
void SetBulletCount(Event *ev);
void SetBulletDamage(Event *ev);
void SetTracerFrequency(Event *ev);
void SetBulletSpread(Event *ev);
void SetBulletRange(Event *ev);
bool Attack(int count) override;
bool TickWeaponAnim();
void TickCycle(Event *ev) override;
void Archive(Archiver& arc) override;
};
class ProjectileGenerator_Heavy : public ProjectileGenerator
{
private:
str m_sProjectileModel;
public:
CLASS_PROTOTYPE(ProjectileGenerator_Heavy);
ProjectileGenerator_Heavy();
void SetProjectileModel(Event *ev);
bool Attack(int count) override;
void Archive(Archiver& arc) override;
};
class ThrobbingBox_Explosive : public Animate
{
protected:
str m_sUsedModel;
str m_sSound;
bool m_bUsed;
float m_fExplosionDamage;
float m_fRadius;
float m_fStopwatchDuration;
str m_sActivateSound;
str m_sTickSound;
str m_sDestroyedModel;
ScriptThreadLabel m_thread;
ScriptThreadLabel m_useThread;
str m_sEffect;
Vector m_vOffset;
public:
CLASS_PROTOTYPE(ThrobbingBox_Explosive);
ThrobbingBox_Explosive();
bool ShouldDoExplosion();
void SetExplosionOffset(Event *ev);
void SetExplosionEffect(Event *ev);
void SetTriggered(Event *ev);
void DoExplosion(Event *ev);
void SetUseThread(Event *ev);
void SetThread(Event *ev);
void SetStopWatchDuration(Event *ev);
void SetRadius(Event *ev);
void SetDamage(Event *ev);
void TickSound(Event *ev);
void ActivateSound(Event *ev);
void ExplosionSound(Event *ev);
void UsedModel(Event *ev);
void SetDestroyModel(Event *ev);
void OnBlowUp(Event *ev);
void OnUse(Event *ev);
void Archive(Archiver& arc) override;
};
class ThrobbingBox_ExplodePlayerFlak88 : public ThrobbingBox_Explosive
{
public:
CLASS_PROTOTYPE(ThrobbingBox_ExplodePlayerFlak88);
};
class ThrobbingBox_ExplodeFlak88 : public ThrobbingBox_Explosive
{
public:
CLASS_PROTOTYPE(ThrobbingBox_ExplodeFlak88);
};
class ThrobbingBox_ExplodeNebelwerfer : public ThrobbingBox_Explosive
{
public:
CLASS_PROTOTYPE(ThrobbingBox_ExplodeNebelwerfer);
};
class ThrobbingBox_ExplodePlayerNebelwerfer : public ThrobbingBox_Explosive
{
public:
CLASS_PROTOTYPE(ThrobbingBox_ExplodePlayerNebelwerfer);
};
#define TBE_SPAWNFLAG_DESTROYED_MODEL 1
#define TBE_SPAWNFLAG_MAKE_WET 2
class ThrobbingBox_Stickybomb : public ThrobbingBox_Explosive
{
private:
float m_fStopwatchStartTime;
public:
CLASS_PROTOTYPE(ThrobbingBox_Stickybomb);
void OnStickyBombWet(Event *ev);
void OnStickyBombUse(Event *ev);
void Archive(Archiver& arc) override;
};
#define OBJECTIVE_SPAWNFLAG_TURN_ON 1
class Objective : public Entity
{
private:
str m_sText;
int m_iObjectiveIndex;
public:
CLASS_PROTOTYPE(Objective);
Objective();
void Archive(Archiver &arc) override;
void TurnOn(Event *ev);
void TurnOff(Event *ev);
void Complete(Event *ev);
void SetCurrent(Event *ev);
Vector GetOrigin() const;
void SetObjectiveNbr(Event *ev);
void SetText(Event *ev);
int GetObjectiveIndex() const;
};
class FencePost : public Entity
{
public:
CLASS_PROTOTYPE(FencePost);
};
class AISpawnPoint : public SimpleArchivedEntity
{
private:
str m_sModel;
int m_iHealth;
str m_sEnemyName;
float m_iAccuracy;
int m_iAmmoGrenade;
float m_iBalconyHeight;
int m_iDisguiseLevel;
float m_fDisguisePeriod;
float m_fDisguiseRange;
float m_fEnemyShareRange;
float m_fFixedLeash;
float m_fGrenadeAwareness;
str m_sGun;
float m_fMaxNoticeTimeScale;
float m_fSoundAwareness;
str m_sTypeAttack;
str m_sTypeDisguise;
str m_sTypeGrenade;
str m_sTypeIdle;
bool m_bPatrolWaitTrigger;
float m_fHearing;
float m_fSight;
float m_fFov;
float m_fLeash;
float m_fMinDist;
float m_fMaxDist;
float m_fInterval;
bool m_bDontDropWeapons;
bool m_bDontDropHealth;
str m_sFavoriteEnemy;
bool m_bNoSurprise;
str m_sPatrolPath;
str m_sTurret;
str m_sAlarmNode;
str m_sWeapon;
str m_sTarget;
str m_sVoiceType;
bool m_bForceDropWeapon;
bool m_bForceDropHealth;
public:
CLASS_PROTOTYPE(AISpawnPoint);
AISpawnPoint();
void GetForceDropHealth(Event *ev);
void SetForceDropHealth(Event *ev);
void GetForceDropWeapon(Event *ev);
void SetForceDropWeapon(Event *ev);
void GetVoiceType(Event *ev);
void SetVoiceType(Event *ev);
void GetTarget(Event *ev);
void SetTarget(Event *ev);
void GetWeapon(Event *ev);
void SetWeapon(Event *ev);
void GetAlarmNode(Event *ev);
void SetAlarmNode(Event *ev);
void GetTurret(Event *ev);
void SetTurret(Event *ev);
void GetPatrolPath(Event *ev);
void SetPatrolPath(Event *ev);
void GetNoSurprise(Event *ev);
void SetNoSurprise(Event *ev);
void SetFavoriteEnemy(Event *ev);
void GetFavoriteEnemy(Event *ev);
void GetDontDropHealth(Event *ev);
void SetDontDropHealth(Event *ev);
void GetDontDropWeapons(Event *ev);
void SetDontDropWeapons(Event *ev);
void GetInterval(Event *ev);
void SetInterval(Event *ev);
void GetMaxDistance(Event *ev);
void SetMaxDistance(Event *ev);
void GetMinDistance(Event *ev);
void SetMinDistance(Event *ev);
void GetLeash(Event *ev);
void SetLeash(Event *ev);
void GetFov(Event *ev);
void SetFov(Event *ev);
void SetSight(Event *ev);
void GetSight(Event *ev);
void GetHearing(Event *ev);
void SetHearing(Event *ev);
void GetPatrolWaitTrigger(Event *ev);
void SetPatrolWaitTrigger(Event *ev);
void GetTypeIdle(Event *ev);
void SetTypeIdle(Event *ev);
void GetTypeGrenade(Event *ev);
void SetTypeGrenade(Event *ev);
void GetTypeDisguise(Event *ev);
void SetTypeDisguise(Event *ev);
void GetTypeAttack(Event *ev);
void SetTypeAttack(Event *ev);
void SetSoundAwareness(Event *ev);
void GetSoundAwareness(Event *ev);
void SetMaxNoticeTimeScale(Event *ev);
void GetMaxNoticeTimeScale(Event *ev);
void GetGun(Event *ev);
void SetGun(Event *ev);
void GetGrenadeAwareness(Event *ev);
void SetGrenadeAwareness(Event *ev);
void SetFixedLeash(Event *ev);
void GetFixedLeash(Event *ev);
void GetEnemyShareRange(Event *ev);
void SetEnemyShareRange(Event *ev);
void GetDisguiseRange(Event *ev);
void SetDisguiseRange(Event *ev);
void GetDisguisePeriod(Event *ev);
void SetDisguisePeriod(Event *ev);
void GetDisguiseLevel(Event *ev);
void SetDisguiseLevel(Event *ev);
void GetBalconyHeight(Event *ev);
void SetBalconyHeight(Event *ev);
void GetAmmoGrenade(Event *ev);
void SetAmmoGrenade(Event *ev);
void GetAccuracy(Event *ev);
void SetAccuracy(Event *ev);
void GetEnemyName(Event *ev);
void SetEnemyName(Event *ev);
void GetHealth(Event *ev);
void SetHealth(Event *ev);
void GetModel(Event *ev);
void SetModel(Event *ev);
void Archive(Archiver& arc) override;
};
+359
View File
@@ -0,0 +1,359 @@
/*
===========================================================================
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 "Tow_Entities.h"
#include "player.h"
#include "scriptthread.h"
TOWObjectiveMan g_TOWObjectiveMan;
TOWObjectiveMan::TOWObjectiveMan()
{
Reset();
}
void TOWObjectiveMan::Reset()
{
m_towObjectives.ClearObjectList();
m_iNumAxisObjectives = 0;
m_iNumAlliesObjectives = 0;
}
void TOWObjectiveMan::AddObjective(TOWObjective *objective)
{
if (!objective) {
return;
}
switch (objective->GetController()) {
case CONTROLLER_ALLIES:
m_iNumAlliesObjectives++;
break;
case CONTROLLER_AXIS:
m_iNumAxisObjectives++;
break;
}
m_towObjectives.AddObject(objective);
}
void TOWObjectiveMan::TakeOverObjective(eController controller, eController controllingTeam)
{
int i;
if (controllingTeam == CONTROLLER_DRAW) {
return;
}
switch (controllingTeam) {
case CONTROLLER_ALLIES:
m_iNumAlliesObjectives++;
if (m_iNumAxisObjectives) {
m_iNumAxisObjectives--;
}
dmManager.CheckEndMatch();
break;
case CONTROLLER_AXIS:
m_iNumAxisObjectives++;
if (m_iNumAlliesObjectives) {
m_iNumAlliesObjectives--;
}
dmManager.CheckEndMatch();
break;
default:
break;
}
for (i = 0; i < game.maxclients; i++) {
gentity_t *ent = &g_entities[i];
Player *player;
bool bSameTeam;
if (!ent->inuse || !ent->entity) {
continue;
}
player = static_cast<Player *>(ent->entity);
switch (controllingTeam) {
case CONTROLLER_ALLIES:
bSameTeam = player->GetTeam() == TEAM_ALLIES;
break;
case CONTROLLER_AXIS:
bSameTeam = player->GetTeam() == TEAM_AXIS;
break;
default:
break;
}
// play a different sound for the losing team
if (bSameTeam) {
player->PlayInstantMessageSound("success");
} else {
player->PlayInstantMessageSound("failure");
}
}
}
//---------------------------------------------------------------------------------------------
/*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_TakeOver
(
"TakeOver",
EV_DEFAULT,
"i",
"TeamNum",
"Sets the team controlling the objective. 0 = Axis, 1 = Allies",
EV_NORMAL
);
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
);
CLASS_DECLARATION(Objective, TOWObjective, "func_towobjective") {
{&EV_SetController, &TOWObjective::SetController },
{&EV_TakeOver, &TOWObjective::TakeOver },
{&EV_SetAxisObjNum, &TOWObjective::SetAxisObjNum },
{&EV_SetAlliesObjNum, &TOWObjective::SetAlliesObjNum},
{&EV_Initialize, &TOWObjective::OnInitialize },
{&EV_SetCurrent, &TOWObjective::SetCurrent },
{&EV_GetController, &TOWObjective::GetController },
{NULL, NULL }
};
TOWObjective::TOWObjective()
{
m_eController = CONTROLLER_DRAW;
m_eLeadingController = CONTROLLER_DRAW;
m_bNoRespawnForLeading = false;
m_iAxisObjNum = 1;
m_iAlliesObjNum = 1;
m_sAxisObjName = "default";
m_sAlliesObjName = "default";
if (spawnflags & TOWOBJECTIVE_SPAWNFLAG_NO_RESPAWN) {
m_bNoRespawnForLeading = true;
}
PostEvent(EV_Initialize, 0.001f);
}
void TOWObjective::SetController(Event *ev)
{
m_eController = static_cast<eController>(ev->GetInteger(1));
if (m_bNoRespawnForLeading) {
m_eLeadingController = m_eController;
}
if (m_eController != CONTROLLER_ALLIES && m_eController != CONTROLLER_AXIS) {
m_eController = CONTROLLER_DRAW;
}
}
void TOWObjective::GetController(Event *ev)
{
ev->AddInteger(m_eController);
}
void TOWObjective::TakeOver(Event *ev)
{
eController controller = static_cast<eController>(ev->GetInteger(1));
if (controller == m_eController || controller == CONTROLLER_DRAW) {
return;
}
switch (controller) {
case CONTROLLER_ALLIES:
gi.cvar_set(m_sAxisObjName.c_str(), "1");
gi.cvar_set(m_sAlliesObjName.c_str(), "0");
break;
case CONTROLLER_AXIS:
gi.cvar_set(m_sAxisObjName.c_str(), "0");
gi.cvar_set(m_sAlliesObjName.c_str(), "1");
break;
default:
break;
}
g_TOWObjectiveMan.TakeOverObjective(m_eController, controller);
m_eController = controller;
if (m_bNoRespawnForLeading) {
//
// Disable team respawn for the leading team
//
dmManager.StopTeamRespawn(m_eLeadingController);
}
}
void TOWObjective::SetAlliesObjNum(Event *ev)
{
m_iAlliesObjNum = ev->GetInteger(1);
}
void TOWObjective::SetAxisObjNum(Event *ev)
{
m_iAxisObjNum = ev->GetInteger(1);
}
void TOWObjective::OnInitialize(Event *ev)
{
m_sAlliesObjName = "tow_allied_obj" + str(m_iAlliesObjNum);
m_sAxisObjName = "tow_axis_obj" + str(m_iAxisObjNum);
switch (m_eController) {
case CONTROLLER_ALLIES:
gi.cvar_set(m_sAxisObjName.c_str(), "1");
gi.cvar_set(m_sAlliesObjName.c_str(), "0");
break;
case CONTROLLER_AXIS:
gi.cvar_set(m_sAxisObjName.c_str(), "0");
gi.cvar_set(m_sAlliesObjName.c_str(), "1");
break;
case CONTROLLER_DRAW:
gi.cvar_set(m_sAxisObjName.c_str(), "0");
gi.cvar_set(m_sAlliesObjName.c_str(), "0");
break;
}
if (!LoadingSavegame) {
g_TOWObjectiveMan.AddObjective(this);
}
}
void TOWObjective::SetCurrent(Event *ev)
{
eController controller = static_cast<eController>(ev->GetInteger(1));
switch (controller) {
case CONTROLLER_ALLIES:
ScriptThread::SetCurrentObjective(GetObjectiveIndex(), TEAM_ALLIES);
break;
case CONTROLLER_AXIS:
ScriptThread::SetCurrentObjective(GetObjectiveIndex(), TEAM_AXIS);
break;
default:
SetCurrent(ev);
break;
}
}
int TOWObjective::GetController() const
{
return m_eController;
}
void TOWObjective::Archive(Archiver& arc)
{
arc.ArchiveInteger(&m_iAxisObjNum);
arc.ArchiveInteger(&m_iAlliesObjNum);
ArchiveEnum(m_eController, eController);
ArchiveEnum(m_eLeadingController, eController);
arc.ArchiveBool(&m_bNoRespawnForLeading);
arc.ArchiveString(&m_sAxisObjName);
arc.ArchiveString(&m_sAlliesObjName);
}
+73
View File
@@ -0,0 +1,73 @@
/*
===========================================================================
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 "Entities.h"
#define TOWOBJECTIVE_SPAWNFLAG_NO_RESPAWN 2
class TOWObjective : public Objective
{
private:
int m_iAxisObjNum;
int m_iAlliesObjNum;
eController m_eController;
eController m_eLeadingController;
bool m_bNoRespawnForLeading;
str m_sAxisObjName;
str m_sAlliesObjName;
public:
CLASS_PROTOTYPE(TOWObjective);
TOWObjective();
void SetController(Event *ev);
void GetController(Event *ev);
void TakeOver(Event *ev);
void SetAlliesObjNum(Event *ev);
void SetAxisObjNum(Event *ev);
void OnInitialize(Event *ev);
void SetCurrent(Event *ev);
int GetController() const;
void Archive(Archiver& arc) override;
};
class TOWObjectiveMan
{
private:
Container<TOWObjective *> m_towObjectives;
int m_iNumAxisObjectives;
int m_iNumAlliesObjectives;
public:
TOWObjectiveMan();
void Reset();
void AddObjective(TOWObjective *objective);
void TakeOverObjective(eController controller, eController controllingTeam);
};
extern TOWObjectiveMan g_TOWObjectiveMan;
+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 -13876
View File
File diff suppressed because it is too large. Load diff
+2017 -1371
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
+219 -450
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,485 +24,254 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitCurious
(
GlobalFuncs_t *func
)
void Actor::InitCurious(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_Cover;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Curious;
func->IsState = &Actor::IsCuriousState;
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_Cover;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Curious;
func->IsState = &Actor::IsCuriousState;
}
void Actor::Begin_Curious
(
void
)
void Actor::SetCuriousAnimHint(int iAnimHint)
{
Vector vDelta;
//float fDistSquared;
DoForceActivate();
m_csMood = STRING_CURIOUS;
Anim_Emotion(EMOTION_CURIOUS);
if (level.inttime > level.m_iCuriousVoiceTime + 3000)
{
if (m_iCuriousAnimHint == 5)
{
Anim_Say(
STRING_ANIM_SAY_CURIOUS_SOUND_SCR,
8000,
false);
level.m_iCuriousVoiceTime = level.inttime;
}
else if (m_iCuriousAnimHint == 6)
{
Anim_Say(
STRING_ANIM_SAY_CURIOUS_SIGHT_SCR,
8000,
false);
level.m_iCuriousVoiceTime = level.inttime;
}
}
m_iCuriousTime = level.inttime;
SetLeashHome(origin);
if (m_bScriptGoalValid)
{
SetPath(
m_vScriptGoal,
"",
0,
NULL,
0.0);
ShortenPathToAvoidSquadMates();
if (!PathExists())
{
m_bScriptGoalValid = false;
}
}
TransitionState(1100, 0);
if (!m_bScriptGoalValid)
{
//check if last enemy pos is within leash area (distance to m_vHome is <= m_fLeash)
vDelta = m_vLastEnemyPos - m_vHome;
if (vDelta.lengthSquared() <= m_fLeashSquared)
{
//it's within leash area, go check it.
SetPath(m_vLastEnemyPos, NULL, 0, NULL, 0.0);
}
else
{
//it's NOT within leash area,
//am I within leash area ?
if ((origin - m_vHome).lengthSquared() <= m_fLeashSquared)
{
//I'm inside leash area,
//Try to go towards enemy as much as possible without leaving leash area.
//vDest = vHome + U * leash
//U = unit vector of vDelta.
SetPath(vDelta * sqrt(m_fLeashSquared / vDelta.lengthSquared()) + m_vHome, NULL, 0, NULL, 0.0);
}
else
{
//I'm outside leash area,
//go to enemy, it doesn't matter.
SetPath(m_vLastEnemyPos, NULL, 0, NULL, 0.0);
}
}
ShortenPathToAvoidSquadMates();
if (m_iCuriousAnimHint <= 3)
{
m_eNextAnimMode = 1;
m_csNextAnimString = STRING_ANIM_STANDFLINCH_SCR;
m_bNextForceStart = true;
m_bLockThinkState = true;
TransitionState(1101, 0);
}
else if(m_Enemy && m_PotentialEnemies.GetCurrentVisibility() < 0.1)
{
vec2_t vDel;
VectorSub2D(m_vLastEnemyPos, origin, vDel);
if (vDel[0] != 0 || vDel[1] != 0)
{
SetDesiredYawDir(vDel);
}
m_eNextAnimMode = 1;
m_csNextAnimString = STRING_ANIM_SURPRISE_SCR;
m_bNextForceStart = true;
m_bLockThinkState = true;
TransitionState(1101, 0);
}
}
m_iNextWatchStepTime = level.inttime + (rand() & 0x1FF);
m_iCuriousAnimHint = iAnimHint;
}
void Actor::End_Curious
(
void
)
void Actor::Begin_Curious(void)
{
m_iCuriousTime = 0;
m_iCuriousLevel = 0;
float fDistSquared;
Vector vDelta;
DoForceActivate();
m_csMood = STRING_CURIOUS;
Anim_Emotion(EMOTION_CURIOUS);
if (level.inttime > level.m_iCuriousVoiceTime + 3000) {
if (m_iCuriousAnimHint == 5) {
Anim_Say(STRING_ANIM_SAY_CURIOUS_SOUND_SCR, 8000, false);
level.m_iCuriousVoiceTime = level.inttime;
} else if (m_iCuriousAnimHint == 6) {
Anim_Say(STRING_ANIM_SAY_CURIOUS_SIGHT_SCR, 8000, false);
level.m_iCuriousVoiceTime = level.inttime;
}
}
m_iCuriousTime = level.inttime;
SetLeashHome(origin);
if (m_bScriptGoalValid) {
SetPath(m_vScriptGoal, NULL, 0, NULL, 0.0);
ShortenPathToAvoidSquadMates();
if (!PathExists()) {
m_bScriptGoalValid = false;
}
}
TransitionState(ACTOR_STATE_CURIOUS_BEGIN, 0);
if (!m_bScriptGoalValid) {
//check if last enemy pos is within leash area (distance to m_vHome is <= m_fLeash)
vDelta = m_vLastEnemyPos - m_vHome;
fDistSquared = vDelta.lengthSquared();
if (fDistSquared > m_fLeashSquared && (origin - m_vHome).lengthSquared() <= m_fLeashSquared) {
//I'm inside leash area,
//Try to go towards enemy as much as possible without leaving leash area.
//vDest = vHome + U * leash
//U = unit vector of vDelta.
SetPath(m_vHome + sqrt(m_fLeashSquared / fDistSquared) * vDelta, NULL, 0, NULL, 0);
ShortenPathToAvoidSquadMates();
} else {
//I'm outside leash area,
//go to enemy, it doesn't matter.
SetPath(m_vLastEnemyPos, NULL, 0, NULL, 0);
ShortenPathToAvoidSquadMates();
}
if (m_iCuriousAnimHint <= 3 && m_iCuriousAnimHint >= 1) {
StartAnimation(ANIM_MODE_NORMAL, STRING_ANIM_STANDFLINCH_SCR);
TransitionState(ACTOR_STATE_CURIOUS_RUNNING);
m_bLockThinkState = true;
} else if (m_Enemy && m_PotentialEnemies.GetCurrentVisibility() < 0.1) {
SetDesiredYawDest(m_vLastEnemyPos);
StartAnimation(ANIM_MODE_NORMAL, STRING_ANIM_SURPRISE_SCR);
TransitionState(ACTOR_STATE_CURIOUS_RUNNING);
m_bLockThinkState = true;
}
}
m_iNextWatchStepTime = level.inttime + (rand() & 0x1FF);
}
void Actor::Resume_Curious
(
void
)
void Actor::End_Curious(void)
{
Begin_Curious();
m_iCuriousTime = 0;
m_iCuriousLevel = 0;
}
void Actor::Suspend_Curious
(
void
)
void Actor::Resume_Curious(void)
{
End_Curious();
Begin_Curious();
}
void Actor::Think_Curious
(
void
)
void Actor::Suspend_Curious(void)
{
//horrible function!
if (RequireThink())
{
UpdateEyeOrigin();
NoPoint();
UpdateEnemy(100);
if(m_State == 1101)
{
ContinueAnimation();
//LABEL_16:
CheckForThinkStateTransition();
glbs.Printf("Think_Curious CheckForThinkStateTransition 1\n");
PostThink(true);
return;
}
m_bLockThinkState = false;
if (!PathExists() || PathComplete())
{
//v1 = &this->baseSimpleActor.baseSentient.m_Enemy;
//goto LABEL_6;
ClearPath();
Anim_Stand();
LookAtCuriosity();
if (!m_Enemy || EnemyIsDisguised())
{
if (level.inttime > m_iCuriousTime + 500)
{
glbs.Printf("Think_Curious m_Enemy: %s EnemyIsDisguised: %s\n", m_Enemy ? "true": "false", EnemyIsDisguised() ? "true" : "false");
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
m_iCuriousTime = 0;
}
}
CheckForThinkStateTransition();
glbs.Printf("Think_Curious CheckForThinkStateTransition 2\n");
PostThink(true);
return;
}
if (m_Enemy || CanSeeEnemy(100))
{
ClearPath();
Anim_Stand();
LookAtCuriosity();
if (!m_Enemy || EnemyIsDisguised())
{
if (level.inttime > m_iCuriousTime + 500)
{
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
m_iCuriousTime = 0;
}
}
CheckForThinkStateTransition();
glbs.Printf("Think_Curious CheckForThinkStateTransition 3\n");
PostThink(true);
return;
}
else
{
if (m_iCuriousLevel <= 5)
{
if (!InFOV(m_vLastEnemyPos, m_fFov, m_fFovDot))
{
if ((m_bScriptGoalValid || CanMovePathWithLeash())
&& MoveOnPathWithSquad())
{
if (PatrolNextNodeExists())
{
m_eNextAnimMode = 2;
}
else
{
//v11 = SimpleActor::GetRunAnim(this);
m_eNextAnimMode = 3;
}
m_csNextAnimString = GetRunAnim();
m_bNextForceStart = false;
FaceMotion();
}
else
{
Anim_Stand();
}
if (level.inttime >= m_iNextWatchStepTime
&& velocity.lengthSquared() >= 4.0)
{
SetDesiredLookDir(velocity);
m_iNextWatchStepTime = level.inttime + (rand() & 0x1FF) + 500;
}
else
{
LookAtCuriosity();
}
CheckForThinkStateTransition();
glbs.Printf("Think_Curious CheckForThinkStateTransition 4\n");
PostThink(true);
return;
}
else
{
Vector vEnd = EyePosition() - m_vLastEnemyPos;
VectorNormalizeFast(vEnd);
vEnd += m_vLastEnemyPos;
if (!G_SightTrace(EyePosition(), vec_zero, vec_zero, vEnd, this, NULL, 33819417, qfalse, "Actor::Think_Curious"))
{
if ((m_bScriptGoalValid || CanMovePathWithLeash())
&& MoveOnPathWithSquad())
{
if (PatrolNextNodeExists())
{
m_eNextAnimMode = 2;
}
else
{
//v11 = SimpleActor::GetRunAnim(this);
m_eNextAnimMode = 3;
}
m_csNextAnimString = GetRunAnim();
m_bNextForceStart = false;
FaceMotion();
}
else
{
Anim_Stand();
}
if (level.inttime >= m_iNextWatchStepTime
&& velocity.lengthSquared() >= 4.0)
{
SetDesiredLookDir(velocity);
m_iNextWatchStepTime = level.inttime + (rand() & 0x1FF) + 500;
}
else
{
LookAtCuriosity();
}
CheckForThinkStateTransition();
glbs.Printf("Think_Curious CheckForThinkStateTransition 5\n");
PostThink(true);
return;
}
else
{
ClearPath();
Anim_Stand();
LookAtCuriosity();
if (!m_Enemy || EnemyIsDisguised())
{
if (level.inttime > m_iCuriousTime + 500)
{
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
m_iCuriousTime = 0;
}
}
CheckForThinkStateTransition();
glbs.Printf("Think_Curious CheckForThinkStateTransition 6\n");
PostThink(true);
return;
}
}
}
else
{
if ((PathGoal()-origin).lengthSquared() >= 2304)
{
if ((m_bScriptGoalValid || CanMovePathWithLeash())
&& MoveOnPathWithSquad())
{
if (PatrolNextNodeExists())
{
m_eNextAnimMode = 2;
}
else
{
//v11 = SimpleActor::GetRunAnim(this);
m_eNextAnimMode = 3;
}
m_csNextAnimString = GetRunAnim();
m_bNextForceStart = false;
FaceMotion();
}
else
{
Anim_Stand();
}
if (level.inttime >= m_iNextWatchStepTime
&& velocity.lengthSquared() >= 4.0)
{
SetDesiredLookDir(velocity);
m_iNextWatchStepTime = level.inttime + (rand() & 0x1FF) + 500;
}
else
{
LookAtCuriosity();
}
CheckForThinkStateTransition();
glbs.Printf("Think_Curious CheckForThinkStateTransition 7\n");
PostThink(true);
return;
}
}
ClearPath();
Anim_Stand();
LookAtCuriosity();
if (!m_Enemy || EnemyIsDisguised())
{
if (level.inttime > m_iCuriousTime + 500)
{
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
m_iCuriousTime = 0;
}
}
CheckForThinkStateTransition();
glbs.Printf("Think_Curious CheckForThinkStateTransition 8\n");
PostThink(true);
return;
}
}
End_Curious();
}
void Actor::FinishedAnimation_Curious
(
void
)
void Actor::Think_Curious(void)
{
FinishedAnimation_AnimCurious();
if (!RequireThink()) {
return;
}
UpdateEyeOrigin();
NoPoint();
UpdateEnemy(100);
if (m_State == ACTOR_STATE_CURIOUS_RUNNING) {
ContinueAnimation();
CheckForThinkStateTransition();
PostThink(true);
return;
}
m_bLockThinkState = false;
if (!PathExists() || PathComplete()) {
ClearPath();
Anim_Stand();
LookAtCuriosity();
TimeOutCurious();
CheckForThinkStateTransition();
PostThink(true);
return;
}
if (m_Enemy && CanSeeEnemy(100)) {
ClearPath();
Anim_Stand();
LookAtCuriosity();
TimeOutCurious();
CheckForThinkStateTransition();
PostThink(true);
return;
}
if (m_iCuriousLevel <= 5) {
if (InFOV(m_vLastEnemyPos, m_fFov, m_fFovDot)) {
Vector vEnd;
vEnd = EyePosition() - m_vLastEnemyPos;
vEnd.normalizefast();
vEnd += m_vLastEnemyPos;
if (G_SightTrace(
EyePosition(), vec_zero, vec_zero, vEnd, this, NULL, MASK_CANSEE, qfalse, "Actor::Think_Curious"
)) {
ClearPath();
Anim_Stand();
LookAtCuriosity();
TimeOutCurious();
CheckForThinkStateTransition();
PostThink(true);
return;
}
}
} else if ((PathGoal() - origin).lengthSquared() < Square(48)) {
ClearPath();
Anim_Stand();
LookAtCuriosity();
TimeOutCurious();
CheckForThinkStateTransition();
PostThink(true);
return;
}
if ((m_bScriptGoalValid || CanMovePathWithLeash()) && MoveOnPathWithSquad()) {
if (PatrolNextNodeExists()) {
DesiredAnimation(ANIM_MODE_PATH, GetRunAnim());
} else {
DesiredAnimation(ANIM_MODE_PATH_GOAL, GetRunAnim());
}
FaceMotion();
} else {
Anim_Stand();
}
if (level.inttime >= m_iNextWatchStepTime && velocity.lengthSquared() >= Square(2)) {
SetDesiredLookDir(velocity);
m_iNextWatchStepTime = level.inttime + (rand() & 0x1FF) + 500;
} else {
LookAtCuriosity();
}
CheckForThinkStateTransition();
PostThink(true);
}
void Actor::LookAtCuriosity
(
void
)
void Actor::LookAtCuriosity(void)
{
Vector vAngles;
float fLookScale;
unsigned int iSeed;
if (m_Enemy && EnemyIsDisguised())
{
SetDesiredLookDir(m_Enemy->origin - origin);
fLookScale = 0.25;
}
else
{
vAngles = m_vLastEnemyPos - origin;
if (vAngles.x < 15.0 && vAngles.x > -15.0 && vAngles.y < 15.0 && vAngles.y > -15.0)
{
SetDesiredLookAnglesRelative(vec_zero);
}
else
{
SetDesiredLookDir(vAngles);
if (velocity.x == 0.0
&& velocity.y == 0.0)
{
SetDesiredYawDir(vAngles);
}
else
{
FaceMotion();
}
}
fLookScale = 1;
}
//FIXME: wth is this ! @_@
iSeed = 1664525 * (-783751945 * ((level.inttime - m_iCuriousTime) & 0xFFFFFF00) + m_iCuriousTime);
unsigned int iSeed;
float fLookScale;
vec3_t vAngles;
vAngles.x = fLookScale * ((1664525 * (iSeed + 1013904223) + 1013904223) * 0.000000013969839) + m_DesiredLookAngles[0];
vAngles.y = (iSeed + 1013904223) * 0.000000027939677 * fLookScale + m_DesiredLookAngles[1];
vAngles.z = m_DesiredLookAngles[2];
if (m_Enemy && !EnemyIsDisguised()) {
SetDesiredLookDir(m_Enemy->origin - origin);
fLookScale = 0.25;
} else {
Vector v;
if (vAngles.x >= -90.0)
{
if (vAngles.x > 90.0)
vAngles.x = 90.0;
}
else
{
vAngles.x = -90.0;
}
v = m_vLastEnemyPos - origin;
if (v[0] < 15 && v[0] > -15 && v[1] < 15 && v[1] > -15) {
SetDesiredLookAnglesRelative(vec_zero);
} else {
SetDesiredLookDir(v);
if (velocity.x || velocity.y) {
FaceMotion();
} else {
SetDesiredYawDir(v);
}
}
fLookScale = 1;
}
SetDesiredLookAnglesRelative(vAngles);
iSeed = 0x19660D * (m_iCuriousTime - 0x2EB71B09 * ((level.inttime - m_iCuriousTime) & 0xFFFFFF00)) + 0x3C6EF35F;
vAngles[0] = m_DesiredLookAngles[0] + (float)iSeed / 0x4444444 * fLookScale;
vAngles[1] = m_DesiredLookAngles[1] + (float)iSeed / 0x2222222 * fLookScale;
vAngles[2] = m_DesiredLookAngles[2];
// clamp
vAngles[0] = Q_clamp_float(vAngles[0], -90, 90);
SetDesiredLookAnglesRelative(vAngles);
}
void Actor::TimeOutCurious
(
void
)
void Actor::TimeOutCurious(void)
{
//FIXME: macros
if (!m_Enemy || EnemyIsDisguised())
{
if (level.inttime > m_iCuriousTime + 500)
{
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
m_iCuriousTime = 0;
}
}
if (m_Enemy && !EnemyIsDisguised()) {
return;
}
if (level.inttime <= m_iCuriousTime + 500) {
return;
}
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE);
m_iCuriousTime = 0;
}
void Actor::SetCuriousAnimHint
(
int iAnimHint
)
void Actor::FinishedAnimation_Curious(void)
{
m_iCuriousAnimHint = iAnimHint;
if (m_State == ACTOR_STATE_CURIOUS_RUNNING) {
TransitionState(ACTOR_STATE_CURIOUS_BEGIN, 0);
}
}
+78 -137
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,174 +24,115 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitDisguiseNone
(
GlobalFuncs_t *func
)
void Actor::InitDisguiseNone(GlobalFuncs_t *func)
{
func->IsState = &Actor::IsDisguiseState;
func->IsState = &Actor::IsDisguiseState;
}
void Actor::State_Disguise_Wait
(
void
)
void Actor::State_Disguise_Wait(void)
{
vec2_t vDelta;
float fDistSquared;
VectorSub2D(origin, m_Enemy->origin, vDelta);
float fDistSquared;
vec2_t vDelta;
m_eNextAnimMode = 1;
m_csNextAnimString = STRING_ANIM_DISGUISE_WAIT_SCR;
m_bNextForceStart = false;
VectorSub2D(origin, m_Enemy->origin, vDelta);
fDistSquared = VectorLength2DSquared(vDelta);
fDistSquared = VectorLength2DSquared(vDelta);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_WAIT_SCR);
if (m_fMaxDisguiseDistSquared > fDistSquared * 4)
{
TransitionState(1, 0);
}
else
{
if (level.inttime > m_iStateTime + 3000)
{
if (fDistSquared <= 65536)
{
TransitionState(1, 0);
}
else
{
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
}
}
}
if (fDistSquared * 4 < m_fMaxDisguiseDistSquared) {
TransitionState(ACTOR_STATE_DISGUISE_PAPERS);
return;
}
if (level.inttime <= m_iStateTime + 3000) {
return;
}
if (fDistSquared > Square(256)) {
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE);
} else {
TransitionState(ACTOR_STATE_DISGUISE_PAPERS);
}
}
void Actor::State_Disguise_Papers
(
void
)
void Actor::State_Disguise_Papers(void)
{
vec2_t vDelta;
vec2_t vDelta;
m_csNextAnimString = STRING_ANIM_DISGUISE_PAPERS_SCR;
m_eNextAnimMode = 1;
m_bNextForceStart = false;
if (m_iEnemyShowPapersTime < m_Enemy->m_ShowPapersTime)
{
if (level.m_iPapersLevel < m_iDisguiseLevel)
{
m_State = 5;
}
else
{
if (m_DisguiseAcceptThread.IsSet())
m_DisguiseAcceptThread.Execute(this);
TransitionState(2, 0);
}
}
else
{
if (level.inttime > m_iStateTime + 12000)
{
TransitionState(3, 0);
}
else
{
VectorSub2D(origin, m_Enemy->origin, vDelta);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_PAPERS_SCR);
if (VectorLength2DSquared(vDelta) > 65536)
{
TransitionState(4, 0);
}
}
}
if (m_iEnemyShowPapersTime >= m_Enemy->m_ShowPapersTime) {
if (level.inttime > m_iStateTime + 12000) {
TransitionState(ACTOR_STATE_DISGUISE_ENEMY);
} else {
VectorSub2D(origin, m_Enemy->origin, vDelta);
if (VectorLength2DSquared(vDelta) > Square(256)) {
TransitionState(ACTOR_STATE_DISGUISE_HALT, 0);
}
}
} else if (level.m_iPapersLevel < m_iDisguiseLevel) {
TransitionState(ACTOR_STATE_DISGUISE_DENY);
} else {
if (m_DisguiseAcceptThread.IsSet()) {
m_DisguiseAcceptThread.Execute(this);
}
TransitionState(ACTOR_STATE_DISGUISE_ACCEPT);
}
}
void Actor::State_Disguise_Fake_Papers
(
void
)
void Actor::State_Disguise_Fake_Papers(void)
{
vec2_t vDelta;
vec2_t vDelta;
m_csNextAnimString = STRING_ANIM_DISGUISE_PAPERS_SCR;
m_eNextAnimMode = 1;
m_bNextForceStart = false;
if (m_iEnemyShowPapersTime < m_Enemy->m_ShowPapersTime || level.inttime > m_iStateTime + 12000)
{
TransitionState(3, 0);
}
else
{
VectorSub2D(origin, m_Enemy->origin, vDelta);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_PAPERS_SCR);
if (VectorLength2DSquared(vDelta) > 65536)
{
TransitionState(4, 0);
}
}
if (m_iEnemyShowPapersTime < m_Enemy->m_ShowPapersTime || level.inttime > m_iStateTime + 12000) {
TransitionState(ACTOR_STATE_DISGUISE_ENEMY);
return;
}
VectorSub2D(origin, m_Enemy->origin, vDelta);
if (VectorLength2DSquared(vDelta) > Square(256)) {
TransitionState(ACTOR_STATE_DISGUISE_HALT, 0);
}
}
void Actor::State_Disguise_Enemy
(
void
)
void Actor::State_Disguise_Enemy(void)
{
m_eNextAnimMode = 1;
m_csNextAnimString = STRING_ANIM_DISGUISE_ENEMY_SCR;
m_bNextForceStart = false;
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_ENEMY_SCR);
if (level.inttime > m_iStateTime + 3000 && !m_Enemy->IsSubclassOfActor())
{
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL);
}
if (level.inttime > m_iStateTime + 3000 && !(m_Enemy->flags & FL_NOTARGET)) {
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE);
}
}
void Actor::State_Disguise_Halt
(
void
)
void Actor::State_Disguise_Halt(void)
{
m_eNextAnimMode = 1;
m_csNextAnimString = STRING_ANIM_DISGUISE_HALT_SCR;
m_bNextForceStart = false;
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_HALT_SCR);
if (level.inttime > m_iStateTime + 1500 && !m_Enemy->IsSubclassOfActor())
{
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL);
}
if (level.inttime > m_iStateTime + 1500 && !(m_Enemy->flags & FL_NOTARGET)) {
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE);
}
}
void Actor::State_Disguise_Accept
(
void
)
void Actor::State_Disguise_Accept(void)
{
m_eNextAnimMode = 1;
m_csNextAnimString = STRING_ANIM_DISGUISE_ACCEPT_SCR;
m_bNextForceStart = false;
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_ACCEPT_SCR);
if (level.inttime > m_iStateTime + 3000 )
{
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
SetThink(THINKSTATE_DISGUISE, THINK_DISGUISE_SALUTE);
}
if (level.inttime > m_iStateTime + 3000) {
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE);
SetThink(THINKSTATE_DISGUISE, THINK_DISGUISE_SALUTE);
}
}
void Actor::State_Disguise_Deny
(
void
)
void Actor::State_Disguise_Deny(void)
{
m_eNextAnimMode = 1;
m_csNextAnimString = STRING_ANIM_DISGUISE_DENY_SCR;
m_bNextForceStart = false;
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_DENY_SCR);
if (level.inttime > m_iStateTime + 3000)
{
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
}
if (level.inttime > m_iStateTime + 3000) {
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE);
}
}
+135
View File
@@ -0,0 +1,135 @@
/*
===========================================================================
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_disguise_officier.cpp
#include "actor.h"
void Actor::InitDisguiseOfficer(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_DisguiseOfficer;
func->BeginState = &Actor::Begin_DisguiseOfficer;
func->EndState = &Actor::End_DisguiseOfficer;
func->ResumeState = &Actor::Resume_DisguiseOfficer;
func->SuspendState = &Actor::Suspend_DisguiseOfficer;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Disguise;
func->IsState = &Actor::IsDisguiseState;
}
void Actor::Begin_DisguiseOfficer(void)
{
m_csMood = STRING_BORED;
assert(m_Enemy);
if (!m_Enemy) {
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE);
return;
}
if ((EnemyIsDisguised() || (m_Enemy->flags & FL_NOTARGET)) && level.m_bAlarm != qtrue) {
SetDesiredYawDest(m_Enemy->origin);
SetDesiredLookDir(m_Enemy->origin - origin);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_PAPERS_SCR);
m_iEnemyShowPapersTime = m_Enemy->m_ShowPapersTime;
TransitionState(ACTOR_STATE_DISGUISE_PAPERS);
} else {
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE);
}
}
void Actor::End_DisguiseOfficer(void)
{
m_iNextDisguiseTime = level.inttime + (m_State ? m_iDisguisePeriod : 500);
}
void Actor::Resume_DisguiseOfficer(void)
{
Begin_DisguiseOfficer();
}
void Actor::Suspend_DisguiseOfficer(void)
{
End_DisguiseOfficer();
}
void Actor::Think_DisguiseOfficer(void)
{
if (!RequireThink()) {
return;
}
UpdateEyeOrigin();
NoPoint();
ContinueAnimation();
UpdateEnemy(1500);
assert(m_Enemy);
if (!m_Enemy) {
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE);
return;
}
if (!EnemyIsDisguised() && !(m_Enemy->flags & FL_NOTARGET) && m_State != ACTOR_STATE_DISGUISE_ENEMY) {
TransitionState(ACTOR_STATE_DISGUISE_ENEMY, 0);
}
if (level.m_bAlarm == qtrue) {
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE);
return;
}
SetDesiredYawDest(m_Enemy->origin);
SetDesiredLookDir(m_Enemy->origin - origin);
switch (m_State) {
case ACTOR_STATE_DISGUISE_ENEMY:
m_pszDebugState = "enemy";
State_Disguise_Enemy();
break;
case ACTOR_STATE_DISGUISE_HALT:
m_pszDebugState = "halt";
State_Disguise_Halt();
break;
case ACTOR_STATE_DISGUISE_PAPERS:
m_pszDebugState = "papers";
State_Disguise_Fake_Papers();
break;
default:
{
Com_Printf("Actor::Think_DisguiseOfficer: invalid think state %i\n", m_State);
char assertStr[16317] = {0};
strcpy(assertStr, "\"invalid think state\"\n\tMessage: ");
Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("thinkstate = %i", m_State));
assert(!assertStr);
}
break;
}
if (!CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE)) {
CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE);
}
PostThink(true);
}
-184
View File
@@ -1,184 +0,0 @@
/*
===========================================================================
Copyright (C) 2015 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_disguise_officier.cpp
#include "actor.h"
void Actor::InitDisguiseOfficer
(
GlobalFuncs_t *func
)
{
func->ThinkState = &Actor::Think_DisguiseOfficer;
func->BeginState = &Actor::Begin_DisguiseOfficer;
func->EndState = &Actor::End_DisguiseOfficer;
func->ResumeState = &Actor::Resume_DisguiseOfficer;
func->SuspendState = &Actor::Suspend_DisguiseOfficer;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Disguise;
func->IsState = &Actor::IsDisguiseState;
}
void Actor::Begin_DisguiseOfficer
(
void
)
{
vec2_t vDelta;
m_csMood = STRING_BORED;
assert(m_Enemy);
if (m_Enemy)
{
if ( (EnemyIsDisguised() || m_Enemy->IsSubclassOfActor()) && !level.m_bAlarm)
{
VectorSub2D(m_Enemy->origin, origin, vDelta);
if (vDelta[0] != 0 || vDelta[1] != 0)
{
SetDesiredYawDir(vDelta);
}
SetDesiredLookDir(m_Enemy->origin - origin);
m_eNextAnimMode = 1;
m_csNextAnimString = STRING_ANIM_DISGUISE_PAPERS_SCR;
m_bNextForceStart = false;
m_iEnemyShowPapersTime = m_Enemy->m_ShowPapersTime;
TransitionState(1, 0);
}
else
{
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL);
}
}
else
{
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
}
}
void Actor::End_DisguiseOfficer
(
void
)
{
m_iNextDisguiseTime = level.inttime + (m_State ? m_iDisguisePeriod : 500);
}
void Actor::Resume_DisguiseOfficer
(
void
)
{
Begin_DisguiseOfficer();
}
void Actor::Suspend_DisguiseOfficer
(
void
)
{
End_DisguiseOfficer();
}
void Actor::Think_DisguiseOfficer
(
void
)
{
if (RequireThink())
{
UpdateEyeOrigin();
NoPoint();
ContinueAnimation();
UpdateEnemy(1500);
assert(m_Enemy);
if (!m_Enemy)
{
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
return;
}
if (!EnemyIsDisguised() && !(m_Enemy->IsSubclassOfActor()) && m_State != 3)
{
TransitionState(3, 0);
}
if (level.m_bAlarm)
{
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL);
return;
}
vec2_t vDelta;
VectorSub2D(m_Enemy->origin, origin, vDelta);
if (vDelta[0] != 0 || vDelta[1] != 0)
{
SetDesiredYawDir(vDelta);
}
SetDesiredLookDir(m_Enemy->origin - origin);
if (m_State == 3)
{
m_pszDebugState = "enemy";
State_Disguise_Enemy();
}
else if (m_State > 3)
{
if (m_State != 4)
{
Com_Printf("Actor::Think_DisguiseOfficer: invalid think state %i\n", m_State);
char assertStr[16317] = { 0 };
strcpy(assertStr, "\"invalid think state\"\n\tMessage: ");
Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("thinkstate = %i", m_State));
assert(!assertStr);
}
else
{
m_pszDebugState = "halt";
Actor::State_Disguise_Halt();
}
}
else
{
if (m_State == 1)
{
m_pszDebugState = "papers";
State_Disguise_Fake_Papers();
}
else
{
char assertStr[16317] = { 0 };
strcpy(assertStr, "\"invalid think state\"\n\tMessage: ");
Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("thinkstate = %i", m_State));
assert(!assertStr);
}
}
CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_NORMAL);
PostThink(true);
}
}
+86 -133
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,163 +24,116 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitDisguiseRover
(
GlobalFuncs_t *func
)
void Actor::InitDisguiseRover(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_DisguiseRover;
func->BeginState = &Actor::Begin_DisguiseRover;
func->EndState = &Actor::End_DisguiseRover;
func->ResumeState = &Actor::Resume_DisguiseRover;
func->SuspendState = &Actor::Suspend_DisguiseRover;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Disguise;
func->IsState = &Actor::IsDisguiseState;
func->ThinkState = &Actor::Think_DisguiseRover;
func->BeginState = &Actor::Begin_DisguiseRover;
func->EndState = &Actor::End_DisguiseRover;
func->ResumeState = &Actor::Resume_DisguiseRover;
func->SuspendState = &Actor::Suspend_DisguiseRover;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Disguise;
func->IsState = &Actor::IsDisguiseState;
}
void Actor::Begin_DisguiseRover
(
void
)
void Actor::Begin_DisguiseRover(void)
{
m_csMood = STRING_BORED;
assert(m_Enemy);
vec2_t vDelta;
m_csMood = STRING_BORED;
assert(m_Enemy);
if (!m_Enemy) {
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE);
return;
}
if (m_Enemy)
{
if ((EnemyIsDisguised() || m_Enemy->IsSubclassOfActor()) && !level.m_bAlarm)
{
VectorSub2D(m_Enemy->origin, origin, vDelta);
if ((EnemyIsDisguised() || (m_Enemy->flags & FL_NOTARGET)) && level.m_bAlarm != qtrue) {
SetDesiredYawDest(m_Enemy->origin);
SetDesiredLookDir(m_Enemy->origin - origin);
if (vDelta[0] != 0 || vDelta[1] != 0)
{
SetDesiredYawDir(vDelta);
}
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_PAPERS_SCR);
m_iEnemyShowPapersTime = m_Enemy->m_ShowPapersTime;
SetDesiredLookDir(m_Enemy->origin - origin);
m_eNextAnimMode = 1;
m_csNextAnimString = STRING_ANIM_DISGUISE_PAPERS_SCR;
m_bNextForceStart = false;
m_iEnemyShowPapersTime = m_Enemy->m_ShowPapersTime;
TransitionState(1, 0);
}
else
{
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL);
}
}
else
{
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
}
TransitionState(ACTOR_STATE_DISGUISE_PAPERS);
} else {
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE);
}
}
void Actor::End_DisguiseRover
(
void
)
void Actor::End_DisguiseRover(void)
{
m_iNextDisguiseTime = level.inttime + (m_State ? m_iDisguisePeriod : 500);
m_iNextDisguiseTime = level.inttime + (m_State ? m_iDisguisePeriod : 500);
}
void Actor::Resume_DisguiseRover
(
void
)
void Actor::Resume_DisguiseRover(void)
{
Begin_DisguiseRover();
Begin_DisguiseRover();
}
void Actor::Suspend_DisguiseRover
(
void
)
void Actor::Suspend_DisguiseRover(void)
{
End_DisguiseRover();
End_DisguiseRover();
}
void Actor::Think_DisguiseRover
(
void
)
void Actor::Think_DisguiseRover(void)
{
if (!RequireThink())
{
return;
}
UpdateEyeOrigin();
NoPoint();
ContinueAnimation();
UpdateEnemy(1500);
if (!RequireThink()) {
return;
}
assert(m_Enemy != NULL);
UpdateEyeOrigin();
NoPoint();
ContinueAnimation();
UpdateEnemy(1500);
if (!m_Enemy)
{
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
return;
}
assert(m_Enemy);
if (!EnemyIsDisguised() && !m_Enemy->IsSubclassOfActor() && m_State != 3)
{
TransitionState(3, 0);
}
if (!m_Enemy) {
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE);
return;
}
if (level.m_bAlarm)
{
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL);
return;
}
{
vec2_t facedir;
facedir[0] = m_Enemy->origin[0] - origin[0];
facedir[1] = m_Enemy->origin[1] - origin[1];
if (facedir[0] != 0 || facedir[1] != 0)
{
SetDesiredYawDir(facedir);
}
if (!EnemyIsDisguised() && !(m_Enemy->flags & FL_NOTARGET) && m_State != ACTOR_STATE_DISGUISE_ENEMY) {
TransitionState(ACTOR_STATE_DISGUISE_ENEMY, 0);
}
}
SetDesiredLookDir(m_Enemy->origin - origin);
if (level.m_bAlarm == qtrue) {
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE);
return;
}
if (m_State == 2)
{
m_pszDebugState = "accept";
State_Disguise_Accept();
}
else if(m_State > 2)
{
if (m_State == 3)
{
m_pszDebugState = "enemy";
State_Disguise_Enemy();
}
else if (m_State == 4)
{
m_pszDebugState = "halt";
State_Disguise_Halt();
}
else
{
assert(!"invalid think state");
}
}
else if (m_State == 1)
{
m_pszDebugState = "papers";
State_Disguise_Papers();
}
else
{
assert(!"invalid think state");
}
SetDesiredYawDest(m_Enemy->origin);
SetDesiredLookDir(m_Enemy->origin - origin);
CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_NORMAL);
PostThink(true);
switch (m_State) {
case ACTOR_STATE_DISGUISE_ACCEPT:
m_pszDebugState = "accept";
State_Disguise_Accept();
break;
case ACTOR_STATE_DISGUISE_ENEMY:
m_pszDebugState = "enemy";
State_Disguise_Enemy();
break;
case ACTOR_STATE_DISGUISE_HALT:
m_pszDebugState = "halt";
State_Disguise_Halt();
break;
case ACTOR_STATE_DISGUISE_PAPERS:
m_pszDebugState = "papers";
State_Disguise_Fake_Papers();
break;
default:
{
Com_Printf("Actor::Think_DisguiseOfficer: invalid think state %i\n", m_State);
char assertStr[16317] = {0};
strcpy(assertStr, "\"invalid think state\"\n\tMessage: ");
Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("thinkstate = %i", m_State));
assert(!assertStr);
}
break;
}
if (!CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE)) {
CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE);
}
PostThink(true);
}
+49 -103
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,133 +24,79 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitDisguiseSalute
(
GlobalFuncs_t *func
)
void Actor::InitDisguiseSalute(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_DisguiseSalute;
func->BeginState = &Actor::Begin_DisguiseSalute;
func->EndState = &Actor::End_DisguiseSalute;
func->ResumeState = &Actor::Resume_DisguiseSalute;
func->SuspendState = &Actor::Suspend_DisguiseSalute;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Disguise;
func->IsState = &Actor::IsDisguiseState;
func->ThinkState = &Actor::Think_DisguiseSalute;
func->BeginState = &Actor::Begin_DisguiseSalute;
func->EndState = &Actor::End_DisguiseSalute;
func->ResumeState = &Actor::Resume_DisguiseSalute;
func->SuspendState = &Actor::Suspend_DisguiseSalute;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Disguise;
func->IsState = &Actor::IsDisguiseState;
}
void Actor::Begin_DisguiseSalute
(
void
)
void Actor::Begin_DisguiseSalute(void)
{
vec2_t vDelta;
Com_Printf("Saluting guy....\n");
m_csMood = STRING_BORED;
assert(m_Enemy);
Com_Printf("Saluting guy....\n");
m_csMood = STRING_BORED;
assert(m_Enemy);
if (m_Enemy)
{
if ((EnemyIsDisguised() || m_Enemy->IsSubclassOfActor()) && !level.m_bAlarm)
{
VectorSub2D(m_Enemy->origin, origin, vDelta);
if (!m_Enemy) {
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE);
return;
}
if (vDelta[0] != 0 || vDelta[1] != 0)
{
SetDesiredYawDir(vDelta);
}
if ((EnemyIsDisguised() || (m_Enemy->flags & FL_NOTARGET)) && level.m_bAlarm != qtrue) {
SetDesiredYawDest(m_Enemy->origin);
SetDesiredLookDir(m_Enemy->origin - origin);
SetDesiredLookDir(m_Enemy->origin - origin);
m_eNextAnimMode = 1;
m_csNextAnimString = STRING_ANIM_DISGUISE_SALUTE_SCR;
m_bNextForceStart = false;
m_iEnemyShowPapersTime = m_Enemy->m_ShowPapersTime;
TransitionState(1, 0);
}
else
{
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL);
}
}
else
{
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
}
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_PAPERS_SCR);
} else {
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE);
}
}
void Actor::End_DisguiseSalute
(
void
)
void Actor::End_DisguiseSalute(void)
{
m_iNextDisguiseTime = level.inttime + m_iDisguisePeriod;
m_iNextDisguiseTime = level.inttime + m_iDisguisePeriod;
}
void Actor::Resume_DisguiseSalute
(
void
)
void Actor::Resume_DisguiseSalute(void)
{
Begin_DisguiseSalute();
Begin_DisguiseSalute();
}
void Actor::Suspend_DisguiseSalute
(
void
)
void Actor::Suspend_DisguiseSalute(void)
{
End_DisguiseSalute();
End_DisguiseSalute();
}
void Actor::Think_DisguiseSalute
(
void
)
void Actor::Think_DisguiseSalute(void)
{
NoPoint();
ContinueAnimation();
UpdateEnemy(2000);
NoPoint();
ContinueAnimation();
UpdateEnemy(2000);
assert(m_Enemy != NULL);
assert(m_Enemy != NULL);
if (m_Enemy)
{
if (!EnemyIsDisguised() && !m_Enemy->IsSubclassOfActor() && level.m_bAlarm)
{
{
vec2_t facedir;
facedir[0] = m_Enemy->origin[0] - origin[0];
facedir[1] = m_Enemy->origin[1] - origin[1];
if (facedir[0] != 0 || facedir[1] != 0)
{
SetDesiredYawDir(facedir);
}
if (!m_Enemy) {
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE);
return;
}
}
SetDesiredLookDir(m_Enemy->origin - origin);
if ((!EnemyIsDisguised() && !(m_Enemy->flags & FL_NOTARGET)) || level.m_bAlarm != qtrue) {
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE);
return;
}
PostThink(true);
}
else
{
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL);
}
}
else
{
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
}
SetDesiredYawDest(m_Enemy->origin);
SetDesiredLookDir(m_Enemy->origin - origin);
PostThink(true);
}
void Actor::FinishedAnimation_DisguiseSalute
(
void
)
void Actor::FinishedAnimation_DisguiseSalute(void)
{
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE);
}
+88 -134
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,164 +24,118 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitDisguiseSentry
(
GlobalFuncs_t *func
)
void Actor::InitDisguiseSentry(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_DisguiseSentry;
func->BeginState = &Actor::Begin_DisguiseSentry;
func->EndState = &Actor::End_DisguiseSentry;
func->ResumeState = &Actor::Resume_DisguiseSentry;
func->SuspendState = &Actor::Suspend_DisguiseSentry;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Disguise;
func->IsState = &Actor::IsDisguiseState;
func->ThinkState = &Actor::Think_DisguiseSentry;
func->BeginState = &Actor::Begin_DisguiseSentry;
func->EndState = &Actor::End_DisguiseSentry;
func->ResumeState = &Actor::Resume_DisguiseSentry;
func->SuspendState = &Actor::Suspend_DisguiseSentry;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Disguise;
func->IsState = &Actor::IsDisguiseState;
}
void Actor::Begin_DisguiseSentry
(
void
)
void Actor::Begin_DisguiseSentry(void)
{
vec2_t vDelta;
m_csMood = STRING_BORED;
assert(m_Enemy);
if (!m_Enemy) {
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE);
return;
}
m_csMood = STRING_BORED;
if ((EnemyIsDisguised() || (m_Enemy->flags & FL_NOTARGET)) && level.m_bAlarm != qtrue) {
SetDesiredYawDest(m_Enemy->origin);
SetDesiredLookDir(m_Enemy->origin - origin);
assert(m_Enemy);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DISGUISE_WAIT_SCR);
m_iEnemyShowPapersTime = m_Enemy->m_ShowPapersTime;
if (m_Enemy)
{
if ((EnemyIsDisguised() || m_Enemy->IsSubclassOfActor()) && !level.m_bAlarm)
{
VectorSub2D(m_Enemy->origin, origin, vDelta);
if (vDelta[0] != 0 || vDelta[1] != 0)
{
SetDesiredYawDir(vDelta);
}
SetDesiredLookDir(m_Enemy->origin - origin);
m_eNextAnimMode = 1;
m_csNextAnimString = STRING_ANIM_DISGUISE_WAIT_SCR;
m_bNextForceStart = false;
m_iEnemyShowPapersTime = m_Enemy->m_ShowPapersTime;
TransitionState(1, 0);
}
else
{
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL);
}
}
else
{
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
}
TransitionState(ACTOR_STATE_DISGUISE_WAIT);
} else {
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE);
}
}
void Actor::End_DisguiseSentry
(
void
)
void Actor::End_DisguiseSentry(void)
{
m_iNextDisguiseTime = level.inttime + (m_State ? m_iDisguisePeriod : 500);
m_iNextDisguiseTime = level.inttime + (m_State ? m_iDisguisePeriod : 500);
}
void Actor::Resume_DisguiseSentry
(
void
)
void Actor::Resume_DisguiseSentry(void)
{
Begin_DisguiseSentry();
Begin_DisguiseSentry();
}
void Actor::Suspend_DisguiseSentry
(
void
)
void Actor::Suspend_DisguiseSentry(void)
{
End_DisguiseSentry();
End_DisguiseSentry();
}
void Actor::Think_DisguiseSentry
(
void
)
void Actor::Think_DisguiseSentry(void)
{
if (RequireThink())
{
UpdateEyeOrigin();
NoPoint();
ContinueAnimation();
UpdateEnemy(1500);
if (!RequireThink()) {
return;
}
assert(m_Enemy != NULL);
UpdateEyeOrigin();
NoPoint();
ContinueAnimation();
UpdateEnemy(1500);
if (!m_Enemy)
{
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
return;
}
if (!EnemyIsDisguised() && !m_Enemy->IsSubclassOfActor() && m_State != 3)
{
TransitionState(3, 0);
}
assert(m_Enemy != NULL);
if (level.m_bAlarm)
{
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_NORMAL);
}
else
{
if (!m_Enemy) {
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE);
return;
}
if (!EnemyIsDisguised() && !(m_Enemy->flags & FL_NOTARGET) && m_State != ACTOR_STATE_DISGUISE_ENEMY) {
TransitionState(ACTOR_STATE_DISGUISE_ENEMY, 0);
}
{
vec2_t facedir;
facedir[0] = m_Enemy->origin[0] - origin[0];
facedir[1] = m_Enemy->origin[1] - origin[1];
if (facedir[0] != 0 || facedir[1] != 0)
{
SetDesiredYawDir(facedir);
}
if (level.m_bAlarm) {
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE);
return;
}
}
SetDesiredYawDest(m_Enemy->origin);
SetDesiredLookDir(m_Enemy->origin - origin);
SetDesiredLookDir(m_Enemy->origin - origin);
switch (m_State) {
case ACTOR_STATE_DISGUISE_WAIT:
m_pszDebugState = "wait";
State_Disguise_Wait();
break;
case ACTOR_STATE_DISGUISE_PAPERS:
m_pszDebugState = "papers";
State_Disguise_Papers();
break;
case ACTOR_STATE_DISGUISE_ACCEPT:
m_pszDebugState = "accept";
State_Disguise_Accept();
break;
case ACTOR_STATE_DISGUISE_ENEMY:
m_pszDebugState = "enemy";
State_Disguise_Enemy();
break;
case ACTOR_STATE_DISGUISE_HALT:
m_pszDebugState = "halt";
State_Disguise_Halt();
break;
case ACTOR_STATE_DISGUISE_DENY:
m_pszDebugState = "deny";
State_Disguise_Deny();
break;
default:
Com_Printf("Actor::Think_DisguiseSentry: invalid think state %i\n", m_State);
assert(!"invalid think state");
break;
}
switch (m_State)
{
case 0:
m_pszDebugState = "wait";
State_Disguise_Wait();
break;
case 1:
m_pszDebugState = "papers";
State_Disguise_Papers();
break;
case 2:
m_pszDebugState = "accept";
State_Disguise_Accept();
break;
case 3:
m_pszDebugState = "enemy";
State_Disguise_Enemy();
break;
case 4:
m_pszDebugState = "halt";
State_Disguise_Halt();
break;
case 5:
m_pszDebugState = "deny";
State_Disguise_Deny();
break;
default:
Com_Printf("Actor::Think_DisguiseSentry: invalid think state %i\n", m_State);
assert(!"invalid think state");
break;
}
CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_NORMAL);
PostThink(true);
}
}
if (!CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE)) {
CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE);
}
PostThink(true);
}
+91 -142
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,176 +24,125 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitDogIdle
(
GlobalFuncs_t *func
)
void Actor::InitDogIdle(GlobalFuncs_t *func)
{
func->BeginState = &Actor::Begin_Dog;
func->EndState = &Actor::End_Dog;
func->ThinkState = &Actor::Think_Dog_Idle;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle;
func->IsState = &Actor::IsDogState;
func->BeginState = &Actor::Begin_Dog;
func->EndState = &Actor::End_Dog;
func->ThinkState = &Actor::Think_Dog_Idle;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle;
func->IsState = &Actor::IsDogState;
}
void Actor::InitDogAttack
(
GlobalFuncs_t *func
)
void Actor::InitDogAttack(GlobalFuncs_t *func)
{
func->BeginState = &Actor::Begin_Dog;
func->EndState = &Actor::End_Dog;
func->ThinkState = &Actor::Think_Dog_Attack;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack;
func->IsState = &Actor::IsDogState;
func->BeginState = &Actor::Begin_Dog;
func->EndState = &Actor::End_Dog;
func->ThinkState = &Actor::Think_Dog_Attack;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack;
func->IsState = &Actor::IsDogState;
}
void Actor::InitDogCurious
(
GlobalFuncs_t *func
)
void Actor::InitDogCurious(GlobalFuncs_t *func)
{
func->BeginState = &Actor::Begin_Dog;
func->EndState = &Actor::End_Dog;
func->ThinkState = &Actor::Think_Dog_Curious;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Curious;
func->IsState = &Actor::IsDogState;
func->BeginState = &Actor::Begin_Dog;
func->EndState = &Actor::End_Dog;
func->ThinkState = &Actor::Think_Dog_Curious;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Curious;
func->IsState = &Actor::IsDogState;
}
void Actor::Begin_Dog
(
void
)
bool Actor::IsDogState(int state)
{
m_bDog = true;
return true;
}
void Actor::End_Dog
(
void
)
void Actor::Begin_Dog(void)
{
;
m_bIsAnimal = true;
}
void Actor::Think_Dog_Idle
(
void
)
void Actor::End_Dog(void)
{
if( !RequireThink() )
{
return;
}
UpdateEyeOrigin();
m_pszDebugState = "Dog_Idle";
m_bHasDesiredLookAngles = false;
m_eNextAnimMode = 1;
m_csNextAnimString = STRING_ANIM_DOG_IDLE_SCR;
CheckForThinkStateTransition();
PostThink( false );
;
}
void Actor::Think_Dog_Attack
(
void
)
void Actor::Think_Dog_Idle(void)
{
if (!RequireThink())
{
return;
}
if (!RequireThink()) {
return;
}
UpdateEyeOrigin();
m_pszDebugState = "Dog_Attack";
UpdateEyeOrigin();
m_pszDebugState = "Dog_Idle";
if (m_Enemy && !(m_Enemy->IsSubclassOfActor()))
{
NoPoint();
ForwardLook();
SetPath(m_Enemy->origin, NULL, 0, NULL, 0.0);
if (PathExists())
{
vec2_t delta;
VectorSub2D(m_Enemy->origin, origin, delta);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DOG_IDLE_SCR);
if (VectorLength2DSquared(delta) >= 8000)
{
FaceMotion();
m_csNextAnimString = STRING_ANIM_DOG_CHASE_SCR;
m_eNextAnimMode = 2;
}
else
{
{
vec2_t facedir;
facedir[0] = m_Enemy->origin[0] - origin[0];
facedir[1] = m_Enemy->origin[1] - origin[1];
if (facedir[0] != 0 || facedir[1] != 0)
{
SetDesiredYawDir(facedir);
}
}
SetDesiredLookDir(m_Enemy->origin - origin);
m_eNextAnimMode = 1;
m_csNextAnimString = STRING_ANIM_DOG_ATTACK_SCR;
}
m_bNextForceStart = false;
CheckForThinkStateTransition();
PostThink(false);
return;
}
{
vec2_t facedir;
facedir[0] = m_Enemy->origin[0] - origin[0];
facedir[1] = m_Enemy->origin[1] - origin[1];
if (facedir[0] != 0 || facedir[1] != 0)
{
SetDesiredYawDir(facedir);
}
}
SetDesiredLookDir(m_Enemy->origin - origin);
}
m_bNextForceStart = false;
m_eNextAnimMode = 1;
m_csNextAnimString = STRING_ANIM_DOG_CURIOUS_SCR;
TransitionState(20, 0);
CheckForThinkStateTransition();
PostThink(false);
CheckForThinkStateTransition();
PostThink(false);
}
void Actor::Think_Dog_Curious
(
void
)
void Actor::Think_Dog_Attack(void)
{
if (RequireThink())
{
UpdateEyeOrigin();
m_pszDebugState = "Dog_Curious";
if (!RequireThink()) {
return;
}
if (m_Enemy && !m_Enemy->IsSubclassOfActor())
{
vec2_t vDelta;
VectorSub2D(m_Enemy->origin, origin, vDelta);
UpdateEyeOrigin();
m_pszDebugState = "Dog_Attack";
if (vDelta[0] != 0 || vDelta[1] != 0)
{
SetDesiredYawDir(vDelta);
}
if (!m_Enemy || (m_Enemy->flags & FL_NOTARGET)) {
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DOG_CURIOUS_SCR);
TransitionState(20);
SetDesiredLookDir(m_Enemy->origin - origin);
CheckForThinkStateTransition();
PostThink(false);
return;
}
}
m_bNextForceStart = false;
m_eNextAnimMode = 1;
m_csNextAnimString = STRING_ANIM_DOG_CURIOUS_SCR;
SetPath(m_Enemy->origin, NULL, 0, NULL, 0.0);
CheckForThinkStateTransition();
PostThink(false);
}
if (PathExists()) {
vec2_t delta;
VectorSub2D(m_Enemy->origin, origin, delta);
if (VectorLength2DSquared(delta) >= 8000) {
FaceMotion();
DesiredAnimation(ANIM_MODE_PATH, STRING_ANIM_DOG_CHASE_SCR);
} else {
SetDesiredYawDest(m_Enemy->origin);
SetDesiredLookDir(m_Enemy->origin - origin);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DOG_ATTACK_SCR);
}
} else {
SetDesiredYawDest(m_Enemy->origin);
SetDesiredLookDir(m_Enemy->origin - origin);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DOG_CURIOUS_SCR);
TransitionState(20);
}
CheckForThinkStateTransition();
PostThink(false);
}
void Actor::Think_Dog_Curious(void)
{
if (!RequireThink()) {
return;
}
UpdateEyeOrigin();
m_pszDebugState = "Dog_Curious";
if (m_Enemy && !(m_Enemy->flags & FL_NOTARGET)) {
SetDesiredYawDest(m_Enemy->origin);
SetDesiredLookDir(m_Enemy->origin - origin);
}
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_DOG_CURIOUS_SCR);
CheckForThinkStateTransition();
PostThink(false);
}
File diff suppressed because it is too large. Load diff
+42 -90
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,105 +24,57 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitIdle
(
GlobalFuncs_t *func
)
void Actor::InitIdle(GlobalFuncs_t *func)
{
func->BeginState = &Actor::Begin_Idle;
func->ThinkState = &Actor::Think_Idle;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle;
func->IsState = &Actor::IsIdleState;
func->BeginState = &Actor::Begin_Idle;
func->ThinkState = &Actor::Think_Idle;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle;
func->IsState = &Actor::IsIdleState;
}
void Actor::Begin_Idle
(
void
)
void Actor::Begin_Idle(void)
{
glbs.Printf("Begin_Idle\n");
m_csMood = m_csIdleMood;
ClearPath();
m_csMood = m_csIdleMood;
ClearPath();
}
void Actor::Think_Idle
(
void
)
void Actor::IdleThink(void)
{
if (RequireThink())
{
UpdateEyeOrigin();
m_pszDebugState = "";
CheckForThinkStateTransition();
IdleThink();
}
IdlePoint();
IdleLook();
if (PathExists() && PathComplete()) {
ClearPath();
}
if (m_bAutoAvoidPlayer && !PathExists()) {
SetPathToNotBlockSentient(static_cast<Sentient *>(G_GetEntity(0)));
}
if (PathExists()) {
Anim_WalkTo(ANIM_MODE_PATH);
if (PathDist() > 128.0) {
FaceMotion();
} else {
IdleTurn();
}
} else {
Anim_Idle();
IdleTurn();
}
PostThink(true);
}
void Actor::IdleThink
(
void
)
void Actor::Think_Idle(void)
{
IdlePoint();
IdleLook();
if (PathExists() && PathComplete())
{
ClearPath();
}
if (m_bAutoAvoidPlayer && !PathExists())
{
SetPathToNotBlockSentient((Sentient *)G_GetEntity(0));
}
if (!RequireThink()) {
return;
}
if (PathExists())
{
Anim_WalkTo(2);
if (PathDist() <= 128.0)
IdleTurn();
else
FaceMotion();
}
else
{
Anim_Idle();
IdleTurn();
}
UpdateEyeOrigin();
m_pszDebugState = "";
PostThink(true);
}
/*
===============
Actor::PassesTransitionConditions_Idle
Should actor transition think state to idle ?
===============
*/
bool Actor::PassesTransitionConditions_Idle
(
void
)
{
glbs.Printf("PassesTransitionConditions_Idle\n");
UpdateEnemy(500);
if (m_bLockThinkState)
return false;
if (!m_Enemy && !m_iCuriousTime)
return true;
return false;
}
bool Actor::IsIdleState
(
int state
)
{
return state == THINKSTATE_IDLE;
CheckForThinkStateTransition();
IdleThink();
}
+32 -50
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,67 +24,49 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitDead
(
GlobalFuncs_t *func
)
void Actor::InitDead(GlobalFuncs_t *func)
{
func->IsState = &Actor::IsKilledState;
func->IsState = &Actor::IsKilledState;
}
void Actor::InitKilled
(
GlobalFuncs_t *func
)
void Actor::InitKilled(GlobalFuncs_t *func)
{
func->BeginState = &Actor::Begin_Killed;
func->ThinkState = &Actor::Think_Killed;
func->FinishedAnimation = &Actor::FinishedAnimation_Killed;
func->IsState = &Actor::IsKilledState;
func->BeginState = &Actor::Begin_Killed;
func->ThinkState = &Actor::Think_Killed;
func->FinishedAnimation = &Actor::FinishedAnimation_Killed;
func->IsState = &Actor::IsKilledState;
}
void Actor::Begin_Killed
(
void
)
void Actor::Begin_Killed(void)
{
Event e1(EV_Actor_DeathEmbalm); // ebx
ClearPath();
ResetBoneControllers();
ClearPath();
ResetBoneControllers();
PostEvent(
e1,
0.05f);
TransitionState(700, 0);
PostEvent(EV_Actor_DeathEmbalm, 0.05f);
TransitionState(ACTOR_STATE_KILLED_BEGIN, 0);
}
void Actor::Think_Killed
(
void
)
void Actor::Think_Killed(void)
{
Unregister(STRING_ANIMDONE);
if (m_State == 700)
{
m_pszDebugState = "begin";
NoPoint();
m_bHasDesiredLookAngles = false;
StopTurning();
Anim_Killed();
PostThink(false);
}
else
{
m_pszDebugState = "end";
}
Unregister(STRING_ANIMDONE);
if (m_State != ACTOR_STATE_KILLED_BEGIN) {
m_pszDebugState = "end";
return;
}
m_pszDebugState = "begin";
NoPoint();
ForwardLook();
StopTurning();
Anim_Killed();
PostThink(false);
}
void Actor::FinishedAnimation_Killed
(
void
)
void Actor::FinishedAnimation_Killed(void)
{
BecomeCorpse();
TransitionState(701, 0);
BecomeCorpse();
TransitionState(ACTOR_STATE_KILLED_END);
}
+251 -310
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,337 +24,278 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
#include "weapturret.h"
#include "bg_local.h"
extern Vector MINS;
extern Vector MAXS;
void Actor::InitMachineGunner
(
GlobalFuncs_t *func
)
void Actor::InitMachineGunner(GlobalFuncs_t *func)
{
func->BeginState = &Actor::Begin_MachineGunner;
func->EndState = &Actor::End_MachineGunner;
func->ThinkState = &Actor::Think_MachineGunner;
func->IsState = &Actor::IsMachineGunnerState;
func->FinishedAnimation = &Actor::FinishedAnimation_MachineGunner;
func->BeginState = &Actor::Begin_MachineGunner;
func->EndState = &Actor::End_MachineGunner;
func->ThinkState = &Actor::Think_MachineGunner;
func->IsState = &Actor::IsMachineGunnerState;
func->FinishedAnimation = &Actor::FinishedAnimation_MachineGunner;
}
void Actor::Begin_MachineGunner
(
void
)
bool Actor::IsMachineGunnerState(int state)
{
m_csMood = STRING_ALERT;
m_csIdleMood = STRING_NERVOUS;
if (m_pTurret)
{
Sentient *pOwner;
m_pTurret->m_bHadOwner = true;
pOwner = m_pTurret->GetOwner();
if (pOwner)
{
Com_Printf(
"^~^~^ Actor (entnum %d, radnum %d, targetname '%s') cannot use turret (entnum %d, radnum %d, targetname '%s')"
" since it is already being used by Actor (entnum %d, radnum %d, targetname '%s')\n",
entnum,
radnum,
targetname.c_str(),
m_pTurret->entnum,
m_pTurret->radnum,
m_pTurret->TargetName().c_str(),
pOwner->entnum,
pOwner->radnum,
pOwner->TargetName().c_str());
}
else
{
Holster();
m_pTurret->TurretBeginUsed(this);
TransitionState(1200, 0);
}
}
else
{
Com_Printf(
"^~^~^ Actor (entnum %d, radnum %d, targetname '%s') has no turret specified\n",
entnum,
radnum,
targetname.c_str());
}
}
void Actor::End_MachineGunner
(
void
)
{
if (!GetWeapon(WEAPON_MAIN))
giveItem("models/weapons/mp40.tik");
Unholster();
if (m_pTurret)
{
if (m_pTurret->GetOwner() == this)
{
m_pTurret->TurretEndUsed();
}
}
}
void Actor::BecomeTurretGuy
(
void
)
{
SetThinkIdle(THINK_IDLE);
SetThink(THINKSTATE_ATTACK, THINK_TURRET);
SetThink(THINKSTATE_DISGUISE, THINK_DISGUISE_SALUTE);
SetThink(THINKSTATE_GRENADE, THINK_GRENADE);
if (CurrentThink() == THINK_IDLE && Turret_DecideToSelectState())
{
TransitionState(100, 0);
}
return true;
}
void Actor::Think_MachineGunner
(
void
)
void Actor::Begin_MachineGunner(void)
{
if (RequireThink())
{
if (m_pTurret && m_pTurret->GetOwner() == this && !m_bNoPlayerCollision)
{
if (!m_bEnableEnemy)
{
ThinkHoldGun();
return;
}
m_csMood = STRING_ALERT;
m_csIdleMood = STRING_NERVOUS;
if (level.inttime < m_iEnemyCheckTime + 200)
{
ThinkHoldGun();
return;
}
m_iEnemyCheckTime = level.inttime;
if (!m_pTurret) {
Com_Printf(
"^~^~^ Actor (entnum %d, radnum %d, targetname '%s') has no turret specified\n",
entnum,
radnum,
targetname.c_str()
);
if (m_pTurret->CanTarget(G_GetEntity(0)->centroid))
{
ThinkHoldGun();
return;
}
if (!m_pGrenade || m_fGrenadeAwareness < rand() * 0.000000046566129)
{
if (!G_SightTrace(
EyePosition(),
vec_zero,
vec_zero,
G_GetEntity(0)->centroid,
this,
G_GetEntity(0),
33819417,
qfalse,
"Actor::Think_MachineGunner"))
{
ThinkHoldGun();
return;
}
if (m_ThinkStates[THINKLEVEL_NORMAL] != THINKSTATE_IDLE)
{
BecomeTurretGuy();
return;
}
return;
}
if (m_Enemy && !m_Enemy->IsSubclassOfActor() && !EnemyIsDisguised() && m_PotentialEnemies.GetCurrentVisibility() >= 1)
{
BecomeTurretGuy();
return;
}
Sentient *pOwner;
m_pTurret->m_bHadOwner = true;
pOwner = m_pTurret->GetOwner();
if (m_pTurret->GetOwner()) {
Com_Printf(
"^~^~^ Actor (entnum %d, radnum %d, targetname '%s') cannot use turret (entnum %d, radnum %d, "
"targetname '%s')"
" since it is already being used by Actor (entnum %d, radnum %d, targetname '%s')\n",
entnum,
radnum,
targetname.c_str(),
m_pTurret->entnum,
m_pTurret->radnum,
m_pTurret->targetname.c_str(),
m_pTurret->GetOwner()->entnum,
m_pTurret->GetOwner()->radnum,
m_pTurret->GetOwner()->targetname.c_str()
);
} else {
Holster();
if (!m_Enemy || !m_Enemy->IsSubclassOfActor() || EnemyIsDisguised() || m_PotentialEnemies.GetCurrentVisibility() > 1)
{
ThinkHoldGun();
return;
}
SetCuriousAnimHint(6);
}
}
BecomeTurretGuy();
}
m_pTurret->TurretBeginUsed(this);
TransitionState(ACTOR_STATE_MACHINE_GUNNER_READY);
}
}
void Actor::ThinkHoldGun
(
void
)
void Actor::End_MachineGunner(void)
{
Vector end;
trace_t trace;
float temp;
float temp2;
float machine_gunner_hands_up_stand;
float heightDiff;
float right;
//vec3_t newOrigin;
Vector offset;
Vector start;
//vec3_t new_angles;
Vector vForward;
UpdateEyeOrigin();
m_pszDebugState = "";
if (m_State == 1200)
{
if (m_pTurret->IsFiring())
{
if (m_pTurret->aim_target == G_GetEntity(0))
{
m_bNoSurprise = true;
}
m_csNextAnimString = STRING_ANIM_MG42_SHOOT_SCR;
}
else
{
m_csNextAnimString = STRING_ANIM_MG42_IDLE_SCR;
}
}
else
{
m_csNextAnimString = STRING_ANIM_MG42_RELOAD_SCR;
m_bAnimScriptSet = false;
}
m_eNextAnimMode = 8;
m_bNextForceStart = false;
CheckUnregister();
StopTurning();
setAngles(Vector(0,m_pTurret->angles[1],0));
vForward = Vector(m_pTurret->orientation[0]) * -39 + m_pTurret->origin;
if (m_State == 1201)
{
heightDiff = 71.6f;
}
else
{
heightDiff = 71.8f;
}
machine_gunner_hands_up_stand = origin[2] - (m_pTurret->origin[2] - heightDiff);
if (machine_gunner_hands_up_stand < 0)
{
if (m_State == 1201)
{
temp = (machine_gunner_hands_up_stand - m_pTurret->origin[2]) / 39;
if (temp >= -1.0 && temp <= 1.0)
{
right = atan2(temp / sqrt(temp*-temp + 1), 1) * 180 / M_PI;
m_pTurret->setAngles(Vector(right, m_pTurret->angles[1], m_pTurret->angles[2]));
}
}
else
{
m_fCrouchWeight = machine_gunner_hands_up_stand / 17.1;
if (m_fCrouchWeight < -1.0)
{
m_fCrouchWeight = -1.0;
}
}
temp2 = m_fCrouchWeight * 2.6;
offset.x = (-(-9.3*m_fCrouchWeight + 23.4)) * orientation[0][0] + vForward.x;
offset.y = (-(-9.3*m_fCrouchWeight + 23.4)) * orientation[0][0] + vForward.y;
}
else
{
m_fCrouchWeight = machine_gunner_hands_up_stand / (heightDiff - 38.7);
if (m_fCrouchWeight > 1.0)
{
m_fCrouchWeight = 1.0;
}
temp2 = m_fCrouchWeight * -1.6;
offset.x = (-(-3*m_fCrouchWeight + 23.4)) * orientation[0][0] + vForward.x;
offset.y = (-(-3*m_fCrouchWeight + 23.4)) * orientation[0][0] + vForward.y;
}
start.x = (temp2 + 10.3) * orientation[1][0] + offset.x;
start.y = (temp2 + 10.3) * orientation[1][1] + offset.y;
if (m_fCrouchWeight >= 0.5)
m_csCurrentPosition = STRING_CROUCH;
else
m_csCurrentPosition = STRING_STAND;
UpdateAimMotion();
UpdateAnim();
start.z = origin.z + 18.0;
end = start;
end.z = origin.z - 94.0;
trace = G_Trace(start, MINS, MAXS, end, this, 1107437825, qfalse, "Actor::ThinkHoldGun");
if (trace.fraction != 1.0 && !trace.startsolid && !trace.allsolid && trace.ent)
SafeSetOrigin(trace.endpos);
velocity = vec_zero;
UpdateBoneControllers();
UpdateFootsteps();
if (!GetWeapon(WEAPON_MAIN)) {
giveItem("models/weapons/mp40.tik");
}
Unholster();
if (m_pTurret && m_pTurret->GetOwner() == this) {
m_pTurret->TurretEndUsed();
}
}
void Actor::FinishedAnimation_MachineGunner
(
void
)
void Actor::ThinkHoldGun_TurretGun(void)
{
if (!m_bAnimScriptSet && m_State == 1201)
{
TransitionState(1200, 0);
Unregister(STRING_ANIMDONE);
}
Vector vForward;
vec3_t new_angles;
vec3_t offset;
vec3_t newOrigin;
float right;
float heightDiff;
float machine_gunner_hands_up_stand;
float temp;
trace_t trace;
Vector end;
if (m_State != ACTOR_STATE_MACHINE_GUNNER_READY) {
DesiredAnimation(ANIM_MODE_FROZEN, STRING_ANIM_MG42_RELOAD_SCR);
m_bAnimScriptSet = false;
} else if (m_pTurret->IsFiring()) {
if (m_pTurret->aim_target == G_GetEntity(0)) {
m_bNoSurprise = true;
}
DesiredAnimation(ANIM_MODE_FROZEN, STRING_ANIM_MG42_SHOOT_SCR);
} else {
DesiredAnimation(ANIM_MODE_FROZEN, STRING_ANIM_MG42_IDLE_SCR);
}
CheckUnregister();
StopTurning();
VectorSet(new_angles, 0, m_pTurret->angles[1], 0);
setAngles(new_angles);
VectorScale(m_pTurret->orientation[0], -39, offset);
VectorAdd(m_pTurret->origin, offset, newOrigin);
if (m_State == ACTOR_STATE_MACHINE_GUNNER_RELOADING) {
heightDiff = 71.6f;
} else {
heightDiff = 71.8f;
}
newOrigin[2] -= heightDiff;
machine_gunner_hands_up_stand = origin[2] - newOrigin[2];
if (machine_gunner_hands_up_stand < 0) {
if (m_State == ACTOR_STATE_MACHINE_GUNNER_RELOADING) {
m_fCrouchWeight = 0;
temp = (origin[2] + 71.6f - m_pTurret->origin[2]) / 39.f;
if (temp >= -1.0 && temp <= 1.0) {
m_pTurret->angles[0] = RAD2DEG(atan(temp / sqrt(temp * -temp + 1)));
m_pTurret->setAngles(m_pTurret->angles);
}
} else {
m_fCrouchWeight = machine_gunner_hands_up_stand / 17.1f;
if (m_fCrouchWeight < -1.0) {
m_fCrouchWeight = -1.0;
}
}
VectorScale2D(orientation[0], m_fCrouchWeight * -9.3f + 23.4f, offset);
VectorAdd2D(newOrigin, offset, newOrigin);
VectorScale2D(orientation[1], m_fCrouchWeight * 2.6f + 10.3f, offset);
VectorAdd2D(newOrigin, offset, newOrigin);
} else {
m_fCrouchWeight = machine_gunner_hands_up_stand / (heightDiff - 38.7f);
if (m_fCrouchWeight > 1.0) {
m_fCrouchWeight = 1.0;
}
VectorScale2D(orientation[0], m_fCrouchWeight * -3.f + 23.4f, offset);
VectorAdd2D(newOrigin, offset, newOrigin);
VectorScale2D(orientation[1], m_fCrouchWeight * -1.6f + 10.3f, offset);
VectorAdd2D(newOrigin, offset, newOrigin);
}
if (m_fCrouchWeight >= 0.5) {
m_csCurrentPosition = STRING_CROUCH;
} else {
m_csCurrentPosition = STRING_STAND;
}
UpdateAimMotion();
UpdateAnim();
end[0] = newOrigin[0];
end[1] = newOrigin[1];
end[2] = newOrigin[2] - 94;
trace = G_Trace(newOrigin, MINS, MAXS, end, this, MASK_PATHSOLID, qfalse, "Actor::ThinkHoldGun_TurretGun");
if (trace.fraction != 1.0 && !trace.startsolid && !trace.allsolid && trace.ent) {
SafeSetOrigin(trace.endpos);
}
VectorClear(velocity);
UpdateBoneControllers();
UpdateFootsteps();
}
bool Actor::MachineGunner_CanSee
(
Entity *ent,
float fov,
float vision_distance
)
void Actor::Think_MachineGunner_TurretGun(void)
{
float delta[2];
if (!m_bEnableEnemy) {
ThinkHoldGun_TurretGun();
return;
}
delta[0] = ent->centroid[0] - centroid[0];
delta[1] = ent->centroid[1] - centroid[1];
if ((vision_distance <= 0.0f) || (delta[0] * delta[0] + delta[1] * delta[1]) <= (vision_distance * vision_distance))
{
if (gi.AreasConnected(edict->r.areanum, ent->edict->r.areanum) &&
((fov <= 0.0f || fov >= 360.0f) ||
(FovCheck(delta, cos(fov * (0.5 * M_PI / 180.0))))))
{
return G_SightTrace(centroid,
vec_zero,
vec_zero,
ent->centroid,
m_pTurret,
ent,
MASK_CANSEE,
0,
"Actor::MachineGunner_CanSee");
}
}
if (level.inttime < m_iEnemyCheckTime + 200) {
ThinkHoldGun_TurretGun();
return;
}
return false;
UpdateEnemyInternal();
if (m_pTurret->AI_CanTarget(G_GetEntity(0)->centroid)) {
ThinkHoldGun_TurretGun();
return;
}
if (m_pGrenade && rand() / 21474836.f <= m_fGrenadeAwareness) {
BecomeTurretGuy();
return;
}
if (!G_SightTrace(
EyePosition(),
vec_zero,
vec_zero,
static_cast<Sentient *>(G_GetEntity(0))->EyePosition(),
this,
G_GetEntity(0),
MASK_CANSEE,
qfalse,
"Actor::Think_MachineGunner"
)) {
ThinkHoldGun_TurretGun();
return;
}
if (m_ThinkStates[THINKLEVEL_IDLE] != THINKSTATE_IDLE) {
BecomeTurretGuy();
return;
}
if (m_Enemy && !(m_Enemy->flags & FL_NOTARGET) && !EnemyIsDisguised() && m_PotentialEnemies.IsEnemyConfirmed()) {
BecomeTurretGuy();
return;
}
if (m_Enemy && m_iCuriousTime || (m_Enemy && !EnemyIsDisguised() && !m_PotentialEnemies.IsEnemyConfirmed())) {
m_iCuriousAnimHint = 6;
BecomeTurretGuy();
return;
}
ThinkHoldGun_TurretGun();
}
void Actor::Think_MachineGunner(void)
{
if (!RequireThink()) {
return;
}
if (m_pTurret && m_pTurret->GetOwner() == this && !m_bNoPlayerCollision) {
UpdateEyeOrigin();
Think_MachineGunner_TurretGun();
} else {
BecomeTurretGuy();
}
}
void Actor::FinishedAnimation_MachineGunner(void)
{
if (!m_bAnimScriptSet && m_State == ACTOR_STATE_MACHINE_GUNNER_RELOADING) {
TransitionState(ACTOR_STATE_MACHINE_GUNNER_READY, 0);
Unregister(STRING_ANIMDONE);
}
}
bool Actor::MachineGunner_CanSee(Entity *ent, float fov, float vision_distance)
{
float delta[2];
delta[0] = ent->centroid[0] - centroid[0];
delta[1] = ent->centroid[1] - centroid[1];
if ((vision_distance <= 0.0f)
|| (delta[0] * delta[0] + delta[1] * delta[1]) <= (vision_distance * vision_distance)) {
if (gi.AreasConnected(edict->r.areanum, ent->edict->r.areanum)
&& ((fov <= 0.0f || fov >= 360.0f) || (FovCheck(delta, cos(fov * (0.5 * M_PI / 180.0)))))) {
return G_SightTrace(
centroid,
vec_zero,
vec_zero,
ent->centroid,
m_pTurret,
ent,
MASK_CANSEE,
0,
"Actor::MachineGunner_CanSee"
);
}
}
return false;
}
+55 -80
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,87 +24,62 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitNoClip
(
GlobalFuncs_t *func
)
void Actor::InitNoClip(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_NoClip;
func->IsState = &Actor::IsIdleState;
func->ThinkState = &Actor::Think_NoClip;
func->IsState = &Actor::IsIdleState;
}
bool Actor::IsNoClipState
(
int state
)
void Actor::Think_NoClip(void)
{
return state == THINKSTATE_NOCLIP;
}
void Actor::Think_NoClip
(
void
)
{
//FIXME: not sure of naming
bool done = false;
Vector newOrigin = vec_zero;
Vector total_offset;
Vector total_offset_unit;
float total_dist;
//vec3_t frame_offset;
float frame_dist;
m_pszDebugState = "";
ContinueAnimationAllowNoPath();
CheckUnregister();
UpdateAngles();
UpdateAnim();
total_offset = m_NoClipDest - origin;
total_dist = VectorNormalize2(total_offset, total_offset_unit);
frame_dist = level.frametime * m_maxspeed;
if (frame_dist >= frame_delta.lengthSquared())
{
frame_dist = frame_delta.lengthSquared();
}
if (frame_dist < total_dist)
{
newOrigin = total_offset_unit * frame_dist + origin;
}
else
{
done = true;
newOrigin = m_NoClipDest;
}
SafeSetOrigin(newOrigin);
velocity = total_offset_unit / level.frametime;
if (velocity.lengthSquared() < 1)
{
done = true;
velocity = vec_zero;
}
groundentity = NULL;
if (done)
{
Com_Printf(
"(entnum %d, radnum %d) failsafe finished\n",
entnum,
radnum);
EndCurrentThinkState();
}
UpdateBoneControllers();
UpdateFootsteps();
float frame_dist;
vec3_t frame_offset;
float total_dist;
vec3_t total_offset;
Vector newOrigin;
bool done = false;
m_pszDebugState = "";
ContinueAnimationAllowNoPath();
CheckUnregister();
UpdateAngles();
UpdateAnim();
VectorSubtract(m_NoClipDest, origin, total_offset);
total_dist = VectorNormalize2(total_offset, frame_offset);
frame_dist = VectorLength(frame_delta);
if (frame_dist > m_maxspeed * level.frametime) {
frame_dist = m_maxspeed * level.frametime;
}
if (frame_dist < total_dist) {
VectorScale(frame_offset, frame_dist, frame_offset);
VectorAdd(origin, frame_offset, newOrigin);
} else {
VectorCopy(m_NoClipDest, newOrigin);
done = true;
}
SafeSetOrigin(newOrigin);
velocity[0] = frame_offset[0] / level.frametime;
velocity[1] = frame_offset[1] / level.frametime;
velocity[2] = frame_offset[2] / level.frametime;
if (VectorLengthSquared(velocity) < 1) {
VectorClear(velocity);
done = true;
}
groundentity = NULL;
if (done) {
Com_Printf("(entnum %d, radnum %d) failsafe finished\n", entnum, radnum);
EndCurrentThinkState();
}
UpdateBoneControllers();
UpdateFootsteps();
}
+25 -40
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,55 +24,40 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitPain
(
GlobalFuncs_t *func
)
void Actor::InitPain(GlobalFuncs_t *func)
{
func->BeginState = &Actor::Begin_Pain;
func->ThinkState = &Actor::Think_Pain;
func->FinishedAnimation = &Actor::FinishedAnimation_Pain;
func->IsState = &Actor::IsPainState;
func->BeginState = &Actor::Begin_Pain;
func->ThinkState = &Actor::Think_Pain;
func->FinishedAnimation = &Actor::FinishedAnimation_Pain;
func->IsState = &Actor::IsPainState;
}
void Actor::Begin_Pain
(
void
)
void Actor::Begin_Pain(void)
{
m_PainState = 500;
m_PainState = ACTOR_STATE_PAIN_INITIAL;
}
void Actor::Think_Pain
(
void
)
void Actor::Think_Pain(void)
{
NoPoint();
NoPoint();
ForwardLook();
UpdateEyeOrigin();
m_bHasDesiredLookAngles = false;
if (m_PainState == ACTOR_STATE_PAIN_INITIAL) {
m_pszDebugState = "initial";
Anim_StartPain();
m_PainState = ACTOR_STATE_PAIN_MAIN;
} else if (m_PainState == ACTOR_STATE_PAIN_MAIN) {
m_pszDebugState = "main";
Anim_Pain();
}
UpdateEyeOrigin();
if (m_PainState == 500)
{
m_pszDebugState = "initial";
Anim_StartPain();
m_PainState = 501;
}
else if (m_PainState == 501)
{
m_pszDebugState = "main";
Anim_Pain();
}
PostThink(false);
PostThink(false);
}
void Actor::FinishedAnimation_Pain
(
void
)
void Actor::FinishedAnimation_Pain(void)
{
if (m_PainState != 500)
EndCurrentThinkState();
if (m_PainState != ACTOR_STATE_PAIN_START) {
EndCurrentThinkState();
}
}
+56 -76
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,92 +24,72 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitPatrol
(
GlobalFuncs_t *func
)
void Actor::InitPatrol(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_Patrol;
func->BeginState = &Actor::Begin_Patrol;
func->EndState = &Actor::End_Patrol;
func->ResumeState = &Actor::Resume_Patrol;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle;
func->ShowInfo = &Actor::ShowInfo_Patrol;
func->IsState = &Actor::IsIdleState;
func->ThinkState = &Actor::Think_Patrol;
func->BeginState = &Actor::Begin_Patrol;
func->EndState = &Actor::End_Patrol;
func->ResumeState = &Actor::Resume_Patrol;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle;
func->ShowInfo = &Actor::ShowInfo_Patrol;
func->IsState = &Actor::IsIdleState;
}
void Actor::Begin_Patrol
(
void
)
void Actor::Begin_Patrol(void)
{
m_csMood = STRING_BORED;
StopTurning();
ClearPath();
m_csMood = STRING_BORED;
StopTurning();
ClearPath();
}
void Actor::End_Patrol
(
void
)
void Actor::End_Patrol(void)
{
parm.movefail = true;
parm.movefail = true;
}
void Actor::Resume_Patrol
(
void
)
void Actor::Resume_Patrol(void) {}
void Actor::Think_Patrol(void)
{
;
bool bMoveInRadius;
if (!RequireThink()) {
return;
}
parm.movefail = false;
UpdateEyeOrigin();
NoPoint();
m_pszDebugState = "";
m_csPatrolCurrentAnim = STRING_ANIM_PATROL_SCR;
bMoveInRadius = MoveToPatrolCurrentNode();
if (m_fLookAroundFov > 1.0) {
LookAround(m_fLookAroundFov);
}
CheckForThinkStateTransition();
if (!m_patrolCurrentNode) {
SetThinkIdle(THINK_IDLE);
m_bScriptGoalValid = false;
parm.movedone = true;
Unregister(STRING_MOVEDONE);
} else if (bMoveInRadius) {
ClearPatrolCurrentNode();
SetThinkIdle(THINK_IDLE);
parm.movedone = true;
Unregister(STRING_MOVEDONE);
}
PostThink(true);
}
void Actor::Think_Patrol
(
void
)
void Actor::ShowInfo_Patrol(void)
{
if (Actor::RequireThink())
{
parm.movefail = false;
UpdateEyeOrigin();
NoPoint();
m_pszDebugState = "";
m_csPatrolCurrentAnim = STRING_ANIM_PATROL_SCR;
if (m_fLookAroundFov > 1.0)
LookAround(m_fLookAroundFov);
CheckForThinkStateTransition();
if (m_patrolCurrentNode)
{
if (!MoveToPatrolCurrentNode())
{
PostThink(true);
return;
}
}
else
{
SetThinkIdle(THINK_IDLE);
m_bScriptGoalValid = false;
}
parm.movedone = true;
Unregister(STRING_MOVEDONE);
PostThink(true);
return;
}
}
void Actor::ShowInfo_Patrol
(
void
)
{
ShowInfo_PatrolCurrentNode();
ShowInfo_PatrolCurrentNode();
}
+204
View File
@@ -0,0 +1,204 @@
/*
===========================================================================
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_runandshoot.cpp
#include "actor.h"
void Actor::InitRunAndShoot(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_RunAndShoot;
func->BeginState = &Actor::Begin_RunAndShoot;
func->EndState = &Actor::End_RunAndShoot;
func->ResumeState = &Actor::Resume_RunAndShoot;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack;
func->ShowInfo = &Actor::ShowInfo_RunAndShoot;
func->IsState = &Actor::IsAttackState;
}
void Actor::Begin_RunAndShoot(void)
{
m_State = ACTOR_STATE_RUN_AND_SHOOT_RUN;
if (m_patrolCurrentNode) {
m_State = ACTOR_STATE_RUN_AND_SHOOT_RUNNING;
}
}
void Actor::End_RunAndShoot(void)
{
m_vHome = origin;
m_pTetherEnt = NULL;
}
void Actor::Resume_RunAndShoot(void) {}
void Actor::Think_RunAndShoot(void)
{
if (m_State == ACTOR_STATE_RUN_AND_SHOOT_RUNNING) {
State_RunAndShoot_Running();
} else if (m_State == ACTOR_STATE_RUN_AND_SHOOT_RUN) {
SetThink(THINKSTATE_ATTACK, THINK_COVER);
}
}
void Actor::ShowInfo_RunAndShoot(void) {}
void Actor::State_RunAndShoot_Running(void)
{
Entity *player;
bool bMoveDone;
if (!RequireThink()) {
return;
}
parm.movefail = false;
UpdateEyeOrigin();
NoPoint();
m_pszDebugState = "";
bMoveDone = RunAndShoot_MoveToPatrolCurrentNode();
CheckForThinkStateTransition();
player = G_GetEntity(0);
if (player) {
vec2_t delta;
VectorSub2D(player->origin, origin, delta);
if (VectorLength2DSquared(delta) < Square(150)) {
ClearPatrolCurrentNode();
}
}
if (!m_patrolCurrentNode) {
if (m_Enemy) {
SetThink(THINKSTATE_ATTACK, THINK_TURRET);
} else {
SetThinkIdle(THINK_IDLE);
}
m_bScriptGoalValid = false;
parm.movedone = true;
Unregister(STRING_MOVEDONE);
} else if (bMoveDone) {
ClearPatrolCurrentNode();
if (m_Enemy) {
SetThink(THINKSTATE_ATTACK, THINK_TURRET);
} else {
SetThinkIdle(THINK_IDLE);
}
parm.movedone = true;
Unregister(STRING_MOVEDONE);
}
Unregister(STRING_MOVE);
CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE);
PostThink(true);
}
bool Actor::RunAndShoot_MoveToPatrolCurrentNode(void)
{
UpdatePatrolCurrentNode();
if (!m_patrolCurrentNode && m_bPatrolWaitTrigger) {
IdleLook();
Anim_Idle();
return false;
}
SetPath(m_patrolCurrentNode->origin, "Actor::RunAndShoot_MoveToPatrolCurrentNode", 0, NULL, 0);
if (!PathExists()) {
IdleLook();
Anim_Idle();
parm.movefail = true;
return false;
}
if (MoveOnPathWithSquad()) {
if (m_Enemy) {
m_eNextAnimMode = ANIM_MODE_PATH;
m_csNextAnimString = STRING_ANIM_RUNTO_INOPEN_SCR;
m_bNextForceStart = false;
Vector delta;
Vector lookDir;
delta = mTargetPos - EyePosition();
lookDir = delta;
lookDir[2] += 16;
SetDesiredLookDir(lookDir);
m_DesiredGunDir[0] = 360 - delta.toPitch();
m_DesiredGunDir[1] = delta.toYaw();
m_DesiredGunDir[2] = 0;
SetDesiredYaw(m_DesiredGunDir[1]);
} else {
m_eNextAnimMode = ANIM_MODE_PATH;
m_csNextAnimString = STRING_ANIM_CROUCH_RUN_SCR;
m_bNextForceStart = false;
FaceMotion();
}
} else if (m_Enemy) {
Vector delta;
Vector lookDir;
delta = mTargetPos - EyePosition();
lookDir = delta;
lookDir[2] += 16;
SetDesiredLookDir(lookDir);
m_DesiredGunDir[0] = 360 - delta.toPitch();
m_DesiredGunDir[1] = delta.toYaw();
m_DesiredGunDir[2] = 0;
SetDesiredYaw(m_DesiredGunDir[1]);
Anim_Attack();
} else {
Anim_Stand();
IdleLook();
}
if (!m_fMoveDoneRadiusSquared) {
return false;
}
if (PathComplete()) {
return true;
}
if (!m_Path.HasCompleteLookahead() || m_patrolCurrentNode->Next()) {
return false;
}
if (VectorLength2DSquared(PathDelta()) > m_fMoveDoneRadiusSquared) {
return false;
}
return true;
}
+53 -74
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,90 +24,69 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitRunner
(
GlobalFuncs_t *func
)
void Actor::InitRunner(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_Runner;
func->BeginState = &Actor::Begin_Runner;
func->EndState = &Actor::End_Runner;
func->ResumeState = &Actor::Resume_Runner;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle;
func->ShowInfo = &Actor::ShowInfo_Runner;
func->IsState = &Actor::IsIdleState;
func->ThinkState = &Actor::Think_Runner;
func->BeginState = &Actor::Begin_Runner;
func->EndState = &Actor::End_Runner;
func->ResumeState = &Actor::Resume_Runner;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle;
func->ShowInfo = &Actor::ShowInfo_Runner;
func->IsState = &Actor::IsIdleState;
}
void Actor::Begin_Runner
(
void
)
void Actor::Begin_Runner(void)
{
m_csMood = STRING_NERVOUS;
m_csIdleMood = STRING_NERVOUS;
StopTurning();
ClearPath();
m_csMood = STRING_NERVOUS;
m_csIdleMood = STRING_NERVOUS;
StopTurning();
ClearPath();
}
void Actor::End_Runner
(
void
)
void Actor::End_Runner(void)
{
parm.movefail = true;
parm.movefail = true;
}
void Actor::Resume_Runner
(
void
)
void Actor::Resume_Runner(void) {}
void Actor::Think_Runner(void)
{
;
bool bMoveInRadius;
if (!RequireThink()) {
return;
}
parm.movefail = false;
UpdateEyeOrigin();
NoPoint();
m_pszDebugState = "";
bMoveInRadius = MoveToPatrolCurrentNode();
CheckForThinkStateTransition();
if (!m_patrolCurrentNode) {
SetThinkIdle(THINK_IDLE);
m_bScriptGoalValid = false;
parm.movedone = true;
Unregister(STRING_MOVEDONE);
} else if (bMoveInRadius) {
ClearPatrolCurrentNode();
SetThinkIdle(THINK_IDLE);
parm.movedone = true;
Unregister(STRING_MOVEDONE);
}
Unregister(STRING_MOVE);
PostThink(true);
}
void Actor::Think_Runner
(
void
)
void Actor::ShowInfo_Runner(void)
{
if (RequireThink())
{
parm.movefail = false;
UpdateEyeOrigin();
NoPoint();
m_pszDebugState = "";
CheckForThinkStateTransition();
if (m_patrolCurrentNode)
{
if (!MoveToPatrolCurrentNode())
{
Unregister(STRING_MOVE);
PostThink(true);
return;
}
}
else
{
SetThinkIdle(THINK_IDLE);
m_bScriptGoalValid = false;
}
parm.movedone = true;
Unregister(STRING_MOVEDONE);
Unregister(STRING_MOVE);
PostThink(true);
return;
}
}
void Actor::ShowInfo_Runner
(
void
)
{
ShowInfo_PatrolCurrentNode();
ShowInfo_PatrolCurrentNode();
}
+836 -1093
View File
File diff suppressed because it is too large. Load diff
+100 -140
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,168 +24,128 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitWeaponless
(
GlobalFuncs_t *func
)
void Actor::InitWeaponless(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_Weaponless;
func->BeginState = &Actor::Begin_Weaponless;
func->SuspendState = &Actor::Suspend_Weaponless;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack;
func->FinishedAnimation = &Actor::FinishedAnimation_Weaponless;
func->IsState = &Actor::IsAttackState;
func->ThinkState = &Actor::Think_Weaponless;
func->BeginState = &Actor::Begin_Weaponless;
func->SuspendState = &Actor::Suspend_Weaponless;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack;
func->FinishedAnimation = &Actor::FinishedAnimation_Weaponless;
func->IsState = &Actor::IsAttackState;
}
void Actor::Begin_Weaponless
(
void
)
void Actor::Begin_Weaponless(void)
{
DoForceActivate();
DoForceActivate();
m_csMood = STRING_ALERT;
m_csIdleMood = STRING_NERVOUS;
m_csMood = STRING_ALERT;
m_csIdleMood = STRING_NERVOUS;
if (level.inttime < m_iEnemyChangeTime + 200) {
SetLeashHome(origin);
if (AttackEntryAnimation()) {
m_bLockThinkState = true;
if (level.inttime < m_iEnemyChangeTime + 200)
{
SetLeashHome(origin);
if (AttackEntryAnimation())
{
m_bLockThinkState = true;
TransitionState(902, 0);
}
}
TransitionState(900, 0);
TransitionState(ACTOR_STATE_WEAPONLESS_LOOP, 0);
}
}
TransitionState(ACTOR_STATE_WEAPONLESS_START, 0);
}
void Actor::Suspend_Weaponless
(
void
)
void Actor::Suspend_Weaponless(void)
{
if (m_State <= 902)
{
TransitionState(900, 0);
}
if (m_State == ACTOR_STATE_WEAPONLESS_GRENADE || m_State == ACTOR_STATE_WEAPONLESS_LOOP) {
TransitionState(ACTOR_STATE_WEAPONLESS_START, 0);
}
}
void Actor::Think_Weaponless
(
void
)
void Actor::State_Weaponless_Normal(void)
{
int iStateTime;
if (m_bScriptGoalValid) {
SetPath(m_vScriptGoal, NULL, 0, NULL, 0);
}
if (RequireThink())
{
UpdateEyeOrigin();
NoPoint();
UpdateEnemy(500);
if (PathExists() && !PathComplete()) {
FaceMotion();
Anim_RunToDanger(ANIM_MODE_PATH_GOAL);
return;
}
m_bScriptGoalValid = false;
if (m_State == 902)
{
ContinueAnimation();
}
else
{
m_bLockThinkState = false;
if (!m_Enemy)
{
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_NORMAL);
IdleThink();
return;
}
if (m_State == 900)
{
State_Weaponless_Normal();
}
else if (m_State == 901)
{
State_Weaponless_Grenade();
}
else
{
Com_Printf("Think_Weaponless: invalid think state %i\n", m_State);
char assertStr[16317] = { 0 };
strcpy(assertStr, "\"invalid think state\"\n\tMessage: ");
Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("thinkstate = %i", m_State));
assert(!assertStr);
}
CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_NORMAL);
}
PostThink(true);
if (GetWeapon(WEAPON_MAIN))
SetThink(THINKSTATE_ATTACK, THINK_TURRET);
}
AimAtTargetPos();
Anim_Stand();
if (level.inttime < m_iStateTime) {
return;
}
if (DecideToThrowGrenade(m_Enemy->origin + m_Enemy->velocity, &m_vGrenadeVel, &m_eGrenadeMode, false)) {
SetDesiredYawDir(m_vGrenadeVel);
DesiredAnimation(
ANIM_MODE_NORMAL,
m_eGrenadeMode == AI_GREN_TOSS_ROLL ? STRING_ANIM_GRENADETOSS_SCR : STRING_ANIM_GRENADETHROW_SCR
);
TransitionState(ACTOR_STATE_WEAPONLESS_GRENADE);
} else {
TransitionState(ACTOR_STATE_WEAPONLESS_START, 1000);
}
}
void Actor::FinishedAnimation_Weaponless
(
void
)
void Actor::Think_Weaponless(void)
{
if (m_State <= 902)
{
TransitionState(900, 4000);
}
if (!RequireThink()) {
return;
}
UpdateEyeOrigin();
NoPoint();
UpdateEnemy(500);
if (m_State == ACTOR_STATE_WEAPONLESS_LOOP) {
ContinueAnimation();
} else {
m_bLockThinkState = false;
if (!m_Enemy) {
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE);
IdleThink();
return;
}
if (m_State == ACTOR_STATE_WEAPONLESS_START) {
State_Weaponless_Normal();
} else if (m_State == ACTOR_STATE_WEAPONLESS_GRENADE) {
State_Weaponless_Grenade();
} else {
Com_Printf("Think_Weaponless: invalid think state %i\n", m_State);
char assertStr[16317] = {0};
strcpy(assertStr, "\"invalid think state\"\n\tMessage: ");
Q_strcat(assertStr, sizeof(assertStr), DumpCallTrace("thinkstate = %i", m_State));
assert(!assertStr);
}
if (!CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE)) {
CheckForTransition(THINKSTATE_GRENADE, THINKLEVEL_IDLE);
}
}
PostThink(true);
if (GetWeapon(WEAPON_MAIN)) {
SetThink(THINKSTATE_ATTACK, THINK_TURRET);
}
}
void Actor::State_Weaponless_Normal
(
void
)
void Actor::FinishedAnimation_Weaponless(void)
{
int iStateTime;
if (m_bScriptGoalValid)
SetPath(
m_vScriptGoal,
NULL,
0,
NULL,
0);
if (PathExists() && !PathComplete())
{
FaceMotion();
Anim_RunToDanger(3);
}
else
{
m_bScriptGoalValid = false;
AimAtTargetPos();
Anim_Stand();
if (level.inttime >= m_iStateTime)
{
if (DecideToThrowGrenade(m_Enemy->velocity + m_Enemy->origin, &m_vGrenadeVel, &m_eGrenadeMode))
{
SetDesiredYawDir(m_vGrenadeVel);
m_State = 901;
m_eNextAnimMode = 1;
m_bNextForceStart = false;
m_csNextAnimString = (m_eGrenadeMode == AI_GREN_TOSS_ROLL) ? STRING_ANIM_GRENADETOSS_SCR : STRING_ANIM_GRENADETHROW_SCR;
iStateTime = level.inttime;
}
else
{
m_State = 900;
iStateTime = level.inttime + 1000;
}
m_iStateTime = iStateTime;
}
}
if (m_State == ACTOR_STATE_WEAPONLESS_GRENADE || m_State == ACTOR_STATE_WEAPONLESS_LOOP) {
TransitionState(ACTOR_STATE_WEAPONLESS_NORMAL, 4000);
}
}
void Actor::State_Weaponless_Grenade
(
void
)
void Actor::State_Weaponless_Grenade(void)
{
GenericGrenadeTossThink();
GenericGrenadeTossThink();
}
+479 -633
View File
File diff suppressed because it is too large. Load diff
+103 -71
View File
@@ -22,8 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// actorenemy.h
#ifndef __ACTORENEMY_H__
#define __ACTORENEMY_H__
#pragma once
#include "g_local.h"
#include "class.h"
@@ -32,92 +31,125 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
class Actor;
class Sentient;
class ActorEnemy : public Class {
class ActorEnemy : public Class
{
public:
int m_iAddTime;
float m_fLastLookTime;
float m_fVisibility;
float m_fTotalVisibility;
int m_iThreat;
SafePtr<Sentient> m_pEnemy;
float m_fCurrentRangeSquared;
Vector m_vLastKnownPos;
int m_iLastSightChangeTime;
bool m_bVisible;
int m_iAddTime;
int m_iNextEnemyTime; // Added in 2.0
float m_fLastLookTime;
float m_fVisibility;
float m_fTotalVisibility;
int m_iThreat;
SafePtr<Sentient> m_pEnemy;
float m_fCurrentRangeSquared;
Vector m_vLastKnownPos;
int m_iLastSightChangeTime;
bool m_bVisible;
ActorEnemy();
virtual ~ActorEnemy();
float UpdateVisibility( Actor *pSelf, bool *pbInFovAndRange, bool *pbVisible );
int UpdateThreat( Actor *pSelf );
Sentient *GetEnemy( void ) const;
float GetVisibility( void ) const;
int GetThreat( void ) const;
float GetRangeSquared( void ) const;
float UpdateVisibility(Actor *pSelf, bool *pbInFovAndRange, bool *pbVisible);
int UpdateThreat(Actor *pSelf);
Sentient *GetEnemy(void) const;
float GetVisibility(void) const;
int GetThreat(void) const;
float GetRangeSquared(void) const;
void Archive( Archiver & ) override;
void Archive(Archiver&) override;
protected:
float UpdateLMRF( Actor *pSelf, bool *pbInFovAndRange, bool *pbVisible );
float UpdateLMRF(Actor *pSelf, bool *pbInFovAndRange, bool *pbVisible);
};
inline void ActorEnemy::Archive
(
Archiver& arc
)
inline void ActorEnemy::Archive(Archiver& arc)
{
Class::Archive( arc );
Class::Archive(arc);
arc.ArchiveInteger( &m_iAddTime );
arc.ArchiveFloat( &m_fLastLookTime );
arc.ArchiveFloat( &m_fVisibility );
arc.ArchiveFloat( &m_fTotalVisibility );
arc.ArchiveInteger( &m_iThreat );
arc.ArchiveSafePointer( &m_pEnemy );
arc.ArchiveFloat( &m_fCurrentRangeSquared );
arc.ArchiveVector( &m_vLastKnownPos );
arc.ArchiveInteger( &m_iLastSightChangeTime );
arc.ArchiveBool( &m_bVisible );
arc.ArchiveInteger(&m_iAddTime);
arc.ArchiveFloat(&m_fLastLookTime);
arc.ArchiveFloat(&m_fVisibility);
arc.ArchiveFloat(&m_fTotalVisibility);
arc.ArchiveInteger(&m_iThreat);
arc.ArchiveSafePointer(&m_pEnemy);
arc.ArchiveFloat(&m_fCurrentRangeSquared);
arc.ArchiveVector(&m_vLastKnownPos);
arc.ArchiveInteger(&m_iLastSightChangeTime);
arc.ArchiveBool(&m_bVisible);
}
class ActorEnemySet : public Class {
inline Sentient *ActorEnemy::GetEnemy(void) const
{
return m_pEnemy;
}
inline float ActorEnemy::GetVisibility(void) const
{
return m_fVisibility;
}
inline int ActorEnemy::GetThreat(void) const
{
return m_iThreat;
}
inline float ActorEnemy::GetRangeSquared(void) const
{
return m_fCurrentRangeSquared;
}
class ActorEnemySet : public Class
{
protected:
Container<ActorEnemy> m_Enemies;
int m_iCheckCount;
SafePtr<Sentient> m_pCurrentEnemy;
float m_fCurrentVisibility;
int m_iCurrentThreat;
Container<ActorEnemy> m_Enemies;
int m_iCheckCount;
SafePtr<Sentient> m_pCurrentEnemy;
float m_fCurrentVisibility;
int m_iCurrentThreat;
public:
ActorEnemySet();
virtual ~ActorEnemySet();
ActorEnemySet();
ActorEnemy *AddPotentialEnemy( Sentient *pEnemy );
void FlagBadEnemy( Sentient *pEnemy );
void CheckEnemies( Actor *pSelf );
Sentient *GetCurrentEnemy( void ) const;
float GetCurrentVisibility( void ) const;
int GetCurrentThreat( void ) const;
qboolean IsEnemyConfirmed( void ) const;
bool HasAlternateEnemy( void ) const;
void RemoveAll( void );
void ConfirmEnemy( Actor *pSelf, Sentient *pEnemy );
void ConfirmEnemyIfCanSeeSharerOrEnemy( Actor *pSelf, Actor *pSharer, Sentient *pEnemy );
bool CaresAboutPerfectInfo( Sentient *pEnemy );
ActorEnemy *AddPotentialEnemy(Sentient *pEnemy);
void FlagBadEnemy(Sentient *pEnemy);
void CheckEnemies(Actor *pSelf);
Sentient *GetCurrentEnemy(void) const;
float GetCurrentVisibility(void) const;
int GetCurrentThreat(void) const;
qboolean IsEnemyConfirmed(void) const;
bool HasAlternateEnemy(void) const;
void RemoveAll(void);
void ConfirmEnemy(Actor *pSelf, Sentient *pEnemy);
void ConfirmEnemyIfCanSeeSharerOrEnemy(Actor *pSelf, Actor *pSharer, Sentient *pEnemy);
bool CaresAboutPerfectInfo(Sentient *pEnemy);
void Archive( Archiver& arc ) override;
void Archive(Archiver& arc) override;
};
inline void ActorEnemySet::Archive
(
Archiver& arc
)
inline Sentient *ActorEnemySet::GetCurrentEnemy(void) const
{
Class::Archive( arc );
m_Enemies.Archive( arc, ArchiveClass< ActorEnemy > );
arc.ArchiveInteger( &m_iCheckCount );
arc.ArchiveSafePointer( &m_pCurrentEnemy );
arc.ArchiveFloat( &m_fCurrentVisibility );
arc.ArchiveInteger( &m_iCurrentThreat );
return m_pCurrentEnemy;
}
#endif /* actorenemy.h */
inline float ActorEnemySet::GetCurrentVisibility(void) const
{
return m_fCurrentVisibility;
}
inline int ActorEnemySet::GetCurrentThreat(void) const
{
return m_iCurrentThreat;
}
inline qboolean ActorEnemySet::IsEnemyConfirmed(void) const
{
return m_fCurrentVisibility > 0.999f;
}
inline void ActorEnemySet::Archive(Archiver& arc)
{
Class::Archive(arc);
m_Enemies.Archive(arc);
arc.ArchiveInteger(&m_iCheckCount);
arc.ArchiveSafePointer(&m_pCurrentEnemy);
arc.ArchiveFloat(&m_fCurrentVisibility);
arc.ArchiveInteger(&m_iCurrentThreat);
}
Loaded 100 of 515 files, more files were not shown because too many files have changed in this diff. Show more