Compare commits

...
822 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
434 changed files with 89752 additions and 128560 deletions

No files matched your search

+10 -1
View File
@@ -11,7 +11,7 @@ if(TARGET_GAME_TYPE)
endif()
set(TARGET_BASE_GAME "main")
set(TARGET_BASE_GAME "./")
set(CMAKE_DEBUG_POSTFIX "-dbg")
if(MSVC)
@@ -22,6 +22,13 @@ 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()
@@ -47,6 +54,7 @@ ENDIF()
IF(CMAKE_BUILD_TYPE MATCHES Debug)
add_definitions(-D_DEBUG)
# NOTE: The following may mess up function importation
#if(UNIX)
# # Enable all exports so all functions name can be seen during executable crash
# set(CMAKE_ENABLE_EXPORTS ON)
@@ -73,6 +81,7 @@ target_compile_features(omohaaded PUBLIC c_variadic_macros)
target_link_libraries(omohaaded PRIVATE omohserver)
target_link_libraries(omohaaded PRIVATE syslib)
target_link_libraries(omohaaded PRIVATE qcommon qcommon_standalone)
# Gamespy dependency
target_include_directories(omohaaded PUBLIC "code/qcommon" "code/script" "code/gamespy" "code/server")
set_target_properties(omohaaded PROPERTIES OUTPUT_NAME "omohaaded${TARGET_BASE_SUFFIX}${TARGET_ARCH_SUFFIX}")
+92 -24
View File
@@ -17,25 +17,49 @@
## Current State
OpenMoHAA is still under development. The single-player campaign is not yet functional due to AI not being fully implemented, and due to the script engine having a few issues. But the `training` map can be played from start to end. The current focus is on multiplayer.
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
You can now start a local OpenMOHAA server or play on a server.
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:
@@ -43,9 +67,11 @@ You can now start a local OpenMOHAA server or play on a server.
- `+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.
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
With `com_target_game`, OpenMoHAA will support the network protocol accordingly.
You can now start a local OpenMOHAA server or play on a server.
### Playing with bots
@@ -57,7 +83,7 @@ This feature is a great way to test the gameplay and mods.
### Server
The server version can be built successfully, but some features are not functional. For example, the Actor and Vehicle systems are almost fully implemented, but they are not yet stable. This means that they may not work as expected and could cause crashes.
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 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.
@@ -76,7 +102,7 @@ The current operational status for each component is as follow:
| Model/TIKI/Skeletor | x | | | | | | |
| Renderer | | x | | | | | Missing ghost, marks, sphere lights, sky portal, sun flare, swipe |
| Server | | x | | | | | Probably a few bugs remaining |
| Server module (fgame) | | x | | | | | Actor, vehicle, and few gameplay bugs |
| Server module (fgame) | | x | | | | | Actor, and few gameplay bugs |
| UI | | | x | | | | Has core features only (menu, widgets, console, hud, urc loading) |
## Compiling
@@ -85,30 +111,36 @@ OpenMoHAA supports any architecture, thanks to the CMake build system and cross-
The following tools are required for all platforms:
- CMake >= 3.5
- Flex and Bison
- Flex (>= 2.6.4) and Bison (>= 3.5.1)
- A C++11 compiler is also required.
The installation directory can be set to the MOHAA directory.
By default, the build will produce both the client and dedicated server versions. The client build can be excluded by appending `-DBUILD_NO_CLIENT=1` to the CMake command-line arguments. Using this parameter will result in only the server portion being built.
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 Linux :
- Clang >= 3.3 or GCC >= 4.8.1
- 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 -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.
@@ -119,12 +151,48 @@ Append `-DFLEX_EXECUTABLE=...\win_flex.exe -DBISON_EXECUTABLE=...\win_bison.exe`
## Screenshots
| | |
|-------------------------------------------------------------------------------|----------------------------------------------------------------------|
| ![](docs/images/opmtt-x86_64_0.56.0_1.png "Playing on a Breakthrough server") | ![](docs/images/opmtt-x86_64_0.56.0_2.png) |
| ![](docs/images/opmtt-x86_64_0.56.0_3.png) | ![](docs/images/opm-arm_53_tt_1.png "OpenMoHAA on Raspberry Pi 4 B") |
| ![](docs/images/opm-x86_64_0.58.0_1.png "Playing Freeze-Tag mode with bots") | ![](docs/images/opm-x86_64_0.58.0_2.png "Single-Player training") |
| | |
|-----------------------------------------------------------------------------------|----------------------------------------------------------------------------|
| ![](docs/images/v0.60.0-x86_64/mohdm1_1.png) | ![](docs/images/v0.60.0-x86_64/training_1.png) |
| ![](docs/images/v0.60.0-x86_64/flughafen_1.png) | ![](docs/images/v0.60.0-x86_64/flughafen_2.png) |
| ![](docs/images/v0.60.0-x86_64/mohdm2_1.png "Playing Freeze-Tag mode with bots") | ![](docs/images/v0.60.0-x86_64/training_3.png "Single-Player training") |
*More screenshots [here](docs/images)*
## 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
+1 -1
View File
@@ -18,7 +18,7 @@ set(SOURCES_SHARED
"../script/scriptvariable.cpp"
)
file(GLOB_RECURSE SOURCES_BG "../fgame/bg_misc.cpp" "../fgame/bg_pmove.cpp" "../fgame/bg_slidemove.cpp")
file(GLOB_RECURSE SOURCES_BG "../fgame/bg_misc.cpp" "../fgame/bg_pmove.cpp" "../fgame/bg_slidemove.cpp" "../fgame/bg_voteoptions.cpp")
file(GLOB_RECURSE SOURCES_CGAME "./*.c" "./*.cpp")
add_library(cgame SHARED ${SOURCES_CGAME} ${SOURCES_BG})
+142 -10
View File
@@ -22,43 +22,175 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cg_local.h"
#include "cg_archive.h"
#include "cg_commands.h"
#include "memarchiver.h"
#include "../qcommon/tiki.h"
void CG_ArchiveStuff(MemArchiver& archiver, int svsTime)
{
// FIXME: unimplemented
archiver.SetBaseTime(svsTime);
commandManager.ArchiveToMemory(archiver);
CG_ArchiveVSSGlobals(archiver);
}
void CG_SaveStateToBuffer(void** out, int svsTime)
size_t CG_SaveStateToBuffer(void** out, int svsTime)
{
// FIXME: unimplemented
MemArchiver archiver;
size_t size;
archiver.SetupForWriting(0x200000);
CG_ArchiveStuff(archiver, svsTime);
size = archiver.BufferSize();
if (size && out) {
*out = archiver.ConfiscateBuffer();
}
return size;
}
void CG_LoadStateToBuffer(void* state, int size, int svsTime)
qboolean CG_LoadStateToBuffer(void* state, size_t size, int svsTime)
{
// FIXME: unimplemented
MemArchiver archiver;
archiver.SetupForReading((byte*)state, size);
CG_ArchiveStuff(archiver, svsTime);
return archiver.FinishedReading();
}
void CG_ArchiveStringContainer(MemArchiver& archiver, Container<str>* container)
{
// FIXME: unimplemented
int num;
int i;
if (archiver.IsReading()) {
str tmp;
archiver.ArchiveInteger(&num);
container->ClearObjectList();
for (i = 0; i < num; i++) {
archiver.ArchiveString(&tmp);
container->AddObject(tmp);
}
} else {
num = container->NumObjects();
archiver.ArchiveInteger(&num);
for (i = 0; i < num; i++) {
str& tmp = container->ObjectAt(i + 1);
archiver.ArchiveString(&tmp);
}
}
}
void CG_ArchiveTikiPointer(MemArchiver& archiver, dtiki_t** pTiki)
{
// FIXME: unimplemented
str tmp;
if (archiver.IsReading()) {
archiver.ArchiveString(&tmp);
if (tmp.length()) {
*pTiki = cgi.R_Model_GetHandle(cgi.R_RegisterModel(tmp.c_str()));
} else {
*pTiki = NULL;
}
} else {
if (*pTiki) {
tmp = (*pTiki)->name;
}
archiver.ArchiveString(&tmp);
}
}
void CG_ArchiveModelHandle(MemArchiver& archiver, qhandle_t* handle)
{
// FIXME: unimplemented
str tmp;
if (archiver.IsReading()) {
archiver.ArchiveString(&tmp);
if (tmp.length()) {
*handle = cgi.R_RegisterModel(tmp.c_str());
} else {
*handle = NULL;
}
} else {
if (*handle) {
tmp = cgi.R_GetModelName(*handle);
} else {
tmp = "";
}
archiver.ArchiveString(&tmp);
}
}
void CG_ArchiveShaderHandle(MemArchiver& archiver, qhandle_t* handle)
{
// FIXME: unimplemented
str tmp;
if (archiver.IsReading()) {
archiver.ArchiveString(&tmp);
if (tmp.length()) {
*handle = cgi.R_RegisterShader(tmp.c_str());
} else {
*handle = NULL;
}
} else {
if (*handle) {
tmp = cgi.R_GetShaderName(*handle);
} else {
tmp = "";
}
archiver.ArchiveString(&tmp);
}
}
void CG_ArchiveRefEntity(MemArchiver& archiver, refEntity_t* ref)
{
// FIXME: unimplemented
archiver.ArchiveRaw(&ref->reType, sizeof(ref->reType));
archiver.ArchiveInteger(&ref->renderfx);
CG_ArchiveModelHandle(archiver, &ref->hModel);
CG_ArchiveModelHandle(archiver, &ref->hOldModel);
archiver.ArchiveVec3(ref->lightingOrigin);
archiver.ArchiveInteger(&ref->parentEntity);
archiver.ArchiveVec3(ref->axis[0]);
archiver.ArchiveVec3(ref->axis[1]);
archiver.ArchiveVec3(ref->axis[2]);
archiver.ArchiveBoolean(&ref->nonNormalizedAxes);
archiver.ArchiveVec3(ref->origin);
archiver.ArchiveRaw(ref->frameInfo, 192);
archiver.ArchiveFloat(&ref->actionWeight);
archiver.ArchiveShort(&ref->wasframe);
archiver.ArchiveFloat(&ref->scale);
archiver.ArchiveVec3(ref->oldorigin);
archiver.ArchiveInteger(&ref->skinNum);
CG_ArchiveShaderHandle(archiver, &ref->customShader);
archiver.ArchiveRaw(ref->shaderRGBA, 4);
archiver.ArchiveFloat(ref->shaderTexCoord);
archiver.ArchiveFloat(&ref->shaderTexCoord[1]);
archiver.ArchiveFloat(&ref->shaderTime);
archiver.ArchiveInteger(&ref->entityNumber);
archiver.ArchiveRaw(ref->surfaces, 32);
archiver.ArchiveFloat(ref->shader_data);
archiver.ArchiveFloat(&ref->shader_data[1]);
ref->bone_tag = NULL;
ref->bone_quat = NULL;
ref->of = NULL;
ref->nf = NULL;
CG_ArchiveTikiPointer(archiver, &ref->tiki);
archiver.ArchiveInteger(&ref->bonestart);
archiver.ArchiveInteger(&ref->morphstart);
archiver.ArchiveBoolean(&ref->hasMorph);
archiver.ArchiveFloat(&ref->radius);
archiver.ArchiveFloat(&ref->rotation);
}
+3 -5
View File
@@ -30,15 +30,13 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "../qcommon/container.h"
#include "../qcommon/str.h"
class MemArchiver {
};
class MemArchiver;
extern "C" {
#endif
void CG_SaveStateToBuffer(void** out, int svsTime);
void CG_LoadStateToBuffer(void* state, int size, int svsTime);
size_t CG_SaveStateToBuffer(void** out, int svsTime);
qboolean CG_LoadStateToBuffer(void* state, size_t size, int svsTime);
#ifdef __cplusplus
void CG_ArchiveStuff(MemArchiver& archiver, int svsTime);
+1143 -306
View File
File diff suppressed because it is too large. Load diff
+94 -19
View File
@@ -116,6 +116,7 @@ TIKI file, similar to ScriptMaster in the server game dll.
class spawnthing_t;
class specialeffect_t;
class MemArchiver;
typedef enum {
NOT_RANDOM,
@@ -181,6 +182,9 @@ public:
float decal_orientation;
float decal_radius;
float spin_rotation;
public:
void ArchiveToMemory(MemArchiver& archiver);
};
inline cg_common_data::cg_common_data()
@@ -249,6 +253,9 @@ public:
spawnthing_t *m_spawnthing;
void (*touchfcn)(ctempmodel_t *ct, trace_t *trace);
public:
void ArchiveToMemory(MemArchiver& archiver);
};
inline ctempmodel_t::ctempmodel_t()
@@ -315,8 +322,44 @@ public:
int lastPhysicsTime;
int lastLightingTime;
qboolean lastValid;
public:
cvssource_t();
public:
void ArchiveToMemory(MemArchiver& archiver);
};
inline cvssource_t::cvssource_t()
: next(NULL)
, prev(NULL)
, stnext(NULL)
, stindex(0)
, lastRadius(0)
, lastDensity(0)
, lastColor {0}
, lastLighting {0}
, newRadius(0)
, newDensity(0)
, newColor {0}
, newLighting {0}
, ooRadius(0)
, startAlpha(0)
, roll(0)
, lifeTime(0)
, collisionmask(0)
, parent(0)
, flags(0)
, flags2(0)
, smokeType(0)
, typeInfo(0)
, fadeMult(0)
, scaleMult(0)
, lastPhysicsTime(0)
, lastLightingTime(0)
, lastValid(qfalse)
{}
class cvssourcestate_t
{
public:
@@ -387,6 +430,9 @@ public:
protected:
qboolean usedNumbers[256];
virtual void RemoveEntity(int entnum);
public:
void ArchiveToMemory(MemArchiver& archiver);
};
inline enttracker_t::enttracker_t()
@@ -437,6 +483,9 @@ public:
Vector oldorigin;
qboolean active;
qboolean lerp_emitter;
public:
void ArchiveToMemory(MemArchiver& archiver);
};
// emitterthing_t is used to keep track of the last time and emitter was updated
@@ -452,6 +501,9 @@ public:
emittertime_t *GetEmitTime(int entnum);
virtual void RemoveEntity(int entnum);
qboolean startoff;
public:
void ArchiveToMemory(MemArchiver& archiver);
};
inline void emitterthing_t::RemoveEntity(int entnum)
@@ -510,18 +562,23 @@ public:
int entity_number;
int command_number;
int last_command_time;
public:
void ArchiveToMemory(MemArchiver& archiver);
};
// This class is used for keeping track of the last time an entity executed a
// particular command. A command number must be assigned externally by the user
class commandthing_t : public enttracker_t
{
Container<commandtime_t *> m_commandtimes; // A list of entity numbers and the last time they
// executed a command
Container<commandtime_t> m_commandtimes; // A list of entity numbers and the last time they
// executed a command
public:
commandtime_t *GetLastCommandTime(int entnum, int commandnum);
virtual void RemoveEntity(int entnum);
void ArchiveToMemory(MemArchiver& archiver);
};
inline void commandthing_t::RemoveEntity(int entnum)
@@ -532,7 +589,7 @@ inline void commandthing_t::RemoveEntity(int entnum)
count = m_commandtimes.NumObjects();
for (num = count; num >= 1; num--) {
ct = m_commandtimes.ObjectAt(num);
ct = &m_commandtimes.ObjectAt(num);
if (ct->entity_number == entnum) {
m_commandtimes.RemoveObjectAt(num);
}
@@ -543,28 +600,27 @@ inline void commandthing_t::RemoveEntity(int entnum)
inline commandtime_t *commandthing_t::GetLastCommandTime(int entnum, int commandnum)
{
int num, count;
commandtime_t *ct;
int num, count;
// Search for this entity number
count = m_commandtimes.NumObjects();
for (num = 1; num <= count; num++) {
ct = m_commandtimes.ObjectAt(num);
commandtime_t *ct = &m_commandtimes.ObjectAt(num);
if ((ct->entity_number == entnum) && (ct->command_number == commandnum)) {
return ct;
}
}
// Add a new entry if we didn't find it
ct = new commandtime_t;
ct->entity_number = entnum;
ct->command_number = commandnum;
ct->last_command_time = 0;
commandtime_t ct;
ct.entity_number = entnum;
ct.command_number = commandnum;
ct.last_command_time = 0;
m_commandtimes.AddObject(ct);
return ct;
return &m_commandtimes.ObjectAt(m_commandtimes.NumObjects());
}
class spawnthing_t : public emitterthing_t
@@ -625,6 +681,9 @@ public:
void (*touchfcn)(ctempmodel_t *ct, trace_t *trace);
str GetModel(void);
void SetModel(str model);
public:
void ArchiveToMemory(MemArchiver& archiver);
};
inline void spawnthing_t::SetModel(str model)
@@ -824,8 +883,8 @@ private:
void SetClampVel(Event *ev);
void SetClampVelAxis(Event *ev);
ctempmodel_t *AllocateTempModel(void);
qboolean TempModelPhysics(ctempmodel_t *p, float ftime, float time2, float scale);
qboolean TempModelRealtimeEffects(ctempmodel_t *p, float ftime, float time2, float scale);
qboolean TempModelPhysics(ctempmodel_t *p, float ftime, float scale);
qboolean TempModelRealtimeEffects(ctempmodel_t *p, float ftime, float scale);
qboolean LerpTempModel(refEntity_t *newEnt, ctempmodel_t *p, float frac);
void SpawnEffect(int count, int timealive);
void SpawnTempModel(int count);
@@ -871,13 +930,13 @@ public:
void UpdateEmitter(dtiki_t *tiki, vec3_t axis[3], int entity_number, int parent_number, Vector entity_origin);
void UpdateBeam(dtiki_t *tiki, int entity_number, spawnthing_t *beamthing);
void PlaySound(
str sound_name,
str sound_name,
const vec3_t origin = NULL,
int channel = CHAN_AUTO,
float volume = -1,
float min_distance = -1,
float pitch = -1,
int argstype = 0
int channel = CHAN_AUTO,
float volume = -1,
float min_distance = -1,
float pitch = -1,
int argstype = 0
);
spawnthing_t *InitializeSpawnthing(spawnthing_t *ep);
@@ -891,6 +950,7 @@ public:
void InitializeEmitters(void);
void RemoveClientEntity(int number, dtiki_t *tiki, centity_t *cent, ctempmodel_t *p = NULL);
void ClearSwipes(void);
void FreeSpawnthing(spawnthing_t *sp);
void ResetTempModels(void);
void SpawnTempModel(int count, spawnthing_t *sp);
@@ -921,6 +981,21 @@ public:
void ResetTreadMarkSources(Event *ev);
void InitializeRainCvars();
void InitializeBeams();
//
// archive stuff
//
int IdForTempModel(const ctempmodel_t *model);
ctempmodel_t *TempModelForId(int id);
int IdForSpawnThing(const spawnthing_t *sp);
spawnthing_t *SpawnThingForId(int id);
int IdForVssSource(const cvssource_t *source);
cvssource_t *VssSourceForId(int id);
void ArchiveTempModelPointerToMemory(MemArchiver& archiver, ctempmodel_t **model);
void ArchiveSpawnThingPointerToMemory(MemArchiver& archiver, spawnthing_t **sp);
void ArchiveVssSourcePointerToMemory(MemArchiver& archiver, cvssource_t **source);
void ArchiveToMemory(MemArchiver& archiver);
};
class EmitterLoader : public Listener
+169 -6
View File
@@ -323,8 +323,12 @@ static void CG_DrawPauseIcon()
}
w = cgi.R_GetShaderWidth(handle);
h = cgi.R_GetShaderHeight(handle);
x = w / 4;
y = cgs.glconfig.vidHeight - (1.25f * h);
if (cg.snap && cg.snap->ps.blend[3] > 0) {
y = cgs.glconfig.vidHeight * 0.45f - h / 2.f;
} else {
y = cgs.glconfig.vidHeight * 0.75f - h / 2.f;
}
x = (cgs.glconfig.vidWidth - w) / 2.f;
cgi.R_SetColor(colorWhite);
cgi.R_DrawStretchPic(x, y, w, h, 0, 0, 1, 1, handle);
@@ -682,11 +686,11 @@ void CG_DrawObjectives()
iTotalNumLines = 0;
for (i = CS_OBJECTIVES; i < CS_OBJECTIVES + MAX_OBJECTIVES; ++i) {
CG_ProcessConfigString(i);
CG_ProcessConfigString(i, qfalse);
}
iCurrentObjective = atoi(CG_ConfigString(CS_CURRENT_OBJECTIVE));
fTimeDelta = cg.ObjectivesAlphaTime - cg.time;
iCurrentObjective = atoi(CG_ConfigString(CS_CURRENT_OBJECTIVE));
fTimeDelta = cg.ObjectivesAlphaTime - cg.time;
cg.ObjectivesCurrentAlpha = cg.ObjectivesDesiredAlpha;
if (fTimeDelta > 0) {
cg.ObjectivesCurrentAlpha =
@@ -1083,7 +1087,7 @@ void CG_DrawSpectatorView_ver_15()
iClientNum = cg.snap->ps.stats[STAT_INFOCLIENT];
sprintf(buf, "%s : %i", cg.clientinfo[iClientNum].name, cg.snap->ps.stats[STAT_INFOCLIENT_HEALTH]);
hShader = 0;
hShader = 0;
color[0] = 0.5;
color[1] = 1.0;
color[2] = 0.5;
@@ -1165,6 +1169,163 @@ void CG_DrawSpectatorView()
}
}
void CG_DrawCrosshair()
{
centity_t *friendEnt;
qhandle_t shader;
vec3_t forward;
vec3_t end;
vec3_t mins, maxs;
trace_t trace;
float x, y;
float width, height;
shader = NULL;
if (!cg_hud->integer || !ui_crosshair->integer) {
return;
}
if (!cg.snap) {
return;
}
if ((cg.snap->ps.pm_flags & PMF_NO_LEAN) || (cg.snap->ps.pm_flags & PMF_INTERMISSION)) {
return;
}
if (!cg.snap->ps.stats[STAT_CROSSHAIR]
&& (!cg.snap->ps.stats[STAT_INZOOM] || cg.snap->ps.stats[STAT_INZOOM] > 30)) {
return;
}
if (cgs.gametype != GT_FFA) {
AngleVectorsLeft(cg.refdefViewAngles, forward, NULL, NULL);
VectorMA(cg.refdef.vieworg, 8192, forward, end);
VectorClear(mins);
VectorClear(maxs);
CG_Trace(&trace, cg.refdef.vieworg, mins, maxs, end, 9999, MASK_SOLID, qfalse, qtrue, "CG_DrawCrosshair");
// ENTITYNUM_WORLD check added in OPM
if ((trace.entityNum != ENTITYNUM_NONE && trace.entityNum != ENTITYNUM_WORLD)
&& trace.entityNum != cg.snap->ps.clientNum) {
int myFlags;
friendEnt = &cg_entities[trace.entityNum];
if (cgs.gametype != GT_SINGLE_PLAYER) {
myFlags = cg_entities[cg.snap->ps.clientNum].currentState.eFlags & EF_ANY_TEAM;
} else {
// the player will always be considered as an allied
// in single-player
myFlags = EF_ALLIES;
}
if (((myFlags & EF_ALLIES) && (friendEnt->currentState.eFlags & EF_ALLIES))
|| ((myFlags & EF_AXIS) && (friendEnt->currentState.eFlags & EF_AXIS))) {
// friend
if (cg.snap->ps.stats[STAT_CROSSHAIR]) {
shader = cgi.R_RegisterShader(cg_crosshair_friend->string);
}
} else {
// enemy
if (cg.snap->ps.stats[STAT_CROSSHAIR]) {
shader = cgi.R_RegisterShader(cg_crosshair->string);
}
}
} else {
if (cg.snap->ps.stats[STAT_CROSSHAIR]) {
shader = cgi.R_RegisterShader(cg_crosshair->string);
}
}
} else {
// FFA
if (cg.snap->ps.stats[STAT_CROSSHAIR]) {
shader = cgi.R_RegisterShader(cg_crosshair->string);
}
}
if (shader) {
width = cgi.R_GetShaderWidth(shader);
height = cgi.R_GetShaderHeight(shader);
x = (cgs.glconfig.vidWidth - width) * 0.5f;
y = (cgs.glconfig.vidHeight - height) * 0.5f;
cgi.R_SetColor(NULL);
cgi.R_DrawStretchPic(x, y, width, height, 0, 0, 1, 1, shader);
}
}
void CG_DrawVote()
{
const char *text;
int seconds;
int percentYes;
int percentNo;
int percentUndecided;
float x, y;
vec4_t col;
if (!cgs.voteTime) {
return;
}
if (cgs.voteRefreshed) {
cgs.voteRefreshed = qfalse;
}
seconds = (30000 - (cg.time - cgs.voteTime)) / 1000 + 1;
if (seconds < 0) {
seconds = 0;
}
percentYes = cgs.numVotesYes * 100 / (cgs.numUndecidedVotes + cgs.numVotesNo + cgs.numVotesYes);
percentNo = cgs.numVotesNo * 100 / (cgs.numUndecidedVotes + cgs.numVotesNo + cgs.numVotesYes);
percentUndecided = cgs.numUndecidedVotes * 100 / (cgs.numUndecidedVotes + cgs.numVotesNo + cgs.numVotesYes);
x = 8;
y = (cgs.glconfig.vidHeight > 480) ? (cgs.glconfig.vidHeight * 0.725f) : (cgs.glconfig.vidHeight * 0.75f);
cgi.R_SetColor(NULL);
text = va("%s: %s", cgi.LV_ConvertString("Vote Running"), cgs.voteString);
cgi.R_DrawString(cgs.media.attackerFont, text, x, y, -1, qfalse);
y += 12;
text =
va("%s: %isec %s: %i%% %s: %i%% %s: %i%%",
cgi.LV_ConvertString("Time"),
seconds,
cgi.LV_ConvertString("Yes"),
percentYes,
cgi.LV_ConvertString("No"),
percentNo,
cgi.LV_ConvertString("Undecided"),
percentUndecided);
cgi.R_DrawString(cgs.media.attackerFont, text, x, y, -1, qfalse);
if (cg.snap && !cg.snap->ps.voted) {
col[0] = 0.5;
col[1] = 1.0;
col[2] = 0.5;
col[3] = 1.0;
cgi.R_SetColor(col);
y += 12;
text = cgi.LV_ConvertString("Vote now, it's your patriotic duty!");
cgi.R_DrawString(cgs.media.attackerFont, text, x, y, -1, qfalse);
y += 12;
text = cgi.LV_ConvertString("To vote Yes, press F1. To vote No, press F2.");
cgi.R_DrawString(cgs.media.attackerFont, text, x, y, -1, qfalse);
cgi.R_SetColor(NULL);
}
}
/*
==============
CG_Draw2D
@@ -1183,5 +1344,7 @@ void CG_Draw2D(void)
CG_DrawPlayerTeam();
CG_DrawPlayerEntInfo();
CG_UpdateAttackerDisplay();
CG_DrawVote();
CG_DrawInstantMessageMenu();
CG_DrawCrosshair();
}
+22 -1
View File
@@ -35,6 +35,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cg_public.h"
#ifdef __cplusplus
class MemArchiver;
extern "C" {
#endif
@@ -394,8 +396,19 @@ extern "C" {
int maxclients;
int cinematic;
int mapChecksum;
qboolean useMapChecksum;
char mapname[MAX_QPATH];
//
// vote
//
int voteTime;
int numVotesYes;
int numVotesNo;
int numUndecidedVotes;
qboolean voteRefreshed;
char voteString[1024];
//
// locally derived information from gamestate
//
@@ -458,6 +471,9 @@ extern "C" {
extern cvar_t *cg_hud;
extern cvar_t *cg_huddraw_force;
extern cvar_t *cg_drawsvlag;
extern cvar_t *cg_crosshair;
extern cvar_t *cg_crosshair_friend;
extern cvar_t *ui_crosshair;
extern cvar_t *vm_offset_max;
extern cvar_t *vm_offset_speed;
extern cvar_t *vm_sway_front;
@@ -488,7 +504,7 @@ extern "C" {
//
// cg_main.c
//
void CG_ProcessConfigString(int num);
void CG_ProcessConfigString(int num, qboolean modelOnly);
const char *CG_ConfigString(int index);
void CG_AddToTeamChat(const char *str);
void CG_NewClientinfo(int clientNum);
@@ -530,6 +546,8 @@ extern "C" {
// cg_tempmodels.cpp
//
extern cvar_t *cg_showtempmodels;
extern cvar_t *cg_max_tempmodels;
extern cvar_t *cg_reserve_tempmodels;
extern cvar_t *cg_detail;
extern cvar_t *cg_effectdetail;
extern cvar_t *cg_effect_physicsrate;
@@ -911,6 +929,9 @@ qboolean CG_LightStyleColor(int style, int realtime, vec4_t color, qboolean clam
//
// cg_volumetricsmoke.cpp
void CG_ResetVSSSources(void);
#ifdef __cplusplus
void CG_ArchiveVSSGlobals(MemArchiver& archiver);
#endif
void CG_AddVSSSources(void);
extern cvar_t *vss_draw;
+198 -122
View File
@@ -80,6 +80,9 @@ cvar_t *cg_acidtrip;
cvar_t *cg_hud;
cvar_t *cg_huddraw_force;
cvar_t *cg_drawsvlag;
cvar_t *cg_crosshair;
cvar_t *cg_crosshair_friend;
cvar_t *ui_crosshair;
cvar_t *vm_offset_max;
cvar_t *vm_offset_speed;
cvar_t *vm_sway_front;
@@ -159,6 +162,15 @@ void CG_RegisterCvars(void)
cg_hud = cgi.Cvar_Get("cg_hud", "0", 0);
cg_huddraw_force = cgi.Cvar_Get("cg_huddraw_force", "0", CVAR_SAVEGAME);
cg_drawsvlag = cgi.Cvar_Get("cg_drawsvlag", "1", CVAR_ARCHIVE);
cg_crosshair = cgi.Cvar_Get("cg_crosshair", "textures/hud/crosshair", CVAR_ARCHIVE);
if (cg_protocol >= PROTOCOL_MOHTA_MIN) {
cg_crosshair_friend = cgi.Cvar_Get("cg_crosshair_friend", "textures/hud/crosshair_friend", CVAR_ARCHIVE);
} else {
// on 1.11 and below, fallback to standard crosshair
// as it doesn't have crosshair_friend texture
cg_crosshair_friend = cgi.Cvar_Get("cg_crosshair_friend", "textures/hud/crosshair", CVAR_ARCHIVE);
}
ui_crosshair = cgi.Cvar_Get("ui_crosshair", "1", CVAR_ARCHIVE);
vm_offset_max = cgi.Cvar_Get("vm_offset_max", "8.0", 0);
vm_offset_speed = cgi.Cvar_Get("vm_offset_speed", "8.0", 0);
vm_sway_front = cgi.Cvar_Get("vm_sway_front", "0.1", 0);
@@ -233,91 +245,48 @@ void CG_RegisterSounds(void)
Com_Printf("-------------UBERDIALOG DONE---------------\n\n");
}
/*
================
CG_IsHandleUnique
Check if the model handle is unique
================
*/
static qboolean CG_IsHandleUnique(int num) {
qhandle_t handle;
int i;
int numRef;
numRef = 0;
handle = cgs.model_draw[num];
for (i = 0; i < MAX_MODELS; i++) {
if (cgs.model_draw[i] == handle) {
numRef++;
if (numRef >= 2) {
return qfalse;
}
}
}
return qtrue;
}
/*
================
CG_ProcessConfigString
================
*/
void CG_ProcessConfigString(int num)
void CG_ProcessConfigString(int num, qboolean modelOnly)
{
const char *str = CG_ConfigString(num);
int i;
const char* str;
int i;
switch (num) {
case CS_RAIN_DENSITY:
cg.rain.density = atof(str);
return;
case CS_RAIN_SPEED:
cg.rain.speed = atof(str);
return;
case CS_RAIN_SPEEDVARY:
cg.rain.speed_vary = atoi(str);
return;
case CS_RAIN_SLANT:
cg.rain.slant = atoi(str);
return;
case CS_RAIN_LENGTH:
cg.rain.length = atof(str);
return;
case CS_RAIN_MINDIST:
cg.rain.min_dist = atof(str);
return;
case CS_RAIN_WIDTH:
cg.rain.width = atof(str);
return;
case CS_RAIN_SHADER:
if (cg.rain.numshaders) {
for (i = 0; i < cg.rain.numshaders; i++) {
sprintf(cg.rain.shader[i], "%s%i", str, i);
}
} else {
strcpy(cg.rain.shader[0], str);
}
return;
case CS_RAIN_NUMSHADERS:
cg.rain.numshaders = atoi(str);
if (cg.rain.numshaders) {
for (i = 0; i < cg.rain.numshaders; i++) {
sprintf(cg.rain.shader[i], "%s%i", str, i);
}
}
return;
}
if (num >= CS_OBJECTIVES && num < CS_OBJECTIVES + MAX_OBJECTIVES) {
cobjective_t *objective = &cg.Objectives[num - CS_OBJECTIVES];
objective->flags = atoi(Info_ValueForKey(str, "flags"));
strcpy(objective->text, Info_ValueForKey(str, "text"));
}
switch (num) {
case CS_MUSIC:
cgi.MUSIC_NewSoundtrack(str);
return;
case CS_WARMUP:
cg.matchStartTime = atoi(str);
return;
case CS_FOGINFO:
CG_ParseFogInfo(str);
return;
case CS_SKYINFO:
sscanf(str, "%f %d", &cg.sky_alpha, &cg.sky_portal);
return;
case CS_SERVERINFO:
CG_ParseServerinfo();
return;
case CS_LEVEL_START_TIME:
cgs.levelStartTime = atoi(str);
return;
case CS_MATCHEND:
cgs.matchEndTime = atoi(str);
return;
}
str = CG_ConfigString(num);
if (num >= CS_MODELS && num < CS_MODELS + MAX_MODELS) {
qhandle_t hOldModel = cgs.model_draw[num - CS_MODELS];
if (str && str[0]) {
if (str && str[0] && !modelOnly) {
qhandle_t hModel = cgi.R_RegisterServerModel(str);
dtiki_t *tiki;
@@ -334,43 +303,142 @@ void CG_ProcessConfigString(int num)
}
} else {
// clear out the model
if (hOldModel) {
if (hOldModel && CG_IsHandleUnique(hOldModel)) {
// Handle uniqueness added in OPM
cgi.R_UnregisterServerModel(hOldModel);
}
cgs.model_draw[num - CS_MODELS] = 0;
}
} else if (num >= CS_SOUNDS && num < CS_SOUNDS + MAX_SOUNDS) {
size_t len = strlen(str);
if (len) {
qboolean streamed;
char buf[1024];
strcpy(buf, str);
}
streamed = buf[len - 1] != '0';
buf[len - 1] = 0;
if (buf[0] != '*') {
cgs.sound_precache[num - CS_SOUNDS] = cgi.S_RegisterSound(buf, streamed);
if (!modelOnly) {
switch (num) {
case CS_RAIN_DENSITY:
cg.rain.density = atof(str);
return;
case CS_RAIN_SPEED:
cg.rain.speed = atof(str);
return;
case CS_RAIN_SPEEDVARY:
cg.rain.speed_vary = atoi(str);
return;
case CS_RAIN_SLANT:
cg.rain.slant = atoi(str);
return;
case CS_RAIN_LENGTH:
cg.rain.length = atof(str);
return;
case CS_RAIN_MINDIST:
cg.rain.min_dist = atof(str);
return;
case CS_RAIN_WIDTH:
cg.rain.width = atof(str);
return;
case CS_RAIN_SHADER:
if (cg.rain.numshaders) {
for (i = 0; i < cg.rain.numshaders; i++) {
sprintf(cg.rain.shader[i], "%s%i", str, i);
}
} else {
strcpy(cg.rain.shader[0], str);
}
}
} else if (num >= CS_LIGHTSTYLES && num < CS_LIGHTSTYLES + MAX_LIGHTSTYLES) {
CG_SetLightStyle(num - CS_LIGHTSTYLES, str);
} else if (num >= CS_PLAYERS && num < CS_PLAYERS + MAX_CLIENTS) {
const char *value;
value = Info_ValueForKey(str, "name");
if (value) {
strncpy(cg.clientinfo[num - CS_PLAYERS].name, value, sizeof(cg.clientinfo[num - CS_PLAYERS].name));
} else {
strncpy(
cg.clientinfo[num - CS_PLAYERS].name, "UnnamedSoldier", sizeof(cg.clientinfo[num - CS_PLAYERS].name)
);
return;
case CS_RAIN_NUMSHADERS:
cg.rain.numshaders = atoi(str);
if (cg.rain.numshaders) {
for (i = 0; i < cg.rain.numshaders; i++) {
sprintf(cg.rain.shader[i], "%s%i", str, i);
}
}
return;
}
value = Info_ValueForKey(str, "team");
if (value) {
cg.clientinfo[num - CS_PLAYERS].team = atoi(value);
} else {
cg.clientinfo[num - CS_PLAYERS].team = TEAM_NONE;
if (num >= CS_OBJECTIVES && num < CS_OBJECTIVES + MAX_OBJECTIVES) {
cobjective_t *objective = &cg.Objectives[num - CS_OBJECTIVES];
objective->flags = atoi(Info_ValueForKey(str, "flags"));
strcpy(objective->text, Info_ValueForKey(str, "text"));
}
switch (num) {
case CS_MUSIC:
cgi.MUSIC_NewSoundtrack(str);
return;
case CS_WARMUP:
cg.matchStartTime = atoi(str);
return;
case CS_FOGINFO:
cg.farclipOverride = 0;
cg.farplaneColorOverride[0] = -1;
cg.farplaneColorOverride[1] = -1;
cg.farplaneColorOverride[2] = -1;
CG_ParseFogInfo(str);
return;
case CS_SKYINFO:
sscanf(str, "%f %d", &cg.sky_alpha, &cg.sky_portal);
return;
case CS_SERVERINFO:
CG_ParseServerinfo();
return;
case CS_LEVEL_START_TIME:
cgs.levelStartTime = atoi(str);
return;
case CS_VOTE_TIME:
cgs.voteTime = atoi(str);
cgs.voteRefreshed = qtrue;
break;
case CS_VOTE_STRING:
Q_strncpyz(cgs.voteString, str, sizeof(cgs.voteString));
break;
case CS_VOTE_YES:
cgs.numVotesYes = atoi(str);
cgs.voteRefreshed = qtrue;
break;
case CS_VOTE_NO:
cgs.numVotesNo = atoi(str);
cgs.voteRefreshed = qtrue;
break;
case CS_VOTE_UNDECIDED:
cgs.numUndecidedVotes = atoi(str);
cgs.voteRefreshed = qtrue;
break;
case CS_MATCHEND:
cgs.matchEndTime = atoi(str);
return;
}
if (num >= CS_SOUNDS && num < CS_SOUNDS + MAX_SOUNDS) {
size_t len = strlen(str);
if (len) {
qboolean streamed;
char buf[1024];
strcpy(buf, str);
streamed = buf[len - 1] != '0';
buf[len - 1] = 0;
if (buf[0] != '*') {
cgs.sound_precache[num - CS_SOUNDS] = cgi.S_RegisterSound(buf, streamed);
}
}
} else if (num >= CS_LIGHTSTYLES && num < CS_LIGHTSTYLES + MAX_LIGHTSTYLES) {
CG_SetLightStyle(num - CS_LIGHTSTYLES, str);
} else if (num >= CS_PLAYERS && num < CS_PLAYERS + MAX_CLIENTS) {
const char *value;
value = Info_ValueForKey(str, "name");
if (value) {
strncpy(cg.clientinfo[num - CS_PLAYERS].name, value, sizeof(cg.clientinfo[num - CS_PLAYERS].name));
} else {
strncpy(
cg.clientinfo[num - CS_PLAYERS].name, "UnnamedSoldier", sizeof(cg.clientinfo[num - CS_PLAYERS].name)
);
}
value = Info_ValueForKey(str, "team");
if (value) {
cg.clientinfo[num - CS_PLAYERS].team = atoi(value);
} else {
cg.clientinfo[num - CS_PLAYERS].team = TEAM_NONE;
}
}
}
}
@@ -423,14 +491,14 @@ void CG_PrepRefresh(void)
cgs.media.binocularsOverlayShader = cgi.R_RegisterShaderNoMip("textures/hud/binocularsoverlay");
cgs.media.hudDrawFont = cgi.R_LoadFont("verdana-14");
cgs.media.attackerFont = cgi.R_LoadFont("facfont-20");
cgs.media.objectiveFont = cgi.R_LoadFont("courier-16");
cgs.media.objectiveFont = cgi.R_LoadFont("facfont-20"); // was courier-16 before 2.0
cgs.media.objectivesBackShader = cgi.R_RegisterShaderNoMip("textures/hud/objectives_backdrop");
cgs.media.checkedBoxShader = cgi.R_RegisterShaderNoMip("textures/objectives/filledbox");
cgs.media.uncheckedBoxShader = cgi.R_RegisterShaderNoMip("textures/objectives/emptybox");
// go through all the configstrings and process them
for (i = CS_SYSTEMINFO + 1; i < MAX_CONFIGSTRINGS; i++) {
CG_ProcessConfigString(i);
CG_ProcessConfigString(i, qfalse);
}
}
@@ -469,6 +537,7 @@ Displays the info screen while loading media
void CG_GameStateReceived(void)
{
const char *s;
int checksum;
// clear everything
memset(&cg, 0, sizeof(cg));
@@ -495,7 +564,10 @@ void CG_GameStateReceived(void)
CG_ParseServerinfo();
// load the new map
cgi.CM_LoadMap(cgs.mapname);
cgi.CM_LoadMap(cgs.mapname, &checksum);
if (cgs.useMapChecksum && checksum != cgs.mapChecksum && cgs.gametype != GT_SINGLE_PLAYER) {
cgi.Error(ERR_DROP, "Client/Server map checksum mismatch: %x/%x", checksum, cgs.mapChecksum);
}
CG_InitMarks();
@@ -539,16 +611,6 @@ void CG_ServerRestarted(void)
CG_InitializeObjectives();
}
void *CG_Malloc(int size)
{
return malloc(size);
}
void CG_Free(void *ptr)
{
free(ptr);
}
/*
=================
CG_Init
@@ -559,10 +621,6 @@ Called after every level change or subsystem restart
void CG_Init(clientGameImport_t *imported, int serverMessageNum, int serverCommandSequence, int clientNum)
{
cgi = *imported;
#if _DEBUG
cgi.Malloc = &CG_Malloc;
cgi.Free = &CG_Free;
#endif
cg_protocol = cgi.Cvar_Get("com_protocol", "", 0)->integer;
CG_InitCGMessageAPI(&cge);
@@ -570,6 +628,11 @@ void CG_Init(clientGameImport_t *imported, int serverMessageNum, int serverComma
memset(&cg, 0, sizeof(cg));
memset(&cgs, 0, sizeof(cgs));
// clear fog values
cg.farclipOverride = 0;
cg.farplaneColorOverride[0] = -1;
cg.farplaneColorOverride[1] = -1;
cg.farplaneColorOverride[2] = -1;
cg.clientNum = clientNum;
cgs.processedSnapshotNum = serverMessageNum;
@@ -626,11 +689,14 @@ Called before every level change or subsystem restart
void CG_Shutdown(void)
{
L_ShutdownEvents();
// Shutdown radar
cgi.CL_InitRadar(NULL, NULL, -1);
// some mods may need to do cleanup work here,
// like closing files or archiving session data
// hide the stats screen
cgi.UI_HideMenu("StatsScreen", 1);
cgi.UI_HideMenu("StatsScreen", qtrue);
// reset the scoreboard
CG_PrepScoreBoardInfo();
@@ -788,10 +854,20 @@ void CG_ParseFogInfo_ver_15(const char *str)
void CG_ParseFogInfo_ver_6(const char *str)
{
cg.farclipOverride = 0.0;
//
// clear all unsupported fields in protocol below version 15
//
// don't set the farplane_bias 0, otherwise the renderer will set a minimum value
cg.farplane_bias = 0.001f;
cg.skyboxFarplane = 0;
cg.skyboxSpeed = 0;
cg.renderTerrain = qtrue;
cg.farclipOverride = -1.0;
cg.farplaneColorOverride[0] = -1.0;
cg.farplaneColorOverride[1] = -1.0;
cg.farplaneColorOverride[2] = -1.0;
sscanf(
str,
"%d %f %f %f %f",
+2 -2
View File
@@ -685,9 +685,9 @@ void CG_ImpactMark(
// create the full polygon
for (i = 0; i < 3; i++) {
originalPoints[0][i] = origin[i] - fSScale2 * info.axis[1][i] - fTScale2 * info.axis[2][i];
originalPoints[1][i] = origin[i] + fSScale3 * info.axis[1][i] - fTScale3 * info.axis[2][i];
originalPoints[1][i] = origin[i] + fSScale3 * info.axis[1][i] - fTScale2 * info.axis[2][i];
originalPoints[2][i] = origin[i] + fSScale3 * info.axis[1][i] + fTScale3 * info.axis[2][i];
originalPoints[3][i] = origin[i] - fSScale2 * info.axis[1][i] + fTScale2 * info.axis[2][i];
originalPoints[3][i] = origin[i] - fSScale2 * info.axis[1][i] + fTScale3 * info.axis[2][i];
}
// get the fragments
+286 -20
View File
@@ -180,6 +180,226 @@ void CG_PlayerTeamIcon(refEntity_t *pModel, entityState_t *pPlayerState)
}
}
/*
===============
CG_CastFootShadow
Cast complex foot shadow using lights
===============
*/
void CG_CastFootShadow(const vec_t* vLightPos, vec_t* vLightIntensity, int iTag, refEntity_t* model)
{
int i;
float fAlpha;
float fLength;
float fWidth;
float fAlphaOfs;
float fOfs;
float fPitchCos;
vec3_t vPos;
vec3_t vEnd;
vec3_t vDelta;
vec3_t vLightAngles;
trace_t trace;
orientation_t oFoot;
VectorCopy(model->origin, vPos);
oFoot = cgi.TIKI_Orientation(model, iTag);
VectorMA(oFoot.origin, 2, oFoot.axis[1], vEnd);
for (i = 0; i < 3; i++) {
VectorMA(vPos, vEnd[i], model->axis[i], vPos);
}
if (cg_shadowdebug->integer)
{
vec3_t vDir;
//
// show debug lines
//
memset(vDir, 0, sizeof(vDir));
for (i = 0; i < 3; ++i) {
VectorMA(vDir, oFoot.axis[0][i], model->axis[i], vDir);
}
VectorMA(vPos, 32.0, vDir, vEnd);
cgi.R_DebugLine(vPos, vEnd, 1.0, 0.0, 0.0, 1.0);
memset(vDir, 0, sizeof(vDir));
for (i = 0; i < 3; ++i) {
VectorMA(vDir, oFoot.axis[1][i], model->axis[i], vDir);
}
VectorMA(vPos, 32.0, vDir, vEnd);
cgi.R_DebugLine(vPos, vEnd, 0.0, 1.0, 0.0, 1.0);
memset(vDir, 0, sizeof(vDir));
for (i = 0; i < 3; ++i) {
VectorMA(vDir, oFoot.axis[2][i], model->axis[i], vDir);
}
VectorMA(vPos, 32.0, vDir, vEnd);
cgi.R_DebugLine(vPos, vEnd, 0.0, 0.0, 1.0, 1.0);
}
// calculate the direction
VectorSubtract(vLightPos, vPos, vDelta);
VectorNormalizeFast(vDelta);
vectoangles(vDelta, vLightAngles);
// normalize to 180 degrees
if (vLightAngles[0] > 180) {
vLightAngles[0] -= 360;
}
if (vLightAngles[0] > -5.7319679) {
// FIXME: what is -5.7319679?
return;
}
fPitchCos = cos(DEG2RAD(vLightAngles[0]));
if (fPitchCos > 0.955) {
fAlpha = 1.0 - (fPitchCos - 0.955) * 25;
} else {
fAlpha = 1.0;
}
fLength = fPitchCos * fPitchCos * 32.0 + fPitchCos * 8.0 + 10.0;
fOfs = 0.5 - (-4.1 / tan(DEG2RAD(vLightAngles[0])) + 4.0 - fLength) / fLength * 0.5;
VectorMA(vPos, -96.0, vDelta, vEnd);
CG_Trace(&trace, vPos, vec3_origin, vec3_origin, vEnd, 0, MASK_FOOTSHADOW, qfalse, qtrue, "CG_CastFootShadow");
if (cg_shadowdebug->integer)
{
cgi.R_DebugLine(vPos, vLightPos, 0.75, 0.75, 0.5, 1.0);
cgi.R_DebugLine(vPos, vEnd, 1.0, 1.0, 1.0, 1.0);
}
if (trace.fraction == 1.0) {
return;
}
trace.fraction -= 0.0427f;
if (trace.fraction < 0) {
trace.fraction = 0;
}
fWidth = 10.f - (1.f - trace.fraction) * 6.f;
fAlphaOfs = (1.f - trace.fraction) * fAlpha;
fAlpha = Q_max(vLightIntensity[0], Q_max(vLightIntensity[1], vLightIntensity[2]));
if (fAlpha < 0.1) {
vLightIntensity[0] *= 0.1 / fAlpha * fAlphaOfs;
vLightIntensity[1] *= 0.1 / fAlpha * fAlphaOfs;
vLightIntensity[2] *= 0.1 / fAlpha * fAlphaOfs;
} else {
vLightIntensity[0] *= fAlphaOfs;
vLightIntensity[1] *= fAlphaOfs;
vLightIntensity[2] *= fAlphaOfs;
}
fAlpha = Q_max(vLightIntensity[0], Q_max(vLightIntensity[1], vLightIntensity[2]));
if (fAlpha > 0.6) {
vLightIntensity[0] *= 0.6 / fAlpha;
vLightIntensity[1] *= 0.6 / fAlpha;
vLightIntensity[2] *= 0.6 / fAlpha;
}
if (vLightIntensity[0] <= 0.01 && vLightIntensity[1] <= 0.01 && vLightIntensity[2] <= 0.01) {
return;
}
CG_ImpactMark(
cgs.media.footShadowMarkShader,
trace.endpos,
trace.plane.normal,
vLightAngles[1],
fWidth,
fLength,
vLightIntensity[0],
vLightIntensity[1],
vLightIntensity[2],
1.0,
qfalse,
qtrue,
qfalse,
qfalse,
0.5,
fOfs
);
}
/*
===============
CG_CastSimpleFeetShadow
Cast basic feet shadow
===============
*/
void CG_CastSimpleFeetShadow(const trace_t* pTrace, float fWidth, float fAlpha, int iRightTag, int iLeftTag, const dtiki_t* tiki, refEntity_t* model)
{
int i;
float fShadowYaw;
float fLength;
vec3_t vPos, vRightPos, vLeftPos;
vec3_t vDelta;
orientation_t oFoot;
//
// right foot
//
VectorCopy(pTrace->endpos, vRightPos);
oFoot = cgi.TIKI_Orientation(model, iRightTag);
VectorMA(oFoot.origin, 3, oFoot.axis[1], vPos);
for (i = 0; i < 3; i++) {
VectorMA(vRightPos, vPos[i], model->axis[i], vRightPos);
}
VectorMA(vRightPos, -2, oFoot.axis[1], vRightPos);
//
// left foot
//
VectorCopy(pTrace->endpos, vLeftPos);
oFoot = cgi.TIKI_Orientation(model, iLeftTag);
VectorMA(oFoot.origin, 3, oFoot.axis[1], vPos);
for (i = 0; i < 3; i++) {
VectorMA(vLeftPos, vPos[i], model->axis[i], vLeftPos);
}
VectorAdd(vRightPos, vLeftPos, vPos);
VectorScale(vPos, 0.5, vPos);
VectorSubtract(vRightPos, vLeftPos, vDelta);
VectorMA(vLeftPos, 0.5, vDelta, vPos);
// get the facing yaw
fShadowYaw = vectoyaw(vDelta);
fLength = VectorNormalize(vDelta) * 0.5 + 12;
if (fLength < fWidth * 0.7) {
fLength = fWidth * 0.7;
}
// add the mark
CG_ImpactMark(
cgs.media.shadowMarkShader,
vPos,
pTrace->plane.normal,
fShadowYaw,
fWidth * 0.7,
fLength,
fAlpha,
fAlpha,
fAlpha,
1.0,
qfalse,
qtrue,
qfalse,
qfalse,
0.5,
0.5
);
}
/*
===============
CG_EntityShadow
@@ -193,9 +413,15 @@ Returns the Z component of the surface being shadowed
qboolean CG_EntityShadow(centity_t *cent, refEntity_t *model)
{
int iTagL, iTagR;
float alpha;
float fWidth;
vec3_t end;
vec3_t vMins, vMaxs;
vec3_t vSize;
trace_t trace;
float alpha, radius;
iTagR = -1;
if (cg_shadows->integer == 0) {
return qfalse;
@@ -206,10 +432,31 @@ qboolean CG_EntityShadow(centity_t *cent, refEntity_t *model)
return qfalse;
}
// no shadows when invisible
// if ( cent->currentState.powerups & ( 1 << PW_INVIS ) ) {
// return qfalse;
// }
if (cg_shadows->integer == 2 && (model->renderfx & RF_SHADOW_PRECISE)) {
iTagL = cgi.Tag_NumForName(model->tiki, "Bip01 L Foot");
if (iTagL != -1) {
iTagR = cgi.Tag_NumForName(model->tiki, "Bip01 R Foot");
}
if (iTagR != -1) {
int iNumLights, iCurrLight;
vec3_t avLightPos[16], avLightIntensity[16];
iNumLights = Q_clamp(cg_shadowscount->integer, 1, 8);
iNumLights = cgi.R_GatherLightSources(model->origin, avLightPos, avLightIntensity, iNumLights);
if (iNumLights)
{
for (iCurrLight = 0; iCurrLight < iNumLights; iCurrLight++)
{
CG_CastFootShadow(avLightPos[iCurrLight], avLightIntensity[iCurrLight], iTagL, model);
CG_CastFootShadow(avLightPos[iCurrLight], avLightIntensity[iCurrLight], iTagR, model);
}
// shadow was casted properly
return qtrue;
}
}
}
// send a trace down from the player to the ground
VectorCopy(model->origin, end);
@@ -222,29 +469,46 @@ qboolean CG_EntityShadow(centity_t *cent, refEntity_t *model)
return qfalse;
}
if ((cg_shadows->integer == 2) && (model->renderfx & RF_SHADOW_PRECISE)) {
// since 2.0: no shadow if solid
if (trace.startsolid || trace.allsolid) {
return qfalse;
}
if ((cg_shadows->integer == 3) && (model->renderfx & RF_SHADOW_PRECISE)) {
return qtrue;
}
//
// get the bounds of the current frame
//
radius = model->scale * cgi.R_ModelRadius(model->hModel);
if (radius < 1) {
fWidth = model->scale * cgi.R_ModelRadius(model->hModel);
if (fWidth < 1) {
return qfalse;
}
// fade the shadow out with height
alpha = (1.0 - trace.fraction) * 0.8f;
alpha = (1.0 - trace.fraction) * 0.65f;
if ((cg_shadows->integer == 3) && (model->renderfx & RF_SHADOW_PRECISE)) {
if (model->shaderRGBA[3] == 255) {
model->shaderRGBA[3] = alpha * 255;
if (model->renderfx & RF_SHADOW_PRECISE) {
iTagL = cgi.Tag_NumForName(model->tiki, "Bip01 L Foot");
if (iTagL != -1) {
iTagR = cgi.Tag_NumForName(model->tiki, "Bip01 R Foot");
}
if (iTagR != -1) {
if (cg_shadows->integer == 2) {
alpha *= 0.6f;
}
CG_CastSimpleFeetShadow(&trace, fWidth, alpha, iTagR, iTagL, model->tiki, model);
return qtrue;
}
return qtrue;
}
cgi.R_ModelBounds(model->hModel, vMins, vMaxs);
VectorSubtract(vMaxs, vMins, vSize);
VectorScale(vSize, 0.6f, vSize);
// add the mark as a temporary, so it goes directly to the renderer
// without taking a spot in the cg_marks array
CG_ImpactMark(
@@ -252,15 +516,15 @@ qboolean CG_EntityShadow(centity_t *cent, refEntity_t *model)
trace.endpos,
trace.plane.normal,
cent->lerpAngles[YAW],
radius,
radius,
vSize[1],
vSize[0],
alpha,
alpha,
alpha,
1,
qfalse,
qtrue,
qtrue,
qfalse,
qfalse,
0.5f,
0.5f
@@ -316,10 +580,12 @@ void CG_AttachEntity(
orientation_t or ;
vec3_t tempAxis[3];
vec3_t vOrigin;
vec3_t vDeltaLightOrg;
or = cgi.TIKI_Orientation(parent, tagnum);
//cgi.Printf( "th = %d %.2f %.2f %.2f\n", tikihandle, or.origin[ 0 ], or.origin[ 1 ], or.origin[ 2 ] );
VectorSubtract(entity->lightingOrigin, entity->origin, vDeltaLightOrg);
VectorCopy(parent->origin, entity->origin);
for (i = 0; i < 3; i++) {
@@ -337,14 +603,14 @@ void CG_AttachEntity(
VectorCopy(entity->origin, entity->oldorigin);
if (use_angles) {
MatrixMultiply(entity->axis, parent->axis, tempAxis);
MatrixMultiply(or.axis, tempAxis, entity->axis);
MatrixMultiply(entity->axis, or.axis, tempAxis);
MatrixMultiply(tempAxis, parent->axis, entity->axis);
}
entity->scale *= parent->scale;
entity->renderfx |= (parent->renderfx & ~(RF_FLAGS_NOT_INHERITED | RF_LIGHTING_ORIGIN));
MatrixTransformVectorRight(entity->axis, entity->lightingOrigin, vOrigin);
MatrixTransformVectorRight(entity->axis, vDeltaLightOrg, vOrigin);
VectorAdd(entity->origin, vOrigin, entity->lightingOrigin);
}
+183 -224
View File
@@ -37,6 +37,7 @@ typedef struct {
vec3_t *i_vEnd;
int i_iNumBullets;
qboolean iLarge;
float alpha;
int iTracerVisible;
qboolean bIgnoreEntities;
} bullet_tracer_t;
@@ -60,21 +61,22 @@ static vec3_t flesh_impact_pos[MAX_IMPACTS];
static vec3_t flesh_impact_norm[MAX_IMPACTS];
static int flesh_impact_large[MAX_IMPACTS];
void CG_MakeBulletHoleSound(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, trace_t* pPreTrace) {
int iSurfType;
float fVolume;
str sSoundName;
vec3_t vFrom, vDest;
void CG_MakeBulletHoleSound(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, trace_t *pPreTrace)
{
int iSurfType;
float fVolume;
str sSoundName;
vec3_t vFrom, vDest;
trace_t trace;
if (pPreTrace) {
trace = *pPreTrace;
}
else {
} else {
VectorMA(i_vPos, 2.0f, i_vNorm, vFrom);
VectorMA(i_vPos, -4.0f, i_vNorm, vDest);
CG_Trace(&trace, vFrom, vec_zero, vec_zero, vDest, ENTITYNUM_NONE, MASK_SHOT, qfalse, qtrue, "CG_MakeBulletHole");
CG_Trace(
&trace, vFrom, vec_zero, vec_zero, vDest, ENTITYNUM_NONE, MASK_SHOT, qfalse, qtrue, "CG_MakeBulletHole"
);
}
iSurfType = trace.surfaceFlags & MASK_SURF_TYPE;
@@ -149,9 +151,12 @@ void CG_MakeBulletHoleSound(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarg
commandManager.PlaySound(sSoundName, vFrom, -1, fVolume, -1.f, -1.f, 1);
}
static void CG_MakeBulletHoleType(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, int iEffectNum, float fRadius, qboolean bMakeSound) {
static void CG_MakeBulletHoleType(
const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, int iEffectNum, float fRadius, qboolean bMakeSound
)
{
if (bMakeSound) {
str sBulletHole = "snd_bh_";
str sBulletHole = "snd_bh_";
float fVolume;
switch (iEffectNum) {
@@ -221,14 +226,15 @@ static void CG_MakeBulletHoleType(const vec3_t i_vPos, const vec3_t i_vNorm, int
sfxManager.MakeEffect_Normal(iEffectNum, i_vPos, i_vNorm);
}
static void CG_MakeBulletHole(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, trace_t *pPreTrace, qboolean bMakeSound)
static void
CG_MakeBulletHole(const vec3_t i_vPos, const vec3_t i_vNorm, int iLarge, trace_t *pPreTrace, qboolean bMakeSound)
{
int iSurfType;
int iEffect;
float fRadius;
str sEffectModel;
str sBulletHole;
vec3_t vFrom, vDest;
int iSurfType;
int iEffect;
float fRadius;
str sEffectModel;
str sBulletHole;
vec3_t vFrom, vDest;
trace_t trace;
if (pPreTrace) {
@@ -236,7 +242,9 @@ static void CG_MakeBulletHole(const vec3_t i_vPos, const vec3_t i_vNorm, int iLa
} else {
VectorMA(i_vPos, 2.0f, i_vNorm, vFrom);
VectorMA(i_vPos, -4.0f, i_vNorm, vDest);
CG_Trace(&trace, vFrom, vec_zero, vec_zero, vDest, ENTITYNUM_NONE, MASK_SHOT, qfalse, qtrue, "CG_MakeBulletHole");
CG_Trace(
&trace, vFrom, vec_zero, vec_zero, vDest, ENTITYNUM_NONE, MASK_SHOT, qfalse, qtrue, "CG_MakeBulletHole"
);
}
iSurfType = trace.surfaceFlags & MASK_SURF_TYPE;
@@ -249,7 +257,7 @@ static void CG_MakeBulletHole(const vec3_t i_vPos, const vec3_t i_vNorm, int iLa
}
VectorAdd(trace.endpos, trace.plane.normal, vFrom);
fRadius = 2.0f;
fRadius = 2.0f;
sBulletHole = "bhole_";
switch (iSurfType) {
@@ -347,36 +355,48 @@ static void CG_MakeBubbleTrail(const vec3_t i_vStart, const vec3_t i_vEnd, int i
{
vec3_t vDir;
vec3_t vPos;
float fDist;
float fMove;
float fDist;
float fMove;
VectorSubtract(i_vEnd, i_vStart, vDir);
fDist = VectorNormalize(vDir);
VectorCopy(i_vStart, vPos);
fMove = random() * 8.f;
fMove = random() * 8.f * alpha;
fDist -= fMove;
while (fDist > 0.f) {
VectorMA(vPos, fMove, vDir, vPos);
sfxManager.MakeEffect_Angles(32, vPos, vec_zero);
fMove = 16.f + crandom() * 8.f;
fMove = 16.f + crandom() * 8.f * alpha;
fDist -= fMove;
}
}
static void CG_BulletTracerEffect(const vec3_t i_vStart, const vec3_t i_vEnd)
static void CG_BulletTracerEffect(const vec3_t i_vStart, const vec3_t i_vEnd, int iLarge, float alpha)
{
int iLife;
int iTracerLength;
float fLength, fDist;
int iLife;
int iTracerLength;
float fLength, fDist;
vec4_t fTracerColor;
vec3_t vDir, vNewStart;
float alphaMult;
float scale;
iTracerLength = 450.0f + random() * 150.f;
VectorSubtract(i_vEnd, i_vStart, vDir);
fLength = VectorNormalize(vDir);
if (iLarge > 1) {
alphaMult = random() * 0.2f + 0.9f;
scale = iLarge * 2;
} else {
alphaMult = 1;
scale = 1;
}
fDist = 450.0f + random() * 150.f;
if (fLength < fDist + 150.f) {
float fFrac;
@@ -384,13 +404,15 @@ static void CG_BulletTracerEffect(const vec3_t i_vStart, const vec3_t i_vEnd)
return;
}
fFrac = fLength / (fDist + 150.0);
fFrac = fLength / (fDist + 150.0);
iTracerLength = (int)((float)iTracerLength * fFrac + 0.5f);
fDist *= fFrac;
}
iLife = (int)((fLength - fDist) / 12000.f * 1000.f);
if (iLife < 20) iLife = 20;
iLife = (int)((fLength - fDist) / 12000.f * 1000.f / (alpha * alphaMult));
if (iLife < 20) {
iLife = 20;
}
VectorMA(i_vStart, fDist, vDir, vNewStart);
fTracerColor[0] = 1.f;
@@ -427,53 +449,54 @@ static void CG_BulletTracerEffect(const vec3_t i_vStart, const vec3_t i_vEnd)
}
static void CG_MakeBulletTracerInternal(
const vec3_t i_vBarrel,
const vec3_t i_vStart,
const vec3_t *i_vEnd,
int i_iNumBullets,
qboolean iLarge,
int iTracerVisible,
qboolean bIgnoreEntities
const vec3_t i_vBarrel,
const vec3_t i_vStart,
const vec3_t *i_vEnd,
int i_iNumBullets,
qboolean iLarge,
int iTracerVisible,
qboolean bIgnoreEntities,
float alpha
)
{
vec3_t vPos;
int iBullet;
int iContinueCount;
int iDist;
int iHeadDist;
int iTravelDist;
float fLen, fDist;
trace_t trace;
qboolean bStartInWater, bInWater;
qboolean bBulletDone;
qboolean bMadeTracer;
vec3_t vDir;
vec3_t vTrailStart;
vec3_t vTraceStart;
vec3_t vTraceEnd;
vec3_t vTmp;
int iNumImpacts;
trace_t tImpacts[128];
float fImpSndDistRA;
vec3_t vPos;
int iBullet;
int iContinueCount;
int iDist;
int iHeadDist;
int iTravelDist;
float fLen, fDist;
trace_t trace;
qboolean bStartInWater, bInWater;
qboolean bBulletDone;
qboolean bMadeTracer;
vec3_t vDir;
vec3_t vTrailStart;
vec3_t vTraceStart;
vec3_t vTraceEnd;
vec3_t vTmp;
int iNumImpacts;
trace_t tImpacts[128];
float fImpSndDistRA;
static float fImpSndDistLA;
float fImpSndDistRB;
float fImpSndDistLB;
int iImpSndIndexRA;
int iImpSndIndexRB;
int iImpSndIndexLB;
float fVolume;
float fPitch;
float fZingDistA, fZingDistB, fZingDistC;
vec3_t vZingPosA, vZingPosB, vZingPosC;
float fImpSndDistRB;
float fImpSndDistLB;
int iImpSndIndexRA;
int iImpSndIndexRB;
int iImpSndIndexLB;
float fVolume;
float fPitch;
float fZingDistA, fZingDistB, fZingDistC;
vec3_t vZingPosA, vZingPosB, vZingPosC;
fZingDistB = 9999.0;
fZingDistA = 9999.0;
fZingDistC = 9999.0;
fZingDistB = 9999.0;
fZingDistA = 9999.0;
fZingDistC = 9999.0;
iNumImpacts = 0;
// check to see if it starts in water
bStartInWater = (cgi.CM_PointContents(i_vStart, 0) & CONTENTS_FLUID) != 0;
for (iBullet = 0; iBullet < i_iNumBullets; iBullet++) {
bInWater = bStartInWater;
VectorCopy(i_vBarrel, vTrailStart);
@@ -481,8 +504,8 @@ static void CG_MakeBulletTracerInternal(
fLen = VectorNormalize(vDir);
trace.fraction = 0;
iDist = (int)fLen + 32;
bBulletDone = qfalse;
iDist = (int)fLen + 32;
bBulletDone = qfalse;
iContinueCount = 0;
if (bStartInWater) {
@@ -501,8 +524,7 @@ static void CG_MakeBulletTracerInternal(
if (iDist > BULLET_TRAVEL_DIST) {
iTravelDist += BULLET_TRAVEL_DIST;
iDist -= BULLET_TRAVEL_DIST;
}
else {
} else {
iTravelDist += iDist;
iDist = 0;
}
@@ -513,16 +535,7 @@ static void CG_MakeBulletTracerInternal(
while (trace.fraction < 1) {
if (bIgnoreEntities) {
cgi.CM_BoxTrace(
&trace,
vTraceStart,
vTraceEnd,
vec_zero,
vec_zero,
0,
MASK_SHOT,
qfalse
);
cgi.CM_BoxTrace(&trace, vTraceStart, vTraceEnd, vec_zero, vec_zero, 0, MASK_SHOT, qfalse);
if (trace.fraction == 1.0f) {
trace.entityNum = ENTITYNUM_NONE;
@@ -533,8 +546,7 @@ static void CG_MakeBulletTracerInternal(
if (trace.startsolid) {
trace.entityNum = ENTITYNUM_WORLD;
}
}
else {
} else {
CG_Trace(
&trace,
vTraceStart,
@@ -556,35 +568,29 @@ static void CG_MakeBulletTracerInternal(
VectorNormalizeFast(trace.plane.normal);
}
if (!bInWater && trace.fraction < 1.0f && iNumImpacts <= 127)
{
if (!bInWater && trace.fraction < 1.0f && iNumImpacts <= 127) {
memcpy(&tImpacts[iNumImpacts], &trace, sizeof(trace_t));
iNumImpacts++;
}
if (iTracerVisible && !bMadeTracer)
{
CG_BulletTracerEffect(vTrailStart, trace.endpos);
if (iTracerVisible && !bMadeTracer) {
CG_BulletTracerEffect(vTrailStart, trace.endpos, iLarge, alpha);
bMadeTracer = qtrue;
}
if (trace.fraction < 1.0f) {
if (((trace.surfaceFlags & (SURF_HINT | SURF_NODLIGHT | SURF_SNOW | SURF_FOLIAGE | SURF_DIRT)) || (trace.contents & CONTENTS_WATER))
&& iContinueCount < 5)
{
if (bInWater)
{
if (((trace.surfaceFlags & (SURF_HINT | SURF_NODLIGHT | SURF_SNOW | SURF_FOLIAGE | SURF_DIRT))
|| (trace.contents & CONTENTS_WATER))
&& iContinueCount < 5) {
if (bInWater) {
VectorSubtract(trace.endpos, vDir, vTmp);
if (!(trace.contents & CONTENTS_FLUID)
&& !(trace.surfaceFlags & SURF_PUDDLE)
&& !(cgi.CM_PointContents(vTmp, 0) & CONTENTS_FLUID))
{
CG_MakeBubbleTrail(vTrailStart, trace.endpos, iLarge);
if (!(trace.contents & CONTENTS_FLUID) && !(trace.surfaceFlags & SURF_PUDDLE)
&& !(cgi.CM_PointContents(vTmp, 0) & CONTENTS_FLUID)) {
CG_MakeBubbleTrail(vTrailStart, trace.endpos, iLarge, alpha);
VectorCopy(trace.endpos, vTrailStart);
bInWater = qfalse;
}
}
else if ((trace.contents & CONTENTS_FLUID) || (trace.surfaceFlags & SURF_PUDDLE)) {
} else if ((trace.contents & CONTENTS_FLUID) || (trace.surfaceFlags & SURF_PUDDLE)) {
VectorCopy(trace.endpos, vTrailStart);
bInWater = qtrue;
}
@@ -593,11 +599,9 @@ static void CG_MakeBulletTracerInternal(
VectorAdd(vTraceStart, vTraceStart, trace.endpos);
iContinueCount++;
}
else
{
} else {
trace.fraction = 1.0f;
bBulletDone = qtrue;
bBulletDone = qtrue;
}
}
}
@@ -605,14 +609,14 @@ static void CG_MakeBulletTracerInternal(
}
if (bInWater) {
CG_MakeBubbleTrail(vTraceStart, trace.endpos, iLarge);
CG_MakeBubbleTrail(vTraceStart, trace.endpos, iLarge, alpha);
}
if (iTracerVisible) {
iTracerVisible--;
}
fLen = ProjectPointOnLine(i_vStart, i_vEnd[iBullet], cg.SoundOrg, vPos);
fLen = ProjectPointOnLine(i_vStart, i_vEnd[iBullet], cg.SoundOrg, vPos);
iHeadDist = (int)Distance(vPos, cg.SoundOrg);
if (iHeadDist > 255) {
continue;
@@ -629,7 +633,7 @@ static void CG_MakeBulletTracerInternal(
if (fLen < 0.f) {
VectorCopy(i_vStart, vPos);
} else if(fDist >= fLen) {
} else if (fDist >= fLen) {
VectorCopy(i_vEnd[iBullet], vPos);
}
@@ -652,11 +656,11 @@ static void CG_MakeBulletTracerInternal(
}
if (iNumImpacts > 2) {
fImpSndDistRA = 9999.0f;
fImpSndDistRB = 9999.0f;
fImpSndDistRA = 9999.0f;
fImpSndDistRB = 9999.0f;
iImpSndIndexRA = 0;
iImpSndIndexRB = 0;
fImpSndDistLB = 9999.0f;
fImpSndDistLB = 9999.0f;
iImpSndIndexLB = 0;
for (iBullet = 0; iBullet < iNumImpacts; iBullet++) {
@@ -671,27 +675,23 @@ static void CG_MakeBulletTracerInternal(
VectorSubtract(tImpacts[iImpSndIndexLB].endpos, cg.SoundOrg, vTmp);
iHeadDist = VectorLength(vTmp);
if (DotProduct(vTmp, cg.SoundAxis[1]) <= 0.f)
{
if (DotProduct(vTmp, cg.SoundAxis[1]) <= 0.f) {
if (iHeadDist < 9999.0f || iHeadDist < fImpSndDistLB) {
if (iHeadDist < 9999.0f) {
fImpSndDistRA = iHeadDist;
fImpSndDistLB = 9999.0;
fImpSndDistRA = iHeadDist;
fImpSndDistLB = 9999.0;
iImpSndIndexRA = iBullet;
} else if (iHeadDist < fImpSndDistLB) {
fImpSndDistLB = iHeadDist;
}
}
}
else
{
if (iHeadDist < fImpSndDistRA || iHeadDist < fImpSndDistRB)
{
} else {
if (iHeadDist < fImpSndDistRA || iHeadDist < fImpSndDistRB) {
if (iHeadDist < fImpSndDistRA) {
iImpSndIndexRB = iImpSndIndexRA;
iImpSndIndexRA = iBullet;
} else if (iHeadDist < fImpSndDistRB) {
fImpSndDistRB = iHeadDist;
fImpSndDistRB = iHeadDist;
iImpSndIndexRB = iBullet;
}
}
@@ -720,11 +720,7 @@ static void CG_MakeBulletTracerInternal(
} else {
for (iBullet = 0; iBullet < iNumImpacts; iBullet++) {
CG_MakeBulletHole(
tImpacts[iBullet].endpos,
tImpacts[iBullet].plane.normal,
iNumImpacts,
&tImpacts[iBullet],
qtrue
tImpacts[iBullet].endpos, tImpacts[iBullet].plane.normal, iNumImpacts, &tImpacts[iBullet], qtrue
);
}
}
@@ -732,10 +728,10 @@ static void CG_MakeBulletTracerInternal(
if (fZingDistA < 9999.0f) {
if (iLarge) {
fVolume = 1.0f;
fPitch = 0.8f;
fPitch = 0.8f;
} else {
fVolume = 0.8f;
fPitch = 1.0f;
fPitch = 1.0f;
}
commandManager.PlaySound("snd_b_zing", vZingPosA, -1, fVolume, -1.0f, fPitch, 1);
@@ -774,13 +770,14 @@ static void CG_MakeBulletTracer(
bullet_tracer->i_vEnd = &bullet_tracer_bullets[bullet_tracers_count];
bullet_tracer->i_iNumBullets = i_iNumBullets;
for (i = 0; i < i_iNumBullets; ++i) {
bullet_tracer_bullets[bullet_tracers_count][0] = (*i_vEnd)[i];
bullet_tracer_bullets[bullet_tracers_count][1] = (*i_vEnd)[i + 1];
bullet_tracer_bullets[bullet_tracers_count++][2] = (*i_vEnd)[i + 2];
for (i = 0; i < i_iNumBullets; i++, bullet_tracers_count++) {
bullet_tracer_bullets[bullet_tracers_count][0] = i_vEnd[i][0];
bullet_tracer_bullets[bullet_tracers_count][1] = i_vEnd[i][1];
bullet_tracer_bullets[bullet_tracers_count][2] = i_vEnd[i][2];
}
bullet_tracer->iLarge = iLarge;
bullet_tracer->alpha = alpha;
bullet_tracer->iTracerVisible = iTracerVisible;
bullet_tracer->bIgnoreEntities = bIgnoreEntities;
}
@@ -797,7 +794,8 @@ void CG_AddBulletTracers()
bullet_tracers[i].i_iNumBullets,
bullet_tracers[i].iLarge,
bullet_tracers[i].iTracerVisible,
bullet_tracers[i].bIgnoreEntities
bullet_tracers[i].bIgnoreEntities,
bullet_tracers[i].alpha
);
}
@@ -807,26 +805,24 @@ void CG_AddBulletTracers()
void CG_AddBulletImpacts()
{
int i;
int iHeadDist;
float fVolume;
float fImpSndDistRA;
int i;
int iHeadDist;
float fVolume;
float fImpSndDistRA;
static float fImpSndDistLA = 9999.f;
float fImpSndDistRB;
float fImpSndDistLB;
int iImpSndIndexRA;
int iImpSndIndexRB;
int iImpSndIndexLB;
vec3_t vTmp;
str sSoundName;
float fImpSndDistRB;
float fImpSndDistLB;
int iImpSndIndexRA;
int iImpSndIndexRB;
int iImpSndIndexLB;
vec3_t vTmp;
str sSoundName;
if (wall_impact_count)
{
if (wall_impact_count > 4)
{
fImpSndDistRA = fImpSndDistLA;
fImpSndDistRB = fImpSndDistLA;
fImpSndDistLB = fImpSndDistLA;
if (wall_impact_count) {
if (wall_impact_count > 4) {
fImpSndDistRA = fImpSndDistLA;
fImpSndDistRB = fImpSndDistLA;
fImpSndDistLB = fImpSndDistLA;
iImpSndIndexRA = 0;
iImpSndIndexRB = 0;
iImpSndIndexLB = 0;
@@ -834,33 +830,28 @@ void CG_AddBulletImpacts()
for (i = 0; i < wall_impact_count; i++) {
VectorSubtract(wall_impact_pos[i], cg.SoundOrg, vTmp);
iHeadDist = VectorLength(vTmp);
if (DotProduct(vTmp, cg.SoundAxis[1]) > 0.f)
{
if (iHeadDist < fImpSndDistRA || iHeadDist < fImpSndDistRB)
{
if (DotProduct(vTmp, cg.SoundAxis[1]) > 0.f) {
if (iHeadDist < fImpSndDistRA || iHeadDist < fImpSndDistRB) {
if (iHeadDist < fImpSndDistRA) {
fImpSndDistRB = fImpSndDistRA;
fImpSndDistRA = iHeadDist;
fImpSndDistRB = fImpSndDistRA;
fImpSndDistRA = iHeadDist;
iImpSndIndexRB = iImpSndIndexRA;
iImpSndIndexRA = i;
} else if (iHeadDist < fImpSndDistRB) {
fImpSndDistRB = iHeadDist;
fImpSndDistRB = iHeadDist;
iImpSndIndexRB = i;
}
}
}
else
{
if (iHeadDist < fImpSndDistLA || iHeadDist < fImpSndDistLB)
{
} else {
if (iHeadDist < fImpSndDistLA || iHeadDist < fImpSndDistLB) {
if (iHeadDist < fImpSndDistLA) {
fImpSndDistRA = iHeadDist;
fImpSndDistLB = fImpSndDistLA;
fImpSndDistRA = iHeadDist;
fImpSndDistLB = fImpSndDistLA;
iImpSndIndexLB = 0;
iImpSndIndexRA = i;
} else if (iHeadDist < fImpSndDistLB) {
fImpSndDistLB = iHeadDist;
fImpSndDistLB = iHeadDist;
iImpSndIndexLB = i;
}
}
@@ -908,8 +899,7 @@ void CG_AddBulletImpacts()
if (wall_impact_type[iImpSndIndexRB] == 2 || wall_impact_type[iImpSndIndexRB] == 3) {
sSoundName = "snd_bh_metal";
}
else {
} else {
sSoundName = "snd_bh_wood";
}
@@ -942,26 +932,15 @@ void CG_AddBulletImpacts()
if (wall_impact_type[0] == 2 || wall_impact_type[0] == 3) {
sSoundName = "snd_bh_metal";
}
else {
} else {
sSoundName = "snd_bh_wood";
}
commandManager.PlaySound(sSoundName, wall_impact_pos[0], -1, fVolume, -1, -1, 1);
sfxManager.MakeEffect_Normal(
wall_impact_type[0],
wall_impact_pos[0],
wall_impact_norm[0]
);
sfxManager.MakeEffect_Normal(wall_impact_type[0], wall_impact_pos[0], wall_impact_norm[0]);
} else {
CG_MakeBulletHole(
wall_impact_pos[0],
wall_impact_norm[0],
wall_impact_large[0],
NULL,
qtrue
);
CG_MakeBulletHole(wall_impact_pos[0], wall_impact_norm[0], wall_impact_large[0], NULL, qtrue);
}
}
@@ -969,15 +948,13 @@ void CG_AddBulletImpacts()
if (wall_impact_type[iImpSndIndexLB]) {
if (wall_impact_large[iImpSndIndexLB]) {
fVolume = 1.f;
}
else {
} else {
fVolume = 0.75f;
}
if (wall_impact_type[iImpSndIndexLB] == 2 || wall_impact_type[iImpSndIndexLB] == 3) {
sSoundName = "snd_bh_metal";
}
else {
} else {
sSoundName = "snd_bh_wood";
}
@@ -998,45 +975,31 @@ void CG_AddBulletImpacts()
);
}
}
}
else
{
} else {
for (i = 0; i < wall_impact_count; i++) {
CG_MakeBulletHole(
wall_impact_pos[i],
wall_impact_norm[i],
wall_impact_large[i],
NULL,
qtrue
);
CG_MakeBulletHole(wall_impact_pos[i], wall_impact_norm[i], wall_impact_large[i], NULL, qtrue);
}
}
wall_impact_count = 0;
}
if (flesh_impact_count)
{
if (flesh_impact_count > 1)
{
fImpSndDistRA = 9999.0;
if (flesh_impact_count) {
if (flesh_impact_count > 1) {
fImpSndDistRA = 9999.0;
iImpSndIndexRA = 0;
for (i = 0; i < flesh_impact_count; i++) {
VectorSubtract(wall_impact_pos[i], cg.SoundOrg, vTmp);
iHeadDist = VectorLength(vTmp);
if (DotProduct(vTmp, cg.SoundAxis[1]) > 0.f)
{
if (iHeadDist < fImpSndDistRA)
{
fImpSndDistRA = iHeadDist;
if (DotProduct(vTmp, cg.SoundAxis[1]) > 0.f) {
if (iHeadDist < fImpSndDistRA) {
fImpSndDistRA = iHeadDist;
iImpSndIndexRA = i;
}
}
else if (iHeadDist < fImpSndDistLA)
{
fImpSndDistRA = iHeadDist;
} else if (iHeadDist < fImpSndDistLA) {
fImpSndDistRA = iHeadDist;
iImpSndIndexRA = i;
}
}
@@ -1105,8 +1068,7 @@ void CG_MakeExplosionEffect(const vec3_t vPos, int iType)
fRadius = 0;
break;
case SURF_SNOW:
switch (iBaseEffect)
{
switch (iBaseEffect) {
case SFX_EXP_TANK_BASE:
iSurfEffect = SFX_EXP_TANK_SNOW;
break;
@@ -1122,7 +1084,7 @@ void CG_MakeExplosionEffect(const vec3_t vPos, int iType)
iBaseEffect = -1;
break;
}
fRadius = 0;
fRadius = 0;
break;
case SURF_CARPET:
iSurfEffect = SFX_EXP_GREN_CARPET;
@@ -1147,8 +1109,7 @@ void CG_MakeExplosionEffect(const vec3_t vPos, int iType)
fRadius = 0;
break;
case SURF_DIRT:
switch (iBaseEffect)
{
switch (iBaseEffect) {
case SFX_EXP_TANK_BASE:
iSurfEffect = SFX_EXP_TANK_DIRT;
break;
@@ -1164,15 +1125,14 @@ void CG_MakeExplosionEffect(const vec3_t vPos, int iType)
iBaseEffect = -1;
break;
}
fRadius = 0;
fRadius = 0;
break;
case SURF_GRILL:
iSurfEffect = SFX_EXP_GREN_GRILL;
fRadius = 0;
break;
case SURF_GRASS:
switch (iBaseEffect)
{
switch (iBaseEffect) {
case SFX_EXP_TANK_BASE:
iSurfEffect = SFX_EXP_TANK_DIRT;
break;
@@ -1190,8 +1150,7 @@ void CG_MakeExplosionEffect(const vec3_t vPos, int iType)
fRadius = 0;
break;
case SURF_ROCK:
switch (iBaseEffect)
{
switch (iBaseEffect) {
case SFX_EXP_TANK_BASE:
iSurfEffect = SFX_EXP_TANK_STONE;
break;
+6
View File
@@ -25,6 +25,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// interpolating between snapshots from the server or locally predicting
// ahead the client's movement. It also handles local physics interaction,
// like fragments bouncing off walls
//
// ADDITIONS:
// - CG_InterpolatePlayerState() footer: Interpolate the lean angles
#include "cg_local.h"
@@ -405,6 +408,9 @@ static void CG_InterpolatePlayerState(qboolean grabAngles)
}
out->velocity[i] = prev->ps.velocity[i] + f * (next->ps.velocity[i] - prev->ps.velocity[i]);
}
// interpolate the lean angle
out->fLeanAngle = LerpAngle(prev->ps.fLeanAngle, next->ps.fLeanAngle, f);
}
/*
+7 -3
View File
@@ -137,6 +137,8 @@ functions exported to the main executable
void (*FS_FreeFile)(void *buf);
int (*FS_WriteFile)(const char *qpath, const void *buffer, int size);
void (*FS_WriteTextFile)(const char *qpath, const void *buffer, int size);
char** (*FS_ListFilteredFiles)(const char* path, const char* extension, const char* filter, qboolean wantSubs, int* numfiles, qboolean allowNonPureFilesOnDisk);
void (*FS_FreeFileList)(char **list);
// add commands to the local console as if they were typed in
// for map changing, etc. The command is not executed immediately,
// but will be executed in order the next time console commands
@@ -163,7 +165,7 @@ functions exported to the main executable
void (*SendClientCommand)(const char *s);
// CM functions
void (*CM_LoadMap)(const char *name);
void (*CM_LoadMap)(const char *name, int* checksum);
clipHandle_t (*CM_InlineModel)(int index); // 0 = world, 1+ = bmodels
int (*CM_NumInlineModels)(void);
int (*CM_PointContents)(const vec3_t p, int headnode);
@@ -283,9 +285,11 @@ functions exported to the main executable
qhandle_t (*R_RegisterModel)(const char *name);
qhandle_t (*R_SpawnEffectModel)(const char *name, vec3_t pos, vec3_t axis[3]);
qhandle_t (*R_RegisterServerModel)(const char *name);
const char * (*R_GetModelName)(qhandle_t hModel);
void (*R_UnregisterServerModel)(qhandle_t hModel);
qhandle_t (*R_RegisterShader)(const char *name);
qhandle_t (*R_RegisterShaderNoMip)(const char *name);
const char* (*R_GetShaderName)(qhandle_t hShader);
void (*R_AddRefEntityToScene)(const refEntity_t *ent, int parentEntityNumber);
void (*R_AddRefSpriteToScene)(const refEntity_t *ent);
void (*R_AddLightToScene)(const vec3_t origin, float intensity, float r, float g, float b, int type);
@@ -499,8 +503,8 @@ functions exported to the main executable
//
void (*CG_ReadNonPVSClient)(radarUnpacked_t* radarUnpacked);
void (*CG_UpdateRadar)();
void (*CG_SaveStateToBuffer)(void** out, int svsTime);
void (*CG_LoadStateToBuffer)(void** state, int size, int svsTime);
size_t (*CG_SaveStateToBuffer)(void** out, int svsTime);
qboolean (*CG_LoadStateToBuffer)(void* state, size_t size, int svsTime);
void (*CG_CleanUpTempModels)();
// FIXME
+59 -13
View File
@@ -24,6 +24,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// cg_servercmds.c -- text commands sent by the server
#include "cg_local.h"
#include "../fgame/bg_voteoptions.h"
static const char *IsWeaponAllowed(int dmFlags, int flags)
{
@@ -112,6 +113,7 @@ void CG_ParseServerinfo(void)
char map[MAX_QPATH];
char *spawnpos;
const char *version;
const char *mapChecksumStr;
info = CG_ConfigString(CS_SERVERINFO);
cgs.gametype = atoi(Info_ValueForKey(info, "g_gametype"));
@@ -135,12 +137,23 @@ void CG_ParseServerinfo(void)
cgi.Cvar_Set("cg_obj_alliedtext1", Info_ValueForKey(info, "g_obj_alliedtext1"));
cgi.Cvar_Set("cg_obj_alliedtext2", Info_ValueForKey(info, "g_obj_alliedtext2"));
cgi.Cvar_Set("cg_obj_alliedtext3", Info_ValueForKey(info, "g_obj_alliedtext3"));
cgi.Cvar_Set("cg_obj_axistext1", Info_ValueForKey(info, "cg_obj_axistext1"));
cgi.Cvar_Set("cg_obj_axistext2", Info_ValueForKey(info, "cg_obj_axistext2"));
cgi.Cvar_Set("cg_obj_axistext3", Info_ValueForKey(info, "cg_obj_axistext3"));
cgi.Cvar_Set("cg_obj_alliedtext4", Info_ValueForKey(info, "g_obj_alliedtext4"));
cgi.Cvar_Set("cg_obj_alliedtext5", Info_ValueForKey(info, "g_obj_alliedtext5"));
cgi.Cvar_Set("cg_obj_axistext1", Info_ValueForKey(info, "g_obj_axistext1"));
cgi.Cvar_Set("cg_obj_axistext2", Info_ValueForKey(info, "g_obj_axistext2"));
cgi.Cvar_Set("cg_obj_axistext3", Info_ValueForKey(info, "g_obj_axistext3"));
cgi.Cvar_Set("cg_obj_axistext4", Info_ValueForKey(info, "g_obj_axistext4"));
cgi.Cvar_Set("cg_obj_axistext5", Info_ValueForKey(info, "g_obj_axistext5"));
cgi.Cvar_Set("cg_scoreboardpic", Info_ValueForKey(info, "g_scoreboardpic"));
cgi.Cvar_Set("cg_scoreboardpicover", Info_ValueForKey(info, "g_scoreboardpicover"));
cgs.mapChecksum = atoi(Info_ValueForKey(info, "sv_mapChecksum"));
mapChecksumStr = Info_ValueForKey(info, "sv_mapChecksum");
if (mapChecksumStr && mapChecksumStr[0]) {
cgs.mapChecksum = atoi(mapChecksumStr);
cgs.useMapChecksum = qtrue;
} else {
cgs.mapChecksum = 0;
cgs.useMapChecksum = qfalse;
}
mapname = Info_ValueForKey(info, "mapname");
@@ -184,17 +197,13 @@ CG_ConfigStringModified
================
*/
static void CG_ConfigStringModified(void)
static void CG_ConfigStringModified(int num, qboolean modelOnly)
{
int num;
num = atoi(cgi.Argv(1));
// get the gamestate from the client system, which will have the
// new configstring already integrated
cgi.GetGameState(&cgs.gameState);
CG_ProcessConfigString(num);
CG_ProcessConfigString(num, modelOnly);
}
/*
@@ -275,7 +284,7 @@ The string has been tokenized and can be retrieved with
Cmd_Argc() / Cmd_Argv()
=================
*/
static void CG_ServerCommand(void)
static void CG_ServerCommand(qboolean modelOnly)
{
const char *cmd;
@@ -287,7 +296,11 @@ static void CG_ServerCommand(void)
}
if (!strcmp(cmd, "cs")) {
CG_ConfigStringModified();
CG_ConfigStringModified(atoi(cgi.Argv(1)), modelOnly);
return;
}
if (modelOnly) {
return;
}
@@ -364,6 +377,28 @@ static void CG_ServerCommand(void)
return;
}
if (!strcmp(cmd, "voteresult")) {
cmd = cgi.Argv(1);
if (*cmd) {
strcmp(cmd, "passed");
}
}
if (!strcmp(cmd, "vo0")) {
CG_VoteOptions_StartReadFromServer(cgi.Argv(1));
return;
}
if (!strcmp(cmd, "vo1")) {
CG_VoteOptions_ContinueReadFromServer(cgi.Argv(1));
return;
}
if (!strcmp(cmd, "vo2")) {
CG_VoteOptions_FinishReadFromServer(cgi.Argv(1));
return;
}
cgi.Printf("Unknown client game command: %s\n", cmd);
}
@@ -377,9 +412,20 @@ with this this snapshot.
*/
void CG_ExecuteNewServerCommands(int latestSequence, qboolean differentServer)
{
int lastServerCommandSequence;
lastServerCommandSequence = cgs.serverCommandSequence;
while (cgs.serverCommandSequence < latestSequence) {
if (cgi.GetServerCommand(++cgs.serverCommandSequence, differentServer)) {
CG_ServerCommand();
CG_ServerCommand(qtrue);
}
}
cgs.serverCommandSequence = lastServerCommandSequence;
while (cgs.serverCommandSequence < latestSequence) {
if (cgi.GetServerCommand(++cgs.serverCommandSequence, differentServer)) {
CG_ServerCommand(qfalse);
}
}
}
+16
View File
@@ -23,8 +23,12 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// DESCRIPTION:
// things that happen on snapshot transition, not necessarily every
// single frame
//
// ADDITIONS:
// - CG_TransitionSnapshot() footer: set ps.walking to true if the ps has a ground entity
#include "cg_local.h"
#include "cg_radar.h"
#include "tiki.h"
/*
@@ -206,6 +210,9 @@ static void CG_TransitionSnapshot(qboolean differentServer)
cent->teleported = qfalse;
}
CG_TransitionEntity(cent);
// remember time of snapshot this entity was last updated in
cent->snapShotTime = cg.snap->serverTime;
}
for (i = 0; i < cg.snap->number_of_sounds; i++) {
@@ -243,6 +250,15 @@ static void CG_TransitionSnapshot(qboolean differentServer)
CG_TransitionPlayerState(ps, ops);
}
}
if (differentServer) {
cgi.CL_RestoreSavedCgameState();
} else {
cgi.CL_ClearSavedCgameState();
}
// this allows the view model to still look normal when the player is on ground
cg.snap->ps.walking = cg.snap->ps.groundEntityNum != ENTITYNUM_NONE;
}
/*
+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));
+6
View File
@@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "cg_local.h"
#include "cg_commands.h"
#include "memarchiver.h"
const char *cg_vsstypes[] = {
"default",
@@ -214,6 +215,11 @@ void CG_ResetVSSSources()
lastVSSFrameTime = cg.time;
}
void CG_ArchiveVSSGlobals(MemArchiver& archiver)
{
archiver.ArchiveTime(&lastVSSFrameTime);
}
void ClientGameCommandManager::InitializeVSSSources()
{
int i;
+241
View File
@@ -0,0 +1,241 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
OpenMoHAA source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#include "cg_local.h"
#include "memarchiver.h"
#include "../qcommon/vector.h"
#include "../qcommon/str.h"
MemArchiver::MemArchiver()
{
state = MEMARC_WRITING;
buffer = 0;
allocatedSize = 0;
bufferSize = 0;
}
MemArchiver::~MemArchiver()
{
if (state == MEMARC_WRITING && buffer) {
cgi.Free(buffer);
}
}
void MemArchiver::SetupForWriting(size_t initialSize)
{
state = MEMARC_WRITING;
buffer = (byte*)cgi.Malloc(initialSize);
allocatedSize = initialSize;
bufferSize = 0;
}
void MemArchiver::SetupForReading(byte* buffer, size_t size)
{
state = MEMARC_READING;
buffer = buffer;
allocatedSize = size;
bufferSize = 0;
}
void MemArchiver::SetBaseTime(unsigned int time)
{
svsTime = time;
}
size_t MemArchiver::BufferSize() const
{
return bufferSize;
}
byte* MemArchiver::ConfiscateBuffer()
{
byte* confiscatedBuffer = buffer;
buffer = NULL;
allocatedSize = 0;
bufferSize = 0;
return confiscatedBuffer;
}
bool MemArchiver::IsReading() const
{
return !IsWriting();
}
bool MemArchiver::IsWriting() const
{
return state == MEMARC_WRITING;
}
bool MemArchiver::FinishedReading() const
{
return bufferSize == allocatedSize;
}
void MemArchiver::ArchiveByte(byte* value)
{
ArchiveRaw(value, sizeof(byte));
}
void MemArchiver::ArchiveBoolean(qboolean* value)
{
ArchiveRaw(value, sizeof(qboolean));
}
void MemArchiver::ArchiveChar(char* value)
{
ArchiveRaw(value, sizeof(char));
}
void MemArchiver::ArchiveUChar(unsigned char* value)
{
ArchiveRaw(value, sizeof(unsigned char));
}
void MemArchiver::ArchiveShort(short* value)
{
ArchiveRaw(value, sizeof(short));
}
void MemArchiver::ArchiveInteger(int* value)
{
ArchiveRaw(value, sizeof(int));
}
void MemArchiver::ArchiveSize(size_t* value)
{
ArchiveRaw(value, sizeof(size_t));
}
void MemArchiver::ArchiveFloat(float* value)
{
ArchiveRaw(value, sizeof(float));
}
void MemArchiver::ArchiveVec3(vec3_t value)
{
ArchiveRaw(value, sizeof(vec3_t));
}
void MemArchiver::ArchiveVector(Vector* value)
{
ArchiveFloat(&value->x);
ArchiveFloat(&value->y);
ArchiveFloat(&value->z);
}
void MemArchiver::ArchiveString(str* value)
{
char tmp[4096];
int current = 0;
if (IsReading()) {
for (current = 0; current < 4096; current++) {
ArchiveReadRaw(&tmp[current], sizeof(char));
if (!tmp[current]) {
break;
}
}
if (current == 4096) {
tmp[current - 1] = 0;
}
*value = tmp;
} else {
ArchiveWriteRaw(value->c_str(), value->length() + 1);
}
}
void MemArchiver::ArchiveTime(int* value)
{
int time;
if (IsReading()) {
ArchiveReadRaw(&time, sizeof(time));
if (time) {
time += svsTime;
}
*value = time;
} else {
time = *value;
if (time) {
time -= svsTime;
}
ArchiveWriteRaw(&time, sizeof(time));
}
}
void MemArchiver::ArchiveRaw(void* buffer, size_t size)
{
if (IsReading()) {
ArchiveReadRaw(buffer, size);
} else {
ArchiveWriteRaw(buffer, size);
}
}
void MemArchiver::ArchiveReadRaw(void* buffer, size_t size)
{
if (!size) {
return;
}
if (size + this->bufferSize > this->allocatedSize) {
Com_Error(ERR_DROP, "MemArchiver: tried to read past end of buffer");
}
memcpy(buffer, this->buffer + this->bufferSize, size);
this->bufferSize += size;
}
void MemArchiver::ArchiveWriteRaw(const void* buffer, size_t size)
{
if (!size) {
return;
}
if (size + this->bufferSize > this->allocatedSize) {
if (!this->allocatedSize) {
this->allocatedSize = 1024;
this->buffer = (byte*)cgi.Malloc(this->allocatedSize);
} else {
byte* newBuffer;
do {
this->allocatedSize *= 2;
} while (size + this->bufferSize > this->allocatedSize);
newBuffer = (byte*)cgi.Malloc(this->allocatedSize);
memcpy(newBuffer, this->buffer, this->bufferSize);
cgi.Free(this->buffer);
this->buffer = newBuffer;
}
}
memcpy(this->buffer + this->bufferSize, buffer, size);
this->bufferSize += size;
}
+72
View File
@@ -0,0 +1,72 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
OpenMoHAA source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// DESCRIPTION:
// In-memory archiver
#include "cg_local.h"
class Vector;
class str;
typedef enum {
MEMARC_WRITING,
MEMARC_READING
} archiverState_e;
class MemArchiver {
public:
MemArchiver();
~MemArchiver();
void SetupForWriting(size_t initialSize);
void SetupForReading(byte* buffer, size_t size);
void SetBaseTime(unsigned int time);
size_t BufferSize() const;
byte* ConfiscateBuffer();
bool IsReading() const;
bool IsWriting() const;
bool FinishedReading() const;
void ArchiveByte(byte* value);
void ArchiveBoolean(qboolean* value);
void ArchiveChar(char* value);
void ArchiveUChar(unsigned char* value);
void ArchiveShort(short* value);
void ArchiveInteger(int* value);
void ArchiveSize(size_t* value);
void ArchiveFloat(float* value);
void ArchiveVec3(vec3_t value);
void ArchiveVector(Vector* value);
void ArchiveString(str* value);
void ArchiveTime(int* value);
void ArchiveRaw(void* buffer, size_t size);
void ArchiveReadRaw(void* buffer, size_t size);
void ArchiveWriteRaw(const void* buffer, size_t size);
private:
archiverState_e state;
byte* buffer;
size_t bufferSize;
size_t allocatedSize;
int svsTime;
};
+9 -4
View File
@@ -435,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());
}
/*
@@ -580,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;
@@ -605,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;
@@ -676,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;
+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;
}
}
+90 -39
View File
@@ -27,6 +27,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#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"
@@ -366,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
@@ -408,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++ ) {
@@ -417,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 );
@@ -441,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 );
@@ -596,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;
}
@@ -798,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;
}
@@ -865,7 +868,7 @@ void CL_ClearState( void )
CL_ShutdownCGame();
if( !com_sv_running->integer ) {
S_StopAllSounds( qtrue );
S_StopAllSounds2( qtrue );
}
UI_ClearState();
@@ -880,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;
@@ -1207,7 +1210,7 @@ void CL_Disconnect_f( void ) {
CL_AbnormalDisconnect();
CL_FlushMemory();
CL_StartHunkUsers(qfalse);
S_StopAllSounds(1);
S_StopAllSounds2(1);
S_TriggeredMusic_PlayIntroMusic();
}
@@ -1239,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" );
@@ -1272,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
@@ -1295,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 );
@@ -1312,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 );
}
/*
@@ -1340,7 +1368,7 @@ void CL_MenuConnect_f( void ) {
server = Cmd_Argv( 1 );
CL_Connect( Cvar_VariableString( server ) );
CL_Connect( Cvar_VariableString( server ), NA_UNSPEC );
}
/*
@@ -1360,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;
}
@@ -1493,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();
@@ -1507,6 +1535,8 @@ void CL_Vid_Restart_f( void ) {
CL_InitRef();
// initialize the ui library
UI_ResolutionChange();
// clear aliases
Alias_Clear();
cls.rendererRegistered = qfalse;
@@ -1519,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");
}
@@ -1658,6 +1694,13 @@ void CL_DownloadsComplete( void ) {
Com_EventLoop();
CL_StartHunkUsers(qfalse);
// set pure checksums
CL_SendPureChecksums();
CL_WritePacket();
CL_WritePacket();
CL_WritePacket();
}
/*
@@ -2434,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" );
}
@@ -2650,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
@@ -2808,7 +2860,7 @@ void CL_InitRef( void ) {
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
@@ -3136,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);
@@ -3338,7 +3390,6 @@ void CL_Init( void ) {
Cvar_Set( "cl_running", "1" );
NET_Init();
S_Init2();
// fixme: should we leave it?
@@ -4261,7 +4312,7 @@ CL_ServerRestarted
==================
*/
void CL_ServerRestarted( void ) {
S_StopAllSounds( qfalse );
S_StopAllSounds2( qfalse );
UI_ServerLoaded();
UI_ClearState();
+2 -36
View File
@@ -514,40 +514,6 @@ static void CL_ParseServerInfo(void)
sizeof(clc.sv_dlURL));
}
char* MSG_ReadGameStateChar_ver_15(msg_t* msg) {
return MSG_ReadScrambledBigString(msg);
}
float MSG_ReadServerFrameTime_ver_15(msg_t* msg) {
return MSG_ReadFloat(msg);
}
char* MSG_ReadGameStateChar_ver_6(msg_t* msg) {
return MSG_ReadString(msg);
}
float MSG_ReadServerFrameTime_ver_6(msg_t* msg) {
return 1.f / atof(Info_ValueForKey(cl.gameState.stringData + cl.gameState.stringOffsets[CS_SYSTEMINFO], "sv_fps"));
}
char* MSG_ReadGameStateChar(msg_t* msg) {
if (MSG_IsProtocolVersion15()) {
return MSG_ReadGameStateChar_ver_15(msg);
} else {
// smaller below version 15
return MSG_ReadGameStateChar_ver_6(msg);
}
}
float MSG_ReadServerFrameTime(msg_t* msg) {
if (MSG_IsProtocolVersion15()) {
return MSG_ReadServerFrameTime_ver_15(msg);
} else {
// smaller below version 15
return MSG_ReadServerFrameTime_ver_6(msg);
}
}
/*
==================
CL_ParseGamestate
@@ -591,7 +557,7 @@ void CL_ParseGamestate( msg_t *msg ) {
if (csNum < 0 || csNum >= MAX_CONFIGSTRINGS) {
Com_Error(ERR_DROP, "configstring > MAX_CONFIGSTRINGS");
}
s = MSG_ReadGameStateChar(msg);
s = MSG_ReadScrambledBigString(msg);
len = strlen(s);
if (len + 1 + cl.gameState.dataCount > MAX_GAMESTATE_CHARS) {
@@ -620,7 +586,7 @@ void CL_ParseGamestate( msg_t *msg ) {
clc.clientNum = MSG_ReadLong(msg);
// read the checksum feed
clc.checksumFeed = MSG_ReadLong( msg );
cls.serverFrameTime = MSG_ReadServerFrameTime(msg);
cls.serverFrameTime = MSG_ReadServerFrameTime(msg, &cl.gameState);
// parse serverId and other cvars
CL_SystemInfoChanged();
+3833 -4028
View File
File diff suppressed because it is too large. Load diff
+85 -68
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -20,112 +20,129 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
#ifndef __CL_UI_H__
#define __CL_UI_H__
#pragma once
#include "../uilib/ui_extern.h"
#include "../uilib/uiwidget.h"
typedef struct {
UIReggedMaterial *loading;
UIReggedMaterial *loading;
} static_media_t;
//
// cvars
//
extern cvar_t* ui_health_start;
extern cvar_t* ui_health_end;
extern cvar_t* sound_overlay;
extern cvar_t *ui_health_start;
extern cvar_t *ui_health_end;
extern cvar_t *sound_overlay;
//
// initialization
//
void CL_FillUIDef( void );
void CL_InitializeUI( void );
void CL_ShutdownUI( void );
void CL_FillUIDef(void);
void CL_InitializeUI(void);
void CL_ShutdownUI(void);
//
// general ui stuff
//
extern inventory_t client_inv;
extern bind_t client_bind;
extern cvar_t* cl_greenfps;
extern bind_t client_bind;
extern cvar_t *cl_greenfps;
const char *CvarGetForUI( const char *name, const char *defval );
void UI_ClearState( void );
void CL_BeginRegistration( void );
void CL_EndRegistration(void);
const char *CvarGetForUI(const char *name, const char *defval);
void UI_ClearState(void);
void CL_BeginRegistration(void);
void CL_EndRegistration(void);
//
// menu
//
extern Menu *ui_pLoadingMenu;
void UI_ShowMenu( const char *name, qboolean bForce );
void UI_HideMenu( const char *name, qboolean bForce );
void UI_ForceMenuOff( bool force );
void UI_PushMenu( const char *name );
void UI_ForceMenu( const char *name );
qboolean UI_BindActive( void );
void UI_SetReturnMenuToCurrent(void);
void UI_ActivateView3D( void );
void UI_MenuEscape( const char *name );
void UI_CreateScoreboard( void );
qboolean UI_MenuActive( void );
qboolean UI_MenuUp( void );
void UI_FocusMenuIfExists(void);
void UI_DrawConnect( void );
void UI_CreateDialog( const char *title, char *cvarname, const char *command, const char *cancelCommand, int width, int height, const char *shader, const char *okshader, const char *cancelshader );
void UI_ToggleDMConsole( int iMode );
void UI_ShowScoreboard_f( const char *pszMenuName );
void UI_HideScoreboard_f( void );
void UI_SetScoreBoardItem( int iItemNumber,
const char *pszData1, const char *pszData2, const char *pszData3, const char *pszData4,
const char *pszData5, const char *pszData6, const char *pszData7, const char *pszData8,
const vec4_t pTextColor, const vec4_t pBackColor, qboolean bIsHeader );
void UI_DeleteScoreBoardItems( int iMaxIndex );
void UI_ShowMenu(const char *name, qboolean bForce);
void UI_HideMenu(const char *name, qboolean bForce);
void UI_ForceMenuOff(bool force);
void UI_PushMenu(const char *name);
void UI_ForceMenu(const char *name);
qboolean UI_BindActive(void);
void UI_SetReturnMenuToCurrent(void);
void UI_ActivateView3D(void);
void UI_MenuEscape(const char *name);
void UI_CreateScoreboard(void);
qboolean UI_MenuActive(void);
qboolean UI_MenuUp(void);
void UI_FocusMenuIfExists(void);
void UI_DrawConnect(void);
void UI_CreateDialog(
const char *title,
char *cvarname,
const char *command,
const char *cancelCommand,
int width,
int height,
const char *shader,
const char *okshader,
const char *cancelshader
);
void UI_ToggleDMConsole(int iMode);
void UI_ShowScoreboard_f(const char *pszMenuName);
void UI_HideScoreboard_f(void);
void UI_SetScoreBoardItem(
int iItemNumber,
const char *pszData1,
const char *pszData2,
const char *pszData3,
const char *pszData4,
const char *pszData5,
const char *pszData6,
const char *pszData7,
const char *pszData8,
const vec4_t pTextColor,
const vec4_t pBackColor,
qboolean bIsHeader
);
void UI_DeleteScoreBoardItems(int iMaxIndex);
//
// ressources
//
void UI_BeginLoad( const char *pszMapName );
void UI_EndLoad( void );
void UI_AbortLoad( void );
void UI_BeginLoadResource( void );
void UI_EndLoadResource( void );
void UI_EndLoadResource( const char *name );
qboolean UI_IsResourceLoaded( const char *name );
void UI_RegisterLoadResource( const char *name );
void UI_ClearResource( void );
void UI_LoadResource( const char *name );
void UI_BeginLoad(const char *pszMapName);
void UI_EndLoad(void);
void UI_AbortLoad(void);
void UI_BeginLoadResource(void);
void UI_EndLoadResource(void);
void UI_EndLoadResource(const char *name);
qboolean UI_IsResourceLoaded(const char *name);
void UI_RegisterLoadResource(const char *name);
void UI_ClearResource(void);
void UI_LoadResource(const char *name);
//
// windows
//
void UI_DeactiveFloatingWindows( void );
void UI_DeactiveFloatingWindows(void);
//
// console
//
void UI_OpenConsole( void );
qboolean UI_ConsoleIsVisible( void );
qboolean UI_ConsoleIsOpen( void );
void UI_CloseConsole( void );
void UI_ToggleConsole( void );
void UI_OpenDMConsole( int iMode );
void UI_CloseDMConsole( void );
void UI_ToggleDMConsole( int iMode );
void UI_OpenDeveloperConsole( void );
void UI_CloseDeveloperConsole( void );
void UI_PrintConsole(const char* msg);
void UI_OpenConsole(void);
qboolean UI_ConsoleIsVisible(void);
qboolean UI_ConsoleIsOpen(void);
void UI_CloseConsole(void);
void UI_ToggleConsole(void);
void UI_OpenDMConsole(int iMode);
void UI_CloseDMConsole(void);
void UI_ToggleDMConsole(int iMode);
void UI_OpenDeveloperConsole(void);
void UI_CloseDeveloperConsole(void);
void UI_PrintConsole(const char *msg);
//
// callbacks
//
void UI_Update( void );
void UI_ServerLoaded( void );
void UI_ResolutionChange( void );
void UI_KeyEvent( int key, unsigned int time );
void UI_CharEvent( int ch );
#endif /* __CL_UI_H__ */
void UI_Update(void);
void UI_ServerLoaded(void);
void UI_ResolutionChange(void);
void UI_KeyEvent(int key, unsigned int time);
void UI_CharEvent(int ch);
+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
+1 -1
View File
@@ -1009,7 +1009,7 @@ void UpdateServerListCallBack(GServerList serverlist, int msg, void* instance, v
return;
}
Cvar_Set("dm_serverstatusbar", va("%i", param2));
Cvar_Set("dm_serverstatusbar", va("%i", (int)(uintptr_t)param2));
}
if (msg == LIST_PROGRESS)
+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
+3 -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;
@@ -471,7 +470,7 @@ void CL_AddReliableCommand(const char *cmd, qboolean isDisconnectCmd);
void CL_StartHunkUsers( qboolean rendererOnly );
void CL_Connect( const char *server );
void CL_Connect( const char *server, netadrtype_t family );
void CL_Disconnect_f (void);
void CL_GetChallengePacket (void);
@@ -690,5 +689,3 @@ void CL_InitConsoleCommands( void );
#ifdef __cplusplus
}
#endif
#endif // __CLIENT_H__
+1
View File
@@ -58,6 +58,7 @@ typedef struct {
void S_ChannelFree_Callback(channel_t* v);
void S_LoadData(soundsystemsavegame_t* pSave);
void S_SaveData(soundsystemsavegame_t* pSave);
#ifdef __cplusplus
}
+17 -2
View File
@@ -55,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();
@@ -83,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
}
@@ -423,3 +434,7 @@ void S_ChannelFree_Callback(channel_t* v) {
void S_LoadData(soundsystemsavegame_t* pSave) {
// FIXME: unimplemented
}
void S_SaveData(soundsystemsavegame_t* pSave) {
// FIXME: unimplemented
}
+2 -1
View File
@@ -30,8 +30,8 @@ void S_Respatialize(int entityNum, const vec3_t origin, vec3_t axis[3]);
sfxHandle_t S_RegisterSound(const char* sample, qboolean compressed, qboolean streamed);
void S_AddLoopingSound(const vec3_t origin, const vec3_t velocity, sfxHandle_t sfxHandle, float volume, float minDist, float maxDist, float pitch, int flags);
void S_StartLocalSound(const char* name, qboolean force_load);
void S_StartLocalSoundChannel(const char* sound_name, qboolean force_load, int channel);
void S_StartSound(const vec3_t origin, int entNum, int entChannel, sfxHandle_t sfxHandle, float volume, float minDist, float pitch, float maxDist, qboolean streamed);
void S_StopAllSounds(qboolean stop_music);
void S_ClearLoopingSounds(void);
qboolean S_IsSoundRegistered(const char* name);
void S_Init2();
@@ -65,6 +65,7 @@ void MUSIC_UpdateMusicVolumes(void);
void MUSIC_CheckForStoppedSongs(void);
void S_StopSound(int entnum, int channel);
void S_StopAllSounds2(qboolean stop_music);
float S_GetSoundTime(sfxHandle_t handle);
void S_SetGlobalAmbientVolumeLevel(float volume);
void S_SetReverb(int reverb_type, float reverb_level);
+1 -1
View File
@@ -120,7 +120,7 @@ bool UConnection::SendEvent
ptr = m_listeners.ObjectAt( i );
if( ptr )
{
Event *e = new Event( m_events.ObjectAt( i ) );
Event *e = new Event( *m_events.ObjectAt( i ) );
for( j = 1; j < numargs; j++ )
{
+41 -1
View File
@@ -21,6 +21,46 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "DrivableVehicleTandem.h"
#include "vehicleturret.h"
// FIXME: unimplemented
CLASS_DECLARATION(DrivableVehicle, DrivableVehicleTandem, "DrivableVehicleTandem") {
{NULL, NULL}
};
DrivableVehicleTandem::DrivableVehicleTandem()
{
}
DrivableVehicleTandem::~DrivableVehicleTandem()
{
}
void DrivableVehicleTandem::SpawnTurret(Event* ev)
{
VehicleTurretGunTandem* pTurret = new VehicleTurretGunTandem();
int slot;
pTurret->SetBaseOrientation(orientation, NULL);
pTurret->setModel(ev->GetString(2));
slot = ev->GetInteger(1);
AttachTurretSlot(slot, pTurret, vec_zero, NULL);
pTurret->SetVehicleOwner(this);
pTurret->PostEvent(EV_TakeDamage, EV_POSTSPAWN);
UpdateTurretSlot(slot);
pTurret->ProcessPendingEvents();
}
void DrivableVehicleTandem::UpdateTurretSlot(int iSlot)
{
DrivableVehicle::UpdateTurretSlot(iSlot);
if (Turrets[iSlot].ent && Turrets[iSlot].ent->isSubclassOf(VehicleTurretGunTandem)) {
VehicleTurretGunTandem* pTurret = static_cast<VehicleTurretGunTandem*>(Turrets[iSlot].ent.Pointer());
pTurret->UpdateLinkedTurret();
}
}
+14
View File
@@ -21,3 +21,17 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#pragma once
#include "vehicle.h"
class DrivableVehicleTandem : public DrivableVehicle {
private:
CLASS_PROTOTYPE(DrivableVehicleTandem);
public:
DrivableVehicleTandem();
~DrivableVehicleTandem();
void SpawnTurret(Event* ev) override;
void UpdateTurretSlot(int iSlot) override;
};
+1449 -414
View File
File diff suppressed because it is too large. Load diff
+17 -4
View File
@@ -32,10 +32,11 @@ typedef enum {
} eController;
#define PT_SPAWNFLAG_PLAY_FIRE_SOUND 1
#define PT_SPAWNFLAG_PLAY_MOTION_SOUND 2
#define PT_SPAWNFLAG_TARGET_RANDOM 4
#define PT_SPAWNFLAG_TURN_ON 8
#define PT_SPAWNFLAG_SET_YAW 16
#define PT_SPAWNFLAG_SET_ROLL 32
#define PT_SPAWNFLAG_ROTATE_YAW 16
#define PT_SPAWNFLAG_ROTATE_ROLL 32
#define PT_SPAWNFLAG_TARGET_PLAYER 64
#define PT_SPAWNFLAG_HIDDEN 128
@@ -101,20 +102,28 @@ public:
bool ShouldStartOn() const;
bool ShouldHideModel() const;
bool ShouldPlayFireSound() const;
bool ShouldPlayMotionSound() const;
bool ShouldRotateYaw() const;
bool ShouldRotateRoll() const;
void EventIsTurnedOn(Event *ev);
void EventGetTargetEntity(Event *ev);
void EventLaunchSound(Event *ev);
void SetTarget(Event *ev);
void SetTarget(Entity* ent);
void OnInitialize(Event *ev);
void TurnOff(Event *ev);
void TurnOn(Event *ev);
bool ShouldTargetRandom() const;
void ChooseTarget();
Entity* ChooseTarget();
void GetLocalTargets();
bool ShouldTargetPlayer() const;
void GetTargetPos(Entity *target);
Vector GetTargetPos(Entity *target);
void GetMuzzlePos(Vector& pos);
void Fire();
void TryLaunchSound();
void SetWeaponAnim(const char* name, Event* ev);
void EventAccuracy(Event *ev);
void EventMaxDelay(Event *ev);
void EventMinDelay(Event *ev);
@@ -154,6 +163,7 @@ public:
void PlayPreImpactSound(Event *ev);
void SetProjectileModel(Event *ev);
float EstimateImpactTime(const Vector& targetOrigin, const Vector& fromOrigin, float speed) const;
bool Attack(int count) override;
void Archive(Archiver& arc) override;
};
@@ -196,6 +206,7 @@ public:
void SetBulletRange(Event *ev);
bool Attack(int count) override;
bool TickWeaponAnim();
void TickCycle(Event *ev) override;
void Archive(Archiver& arc) override;
};
@@ -238,6 +249,8 @@ public:
ThrobbingBox_Explosive();
bool ShouldDoExplosion();
void SetExplosionOffset(Event *ev);
void SetExplosionEffect(Event *ev);
void SetTriggered(Event *ev);
+99 -12
View File
@@ -114,19 +114,105 @@ void TOWObjectiveMan::TakeOverObjective(eController controller, eController cont
}
}
Event EV_SetController("ControlledBy", EV_DEFAULT, "i", "ControlledBy", "Sets the team controlling the objective");
Event EV_TakeOver(
"TakeOver", EV_DEFAULT, "i", "TeamNum", "Sets the team controlling the objective. 0 = Axis, 1 = Allies"
//---------------------------------------------------------------------------------------------
/*QUAKED func_TOWObjective (1.0 0.0 1.0) (-12 -12 -12) (12 12 12) StartOn Respawner
This object is an extension of the standard objective object. It is used for Tug of War
Maps.
object used to simplify placing objectives. You may optionally connect this object to the
target you want to use for the compass position....
Checkboxes:
StartOn - check this if you want this objective to be displayed when the level first loads
Respawner - check this if the objective is the respawn point for a team. If you set this
you must set ControlledBy to a valid team and not Neutral.
Parameters:
ControlledBy 0 = Axis, 1 = Allies, 2 = Neutral
AxisObjNum 1 - 5. Set the objective number for the axis. This will associate the objective with
the check box for the corresponding text in the score screen.
AlliesObjNum 1 - 5. Set the objective number for the allies. This will associate the objective with
the check box for the corresponding text in the score screen.
ObjectiveNbr <nObjNbr=0> Please ignore this for now.
Events:
TurnOn
TurnOff
Complete
Text <sNewText>
SetCurrent
SetController <ControlledBy> - This will set the starting controller default is neutral. See ControlledBy var above.
//---------------------------------------------------------------------------------------------
*/
Event EV_SetController
(
"ControlledBy",
EV_DEFAULT,
"i",
"ControlledBy",
"Sets the team controlling the objective",
EV_NORMAL
);
Event EV_SetAxisObjNum("AxisObjNum", EV_DEFAULT, "i", "AxisObjNum", "Sets the objective number for the axis team");
Event EV_SetAlliesObjNum(
"AlliesObjNum", EV_DEFAULT, "i", "AlliesObjNum", "Sets the objective number for the allies team"
Event EV_TakeOver
(
"TakeOver",
EV_DEFAULT,
"i",
"TeamNum",
"Sets the team controlling the objective. 0 = Axis, 1 = Allies",
EV_NORMAL
);
static Event EV_Initialize("initialize", EV_DEFAULT, 0, 0, "Initialize object");
static Event EV_SetCurrent(
"SetCurrent", EV_DEFAULT, "i", "TeamNum", "Set this objective as the current objective for the specified team."
Event EV_SetAxisObjNum
(
"AxisObjNum",
EV_DEFAULT,
"i",
"AxisObjNum",
"Sets the objective number for the axis team",
EV_NORMAL
);
Event EV_SetAlliesObjNum
(
"AlliesObjNum",
EV_DEFAULT,
"i",
"AlliesObjNum",
"Sets the objective number for the allies team",
EV_NORMAL
);
static Event EV_Initialize
(
"initialize",
EV_DEFAULT,
0,
0,
"Initialize object",
EV_NORMAL
);
static Event EV_SetCurrent
(
"SetCurrent",
EV_DEFAULT,
"i",
"TeamNum",
"Set this objective as the current objective for the specified team.",
EV_NORMAL
);
Event EV_GetController
(
"ControlledBy",
EV_DEFAULT,
0,
0,
"Objective controller",
EV_GETTER
);
Event EV_GetController("ControlledBy", EV_DEFAULT, 0, 0, "Objective controller", EV_GETTER);
CLASS_DECLARATION(Objective, TOWObjective, "func_towobjective") {
{&EV_SetController, &TOWObjective::SetController },
@@ -195,6 +281,7 @@ void TOWObjective::TakeOver(Event *ev)
}
g_TOWObjectiveMan.TakeOverObjective(m_eController, controller);
m_eController = controller;
if (m_bNoRespawnForLeading) {
//
@@ -216,8 +303,8 @@ void TOWObjective::SetAxisObjNum(Event *ev)
void TOWObjective::OnInitialize(Event *ev)
{
m_sAlliesObjName = "tow_allied_obj" + str(m_iAlliesObjNum);
m_sAxisObjName = "tow_allied_obj" + str(m_iAxisObjNum);
m_sAlliesObjName = "tow_allied_obj" + str(m_iAlliesObjNum);
m_sAxisObjName = "tow_axis_obj" + str(m_iAxisObjNum);
switch (m_eController) {
case CONTROLLER_ALLIES:
+4 -7
View File
@@ -45,12 +45,11 @@ VehicleCollisionEntity::VehicleCollisionEntity
m_pOwner = ent;
takedamage = DAMAGE_YES;
edict->s.renderfx &= ~RF_DONTDRAW;
edict->r.svFlags &= ~SVF_NOCLIENT;
showModel();
setMoveType( MOVETYPE_PUSH );
setSolidType(SOLID_NOT);
edict->clipmask |= MASK_CLIP;
edict->clipmask |= MASK_VEHICLE;
edict->s.eFlags |= EF_LINKANGLES;
}
@@ -72,9 +71,7 @@ void VehicleCollisionEntity::EventDamage
Event *ev
)
{
Event *event = new Event( ev );
m_pOwner->ProcessEvent( event );
m_pOwner->ProcessEvent(*ev);
}
void VehicleCollisionEntity::Solid
+124 -96
View File
@@ -28,131 +28,159 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
cVehicleSlot::cVehicleSlot()
{
prev_takedamage = ( damage_t )-1;
prev_solid = ( solid_t )-1;
prev_contents = -1;
prev_takedamage = (damage_t)-1;
prev_solid = (solid_t)-1;
prev_contents = -1;
}
void cVehicleSlot::NotSolid
(
void
)
void cVehicleSlot::NotSolid(void)
{
if( !( flags & FL_SWIM ) )
{
return;
}
int i;
if( !ent )
{
return;
}
if (!(flags & SLOT_BUSY)) {
return;
}
// Save previous values
prev_takedamage = ent->takedamage;
prev_solid = ent->edict->solid;
prev_contents = ent->edict->r.contents;
ent->takedamage = DAMAGE_NO;
ent->setSolidType( SOLID_NOT );
if (!ent) {
return;
}
// Save previous values
prev_takedamage = ent->takedamage;
prev_solid = ent->edict->solid;
prev_contents = ent->edict->r.contents;
ent->takedamage = DAMAGE_NO;
ent->setSolidType(SOLID_NOT);
for (i = 0; i < ent->numchildren; i++) {
Entity *sub = G_GetEntity(ent->children[i]);
if (sub && !sub->IsSubclassOfWeapon()) {
sub->setSolidType(SOLID_NOT);
}
}
if (!ent->IsSubclassOfPlayer()) {
ent->setSolidType(SOLID_NOT);
}
}
void cVehicleSlot::Solid
(
void
)
void cVehicleSlot::Solid(void)
{
if( !( flags & FL_SWIM ) )
{
return;
}
int i;
if( !ent )
{
return;
}
if (!(flags & FL_SWIM)) {
return;
}
// Restore previous values
ent->takedamage = prev_takedamage;
ent->setSolidType( prev_solid );
ent->edict->r.contents = prev_contents;
if (!ent) {
return;
}
// Save previous values
prev_takedamage = ( damage_t )-1;
prev_solid = ( solid_t )-1;
prev_contents = -1;
// Restore previous values
ent->takedamage = prev_takedamage;
ent->setSolidType(prev_solid);
ent->setContents(prev_contents);
// Save previous values
prev_takedamage = (damage_t)-1;
prev_solid = (solid_t)-1;
prev_contents = -1;
for (i = 0; i < ent->numchildren; i++) {
Entity *sub = G_GetEntity(ent->children[i]);
if (sub && !sub->IsSubclassOfWeapon()) {
sub->setSolidType(SOLID_BBOX);
}
}
}
cTurretSlot::cTurretSlot()
{
owner_prev_takedamage = ( damage_t )-1;
owner_prev_solid = ( solid_t )-1;
owner_prev_contents = -1;
owner_prev_takedamage = (damage_t)-1;
owner_prev_solid = (solid_t)-1;
owner_prev_contents = -1;
}
void cTurretSlot::NotSolid
(
void
)
void cTurretSlot::NotSolid(void)
{
if( !( flags & FL_SWIM ) )
{
return;
}
int i;
if( !ent )
{
return;
}
if (!(flags & FL_SWIM)) {
return;
}
cVehicleSlot::NotSolid();
if (!ent) {
return;
}
if( ent->IsSubclassOfTurretGun() )
{
TurretGun *turret = ( TurretGun * )ent.Pointer();
Entity *owner = turret->GetOwner();
// Save previous values
prev_takedamage = ent->takedamage;
prev_solid = ent->edict->solid;
prev_contents = ent->edict->r.contents;
if( owner )
{
owner_prev_takedamage = owner->takedamage;
owner_prev_solid = owner->edict->solid;
owner_prev_contents = owner->edict->r.contents;
ent->takedamage = DAMAGE_NO;
ent->setSolidType(SOLID_NOT);
owner->takedamage = DAMAGE_NO;
owner->setSolidType( SOLID_NOT );
}
}
if (ent->IsSubclassOfTurretGun()) {
TurretGun *turret = static_cast<TurretGun *>(ent.Pointer());
Entity *owner = turret->GetOwner();
if (owner) {
owner_prev_takedamage = owner->takedamage;
owner_prev_solid = owner->edict->solid;
owner_prev_contents = owner->edict->r.contents;
owner->takedamage = DAMAGE_NO;
owner->setSolidType(SOLID_NOT);
}
}
for (i = 0; i < ent->numchildren; i++) {
Entity *sub = G_GetEntity(ent->children[i]);
if (sub && !sub->IsSubclassOfWeapon()) {
sub->setSolidType(SOLID_NOT);
}
}
}
void cTurretSlot::Solid
(
void
)
void cTurretSlot::Solid(void)
{
if( !( flags & FL_SWIM ) )
{
return;
}
int i;
if( !ent )
{
return;
}
if (!(flags & FL_SWIM)) {
return;
}
cVehicleSlot::NotSolid();
if (!ent) {
return;
}
if( ent->IsSubclassOfTurretGun() )
{
TurretGun *turret = ( TurretGun * )ent.Pointer();
Entity *owner = turret->GetOwner();
// Restore previous values
ent->takedamage = prev_takedamage;
ent->setSolidType(prev_solid);
if( owner )
{
owner->takedamage = owner_prev_takedamage;
owner->setSolidType( owner_prev_solid );
// Save previous values
prev_takedamage = (damage_t)-1;
prev_solid = (solid_t)-1;
owner_prev_takedamage = ( damage_t )-1;
owner_prev_solid = ( solid_t )-1;
}
}
if (ent->IsSubclassOfTurretGun()) {
TurretGun *turret = static_cast<TurretGun *>(ent.Pointer());
Entity *owner = turret->GetOwner();
if (owner) {
owner->takedamage = owner_prev_takedamage;
owner->setSolidType(owner_prev_solid);
owner_prev_takedamage = (damage_t)-1;
owner_prev_solid = (solid_t)-1;
}
}
for (i = 0; i < ent->numchildren; i++) {
Entity *sub = G_GetEntity(ent->children[i]);
if (sub && !sub->IsSubclassOfWeapon()) {
sub->setSolidType(SOLID_BBOX);
}
}
}
+41 -50
View File
@@ -23,78 +23,69 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// VehicleSlot.h
//
#ifndef __VEHICLESLOT_H__
#define __VEHICLESLOT_H__
#pragma once
#include "g_local.h"
#include "class.h"
#include "entity.h"
#define SLOT_FREE 1
#define SLOT_BUSY 2
#define SLOT_UNUSED 4
#define SLOT_FREE 1
#define SLOT_BUSY 2
#define SLOT_UNUSED 4
class cVehicleSlot : public Class {
class cVehicleSlot : public Class
{
public:
SafePtr<Entity> ent;
int flags;
int boneindex;
int enter_boneindex;
SafePtr<Entity> ent;
int flags;
int boneindex;
int enter_boneindex;
private:
damage_t prev_takedamage;
solid_t prev_solid;
int prev_contents;
protected:
damage_t prev_takedamage;
solid_t prev_solid;
int prev_contents;
public:
cVehicleSlot();
cVehicleSlot();
virtual void NotSolid( void );
virtual void Solid( void );
void Archive( Archiver& arc ) override;
virtual void NotSolid(void);
virtual void Solid(void);
void Archive(Archiver &arc) override;
};
inline
void cVehicleSlot::Archive
(
Archiver& arc
)
inline void cVehicleSlot::Archive(Archiver& arc)
{
Class::Archive( arc );
Class::Archive(arc);
arc.ArchiveSafePointer( &ent );
arc.ArchiveInteger( &flags );
arc.ArchiveInteger( &boneindex );
arc.ArchiveInteger( &enter_boneindex );
ArchiveEnum( prev_takedamage, damage_t );
ArchiveEnum( prev_solid, solid_t );
arc.ArchiveInteger( &prev_contents );
arc.ArchiveSafePointer(&ent);
arc.ArchiveInteger(&flags);
arc.ArchiveInteger(&boneindex);
arc.ArchiveInteger(&enter_boneindex);
ArchiveEnum(prev_takedamage, damage_t);
ArchiveEnum(prev_solid, solid_t);
arc.ArchiveInteger(&prev_contents);
}
class cTurretSlot : public cVehicleSlot {
damage_t owner_prev_takedamage;
solid_t owner_prev_solid;
int owner_prev_contents;
class cTurretSlot : public cVehicleSlot
{
damage_t owner_prev_takedamage;
solid_t owner_prev_solid;
int owner_prev_contents;
public:
cTurretSlot();
cTurretSlot();
void NotSolid( void ) override;
void Solid( void ) override;
void Archive( Archiver& arc ) override;
void NotSolid(void) override;
void Solid(void) override;
void Archive(Archiver& arc) override;
};
inline
void cTurretSlot::Archive
(
Archiver& arc
)
inline void cTurretSlot::Archive(Archiver& arc)
{
cVehicleSlot::Archive( arc );
cVehicleSlot::Archive(arc);
ArchiveEnum( owner_prev_takedamage, damage_t );
ArchiveEnum( owner_prev_solid, solid_t );
arc.ArchiveInteger( &owner_prev_contents );
ArchiveEnum(owner_prev_takedamage, damage_t);
ArchiveEnum(owner_prev_solid, solid_t);
arc.ArchiveInteger(&owner_prev_contents);
}
#endif // __VEHICLESLOT_H__
+494 -74
View File
@@ -23,127 +23,547 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "vehicle.h"
#include "vehicleturret.h"
#include "player.h"
#include "g_phys.h"
CLASS_DECLARATION(DrivableVehicle, VehicleTank, "VehicleTank")
{
{ &EV_Damage, &VehicleTank::EventDamage },
{ NULL, NULL }
CLASS_DECLARATION(DrivableVehicle, VehicleTank, "VehicleTank") {
{&EV_Damage, &VehicleTank::EventDamage},
{NULL, NULL }
};
VehicleTank::VehicleTank()
{
entflags |= FL_ROTATEDBOUNDS;
entflags |= FL_ROTATEDBOUNDS;
}
VehicleTank::~VehicleTank()
{
entflags &= ~FL_ROTATEDBOUNDS;
entflags &= ~FL_ROTATEDBOUNDS;
}
qboolean VehicleTank::Drive(usercmd_t *ucmd)
{
Vector i;
Vector j;
Vector k;
Vector vTmp;
Vector i;
Vector j;
Vector k;
Vector vTmp;
vTmp = velocity;
VectorNormalize(vTmp);
vTmp = velocity;
vTmp.normalize();
if (!driver.ent || !driver.ent->client)
{
return qfalse;
}
if (!driver.ent || !driver.ent->isClient()) {
return qfalse;
}
if (!drivable)
{
driver.ent->client->ps.pm_flags |= PMF_FROZEN;
ucmd->forwardmove = 0;
ucmd->rightmove = 0;
ucmd->upmove = 0;
return qfalse;
}
if (!drivable) {
driver.ent->client->ps.pm_flags |= PMF_FROZEN;
ucmd->forwardmove = 0;
ucmd->rightmove = 0;
ucmd->upmove = 0;
return qfalse;
}
moveimpulse = ucmd->forwardmove * (vTmp.length() + 1.0);
m_bIsBraking = ucmd->forwardmove >> 31;
if (!m_bAutoPilot) {
//
// ignore client's control if the vehicle is in auto-pilot mode
//
moveimpulse = ucmd->forwardmove * (vTmp.length() + 1.0);
m_bIsBraking = ucmd->forwardmove < 0;
m_fAccelerator += ucmd->forwardmove * 0.005;
// acceleration must be an alpha value between [0, 1]
m_fAccelerator = Q_clamp_float(m_fAccelerator, 0, 1);
m_fAccelerator += ucmd->forwardmove * 0.005;
turnimpulse = -ucmd->rightmove;
jumpimpulse = ucmd->upmove;
}
if (m_fAccelerator < 0)
{
m_fAccelerator = 0.0;
}
VehicleTurretGun *vtg = (VehicleTurretGun *)Turrets[0].ent.Pointer();
turnimpulse = -ucmd->rightmove;
if (vtg && vtg->IsSubclassOfVehicleTurretGun() && driver.ent->IsSubclassOfSentient()) {
vtg->RemoteControl(ucmd, (Sentient *)driver.ent.Pointer());
VehicleTurretGun *vtg = (VehicleTurretGun *)Turrets[0].ent.Pointer();
if (vtg && vtg->IsSubclassOfVehicleTurretGun() && driver.ent->IsSubclassOfSentient())
{
vtg->RemoteControl(ucmd, (Sentient *)driver.ent.Pointer());
if (ucmd->upmove)
turnimpulse -= AngleSubtract(angles[1], vtg->angles[1]);
}
return qtrue;
if (ucmd->upmove) {
turnimpulse -= AngleSubtract(angles[1], vtg->angles[1]);
}
}
return qtrue;
}
void VehicleTank::EventDamage(Event *ev)
{
int mod;
mod = ev->GetInteger(9);
int mod;
mod = ev->GetInteger(9);
if (mod > MOD_VEHICLE && mod != MOD_SHOTGUN && mod != MOD_GRENADE)
{
Vehicle::EventDamage(ev);
if (g_gametype->integer == GT_SINGLE_PLAYER)
{
Player *p = (Player *)driver.ent.Pointer();
if (p)
{
if (p->IsSubclassOfPlayer())
{
p->m_iNumHitsTaken++;
}
}
}
}
if (g_gametype->integer == GT_TOW && !dmManager.RoundActive()) {
return;
}
switch (mod) {
case MOD_BULLET:
case MOD_BASH:
case MOD_FAST_BULLET:
case MOD_VEHICLE:
case MOD_SHOTGUN:
case MOD_GRENADE:
return;
}
Vehicle::EventDamage(ev);
if (g_gametype->integer == GT_SINGLE_PLAYER) {
Player *p = (Player *)driver.ent.Pointer();
if (p) {
if (p->IsSubclassOfPlayer()) {
p->m_iNumHitsTaken++;
}
}
}
}
void VehicleTank::Think()
{
flags |= FL_POSTTHINK;
flags |= FL_POSTTHINK;
}
void VehicleTank::Postthink()
{
// FIXME: STUB
float turn;
Vector i, j, k;
Vector normalsum;
Vector temp;
Vector pitch, roll;
Vector acceleration;
Vector atmp, atmp2, aup;
VehicleBase *v, *last;
float drivespeed;
Vector primal_angles, primal_origin;
Vector vTmp;
Vector vAddedAngles;
Vector n_angles;
float dot;
Vector newvel, flatvel;
Vector anglediff;
primal_angles = angles;
primal_origin = origin;
if (!g_vehicle->integer || edict->s.renderfx & RF_DONTDRAW) {
// don't process physics
return;
}
if (m_pCollisionEntity) {
// use the collision entity for collision
setSolidType(SOLID_NOT);
m_pCollisionEntity->Solid();
}
prev_velocity = velocity;
SetSlotsNonSolid();
if (m_bAnimMove) {
AnimMoveVehicle();
} else {
if (!m_bMovementLocked) {
FactorOutAnglesOffset();
FactorOutOriginOffset();
}
MoveVehicle();
}
SetSlotsSolid();
if (m_vOldMins != vec_zero && m_vOldMaxs != vec_zero) {
mins = m_vOldMins;
maxs = m_vOldMaxs;
} else if (mins != vec_zero && maxs != vec_zero) {
m_vOldMins = mins;
m_vOldMaxs = maxs;
}
if (m_bAnimMove) {
moveimpulse = velocity.length() * level.frametime;
turnimpulse = avelocity[1] * level.frametime;
} else if (m_bAutoPilot) {
AutoPilot();
}
currentspeed = moveimpulse;
turnangle = turnangle * 0.25 + turnimpulse;
turnangle = Q_clamp_float(turnangle, -maxturnrate, maxturnrate);
real_velocity = origin - prev_origin;
prev_origin = origin;
prev_acceleration = real_acceleration;
real_acceleration = real_velocity - prev_velocity;
prev_velocity = real_velocity;
acceleration = real_acceleration - prev_acceleration;
UpdateBones();
UpdateShaderOffset();
UpdateTires();
UpdateNormals();
temp = angles;
temp.AngleVectorsLeft(&i, &j, &k);
velocity[0] *= 0.925f;
velocity[1] *= 0.925f;
turn = turnangle / 200.0;
flatvel = orientation[0];
velocity += flatvel * currentspeed;
flatvel[2] = 0;
dot = velocity * flatvel;
dot = Q_clamp_float(dot, -speed, speed);
newvel = flatvel * dot;
velocity[0] = newvel[0];
velocity[1] = newvel[1];
avelocity *= 0.05f;
if (dot < 350) {
dot = 350;
}
avelocity.y += turn * dot;
angles += avelocity * level.frametime;
setAngles(angles);
if (Turrets[0].ent && Turrets[0].ent->IsSubclassOfVehicleTurretGun() && driver.ent
&& driver.ent->IsSubclassOfSentient()) {
VehicleTurretGun *pTurret = static_cast<VehicleTurretGun *>(Turrets[0].ent.Pointer());
if (jumpimpulse != 0) {
pTurret->SetUserViewAngles(pTurret->GetUserViewAngles() - Vector(0, avelocity[1] * level.frametime, 0));
}
}
drivespeed = acceleration * orientation[0];
UpdateSound();
if (AssertRotation(angles, primal_angles) != true) {
angles = primal_angles;
}
CalculateAnglesOffset(acceleration);
CalculateOriginOffset();
last_origin = origin;
anglediff = (angles - primal_angles) * level.frametime;
if (anglediff.x > 180 || anglediff.x < -180) anglediff.x = 0;
if (anglediff.y > 180 || anglediff.y < -180) anglediff.y = 0;
if (anglediff.z > 180 || anglediff.z < -180) anglediff.z = 0;
if (anglediff.x > -1 || anglediff.x < 1) anglediff.x = 0;
if (anglediff.y > -1 || anglediff.y < 1) anglediff.y = 0;
if (anglediff.z > -1 || anglediff.z < 1) anglediff.z = 0;
avelocity = anglediff;
if (!m_bAnimMove && !m_bMovementLocked) {
FactorInOriginOffset();
FactorInAnglesOffset(&vAddedAngles);
}
CalculateAnimationData(vAddedAngles, m_vOriginOffset + m_vOriginOffset2);
if (m_pCollisionEntity) {
Vector vaDelta;
SetSlotsNonSolid();
vaDelta[0] = angledist(angles[0] - m_pCollisionEntity->angles[0]);
vaDelta[1] = angledist(angles[1] - m_pCollisionEntity->angles[1]);
vaDelta[2] = angledist(angles[2] - m_pCollisionEntity->angles[2]);
m_pCollisionEntity->Solid();
G_PushMove(m_pCollisionEntity, origin - primal_origin, vaDelta);
G_TouchTriggers(m_pCollisionEntity);
SetSlotsSolid();
m_pCollisionEntity->setOrigin(origin);
m_pCollisionEntity->setAngles(angles);
}
SetupVehicleSoundEntities();
i = orientation[0];
j = orientation[1];
k = orientation[2];
//
// update slots
//
for (int ii = 0; ii < MAX_PASSENGERS; ii++) {
UpdatePassengerSlot(ii);
}
for (int ii = 0; ii < MAX_TURRETS; ii++) {
UpdateTurretSlot(ii);
}
for (last = this; last->vlink; last = v) {
v = last->vlink;
v->setOrigin(origin + i * v->offset.x + j * v->offset.y + k * v->offset.z);
v->avelocity = avelocity;
v->velocity = velocity;
v->angles[ROLL] = angles[ROLL];
v->angles[YAW] = angles[YAW];
v->angles[PITCH] = (int)(drivespeed / 4.f + v->angles[PITCH]) % 360;
v->setAngles(v->angles);
}
CheckWater();
WorldEffects();
if (m_pCollisionEntity) {
setSolidType(SOLID_NOT);
m_pCollisionEntity->Solid();
} else {
setSolidType(SOLID_BBOX);
setContents(CONTENTS_UNKNOWN2);
}
if ((driver.flags & SLOT_BUSY) && driver.ent) {
if (driver.ent->IsSubclassOfPlayer()) {
driver.ent->takedamage = DAMAGE_YES;
// Fixed in OPM.
// It's probably a mistake in moh 2.0 and above,
// the tank was non-solid with a player driver,
// instead of the driver being non-solid.
//setSolidType(SOLID_NOT);
driver.ent->setSolidType(SOLID_NOT);
} else {
driver.ent->takedamage = DAMAGE_NO;
driver.ent->setSolidType(SOLID_NOT);
}
}
}
void VehicleTank::CalculateOriginOffset()
{
// FIXME: STUB
int index;
Vector vTireAvg;
Vector vMissHit;
Vector temp;
int iNum = 0;
Vector acceleration;
Vector oldoffset;
oldoffset = m_vOriginOffset;
m_vOriginOffset += m_vOriginOffset2;
m_vOriginOffset2 = vec_zero;
for (index = 0; index < NUM_VEHICLE_TIRES; index++) {
if (m_bTireHit[index]) {
vTireAvg += origin - m_vTireEnd[index];
iNum++;
} else {
vMissHit = Corners[index];
}
}
if (m_iNumNormals > 0 && iNum == NUM_VEHICLE_TIRES - 1) {
Vector point;
temp = m_vNormalSum * (1.f / m_iNumNormals);
temp.normalize();
ProjectPointOnPlane(point, vMissHit, temp);
vTireAvg += point;
iNum++;
}
if (iNum == NUM_VEHICLE_TIRES) {
vec3_t vOriginCornerOffset;
vTireAvg *= 1.f / NUM_VEHICLE_TIRES;
MatrixTransformVector(m_vOriginCornerOffset, orientation, vOriginCornerOffset);
vTireAvg -= vOriginCornerOffset;
m_vOriginOffset2 += vTireAvg;
}
//m_vOriginOffset2 += vec_zero;
m_vOriginOffset -= m_vOriginOffset2;
if (!isfinite(m_vOriginOffset[0]) || !isfinite(m_vOriginOffset[1]) || !isfinite(m_vOriginOffset[2])) {
m_vOriginOffset = oldoffset;
}
}
void VehicleTank::UpdateSound()
{
// FIXME: STUB
float pitch = 1.f;
float volume = 1.f;
if (level.time < m_fNextSoundState) {
return;
}
pitch = (velocity.length() - m_fSoundMinSpeed) / (m_fSoundMaxSpeed - m_fSoundMinSpeed);
pitch = Q_clamp_float(pitch, 0, 1);
pitch = (m_fSoundMaxPitch - m_fSoundMinPitch) * pitch + m_fSoundMinPitch;
volume = (velocity.length() - m_fVolumeMinSpeed) / (m_fVolumeMaxSpeed - m_fVolumeMinSpeed);
volume = Q_clamp_float(volume, 0, 1);
volume = (m_fVolumeMaxPitch - m_fVolumeMinPitch) * volume + m_fVolumeMinPitch;
if (level.intermissiontime) {
m_eSoundState = ST_OFF;
}
switch (m_eSoundState) {
case ST_OFF:
StopLoopSound();
TurnOffVehicleSoundEntities();
m_fNextSoundState = level.time;
if (driver.ent || m_bAutoPilot) {
m_eSoundState = ST_OFF_TRANS_IDLE;
}
break;
case ST_OFF_TRANS_IDLE:
m_fNextSoundState = level.time;
m_eSoundState = ST_IDLE;
Sound(m_sSoundSet + "snd_on", CHAN_AUTO);
LoopSound(m_sSoundSet + "snd_idle");
break;
case ST_IDLE_TRANS_OFF:
m_fNextSoundState = level.time;
m_eSoundState = ST_OFF;
Sound(m_sSoundSet + "snd_off", CHAN_AUTO);
StopLoopSound();
break;
case ST_IDLE:
m_fNextSoundState = level.time;
if (driver.ent || m_bAutoPilot) {
if (fabs(velocity * orientation[0]) > 150) {
m_eSoundState = ST_IDLE_TRANS_RUN;
} else if (fabs(turnimpulse) > 1) {
m_eSoundState = ST_IDLE_TRANS_TURN;
}
} else {
m_eSoundState = ST_IDLE_TRANS_OFF;
}
LoopSound(m_sSoundSet + "snd_idle");
TurnOffVehicleSoundEntities();
break;
case ST_IDLE_TRANS_RUN:
m_fNextSoundState = level.time;
m_eSoundState = ST_RUN;
Sound(m_sSoundSet + "snd_revup", CHAN_AUTO);
Sound(m_sSoundSet + "snd_shift", CHAN_AUTO);
LoopSound(m_sSoundSet + "snd_run", volume, -1, -1, pitch);
break;
case ST_RUN:
m_fNextSoundState = level.time;
if (fabs(velocity * orientation[0]) < 150) {
m_eSoundState = ST_RUN_TRANS_IDLE;
}
TurnOnVehicleSoundEntities();
LoopSound(m_sSoundSet + "snd_run", volume, -1, -1, pitch);
break;
case ST_RUN_TRANS_IDLE:
m_fNextSoundState = level.time;
m_eSoundState = ST_IDLE;
Sound(m_sSoundSet + "snd_revdown", CHAN_AUTO);
LoopSound(m_sSoundSet + "snd_idle");
break;
case ST_IDLE_TRANS_TURN:
m_fNextSoundState = level.time;
m_eSoundState = ST_TURN;
Sound(m_sSoundSet + "snd_revup", CHAN_AUTO);
Sound(m_sSoundSet + "snd_shift", CHAN_AUTO);
LoopSound(m_sSoundSet + "snd_run", volume, -1, -1, pitch);
break;
case ST_TURN:
m_fNextSoundState = level.time;
if (fabs(turnimpulse) < 1) {
m_eSoundState = ST_TURN_TRANS_IDLE;
}
LoopSound(m_sSoundSet + "snd_run", volume, -1, -1, pitch);
break;
case ST_TURN_TRANS_IDLE:
m_fNextSoundState = level.time;
m_eSoundState = ST_IDLE;
Sound(m_sSoundSet + "snd_revdown", CHAN_AUTO);
LoopSound(m_sSoundSet + "snd_idle");
break;
default:
m_fNextSoundState = level.time;
m_eSoundState = ST_OFF;
break;
}
}
void VehicleTank::AttachDriverSlot(Event* ev)
//
// Fixed in OPM:
// This method only work when called from script.
// But it is not called automatically when the player actually uses the vehicle
// when that vehicle is unlocked.
// So the other native method is overriden instead
/*
void VehicleTank::AttachDriverSlot(Event *ev)
{
Vehicle::AttachDriverSlot(ev);
Vehicle::AttachDriverSlot(ev);
VehicleTurretGun *vtg = (VehicleTurretGun *)Turrets[0].ent.Pointer();
if (!driver.ent) {
//
// Added in OPM.
// original mohaa doesn't check if driver.ent is valid, which can cause crash if the attached entity is null.
// on single-player, it would crash while loading m5l2a when sv_maxclients is above 1.
// The reason of the crash is that attachdriverslot is called with $player which can be NULL on prespawn.
// $player is not created on prespawn when sv_maxclients is above 1
//
return;
}
if (vtg && vtg->IsSubclassOfVehicleTurretGun() && driver.ent->IsSubclassOfSentient())
{
vtg->SetOwner((Sentient *)driver.ent.Pointer());
Think();
Postthink();
vtg->Think();
}
VehicleTurretGun *vtg = (VehicleTurretGun *)Turrets[0].ent.Pointer();
if (vtg && vtg->IsSubclassOfVehicleTurretGun() && driver.ent->IsSubclassOfSentient()) {
vtg->SetRemoteOwner(static_cast<Sentient *>(driver.ent.Pointer()));
Think();
Postthink();
vtg->Think();
}
}
*/
void VehicleTank::AttachDriverSlot(int slot, Entity* ent, Vector vExitPosition)
{
Vehicle::AttachDriverSlot(slot, ent, vExitPosition);
if (!driver.ent) {
//
// Added in OPM.
// original mohaa doesn't check if driver.ent is valid, which can cause crash if the attached entity is null.
// on single-player, it would crash while loading m5l2a when sv_maxclients is above 1.
// The reason of the crash is that attachdriverslot is called with $player which can be NULL on prespawn.
// $player is not created on prespawn when sv_maxclients is above 1
//
return;
}
VehicleTurretGun* vtg = static_cast<VehicleTurretGun*>(Turrets[0].ent.Pointer());
if (vtg && vtg->IsSubclassOfVehicleTurretGun() && driver.ent->IsSubclassOfSentient()) {
vtg->SetRemoteOwner(static_cast<Sentient*>(driver.ent.Pointer()));
Think();
Postthink();
vtg->Think();
}
}
void VehicleTank::DriverAdded()
{
int i;
for (i = 0; i < MAX_TURRETS; i++) {
if (Turrets[i].flags & SLOT_BUSY && Turrets[i].ent && Turrets[i].ent->IsSubclassOfVehicleTurretGun()) {
VehicleTurretGun *pTurret = static_cast<VehicleTurretGun *>(Turrets[i].ent.Pointer());
pTurret->TurretHasBeenMounted();
}
}
}
+641 -38
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2018 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -22,64 +22,667 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "vehicle.h"
#include "player.h"
#include "debuglines.h"
#include "g_phys.h"
CLASS_DECLARATION(DrivableVehicle, VehicleWheelsX2, "VehicleWheelsX2")
{
{ &EV_Damage, &VehicleWheelsX2::EventDamage },
{ &EV_Killed, &VehicleWheelsX2::Killed },
{ NULL, NULL }
CLASS_DECLARATION(DrivableVehicle, VehicleWheelsX2, "VehicleWheelsX2") {
{&EV_Damage, &VehicleWheelsX2::EventDamage},
{&EV_Killed, &VehicleWheelsX2::Killed },
{NULL, NULL }
};
VehicleWheelsX2::VehicleWheelsX2()
{
m_iGear = 1;
m_iRPM = 0;
gravity = 1.0;
m_fDifferentialRatio = 4.8800001f;
m_fGearEfficiency = 0.69999999f;
m_fGearRatio[0] = -2.9400001f;
m_fGearRatio[1] = 2.9400001f;
m_fGearRatio[2] = 1.9400001f;
m_fGearRatio[3] = 1.0f;
m_fAccelerator = 0.0f;
m_bAutomatic = qtrue;
m_bBackSlipping = qfalse;
m_bFrontSlipping = qfalse;
gravity = 1.0;
m_fDifferentialRatio = 4.88f;
m_fGearEfficiency = 0.7f;
m_fGearRatio[0] = -2.95f;
m_fGearRatio[1] = 2.95f;
m_fGearRatio[2] = 1.95f;
m_fGearRatio[3] = 1.0f;
m_iGear = 1;
m_iRPM = 0;
m_fAccelerator = 0.0f;
m_bAutomatic = qtrue;
m_bBackSlipping = qfalse;
m_bFrontSlipping = qfalse;
}
void VehicleWheelsX2::UpdateVariables(Vector *acceleration, Vector *vpn, Vector *vup, Vector *vright, Vector *t_vpn, Vector *t_vup, Vector *t_vright)
void VehicleWheelsX2::Killed(Event *ev)
{
// FIXME: STUB
deadflag = DEAD_DEAD;
}
float VehicleWheelsX2::TorqueLookup(int rpm)
{
if (rpm <= 2099)
return 100.0;
if (rpm > 3599)
return 0.0;
return (100 * (3600 - rpm)) * 0.001;
if (rpm < 2100) {
return 100.0;
} else if (rpm >= 3600) {
return 0.0;
} else {
return (100 * (3600 - rpm)) / 1000.f;
}
}
void VehicleWheelsX2::UpdateVariables(
Vector *acceleration, Vector *vpn, Vector *vup, Vector *vright, Vector *t_vpn, Vector *t_vup, Vector *t_vright
)
{
int i;
Vector vNewCG;
Vector vBoxSize;
float longspeed;
Vector _i, _j, _k;
Vector r_i, r_j, r_k;
Vector r_velocity;
float dots[4];
r_velocity = velocity;
m_bIsSkidding = false;
vBoxSize = maxs - mins;
SetControllerAngles(0, Vector(0, turnangle, 0));
SetControllerAngles(1, Vector(0, turnangle, 0));
vNewCG = localorigin;
if (vNewCG != m_vCG) {
m_vCG = vNewCG;
vNewCG -= localorigin;
m_fWheelBase = vBoxSize.x;
m_fWheelFrontDist = vBoxSize.x * 0.5 - vNewCG.x;
m_fWheelBackDist = vBoxSize.x * -0.5 + vNewCG.x;
m_fTrackWidth = vBoxSize.y;
}
Vector vNewVpn = angles;
vNewVpn.AngleVectorsLeft(&r_i, &r_j, &r_k);
vNewVpn.y += turnangle;
vNewVpn.AngleVectorsLeft(&_i, &_j, &_k);
dots[3] = r_velocity * *vpn * 0.02;
dots[2] = r_velocity * *vright * 0.02;
dots[1] = r_velocity * *t_vpn * 0.02;
dots[0] = r_velocity * *t_vright * 0.02;
m_sWheels[0].fTraction = 0.8f;
m_sWheels[1].fTraction = 0.9f;
m_sWheels[0].fYawOffset = 0;
m_sWheels[1].fYawOffset = DEG2RAD(turnangle);
m_sWheels[0].fLongDist = m_fWheelBackDist * 0.02;
m_sWheels[1].fLongDist = m_fWheelFrontDist * 0.02;
m_sWheels[0].fLatDist = m_fTrackWidth * -0.02;
m_sWheels[1].fLatDist = m_fTrackWidth * 0.02;
// initialize the wheels
for (i = 0; i < 2; i++) {
m_sWheels[i].fLongForce = 0;
m_sWheels[i].fForce = 0;
m_sWheels[i].vLongForce = vec_zero;
m_sWheels[i].vLatForce = vec_zero;
m_sWheels[i].vForce = vec_zero;
m_sWheels[i].vVelocity = vec_zero;
m_sWheels[i].bSkidding = false;
m_sWheels[i].bSpinning = false;
m_sWheels[i].fTorque = 0;
m_sWheels[i].fLatTorque = 0;
m_sWheels[i].fLongTorque = 0;
}
for (i = 0; i < 2; i++) {
Vector p1, p3, p4;
Vector vTp, vTr, vTu;
vec3_t p2;
p3 = Corners[i];
p3.normalize();
vectoangles(p3, p2);
p1 = vec_zero;
p1[1] = angles[1] + p2[1] + 90;
p1.AngleVectorsLeft(&vTp, &vTr, &vTu);
m_sWheels[i].vVelocity = vTp * RAD2DEG(m_vAngularVelocity.y) * fabs(m_sWheels[i].fLongDist) * level.frametime;
G_LineWidth(5.0);
G_DebugLine(
origin + Corners[i][0] * r_i + Corners[i][1] * r_j,
origin + Corners[i][0] * r_i + Corners[i][1] * r_j + m_sWheels[i].vVelocity * 50,
0.7f,
0.5f,
1.0f,
1.0f
);
p1 = vec_zero;
p1[1] = angles[1] + RAD2DEG(m_sWheels[i].fYawOffset);
p1.AngleVectorsLeft(&vTp, &vTr, &vTu);
m_sWheels[i].vOrientation = vTp;
G_LineWidth(5.0);
G_DebugLine(
origin + Corners[i][0] * r_i + Corners[i][1] * r_j,
origin + Corners[i][0] * r_i + Corners[i][1] * r_j + m_sWheels[i].vOrientation * 50,
0.7f,
0.0f,
1.0f,
1.0f
);
}
Vector start, end;
Vector boxoffset;
Vector t_mins(-8, -8, -8);
Vector t_maxs(8, 8, 8);
trace_t trace;
start = origin + *vpn * (m_vCG[0] - localorigin[0]) + *vright * (m_vCG[1] - localorigin[1])
+ *vup * (m_vCG[2] - localorigin[2]);
end = start;
end[2] -= maxtracedist;
trace = G_Trace(start, t_mins, t_maxs, end, this, MASK_SOLID, qfalse, "Vehicle::PostThink Corners");
m_fInertia = m_fMass * 100;
m_fWheelFrontLoad = m_fMass * 9.81 * fabs(m_fWheelFrontDist / m_fWheelBase);
m_fWheelBackLoad = m_fMass * 9.81 * fabs(m_fWheelBackDist / m_fWheelBase);
longspeed = m_vAcceleration.length() * 0.02 * m_fMass / m_fWheelBase;
m_fWheelFrontLoad -= longspeed;
m_fWheelBackLoad += longspeed;
m_sWheels[0].fLoad = m_fWheelBackLoad;
m_sWheels[1].fLoad = m_fWheelFrontLoad;
float fMassShifted = m_fTireRadius * M_PI;
m_fTireRotationalSpeed = dots[3] / (fMassShifted + fMassShifted);
m_iRPM = m_fTireRotationalSpeed * m_fGearRatio[m_iGear] * m_fDifferentialRatio * 10;
m_fMaxTraction =
TorqueLookup(m_iRPM) * m_fGearRatio[m_iGear] * m_fDifferentialRatio * m_fGearEfficiency / m_fTireRadius;
m_fTractionForce = m_fAccelerator * m_fMaxTraction;
if (m_bIsBraking && dots[3] > 0) {
m_fTractionForce = -fSign(dots[3]) * 1000 * dots[3];
}
for (i = 0; i < 2; i++) {
float maxgrip;
maxgrip = m_sWheels[i].fTraction * m_sWheels[i].fLoad * 9.81;
if (m_fTractionForce > maxgrip) {
m_fTractionForce = maxgrip * 0.6;
m_sWheels[i].bSpinning = true;
m_sWheels[i].bSkidding = true;
Com_Printf("Skidding!\n");
}
if (m_fTractionForce < -maxgrip) {
m_fTractionForce = -maxgrip * 0.6;
m_sWheels[i].bSkidding = true;
Com_Printf("Skidding!\n");
}
m_sWheels[i].fLongForce = this->m_sWheels[i].fLongForce + m_fTractionForce;
m_sWheels[i].vLongForce += m_sWheels[i].vOrientation * m_sWheels[i].fLongForce;
}
m_vResistance[0] =
-(velocity[0] * 0.02 * m_fRollingResistance + velocity[0] * 0.02 * m_fDrag * fabs(velocity[0] * 0.02));
m_vResistance[1] =
-(velocity[1] * 0.02 * m_fRollingResistance + velocity[1] * 0.02 * m_fDrag * fabs(velocity[1] * 0.02));
m_vResistance[2] =
-(velocity[2] * 0.02 * m_fRollingResistance + velocity[2] * 0.02 * m_fDrag * fabs(velocity[2] * 0.02));
m_fBrakingPerformance = -m_fRollingResistance - *vpn * Vector(0, 0, -1) * m_fMass;
if (dots[3] == 0) {
m_fBrakingPerformance = 0;
} else {
m_fBrakingPerformance = (dots[3] - (m_fTireRotationalSpeed * m_fTireRadius - m_fBrakingPerformance)) / dots[3];
m_fBrakingPerformance = (1.0 - m_fBrakingPerformance) * -(-m_fFrontBrakingForce - m_fBackBrakingForce);
}
if (r_velocity.length() * 0.02 > 0.01) {
m_fTangForce = 0;
m_vTangForce = vec_zero;
for (i = 0; i < 2; i++) {
Vector va, vr;
Vector vVel;
Vector v1, v2;
va = angles;
va.x = 0;
va.y += RAD2DEG(m_sWheels[i].fYawOffset);
va.z = 0;
va.AngleVectorsLeft(NULL, &vr, NULL);
vVel = m_sWheels[i].vVelocity + velocity;
// get the direction
v1 = vVel;
v1.normalize();
// get the angles
vectoangles(v1, v2);
m_sWheels[i].fSlipAngle = DEG2RAD(angledist(va.y - v2.y));
m_sWheels[i].fGripCoef = m_sWheels[i].fSlipAngle * 0.15;
m_sWheels[i].fGripCoef = Q_clamp_float(m_sWheels[i].fGripCoef, -1.2f, 1.2f);
m_sWheels[i].fLatForce += m_sWheels[i].fGripCoef * m_sWheels[i].fLoad * 9.81;
if (m_sWheels[i].fLoad * 2 * m_sWheels[i].fTraction < fabs(m_sWheels[i].fLatForce)) {
m_sWheels[i].fLatForce = m_sWheels[i].fLatForce / 9.81;
m_sWheels[i].bSkidding = true;
Com_Printf("Skidding %i!\n", i);
}
m_sWheels[i].vLatForce += vr * m_sWheels[i].fLatForce;
G_LineWidth(3.0);
G_DebugLine(
origin + Corners[i][0] * r_i + Corners[i][1] * r_j,
origin + Corners[i][0] * r_i + Corners[i][1] * r_j + m_sWheels[i].vLatForce * 50 * (1.0 / m_fMass),
0.7f,
0.5f,
0.2f,
1.0f
);
}
} else {
m_fTangForce = 0;
m_vTangForce = vec_zero;
}
m_vForce = vec_zero;
for (i = 0; i < 2; i++) {
m_sWheels[i].vForce = m_sWheels[i].vLatForce + m_sWheels[i].vLongForce;
m_vForce += m_sWheels[i].vForce;
}
m_vForce += m_vResistance;
G_LineWidth(5.0);
G_DebugLine(origin, origin + m_vTangForce * (1.0 / m_fMass) * 50, 1.0, 0.0, 1.0, 1.0);
m_vAcceleration = m_vForce * (1.0 / m_fMass) * 50;
m_fTorque = 0;
for (i = 0; i < 2; i++) {
m_sWheels[i].fTorque += m_sWheels[i].fLongTorque + m_sWheels[i].fLatTorque;
m_fTorque += m_sWheels[i].fTorque;
}
m_vAngularAcceleration[1] = angledist(RAD2DEG(m_fTorque));
m_vAngularVelocity += m_vAngularAcceleration * level.frametime;
m_vAngularVelocity *= 0.825f;
avelocity = m_vAngularVelocity;
if (m_bAutomatic) {
//
// set the gear
//
if (m_iRPM >= 2100 && m_iGear <= 2) {
m_iGear++;
}
if (m_iRPM <= 600 && m_iGear > 1) {
m_iGear--;
}
}
prev_moveimpulse = moveimpulse;
}
void VehicleWheelsX2::Think()
{
vmove_t vm;
vmove_t vm;
flags |= FL_POSTTHINK;
prev_velocity = velocity;
flags |= FL_POSTTHINK;
prev_velocity = velocity;
SetMoveInfo(&vm);
VmoveSingle(&vm);
GetMoveInfo(&vm);
SetMoveInfo(&vm);
VmoveSingle(&vm);
GetMoveInfo(&vm);
}
void VehicleWheelsX2::Postthink()
{
// FIXME: STUB
}
float turn;
Vector i, j, k;
int index;
trace_t trace;
Vector normalsum;
Vector normalsum_Front;
int numnormals_Front;
Vector normalsum_Back;
int numnormals_Back;
Vector temp;
Vector pitch, roll;
Vector acceleration;
Vector atmp, atmp2, aup;
VehicleBase *v;
VehicleBase *last;
float drivespeed;
Vector primal_angles;
Vector vTmp;
Vector n_angles;
void VehicleWheelsX2::Killed(Event* ev)
{
deadflag = DEAD_DEAD;
}
primal_angles = angles;
if (drivable) {
currentspeed = moveimpulse;
turnangle = turnangle * 0.25f + turnimpulse;
turnangle = Q_clamp_float(turnangle, -maxturnrate, maxturnrate);
if (turnangle > maxturnrate) {
turnangle = maxturnrate;
} else if (turnangle < -maxturnrate) {
turnangle = -maxturnrate;
} else if (fabs(turnangle) < 2) {
turnangle = 0;
}
real_velocity = origin - prev_origin;
prev_origin = origin;
prev_acceleration = real_acceleration;
real_acceleration = real_velocity - prev_velocity;
prev_velocity = real_velocity;
acceleration = real_acceleration - prev_acceleration;
angles[0] = 0;
angles[2] = 0;
temp[0] = angles[0];
temp[1] = angles[1];
temp[2] = angles[2];
temp.AngleVectorsLeft(&i, &j, &k);
j = vec_zero - j;
index = 0;
numnormals_Front = 0;
numnormals_Back = 0;
for (index = 0; index < 4; index++) {
Vector start, end;
Vector boxoffset;
Vector t_mins(-8, -8, -8);
Vector t_maxs(8, 8, 8);
boxoffset = Corners[index];
start = origin + i * boxoffset[0] + j * boxoffset[1] + k * boxoffset[2];
end = start;
end[2] -= maxtracedist;
trace = G_Trace(start, mins, maxs, end, this, MASK_SOLID, qfalse, "Vehicle::PostThink Corners");
if (trace.fraction != 1 && !trace.startsolid) {
if (index > 2) {
normalsum_Front += trace.plane.normal;
numnormals_Front++;
} else {
normalsum_Back += trace.plane.normal;
numnormals_Back++;
}
normalsum += trace.plane.normal;
}
}
if (angles[2] < 60 || angles[2] > 300) {
if (numnormals_Front > 1) {
m_vFrontNormal = normalsum_Front * (1.0 / numnormals_Front);
temp = m_vFrontNormal;
m_vFrontAngles[0] = -temp.CrossProduct(temp, j).toPitch();
// no yaw
m_vFrontAngles[1] = 0;
temp = m_vFrontNormal;
m_vFrontAngles[2] = temp.CrossProduct(temp, i).toPitch();
}
if (numnormals_Back > 1) {
m_vBackNormal = normalsum_Back * (1.0 / numnormals_Back);
temp = m_vBackNormal;
m_vBackAngles[0] = -temp.CrossProduct(temp, j).toPitch();
// no yaw
m_vBackAngles[1] = 0;
temp = m_vBackNormal;
m_vBackAngles[2] = temp.CrossProduct(temp, i).toPitch();
}
if (numnormals_Front + numnormals_Back > 1) {
m_vBaseNormal = (normalsum_Front + normalsum_Back) * (1.0 / numnormals_Front + numnormals_Back);
temp = m_vBaseNormal;
m_vBaseAngles[0] = -temp.CrossProduct(temp, j).toPitch();
// no yaw
m_vBaseAngles[1] = 0;
temp = m_vBaseNormal;
m_vBaseAngles[2] = temp.CrossProduct(temp, i).toPitch();
}
}
n_angles = m_vBaseAngles - angles;
n_angles[0] = angledist(n_angles[0]);
n_angles[1] = angledist(n_angles[1]);
n_angles[2] = angledist(n_angles[2]);
angles[0] += n_angles[0] * 4.5 * level.frametime;
angles[2] += n_angles[2] * 4.5 * level.frametime;
m_vPrevNormal = m_vBaseNormal;
if (currentspeed < 0 && velocity * i > 0) {
m_fFrontBrakingForce = 0.2f;
m_fBackBrakingForce = 0.1f;
} else {
m_fFrontBrakingForce = 0;
m_fBackBrakingForce = 0;
}
turn = turnangle * 0.005;
Vector _i, _j, _k;
Vector vNewVpn = angles;
vNewVpn.y += turnangle;
vNewVpn.AngleVectorsLeft(&_i, &_j, &_k);
UpdateVariables(&acceleration, &i, &j, &k, &_i, &_j, &_k);
m_vAngles = angles;
if (currentspeed < 0 && velocity * i > 0) {
currentspeed = 0;
}
normalsum = vec_zero;
for (index = 0; index < 4; index++) {
Vector start, end;
Vector boxoffset;
Vector t_mins(-8, -8, -8);
Vector t_maxs(8, 8, 8);
boxoffset = Corners[index];
start = origin + i * boxoffset[0] + j * boxoffset[1] + k * boxoffset[2] + Vector(0, 0, 10);
end = start;
end[2] -= maxtracedist;
trace = G_Trace(start, mins, maxs, end, this, MASK_SOLID, qfalse, "Vehicle::PostThink Corners");
if (trace.fraction != 1.0) {
float fCoef;
if (index > 2) {
fCoef = m_fWheelFrontLoad / (m_fWheelFrontDist / m_fWheelBase * m_fMass);
fCoef = Q_clamp_float(fCoef, 0, 1);
normalsum += _i * currentspeed * fCoef;
normalsum += i * currentspeed * (1.0 - fCoef);
} else {
fCoef = m_fWheelBackLoad / (m_fWheelBackDist / m_fWheelBase * m_fMass);
fCoef = Q_clamp_float(fCoef, 0, 1);
normalsum += i * currentspeed * fCoef;
normalsum += _i * currentspeed * (1.0 - fCoef);
}
}
}
AnglesToAxis(angles, orientation);
vmove_t vm;
SetMoveInfo(&vm);
m_sMoveGrid->SetMoveInfo(&vm);
m_sMoveGrid->SetOrientation(orientation);
if (m_sMoveGrid->CheckStuck()) {
angles = primal_angles;
AnglesToAxis(angles, orientation);
}
if (groundentity && (angles[2] < 60 || angles[2] > 300)) {
float dot;
Vector newvel, flatvel;
velocity[0] *= 0.925f;
velocity[1] *= 0.925f;
newvel = orientation[0];
velocity += newvel * currentspeed;
newvel[2] = 0;
dot = velocity * newvel;
dot = Q_clamp_float(dot, -speed, speed);
if (dot > speed) {
dot = speed;
} else if (dot < -speed) {
dot = -speed;
} else if (fabs(dot) < 20) {
dot = 0;
}
flatvel = newvel * dot;
velocity[0] = flatvel[0];
velocity[1] = flatvel[1];
velocity[2] += jumpimpulse * dot;
avelocity *= 0.05f;
if (steerinplace) {
if (dot < 350) {
dot = 350;
}
avelocity.y += turn * dot;
} else {
avelocity.y += turn * dot;
}
} else {
if (angles[2] > 60) {
angles[2]; // FIXME: ??
}
velocity += m_vAcceleration * level.frametime;
}
angles += avelocity * level.frametime;
setAngles(angles);
prev_origin = origin;
}
drivespeed = acceleration * orientation[0];
if (drivable && driver.ent) {
str sound_name;
if (currentspeed > 0) {
sound_name = "snd_forward";
} else if (currentspeed == 0) {
sound_name = "snd_idle";
} else {
sound_name = "snd_backward";
}
LoopSound(sound_name);
}
i = orientation[0];
j = orientation[1];
k = orientation[2];
if (driver.ent) {
driver.ent->setOrigin(origin + i * driveroffset[0] + j * driveroffset[1] + k * driveroffset[2]);
if (drivable) {
// clear the driver velocity
driver.ent->velocity = vec_zero;
// set the driver angles to the vehicle's angle
driver.ent->setAngles(angles);
}
}
vTmp = (angles - primal_angles) * level.frametime;
if (vTmp.x > 180 || vTmp.x < -180) {
vTmp.x = 0;
}
if (vTmp.y > 180 || vTmp.y < -180) {
vTmp.y = 0;
}
if (vTmp.z > 180 || vTmp.z < -180) {
vTmp.z = 0;
}
if (vTmp.x > -1 || vTmp.x < 1) {
vTmp.x = 0;
}
if (vTmp.y > -1 || vTmp.y < 1) {
vTmp.y = 0;
}
if (vTmp.z > -1 || vTmp.z < 1) {
vTmp.z = 0;
}
avelocity = vTmp;
for (last = this; last->vlink; last = v) {
v = last->vlink;
v->setOrigin(origin + i * v->offset.x + j * v->offset.y + k * v->offset.z);
v->avelocity = avelocity;
v->velocity = velocity;
v->angles[ROLL] = angles[ROLL];
v->angles[YAW] = angles[YAW];
v->angles[PITCH] = (int)(drivespeed / 4.f + v->angles[PITCH]) % 360;
v->setAngles(v->angles);
}
CheckWater();
WorldEffects();
last_origin = origin;
if (!driver.ent && !velocity.length() && groundentity && !(watertype & CONTENTS_LAVA)) {
// make the vehicle stationary if it's completely immobile
flags &= ~FL_POSTTHINK;
if (drivable) {
setMoveType(MOVETYPE_STATIONARY);
}
}
}
+653 -42
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2018 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -22,69 +22,680 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "vehicle.h"
#include "player.h"
#include "debuglines.h"
#include "g_phys.h"
CLASS_DECLARATION(DrivableVehicle, VehicleWheelsX4, "VehicleWheelsX4")
{
{ &EV_Damage, &VehicleWheelsX4::EventDamage },
{ &EV_Killed, &VehicleWheelsX4::Killed },
{ NULL, NULL }
CLASS_DECLARATION(DrivableVehicle, VehicleWheelsX4, "VehicleWheelsX4") {
{&EV_Damage, &VehicleWheelsX4::EventDamage},
{&EV_Killed, &VehicleWheelsX4::Killed },
{NULL, NULL }
};
VehicleWheelsX4::VehicleWheelsX4()
{
m_iGear = 1;
m_iRPM = 0;
gravity = 1.0;
m_fDifferentialRatio = 4.8800001f;
m_fGearEfficiency = 0.69999999f;
m_fGearRatio[0] = -2.9400001f;
m_fGearRatio[1] = 2.9400001f;
m_fGearRatio[2] = 1.9400001f;
m_fGearRatio[3] = 1.0f;
m_fAccelerator = 0.0f;
m_bBackSlipping = qfalse;
m_bAutomatic = qtrue;
m_bFrontSlipping = qfalse;
gravity = 1.0;
m_fDifferentialRatio = 4.88f;
m_fGearEfficiency = 0.7f;
m_fGearRatio[0] = -2.95f;
m_fGearRatio[1] = 2.95f;
m_fGearRatio[2] = 1.95f;
m_fGearRatio[3] = 1.0f;
m_iGear = 1;
m_iRPM = 0;
m_fAccelerator = 0.0f;
m_bAutomatic = qtrue;
m_bBackSlipping = qfalse;
m_bFrontSlipping = qfalse;
}
void VehicleWheelsX4::UpdateVariables(Vector *acceleration, Vector *vpn, Vector *vup, Vector *vright, Vector *t_vpn, Vector *t_vup, Vector *t_vright)
void VehicleWheelsX4::UpdateVariables(
Vector *acceleration, Vector *vpn, Vector *vup, Vector *vright, Vector *t_vpn, Vector *t_vup, Vector *t_vright
)
{
// FIXME: STUB
int i;
Vector vNewCG;
Vector vBoxSize;
float longspeed;
Vector _i, _j, _k;
Vector r_i, r_j, r_k;
Vector r_velocity;
float dots[4];
r_velocity = velocity;
m_bIsSkidding = false;
vBoxSize = maxs - mins;
SetControllerAngles(0, Vector(0, turnangle, 0));
SetControllerAngles(1, Vector(0, turnangle, 0));
vNewCG = localorigin;
if (vNewCG != m_vCG) {
m_vCG = vNewCG;
vNewCG -= localorigin;
m_fWheelBase = vBoxSize.x;
m_fWheelFrontDist = vBoxSize.x * 0.5 - vNewCG.x;
m_fWheelBackDist = vBoxSize.x * -0.5 + vNewCG.x;
m_fTrackWidth = vBoxSize.y;
}
Vector vNewVpn = angles;
vNewVpn.AngleVectorsLeft(&r_i, &r_j, &r_k);
vNewVpn.y += turnangle;
vNewVpn.AngleVectorsLeft(&_i, &_j, &_k);
dots[3] = r_velocity * *vpn * 0.02;
dots[2] = r_velocity * *vright * 0.02;
dots[1] = r_velocity * *t_vpn * 0.02;
dots[0] = r_velocity * *t_vright * 0.02;
m_sWheels[0].fTraction = 0.8f;
m_sWheels[1].fTraction = 0.9f;
m_sWheels[2].fTraction = 0.8f;
m_sWheels[3].fTraction = 0.9f;
m_sWheels[0].fYawOffset = 0;
m_sWheels[1].fYawOffset = DEG2RAD(turnangle);
m_sWheels[2].fYawOffset = 0;
m_sWheels[3].fYawOffset = DEG2RAD(turnangle);
m_sWheels[0].fLongDist = m_fWheelBackDist * 0.02;
m_sWheels[1].fLongDist = m_fWheelFrontDist * 0.02;
m_sWheels[2].fLongDist = m_fWheelBackDist * 0.02;
m_sWheels[3].fLongDist = m_fWheelFrontDist * 0.02;
m_sWheels[0].fLatDist = m_fTrackWidth * 0.5 * -0.02;
m_sWheels[1].fLatDist = m_fTrackWidth * 0.5 * 0.02;
m_sWheels[2].fLatDist = m_fTrackWidth * 0.5 * -0.02;
m_sWheels[3].fLatDist = m_fTrackWidth * 0.5 * 0.02;
// initialize the wheels
for (i = 0; i < 4; i++) {
m_sWheels[i].fLongForce = 0;
m_sWheels[i].fForce = 0;
m_sWheels[i].vLongForce = vec_zero;
m_sWheels[i].vLatForce = vec_zero;
m_sWheels[i].vForce = vec_zero;
m_sWheels[i].vVelocity = vec_zero;
m_sWheels[i].bSkidding = false;
m_sWheels[i].bSpinning = false;
m_sWheels[i].fTorque = 0;
m_sWheels[i].fLatTorque = 0;
m_sWheels[i].fLongTorque = 0;
}
for (i = 0; i < 4; i++) {
Vector p1, p3, p4;
Vector vTp, vTr, vTu;
vec3_t p2;
p3 = Corners[i];
p3.normalize();
vectoangles(p3, p2);
p1 = vec_zero;
p1[1] = angles[1] + p2[1] + 90;
p1.AngleVectorsLeft(&vTp, &vTr, &vTu);
m_sWheels[i].vVelocity = vTp * RAD2DEG(m_vAngularVelocity.y) * fabs(m_sWheels[i].fLongDist) * level.frametime;
G_LineWidth(5.0);
G_DebugLine(
origin + Corners[i][0] * r_i + Corners[i][1] * r_j,
origin + Corners[i][0] * r_i + Corners[i][1] * r_j + m_sWheels[i].vVelocity * 50,
0.7f,
0.5f,
1.0f,
1.0f
);
p1 = vec_zero;
p1[1] = angles[1] + RAD2DEG(m_sWheels[i].fYawOffset);
p1.AngleVectorsLeft(&vTp, &vTr, &vTu);
m_sWheels[i].vOrientation = vTp;
G_LineWidth(5.0);
G_DebugLine(
origin + Corners[i][0] * r_i + Corners[i][1] * r_j,
origin + Corners[i][0] * r_i + Corners[i][1] * r_j + m_sWheels[i].vOrientation * 50,
0.7f,
0.0f,
1.0f,
1.0f
);
}
Vector start, end;
Vector boxoffset;
Vector t_mins(-8, -8, -8);
Vector t_maxs(8, 8, 8);
trace_t trace;
start = origin + *vpn * (m_vCG[0] - localorigin[0]) + *vright * (m_vCG[1] - localorigin[1])
+ *vup * (m_vCG[2] - localorigin[2]);
end = start;
end[2] -= maxtracedist;
trace = G_Trace(start, t_mins, t_maxs, end, this, MASK_SOLID, qfalse, "Vehicle::PostThink Corners");
m_fInertia = m_fMass * 100;
m_fWheelFrontLoad = m_fMass * 9.81 * fabs(m_fWheelFrontDist / m_fWheelBase);
m_fWheelBackLoad = m_fMass * 9.81 * fabs(m_fWheelBackDist / m_fWheelBase);
longspeed = m_vAcceleration.length() * 0.02 * m_fMass / m_fWheelBase;
m_fWheelFrontLoad -= longspeed;
m_fWheelBackLoad += longspeed;
m_sWheels[0].fLoad = m_fWheelBackLoad / 2.0;
m_sWheels[1].fLoad = m_fWheelBackLoad / 2.0;
m_sWheels[2].fLoad = m_fWheelFrontLoad / 2.0;
m_sWheels[3].fLoad = m_fWheelFrontLoad / 2.0;
float fMassShifted = m_fTireRadius * M_PI;
m_fTireRotationalSpeed = dots[3] / (fMassShifted + fMassShifted);
m_iRPM = m_fTireRotationalSpeed * m_fGearRatio[m_iGear] * m_fDifferentialRatio * 10;
m_fMaxTraction =
TorqueLookup(m_iRPM) * m_fGearRatio[m_iGear] * m_fDifferentialRatio * m_fGearEfficiency / m_fTireRadius;
m_fTractionForce = m_fAccelerator * m_fMaxTraction;
if (m_bIsBraking && dots[3] > 0) {
m_fTractionForce = -fSign(dots[3]) * 1000 * dots[3];
}
for (i = 0; i < 4; i++) {
float maxgrip;
maxgrip = m_sWheels[i].fTraction * m_sWheels[i].fLoad * 9.81;
if (m_fTractionForce > maxgrip) {
m_fTractionForce = maxgrip * 0.6;
m_sWheels[i].bSpinning = true;
m_sWheels[i].bSkidding = true;
Com_Printf("Skidding!\n");
}
if (m_fTractionForce < -maxgrip) {
m_fTractionForce = -maxgrip * 0.6;
m_sWheels[i].bSkidding = true;
Com_Printf("Skidding!\n");
}
m_sWheels[i].fLongForce = this->m_sWheels[i].fLongForce + m_fTractionForce;
m_sWheels[i].vLongForce += m_sWheels[i].vOrientation * m_sWheels[i].fLongForce;
}
m_vResistance[0] =
-(velocity[0] * 0.02 * m_fRollingResistance + velocity[0] * 0.02 * m_fDrag * fabs(velocity[0] * 0.02));
m_vResistance[1] =
-(velocity[1] * 0.02 * m_fRollingResistance + velocity[1] * 0.02 * m_fDrag * fabs(velocity[1] * 0.02));
m_vResistance[2] =
-(velocity[2] * 0.02 * m_fRollingResistance + velocity[2] * 0.02 * m_fDrag * fabs(velocity[2] * 0.02));
m_fBrakingPerformance = -m_fRollingResistance - *vpn * Vector(0, 0, -1) * m_fMass;
if (dots[3] == 0) {
m_fBrakingPerformance = 0;
} else {
m_fBrakingPerformance = (dots[3] - (m_fTireRotationalSpeed * m_fTireRadius - m_fBrakingPerformance)) / dots[3];
m_fBrakingPerformance = (1.0 - m_fBrakingPerformance) * -(-m_fFrontBrakingForce - m_fBackBrakingForce);
}
if (r_velocity.length() * 0.02 > 0.01) {
m_fTangForce = 0;
m_vTangForce = vec_zero;
for (i = 0; i < 2; i++) {
Vector va, vr;
Vector vVel;
Vector v1, v2;
va = angles;
va.x = 0;
va.y += RAD2DEG(m_sWheels[i].fYawOffset);
va.z = 0;
va.AngleVectorsLeft(NULL, &vr, NULL);
vVel = m_sWheels[i].vVelocity + velocity;
// get the direction
v1 = vVel;
v1.normalize();
// get the angles
vectoangles(v1, v2);
m_sWheels[i].fSlipAngle = DEG2RAD(angledist(va.y - v2.y));
m_sWheels[i].fGripCoef = m_sWheels[i].fSlipAngle * 0.15;
m_sWheels[i].fGripCoef = Q_clamp_float(m_sWheels[i].fGripCoef, -1.2f, 1.2f);
m_sWheels[i].fLatForce += m_sWheels[i].fGripCoef * m_sWheels[i].fLoad * 9.81;
if (m_sWheels[i].fLoad * 2 * m_sWheels[i].fTraction < fabs(m_sWheels[i].fLatForce)) {
m_sWheels[i].fLatForce = m_sWheels[i].fLatForce / 9.81;
m_sWheels[i].bSkidding = true;
Com_Printf("Skidding %i!\n", i);
}
m_sWheels[i].vLatForce += vr * m_sWheels[i].fLatForce;
G_LineWidth(3.0);
G_DebugLine(
origin + Corners[i][0] * r_i + Corners[i][1] * r_j,
origin + Corners[i][0] * r_i + Corners[i][1] * r_j + m_sWheels[i].vLatForce * 50 * (1.0 / m_fMass),
0.7f,
0.5f,
0.2f,
1.0f
);
}
} else {
m_fTangForce = 0;
m_vTangForce = vec_zero;
}
m_vForce = vec_zero;
for (i = 0; i < 4; i++) {
m_sWheels[i].vForce = m_sWheels[i].vLatForce + m_sWheels[i].vLongForce;
m_vForce += m_sWheels[i].vForce;
}
m_vForce += m_vResistance;
G_LineWidth(5.0);
G_DebugLine(origin, origin + m_vTangForce * (1.0 / m_fMass) * 50, 1.0, 0.0, 1.0, 1.0);
m_vAcceleration = m_vForce * (1.0 / m_fMass) * 50;
m_fTorque = 0;
for (i = 0; i < 4; i++) {
m_sWheels[i].fTorque += m_sWheels[i].fLongTorque + m_sWheels[i].fLatTorque;
m_fTorque += m_sWheels[i].fTorque;
}
m_vAngularAcceleration[1] = angledist(RAD2DEG(m_fTorque));
m_vAngularVelocity += m_vAngularAcceleration * level.frametime;
m_vAngularVelocity *= 0.825f;
avelocity = m_vAngularVelocity;
if (m_bAutomatic) {
//
// set the gear
//
if (m_iRPM >= 2100 && m_iGear <= 2) {
m_iGear++;
}
if (m_iRPM <= 600 && m_iGear > 1) {
m_iGear--;
}
}
prev_moveimpulse = moveimpulse;
}
void VehicleWheelsX4::Killed(Event *ev)
{
deadflag = DEAD_DEAD;
}
float VehicleWheelsX4::TorqueLookup(int rpm)
{
if (rpm <= 2099)
return 20.0;
if (rpm > 3599)
return 0.0;
return (20 * (3600 - rpm)) * 0.001;
if (rpm <= 2099) {
return 20.0;
}
if (rpm > 3599) {
return 0.0;
}
return (20 * (3600 - rpm)) * 0.001;
}
void VehicleWheelsX4::Think()
{
vmove_t vm;
flags |= FL_POSTTHINK;
prev_velocity = velocity;
vmove_t vm;
flags |= FL_POSTTHINK;
angles -= m_vAnglesOffset;
origin -= m_vOriginOffset;
prev_velocity = velocity;
mins = m_vOldMins;
maxs = m_vOldMaxs;
angles -= m_vAnglesOffset;
origin -= m_vOriginOffset;
SetMoveInfo(&vm);
VmoveSingle(&vm);
GetMoveInfo(&vm);
mins = m_vOldMins;
maxs = m_vOldMaxs;
SetMoveInfo(&vm);
VmoveSingle(&vm);
GetMoveInfo(&vm);
}
void VehicleWheelsX4::Postthink()
{
// FIXME: STUB
}
float turn;
Vector i, j, k;
int index;
trace_t trace;
Vector normalsum;
Vector normalsum_Front;
int numnormals_Front;
Vector normalsum_Back;
int numnormals_Back;
Vector temp;
Vector pitch, roll;
Vector acceleration;
Vector atmp, atmp2, aup;
VehicleBase *v;
VehicleBase *last;
float drivespeed;
Vector primal_angles;
Vector vTmp;
Vector n_angles;
void VehicleWheelsX4::Killed(Event* ev)
{
deadflag = DEAD_DEAD;
primal_angles = angles;
if (drivable) {
if (m_bAutoPilot) {
AutoPilot();
} else {
moveimpulse *= 0.825f;
turnimpulse *= 0.825f;
}
currentspeed = moveimpulse;
turnangle = turnangle * 0.25f + turnimpulse;
turnangle = Q_clamp_float(turnangle, -maxturnrate, maxturnrate);
if (turnangle > maxturnrate) {
turnangle = maxturnrate;
} else if (turnangle < -maxturnrate) {
turnangle = -maxturnrate;
} else if (fabs(turnangle) < 2) {
turnangle = 0;
}
real_velocity = origin - prev_origin;
prev_origin = origin;
prev_acceleration = real_acceleration;
real_acceleration = real_velocity - prev_velocity;
prev_velocity = real_velocity;
acceleration = real_acceleration - prev_acceleration;
angles[0] = 0;
angles[2] = 0;
temp[0] = angles[0];
temp[1] = angles[1];
temp[2] = angles[2];
temp.AngleVectorsLeft(&i, &j, &k);
j = vec_zero - j;
index = 0;
numnormals_Front = 0;
numnormals_Back = 0;
for (index = 0; index < 4; index++) {
Vector start, end;
Vector boxoffset;
Vector t_mins(-8, -8, -8);
Vector t_maxs(8, 8, 8);
boxoffset = Corners[index];
start = origin + i * boxoffset[0] + j * boxoffset[1] + k * boxoffset[2];
end = start;
end[2] -= maxtracedist;
trace = G_Trace(start, mins, maxs, end, this, MASK_SOLID, qfalse, "Vehicle::PostThink Corners");
if (trace.fraction != 1 && !trace.startsolid) {
if (index > 2) {
normalsum_Front += trace.plane.normal;
numnormals_Front++;
} else {
normalsum_Back += trace.plane.normal;
numnormals_Back++;
}
normalsum += trace.plane.normal;
}
}
if (angles[2] < 60 || angles[2] > 300) {
if (numnormals_Front > 1) {
m_vFrontNormal = normalsum_Front * (1.0 / numnormals_Front);
temp = m_vFrontNormal;
m_vFrontAngles[0] = -temp.CrossProduct(temp, j).toPitch();
// no yaw
m_vFrontAngles[1] = 0;
temp = m_vFrontNormal;
m_vFrontAngles[2] = temp.CrossProduct(temp, i).toPitch();
}
if (numnormals_Back > 1) {
m_vBackNormal = normalsum_Back * (1.0 / numnormals_Back);
temp = m_vBackNormal;
m_vBackAngles[0] = -temp.CrossProduct(temp, j).toPitch();
// no yaw
m_vBackAngles[1] = 0;
temp = m_vBackNormal;
m_vBackAngles[2] = temp.CrossProduct(temp, i).toPitch();
}
if (numnormals_Front + numnormals_Back > 1) {
m_vBaseNormal = (normalsum_Front + normalsum_Back) * (1.0 / numnormals_Front + numnormals_Back);
temp = m_vBaseNormal;
m_vBaseAngles[0] = -temp.CrossProduct(temp, j).toPitch();
// no yaw
m_vBaseAngles[1] = 0;
temp = m_vBaseNormal;
m_vBaseAngles[2] = temp.CrossProduct(temp, i).toPitch();
}
}
n_angles = m_vBaseAngles - angles;
n_angles[0] = angledist(n_angles[0]);
n_angles[1] = angledist(n_angles[1]);
n_angles[2] = angledist(n_angles[2]);
angles[0] += n_angles[0] * 4.5 * level.frametime;
angles[2] += n_angles[2] * 4.5 * level.frametime;
m_vPrevNormal = m_vBaseNormal;
if (currentspeed < 0 && velocity * i > 0) {
m_fFrontBrakingForce = 0.2f;
m_fBackBrakingForce = 0.1f;
} else {
m_fFrontBrakingForce = 0;
m_fBackBrakingForce = 0;
}
turn = turnangle * 0.005;
Vector _i, _j, _k;
Vector vNewVpn = angles;
vNewVpn.y += turnangle;
vNewVpn.AngleVectorsLeft(&_i, &_j, &_k);
UpdateVariables(&acceleration, &i, &j, &k, &_i, &_j, &_k);
m_vAngles = angles;
if (currentspeed < 0 && velocity * i > 0) {
currentspeed = 0;
}
normalsum = vec_zero;
for (index = 0; index < 4; index++) {
Vector start, end;
Vector boxoffset;
Vector t_mins(-8, -8, -8);
Vector t_maxs(8, 8, 8);
boxoffset = Corners[index];
start = origin + i * boxoffset[0] + j * boxoffset[1] + k * boxoffset[2] + Vector(0, 0, 10);
end = start;
end[2] -= maxtracedist;
trace = G_Trace(start, mins, maxs, end, this, MASK_SOLID, qfalse, "Vehicle::PostThink Corners");
if (trace.fraction != 1.0) {
float fCoef;
if (index > 2) {
fCoef = m_fWheelFrontLoad / (m_fWheelFrontDist / m_fWheelBase * m_fMass);
fCoef = Q_clamp_float(fCoef, 0, 1);
normalsum += _i * currentspeed * fCoef;
normalsum += i * currentspeed * (1.0 - fCoef);
} else {
fCoef = m_fWheelBackLoad / (m_fWheelBackDist / m_fWheelBase * m_fMass);
fCoef = Q_clamp_float(fCoef, 0, 1);
normalsum += i * currentspeed * fCoef;
normalsum += _i * currentspeed * (1.0 - fCoef);
}
}
}
AnglesToAxis(angles, orientation);
vmove_t vm;
SetMoveInfo(&vm);
m_sMoveGrid->SetMoveInfo(&vm);
m_sMoveGrid->SetOrientation(orientation);
if (m_sMoveGrid->CheckStuck()) {
angles = primal_angles;
AnglesToAxis(angles, orientation);
}
m_fForwardForce = acceleration * i * 0.1;
m_fBackForce += -m_vAnglesOffset[0] * m_fBouncyCoef;
m_fBackForce *= m_fSpringyCoef;
m_vAnglesOffset[0] += m_fForwardForce + m_fBackForce * 12.0 * level.frametime;
m_vAnglesOffset[0] = Q_clamp_float(m_vAnglesOffset[0], m_fYawMin, m_fYawMax);
m_fLeftForce += acceleration * j * 0.1;
m_fRightForce += -m_vAnglesOffset[2] * m_fBouncyCoef;
m_fRightForce *= m_fSpringyCoef;
m_vAnglesOffset[2] += (m_fLeftForce + m_fRightForce) * 12.0 * level.frametime;
m_vAnglesOffset[2] = Q_clamp_float(m_vAnglesOffset[2], m_fRollMin, m_fRollMax);
m_fDownForce = acceleration[2];
m_fUpForce += -m_vOriginOffset[2] * m_fBouncyCoef;
m_fUpForce *= m_fSpringyCoef;
m_vAnglesOffset[2] += (m_fDownForce + m_fUpForce) * 12.0 * level.frametime;
m_vAnglesOffset[2] = Q_clamp_float(m_vAnglesOffset[2], m_fZMin, m_fZMax);
if (groundentity && (angles[2] < 60 || angles[2] > 300)) {
velocity += m_vAcceleration * level.frametime;
} else {
if (angles[2] > 60) {
angles[2]; // FIXME: ??
}
velocity += m_vAcceleration * level.frametime;
}
angles += avelocity * level.frametime;
setAngles(angles);
prev_origin = origin;
}
drivespeed = acceleration * orientation[0];
if (drivable && driver.ent) {
str sound_name;
if (currentspeed > 0) {
sound_name = "snd_forward";
} else if (currentspeed == 0) {
sound_name = "snd_idle";
} else {
sound_name = "snd_backward";
}
LoopSound(sound_name);
}
i = orientation[0];
j = orientation[1];
k = orientation[2];
last_origin = origin;
vTmp = (angles - primal_angles) * level.frametime;
if (vTmp.x > 180 || vTmp.x < -180) {
vTmp.x = 0;
}
if (vTmp.y > 180 || vTmp.y < -180) {
vTmp.y = 0;
}
if (vTmp.z > 180 || vTmp.z < -180) {
vTmp.z = 0;
}
if (vTmp.x > -1 || vTmp.x < 1) {
vTmp.x = 0;
}
if (vTmp.y > -1 || vTmp.y < 1) {
vTmp.y = 0;
}
if (vTmp.z > -1 || vTmp.z < 1) {
vTmp.z = 0;
}
avelocity = vTmp;
origin += m_vOriginOffset;
setOrigin(origin);
angles += m_vAnglesOffset;
setAngles(angles);
if (driver.ent) {
driver.ent->setOrigin(origin + i * driveroffset[0] + j * driveroffset[1] + k * driveroffset[2]);
if (drivable) {
// clear the driver velocity
driver.ent->velocity = vec_zero;
// set the driver angles to the vehicle's angle
driver.ent->setAngles(angles);
}
}
for (last = this; last->vlink; last = v) {
v = last->vlink;
v->setOrigin(origin + i * v->offset.x + j * v->offset.y + k * v->offset.z);
v->avelocity = avelocity;
v->velocity = velocity;
v->angles[ROLL] = angles[ROLL];
v->angles[YAW] = angles[YAW];
v->angles[PITCH] = (int)(drivespeed / 4.f + v->angles[PITCH]) % 360;
v->setAngles(v->angles);
}
CheckWater();
WorldEffects();
if (!driver.ent && !velocity.length() && groundentity && !(watertype & CONTENTS_LAVA)) {
// make the vehicle stationary if it's completely immobile
flags &= ~FL_POSTTHINK;
if (drivable) {
setMoveType(MOVETYPE_STATIONARY);
}
}
}
+10937 -13867
View File
File diff suppressed because it is too large. Load diff
+1920 -1346
View File
File diff suppressed because it is too large. Load diff
+35 -45
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -24,52 +24,42 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitAim
(
GlobalFuncs_t *func
)
void Actor::InitAim(GlobalFuncs_t *func)
{
func->BeginState = &Actor::Begin_Aim;
func->ThinkState = &Actor::Think_Aim;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle;
func->ShowInfo = &Actor::ShowInfo_Aim;
func->IsState = &Actor::IsIdleState;
}
void Actor::Begin_Aim
(
void
)
{
m_csMood = STRING_ALERT;
m_csIdleMood = STRING_NERVOUS;
ClearPath();
}
void Actor::Think_Aim
(
void
)
{
if( !RequireThink() )
return;
UpdateEyeOrigin();
NoPoint();
m_pszDebugState = "";
Anim_Aim();
if( m_aimNode )
{
AimAtAimNode();
}
CheckForThinkStateTransition();
PostThink( true );
func->BeginState = &Actor::Begin_Aim;
func->ThinkState = &Actor::Think_Aim;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle;
func->ShowInfo = &Actor::ShowInfo_Aim;
func->IsState = &Actor::IsIdleState;
}
void Actor::ShowInfo_Aim
(
void
)
void Actor::Begin_Aim(void)
{
ShowInfo_AimNode();
m_csMood = STRING_ALERT;
m_csIdleMood = STRING_NERVOUS;
ClearPath();
}
void Actor::Think_Aim(void)
{
if (!RequireThink()) {
return;
}
UpdateEyeOrigin();
NoPoint();
m_pszDebugState = "";
Anim_Aim();
if (m_aimNode) {
AimAtAimNode();
}
CheckForThinkStateTransition();
PostThink(true);
}
void Actor::ShowInfo_Aim(void)
{
ShowInfo_AimNode();
}
+73 -110
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -24,143 +24,106 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitAlarm
(
GlobalFuncs_t *func
)
void Actor::InitAlarm(GlobalFuncs_t *func)
{
func->BeginState = &Actor::Begin_Alarm;
func->EndState = &Actor::End_Alarm;
func->ThinkState = &Actor::Think_Alarm;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack;
func->IsState = &Actor::IsAttackState;
func->BeginState = &Actor::Begin_Alarm;
func->EndState = &Actor::End_Alarm;
func->ThinkState = &Actor::Think_Alarm;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack;
func->IsState = &Actor::IsAttackState;
}
void Actor::Begin_Alarm
(
void
)
void Actor::Begin_Alarm(void)
{
DoForceActivate();
DoForceActivate();
m_csMood = STRING_ALERT;
m_csIdleMood = STRING_NERVOUS;
m_csMood = STRING_ALERT;
m_csIdleMood = STRING_NERVOUS;
if( m_AlarmNode )
{
SetPath( m_AlarmNode, "Actor::Begin_Alarm", 0 );
if (!m_AlarmNode) {
State_Alarm_StartThread();
return;
}
if( PathExists() )
{
TransitionState(601, 0);
}
else
{
TransitionState(600, 0);
parm.movefail = true;
}
}
else
{
SetLeashHome( origin );
TransitionState(600, 0);
m_AlarmThread.Execute( this );
}
SetPath(m_AlarmNode, "Actor::Begin_Alarm", 0);
if (PathExists()) {
TransitionState(ACTOR_STATE_ALARM_MOVE, 0);
} else {
TransitionState(ACTOR_STATE_ALARM_IDLE, 0);
parm.movefail = true;
}
}
void Actor::End_Alarm
(
void
)
void Actor::End_Alarm(void)
{
parm.movefail = true;
parm.movefail = true;
}
void Actor::State_Alarm_StartThread
(
void
)
void Actor::State_Alarm_StartThread(void)
{
if( m_AlarmNode )
SetLeashHome( m_AlarmNode->origin );
else
SetLeashHome( origin );
SetLeashHome(m_AlarmNode ? m_AlarmNode->origin : origin);
// Added in 2.30.
// Execute the pre-alarm thread
m_PreAlarmThread.Execute(this);
TransitionState(600, 0);
m_AlarmThread.Execute();
TransitionState(ACTOR_STATE_ALARM_IDLE, 0);
m_AlarmThread.Execute(this);
}
void Actor::State_Alarm_Move
(
void
)
void Actor::State_Alarm_Move(void)
{
if( PathExists() )
{
if( PathComplete() )
{
Anim_Aim();
AimAtTargetPos();
}
else
{
Anim_RunToAlarm( 2 );
FaceMotion();
}
}
else
{
TransitionState(600, 0);
parm.movefail = true;
if (!PathExists()) {
TransitionState(ACTOR_STATE_ALARM_IDLE, 0);
parm.movefail = true;
Anim_Aim();
AimAtTargetPos();
}
Anim_Aim();
AimAtTargetPos();
} else if (PathComplete()) {
Anim_Aim();
AimAtTargetPos();
State_Alarm_StartThread();
} else {
Anim_RunToAlarm(ANIM_MODE_PATH);
FaceMotion();
}
}
void Actor::State_Alarm_Idle
(
void
)
void Actor::State_Alarm_Idle(void)
{
AimAtTargetPos();
SetThink(THINKSTATE_ATTACK, THINK_TURRET);
Anim_Aim();
AimAtTargetPos();
SetThink(THINKSTATE_ATTACK, THINK_TURRET);
}
void Actor::Think_Alarm
(
void
)
void Actor::Think_Alarm(void)
{
if( !RequireThink() )
return;
if (!RequireThink()) {
return;
}
parm.movefail = false;
parm.movefail = false;
UpdateEyeOrigin();
NoPoint();
UpdateEyeOrigin();
NoPoint();
if( m_State == 600 )
{
m_pszDebugState = "idle";
State_Alarm_Idle();
}
else if( m_State == 601 )
{
m_pszDebugState = "move";
State_Alarm_Move();
}
else
{
Com_Printf( "Actor::Think_Alarm: invalid think state %i\n", m_State );
}
switch (m_State) {
case ACTOR_STATE_ALARM_IDLE:
m_pszDebugState = "idle";
State_Alarm_Idle();
break;
case ACTOR_STATE_ALARM_MOVE:
m_pszDebugState = "move";
State_Alarm_Move();
break;
default:
Com_Printf("Actor::Think_Alarm: invalid think state %i\n", m_State);
break;
}
}
void Actor::FinishedAnimation_Alarm
(
void
)
void Actor::FinishedAnimation_Alarm(void)
{
// not needed
return;
// not needed
return;
}
+48 -63
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -24,81 +24,66 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitAnim
(
GlobalFuncs_t *func
)
void Actor::InitAnim(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_Anim;
func->BeginState = &Actor::Begin_Anim;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle;
func->FinishedAnimation = &Actor::FinishedAnimation_Anim;
func->ShowInfo = &Actor::ShowInfo_Anim;
func->IsState = &Actor::IsIdleState;
func->ThinkState = &Actor::Think_Anim;
func->BeginState = &Actor::Begin_Anim;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle;
func->FinishedAnimation = &Actor::FinishedAnimation_Anim;
func->ShowInfo = &Actor::ShowInfo_Anim;
func->IsState = &Actor::IsIdleState;
}
void Actor::Begin_Anim
(
void
)
void Actor::Begin_Anim(void)
{
m_csMood = m_csIdleMood;
ClearPath();
StopTurning();
TransitionState(1000, 0);
m_csMood = m_csIdleMood;
ClearPath();
StopTurning();
TransitionState(ACTOR_STATE_ANIMATION_INITIAL, 0);
}
void Actor::Think_Anim
(
void
)
void Actor::Think_Anim(void)
{
if (RequireThink())
{
UpdateEyeOrigin();
IdlePoint();
IdleLook();
if (m_State == 1000)
{
m_bNextForceStart = true;
if (!RequireThink()) {
return;
}
m_bAnimScriptSet = false;
m_pszDebugState = "initial";
TransitionState(1001, 0);
}
else if (m_State == 1001)
{
m_bNextForceStart = false;
m_pszDebugState = "main";
}
m_eNextAnimMode = m_AnimMode;
m_csNextAnimString = m_csAnimScript;
UpdateEyeOrigin();
IdlePoint();
IdleLook();
CheckForThinkStateTransition();
IdleTurn();
PostThink(false);
}
if (m_State == ACTOR_STATE_ANIMATION_INITIAL) {
m_pszDebugState = "initial";
m_bAnimScriptSet = false;
StartAnimation(m_AnimMode, m_csAnimScript);
TransitionState(ACTOR_STATE_ANIMATION_MAIN, 0);
} else if (m_State == ACTOR_STATE_ANIMATION_MAIN) {
m_bNextForceStart = false;
m_pszDebugState = "main";
DesiredAnimation(m_AnimMode, m_csAnimScript);
}
CheckForThinkStateTransition();
IdleTurn();
PostThink(false);
}
void Actor::FinishedAnimation_Anim
(
void
)
void Actor::FinishedAnimation_Anim(void)
{
if (!m_bAnimScriptSet)
{
if (m_bNoIdleAfterAnim)
m_csAnimScript = STRING_ANIM_CONTINUE_LAST_ANIM_SCR;
else
SetThinkIdle(THINK_IDLE);
Unregister(STRING_ANIMDONE);
}
if (m_bAnimScriptSet) {
return;
}
if (m_bNoIdleAfterAnim) {
m_csAnimScript = STRING_ANIM_CONTINUE_LAST_ANIM_SCR;
} else {
SetThinkIdle(THINK_IDLE);
}
Unregister(STRING_ANIMDONE);
}
void Actor::ShowInfo_Anim
(
void
)
void Actor::ShowInfo_Anim(void)
{
Com_Printf("anim script: %s, anim mode %d\n", Director.GetString(m_csAnimScript).c_str(), m_AnimMode);
Com_Printf("anim script: %s, anim mode %d\n", Director.GetString(m_csAnimScript).c_str(), m_AnimMode);
}
+103 -191
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -23,289 +23,201 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// actor_animapi.cpp: Base actor animation script
#include "actor.h"
#include "scriptthread.h"
const_str SimpleActor::GetRunAnim
(
void
)
const_str SimpleActor::GetRunAnim(void)
{
if( m_csCurrentPosition != STRING_PRONE && ( m_csCurrentPosition < STRING_PRONE || m_csCurrentPosition > STRING_CROUCHRUN ) )
return STRING_ANIM_RUN_SCR;
else
return STRING_ANIM_CROUCH_RUN_SCR;
if (m_csCurrentPosition == STRING_PRONE) {
return STRING_ANIM_CROUCH_RUN_SCR;
}
if (m_csCurrentPosition >= STRING_PRONE && m_csCurrentPosition <= STRING_CROUCHRUN && m_csCurrentPosition >= STRING_CROUCH) {
return STRING_ANIM_CROUCH_RUN_SCR;
} else {
return STRING_ANIM_RUN_SCR;
}
}
const_str SimpleActor::GetWalkAnim
(
void
)
const_str SimpleActor::GetWalkAnim(void)
{
if( m_csCurrentPosition != STRING_PRONE && ( m_csCurrentPosition < STRING_PRONE || m_csCurrentPosition > STRING_CROUCHRUN ) )
return STRING_ANIM_WALK_SCR;
else
return STRING_ANIM_CROUCH_WALK_SCR;
if (m_csCurrentPosition == STRING_PRONE) {
return STRING_ANIM_CROUCH_WALK_SCR;
}
if (m_csCurrentPosition >= STRING_PRONE && m_csCurrentPosition <= STRING_CROUCHRUN && m_csCurrentPosition >= STRING_CROUCH) {
return STRING_ANIM_CROUCH_WALK_SCR;
} else {
return STRING_ANIM_WALK_SCR;
}
}
void SimpleActor::Anim_Attack
(
void
)
void SimpleActor::Anim_Attack(void)
{
DesiredAnimation(1, m_AttackHandler);
DesiredAnimation(ANIM_MODE_NORMAL, m_AttackHandler);
}
void SimpleActor::Anim_Sniper
(
void
)
void SimpleActor::Anim_Suppress(void)
{
DesiredAnimation(1, m_SniperHandler);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_SUPPRESS_SCR);
}
void SimpleActor::Anim_Aim
(
void
)
void SimpleActor::Anim_Sniper(void)
{
DesiredAnimation(1, STRING_ANIM_AIM_SCR);
DesiredAnimation(ANIM_MODE_NORMAL, m_SniperHandler);
}
void SimpleActor::Anim_Shoot
(
void
)
void SimpleActor::Anim_Aim(void)
{
DesiredAnimation(1, STRING_ANIM_SHOOT_SCR);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_AIM_SCR);
}
void SimpleActor::Anim_Idle
(
void
)
void SimpleActor::Anim_Shoot(void)
{
DesiredAnimation(1, STRING_ANIM_IDLE_SCR);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_SHOOT_SCR);
}
void SimpleActor::Anim_Crouch
(
void
)
void SimpleActor::Anim_Idle(void)
{
DesiredAnimation(1, STRING_ANIM_CROUCH_SCR);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_IDLE_SCR);
}
void SimpleActor::Anim_Prone
(
void
)
void SimpleActor::Anim_Crouch(void)
{
DesiredAnimation(1, STRING_ANIM_PRONE_SCR);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_CROUCH_SCR);
}
void SimpleActor::Anim_Stand
(
void
)
void SimpleActor::Anim_Prone(void)
{
DesiredAnimation(1, STRING_ANIM_STAND_SCR);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_PRONE_SCR);
}
void SimpleActor::Anim_Cower
(
void
)
void SimpleActor::Anim_Stand(void)
{
DesiredAnimation(1, STRING_ANIM_COWER_SCR);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_STAND_SCR);
}
void SimpleActor::Anim_Killed
(
void
)
void SimpleActor::Anim_Cower(void)
{
Com_Printf("m_eAnimMode Anim_Killed \n");
DesiredAnimation(1, m_DeathHandler);
DesiredAnimation(ANIM_MODE_NORMAL, STRING_ANIM_COWER_SCR);
}
void SimpleActor::Anim_StartPain
(
void
)
void SimpleActor::Anim_Killed(void)
{
Com_Printf("m_eAnimMode Anim_StartPain \n");
StartAnimation(1, m_PainHandler);
DesiredAnimation(ANIM_MODE_NORMAL, m_DeathHandler);
}
void SimpleActor::Anim_Pain
(
void
)
void SimpleActor::Anim_StartPain(void)
{
ContinueAnimation();
StartAnimation(ANIM_MODE_NORMAL, m_PainHandler);
}
void SimpleActor::Anim_CrouchRunTo
(
int eAnimMode
)
void SimpleActor::Anim_Pain(void)
{
DesiredAnimation(eAnimMode, STRING_ANIM_CROUCH_RUN_SCR);
ContinueAnimation();
}
void SimpleActor::Anim_CrouchWalkTo
(
int eAnimMode
)
void SimpleActor::Anim_CrouchRunTo(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_CROUCH_WALK_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_CROUCH_RUN_SCR);
}
void SimpleActor::Anim_StandRunTo
(
int eAnimMode
)
void SimpleActor::Anim_CrouchWalkTo(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_RUN_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_CROUCH_WALK_SCR);
}
void SimpleActor::Anim_StandWalkTo
(
int eAnimMode
)
void SimpleActor::Anim_StandRunTo(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_WALK_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_RUN_SCR);
}
void SimpleActor::Anim_RunTo
(
int eAnimMode
)
void SimpleActor::Anim_StandWalkTo(int eAnimMode)
{
DesiredAnimation(eAnimMode, GetRunAnim());
DesiredAnimation(eAnimMode, STRING_ANIM_WALK_SCR);
}
void SimpleActor::Anim_WalkTo
(
int eAnimMode
)
void SimpleActor::Anim_RunTo(int eAnimMode)
{
DesiredAnimation(eAnimMode, GetWalkAnim());
DesiredAnimation(eAnimMode, GetRunAnim());
}
void SimpleActor::Anim_RunAwayFiring
(
int eAnimMode
)
void SimpleActor::Anim_RunAwayFiring(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_RUNAWAYFIRING_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_RUNAWAYFIRING_SCR);
}
void SimpleActor::Anim_RunToShooting
(
int eAnimMode
)
void SimpleActor::Anim_RunToShooting(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_RUN_SHOOT_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_RUN_SHOOT_SCR);
}
void SimpleActor::Anim_RunToAlarm
(
int eAnimMode
)
void SimpleActor::Anim_RunToAlarm(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_ALARM_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_ALARM_SCR);
}
void SimpleActor::Anim_RunToCasual
(
int eAnimMode
)
void SimpleActor::Anim_RunToCasual(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_CASUAL_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_CASUAL_SCR);
}
void SimpleActor::Anim_RunToCover
(
int eAnimMode
)
void SimpleActor::Anim_RunToCover(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_COVER_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_COVER_SCR);
}
void SimpleActor::Anim_RunToDanger
(
int eAnimMode
)
void SimpleActor::Anim_RunToDanger(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_DANGER_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_DANGER_SCR);
}
void SimpleActor::Anim_RunToDive
(
int eAnimMode
)
void SimpleActor::Anim_RunToDive(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_DIVE_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_DIVE_SCR);
}
void SimpleActor::Anim_RunToFlee
(
int eAnimMode
)
void SimpleActor::Anim_RunToFlee(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_FLEE_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_FLEE_SCR);
}
void SimpleActor::Anim_RunToInOpen
(
int eAnimMode
)
void SimpleActor::Anim_RunToInOpen(int eAnimMode)
{
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_INOPEN_SCR);
DesiredAnimation(eAnimMode, STRING_ANIM_RUNTO_INOPEN_SCR);
}
void SimpleActor::Anim_Emotion
(
eEmotionMode eEmotMode
)
void SimpleActor::Anim_WalkTo(int eAnimMode)
{
m_eEmotionMode = eEmotMode;
DesiredAnimation(eAnimMode, GetWalkAnim());
}
void SimpleActor::Anim_Say
(
const_str csSayAnimScript,
int iMinTimeSinceLastSay,
bool bCanInterrupt
)
void SimpleActor::Anim_Emotion(eEmotionMode eEmotMode)
{
if (!m_bSayAnimSet || bCanInterrupt)
{
if (level.inttime > m_iVoiceTime + iMinTimeSinceLastSay)
{
ScriptThreadLabel label;
label.TrySetScript(csSayAnimScript);
label.Execute(this);
}
}
m_eEmotionMode = eEmotMode;
}
void SimpleActor::Anim_FullBody
(
const_str csFullBodyAnim,
int eAnimMode
)
void SimpleActor::Anim_Say(const_str csSayAnimScript, int iMinTimeSinceLastSay, bool bCanInterrupt)
{
if( m_csAnimName == csFullBodyAnim )
{
DesiredAnimation(eAnimMode, STRING_ANIM_FULLBODY_SCR);
}
else
{
m_csAnimName = csFullBodyAnim;
StartAnimation(eAnimMode, STRING_ANIM_FULLBODY_SCR);
}
if (m_bSayAnimSet && !bCanInterrupt) {
return;
}
if (level.inttime <= iMinTimeSinceLastSay + m_iVoiceTime) {
return;
}
ScriptThreadLabel label;
label.TrySetScript(csSayAnimScript);
label.Create(this)->Execute();
}
void SimpleActor::Anim_FullBody(const_str csFullBodyAnim, int eAnimMode)
{
if (m_csAnimName == csFullBodyAnim) {
DesiredAnimation(eAnimMode, STRING_ANIM_FULLBODY_SCR);
} else {
m_csAnimName = csFullBodyAnim;
StartAnimation(eAnimMode, STRING_ANIM_FULLBODY_SCR);
}
}
+32 -41
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -24,56 +24,47 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
void Actor::InitAnimCurious
(
GlobalFuncs_t *func
)
void Actor::InitAnimCurious(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_AnimCurious;
func->BeginState = &Actor::Begin_AnimCurious;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Curious;
func->FinishedAnimation = &Actor::FinishedAnimation_Anim;
func->ShowInfo = &Actor::ShowInfo_Anim;
func->IsState = &Actor::IsCuriousState;
func->ThinkState = &Actor::Think_AnimCurious;
func->BeginState = &Actor::Begin_AnimCurious;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Curious;
func->FinishedAnimation = &Actor::FinishedAnimation_Anim;
func->ShowInfo = &Actor::ShowInfo_Anim;
func->IsState = &Actor::IsCuriousState;
}
void Actor::Begin_AnimCurious
(
void
)
void Actor::Begin_AnimCurious(void)
{
DoForceActivate();
DoForceActivate();
m_csMood = STRING_CURIOUS;
StartAnimation(m_AnimMode, m_csAnimScript);
StopTurning();
m_iCuriousTime = level.inttime;
m_csMood = STRING_CURIOUS;
m_iCuriousTime = level.inttime;
StopTurning();
StartAnimation(m_AnimMode, m_csAnimScript);
}
void Actor::Think_AnimCurious
(
void
)
void Actor::Think_AnimCurious(void)
{
if( !RequireThink() )
return;
if (!RequireThink()) {
return;
}
UpdateEyeOrigin();
m_pszDebugState = "";
LookAtCuriosity();
TimeOutCurious();
DesiredAnimation(m_AnimMode, m_csAnimScript);
CheckForThinkStateTransition();
PostThink( false );
UpdateEyeOrigin();
m_pszDebugState = "";
LookAtCuriosity();
TimeOutCurious();
DesiredAnimation(m_AnimMode, m_csAnimScript);
CheckForThinkStateTransition();
PostThink(false);
}
void Actor::FinishedAnimation_AnimCurious
(
void
)
void Actor::FinishedAnimation_AnimCurious(void)
{
if( m_State == 1101 )
{
TransitionState(1100, 0);
}
if (m_State == ACTOR_STATE_CURIOUS_RUNNING) {
TransitionState(ACTOR_STATE_CURIOUS_BEGIN, 0);
}
}
+84
View File
@@ -0,0 +1,84 @@
/*
===========================================================================
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
OpenMoHAA source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
OpenMoHAA source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// actor_badplace.cpp
#include "actor.h"
void Actor::InitBadPlace(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_BadPlace;
func->BeginState = &Actor::Begin_BadPlace;
func->EndState = &Actor::End_BadPlace;
func->ResumeState = &Actor::Begin_BadPlace;
func->SuspendState = &Actor::End_BadPlace;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_BadPlace;
func->IsState = &Actor::IsBadPlaceState;
}
void Actor::Begin_BadPlace(void)
{
DoForceActivate();
m_csMood = STRING_ALERT;
m_csIdleMood = STRING_NERVOUS;
badplace_t& badplace = level.m_badPlaces.ObjectAt(m_iBadPlaceIndex);
FindPathAway(badplace.m_vOrigin, origin - badplace.m_vOrigin, badplace.m_fRadius + 64);
}
void Actor::End_BadPlace(void)
{
m_iBadPlaceIndex = 0;
}
void Actor::Think_BadPlace(void)
{
if (m_bEnableEnemy) {
UpdateEnemy(200);
}
m_pszDebugState = "";
NoPoint();
if (!PathExists() || PathComplete() || !m_iBadPlaceIndex) {
m_iBadPlaceIndex = 0;
if (!m_Enemy || (m_Enemy->flags & FL_NOTARGET)) {
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE);
} else {
SetThinkState(THINKSTATE_ATTACK, THINKLEVEL_IDLE);
}
}
if (m_Enemy) {
m_pszDebugState = "badplace_shoot";
FaceEnemyOrMotion(m_iStateTime);
Anim_RunAwayFiring(ANIM_MODE_PATH);
} else {
m_pszDebugState = "badplace_run";
FaceMotion();
Anim_RunToInOpen(ANIM_MODE_PATH);
}
PostThink(false);
}
+322 -295
View File
@@ -1,6 +1,6 @@
/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team
Copyright (C) 2023 the OpenMoHAA team
This file is part of OpenMoHAA source code.
@@ -25,366 +25,393 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "actor.h"
#include "scriptexception.h"
void Actor::InitBalconyIdle
(
GlobalFuncs_t *func
)
void Actor::InitBalconyIdle(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_Idle;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle;
func->Pain = &Actor::Pain_Balcony;
func->Killed = &Actor::Killed_Balcony;
func->IsState = &Actor::IsIdleState;
func->ThinkState = &Actor::Think_Idle;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Idle;
func->Pain = &Actor::Pain_Balcony;
func->Killed = &Actor::Killed_Balcony;
func->IsState = &Actor::IsIdleState;
}
void Actor::InitBalconyCurious
(
GlobalFuncs_t *func
)
void Actor::InitBalconyCurious(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_Curious;
func->BeginState = &Actor::Begin_Curious;
func->EndState = &Actor::End_Curious;
func->ResumeState = &Actor::Resume_Curious;
func->SuspendState = &Actor::Suspend_Curious;
func->FinishedAnimation = &Actor::FinishedAnimation_Curious;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Curious;
func->IsState = &Actor::IsCuriousState;
func->Pain = &Actor::Pain_Balcony;
func->Killed = &Actor::Killed_Balcony;
func->ThinkState = &Actor::Think_Curious;
func->BeginState = &Actor::Begin_Curious;
func->EndState = &Actor::End_Curious;
func->ResumeState = &Actor::Resume_Curious;
func->SuspendState = &Actor::Suspend_Curious;
func->FinishedAnimation = &Actor::FinishedAnimation_Curious;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Curious;
func->IsState = &Actor::IsCuriousState;
func->Pain = &Actor::Pain_Balcony;
func->Killed = &Actor::Killed_Balcony;
}
void Actor::InitBalconyAttack
(
GlobalFuncs_t *func
)
void Actor::InitBalconyAttack(GlobalFuncs_t *func)
{
func->ThinkState = &Actor::Think_BalconyAttack;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack;
func->BeginState = &Actor::Begin_BalconyAttack;
func->FinishedAnimation = &Actor::FinishedAnimation_BalconyAttack;
func->Pain = &Actor::Pain_Balcony;
func->Killed = &Actor::Killed_Balcony;
func->IsState = &Actor::IsAttackState;
func->PostShoot = &Actor::State_Balcony_PostShoot;
func->ThinkState = &Actor::Think_BalconyAttack;
func->PassesTransitionConditions = &Actor::PassesTransitionConditions_Attack;
func->BeginState = &Actor::Begin_BalconyAttack;
func->FinishedAnimation = &Actor::FinishedAnimation_BalconyAttack;
func->Pain = &Actor::Pain_Balcony;
func->Killed = &Actor::Killed_Balcony;
func->IsState = &Actor::IsAttackState;
func->PostShoot = &Actor::State_Balcony_PostShoot;
}
void Actor::InitBalconyDisguise
(
GlobalFuncs_t *func
)
void Actor::InitBalconyDisguise(GlobalFuncs_t *func)
{
func->IsState = &Actor::IsDisguiseState;
func->IsState = &Actor::IsDisguiseState;
}
void Actor::InitBalconyGrenade
(
GlobalFuncs_t *func
)
void Actor::InitBalconyGrenade(GlobalFuncs_t *func)
{
func->IsState = &Actor::IsGrenadeState;
func->IsState = &Actor::IsGrenadeState;
}
void Actor::InitBalconyPain
(
GlobalFuncs_t *func
)
void Actor::InitBalconyPain(GlobalFuncs_t *func)
{
func->BeginState = &Actor::Begin_Pain;
func->ThinkState = &Actor::Think_Pain;
func->FinishedAnimation = &Actor::FinishedAnimation_Pain;
func->Pain = &Actor::Pain_Balcony;
func->Killed = &Actor::Killed_Balcony;
func->IsState = &Actor::IsPainState;
func->BeginState = &Actor::Begin_Pain;
func->ThinkState = &Actor::Think_Pain;
func->FinishedAnimation = &Actor::FinishedAnimation_Pain;
func->Pain = &Actor::Pain_Balcony;
func->Killed = &Actor::Killed_Balcony;
func->IsState = &Actor::IsPainState;
}
void Actor::InitBalconyKilled
(
GlobalFuncs_t *func
)
void Actor::InitBalconyKilled(GlobalFuncs_t *func)
{
func->BeginState = &Actor::Begin_BalconyKilled;
func->EndState = &Actor::End_BalconyKilled;
func->ThinkState = &Actor::Think_BalconyKilled;
func->FinishedAnimation = &Actor::FinishedAnimation_BalconyKilled;
func->IsState = &Actor::IsKilledState;
func->BeginState = &Actor::Begin_BalconyKilled;
func->EndState = &Actor::End_BalconyKilled;
func->ThinkState = &Actor::Think_BalconyKilled;
func->FinishedAnimation = &Actor::FinishedAnimation_BalconyKilled;
func->IsState = &Actor::IsKilledState;
}
void Actor::Pain_Balcony
(
Event *ev
)
void Actor::Pain_Balcony(Event *ev)
{
SetThink( THINKSTATE_PAIN, THINK_BALCONY_PAIN);
HandlePain( ev );
SetThink(THINKSTATE_PAIN, THINK_BALCONY_PAIN);
HandlePain(ev);
}
void Actor::Killed_Balcony
(
Event *ev,
bool bPlayDeathAnim
)
void Actor::Killed_Balcony(Event *ev, bool bPlayDeathAnim)
{
ClearStates();
SetThink( THINKSTATE_KILLED, THINK_BALCONY_KILLED);
HandleKilled( ev, true );
ClearStates();
SetThink(THINKSTATE_KILLED, THINK_BALCONY_KILLED);
HandleKilled(ev, true);
if( !bPlayDeathAnim )
ScriptError( "cannot do 'bedead' on balcony guys" );
if (!bPlayDeathAnim) {
ScriptError("cannot do 'bedead' on balcony guys");
}
}
void Actor::Begin_BalconyAttack
(
void
)
void Actor::Begin_BalconyAttack(void)
{
TransitionState(200, 0);
TransitionState(ACTOR_STATE_BALCONY_ATTACK_FIND_ENEMY, 0);
}
void Actor::State_Balcony_PostShoot
(
void
)
void Actor::State_Balcony_PostShoot(void)
{
if( m_Enemy )
{
TransitionState(201, 0);
}
if (m_Enemy) {
TransitionState(ACTOR_STATE_BALCONY_ATTACK_TARGET, 0);
}
}
void Actor::State_Balcony_FindEnemy
(
void
)
void Actor::State_Balcony_FindEnemy(void)
{
m_bHasDesiredLookAngles = false;
Anim_Aim();
m_bHasDesiredLookAngles = false;
Anim_Aim();
if( CanSeeEnemy( 200 ) )
{
TransitionState(201, 0);
}
if (CanSeeEnemy(200)) {
TransitionState(ACTOR_STATE_BALCONY_ATTACK_TARGET, 0);
}
}
void Actor::State_Balcony_Target
(
void
)
void Actor::State_Balcony_Target(void)
{
Anim_Aim();
AimAtTargetPos();
Anim_Aim();
AimAtTargetPos();
if( level.inttime > m_iStateTime + 1000 )
{
if( CanSeeEnemy( 0 ) && CanShootEnemy( 0 ) )
{
TransitionState(202, 0);
}
else
{
ClearPath();
TransitionState(200, 0);
}
}
if (level.inttime > m_iStateTime + 1000) {
if (CanSeeEnemy(0) && CanShootEnemy(0)) {
TransitionState(ACTOR_STATE_BALCONY_ATTACK_SHOOT, 0);
} else {
ClearPath();
TransitionState(ACTOR_STATE_BALCONY_ATTACK_FIND_ENEMY, 0);
}
}
}
void Actor::State_Balcony_Shoot
(
void
)
void Actor::State_Balcony_Shoot(void)
{
Anim_Shoot();
AimAtTargetPos();
Anim_Shoot();
AimAtTargetPos();
}
void Actor::Think_BalconyAttack
(
void
)
void Actor::Think_BalconyAttack(void)
{
if( !RequireThink() )
return;
if (!RequireThink()) {
return;
}
UpdateEyeOrigin();
UpdateEnemy( 500 );
UpdateEyeOrigin();
UpdateEnemy(500);
if( !m_Enemy )
{
SetThinkState( THINKSTATE_IDLE, THINKLEVEL_NORMAL);
IdleThink();
return;
}
if (!m_Enemy) {
SetThinkState(THINKSTATE_IDLE, THINKLEVEL_IDLE);
IdleThink();
return;
}
NoPoint();
NoPoint();
if( m_State == 201 )
{
m_pszDebugState = "target";
State_Balcony_Target();
}
else if( m_State == 202 )
{
m_pszDebugState = "shoot";
State_Balcony_Shoot();
}
else if( m_State == 200 )
{
m_pszDebugState = "findenemy";
State_Balcony_FindEnemy();
}
else
{
Com_Printf( "Actor::Think_BalconyAttack: invalid think state %i\n", m_State );
assert( 0 );
}
switch (m_State) {
case ACTOR_STATE_BALCONY_ATTACK_TARGET:
m_pszDebugState = "target";
State_Balcony_Target();
break;
case ACTOR_STATE_BALCONY_ATTACK_SHOOT:
m_pszDebugState = "shoot";
State_Balcony_Shoot();
break;
case ACTOR_STATE_BALCONY_ATTACK_FIND_ENEMY:
m_pszDebugState = "findenemy";
State_Balcony_FindEnemy();
break;
default:
Com_Printf("Actor::Think_BalconyAttack: invalid think state %i\n", m_State);
assert(0);
break;
}
PostThink( true );
PostThink(true);
}
void Actor::FinishedAnimation_BalconyAttack
(
void
)
void Actor::FinishedAnimation_BalconyAttack(void)
{
if( m_State == 202 )
State_Balcony_PostShoot();
if (m_State == ACTOR_STATE_BALCONY_ATTACK_SHOOT) {
State_Balcony_PostShoot();
}
}
void Actor::Begin_BalconyKilled
(
void
)
bool Actor::CalcFallPath(void)
{
ClearPath();
ResetBoneControllers();
mmove_t mm;
int currentPos = 0;
int loop;
vec3_t pos[200];
float startDeltaTime;
float nextTime;
vec3_t vRelDelta;
vec3_t vAbsDelta;
float animTime;
int anim;
int i;
float startTime;
PostEvent( EV_Actor_DeathEmbalm, 0.05f );
SetMoveInfo(&mm);
if( CalcFallPath() )
TransitionState(800, 0);
else
TransitionState(806, 0);
mm.tracemask &= ~(CONTENTS_BODY | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP | CONTENTS_BBOX);
mm.desired_speed = 80;
VectorCopy2D(orientation[0], mm.desired_dir);
anim = gi.Anim_NumForName(edict->tiki, "death_balcony_intro");
animTime = gi.Anim_Time(edict->tiki, anim);
startTime = 0.65f;
for (;;) {
MmoveSingle(&mm);
VectorCopy(mm.origin, pos[currentPos]);
currentPos++;
if (currentPos >= ARRAY_LEN(pos)) {
return false;
}
if (mm.hit_obstacle) {
break;
}
if (!mm.groundPlane) {
return false;
}
startTime -= level.frametime;
if (startTime < 0) {
return false;
}
}
for (startDeltaTime = 0.65f; startDeltaTime < animTime; startDeltaTime = nextTime) {
nextTime = startDeltaTime + level.frametime;
if (nextTime >= animTime - 0.01f) {
nextTime = animTime;
}
gi.Anim_DeltaOverTime(edict->tiki, anim, startDeltaTime, nextTime, vRelDelta);
MatrixTransformVector(vRelDelta, orientation, vAbsDelta);
VectorAdd(mm.origin, vAbsDelta, mm.origin);
VectorCopy(mm.origin, pos[currentPos]);
currentPos++;
if (currentPos >= ARRAY_LEN(pos)) {
return false;
}
}
loop = currentPos;
mm.desired_speed = 0;
mm.groundPlane = NULL;
mm.walking = false;
VectorSet(mm.velocity, 0, 0, -171);
do {
MmoveSingle(&mm);
VectorCopy(mm.origin, pos[currentPos]);
currentPos++;
if (currentPos >= ARRAY_LEN(pos)) {
return false;
}
if (mm.hit_obstacle) {
return false;
}
} while (!mm.groundPlane);
if (origin[2] - pos[currentPos - 1][2] < m_fBalconyHeight) {
return false;
}
m_pFallPath = (FallPath*)gi.Malloc(sizeof(FallPath) + sizeof(FallPath::pos) * (currentPos - 1));
m_pFallPath->length = currentPos;
m_pFallPath->currentPos = 0;
m_pFallPath->startTime = startTime;
m_pFallPath->loop = loop;
for (i = 0; i < currentPos; i++) {
VectorCopy(pos[i], m_pFallPath->pos[i]);
}
return true;
}
void Actor::End_BalconyKilled
(
void
)
void Actor::Begin_BalconyKilled(void)
{
if( m_pFallPath )
{
gi.Free(m_pFallPath);
m_pFallPath = NULL;
}
ClearPath();
ResetBoneControllers();
PostEvent(EV_Actor_DeathEmbalm, 0.05f);
if (CalcFallPath()) {
TransitionState(ACTOR_STATE_BALCONY_KILLED_BEGIN, 0);
} else {
TransitionState(ACTOR_STATE_BALCONY_KILLED_NORMAL, 0);
}
}
void Actor::Think_BalconyKilled
(
void
)
void Actor::End_BalconyKilled(void)
{
int animnum;
Unregister( STRING_ANIMDONE );
if( m_State == 805 )
{
m_pszDebugState = "end";
}
else
{
NoPoint();
m_bHasDesiredLookAngles = false;
StopTurning();
switch( m_State )
{
case 800:
m_bNextForceStart = true;
m_eNextAnimMode = 7;
m_pszDebugState = "begin";
m_csNextAnimString = STRING_ANIM_NO_KILLED_SCR;
animnum = gi.Anim_NumForName(edict->tiki, "death_balcony_intro");
ChangeMotionAnim();
m_bMotionAnimSet = true;
m_iMotionSlot = GetMotionSlot(0);
m_weightType[m_iMotionSlot] = 1;
m_weightCrossBlend[m_iMotionSlot] = 0.0;
m_weightBase[m_iMotionSlot] = 1.0;
NewAnim( animnum, m_iMotionSlot );
SetTime( m_iMotionSlot, m_pFallPath->startTime );
UpdateNormalAnimSlot( m_iMotionSlot );
TransitionState(801, 0);
break;
case 801:
m_bNextForceStart = false;
m_pszDebugState = "intro";
m_eNextAnimMode = 7;
m_csNextAnimString = STRING_ANIM_NO_KILLED_SCR;
break;
case 802:
m_pszDebugState = "loop";
Anim_FullBody( STRING_DEATH_BALCONY_LOOP, 7 );
break;
case 803:
TransitionState(804, 0);
StopAllAnimating();
case 804:
m_pszDebugState = "outtro";
Anim_FullBody( STRING_DEATH_BALCONY_OUTTRO, 1 );
break;
case 806:
m_pszDebugState = "normal";
Anim_Killed();
break;
default:
Com_Printf( "Actor::Think_BalconyKilled: invalid think state %i\n", m_State );
assert( 0 );
}
PostThink( false );
if( m_State >= 800 )
{
if( m_State == 801 )
{
if( m_pFallPath->currentPos >= m_pFallPath->length )
{
TransitionState(803, 0);
}
else if (m_pFallPath->currentPos >= m_pFallPath->loop)
{
TransitionState(802, 0);
}
}
else if( m_State == 802 )
{
if (m_pFallPath->currentPos >= m_pFallPath->length)
{
TransitionState(803, 0);
}
}
}
}
if (m_pFallPath) {
gi.Free(m_pFallPath);
m_pFallPath = NULL;
}
}
void Actor::FinishedAnimation_BalconyKilled
(
void
)
void Actor::Think_BalconyKilled(void)
{
if( m_State == 804 || m_State == 806 )
{
BecomeCorpse();
TransitionState(805, 0);
}
else if( m_State == 801 )
{
TransitionState(802, 0);
StopAllAnimating();
}
int animnum;
Unregister(STRING_ANIMDONE);
if (m_State == ACTOR_STATE_BALCONY_KILLED_END) {
m_pszDebugState = "";
return;
}
NoPoint();
ForwardLook();
switch (m_State) {
case ACTOR_STATE_BALCONY_KILLED_BEGIN:
m_bNextForceStart = true;
m_eNextAnimMode = ANIM_MODE_FALLING_PATH;
m_pszDebugState = "begin";
m_csNextAnimString = STRING_ANIM_NO_KILLED_SCR;
animnum = gi.Anim_NumForName(edict->tiki, "death_balcony_intro");
ChangeMotionAnim();
m_bMotionAnimSet = true;
m_iMotionSlot = GetMotionSlot(0);
m_weightType[m_iMotionSlot] = ANIM_WEIGHT_MOTION;
m_weightCrossBlend[m_iMotionSlot] = 0.0;
m_weightBase[m_iMotionSlot] = 1.0;
NewAnim(animnum, m_iMotionSlot);
SetTime(m_iMotionSlot, m_pFallPath->startTime);
UpdateNormalAnimSlot(m_iMotionSlot);
TransitionState(ACTOR_STATE_BALCONY_KILLED_INTRO, 0);
break;
case ACTOR_STATE_BALCONY_KILLED_INTRO:
m_bNextForceStart = false;
m_pszDebugState = "intro";
m_eNextAnimMode = ANIM_MODE_FALLING_PATH;
m_csNextAnimString = STRING_ANIM_NO_KILLED_SCR;
break;
case ACTOR_STATE_BALCONY_KILLED_LOOP:
m_pszDebugState = "loop";
Anim_FullBody(STRING_DEATH_BALCONY_LOOP, 7);
break;
case ACTOR_STATE_BALCONY_KILLED_LOOP_END:
TransitionState(804, 0);
StopAllAnimating();
case ACTOR_STATE_BALCONY_KILLED_OUTTRO:
m_pszDebugState = "outtro";
Anim_FullBody(STRING_DEATH_BALCONY_OUTTRO, 1);
break;
case ACTOR_STATE_BALCONY_KILLED_NORMAL:
m_pszDebugState = "normal";
Anim_Killed();
break;
default:
Com_Printf("Actor::Think_BalconyKilled: invalid think state %i\n", m_State);
assert(0);
}
PostThink(false);
if (m_State >= ACTOR_STATE_BALCONY_KILLED_BEGIN) {
if (m_State == ACTOR_STATE_BALCONY_KILLED_INTRO) {
if (m_pFallPath->currentPos >= m_pFallPath->length) {
TransitionState(ACTOR_STATE_BALCONY_KILLED_LOOP_END, 0);
}
else if (m_pFallPath->currentPos >= m_pFallPath->loop) {
TransitionState(ACTOR_STATE_BALCONY_KILLED_LOOP, 0);
}
} else if (m_State == ACTOR_STATE_BALCONY_KILLED_LOOP) {
if (m_pFallPath->currentPos >= m_pFallPath->length) {
TransitionState(ACTOR_STATE_BALCONY_KILLED_LOOP_END, 0);
}
}
}
}
void Actor::FinishedAnimation_BalconyKilled(void)
{
switch (m_State) {
case ACTOR_STATE_BALCONY_KILLED_OUTTRO:
case ACTOR_STATE_BALCONY_KILLED_NORMAL:
BecomeCorpse();
TransitionState(ACTOR_STATE_BALCONY_KILLED_END, 0);
break;
case ACTOR_STATE_BALCONY_KILLED_INTRO:
TransitionState(ACTOR_STATE_BALCONY_KILLED_LOOP, 0);
StopAllAnimating();
break;
}
}
+621 -827
View File
File diff suppressed because it is too large. Load diff
+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);
}
+414 -521
View File
File diff suppressed because it is too large. Load diff
+120 -111
View File
@@ -22,138 +22,147 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// actorpath.h: Actor path
#ifndef __ACTORPATH_H__
#define __ACTORPATH_H__
#pragma once
#define MIN_FALLHEIGHT 18
#define MAX_FALLHEIGHT 1024
class ActorPath {
// path list
PathInfo *m_path;
int m_pathlen;
// path position
PathInfo *m_pathpos;
class ActorPath
{
// path list
PathInfo *m_path;
int m_pathlen;
// starting path position
PathInfo *m_startpathpos;
vec2_t m_delta;
bool m_Side;
int m_Time;
float m_TotalDist;
short int m_FallHeight;
bool m_HasCompleteLookahead;
float m_fLookAhead;
bool m_bChangeLookAhead;
// path position
PathInfo *m_pathpos;
// starting path position
PathInfo *m_startpathpos;
vec2_t m_delta;
bool m_Side;
int m_Time;
float m_TotalDist;
short int m_FallHeight;
bool m_HasCompleteLookahead;
float m_fLookAhead;
bool m_bChangeLookAhead;
private:
float PathLookAhead( float total_area, Vector& end, float *origin );
float PathLookAhead(float total_area, Vector& end, float *origin);
public:
ActorPath();
~ActorPath();
ActorPath();
~ActorPath();
void Clear( void );
bool DoesTheoreticPathExist( float *start, float *end, class SimpleActor *ent, float maxPath, float *vLeashHome, float fLeashDistSquared );
void FindPath( float *start, float *end, Entity *ent, float maxPath, float *vLeashHome, float fLeashDistSquared );
void FindPathAway( float *start, float *avoid, float *vPreferredDir, Entity *ent, float fMinSafeDist, float *vLeashHome, float fLeashDistSquared );
void FindPathNear( float *start, float *nearby, Entity *ent, float maxPath, float fRadiusSquared, float *vLeashHome, float fLeashDistSquared );
void ReFindPath( float *start, Entity *ent );
void UpdatePos( float *origin, float fNodeRadius = 0.0f );
bool Complete( const float *origin ) const;
PathInfo *StartNode( void ) const;
PathInfo *CurrentNode( void ) const;
int CurrentNodeIndex( void ) const;
PathInfo *NextNode( void ) const;
PathInfo *LastNode( void ) const;
Vector CurrentPathDir( void ) const;
float *CurrentPathGoal( void ) const;
int Time( void ) const;
Vector CurrentDelta( void ) const;
bool IsAccurate( void ) const;
float TotalDist( void ) const;
void SetFallHeight( float fHeight );
float GetFallHeight( void ) const;
void TrimPathFromEnd( int nNodesPop );
void Shorten( float fDistRemove );
bool HasCompleteLookahead( void ) const;
bool IsSide( void ) const;
void ForceShortLookahead( void );
void Clear(void);
bool DoesTheoreticPathExist(
float *start, float *end, class SimpleActor *ent, float maxPath, float *vLeashHome, float fLeashDistSquared
);
void FindPath(float *start, float *end, Entity *ent, float maxPath, float *vLeashHome, float fLeashDistSquared);
void FindPathAway(
float *start,
float *avoid,
float *vPreferredDir,
Entity *ent,
float fMinSafeDist,
float *vLeashHome,
float fLeashDistSquared
);
void FindPathNear(
float *start,
float *nearby,
Entity *ent,
float maxPath,
float fRadiusSquared,
float *vLeashHome,
float fLeashDistSquared
);
void ReFindPath(float *start, Entity *ent);
void UpdatePos(float *origin, float fNodeRadius = 0.0f);
bool Complete(const float *origin) const;
PathInfo *StartNode(void) const;
PathInfo *CurrentNode(void) const;
int CurrentNodeIndex(void) const;
PathInfo *NextNode(void) const;
PathInfo *LastNode(void) const;
const float *CurrentPathDir(void) const;
const float *CurrentPathGoal(void) const;
int Time(void) const;
const float *CurrentDelta(void) const;
bool IsAccurate(void) const;
float TotalDist(void) const;
void SetFallHeight(float fHeight);
float GetFallHeight(void) const;
void TrimPathFromEnd(int nNodesPop);
void Shorten(float fDistRemove);
bool HasCompleteLookahead(void) const;
void ForceShortLookahead(void);
virtual void Archive( Archiver& arc );
virtual void Archive(Archiver& arc);
bool IsSide(void) const;
};
inline void ActorPath::Archive
(
Archiver& arc
)
inline void ActorPath::Archive(Archiver& arc)
{
int pos;
int startpathpos;
int pos;
int startpathpos;
arc.ArchiveInteger( &m_pathlen );
arc.ArchiveInteger(&m_pathlen);
if( m_pathlen )
{
if( arc.Loading() )
{
m_path = new PathInfo[ m_pathlen ];
}
if (m_pathlen) {
if (arc.Loading()) {
m_path = new PathInfo[m_pathlen];
}
if( m_pathlen > 0 )
{
for( int i = 0; i < m_pathlen; i++ )
{
m_path->Archive( arc );
}
}
if (m_pathlen > 0) {
for (int i = 0; i < m_pathlen; i++) {
m_path->Archive(arc);
}
}
if( !arc.Saving() )
{
arc.ArchiveInteger( &pos );
if( pos == -1 )
m_pathpos = NULL;
else
m_pathpos = &m_path[ pos ];
if (!arc.Saving()) {
arc.ArchiveInteger(&pos);
if (pos == -1) {
m_pathpos = NULL;
} else {
m_pathpos = &m_path[pos];
}
arc.ArchiveInteger( &startpathpos );
if( startpathpos == -1 )
m_startpathpos = NULL;
else
m_startpathpos = &m_path[ pos ];
}
else
{
if( m_pathpos )
pos = m_pathpos - m_path;
else
pos = -1;
arc.ArchiveInteger(&startpathpos);
if (startpathpos == -1) {
m_startpathpos = NULL;
} else {
m_startpathpos = &m_path[pos];
}
} else {
if (m_pathpos) {
pos = m_pathpos - m_path;
} else {
pos = -1;
}
arc.ArchiveInteger( &pos );
arc.ArchiveInteger(&pos);
if( m_startpathpos )
pos = m_startpathpos - m_path;
else
pos = -1;
if (m_startpathpos) {
pos = m_startpathpos - m_path;
} else {
pos = -1;
}
arc.ArchiveInteger( &pos );
}
}
else if( arc.Loading() )
{
m_pathpos = 0;
}
arc.ArchiveInteger(&pos);
}
} else if (arc.Loading()) {
m_pathpos = 0;
}
arc.ArchiveVec2( m_delta );
arc.ArchiveBool( &m_Side );
arc.ArchiveInteger( &m_Time );
arc.ArchiveFloat( &m_TotalDist );
arc.ArchiveShort( &m_FallHeight );
arc.ArchiveShort( &m_FallHeight );
arc.ArchiveBool( &m_HasCompleteLookahead );
arc.ArchiveFloat( &m_fLookAhead );
arc.ArchiveBool( &m_bChangeLookAhead );
arc.ArchiveVec2(m_delta);
arc.ArchiveBool(&m_Side);
arc.ArchiveInteger(&m_Time);
arc.ArchiveFloat(&m_TotalDist);
arc.ArchiveShort(&m_FallHeight);
arc.ArchiveShort(&m_FallHeight);
arc.ArchiveBool(&m_HasCompleteLookahead);
arc.ArchiveFloat(&m_fLookAhead);
arc.ArchiveBool(&m_bChangeLookAhead);
}
#endif /* actorpath.h */
+103 -119
View File
@@ -21,163 +21,147 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// ammo.cpp: Base class for all ammunition for entities derived from the Weapon class.
//
//
// AmmoEntity is the Class which represents ammo that the player "sees" and "
// picks up" in the game
//
// Ammo is the Class which is used to keep track of how much ammo a player has
// Ammo is the Class which is used to keep track of how much ammo a player has
// in his inventory
#include "ammo.h"
#include "player.h"
CLASS_DECLARATION( Item, AmmoEntity, NULL )
{
{ NULL, NULL }
};
CLASS_DECLARATION(Item, AmmoEntity, NULL) {
{NULL, NULL}
};
AmmoEntity::AmmoEntity
(
)
AmmoEntity::AmmoEntity()
{
if ( LoadingSavegame )
{
// all data will be setup by the archive function
return;
}
setName( "UnknownAmmo" );
amount = 0;
}
{
if (LoadingSavegame) {
// all data will be setup by the archive function
return;
}
setName("UnknownAmmo");
amount = 0;
}
Item *AmmoEntity::ItemPickup
(
Entity *other,
qboolean add_to_inventory
)
Item *AmmoEntity::ItemPickup(Entity *other, qboolean add_to_inventory)
{
Sentient *player;
str realname;
AliasListNode_t *ret;
{
Sentient *player;
Weapon* pWeap;
if ( !other->isSubclassOf( Player ) )
return NULL;
if (!other->IsSubclassOfPlayer()) {
return NULL;
}
player = ( Sentient * )other;
player = (Sentient *)other;
// Play pickup sound
realname = GetRandomAlias( "snd_pickup", &ret );
if ( realname.length() > 1 )
player->Sound( realname, CHAN_ITEM );
if (player->AmmoCount(item_name.c_str()) == player->MaxAmmoCount(item_name.c_str())) {
// don't pickup if the player already has max ammo
return NULL;
}
// Cancel some events
CancelEventsOfType( EV_Item_DropToFloor );
CancelEventsOfType( EV_Item_Respawn );
CancelEventsOfType( EV_FadeOut );
// Play pickup sound
player->Sound(sPickupSound, CHAN_ITEM);
// Hide the model
setSolidType( SOLID_NOT );
hideModel();
// Cancel some events
CancelEventsOfType(EV_Item_DropToFloor);
CancelEventsOfType(EV_Item_Respawn);
CancelEventsOfType(EV_FadeOut);
// Respawn?
if ( !Respawnable() )
PostEvent( EV_Remove, FRAMETIME );
else
PostEvent( EV_Item_Respawn, RespawnTime() );
// Hide the model
setSolidType(SOLID_NOT);
hideModel();
// Give the ammo to the player
player->GiveAmmo( item_name, amount );
return NULL; // This doesn't create any items
}
// Respawn?
if (!Respawnable()) {
PostEvent(EV_Remove, FRAMETIME);
} else {
PostEvent(EV_Item_Respawn, RespawnTime());
}
// Notify scripts about the pickup
Unregister(STRING_PICKUP);
// Tell the player about the ammo being picked
gi.SendServerCommand(other->edict - g_entities, "print \"" HUD_MESSAGE_YELLOW "%s\"", gi.LV_ConvertString(va("Got %d %s Rounds", amount, item_name.c_str())));
// Give the ammo to the player
player->GiveAmmo(item_name, amount);
// Make the weapon reload if the weapon has an empty clip
pWeap = player->GetActiveWeapon(WEAPON_MAIN);
if (pWeap && !pWeap->HasAmmoInClip(FIRE_PRIMARY) && pWeap->CheckReload(FIRE_PRIMARY)) {
pWeap->SetShouldReload(qtrue);
}
return NULL; // This doesn't create any items
}
// This is the Class that is used to keep track of ammo in the player's inventory.
// It is not an entit, just a name and an amount.
CLASS_DECLARATION( Class, Ammo, NULL )
{
{NULL, NULL}
};
CLASS_DECLARATION(Class, Ammo, NULL) {
{NULL, NULL}
};
Ammo::Ammo
(
)
Ammo::Ammo()
{
if ( LoadingSavegame )
{
// all data will be setup by the archive function
return;
}
setName( "UnknownAmmo" );
setAmount( 0 );
setMaxAmount( 100 );
}
{
if (LoadingSavegame) {
// all data will be setup by the archive function
return;
}
setName("UnknownAmmo");
setAmount(0);
setMaxAmount(100);
}
void Ammo::setAmount
(
int a
)
void Ammo::setAmount(int a)
{
amount = a;
{
amount = a;
if ( ( maxamount > 0 ) && ( amount > maxamount ) )
amount = maxamount;
}
if ((maxamount > 0) && (amount > maxamount)) {
amount = maxamount;
}
}
int Ammo::getAmount
(
void
)
int Ammo::getAmount(void)
{
return amount;
}
{
return amount;
}
void Ammo::setMaxAmount
(
int a
)
void Ammo::setMaxAmount(int a)
{
maxamount = a;
}
{
maxamount = a;
}
int Ammo::getMaxAmount
(
void
)
int Ammo::getMaxAmount(void)
{
return maxamount;
}
{
return maxamount;
}
void Ammo::setName
(
str n
)
void Ammo::setName(str n)
{
name = n;
name_index = gi.itemindex( name ) + CS_WEAPONS;
}
{
name = n;
name_index = gi.itemindex(name) + CS_WEAPONS;
}
str Ammo::getName
(
void
)
str Ammo::getName(void)
{
return name;
}
{
return name;
}
int Ammo::getIndex
(
void
)
int Ammo::getIndex(void)
{
return name_index;
}
{
return name_index;
}
+37 -41
View File
@@ -29,55 +29,51 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "item.h"
class AmmoEntity : public Item
{
public:
CLASS_PROTOTYPE( AmmoEntity );
{
public:
CLASS_PROTOTYPE(AmmoEntity);
AmmoEntity();
Item *ItemPickup( Entity *other, qboolean add_to_inventory ) override;
};
AmmoEntity();
Item *ItemPickup(Entity *other, qboolean add_to_inventory) override;
};
class Ammo : public Class
{
int amount;
int maxamount;
str name;
int name_index;
{
int amount;
int maxamount;
str name;
int name_index;
public:
CLASS_PROTOTYPE( Ammo );
public:
CLASS_PROTOTYPE(Ammo);
Ammo();
Ammo(str name, int amount, int name_index );
Ammo();
Ammo(str name, int amount, int name_index);
void setAmount( int a );
int getAmount( void );
void setMaxAmount( int a );
int getMaxAmount( void );
void setName( str name);
str getName( void );
int getIndex( void );
void Archive( Archiver &arc ) override;
};
void setAmount(int a);
int getAmount(void);
void setMaxAmount(int a);
int getMaxAmount(void);
void setName(str name);
str getName(void);
int getIndex(void);
void Archive(Archiver& arc) override;
};
inline void Ammo::Archive
(
Archiver &arc
)
inline void Ammo::Archive(Archiver& arc)
{
Class::Archive( arc );
{
Class::Archive(arc);
arc.ArchiveInteger( &amount );
arc.ArchiveInteger( &maxamount );
arc.ArchiveString( &name );
//
// name_index not archived, because it is auto-generated by gi.itemindex
//
if ( arc.Loading() )
{
setName( name );
}
}
arc.ArchiveInteger(&amount);
arc.ArchiveInteger(&maxamount);
arc.ArchiveString(&name);
//
// name_index not archived, because it is auto-generated by gi.itemindex
//
if (arc.Loading()) {
setName(name);
}
}
#endif /* ammo.h */
+316 -149
View File
@@ -32,48 +32,35 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
extern Event EV_Entity_Start;
// Leg Animation events
Event EV_SetAnim("anim", EV_ZERO, "s", "animName", "Exec anim commands on server or client.", EV_NORMAL);
Event EV_SetSyncTime("setsynctime", EV_ZERO, "f", "synctime", "Set sync time for entity.");
Event EV_SetFrame(
"setframe",
Event EV_SetAnim
(
"anim",
EV_ZERO,
"iS",
"frameNumber animName",
"Set the frame on the legs, if anim is not specified, current is assumed.",
"s",
"animName",
"Exec anim commands on server or client.",
EV_NORMAL
);
Event EV_AnimDone("animdone", EV_ZERO, NULL, NULL, "Legs animation has finished, not for script use.", EV_NORMAL);
Event EV_FrameDelta(
"setmovedelta", EV_ZERO, "vf", "moveDelta moveTime", "movement from animation, not for script use.", EV_NORMAL
);
Event EV_Torso_Anim("torso_anim", EV_ZERO, "s", "animName", "set the torso animation to animName.", EV_NORMAL);
Event EV_Torso_SetFrame(
"torso_setframe",
Event EV_SetSyncTime
(
"setsynctime",
EV_ZERO,
"iS",
"frameNumber animName",
"Set the frame on the torso, if anim is not specified, current is assumed.",
"f",
"synctime",
"Set sync time for entity.",
EV_NORMAL
);
Event EV_Torso_AnimDone(
"torso_animdone", EV_ZERO, NULL, NULL, "Torso animation has finished, not for script use.", EV_NORMAL
Event EV_Animate_IsLoopingAnim
(
"isloopinganim",
EV_DEFAULT,
"s",
"anim_name",
"returns 1 if the anim is a looping anim, or 0 otherwise",
EV_RETURN
);
Event EV_Torso_StopAnimating(
"torso_stopanimating",
EV_ZERO,
NULL,
NULL,
"stop the torso from animating. Animation will end at the end of current cycle.",
EV_NORMAL
);
Event EV_NewAnim(
"animate_newanim", EV_ZERO, "ii", "animNum slot", "Start a new animation, not for script use.", EV_NORMAL
);
Event EV_ViewAnim("viewanim", EV_DEFAULT, "s", "anim", "testing");
Event EV_Animate_IsLoopingAnim(
"isloopinganim", EV_DEFAULT, "s", "anim_name", "returns 1 if the anim is a looping anim, or 0 otherwise", EV_RETURN
);
Event EV_Animate_SetYawfromBone(
Event EV_Animate_SetYawfromBone
(
"setyawfrombone",
EV_DEFAULT,
"s",
@@ -81,7 +68,8 @@ Event EV_Animate_SetYawfromBone(
"Set the yaw of the model based on the current animation time",
EV_NORMAL
);
Event EV_Animate_PlayerSpawn(
Event EV_Animate_PlayerSpawn
(
"playerspawn",
EV_DEFAULT,
"sFVFF",
@@ -101,10 +89,33 @@ Event EV_Animate_PlayerSpawn(
"one second later.",
EV_NORMAL
);
Event EV_Animate_PlayerSpawn_Utility(
"testmojo", EV_DEFAULT, "sv", "model_name vector_offset", "INTERNAL EVENT", EV_NORMAL
Event EV_Animate_PlayerSpawn_Utility
(
"testmojo",
EV_DEFAULT,
"sv",
"model_name vector_offset",
"INTERNAL EVENT",
EV_NORMAL
);
Event EV_Animate_PauseAnim
(
"pauseanims",
EV_DEFAULT,
"i",
"pause",
"Pause (or unpause) animations",
EV_NORMAL
);
Event EV_Animate_Client_Sound
(
"_client_sound",
EV_DEFAULT,
NULL,
NULL,
NULL,
EV_NORMAL
);
Event EV_Animate_PauseAnim("pauseanims", EV_DEFAULT, "i", "pause", "Pause (or unpause) animations");
CLASS_DECLARATION(Entity, Animate, "animate") {
{&EV_SetControllerAngles, &Animate::SetControllerAngles },
@@ -115,16 +126,54 @@ CLASS_DECLARATION(Entity, Animate, "animate") {
{&EV_Animate_PlayerSpawn, &Animate::EventPlayerSpawn },
{&EV_Animate_PlayerSpawn_Utility, &Animate::EventPlayerSpawnUtility},
{&EV_Animate_PauseAnim, &Animate::EventPauseAnim },
{&EV_Animate_Client_Sound, &Animate::ClientSound },
{NULL, NULL }
};
static size_t GetLongestClientCmdLength(const tiki_cmd_t& cmds)
{
size_t ii;
size_t longest = 0;
for (ii = 0; ii < cmds.num_cmds; ii++) {
const tiki_singlecmd_t& single_cmd = cmds.cmds[ii];
size_t length = strlen(single_cmd.args[0]);
if (length > longest) {
longest = length;
}
}
return longest;
}
static size_t GetLongestClientCmdAllFramesLength(dtiki_t *tiki, int animnum, int numframes)
{
tiki_cmd_t cmds;
size_t longest = 0;
int i;
for (i = 0; i < numframes; i++) {
// we want normal frame commands to occur right on the frame
if (gi.Frame_Commands_Client(tiki, animnum, i, &cmds)) {
size_t length = GetLongestClientCmdLength(cmds);
if (length > longest) {
longest = length;
}
}
}
return longest;
}
Animate::Animate()
{
entflags |= EF_ANIMATE;
entflags |= ECF_ANIMATE;
syncTime = 0.0f;
syncRate = 1.0f;
pauseSyncTime = 0.0f;
syncTime = 0.0f;
syncRate = 1.0f;
is_paused = false;
frame_delta = vec_zero;
angular_delta = 0;
@@ -149,7 +198,7 @@ Animate::Animate()
Animate::~Animate()
{
entflags &= ~EF_ANIMATE;
entflags &= ~ECF_ANIMATE;
}
void Animate::ForwardExec(Event *ev)
@@ -164,7 +213,6 @@ void Animate::ForwardExec(Event *ev)
);
}
NewAnim(ev->GetString(1), 0);
RestartAnimSlot(0);
}
@@ -217,11 +265,10 @@ void Animate::NewAnim(int animnum, int slot, float weight)
animFlags[slot] = ANIM_LOOP | ANIM_NODELTA | ANIM_NOEXIT;
if (!(gi.Anim_FlagsSkel(edict->tiki, animnum) & ANIM_LOOP)) {
animFlags[slot] &= ~ANIM_LOOP;
SetOnceType(slot);
}
edict->s.frameInfo[slot].weight = weight;
SetWeight(slot, weight);
animtimes[slot] = gi.Anim_Time(edict->tiki, animnum);
frametimes[slot] = gi.Anim_Frametime(edict->tiki, animnum);
@@ -229,7 +276,8 @@ void Animate::NewAnim(int animnum, int slot, float weight)
edict->s.eType = ET_MODELANIM;
}
qboolean hascommands = gi.Anim_HasCommands(edict->tiki, animnum);
qboolean hascommands =
gi.Anim_HasCommands(edict->tiki, animnum) || gi.Anim_HasCommands_Client(edict->tiki, animnum);
// enter this animation
if (newanim) {
@@ -241,18 +289,53 @@ void Animate::NewAnim(int animnum, int slot, float weight)
int ii, j;
for (ii = 0; ii < cmds.num_cmds; ii++) {
ev = new AnimationEvent(cmds.cmds[ii].args[0]);
const tiki_singlecmd_t& single_cmd = cmds.cmds[ii];
ev->SetAnimationNumber(animnum);
ev->SetAnimationFrame(0);
AnimationEvent ev(single_cmd.args[0], single_cmd.num_args);
for (j = 1; j < cmds.cmds[ii].num_args; j++) {
ev->AddToken(cmds.cmds[ii].args[j]);
ev.SetAnimationNumber(animnum);
ev.SetAnimationFrame(0);
for (j = 1; j < single_cmd.num_args; j++) {
ev.AddToken(single_cmd.args[j]);
}
ProcessEvent(ev);
}
}
if (gi.Frame_Commands_Client(edict->tiki, animnum, TIKI_FRAME_ENTRY, &cmds)) {
size_t longest = GetLongestClientCmdLength(cmds);
int ii, j;
if (longest) {
char *cmdName = (char *)alloca(longest + 8 + 1);
for (ii = 0; ii < cmds.num_cmds; ii++) {
const tiki_singlecmd_t& single_cmd = cmds.cmds[ii];
int eventNum;
strcpy(cmdName, "_client_");
strcpy(cmdName + 8, single_cmd.args[0]);
eventNum = Event::FindEventNum(cmdName);
AnimationEvent ev(eventNum, single_cmd.num_args);
if (!ev.eventnum) {
continue;
}
ev.SetAnimationNumber(animnum);
ev.SetAnimationFrame(0);
for (j = 1; j < single_cmd.num_args; j++) {
ev.AddToken(single_cmd.args[j]);
}
ProcessEvent(ev);
}
}
}
}
if (!hascommands) {
@@ -272,37 +355,75 @@ void Animate::NewAnim(int animnum, int slot, float weight)
int ii, j;
for (ii = 0; ii < cmds.num_cmds; ii++) {
ev = new AnimationEvent(cmds.cmds[ii].args[0]);
const tiki_singlecmd_t& single_cmd = cmds.cmds[ii];
ev = new AnimationEvent(single_cmd.args[0], single_cmd.num_args);
ev->SetAnimationNumber(animnum);
ev->SetAnimationFrame(i);
for (j = 1; j < cmds.cmds[ii].num_args; j++) {
ev->AddToken(cmds.cmds[ii].args[j]);
for (j = 1; j < single_cmd.num_args; j++) {
ev->AddToken(single_cmd.args[j]);
}
PostEvent(ev, time, 1 << slot);
}
}
}
time = 0.0f;
const size_t longestAllFrames = GetLongestClientCmdAllFramesLength(edict->tiki, animnum, numframes);
if (longestAllFrames) {
char *cmdName = (char *)alloca(longestAllFrames + 8 + 1);
for (i = 0; i < numframes; i++, time += frametimes[slot]) {
// we want normal frame commands to occur right on the frame
if (gi.Frame_Commands_Client(edict->tiki, animnum, i, &cmds)) {
int ii, j;
for (ii = 0; ii < cmds.num_cmds; ii++) {
const tiki_singlecmd_t& single_cmd = cmds.cmds[ii];
int eventNum;
strcpy(cmdName, "_client_");
strcpy(cmdName + 8, single_cmd.args[0]);
eventNum = Event::FindEventNum(cmdName);
AnimationEvent ev(eventNum, single_cmd.num_args);
if (!ev.eventnum) {
continue;
}
ev.SetAnimationNumber(animnum);
ev.SetAnimationFrame(i);
for (j = 1; j < single_cmd.num_args; j++) {
ev.AddToken(single_cmd.args[j]);
}
PostEvent(ev, time, 1 << slot);
}
}
}
}
}
void Animate::NewAnim(int animnum, Event& newevent, int slot, float weight)
{
if (animnum == -1) {
if (animnum != -1) {
NewAnim(animnum, slot);
SetAnimDoneEvent(newevent, slot);
} else {
PostEvent(newevent, level.frametime);
}
NewAnim(animnum, slot);
SetAnimDoneEvent(newevent, slot);
}
void Animate::NewAnim(int animnum, Event *newevent, int slot, float weight)
{
if (animnum == -1) {
if (newevent) {
PostEvent(newevent, level.frametime);
}
if (animnum == -1 && newevent) {
PostEvent(newevent, level.frametime);
}
NewAnim(animnum, slot);
@@ -311,7 +432,7 @@ void Animate::NewAnim(int animnum, Event *newevent, int slot, float weight)
void Animate::NewAnim(const char *animname, int slot, float weight)
{
int animnum = gi.Anim_Random(edict->tiki, animname);
int animnum = gi.Anim_NumForName(edict->tiki, animname);
if (animnum != -1) {
NewAnim(animnum, slot);
@@ -320,19 +441,25 @@ void Animate::NewAnim(const char *animname, int slot, float weight)
void Animate::NewAnim(const char *animname, Event *endevent, int slot, float weight)
{
int animnum = gi.Anim_Random(edict->tiki, animname);
int animnum = gi.Anim_NumForName(edict->tiki, animname);
if (animnum != -1) {
NewAnim(animnum, endevent, slot);
NewAnim(animnum, slot, weight);
SetAnimDoneEvent(endevent, slot);
} else if (endevent) {
PostEvent(endevent, level.frametime);
}
}
void Animate::NewAnim(const char *animname, Event& endevent, int slot, float weight)
{
int animnum = gi.Anim_Random(edict->tiki, animname);
int animnum = gi.Anim_NumForName(edict->tiki, animname);
if (animnum != -1) {
NewAnim(animnum, endevent, slot);
NewAnim(animnum, slot, weight);
SetAnimDoneEvent(endevent, slot);
} else {
PostEvent(endevent, level.frametime);
}
}
@@ -403,7 +530,8 @@ void Animate::DoExitCommands(int slot)
int ii, j;
for (ii = 0; ii < cmds.num_cmds; ii++) {
tiki_singlecmd_t& single_cmd = cmds.cmds[ii];
const tiki_singlecmd_t& single_cmd = cmds.cmds[ii];
ev = new AnimationEvent(single_cmd.args[0], single_cmd.num_args);
ev->SetAnimationNumber(edict->s.frameInfo[slot].index);
@@ -417,6 +545,38 @@ void Animate::DoExitCommands(int slot)
}
}
if (gi.Frame_Commands_Client(edict->tiki, edict->s.frameInfo[slot].index, TIKI_FRAME_EXIT, &cmds)) {
size_t longest = GetLongestClientCmdLength(cmds);
if (longest) {
char *cmdName = (char *)alloca(longest + 8 + 1);
int ii, j;
for (ii = 0; ii < cmds.num_cmds; ii++) {
const tiki_singlecmd_t& single_cmd = cmds.cmds[ii];
int eventNum;
strcpy(cmdName, "_client_");
strcpy(cmdName + 8, single_cmd.args[0]);
eventNum = Event::FindEventNum(cmdName);
AnimationEvent ev(eventNum, single_cmd.num_args);
if (!ev.eventnum) {
continue;
}
ev.SetAnimationNumber(edict->s.frameInfo[slot].index);
ev.SetAnimationFrame(0);
for (j = 1; j < single_cmd.num_args; j++) {
ev.AddToken(single_cmd.args[j]);
}
PostEvent(ev, 0);
}
}
}
animFlags[slot] |= ANIM_NOEXIT;
}
@@ -465,12 +625,12 @@ void Animate::PreAnimate(void)
void Animate::PostAnimate(void)
{
float startTime;
float deltaSyncTime;
float total_weight;
float total_angular_delta;
Vector vFrameDelta;
bool hasAction = false;
float startTime;
float deltaSyncTime;
float total_weight;
float total_angular_delta;
Vector vFrameDelta;
bool hasAction = false;
if (!edict->tiki) {
return;
@@ -482,14 +642,12 @@ void Animate::PostAnimate(void)
syncTime = 1.0f / syncRate * level.frametime + deltaSyncTime;
}
total_weight = 0;
total_weight = 0;
total_angular_delta = 0;
for (int i = 0; i < MAX_FRAMEINFOS; i++) {
if (edict->s.frameInfo[i].weight > 0.0f) {
if (!(animFlags[i] & ANIM_NOACTION)) {
hasAction = true;
}
if (edict->s.frameInfo[i].weight > 0.0f && !(animFlags[i] & ANIM_NOACTION)) {
hasAction = true;
}
if (animFlags[i] & ANIM_PAUSED) {
@@ -509,84 +667,88 @@ void Animate::PostAnimate(void)
animFlags[i] |= ANIM_FINISHED;
RestartAnimSlot(i);
} else {
if (!(animFlags[i] & ANIM_NODELTA)) {
if (gi.Anim_HasDelta(edict->tiki, edict->s.frameInfo[i].index)) {
float vDelta[3];
float angleDelta;
if (!(animFlags[i] & ANIM_NODELTA) && gi.Anim_HasDelta(edict->tiki, edict->s.frameInfo[i].index)) {
vec3_t vDelta;
float angleDelta;
//
// Get the animation's delta position from start time
//
gi.Anim_DeltaOverTime(edict->tiki, edict->s.frameInfo[i].index, startTime, edict->s.frameInfo[i].time, vDelta);
vFrameDelta += Vector(vDelta) * edict->s.frameInfo[i].weight;
total_weight += edict->s.frameInfo[i].weight;
//
// Get the animation's delta position from start time
//
gi.Anim_DeltaOverTime(
edict->tiki, edict->s.frameInfo[i].index, startTime, edict->s.frameInfo[i].time, vDelta
);
VectorScale(vDelta, edict->s.frameInfo[i].weight, vDelta);
vFrameDelta += vDelta;
total_weight += edict->s.frameInfo[i].weight;
//
// Get the animation's delta angle from start time
//
gi.Anim_AngularDeltaOverTime(edict->tiki, edict->s.frameInfo[i].index, startTime, edict->s.frameInfo[i].time, &angleDelta);
total_angular_delta += angleDelta * edict->s.frameInfo[i].weight;
}
//
// Get the animation's delta angle from start time
//
gi.Anim_AngularDeltaOverTime(
edict->tiki, edict->s.frameInfo[i].index, startTime, edict->s.frameInfo[i].time, &angleDelta
);
angleDelta *= edict->s.frameInfo[i].weight;
total_angular_delta += angleDelta;
}
animFlags[i] &= ~ANIM_NODELTA;
float animTime;
if (animFlags[i] & ANIM_SYNC) {
animTime = animtimes[i];
if (edict->s.frameInfo[i].time < animtimes[i]) {
continue;
}
} else {
animTime = animtimes[i] - 0.01f;
}
if (edict->s.frameInfo[i].time >= animTime) {
if (animFlags[i] & ANIM_LOOP) {
animFlags[i] |= ANIM_FINISHED;
do {
edict->s.frameInfo[i].time -= animtimes[i];
} while (edict->s.frameInfo[i].time >= animtimes[i]);
if (edict->s.frameInfo[i].time < 0) {
edict->s.frameInfo[i].time = 0;
}
} else {
if (startTime != animtimes[i]) {
animFlags[i] |= ANIM_FINISHED;
}
edict->s.frameInfo[i].time = animtimes[i];
if (edict->s.frameInfo[i].time < (animtimes[i] - 0.01f)) {
continue;
}
}
}
if (total_weight) {
vFrameDelta *= 1.f / total_weight;
total_angular_delta *= 1.f / total_weight;
}
if (IsRepeatType(i)) {
animFlags[i] |= ANIM_FINISHED;
MatrixTransformVector(vFrameDelta, orientation, frame_delta);
angular_delta = total_angular_delta;
do {
edict->s.frameInfo[i].time -= animtimes[i];
} while (edict->s.frameInfo[i].time >= animtimes[i]);
while (syncTime > 1.0f) {
syncTime -= 1.0f;
}
if (edict->s.frameInfo[i].time < 0) {
edict->s.frameInfo[i].time = 0;
}
total_weight = level.frametime * 4.0f;
} else {
if (startTime != animtimes[i]) {
animFlags[i] |= ANIM_FINISHED;
}
if (hasAction) {
edict->s.actionWeight += total_weight;
if (edict->s.actionWeight > 1.0f) {
edict->s.actionWeight = 1.0f;
edict->s.frameInfo[i].time = animtimes[i];
}
} else {
edict->s.actionWeight -= total_weight;
}
}
if (edict->s.actionWeight < 0.0f) {
edict->s.actionWeight = 0.0f;
}
if (total_weight) {
vFrameDelta *= 1.f / total_weight;
total_angular_delta *= 1.f / total_weight;
}
MatrixTransformVector(vFrameDelta, orientation, frame_delta);
angular_delta = total_angular_delta;
while (syncTime >= 1.0f) {
syncTime -= 1.0f;
}
total_weight = level.frametime * 4.0f;
if (hasAction) {
edict->s.actionWeight += total_weight;
if (edict->s.actionWeight > 1.0f) {
edict->s.actionWeight = 1.0f;
}
} else {
edict->s.actionWeight -= total_weight;
if (edict->s.actionWeight < 0.0f) {
edict->s.actionWeight = 0.0f;
}
}
}
@@ -630,8 +792,8 @@ void Animate::Pause(int slot, int pause)
if (pause) {
animFlags[slot] |= ANIM_PAUSED;
} else {
if ((animFlags[slot] & ANIM_PAUSED)) {
if ((animFlags[slot] & ANIM_SYNC)) {
if (animFlags[slot] & ANIM_PAUSED) {
if (animFlags[slot] & ANIM_SYNC) {
SlotChanged(animFlags[slot]);
}
@@ -643,14 +805,14 @@ void Animate::Pause(int slot, int pause)
void Animate::UseSyncTime(int slot, int sync)
{
if (sync) {
if (animFlags[slot] & ANIM_SYNC) {
return;
if (!(animFlags[slot] & ANIM_SYNC)) {
animFlags[slot] |= ANIM_SYNC;
SlotChanged(slot);
}
animFlags[slot] = (animFlags[slot] | (ANIM_SYNC | ANIM_NODELTA)) & ~ANIM_FINISHED;
} else {
if (animFlags[slot] & ANIM_SYNC) {
animFlags[slot] = (animFlags[slot] | ANIM_NODELTA) & ~(ANIM_FINISHED | ANIM_SYNC);
animFlags[slot] &= ~ANIM_SYNC;
SlotChanged(slot);
}
}
}
@@ -880,6 +1042,11 @@ void Animate::DumpAnimInfo(void)
MPrintf("actionWeight: %f\n", edict->s.actionWeight);
}
void Animate::ClientSound(Event *ev)
{
PlayNonPvsSound(ev->GetString(1));
}
void Animate::EventPauseAnim(Event *ev)
{
is_paused = ev->GetInteger(1) ? true : false;
+9 -8
View File
@@ -21,8 +21,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// animate.h -- Animate class
#ifndef __ANIMATE_H__
#define __ANIMATE_H__
#pragma once
#if defined(GAME_DLL)
# include "entity.h"
@@ -132,6 +131,8 @@ public:
virtual void DumpAnimInfo();
void SlotChanged(int slot);
void ClientSound(Event *ev);
// FIXME: delete this, fakk2 remnant
int NumFrames(int slot = 0);
};
@@ -168,22 +169,24 @@ inline void Animate::PauseSyncTime(int pause)
inline void Animate::Archive(Archiver& arc)
{
int i;
Entity::Archive(arc);
for (int i = MAX_FRAMEINFOS - 1; i >= 0; i--) {
for (i = 0; i < MAX_FRAMEINFOS; i++) {
arc.ArchiveInteger(&animFlags[i]);
}
arc.ArchiveFloat(&syncTime);
arc.ArchiveFloat(&syncRate);
arc.ArchiveInteger(&pauseSyncTime);
arc.ArchiveBool(&is_paused);
for (int i = MAX_FRAMEINFOS - 1; i >= 0; i--) {
for (i = 0; i < MAX_FRAMEINFOS; i++) {
arc.ArchiveEventPointer(&doneEvents[i]);
}
for (int i = MAX_FRAMEINFOS - 1; i >= 0; i--) {
for (i = 0; i < MAX_FRAMEINFOS; i++) {
arc.ArchiveFloat(&animtimes[i]);
}
for (int i = MAX_FRAMEINFOS - 1; i >= 0; i--) {
for (i = 0; i < MAX_FRAMEINFOS; i++) {
arc.ArchiveFloat(&frametimes[i]);
}
arc.ArchiveVector(&frame_delta);
@@ -209,5 +212,3 @@ inline int Animate::NumFrames(int slot)
{
return gi.Anim_NumFrames(edict->tiki, edict->s.frameInfo[slot].index);
}
#endif /* animate.h */
+8 -1
View File
@@ -29,13 +29,20 @@ CLASS_DECLARATION(Event, AnimationEvent, NULL) {
{NULL, NULL}
};
AnimationEvent::AnimationEvent(str command, int numArgs)
AnimationEvent::AnimationEvent(const char* command, int numArgs)
: Event(command, numArgs)
{
anim_number = 0;
anim_frame = 0;
}
AnimationEvent::AnimationEvent(int eventNum, int numArgs)
: Event(eventNum, numArgs)
{
anim_number = 0;
anim_frame = 0;
}
AnimationEvent::AnimationEvent(const Event& ev)
: Event(ev)
{
+2 -1
View File
@@ -35,7 +35,8 @@ public:
void *operator new(size_t size);
void operator delete(void *ptr);
AnimationEvent(str command, int numArgs = 0);
AnimationEvent(const char* command, int numArgs = 0);
AnimationEvent(int eventNum, int numArgs = 0);
AnimationEvent(const Event& ev);
AnimationEvent();
+880 -1011
View File
File diff suppressed because it is too large. Load diff
+235 -300
View File
@@ -30,382 +30,317 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "str.h"
#include "vector.h"
#define ARCHIVE_NULL_POINTER ( -654321 )
#define ARCHIVE_POINTER_VALID ( 0 )
#define ARCHIVE_POINTER_NULL ( ARCHIVE_NULL_POINTER )
#define ARCHIVE_POINTER_SELF_REFERENTIAL ( -123456 )
#define ARCHIVE_NULL_POINTER (-654321)
#define ARCHIVE_POINTER_VALID (0)
#define ARCHIVE_POINTER_NULL (ARCHIVE_NULL_POINTER)
#define ARCHIVE_POINTER_SELF_REFERENTIAL (-123456)
#define ARCHIVE_USE_TYPES
#define ARCHIVE_WRITE 0
#define ARCHIVE_READ 1
typedef enum {
ARCHIVE_NONE,
ARCHIVE_WRITE,
ARCHIVE_READ
} archivemode_e;
enum
{
pointer_fixup_normal,
pointer_fixup_safe
enum {
pointer_fixup_ptr,
pointer_fixup_normal,
pointer_fixup_safe
};
typedef struct
{
void **ptr;
int index;
int type;
typedef struct {
void **ptr;
int index;
int type;
} pointer_fixup_t;
using fileSize_t = uint32_t;
class FileRead : public Class
class ArchiveFile
{
protected:
str filename;
size_t length;
byte *buffer;
byte *pos;
str filename;
size_t length;
byte *buffer;
byte *pos;
size_t bufferlength;
bool writing;
bool opened;
public:
CLASS_PROTOTYPE( FileRead );
FileRead();
~FileRead();
void Close( bool bDoCompression = false );
const char *Filename( void );
size_t Length( void );
size_t Pos( void );
qboolean Seek( size_t newpos );
qboolean Open( const char *name );
qboolean Read( void *dest, size_t size );
ArchiveFile();
~ArchiveFile();
void Close();
const char *Filename(void);
qboolean Compress();
size_t Length(void);
size_t Pos(void);
size_t Tell(void);
qboolean Seek(size_t newpos);
qboolean OpenRead(const char *name);
qboolean OpenWrite(const char *name);
qboolean Read(void *dest, size_t size);
qboolean Write(const void *source, size_t size);
};
class Archiver : public Class
class Archiver
{
private:
Container<Class *> classpointerList;
Container<pointer_fixup_t *> fixupList;
Container<LightClass *> classpointerList;
Container<pointer_fixup_t *> fixupList;
protected:
str filename;
qboolean fileerror;
fileHandle_t file;
FileRead readfile;
int archivemode;
int numclassespos;
qboolean harderror;
size_t m_iNumBytesIO;
qboolean silent;
str filename;
qboolean fileerror;
ArchiveFile archivefile;
int archivemode;
int numclassespos;
qboolean harderror;
size_t m_iNumBytesIO;
qboolean silent;
void CheckRead( void );
void CheckType( int type );
int ReadType( void );
fileSize_t ReadSize( void );
void CheckSize( int type, fileSize_t size );
void ArchiveData( int type, void *data, size_t size );
void CheckRead(void);
void CheckType(int type);
int ReadType(void);
fileSize_t ReadSize(void);
void CheckSize(int type, fileSize_t size);
void ArchiveData(int type, void *data, size_t size);
void CheckWrite( void );
void WriteType( int type );
void WriteSize(fileSize_t size );
void CheckWrite(void);
void WriteType(int type);
void WriteSize(fileSize_t size);
public:
CLASS_PROTOTYPE( Archiver );
Archiver();
~Archiver();
void FileError(const char *fmt, ...);
void Close(void);
Archiver();
~Archiver();
void FileError( const char *fmt, ... );
void Close( void );
qboolean Read(str& name, qboolean harderror = qtrue);
qboolean Read(const char *name, qboolean harderror = qtrue);
Class *ReadObject(void);
qboolean Read( str &name, qboolean harderror = qtrue );
qboolean Read( const char *name, qboolean harderror = qtrue );
Class *ReadObject( void );
qboolean Create(str& name, qboolean harderror = qtrue);
qboolean Create(const char *name, qboolean harderror = qtrue);
qboolean Create( str &name, qboolean harderror = qtrue );
qboolean Create( const char *name, qboolean harderror = qtrue );
qboolean Loading(void);
qboolean Saving(void);
qboolean NoErrors(void);
qboolean Loading( void );
qboolean Saving( void );
qboolean NoErrors( void );
void ArchiveVector(Vector *vec);
void ArchiveQuat(Quat *quat);
void ArchiveInteger(int *num);
void ArchiveUnsigned(unsigned *unum);
void ArchiveSize(long *unum);
void ArchiveByte(byte *num);
void ArchiveChar(char *ch);
void ArchiveShort(short *num);
void ArchiveUnsignedShort(unsigned short *num);
void ArchiveFloat(float *num);
void ArchiveDouble(double *num);
void ArchiveBoolean(qboolean *boolean);
void ArchiveString(str *string);
void ArchiveObjectPointer(LightClass **ptr);
void ArchiveObjectPointer(Class **ptr);
void ArchiveObjectPosition(LightClass *obj);
void ArchiveSafePointer(SafePtrBase *ptr);
void ArchiveEventPointer(Event **ev);
void ArchiveBool(bool *boolean);
void ArchivePosition(int *pos);
void ArchiveSvsTime(int *time);
void ArchiveVec2(vec2_t vec);
void ArchiveVec3(vec3_t vec);
void ArchiveVec4(vec4_t vec);
void ArchiveVector( Vector * vec );
void ArchiveQuat( Quat * quat );
void ArchiveInteger( int * num );
void ArchiveUnsigned( unsigned * unum );
void ArchiveSize( long * unum );
void ArchiveByte( byte * num );
void ArchiveChar( char * ch );
void ArchiveShort( short * num );
void ArchiveUnsignedShort( unsigned short * num );
void ArchiveFloat( float * num );
void ArchiveDouble( double * num );
void ArchiveBoolean( qboolean * boolean );
void ArchiveString( str * string );
void ArchiveConfigString( int cs );
void ArchiveObjectPointer( Class ** ptr );
void ArchiveObjectPosition( void *obj );
void ArchiveSafePointer( SafePtrBase * ptr );
void ArchiveEventPointer( Event ** ev );
void ArchiveBool( bool * boolean );
void ArchivePosition( int * pos );
void ArchiveSvsTime( int * time );
void ArchiveVec2( vec2_t vec );
void ArchiveVec3( vec3_t vec );
void ArchiveVec4( vec4_t vec );
void ArchiveRaw(void *data, size_t size);
void ArchiveObject(Class *obj);
void ArchiveRaw( void *data, size_t size );
void ArchiveObject( Class *obj );
qboolean ObjectPositionExists(void *obj);
qboolean ObjectPositionExists( void * obj );
void SetSilent( bool bSilent );
void Reset();
size_t Counter() const;
void ArchiveConfigString(int cs);
void SetSilent(bool bSilent);
};
inline qboolean Archiver::Read
(
str &name,
qboolean harderror
)
template<class Type>
inline void Container<Type>::Archive(Archiver& arc, void (*ArchiveFunc)(Archiver& arc, Type *obj))
{
return Read( name.c_str(), harderror );
}
int num;
int i;
inline qboolean Archiver::Create
(
str &name,
qboolean harderror
)
{
return Create( name.c_str(), harderror );
}
if (arc.Loading()) {
arc.ArchiveInteger(&num);
Resize(num);
} else {
num = numobjects;
arc.ArchiveInteger(&num);
}
inline qboolean Archiver::Loading
(
void
)
{
return (archivemode == ARCHIVE_READ) ? qtrue : qfalse;
}
for (i = 1; i <= num; i++) {
if (num > numobjects) {
numobjects = num;
}
inline qboolean Archiver::Saving
(
void
)
{
return (archivemode == ARCHIVE_WRITE) ? qtrue : qfalse;
}
inline qboolean Archiver::NoErrors
(
void
)
{
return fileerror ? qfalse : qtrue;
}
template< class Type >
inline void Container<Type>::Archive
(
Archiver& arc,
void( *ArchiveFunc )( Archiver& arc, Type *obj )
)
{
int num;
int i;
if( arc.Loading() )
{
arc.ArchiveInteger( &num );
Resize( num );
}
else
{
num = numobjects;
arc.ArchiveInteger( &num );
}
for( i = 1; i <= num; i++ )
{
if( num > numobjects ) {
numobjects = num;
}
ArchiveFunc( arc, &objlist[ i - 1 ] );
}
ArchiveFunc(arc, &objlist[i - 1]);
}
}
template<>
inline void Container<str>::Archive
(
Archiver &arc
)
inline void Container<str>::Archive(Archiver& arc)
{
int i, num;
int i, num;
if( arc.Loading() )
{
ClearObjectList();
arc.ArchiveInteger( &num );
Resize( num );
}
else
{
num = numobjects;
arc.ArchiveInteger( &num );
}
for( i = 1; i <= num; i++ )
{
arc.ArchiveString( AddressOfObjectAt( i ) );
}
if (arc.Loading()) {
ClearObjectList();
arc.ArchiveInteger(&num);
Resize(num);
} else {
num = numobjects;
arc.ArchiveInteger(&num);
}
for (i = 1; i <= num; i++) {
arc.ArchiveString(AddressOfObjectAt(i));
}
}
template<>
inline void Container<Vector>::Archive
(
Archiver &arc
)
inline void Container<Vector>::Archive(Archiver& arc)
{
int i, num;
int i, num;
if( arc.Loading() )
{
ClearObjectList();
arc.ArchiveInteger( &num );
Resize( num );
}
else
{
num = numobjects;
arc.ArchiveInteger( &num );
}
for( i = 1; i <= num; i++ )
{
arc.ArchiveVector( AddressOfObjectAt( i ) );
}
if (arc.Loading()) {
ClearObjectList();
arc.ArchiveInteger(&num);
Resize(num);
} else {
num = numobjects;
arc.ArchiveInteger(&num);
}
for (i = 1; i <= num; i++) {
arc.ArchiveVector(AddressOfObjectAt(i));
}
}
template<>
inline void Container<int>::Archive
(
Archiver &arc
)
inline void Container<int>::Archive(Archiver& arc)
{
int i, num;
int i, num;
if( arc.Loading() )
{
ClearObjectList();
arc.ArchiveInteger( &num );
Resize( num );
}
else
{
num = numobjects;
arc.ArchiveInteger( &num );
}
for( i = 1; i <= num; i++ )
{
arc.ArchiveInteger( AddressOfObjectAt( i ) );
}
if (arc.Loading()) {
ClearObjectList();
arc.ArchiveInteger(&num);
Resize(num);
} else {
num = numobjects;
arc.ArchiveInteger(&num);
}
for (i = 1; i <= num; i++) {
arc.ArchiveInteger(AddressOfObjectAt(i));
}
}
template<>
inline void Container<float>::Archive
(
Archiver &arc
)
inline void Container<float>::Archive(Archiver& arc)
{
int i, num;
int i, num;
if( arc.Loading() )
{
ClearObjectList();
arc.ArchiveInteger( &num );
Resize( num );
}
else
{
num = numobjects;
arc.ArchiveInteger( &num );
}
for( i = 1; i <= num; i++ )
{
arc.ArchiveFloat( AddressOfObjectAt( i ) );
}
if (arc.Loading()) {
ClearObjectList();
arc.ArchiveInteger(&num);
Resize(num);
} else {
num = numobjects;
arc.ArchiveInteger(&num);
}
for (i = 1; i <= num; i++) {
arc.ArchiveFloat(AddressOfObjectAt(i));
}
}
template< typename c >
inline void ArchiveClass
(
Archiver& arc,
c *obj
)
template<typename c>
inline void ArchiveClass(Archiver& arc, c *obj)
{
arc.ArchiveObject( obj );
arc.ArchiveObject(obj);
}
template<typename Type>
void Container<Type>::Archive(Archiver& arc)
{
Archive(arc, ArchiveClass<Type>);
}
#ifndef NO_ARCHIVE
template< typename key, typename value >
void con_set< key, value >::Archive
(
Archiver& arc
)
template<typename key, typename value>
void con_set<key, value>::Archive(Archiver& arc)
{
Entry *e;
int hash;
int i;
Entry *e = NULL;
int hash;
int i;
arc.ArchiveUnsigned( &tableLength );
arc.ArchiveUnsigned( &threshold );
arc.ArchiveUnsigned( &count );
arc.ArchiveUnsignedShort( &tableLengthIndex );
arc.ArchiveUnsigned(&tableLength);
arc.ArchiveUnsigned(&threshold);
arc.ArchiveUnsigned(&count);
arc.ArchiveUnsignedShort(&tableLengthIndex);
if( arc.Loading() )
{
if( tableLength != 1 )
{
table = new Entry *[ tableLength ]();
memset( table, 0, tableLength * sizeof( Entry * ) );
}
if (arc.Loading()) {
if (tableLength != 1) {
table = new Entry *[tableLength]();
memset(table, 0, tableLength * sizeof(Entry *));
}
for( i = 0; i < count; i++ )
{
e = new Entry;
e->Archive( arc );
for (i = 0; i < count; i++) {
e = new Entry;
e->Archive(arc);
hash = HashCode< key >( e->key ) % tableLength;
hash = HashCode<key>(e->GetKey()) % tableLength;
e->next = table[ hash ];
table[ hash ] = e;
}
}
else
{
for( i = tableLength - 1; i >= 0; i-- )
{
for( e = table[ i ]; e != NULL; e = e->next )
{
e->Archive( arc );
}
}
}
e->next = table[hash];
table[hash] = e;
}
defaultEntry = e;
} else {
#ifndef NDEBUG
int total;
total = 0;
for (i = 0; i < tableLength; i++) {
for (e = table[i]; e != NULL; e = e->next) {
e->Archive(arc);
total++;
}
}
// it must match the number of elements
assert(total == count);
#else
for (i = 0; i < tableLength; i++) {
for (e = table[i]; e != NULL; e = e->next) {
e->Archive(arc);
}
}
#endif
}
}
template< typename key, typename value >
void con_map< key, value >::Archive
(
Archiver& arc
)
template<typename key, typename value>
void con_map<key, value>::Archive(Archiver& arc)
{
m_con_set.Archive( arc );
m_con_set.Archive(arc);
}
#endif
#define ArchiveEnum( thing, type ) \
{ \
int tempInt; \
\
tempInt = ( int )( thing ); \
arc.ArchiveInteger( &tempInt ); \
( thing ) = ( type )tempInt; \
}
#define ArchiveEnum(thing, type) \
{ \
int tempInt; \
\
tempInt = (int)(thing); \
arc.ArchiveInteger(&tempInt); \
(thing) = (type)tempInt; \
}
#endif // __ARCHIVE_H__
+14 -13
View File
@@ -26,6 +26,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include "beam.h"
#include "../qcommon/qfiles.h"
#include "game.h"
#include <utility>
/*****************************************************************************/
/*QUAKED func_beam (0 0.25 .5) (-8 -8 -8) (8 8 8) START_ON PERSIST WAVE NOISE
@@ -765,19 +766,19 @@ void FuncBeam::Activate
}
void FuncBeam::UpdateEndpoint
(
Event *ev
)
(
Event* ev
)
{
if ( end )
{
Event *ev1 = new Event( ev );
{
if (end)
{
Event* ev1 = new Event(std::move(*ev));
VectorCopy( end->origin, edict->s.origin2 );
PostEvent( ev1, level.frametime );
}
}
VectorCopy(end->origin, edict->s.origin2);
PostEvent(ev1, level.frametime);
}
}
void FuncBeam::UpdateOrigin
(
@@ -786,8 +787,8 @@ void FuncBeam::UpdateOrigin
{
if ( origin_target )
{
Event *ev1 = new Event( ev );
{
Event* ev1 = new Event(std::move(*ev));
setOrigin( origin_target->centroid );
PostEvent( ev1, level.frametime );
+3
View File
@@ -76,6 +76,9 @@ extern float pm_friction;
extern float pm_waterfriction;
extern float pm_flightfriction;
extern const vec3_t MINS;
extern const vec3_t MAXS;
extern int c_pmove;
void PM_ClipVelocity( vec3_t in, vec3_t normal, vec3_t out, float overbounce );
+12 -4
View File
@@ -48,6 +48,9 @@ float pm_backspeed = 0.80f;
float pm_flightfriction = 3.0f;
float PM_NOCLIPfriction = 5.0f;
const vec3_t MINS = { -15, -15, 0 };
const vec3_t MAXS = { 15, 15, 94 };
int c_pmove = 0;
/*
@@ -1520,22 +1523,27 @@ void PmoveSingle( pmove_t *pmove )
{
float fLeanAngle = pml.frametime * -pm->leanSpeed;
if( fAngle <= fLeanAngle )
{
if(fLeanAngle >= fAngle) {
fLeanAngle = fAngle;
}
pm->ps->fLeanAngle -= fLeanAngle;
if (pm->ps->fLeanAngle > 0) {
pm->ps->fLeanAngle = 0;
}
}
else
{
float fLeanAngle = pml.frametime * pm->leanSpeed;
if(fAngle >= fLeanAngle) {
if(fLeanAngle <= fAngle) {
fLeanAngle = fAngle;
}
pm->ps->fLeanAngle -= fLeanAngle;
pm->ps->fLeanAngle -= fLeanAngle;
if (pm->ps->fLeanAngle < 0) {
pm->ps->fLeanAngle = 0;
}
}
}
+154 -197
View File
@@ -25,34 +25,25 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
// because games can change separately from the main system version, we need a
// second version that must match between game and cgame
#ifndef __BG_PUBLIC_H__
#define __BG_PUBLIC_H__
#pragma once
#define GAME_VERSION "mohaa-base-1"
#define GAME_VERSION "mohaa-base-1"
#define DEFAULT_GRAVITY 800
static const unsigned int MINS_X = -15;
static const unsigned int MINS_Y = -15;
static const unsigned int MINS_Z = 0; // IneQuation: bounding box and viewheights to match MoHAA
static const unsigned int MAXS_X = 15;
static const unsigned int MAXS_Y = 15;
static const unsigned int MAXS_Z = 96;
#define SCORE_NOT_PRESENT -9999 // for the CS_SCORES[12] when only one player is present
#define VOTE_TIME 30000 // 30 seconds before vote times out
#define MINS_Z 0
#define MINS_X -15
#define MINS_Y -15
#define MAXS_X 15
#define MAXS_Y 15
#define MINS_Z 0 // IneQuation: bounding box and viewheights to match MoHAA
#define MAXS_Z 96
#define DEAD_MINS_Z 32
#define CROUCH_MAXS_Z 49
#define DEFAULT_VIEWHEIGHT 82
#define CROUCH_RUN_VIEWHEIGHT 64
#define JUMP_START_VIEWHEIGHT 52
#define CROUCH_VIEWHEIGHT 48
#define PRONE_VIEWHEIGHT 16
#define DEAD_VIEWHEIGHT 8
static const unsigned int DEAD_MINS_Z = 32;
static const unsigned int CROUCH_MAXS_Z = 49;
static const unsigned int DEFAULT_VIEWHEIGHT = 82;
static const unsigned int CROUCH_RUN_VIEWHEIGHT = 64;
static const unsigned int JUMP_START_VIEWHEIGHT = 52;
static const unsigned int CROUCH_VIEWHEIGHT = 48;
static const unsigned int PRONE_VIEWHEIGHT = 16;
static const unsigned int DEAD_VIEWHEIGHT = 8;
//
// config strings are a general means of communicating variable length strings
@@ -140,10 +131,10 @@ extern "C" {
GT_MAX_GAME_TYPE
} gametype_t;
//
// scale to use when evaluating entityState_t::constantLight scale
//
#define CONSTANTLIGHT_RADIUS_SCALE 8
//
// scale to use when evaluating entityState_t::constantLight scale
//
static const float CONSTANTLIGHT_RADIUS_SCALE = 8;
typedef enum {
GENDER_MALE,
@@ -151,30 +142,31 @@ extern "C" {
GENDER_NEUTER
} gender_t;
// su44: vma indexes are sent as 4 bits
// see playerState_t::iViewModelAnim
typedef enum {
VMA_IDLE,
VMA_CHARGE,
VMA_FIRE,
VMA_FIRE_SECONDARY,
VMA_RECHAMBER,
VMA_RELOAD,
VMA_RELOAD_SINGLE,
VMA_RELOAD_END,
VMA_PULLOUT,
VMA_PUTAWAY,
VMA_LADDERSTEP,
VMA_ENABLE,
VMA_CUSTOMANIMATION,
VMA_NUMANIMATIONS
} viewmodelanim_t;
enum vmAnim_e {
VM_ANIM_DISABLED,
VM_ANIM_IDLE,
VM_ANIM_CHARGE,
VM_ANIM_FIRE,
VM_ANIM_FIRE_SECONDARY,
VM_ANIM_RECHAMBER,
VM_ANIM_RELOAD,
VM_ANIM_RELOAD_SINGLE,
VM_ANIM_RELOAD_END,
VM_ANIM_PULLOUT,
VM_ANIM_PUTAWAY,
VM_ANIM_LADDERSTEP,
VM_ANIM_IDLE_0,
VM_ANIM_IDLE_1,
VM_ANIM_IDLE_2,
};
// su44: playerState_t::activeItems[8] slots
// they are sent as 16 bits
// TODO: find out rest of them
#define ITEM_AMMO 0 // current ammo
#define ITEM_WEAPON 1 // current mainhand weapon
// su44: playerState_t::activeItems[8] slots
// they are sent as 16 bits
// TODO: find out rest of them
enum itemtype_e {
ITEM_AMMO,
ITEM_WEAPON
};
/*
===================================================================================
@@ -187,17 +179,12 @@ movement on the server game.
===================================================================================
*/
#define MAX_CLIP_PLANES 5
#define MIN_WALK_NORMAL 0.7f // can't walk on very steep slopes
static const unsigned int MAX_CLIP_PLANES = 5;
static const float MIN_WALK_NORMAL = 0.7f; // can't walk on very steep slopes
#define STEPSIZE 18
static const float STEPSIZE = 18;
#define WATER_TURBO_SPEED 1.35f
#define WATER_TURBO_TIME 1200
#define MINIMUM_RUNNING_TIME 800
#define MINIMUM_WATER_FOR_TURBO 90
#define OVERCLIP 1.001f
static const float OVERCLIP = 1.001f;
// su44: our pmtype_t enum must be the same
// as in MoHAA, because playerState_t::pm_type
@@ -251,8 +238,9 @@ movement on the server game.
#endif
// moh pm_flags
#define PMF_DUCKED (1 << 0)
#define PMF_VIEW_PRONE (1 << 1)
#define PMF_DUCKED (1 << 0)
#define PMF_VIEW_PRONE (1 << 1)
#define PMF_DAMAGE_ANGLES (1 << 1) // in protocol >= 15
//
// 2 Flags removed in team tactics
//
@@ -272,22 +260,25 @@ movement on the server game.
#define PMF_UNKNOWN (1 << 14)
#define PMF_NO_LEAN (1 << 15)
// moveposflags
#define MPF_POSITION_STANDING (1 << 0)
#define MPF_POSITION_CROUCHING (1 << 1)
#define MPF_POSITION_PRONE (1 << 2)
#define MPF_POSITION_OFFGROUND (1 << 3)
// moveposflags
enum moveposflags_e {
MPF_POSITION_STANDING = (1 << 0),
MPF_POSITION_CROUCHING = (1 << 1),
MPF_POSITION_PRONE = (1 << 2),
MPF_POSITION_OFFGROUND = (1 << 3),
MPF_MOVEMENT_WALKING = (1 << 4),
MPF_MOVEMENT_RUNNING = (1 << 5),
MPF_MOVEMENT_FALLING = (1 << 6),
};
#define MPF_MOVEMENT_WALKING (1 << 4)
#define MPF_MOVEMENT_RUNNING (1 << 5)
#define MPF_MOVEMENT_FALLING (1 << 6)
#define MAXTOUCH 32
#define MAXTOUCH 32
#define MOVERESULT_NONE 0 // nothing blocking
#define MOVERESULT_TURNED 1 // move blocked, but player turned to avoid it
#define MOVERESULT_BLOCKED 2 // move blocked by slope or wall
#define MOVERESULT_HITWALL 3 // player ran into wall
enum moveresult_e {
MOVERESULT_NONE, // nothing blocking
MOVERESULT_TURNED, // move blocked, but player turned to avoid it
MOVERESULT_BLOCKED, // move blocked by slope or wall
MOVERESULT_HITWALL // player ran into wall
};
typedef struct {
// state (in / out)
@@ -339,7 +330,7 @@ movement on the server game.
//
// Openmohaa addition
//
int protocol;
int protocol;
float leanSpeed;
float leanRecoverSpeed;
float leanAdd;
@@ -359,35 +350,33 @@ movement on the server game.
//===================================================================================
#define MAX_LETTERBOX_SIZE 0x7fff
static const unsigned int MAX_LETTERBOX_SIZE = 0x7fff;
#define ITEM_NAME_AMMO 0
#define ITEM_NAME_WEAPON 1
#define WEAPON_CLASS_PISTOL (1 << 0)
#define WEAPON_CLASS_RIFLE (1 << 1)
#define WEAPON_CLASS_SMG (1 << 2)
#define WEAPON_CLASS_MG (1 << 3)
#define WEAPON_CLASS_GRENADE (1 << 4)
#define WEAPON_CLASS_HEAVY (1 << 5)
#define WEAPON_CLASS_CANNON (1 << 6)
#define WEAPON_CLASS_ITEM (1 << 7)
#define WEAPON_CLASS_ITEM1 (1 << 8)
#define WEAPON_CLASS_ITEM2 (1 << 9)
#define WEAPON_CLASS_ITEM3 (1 << 10)
#define WEAPON_CLASS_ITEM4 (1 << 11)
#define WEAPON_CLASS_ANY_ITEM \
(WEAPON_CLASS_ITEM | WEAPON_CLASS_ITEM1 | WEAPON_CLASS_ITEM2 | WEAPON_CLASS_ITEM3 | WEAPON_CLASS_ITEM4)
#define WEAPON_CLASS_PRIMARY (!(WEAPON_CLASS_PISTOL | WEAPON_CLASS_GRENADE))
#define WEAPON_CLASS_SECONDARY (WEAPON_CLASS_PISTOL | WEAPON_CLASS_GRENADE)
#define WEAPON_CLASS_THROWABLE (WEAPON_CLASS_GRENADE | WEAPON_CLASS_ITEM)
#define WEAPON_CLASS_MISC \
(WEAPON_CLASS_CANNON | WEAPON_CLASS_ITEM | WEAPON_CLASS_ITEM1 | WEAPON_CLASS_ITEM2 | WEAPON_CLASS_ITEM3 \
| WEAPON_CLASS_ITEM4)
#define WEAPON_CLASS_ITEMINDEX (WEAPON_CLASS_ITEM1 | WEAPON_CLASS_ITEM2 | WEAPON_CLASS_ITEM3 | WEAPON_CLASS_ITEM4)
#define STAT_DEAD_YAW 5 // su44: Is there a DEAD_YAW stat in MoHAA?
enum weaponclass_e {
WEAPON_CLASS_PISTOL = (1 << 0),
WEAPON_CLASS_RIFLE = (1 << 1),
WEAPON_CLASS_SMG = (1 << 2),
WEAPON_CLASS_MG = (1 << 3),
WEAPON_CLASS_GRENADE = (1 << 4),
WEAPON_CLASS_HEAVY = (1 << 5),
WEAPON_CLASS_CANNON = (1 << 6),
WEAPON_CLASS_ITEM = (1 << 7),
WEAPON_CLASS_ITEM1 = (1 << 8),
WEAPON_CLASS_ITEM2 = (1 << 9),
WEAPON_CLASS_ITEM3 = (1 << 10),
WEAPON_CLASS_ITEM4 = (1 << 11),
WEAPON_CLASS_ANY_ITEM =
(WEAPON_CLASS_ITEM | WEAPON_CLASS_ITEM1 | WEAPON_CLASS_ITEM2 | WEAPON_CLASS_ITEM3 | WEAPON_CLASS_ITEM4),
WEAPON_CLASS_ITEM_SLOT_BITS =
(WEAPON_CLASS_ITEM1 | WEAPON_CLASS_ITEM2 | WEAPON_CLASS_ITEM3 | WEAPON_CLASS_ITEM4),
WEAPON_CLASS_PRIMARY = (!(WEAPON_CLASS_PISTOL | WEAPON_CLASS_GRENADE)),
WEAPON_CLASS_SECONDARY = (WEAPON_CLASS_PISTOL | WEAPON_CLASS_GRENADE),
WEAPON_CLASS_THROWABLE = (WEAPON_CLASS_GRENADE | WEAPON_CLASS_ITEM),
WEAPON_CLASS_MISC =
(WEAPON_CLASS_CANNON | WEAPON_CLASS_ITEM | WEAPON_CLASS_ITEM1 | WEAPON_CLASS_ITEM2 | WEAPON_CLASS_ITEM3
| WEAPON_CLASS_ITEM4),
WEAPON_CLASS_ITEMINDEX = (WEAPON_CLASS_ITEM1 | WEAPON_CLASS_ITEM2 | WEAPON_CLASS_ITEM3 | WEAPON_CLASS_ITEM4)
};
// player_state->persistant[] indexes
// these fields are the only part of player_state that isn't
@@ -400,6 +389,7 @@ movement on the server game.
// entityState_t->eFlags
// su44: eFlags used in MoHAA
#define EF_EVERYFRAME 0x00000008
#define EF_CLIMBWALL 0x00000010
#define EF_UNARMED 0x00000020 // su44: this player has his weapon holstered
#define EF_LINKANGLES 0x00000040
@@ -407,6 +397,8 @@ movement on the server game.
#define EF_AXIS 0x00000100 // su44: this player is in axis team
#define EF_ANY_TEAM (EF_ALLIES | EF_AXIS)
#define EF_DEAD 0x00000200 // don't draw a foe marker over players with EF_DEAD
#define EF_NO_LERP 0x00001000 // don't lerp animations
//
// Team assault flags
//
@@ -431,33 +423,11 @@ movement on the server game.
#define EF_AWARD_ASSIST 0x00020000 // draw a assist sprite
#define EF_AWARD_DENIED 0x00040000 // denied
#define EF_TEAMVOTED 0x00080000 // already cast a team vote
#define EF_EVERYFRAME 0x00100000 // def commands will be run every client frame
#define EF_ANTISBJUICE 0x00200000 // anti sucknblow juice
#define EF_DONT_PROCESS_COMMANDS 0x00400000 // don't process client commands for this entity
// these defines could be deleted sometime when code/game/ is cleared of Q3A stuff
#define TEAM_FREE 0
#define TEAM_RED 4
#define TEAM_BLUE 3
#define TEAM_NUM_TEAMS 5
//===================================================================================
// flip the togglebit every time an animation
// changes so a restart of the same anim can be detected
#define ANIM_TOGGLEBIT (1 << 9)
#define ANIM_BLEND (1 << 10)
#define ANIM_NUMBITS 11
// server side anim bits
#define ANIM_SERVER_EXITCOMMANDS_PROCESSED (1 << 12)
#define ANIM_MASK (~(ANIM_TOGGLEBIT | ANIM_BLEND | ANIM_SERVER_EXITCOMMANDS_PROCESSED))
// if FRAME_EXPLICIT is set, don't auto animate
#define FRAME_EXPLICIT 512
#define FRAME_MASK (~FRAME_EXPLICIT)
//
// Tag specific flags
//
@@ -558,8 +528,8 @@ movement on the server game.
STAT_MAXCLIPAMMO,
STAT_INZOOM,
STAT_CROSSHAIR,
STAT_LAST_PAIN,
STAT_NEXTHEALTH, // was unused until 2.0
STAT_LAST_PAIN,
STAT_NEXTHEALTH, // was unused until 2.0
STAT_BOSSHEALTH,
STAT_CINEMATIC,
STAT_ADDFADE,
@@ -570,9 +540,9 @@ movement on the server game.
STAT_OBJECTIVECENTER,
STAT_TEAM,
STAT_KILLS,
STAT_DEATHS,
STAT_VEHICLE_HEALTH, // was unused until 2.0
STAT_VEHICLE_MAX_HEALTH, // was unused until 2.0
STAT_DEATHS,
STAT_VEHICLE_HEALTH, // was unused until 2.0
STAT_VEHICLE_MAX_HEALTH, // was unused until 2.0
STAT_HIGHEST_SCORE,
STAT_ATTACKERCLIENT,
STAT_INFOCLIENT,
@@ -598,9 +568,6 @@ movement on the server game.
SWT_FUSE_WET
} stopWatchType_t;
// How many players on the overlay
#define TEAM_MAXOVERLAY 32
//---------------------------------------------------------
// g_dmflags->integer flags
@@ -635,28 +602,34 @@ movement on the server game.
#define DF_WEAPON_NO_SHOTGUN (1 << 27)
#define DF_WEAPON_NO_LANDMINE (1 << 28)
#define DM_FLAG(flag) (g_gametype->integer && ((int)dmflags->integer & (flag)))
#define DM_FLAG(flag) (g_gametype->integer != GT_SINGLE_PLAYER && ((int)dmflags->integer & (flag)))
// content masks
#define MASK_ALL (-1)
#define MASK_SOLID (CONTENTS_SOLID | CONTENTS_BODY | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP | CONTENTS_BBOX)
#define MASK_ALL (-1)
#define MASK_SOLID \
(CONTENTS_SOLID | CONTENTS_BODY | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP | CONTENTS_BBOX | CONTENTS_FENCE)
#define MASK_SAFESOLID (CONTENTS_BODY | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP | CONTENTS_BBOX)
#define MASK_USABLE (CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_BODY)
#define MASK_PLAYERSOLID \
(CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_BODY | CONTENTS_TRIGGER | CONTENTS_FENCE | CONTENTS_UNKNOWN2 \
| CONTENTS_NOBOTCLIP | CONTENTS_BBOX)
#define MASK_PLAYERSTART (CONTENTS_SOLID|CONTENTS_BBOX|CONTENTS_NOBOTCLIP|CONTENTS_UNKNOWN2|CONTENTS_BODY)
#define MASK_GUNTARGET \
(CONTENTS_SOLID | CONTENTS_LADDER | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_CLAYPIDGEON | CONTENTS_BBOX \
| CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_UNKNOWN3 | CONTENTS_FENCE | CONTENTS_BODY | CONTENTS_CORPSE \
| CONTENTS_TRIGGER)
#define MASK_FOOTSHADOW (CONTENTS_FENCE | CONTENTS_SLIME | CONTENTS_LAVA | CONTENTS_SOLID)
#define MASK_PLAYERSTART (CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_BODY)
#define MASK_VIEWSOLID (CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_FENCE | CONTENTS_TRIGGER)
#define MASK_DEADSOLID (CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_CORPSE | CONTENTS_NOTTEAM2 | CONTENTS_FENCE)
#define MASK_MONSTERSOLID (CONTENTS_SOLID | CONTENTS_MONSTERCLIP | CONTENTS_BODY)
#define MASK_WATER (CONTENTS_WATER | CONTENTS_LAVA | CONTENTS_SLIME)
#define MASK_OPAQUE (CONTENTS_SOLID | CONTENTS_SLIME | CONTENTS_LAVA)
#define MASK_SHOT \
(CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_FENCE \
| CONTENTS_WEAPONCLIP | CONTENTS_BODY | CONTENTS_TRIGGER)
#define MASK_SHOT_TRIG \
(CONTENTS_SOLID | CONTENTS_CLAYPIDGEON | CONTENTS_WATER | CONTENTS_BBOX | CONTENTS_NOBOTCLIP \
| CONTENTS_UNKNOWN2 | CONTENTS_FENCE | CONTENTS_WEAPONCLIP | CONTENTS_BODY | CONTENTS_TRIGGER)
#define MASK_SHOT \
(CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_FENCE | CONTENTS_WEAPONCLIP \
| CONTENTS_BODY | CONTENTS_TRIGGER)
#define MASK_SHOT_TRIG \
(CONTENTS_SOLID | CONTENTS_CLAYPIDGEON | CONTENTS_WATER | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 \
| CONTENTS_FENCE | CONTENTS_WEAPONCLIP | CONTENTS_BODY | CONTENTS_TRIGGER)
#define MASK_PROJECTILE \
(CONTENTS_SOLID | CONTENTS_BODY | CONTENTS_TRIGGER | CONTENTS_FENCE | CONTENTS_WEAPONCLIP | CONTENTS_UNKNOWN2 \
| CONTENTS_NOBOTCLIP | CONTENTS_BBOX)
@@ -666,6 +639,7 @@ movement on the server game.
#define MASK_PATHSOLID \
(CONTENTS_SOLID | CONTENTS_TRIGGER | CONTENTS_BODY | CONTENTS_FENCE | CONTENTS_UNKNOWN2 | CONTENTS_BBOX \
| CONTENTS_MONSTERCLIP)
#define MASK_LOOK (CONTENTS_SOLID | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_FENCE)
#define MASK_CAMERASOLID (CONTENTS_SOLID | CONTENTS_PLAYERCLIP | CONTENTS_BODY | MASK_WATER)
#define MASK_BEAM (CONTENTS_SOLID | CONTENTS_TRIGGER | CONTENTS_PLAYERCLIP | CONTENTS_BODY | CONTENTS_FENCE)
#define MASK_LADDER \
@@ -673,17 +647,24 @@ movement on the server game.
#define MASK_AUTOCALCLIFE (CONTENTS_SOLID | CONTENTS_TRIGGER | CONTENTS_FENCE)
#define MASK_EXPLOSION (CONTENTS_SOLID | CONTENTS_TRIGGER | CONTENTS_WEAPONCLIP)
#define MASK_SOUND (CONTENTS_SOLID | CONTENTS_TRANSLUCENT)
#define MASK_VEHICLE (CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_FENCE | CONTENTS_VEHICLECLIP | CONTENTS_BODY | CONTENTS_TRIGGER)
#define MASK_VEHICLE \
(CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_FENCE | CONTENTS_VEHICLECLIP \
| CONTENTS_BODY | CONTENTS_TRIGGER)
#define MASK_VEHICLE_TIRES (CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_FENCE | CONTENTS_VEHICLECLIP | CONTENTS_TRIGGER)
#define MASK_CLICK \
(CONTENTS_SOLID | CONTENTS_BODY | CONTENTS_UNKNOWN3 | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP | CONTENTS_BBOX)
#define MASK_CANSEE \
(CONTENTS_SOLID | CONTENTS_BODY | CONTENTS_WEAPONCLIP | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP | CONTENTS_SLIME \
| CONTENTS_LAVA | CONTENTS_BBOX)
#define MASK_ITEM (CONTENTS_SOLID | CONTENTS_TRIGGER | CONTENTS_PLAYERCLIP | CONTENTS_FENCE)
#define MASK_CANSEE \
(CONTENTS_SOLID | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_FENCE | CONTENTS_WEAPONCLIP | CONTENTS_BODY)
#define MASK_CANSEE_NOENTS (CONTENTS_SOLID | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_FENCE | CONTENTS_WEAPONCLIP)
#define MASK_ITEM (CONTENTS_SOLID | CONTENTS_TRIGGER | CONTENTS_PLAYERCLIP | CONTENTS_FENCE)
#define MASK_TRANSITION \
(CONTENTS_SOLID | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_UNKNOWN2 | CONTENTS_NOTTEAM1 | CONTENTS_WEAPONCLIP)
#define MASK_TARGETPATH \
(CONTENTS_SOLID | CONTENTS_TRIGGER | CONTENTS_MONSTERCLIP | CONTENTS_FENCE | CONTENTS_UNKNOWN2 | CONTENTS_BBOX)
#define MASK_ACTORPATH (CONTENTS_SOLID | CONTENTS_FENCE | CONTENTS_MONSTERCLIP | CONTENTS_TRIGGER)
#define MASK_GRENADEPATH \
(CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_FENCE | CONTENTS_WEAPONCLIP \
| CONTENTS_BODY | CONTENTS_TRIGGER)
#define MASK_LINE (CONTENTS_SOLID | CONTENTS_BODY | CONTENTS_UNKNOWN2 | CONTENTS_NOBOTCLIP | CONTENTS_BBOX)
#define MASK_VEHICLETURRET \
(CONTENTS_SOLID | CONTENTS_TRIGGER | CONTENTS_FENCE | CONTENTS_VEHICLECLIP | CONTENTS_MONSTERCLIP \
@@ -700,52 +681,30 @@ movement on the server game.
#define MASK_BATTLELANGUAGE \
(CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_PLAYERCLIP \
| CONTENTS_WEAPONCLIP | CONTENTS_BODY | CONTENTS_TRIGGER)
#define MASK_SCRIPT_SLAVE (CONTENTS_LADDER|CONTENTS_CLAYPIDGEON|CONTENTS_BBOX|CONTENTS_NOBOTCLIP|CONTENTS_UNKNOWN2|CONTENTS_UNKNOWN3|CONTENTS_BODY|CONTENTS_CORPSE)
// mohaa mask
/*
#define MASK_ALL -1
#define MASK_SOLID 1
#define MASK_COLLISION 0x26000B21
#define MASK_PERMANENTMARK 0x40000001
#define MASK_AUTOCALCLIFE 0x40002021
#define MASK_EXPLOSION 0x40040001
#define MASK_TREADMARK 0x42012B01
#define MASK_THIRDPERSON 0x42012B39
#define MASK_FOOTSTEP 0x42022901
#define MASK_BEAM 0x42042B01
#define MASK_VISIBLE 0x42042B01
#define MASK_VEHICLE 0x42042B01
#define MASK_BULLET 0x42042B21
#define MASK_SHOT 0x42042BA1
#define MASK_CROSSHAIRSHADER 0x42092B01
#define MASK_TRACER 0x42142B21
*/
#define MASK_SCRIPT_SLAVE \
(CONTENTS_LADDER | CONTENTS_CLAYPIDGEON | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 \
| CONTENTS_UNKNOWN3 | CONTENTS_BODY | CONTENTS_CORPSE)
#define MASK_CARRYABLETURRET \
(CONTENTS_SOLID | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 | CONTENTS_FENCE | CONTENTS_BODY)
#define MASK_AITURRET \
(CONTENTS_SOLID | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN2 \
| CONTENTS_FENCE | CONTENTS_WEAPONCLIP | CONTENTS_BODY)
#define MASK_TRANSPARENT (CONTENTS_SOLID | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_BBOX | CONTENTS_FENCE)
#define MASK_MOVEVEHICLE \
(CONTENTS_LADDER | CONTENTS_CLAYPIDGEON | CONTENTS_BBOX | CONTENTS_NOBOTCLIP | CONTENTS_UNKNOWN3 | CONTENTS_BODY \
| CONTENTS_CORPSE)
#define MASK_MOVEINFO (CONTENTS_SOLID | CONTENTS_FENCE)
#define MASK_AI_CANSEE \
(CONTENTS_SOLID | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_BBOX | CONTENTS_UNKNOWN2 | CONTENTS_FENCE \
| CONTENTS_WEAPONCLIP)
#define MASK_CORNER_NODE \
(CONTENTS_SOLID | CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_UNKNOWN2 | CONTENTS_WEAPONCLIP | CONTENTS_BODY)
void BG_EvaluateTrajectoryDelta(const trajectory_t *tr, int atTime, vec3_t result);
void BG_PlayerStateToEntityState(playerState_t *ps, entityState_t *s, qboolean snap);
void BG_PlayerStateToEntityStateExtraPolate(playerState_t *ps, entityState_t *s, int time, qboolean snap);
enum vmAnim_e {
VM_ANIM_DISABLED,
VM_ANIM_IDLE,
VM_ANIM_CHARGE,
VM_ANIM_FIRE,
VM_ANIM_FIRE_SECONDARY,
VM_ANIM_RECHAMBER,
VM_ANIM_RELOAD,
VM_ANIM_RELOAD_SINGLE,
VM_ANIM_RELOAD_END,
VM_ANIM_PULLOUT,
VM_ANIM_PUTAWAY,
VM_ANIM_LADDERSTEP,
VM_ANIM_IDLE_0,
VM_ANIM_IDLE_1,
VM_ANIM_IDLE_2,
};
enum cg_message_ver_15_e {
CGM_NONE,
CGM_BULLET_1,
@@ -839,10 +798,10 @@ movement on the server game.
#endif
typedef enum {
OBJ_FLAG_NONE,
OBJ_FLAG_HIDDEN = 1,
OBJ_FLAG_CURRENT = 2,
OBJ_FLAG_COMPLETED = 4
OBJ_FLAG_NONE,
OBJ_FLAG_HIDDEN = 1,
OBJ_FLAG_CURRENT = 2,
OBJ_FLAG_COMPLETED = 4
} objective_flags_t;
typedef enum {
@@ -851,5 +810,3 @@ typedef enum {
OBJ_STATUS_CURRENT,
OBJ_STATUS_COMPLETED
} objective_status_t;
#endif /* bg_public.h */
+716 -1
View File
@@ -21,5 +21,720 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "bg_voteoptions.h"
#include "../qcommon/script.h"
// FIXME: unimplemented
#if defined(GAME_DLL)
# define VO_FS_FreeFile gi.FS_FreeFile
# define VO_FS_ReadFile(a, b) gi.FS_ReadFile(a, b, true)
# define VO_SendRemoteCommand(s) // ?
# define VO_ExecuteCommand(s) gi.Cmd_Execute(EXEC_NOW, s)
# define VO_Cvar_Set(name, value) gi.cvar_set(name, value)
# define VO_Cvar_Get(name, value, flags) gi.Cvar_Get(name, value, flags)
# define VO_LV_ConvertString(s) gi.LV_ConvertString(s)
#elif defined(CGAME_DLL)
# define VO_FS_FreeFile cgi.FS_FreeFile
# define VO_FS_ReadFile(a, b) cgi.FS_ReadFile(a, b, qtrue)
# define VO_SendRemoteCommand(s) cgi.SendClientCommand(s)
# define VO_ExecuteCommand(s) cgi.Cmd_Execute(EXEC_NOW, s)
# define VO_Cvar_Set(name, value) cgi.Cvar_Set(name, value)
# define VO_Cvar_Get(name, value, flags) cgi.Cvar_Get(name, value, flags)
# define VO_LV_ConvertString(s) cgi.LV_ConvertString(s)
#else
# pragma error("VoteOptions can must be used with fgame or cgame")
#endif
CLASS_DECLARATION(Class, VoteOptions, NULL) {
{NULL, NULL}
};
VoteOptionListItem::VoteOptionListItem()
: m_pNext(NULL)
{}
SingleVoteOption::SingleVoteOption()
: m_optionType(VOTE_NO_CHOICES)
, m_pListItem(NULL)
, m_pNext(NULL)
{}
SingleVoteOption::~SingleVoteOption()
{
VoteOptionListItem *item;
VoteOptionListItem *next;
for (item = m_pListItem; item; item = next) {
next = item->m_pNext;
delete item;
}
}
VoteOptions::VoteOptions()
{
m_pHeadOption = NULL;
}
VoteOptions::~VoteOptions()
{
ClearOptions();
}
void VoteOptions::ClearOptions()
{
SingleVoteOption *option;
SingleVoteOption *next;
for (option = m_pHeadOption; option; option = next) {
next = option->m_pNext;
delete option;
}
m_pHeadOption = NULL;
}
void VoteOptions::SetupVoteOptions(const char *configFileName)
{
char *buffer;
int compressedLength;
long length;
length = VO_FS_ReadFile(configFileName, (void **)&buffer);
if (length == -1 || !length) {
Com_Printf("WARNING: Couldn't find voting options file: %s\n", configFileName);
return;
}
// compress the buffer before setting up
compressedLength = COM_Compress(buffer);
SetupVoteOptions(configFileName, compressedLength, buffer);
VO_FS_FreeFile(buffer);
}
void VoteOptions::SetupVoteOptions(const char *configFileName, int length, const char *buffer)
{
if (length >= MAX_VOTEOPTIONS_BUFFER_LENGTH) {
Com_Error(
ERR_DROP,
"VoteOptions: Options file '%s' is too big. Max size is %i bytes\n",
configFileName,
MAX_VOTEOPTIONS_BUFFER_LENGTH
);
return;
}
m_sFileName = configFileName;
m_sBuffer = buffer;
ParseVoteOptions();
}
void VoteOptions::ParseVoteOptions()
{
SingleVoteOption *option;
SingleVoteOption *newOption;
VoteOptionListItem *listItem;
VoteOptionListItem *newListItem;
str token;
Script script;
ClearOptions();
script.LoadFile(m_sFileName.c_str(), m_sBuffer.length(), m_sBuffer.c_str());
option = m_pHeadOption;
while (script.TokenAvailable(true)) {
token = script.GetToken(true);
if (!str::icmp(token, "{")) {
Com_Error(
ERR_DROP,
"Vote Options %s: Found choices list without option header on line %d.\n",
m_sFileName.c_str(),
script.GetLineNumber()
);
return;
}
if (!str::icmp(token, "}")) {
Com_Error(
ERR_DROP,
"Vote Options %s: Illegal end of choices list without list being started on line %d.\n",
m_sFileName.c_str(),
script.GetLineNumber()
);
return;
}
if (!token.length()) {
Com_Error(
ERR_DROP,
"Vote Options %s: Empty option name on line %d.\n",
m_sFileName.c_str(),
script.GetLineNumber()
);
return;
}
newOption = new SingleVoteOption();
if (option) {
option->m_pNext = newOption;
} else {
m_pHeadOption = newOption;
}
option = newOption;
newOption->m_sOptionName = token;
if (!script.TokenAvailable(false)) {
Com_Error(
ERR_DROP,
"Vote Options %s: Option without a command specified on line %d.\n",
m_sFileName.c_str(),
script.GetLineNumber()
);
return;
}
newOption->m_sCommand = script.GetToken(false);
if (script.TokenAvailable(false)) {
token = script.GetToken(false);
if (!str::icmp(token, "nochoices")) {
newOption->m_optionType = VOTE_NO_CHOICES;
} else if (!str::icmp(token, "list")) {
newOption->m_optionType = VOTE_OPTION_LIST;
} else if (!str::icmp(token, "text")) {
newOption->m_optionType = VOTE_OPTION_TEXT;
} else if (!str::icmp(token, "integer")) {
newOption->m_optionType = VOTE_OPTION_INTEGER;
} else if (!str::icmp(token, "float")) {
newOption->m_optionType = VOTE_OPTION_FLOAT;
} else if (!str::icmp(token, "client")) {
newOption->m_optionType = VOTE_OPTION_CLIENT;
} else if (!str::icmp(token, "clientnotself")) {
newOption->m_optionType = VOTE_OPTION_CLIENT_NOT_SELF;
} else {
Com_Error(
ERR_DROP,
"Vote Options %s: Illegal option type '%s' specified on line %d.\n"
" Valid types are nochoices, list, text, & number.\n",
m_sFileName.c_str(),
token.c_str(),
script.GetLineNumber()
);
return;
}
}
if (newOption->m_optionType == VOTE_OPTION_LIST) {
if (!script.TokenAvailable(true) || Q_stricmp(script.GetToken(true), "{")) {
Com_Error(
ERR_DROP,
"Vote Options %s: Missing '{'. No choices list specified for list option on line %d.\n",
m_sFileName.c_str(),
script.GetLineNumber()
);
return;
}
listItem = NULL;
while (script.TokenAvailable(true)) {
token = script.GetToken(true);
if (!str::icmp(token, "}")) {
break;
}
newListItem = new VoteOptionListItem();
if (listItem) {
listItem->m_pNext = newListItem;
} else {
newOption->m_pListItem = newListItem;
}
listItem = newListItem;
if (!script.TokenAvailable(false)) {
Com_Error(
ERR_DROP,
"Vote Options %s: List choice without vote string specified on line %d.\n",
m_sFileName.c_str(),
script.GetLineNumber()
);
return;
}
newListItem->m_sCommand = script.GetToken(false);
}
} else if (script.TokenAvailable(true)) {
token = script.GetToken(true);
if (!str::icmp(token, "{")) {
Com_Error(
ERR_DROP,
"Vote Options %s: Choices list specified for non-list option on line %d.\n",
m_sFileName.c_str(),
script.GetLineNumber()
);
return;
}
script.UnGetToken();
}
}
}
const char *VoteOptions::GetVoteOptionsFile(int *outLen) const
{
if (outLen) {
*outLen = m_sBuffer.length();
}
return m_sBuffer.c_str();
}
bool VoteOptions::GetVoteOptionsMain(int index, str *outOptionCommand, voteoptiontype_t *outOptionType) const
{
SingleVoteOption *option;
int optionIndex;
if (index < 1) {
return false;
}
optionIndex = 1;
for (option = m_pHeadOption; optionIndex < index && option != NULL; option = option->m_pNext) {
optionIndex++;
}
if (!option) {
return false;
}
*outOptionCommand = option->m_sCommand;
*outOptionType = option->m_optionType;
return true;
}
bool VoteOptions::GetVoteOptionSub(int index, int listIndex, str *outCommand) const
{
SingleVoteOption *option;
VoteOptionListItem *item;
int optionIndex;
int itemIndex;
if (index < 1 || listIndex < 1) {
return false;
}
optionIndex = 1;
for (option = m_pHeadOption; optionIndex < index && option != NULL; option = option->m_pNext) {
optionIndex++;
}
if (!option) {
return false;
}
if (option->m_optionType != VOTE_OPTION_LIST) {
return false;
}
itemIndex = 1;
for (item = option->m_pListItem; itemIndex < listIndex && option != NULL; item = item->m_pNext) {
itemIndex++;
}
if (!item) {
return false;
}
*outCommand = item->m_sCommand;
return true;
}
bool VoteOptions::GetVoteOptionMainName(int index, str *outVoteName) const
{
SingleVoteOption *option;
int optionIndex;
if (index < 1) {
return false;
}
optionIndex = 1;
for (option = m_pHeadOption; optionIndex < index && option != NULL; option = option->m_pNext) {
optionIndex++;
}
if (!option) {
return false;
}
*outVoteName = option->m_sOptionName;
return true;
}
bool VoteOptions::GetVoteOptionSubName(int index, int listIndex, str *outName) const
{
SingleVoteOption *option;
VoteOptionListItem *item;
int optionIndex;
int itemIndex;
if (index < 1 || listIndex < 1) {
return false;
}
optionIndex = 1;
for (option = m_pHeadOption; optionIndex < index && option != NULL; option = option->m_pNext) {
optionIndex++;
}
if (!option) {
return false;
}
if (option->m_optionType != VOTE_OPTION_LIST) {
return false;
}
itemIndex = 1;
for (item = option->m_pListItem; itemIndex < listIndex && option != NULL; item = item->m_pNext) {
itemIndex++;
}
if (!item) {
return false;
}
*outName = item->m_sItemName;
return true;
}
#if defined(CGAME_DLL)
static str g_sVoteString;
static VoteOptions g_voteOptions;
void CG_VoteOptions_StartReadFromServer(const char *string)
{
g_sVoteString = string;
}
void CG_VoteOptions_ContinueReadFromServer(const char *string)
{
if (g_sVoteString.length() >= MAX_VOTEOPTIONS_BUFFER_LENGTH) {
return;
}
g_sVoteString += string;
}
void CG_VoteOptions_FinishReadFromServer(const char *string)
{
int i;
if (g_sVoteString.length() >= MAX_VOTEOPTIONS_BUFFER_LENGTH) {
return;
}
g_sVoteString += va("%s\n", string);
if (!str::cmp(g_sVoteString, "\n")) {
VO_SendRemoteCommand("wait 250;gvo\n");
return;
}
for (i = 0; i < g_sVoteString.length(); i++) {
if (g_sVoteString[i] == 1) {
g_sVoteString[i] = '"';
}
}
g_voteOptions.SetupVoteOptions("ServerVoteOptions", g_sVoteString.length(), g_sVoteString.c_str());
g_sVoteString = "";
g_voteOptions.SetupMainOptionsList();
}
void CG_PushCallVote_f()
{
g_voteOptions.SetupMainOptionsList();
}
void CG_PushCallVoteSubList_f()
{
g_voteOptions.SetupSubOptionsList(atoi(cgi.Argv(1)));
}
void CG_PushCallVoteSubText_f()
{
str command;
str name;
voteoptiontype_t type;
if (!g_voteOptions.GetVoteOptionsMain(atoi(cgi.Argv(1)), &command, &type)) {
return;
}
if (type != voteoptiontype_t::VOTE_OPTION_TEXT) {
return;
}
g_voteOptions.GetVoteOptionMainName(atoi(cgi.Argv(1)), &name);
VO_ExecuteCommand("forcemenu votesubtext\n");
VO_Cvar_Set("ui_votesubtitle", name.c_str());
VO_Cvar_Set("ui_votestringentry", "");
}
void CG_PushCallVoteSubInteger_f()
{
str command;
str name;
voteoptiontype_t type;
if (!g_voteOptions.GetVoteOptionsMain(atoi(cgi.Argv(1)), &command, &type)) {
return;
}
if (type != voteoptiontype_t::VOTE_OPTION_INTEGER) {
return;
}
g_voteOptions.GetVoteOptionMainName(atoi(cgi.Argv(1)), &name);
VO_ExecuteCommand("forcemenu votesubinteger\n");
VO_Cvar_Set("ui_votesubtitle", name.c_str());
VO_Cvar_Set("ui_votestringentry", "");
}
void CG_PushCallVoteSubFloat_f()
{
str command;
str name;
voteoptiontype_t type;
if (!g_voteOptions.GetVoteOptionsMain(atoi(cgi.Argv(1)), &command, &type)) {
return;
}
if (type != voteoptiontype_t::VOTE_OPTION_FLOAT) {
return;
}
g_voteOptions.GetVoteOptionMainName(atoi(cgi.Argv(1)), &name);
VO_ExecuteCommand("forcemenu votesubfloat\n");
VO_Cvar_Set("ui_votesubtitle", name.c_str());
VO_Cvar_Set("ui_votestringentry", "");
}
void CG_PushCallVoteSubClient_f()
{
str command;
str name;
int index;
int i;
voteoptiontype_t type;
index = atoi(cgi.Argv(1));
if (!g_voteOptions.GetVoteOptionsMain(index, &command, &type)) {
return;
}
if (type != voteoptiontype_t::VOTE_OPTION_CLIENT && type != voteoptiontype_t::VOTE_OPTION_CLIENT_NOT_SELF) {
return;
}
g_voteOptions.GetVoteOptionMainName(index, &name);
VO_ExecuteCommand("forcemenu votesubclient\n");
VO_Cvar_Set("ui_votesubtitle", name.c_str());
VO_ExecuteCommand("globalwidgetcommand voteclientlist deleteallitems\n");
for (i = 0; i < cgs.maxclients; i++) {
if (type == VOTE_OPTION_CLIENT_NOT_SELF && cg.snap && i == cg.snap->ps.clientNum) {
continue;
}
if (!strlen(cg.clientinfo[i].name)) {
continue;
}
VO_ExecuteCommand(
va("globalwidgetcommand voteclientlist additem \"%i: %s\" \"callvote %i %i;popmenu 0\"\n",
i,
cg.clientinfo[i],
index,
i)
);
}
VO_ExecuteCommand(
va("globalwidgetcommand voteclientlist additem \"%s\" \"popmenu 0\"\n", VO_LV_ConvertString("[Cancel Vote]"))
);
}
void CG_PushVote_f()
{
VO_Cvar_Set("ui_votesubtitle", cgs.voteString);
VO_ExecuteCommand("forcemenu votecast\n");
}
void CG_CallEntryVote_f()
{
str command;
str name;
const char *entry;
int index;
voteoptiontype_t type;
index = VO_Cvar_Get("ui_votetype", "0", 0)->integer;
if (!g_voteOptions.GetVoteOptionsMain(index, &command, &type)) {
return;
}
if (type != voteoptiontype_t::VOTE_OPTION_TEXT && type != voteoptiontype_t::VOTE_OPTION_INTEGER
&& type != voteoptiontype_t::VOTE_OPTION_FLOAT) {
return;
}
entry = VO_Cvar_Get("ui_votestringentry", "", 0)->string;
VO_ExecuteCommand(va("callvote %i \"%s\"\n", index, entry));
}
void VoteOptions::SetupMainOptionsList()
{
SingleVoteOption *option;
int count;
VO_ExecuteCommand("forcemenu votemain\n");
VO_ExecuteCommand("globalwidgetcommand votelistmain deleteallitems\n");
if (!IsSetup()) {
VO_ExecuteCommand(
va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0\"\n",
VO_LV_ConvertString("Retrieving voting options from server..."))
);
VO_SendRemoteCommand("gvo\n");
return;
}
count = 1;
for (option = m_pHeadOption; option; option = option->m_pNext, count++) {
switch (option->m_optionType) {
case VOTE_NO_CHOICES:
VO_ExecuteCommand(
va("globalwidgetcommand votelistmain additem \"%s\" \"callvote %i;popmenu 0\"\n",
option->m_sOptionName.c_str(),
count)
);
break;
case VOTE_OPTION_LIST:
VO_ExecuteCommand(
va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0;wait 100;pushcallvotesublist %i\"\n",
option->m_sOptionName.c_str(),
count)
);
break;
case VOTE_OPTION_TEXT:
VO_ExecuteCommand(
va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0;wait 100;set ui_votetype "
"%i;pushcallvotesubtext %i\"\n",
option->m_sOptionName.c_str(),
count,
count)
);
break;
case VOTE_OPTION_INTEGER:
VO_ExecuteCommand(
va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0;wait 100;set ui_votetype "
"%i;pushcallvotesubinteger %i\"\n",
option->m_sOptionName.c_str(),
count,
count)
);
break;
case VOTE_OPTION_FLOAT:
VO_ExecuteCommand(
va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0;wait 100;set ui_votetype "
"%i;pushcallvotesubfloat %i\"\n",
option->m_sOptionName.c_str(),
count,
count)
);
break;
case VOTE_OPTION_CLIENT:
case VOTE_OPTION_CLIENT_NOT_SELF:
VO_ExecuteCommand(
va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0;wait 100;set ui_votetype "
"%i;pushcallvotesubclient %i\"\n",
option->m_sOptionName.c_str(),
count,
count)
);
break;
}
}
VO_ExecuteCommand(
va("globalwidgetcommand votelistmain additem \"%s\" \"popmenu 0\"\n", VO_LV_ConvertString("[Cancel Vote]"))
);
}
void VoteOptions::SetupSubOptionsList(int index)
{
SingleVoteOption *option;
VoteOptionListItem *item;
int count;
int numItems;
if (index < 1) {
return;
}
count = 1;
for (option = m_pHeadOption; count < index && option; option = option->m_pNext) {
count++;
}
if (!option) {
return;
}
if (option->m_optionType != VOTE_OPTION_LIST || !option->m_pListItem) {
return;
}
VO_ExecuteCommand("forcemenu votesublist\n");
VO_Cvar_Set("ui_votesubtitle", option->m_sOptionName.c_str());
VO_ExecuteCommand("globalwidgetcommand votelistsub deleteallitems\n");
if (IsSetup()) {
numItems = 1;
for (item = option->m_pListItem; item; item = item->m_pNext, numItems++) {
VO_ExecuteCommand(
va("globalwidgetcommand votelistsub additem \"%s\" \"callvote %i %i;popmenu 0\"\n",
item->m_sItemName.c_str(),
index,
numItems)
);
}
VO_ExecuteCommand(
va("globalwidgetcommand votelistsub additem \"%s\" \"popmenu 0\"\n", VO_LV_ConvertString("[Cancel Vote]"))
);
} else {
VO_ExecuteCommand(
"globalwidgetcommand votelistsub additem \"Retrieving voting options from server...\" \"popmenu 0\"\n"
);
VO_SendRemoteCommand("gvo\n");
}
}
#endif
+72 -13
View File
@@ -22,9 +22,17 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#pragma once
#include "listener.h"
#ifdef __cplusplus
# include "listener.h"
#endif
#include "g_public.h"
#ifdef __cplusplus
static const unsigned long MAX_VOTEOPTIONS_UPLOAD_BUFFER_LENGTH = 2024;
static const unsigned long MAX_VOTEOPTIONS_BUFFER_LENGTH = 0x100000;
typedef enum voteoptiontype_e {
/** No input. */
VOTE_NO_CHOICES,
@@ -44,18 +52,27 @@ typedef enum voteoptiontype_e {
class VoteOptionListItem
{
public:
str m_sItemName;
str m_sCommand;
class VoteOptionListItem *m_pNext;
public:
VoteOptionListItem();
};
class SingleVoteOption
{
str m_sVoteName;
str m_sCommand;
voteoptiontype_t m_optionType;
VoteOptionListItem *m_pListItem;
class SingleVoteOption *m_pNext;
public:
str m_sOptionName;
str m_sCommand;
voteoptiontype_t m_optionType;
VoteOptionListItem *m_pListItem;
SingleVoteOption *m_pNext;
public:
SingleVoteOption();
~SingleVoteOption();
};
class VoteOptions : public Class
@@ -63,14 +80,56 @@ class VoteOptions : public Class
public:
CLASS_PROTOTYPE(VoteOptions);
public:
private:
str m_sFileName;
str m_sBuffer;
SingleVoteOption *m_pHeadOption;
int field_5;
float field_6;
float field_7;
float field_8;
float field_9;
float field_10;
public:
VoteOptions();
~VoteOptions();
bool IsSetup() const;
void ClearOptions();
void SetupVoteOptions(const char *configFileName);
void SetupVoteOptions(const char *configFileName, int length, const char *buffer);
void ParseVoteOptions();
const char *GetVoteOptionsFile(int *outLen) const;
bool GetVoteOptionsMain(int index, str *outOptionCommand, voteoptiontype_t *outOptionType) const;
bool GetVoteOptionSub(int index, int listIndex, str *outCommand) const;
bool GetVoteOptionMainName(int index, str *outVoteName) const;
bool GetVoteOptionSubName(int index, int listIndex, str *outName) const;
void SetupMainOptionsList();
void SetupSubOptionsList(int index);
};
inline bool VoteOptions::IsSetup() const
{
return m_pHeadOption != NULL;
}
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if defined(CGAME_DLL)
void CG_VoteOptions_StartReadFromServer(const char *string);
void CG_VoteOptions_ContinueReadFromServer(const char *string);
void CG_VoteOptions_FinishReadFromServer(const char *string);
void CG_PushCallVote_f();
void CG_PushCallVoteSubList_f();
void CG_PushCallVoteSubText_f();
void CG_PushCallVoteSubInteger_f();
void CG_PushCallVoteSubFloat_f();
void CG_PushCallVoteSubClient_f();
void CG_PushVote_f();
void CG_CallEntryVote_f();
#endif
#ifdef __cplusplus
}
#endif
+653 -886
View File
File diff suppressed because it is too large. Load diff
+2633 -3309
View File
File diff suppressed because it is too large. Load diff
+335 -359
View File
@@ -21,10 +21,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
// camera.h: Camera. Duh.
//
//
#ifndef __CAMERA_H__
#define __CAMERA_H__
#pragma once
#include "g_local.h"
#include "entity.h"
@@ -34,13 +33,12 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define CAMERA_SWITCHTIME 0.5f
#define ORBIT ( 1 << 0 )
#define START_ON ( 1 << 1 )
#define AUTOMATIC ( 1 << 2 )
#define NO_TRACE ( 1 << 3 )
#define NO_WATCH ( 1 << 4 )
#define LEVEL_EXIT ( 1 << 5 )
#define ORBIT (1 << 0)
#define START_ON (1 << 1)
#define AUTOMATIC (1 << 2)
#define NO_TRACE (1 << 3)
#define NO_WATCH (1 << 4)
#define LEVEL_EXIT (1 << 5)
extern Event EV_Camera_CameraThink;
extern Event EV_Camera_StartMoving;
@@ -69,408 +67,386 @@ extern Event EV_Camera_Cut;
class Camera;
class CameraMoveState : public Class
{
public:
Vector pos;
Vector movedir; // direction of travel
Vector angles; // angles from spline camera
{
public:
Vector pos;
Vector movedir; // direction of travel
Vector angles; // angles from spline camera
BSpline cameraPath;
SplinePathPtr splinePath;
SplinePathPtr currentNode;
SplinePathPtr loopNode;
BSpline cameraPath;
SplinePathPtr splinePath;
SplinePathPtr currentNode;
SplinePathPtr loopNode;
float cameraTime;
int lastTime;
int newTime;
float cameraTime;
int lastTime;
int newTime;
qboolean followingpath;
EntityPtr followEnt;
EntityPtr orbitEnt;
qboolean followingpath;
EntityPtr followEnt;
EntityPtr orbitEnt;
void operator=( CameraMoveState &newstate );
void Evaluate( Camera * camera );
void Initialize( Camera * camera );
void DoNodeEvents( Camera * camera );
void Archive( Archiver &arc ) override;
};
void operator=(CameraMoveState& newstate);
void Evaluate(Camera *camera);
void Initialize(Camera *camera);
void DoNodeEvents(Camera *camera);
void Archive(Archiver& arc) override;
};
inline void CameraMoveState::operator=
(
CameraMoveState &newstate
)
inline void CameraMoveState::operator=(CameraMoveState& newstate)
{
movedir = newstate.movedir;
pos = newstate.pos;
angles = newstate.angles;
{
movedir = newstate.movedir;
pos = newstate.pos;
angles = newstate.angles;
cameraPath = newstate.cameraPath;
splinePath = newstate.splinePath;
currentNode = newstate.currentNode;
loopNode = newstate.loopNode;
cameraPath = newstate.cameraPath;
splinePath = newstate.splinePath;
currentNode = newstate.currentNode;
loopNode = newstate.loopNode;
cameraTime = newstate.cameraTime;
lastTime = newstate.lastTime;
newTime = newstate.newTime;
cameraTime = newstate.cameraTime;
lastTime = newstate.lastTime;
newTime = newstate.newTime;
followEnt = newstate.followEnt;
orbitEnt = newstate.orbitEnt;
followEnt = newstate.followEnt;
orbitEnt = newstate.orbitEnt;
followingpath = newstate.followingpath;
}
followingpath = newstate.followingpath;
}
inline void CameraMoveState::Archive
(
Archiver &arc
)
{
arc.ArchiveVector( &movedir );
arc.ArchiveVector( &pos );
arc.ArchiveVector( &angles );
inline void CameraMoveState::Archive(Archiver& arc)
{
arc.ArchiveVector(&movedir);
arc.ArchiveVector(&pos);
arc.ArchiveVector(&angles);
cameraPath.Archive( arc );
cameraPath.Archive(arc);
arc.ArchiveSafePointer( &splinePath );
arc.ArchiveSafePointer( &currentNode );
arc.ArchiveSafePointer( &loopNode );
arc.ArchiveSafePointer(&splinePath);
arc.ArchiveSafePointer(&currentNode);
arc.ArchiveSafePointer(&loopNode);
arc.ArchiveFloat( &cameraTime );
arc.ArchiveInteger( &lastTime );
arc.ArchiveInteger( &newTime );
arc.ArchiveFloat(&cameraTime);
arc.ArchiveInteger(&lastTime);
arc.ArchiveInteger(&newTime);
arc.ArchiveSafePointer( &followEnt );
arc.ArchiveSafePointer( &orbitEnt );
arc.ArchiveSafePointer(&followEnt);
arc.ArchiveSafePointer(&orbitEnt);
arc.ArchiveBoolean( &followingpath );
}
arc.ArchiveBoolean(&followingpath);
}
class CameraWatchState : public Class
{
public:
Vector watchAngles;
class CameraWatchState : public Class
{
public:
Vector watchAngles;
EntityPtr watchEnt;
qboolean watchNodes;
qboolean watchPath;
EntityPtr watchEnt;
qboolean watchNodes;
qboolean watchPath;
void Evaluate( Camera * camera, CameraMoveState * move );
void Initialize( Camera * camera );
void Archive( Archiver &arc ) override;
};
void Evaluate(Camera *camera, CameraMoveState *move);
void Initialize(Camera *camera);
void Archive(Archiver& arc) override;
};
inline void CameraWatchState::Archive
(
Archiver &arc
)
{
arc.ArchiveVector( &watchAngles );
arc.ArchiveSafePointer( &watchEnt );
arc.ArchiveBoolean( &watchNodes );
arc.ArchiveBoolean( &watchPath );
}
inline void CameraWatchState::Archive(Archiver& arc)
{
arc.ArchiveVector(&watchAngles);
arc.ArchiveSafePointer(&watchEnt);
arc.ArchiveBoolean(&watchNodes);
arc.ArchiveBoolean(&watchPath);
}
class CameraState : public Class
{
public:
CameraMoveState move;
CameraWatchState watch;
float fov;
class CameraState : public Class
{
public:
CameraMoveState move;
CameraWatchState watch;
float fov;
void Evaluate( Camera * camera );
void Initialize( Camera * camera );
void Archive( Archiver &arc ) override;
};
void Evaluate(Camera *camera);
void Initialize(Camera *camera);
void Archive(Archiver& arc) override;
};
inline void CameraState::Archive
(
Archiver &arc
)
{
move.Archive( arc );
watch.Archive( arc );
arc.ArchiveFloat( &fov );
}
inline void CameraState::Archive(Archiver& arc)
{
move.Archive(arc);
watch.Archive(arc);
arc.ArchiveFloat(&fov);
}
class Camera : public Entity
{
private:
friend class CameraState;
friend class CameraWatchState;
friend class CameraMoveState;
//
// follow parameters
//
float follow_yaw;
qboolean follow_yaw_fixed;
float follow_dist;
int follow_mask;
// camera speed
float camera_speed;
// current camera fov
float camera_fov;
// orbit height
float orbit_height;
// orbit_dotrace
qboolean orbit_dotrace;
// whether or not auto calculate fov, a non-zero value means yes
float auto_fov;
// automatic variables
float automatic_startTime;
float automatic_stopTime;
float automatic_radius;
float automatic_maxFOV;
qboolean automatic_active;
Container<str> automatic_states;
// Miscellaneous
Vector m_vPosOffset;
protected:
CameraState currentstate;
CameraState newstate;
float watchTime; // if non-zero, camera view is transitioning
float followTime; // if non-zero, camera position is tranisitioning
float fovTime; // if non-zero, fov is being lerped
float fadeTime; // time to transition over
float fovFadeTime; // time for fov transition
float followFadeTime; // time for fov transition
float watchFadeTime; // time for fov transition
bool m_bShowquakes;
str nextCamera;
qboolean showcamera;
void SetupCamera( Event *ev );
void CameraThink( Event *ev );
void CreateOrbit( Vector pos, float radius, Vector &forward, Vector &left );
void CreatePath( SplinePath *path, splinetype_t type );
void UpdateStates( void );
Vector CalculatePosition( void );
Vector CalculateOrientation( void );
float CalculateFov( void );
virtual void bind( Entity *master, qboolean use_my_angles = false );
void unbind( void ) override;
public:
CLASS_PROTOTYPE( Camera );
Camera();
void Stop( void );
void FollowPath( SplinePath *path, qboolean loop, Entity *watch );
void Orbit( Entity *ent, float dist, Entity *watch, float yaw_offset = 0, qboolean dotrace = qtrue );
void FollowEntity( Entity *ent, float dist, int mask, Entity *watch = NULL );
void Watch( str watch, float time );
void Watch( Entity *ent, float time );
void SetFOV( float fov, float time );
void StartMoving( Event *ev );
void StopMoving( Event *ev );
void Pause( Event *ev );
void Continue( Event *ev );
void SetAnglesEvent( Event *ev );
void SetSpeed( Event *ev );
void SetFollowDistance( Event *ev );
void SetOrbitHeight( float height );
void SetOrbitHeight( Event *ev );
void SetFollowYaw( Event *ev );
void AbsoluteYaw( Event *ev );
void RelativeYaw( Event *ev );
void SetFOV( Event *ev );
void OrbitEvent( Event *ev );
void FollowEvent( Event *ev );
void WatchEvent( Event *ev );
void WatchStringEvent( Event *ev );
void WatchPathEvent( Event *ev );
void WatchNodesEvent( Event *ev );
void NoWatchEvent(Event* ev);
void EventShowQuakes(Event* ev);
void LookAt( Event *ev );
void MoveToEntity( Event *ev );
void MoveToPos( Event *ev );
void Cut( Event *ev );
void FadeTime( Event *ev );
void TurnTo( Event *ev );
void SetNextCamera( Event *ev );
float CalculateScore( Entity * player, str state );
float AutomaticStart( Entity * player );
float AutomaticStop( Entity * player );
qboolean IsAutomatic( void );
qboolean IsLevelExit( void );
void SetAutoStateEvent( Event * ev );
void SetAutoRadiusEvent( Event * ev );
void SetAutoStartTimeEvent( Event * ev );
void SetAutoStopTimeEvent( Event * ev );
void SetMaximumAutoFOVEvent( Event * ev );
void SetAutoActiveEvent( Event * ev );
str& NextCamera( void );
float Fov( void );
void Reset( Vector org, Vector ang );
Vector GetPositionOffset( void );
void SetPositionOffset( Vector vNewOfs );
void Archive( Archiver &arc ) override;
};
inline Vector Camera::GetPositionOffset
(
void
)
{
return m_vPosOffset;
private:
friend class CameraState;
friend class CameraWatchState;
friend class CameraMoveState;
//
// follow parameters
//
float follow_yaw;
qboolean follow_yaw_fixed;
float follow_dist;
int follow_mask;
// camera speed
float camera_speed;
// current camera fov
float camera_fov;
// orbit height
float orbit_height;
// orbit_dotrace
qboolean orbit_dotrace;
// whether or not auto calculate fov, a non-zero value means yes
float auto_fov;
// automatic variables
float automatic_startTime;
float automatic_stopTime;
float automatic_radius;
float automatic_maxFOV;
qboolean automatic_active;
Container<str> automatic_states;
// Miscellaneous
Vector m_vPosOffset;
protected:
CameraState currentstate;
CameraState newstate;
float watchTime; // if non-zero, camera view is transitioning
float followTime; // if non-zero, camera position is tranisitioning
float fovTime; // if non-zero, fov is being lerped
float fadeTime; // time to transition over
float fovFadeTime; // time for fov transition
float followFadeTime; // time for fov transition
float watchFadeTime; // time for fov transition
bool m_bShowquakes;
str nextCamera;
qboolean showcamera;
void SetupCamera(Event *ev);
void CameraThink(Event *ev);
void CreateOrbit(Vector pos, float radius, Vector &forward, Vector &left);
void CreatePath(SplinePath *path, splinetype_t type);
void UpdateStates(void);
Vector CalculatePosition(void);
Vector CalculateOrientation(void);
float CalculateFov(void);
virtual void bind(Entity *master, qboolean use_my_angles = false);
void unbind(void) override;
public:
CLASS_PROTOTYPE(Camera);
Camera();
void Stop(void);
void FollowPath(SplinePath *path, qboolean loop, Entity *watch);
void Orbit(Entity *ent, float dist, Entity *watch, float yaw_offset = 0, qboolean dotrace = qtrue);
void FollowEntity(Entity *ent, float dist, int mask, Entity *watch = NULL);
void Watch(str watch, float time);
void Watch(Entity *ent, float time);
void SetFOV(float fov, float time);
void StartMoving(Event *ev);
void StopMoving(Event *ev);
void Pause(Event *ev);
void Continue(Event *ev);
void SetAnglesEvent(Event *ev);
void SetSpeed(Event *ev);
void SetFollowDistance(Event *ev);
void SetOrbitHeight(float height);
void SetOrbitHeight(Event *ev);
void SetFollowYaw(Event *ev);
void AbsoluteYaw(Event *ev);
void RelativeYaw(Event *ev);
void SetFOV(Event *ev);
void OrbitEvent(Event *ev);
void FollowEvent(Event *ev);
void WatchEvent(Event *ev);
void WatchStringEvent(Event *ev);
void WatchPathEvent(Event *ev);
void WatchNodesEvent(Event *ev);
void NoWatchEvent(Event *ev);
void EventShowQuakes(Event *ev);
void LookAt(Event *ev);
void MoveToEntity(Event *ev);
void MoveToPos(Event *ev);
void Cut(Event *ev);
void FadeTime(Event *ev);
void TurnTo(Event *ev);
void SetNextCamera(Event *ev);
float CalculateScore(Entity *player, str state);
float AutomaticStart(Entity *player);
float AutomaticStop(Entity *player);
qboolean IsAutomatic(void);
qboolean IsLevelExit(void);
void SetAutoStateEvent(Event *ev);
void SetAutoRadiusEvent(Event *ev);
void SetAutoStartTimeEvent(Event *ev);
void SetAutoStopTimeEvent(Event *ev);
void SetMaximumAutoFOVEvent(Event *ev);
void SetAutoActiveEvent(Event *ev);
str & NextCamera(void);
float Fov(void);
void Reset(Vector org, Vector ang);
bool ShowQuakes(void) const;
Vector GetPositionOffset(void);
void SetPositionOffset(Vector vNewOfs);
void Archive(Archiver& arc) override;
};
inline bool Camera::ShowQuakes(void) const
{
return m_bShowquakes;
}
inline void Camera::SetPositionOffset
(
Vector vNewOfs
)
inline Vector Camera::GetPositionOffset(void)
{
m_vPosOffset = vNewOfs;
return m_vPosOffset;
}
inline void Camera::Archive
(
Archiver &arc
)
{
Entity::Archive( arc );
inline void Camera::SetPositionOffset(Vector vNewOfs)
{
m_vPosOffset = vNewOfs;
}
arc.ArchiveFloat( &follow_yaw );
arc.ArchiveBoolean( &follow_yaw_fixed );
arc.ArchiveFloat( &follow_dist );
arc.ArchiveInteger( &follow_mask );
inline void Camera::Archive(Archiver& arc)
{
Entity::Archive(arc);
arc.ArchiveFloat( &camera_speed );
arc.ArchiveFloat( &camera_fov );
arc.ArchiveFloat( &orbit_height );
arc.ArchiveBoolean( &orbit_dotrace );
arc.ArchiveFloat( &auto_fov );
arc.ArchiveFloat(&follow_yaw);
arc.ArchiveBoolean(&follow_yaw_fixed);
arc.ArchiveFloat(&follow_dist);
arc.ArchiveInteger(&follow_mask);
arc.ArchiveFloat( &automatic_startTime );
arc.ArchiveFloat( &automatic_stopTime );
arc.ArchiveFloat( &automatic_radius );
arc.ArchiveFloat( &automatic_maxFOV );
arc.ArchiveBoolean( &automatic_active );
arc.ArchiveFloat(&camera_speed);
arc.ArchiveFloat(&camera_fov);
arc.ArchiveFloat(&orbit_height);
arc.ArchiveBoolean(&orbit_dotrace);
arc.ArchiveFloat(&auto_fov);
automatic_states.Archive( arc );
arc.ArchiveFloat(&automatic_startTime);
arc.ArchiveFloat(&automatic_stopTime);
arc.ArchiveFloat(&automatic_radius);
arc.ArchiveFloat(&automatic_maxFOV);
arc.ArchiveBoolean(&automatic_active);
// currentstate
currentstate.Archive( arc );
// newstate
newstate.Archive( arc );
automatic_states.Archive(arc);
arc.ArchiveFloat( &watchTime );
arc.ArchiveFloat( &followTime );
arc.ArchiveFloat( &fovTime );
arc.ArchiveFloat( &fadeTime );
arc.ArchiveFloat( &fovFadeTime );
arc.ArchiveFloat( &followFadeTime );
arc.ArchiveFloat( &watchFadeTime );
// currentstate
currentstate.Archive(arc);
// newstate
newstate.Archive(arc);
arc.ArchiveString( &nextCamera );
arc.ArchiveFloat(&watchTime);
arc.ArchiveFloat(&followTime);
arc.ArchiveFloat(&fovTime);
arc.ArchiveFloat(&fadeTime);
arc.ArchiveFloat(&fovFadeTime);
arc.ArchiveFloat(&followFadeTime);
arc.ArchiveFloat(&watchFadeTime);
arc.ArchiveBoolean( &showcamera );
arc.ArchiveString(&nextCamera);
if ( arc.Loading() )
{
if ( spawnflags & AUTOMATIC )
{
level.AddAutomaticCamera( this );
}
}
}
arc.ArchiveBoolean(&showcamera);
void SetCamera( Entity *ent, float switchTime );
Entity * GetWatchEntity( str watch );
if (arc.Loading()) {
if (spawnflags & AUTOMATIC) {
level.AddAutomaticCamera(this);
}
}
}
void SetCamera(Entity *ent, float switchTime);
Entity *GetWatchEntity(str watch);
typedef SafePtr<Camera> CameraPtr;
class CameraManager : public Listener
{
protected:
Container<str> pathList;
BSpline cameraPath;
SplinePathPtr path;
SplinePathPtr current;
float speed;
int watch;
str pathName;
CameraPtr cam;
qboolean cameraPath_dirty;
{
protected:
Container<str> pathList;
BSpline cameraPath;
SplinePathPtr path;
SplinePathPtr current;
float speed;
int watch;
str pathName;
CameraPtr cam;
qboolean cameraPath_dirty;
void NewPath( Event *ev );
void SetPath( Event *ev );
void SetTargetName( Event *ev );
void SetTarget( Event *ev );
void AddPoint( Event *ev );
void ReplacePoint( Event *ev );
void DeletePoint( Event *ev );
void MovePlayer( Event *ev );
void NextPoint( Event *ev );
void PreviousPoint( Event *ev );
void ShowingPath( Event *ev );
void ShowPath( Event *ev );
void HidePath( Event *ev );
void StopPlayback( Event *ev );
void PlayPath( Event *ev );
void LoopPath( Event *ev );
void Watch( Event *ev );
void NoWatch( Event *ev );
void Fov( Event *ev );
void FadeTime( Event *ev );
void Speed( Event *ev );
void Save( Event *ev );
void Load( Event *ev );
void SaveMap( Event *ev );
void UpdateEvent( Event *ev );
void NextPath( Event *ev );
void PreviousPath( Event *ev );
void RenamePath( Event *ev );
void NewPath(Event *ev);
void SetPath(Event *ev);
void SetTargetName(Event *ev);
void SetTarget(Event *ev);
void AddPoint(Event *ev);
void ReplacePoint(Event *ev);
void DeletePoint(Event *ev);
void MovePlayer(Event *ev);
void NextPoint(Event *ev);
void PreviousPoint(Event *ev);
void ShowingPath(Event *ev);
void ShowPath(Event *ev);
void HidePath(Event *ev);
void StopPlayback(Event *ev);
void PlayPath(Event *ev);
void LoopPath(Event *ev);
void Watch(Event *ev);
void NoWatch(Event *ev);
void Fov(Event *ev);
void FadeTime(Event *ev);
void Speed(Event *ev);
void Save(Event *ev);
void Load(Event *ev);
void SaveMap(Event *ev);
void UpdateEvent(Event *ev);
void NextPath(Event *ev);
void PreviousPath(Event *ev);
void RenamePath(Event *ev);
void ShowPath( void );
void UpdateUI( void );
void SetPathName( str name );
void SavePath( str pathName );
void ShowPath(void);
void UpdateUI(void);
void SetPathName(str name);
void SavePath(str pathName);
public:
CLASS_PROTOTYPE( CameraManager );
public:
CLASS_PROTOTYPE(CameraManager);
CameraManager();
void SetPath( str pathName );
void Archive( Archiver &arc ) override;
};
CameraManager();
void SetPath(str pathName);
void Archive(Archiver& arc) override;
};
inline void CameraManager::Archive
(
Archiver &arc
)
inline void CameraManager::Archive(Archiver& arc)
{
Listener::Archive( arc );
{
Listener::Archive(arc);
pathList.Archive( arc );
pathList.Archive(arc);
// no need to archive the cameraPath
arc.ArchiveSafePointer( &path );
arc.ArchiveSafePointer( &current );
arc.ArchiveFloat( &speed );
arc.ArchiveInteger( &watch );
arc.ArchiveString( &pathName );
arc.ArchiveSafePointer( &cam );
// no need to archive the cameraPath
arc.ArchiveSafePointer(&path);
arc.ArchiveSafePointer(&current);
arc.ArchiveFloat(&speed);
arc.ArchiveInteger(&watch);
arc.ArchiveString(&pathName);
arc.ArchiveSafePointer(&cam);
// make sure the cameraPath gets rebuilt
cameraPath_dirty = qtrue;
}
// make sure the cameraPath gets rebuilt
cameraPath_dirty = qtrue;
}
extern CameraManager CameraMan;
#endif /* camera.h */
+297 -374
View File
@@ -45,491 +45,414 @@ NOTSTACKED prevents the crate from causing crates above it to fall. Great for cr
Event EV_Crate_Think
(
"_crate_think",
EV_DEFAULT,
NULL,
NULL,
"think function for a crate."
"_crate_think",
EV_DEFAULT,
NULL,
NULL,
"think function for a crate."
);
Event EV_Crate_Falling
(
"_crate_falling",
EV_DEFAULT,
NULL,
NULL,
"crate's falling."
"_crate_falling",
EV_DEFAULT,
NULL,
NULL,
"crate's falling."
);
Event EV_Crate_Setup
(
"_cratesetup",
EV_DEFAULT,
NULL,
NULL,
"Does the post spawn setup of the crate"
"_cratesetup",
EV_DEFAULT,
NULL,
NULL,
"Does the post spawn setup of the crate"
);
Event EV_Crate_Start_Falling
(
"_cratestartfalling",
EV_DEFAULT,
NULL,
NULL,
"Makes a crate start falling"
"_cratestartfalling",
EV_DEFAULT,
NULL,
NULL,
"Makes a crate start falling"
);
Event EV_Crate_SetDebris
(
"debristype",
EV_DEFAULT,
"i",
"type",
"Sets the debris type of the crate"
"debristype",
EV_DEFAULT,
"i",
"type",
"Sets the debris type of the crate"
);
CLASS_DECLARATION( Entity, CrateObject, "func_crate" )
{
{ &EV_Crate_Setup, &CrateObject::CrateSetup },
{ &EV_Crate_Falling, &CrateObject::CrateFalling },
{ &EV_Damage, &CrateObject::CrateDamaged },
{ &EV_Killed, &CrateObject::CrateKilled },
{ &EV_Crate_Start_Falling, &CrateObject::StartFalling },
{ &EV_Crate_Think, &CrateObject::CrateThink },
{ &EV_Crate_SetDebris, &CrateObject::CrateDebrisType },
{ NULL, NULL }
CLASS_DECLARATION(Entity, CrateObject, "func_crate") {
{&EV_Crate_Setup, &CrateObject::CrateSetup },
{&EV_Crate_Falling, &CrateObject::CrateFalling },
{&EV_Damage, &CrateObject::CrateDamaged },
{&EV_Killed, &CrateObject::CrateKilled },
{&EV_Crate_Start_Falling, &CrateObject::StartFalling },
{&EV_Crate_Think, &CrateObject::CrateThink },
{&EV_Crate_SetDebris, &CrateObject::CrateDebrisType},
{NULL, NULL }
};
CrateObject::CrateObject()
{
entflags |= EF_CRATEOBJECT;
entflags |= ECF_CRATEOBJECT;
AddWaitTill(STRING_DEATH);
AddWaitTill(STRING_DEATH);
if( LoadingSavegame )
{
return;
}
if (LoadingSavegame) {
return;
}
edict->s.eType = ET_GENERAL;
edict->s.eType = ET_GENERAL;
m_fMoveTime = 0.0f;
m_fMoveTime = 0.0f;
health = 100.0f;
max_health = 100.0f;
deadflag = 0;
takedamage = DAMAGE_YES;
health = 100.0f;
max_health = 100.0f;
deadflag = 0;
takedamage = DAMAGE_YES;
mass = 1200;
mass = 1200;
m_iDebrisType = 0;
m_iDebrisType = 0;
PostEvent( EV_Crate_Setup, EV_POSTSPAWN );
PostEvent(EV_Crate_Setup, EV_POSTSPAWN);
}
void CrateObject::TellNeighborsToFall
(
void
)
void CrateObject::TellNeighborsToFall(void)
{
Entity *pEnt;
Entity *pNext;
Vector vMins;
Vector vMaxs;
Entity *pEnt;
Entity *pNext;
Vector vMins;
Vector vMaxs;
vMins[ 0 ] = mins[ 0 ] + origin[ 0 ] + 6.0f;
vMins[ 1 ] = mins[ 1 ] + origin[ 1 ] + 6.0f;
vMins[ 2 ] = mins[ 2 ] + origin[ 2 ] + 6.0f;
vMins[0] = mins[0] + origin[0] + 6.0f;
vMins[1] = mins[1] + origin[1] + 6.0f;
vMins[2] = mins[2] + origin[2] + 6.0f;
vMaxs[ 0 ] = maxs[ 0 ] + origin[ 0 ] - 6.0f;
vMaxs[ 1 ] = maxs[ 1 ] + origin[ 1 ] - 6.0f;
vMaxs[ 2 ] = maxs[ 2 ] + origin[ 2 ] + 12.0f;
vMaxs[0] = maxs[0] + origin[0] - 6.0f;
vMaxs[1] = maxs[1] + origin[1] - 6.0f;
vMaxs[2] = maxs[2] + origin[2] + 12.0f;
for( pEnt = G_NextEntity( NULL ); pEnt != NULL; pEnt = pNext )
{
pNext = G_NextEntity( pEnt );
for (pEnt = G_NextEntity(NULL); pEnt != NULL; pEnt = pNext) {
pNext = G_NextEntity(pEnt);
for( pEnt = G_NextEntity( NULL ); pEnt != NULL; pEnt = pNext )
{
pNext = G_NextEntity( pEnt );
for (pEnt = G_NextEntity(NULL); pEnt != NULL; pEnt = pNext) {
pNext = G_NextEntity(pEnt);
if( pEnt != this && pEnt->IsSubclassOfCrateObject() )
{
if( vMins[ 0 ] <= absmax[ 0 ] &&
vMins[ 1 ] <= absmax[ 1 ] &&
vMins[ 2 ] <= absmax[ 2 ] &&
absmin[ 0 ] <= vMaxs[ 0 ] &&
absmin[ 1 ] <= vMaxs[ 1 ] &&
absmin[ 2 ] <= vMaxs[ 2 ] )
{
if( !pEnt->EventPending( EV_Crate_Start_Falling ) )
{
float time = level.frametime + level.frametime;
pEnt->PostEvent( EV_Crate_Start_Falling, time );
}
}
}
}
}
if (pEnt != this && pEnt->IsSubclassOfCrateObject()) {
if (vMins[0] <= absmax[0] && vMins[1] <= absmax[1] && vMins[2] <= absmax[2] && absmin[0] <= vMaxs[0]
&& absmin[1] <= vMaxs[1] && absmin[2] <= vMaxs[2]) {
if (!pEnt->EventPending(EV_Crate_Start_Falling)) {
float time = level.frametime + level.frametime;
pEnt->PostEvent(EV_Crate_Start_Falling, time);
}
}
}
}
}
}
void CrateObject::TellNeighborsToJitter
(
Vector vJitterAdd
)
void CrateObject::TellNeighborsToJitter(Vector vJitterAdd)
{
Entity *pEnt;
Entity *pNext;
Vector vMins;
Vector vMaxs;
Entity *pEnt;
Entity *pNext;
Vector vMins;
Vector vMaxs;
vMins[0] = mins[0] + origin[0] + 6.0f;
vMins[1] = mins[1] + origin[1] + 6.0f;
vMins[2] = mins[2] + origin[2] + 6.0f;
vMins[ 0 ] = mins[ 0 ] + origin[ 0 ] + 6.0f;
vMins[ 1 ] = mins[ 1 ] + origin[ 1 ] + 6.0f;
vMins[ 2 ] = mins[ 2 ] + origin[ 2 ] + 6.0f;
vMaxs[0] = maxs[0] + origin[0] - 6.0f;
vMaxs[1] = maxs[1] + origin[1] - 6.0f;
vMaxs[2] = maxs[2] + origin[2] + 12.0f;
vMaxs[ 0 ] = maxs[ 0 ] + origin[ 0 ] - 6.0f;
vMaxs[ 1 ] = maxs[ 1 ] + origin[ 1 ] - 6.0f;
vMaxs[ 2 ] = maxs[ 2 ] + origin[ 2 ] + 12.0f;
for (pEnt = G_NextEntity(NULL); pEnt != NULL; pEnt = pNext) {
CrateObject *crate = (CrateObject *)pEnt;
for( pEnt = G_NextEntity( NULL ); pEnt != NULL; pEnt = pNext )
{
CrateObject *crate = ( CrateObject * )pEnt;
pNext = G_NextEntity(pEnt);
pNext = G_NextEntity( pEnt );
if (pEnt == this) {
continue;
}
if( pEnt == this )
{
continue;
}
if (!pEnt->IsSubclassOfCrateObject()) {
continue;
}
if( !pEnt->IsSubclassOfCrateObject() )
{
continue;
}
if (vMins[0] > absmax[0] || vMins[1] > absmax[1] || vMins[2] > absmax[2] || absmin[0] > vMaxs[0]
|| absmin[1] > vMaxs[1] || absmin[2] > vMaxs[2]) {
continue;
}
if( vMins[ 0 ] > absmax[ 0 ] ||
vMins[ 1 ] > absmax[ 1 ] ||
vMins[ 2 ] > absmax[ 2 ] ||
absmin[ 0 ] > vMaxs[ 0 ] ||
absmin[ 1 ] > vMaxs[ 1 ] ||
absmin[ 2 ] > vMaxs[ 2 ] )
{
continue;
}
crate->m_vJitterAngles[0] = m_vJitterAngles[0] + vJitterAdd[0];
crate->m_vJitterAngles[ 0 ] = m_vJitterAngles[ 0 ] + vJitterAdd[ 0 ];
if (crate->m_vJitterAngles[0] > m_fJitterScale * 1.25f
|| -(m_fJitterScale * 1.25f) <= crate->m_vJitterAngles[0]) {
crate->m_vJitterAngles[0] = m_fJitterScale * 1.25f;
}
if( crate->m_vJitterAngles[ 0 ] > m_fJitterScale * 1.25f ||
-( m_fJitterScale * 1.25f ) <= crate->m_vJitterAngles[ 0 ] )
{
crate->m_vJitterAngles[ 0 ] = m_fJitterScale * 1.25f;
}
crate->m_vJitterAngles[2] += vJitterAdd[2];
crate->m_vJitterAngles[ 2 ] += vJitterAdd[ 2 ];
if (crate->m_vJitterAngles[2] > m_fJitterScale * 1.25f) {
break;
}
if( crate->m_vJitterAngles[ 2 ] > m_fJitterScale * 1.25f ) {
break;
}
if (-(m_fJitterScale * 1.25f) <= crate->m_vJitterAngles[2]) {
m_vJitterAngles[2] = -(m_fJitterScale * 1.25f);
}
if( -( m_fJitterScale * 1.25f ) <= crate->m_vJitterAngles[ 2 ] )
{
m_vJitterAngles[ 2 ] = -( m_fJitterScale * 1.25f );
}
if( !crate->EventPending( EV_Crate_Think ) )
{
crate->ProcessEvent( EV_Crate_Think );
}
}
if (!crate->EventPending(EV_Crate_Think)) {
crate->ProcessEvent(EV_Crate_Think);
}
}
}
void CrateObject::CrateSetup
(
Event *ev
)
void CrateObject::CrateSetup(Event *ev)
{
Vector vMins;
Vector vMaxs;
Entity *pEnt;
Entity *pNext;
Vector vMins;
Vector vMaxs;
Entity *pEnt;
Entity *pNext;
mass = 20 * ( size[ 0 ] * 0.625f * size[ 1 ] * 0.625f * size[ 2 ] * 0.625f );
mass = 20 * ((size[0] / 16) * (size[1] / 16) * (size[2] / 16));
m_vStartAngles = angles;
m_fJitterScale = 64.0f / size[ 2 ];
m_vStartAngles = angles;
m_fJitterScale = 64.0f / size[2];
setMoveType( MOVETYPE_PUSH );
setSolidType( SOLID_BSP );
setMoveType(MOVETYPE_PUSH);
setSolidType(SOLID_BSP);
vMins[ 0 ] = mins[ 0 ] + origin[ 0 ] + 12.0f;
vMins[ 1 ] = mins[ 1 ] + origin[ 1 ] + 12.0f;
vMins[ 2 ] = mins[ 2 ] + origin[ 2 ] + 18.0f;
vMins = origin + mins + Vector(12, 12, 18);
vMaxs = origin + maxs - Vector(12, 12, 18);
vMaxs[ 0 ] = maxs[ 0 ] + origin[ 0 ] - 12.0f;
vMaxs[ 1 ] = maxs[ 1 ] + origin[ 1 ] - 12.0f;
vMaxs[ 2 ] = maxs[ 2 ] + origin[ 2 ] - 18.0f;
for (pEnt = G_NextEntity(NULL); pEnt != NULL; pEnt = pNext) {
pNext = G_NextEntity(pEnt);
for( pEnt = G_NextEntity( NULL ); pEnt != NULL; pEnt = pNext )
{
pNext = G_NextEntity( pEnt );
if (pEnt->entnum <= entnum) {
continue;
}
if( pEnt->entnum > entnum && pEnt->IsSubclassOfCrateObject() )
{
if( vMins[ 0 ] <= absmax[ 0 ] &&
vMins[ 1 ] <= absmax[ 1 ] &&
vMins[ 2 ] <= absmax[ 2 ] &&
absmin[ 0 ] <= vMaxs[ 0 ] &&
absmin[ 1 ] <= vMaxs[ 1 ] &&
absmin[ 2 ] <= vMaxs[ 2 ] )
{
Com_Printf( "^~^~^ WARNING: func_crate entities %i and %i have overlapping volumes near (%g %g %g) to (%g %g %g)\n",
entnum, pEnt->entnum, vMins[ 0 ], vMins[ 1 ], vMins[ 2 ], vMaxs[ 0 ], vMaxs[ 1 ], vMaxs[ 2 ] );
}
}
}
if (!pEnt->IsSubclassOfCrateObject()) {
continue;
}
if (vMins[0] <= pEnt->absmax[0]
&& vMins[1] <= pEnt->absmax[1]
&& vMins[2] <= pEnt->absmax[2]
&& vMaxs[0] >= pEnt->absmin[0]
&& vMaxs[1] >= pEnt->absmin[1]
&& vMaxs[2] >= pEnt->absmin[2]) {
Com_Printf(
"^~^~^ WARNING: func_crate entities %i and %i have overlapping volumes near (%g %g %g) to (%g %g %g)\n",
entnum,
pEnt->entnum,
vMins[0],
vMins[1],
vMins[2],
vMaxs[0],
vMaxs[1],
vMaxs[2]
);
}
}
}
void CrateObject::CrateDebrisType
(
Event *ev
)
void CrateObject::CrateDebrisType(Event *ev)
{
m_iDebrisType = ev->GetInteger( 1 );
m_iDebrisType = ev->GetInteger(1);
if( m_iDebrisType >= 0 )
{
CacheResource( va( "models/fx/crates/debris_%i.tik", m_iDebrisType ) );
}
if (m_iDebrisType >= 0) {
CacheResource(va("models/fx/crates/debris_%i.tik", m_iDebrisType));
}
}
void CrateObject::StartFalling
(
Event *ev
)
void CrateObject::StartFalling(Event *ev)
{
setMoveType( MOVETYPE_FLY );
m_fMoveTime = 0;
setMoveType(MOVETYPE_FLY);
m_fMoveTime = 0;
PostEvent( EV_Crate_Think, level.frametime );
PostEvent(EV_Crate_Think, level.frametime);
if( !( spawnflags & CRATE_NOTSTACKEDON ) )
{
TellNeighborsToFall();
}
if (!(spawnflags & CRATE_NOTSTACKEDON)) {
TellNeighborsToFall();
}
}
void CrateObject::CrateFalling
(
Event *ev
)
void CrateObject::CrateFalling(Event *ev)
{
if( velocity != vec_zero || !groundentity || edict->solid != SOLID_BSP )
{
m_fMoveTime = level.time + 2.0f;
}
if (velocity != vec_zero || !groundentity || edict->solid != SOLID_BSP) {
m_fMoveTime = level.time + 2.0f;
}
if( level.time <= m_fMoveTime )
{
PostEvent( EV_Crate_Think, level.frametime );
}
else
{
setMoveType( MOVETYPE_PUSH );
setSolidType( SOLID_BSP );
}
if (level.time <= m_fMoveTime) {
PostEvent(EV_Crate_Think, level.frametime);
} else {
setMoveType(MOVETYPE_PUSH);
setSolidType(SOLID_BSP);
}
}
void CrateObject::CrateDamaged
(
Event *ev
)
void CrateObject::CrateDamaged(Event *ev)
{
Vector vDir;
Vector vForward;
Vector vRight;
Vector vJitterAdd;
int iDamage;
int iMeansOfDeath;
Vector vHitPos;
Vector vHitDirection;
Vector vHitNormal;
Vector vDir;
Vector vForward;
Vector vRight;
Vector vJitterAdd;
int iDamage;
int iMeansOfDeath;
Vector vHitPos;
Vector vHitDirection;
Vector vHitNormal;
if( !takedamage )
{
return;
}
if (!takedamage) {
return;
}
iDamage = ev->GetInteger( 2 );
iMeansOfDeath = ev->GetInteger( 9 );
vHitPos = ev->GetVector( 4 );
vHitDirection = ev->GetVector( 5 );
vHitNormal = ev->GetVector( 6 );
iDamage = ev->GetInteger(2);
iMeansOfDeath = ev->GetInteger(9);
vHitPos = ev->GetVector(4);
vHitDirection = ev->GetVector(5);
vHitNormal = ev->GetVector(6);
vDir = ( vHitDirection - vHitNormal ) * 0.5f;
AngleVectors( angles, vForward, vRight, NULL );
vDir = (vHitDirection - vHitNormal) * 0.5f;
AngleVectors(angles, vForward, vRight, NULL);
vJitterAdd[ 0 ] = DotProduct( vDir, vForward ) * m_fJitterScale * 0.025f * ( float )iDamage;
vJitterAdd[ 2 ] = DotProduct( vDir, vRight ) * m_fJitterScale * 0.025f * ( float )iDamage;
vJitterAdd[0] = DotProduct(vDir, vForward) * m_fJitterScale * 0.025f * (float)iDamage;
vJitterAdd[2] = DotProduct(vDir, vRight) * m_fJitterScale * 0.025f * (float)iDamage;
m_vJitterAngles += Vector( vJitterAdd[ 0 ], 0, vJitterAdd[ 2 ] );
m_vJitterAngles += Vector(vJitterAdd[0], 0, vJitterAdd[2]);
if( m_vJitterAngles[ 0 ] > m_fJitterScale * 1.25f ||
-( m_fJitterScale * 1.25f ) > m_vJitterAngles[ 0 ] )
{
m_vJitterAngles[ 0 ] = m_fJitterScale * 1.25f;
}
if (m_vJitterAngles[0] > m_fJitterScale * 1.25f || -(m_fJitterScale * 1.25f) > m_vJitterAngles[0]) {
m_vJitterAngles[0] = m_fJitterScale * 1.25f;
}
if( m_vJitterAngles[ 2 ] > m_fJitterScale * 1.25f )
{
m_vJitterAngles[ 2 ] = m_fJitterScale * 1.25f;
}
else if( m_vJitterAngles[ 2 ] >= -( m_fJitterScale * 1.25f ) )
{
m_vJitterAngles[ 2 ] = -( m_fJitterScale * 1.25f );
}
if (m_vJitterAngles[2] > m_fJitterScale * 1.25f) {
m_vJitterAngles[2] = m_fJitterScale * 1.25f;
} else if (m_vJitterAngles[2] >= -(m_fJitterScale * 1.25f)) {
m_vJitterAngles[2] = -(m_fJitterScale * 1.25f);
}
vJitterAdd[ 1 ] = 0.0f;
vJitterAdd *= -0.5f;
TellNeighborsToJitter( vJitterAdd );
if( !EventPending( EV_Crate_Think ) )
{
ProcessEvent( EV_Crate_Think );
}
if( spawnflags & CRATE_INDESTRUCTABLE ) {
return;
}
if( iMeansOfDeath >= MOD_VEHICLE )
{
if( iMeansOfDeath == MOD_BASH )
{
iDamage *= 2;
}
}
else
{
iDamage /= 2;
}
health -= iDamage;
if( health <= 0.0f )
{
Event *event = new Event( EV_Killed );
event->AddEntity( ev->GetEntity( 1 ) );
event->AddInteger( iDamage );
ev->AddEntity( ev->GetEntity( 3 ) );
ProcessEvent( event );
}
vJitterAdd[1] = 0.0f;
vJitterAdd *= -0.5f;
TellNeighborsToJitter(vJitterAdd);
if (!EventPending(EV_Crate_Think)) {
ProcessEvent(EV_Crate_Think);
}
if (spawnflags & CRATE_INDESTRUCTABLE) {
return;
}
if (iMeansOfDeath >= MOD_VEHICLE) {
if (iMeansOfDeath == MOD_BASH) {
iDamage *= 2;
}
} else {
iDamage /= 2;
}
health -= iDamage;
if (health <= 0.0f) {
Event *event = new Event(EV_Killed);
event->AddEntity(ev->GetEntity(1));
event->AddInteger(iDamage);
ev->AddEntity(ev->GetEntity(3));
ProcessEvent(event);
}
}
void CrateObject::CrateKilled
(
Event *ev
)
void CrateObject::CrateKilled(Event *ev)
{
Vector vCenter;
Entity *attacker = ev->GetEntity( 1 );
Vector vCenter;
Entity *attacker = ev->GetEntity(1);
if( attacker->IsSubclassOfPlayer() )
{
Player *p = ( Player * )attacker;
p->m_iNumObjectsDestroyed++;
}
if (attacker->IsSubclassOfPlayer()) {
Player *p = (Player *)attacker;
p->m_iNumObjectsDestroyed++;
}
setSolidType( SOLID_NOT );
hideModel();
setSolidType(SOLID_NOT);
hideModel();
takedamage = DAMAGE_NO;
takedamage = DAMAGE_NO;
if( !( spawnflags & CRATE_NOTSTACKEDON ) )
{
TellNeighborsToFall();
}
if (!(spawnflags & CRATE_NOTSTACKEDON)) {
TellNeighborsToFall();
}
vCenter = origin + ( maxs + mins ) * 0.5f;
vCenter = origin + (maxs + mins) * 0.5f;
// Tell clients around that a crate is destroyed
gi.SetBroadcastVisible( origin, origin );
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_CRATE_DEBRIS));
gi.MSG_WriteCoord( vCenter[ 0 ] );
gi.MSG_WriteCoord( vCenter[ 1 ] );
gi.MSG_WriteCoord( vCenter[ 2 ] );
gi.MSG_WriteByte( m_iDebrisType );
gi.MSG_EndCGM();
// Tell clients around that a crate is destroyed
gi.SetBroadcastVisible(origin, origin);
gi.MSG_StartCGM(BG_MapCGMToProtocol(g_protocol, CGM_MAKE_CRATE_DEBRIS));
gi.MSG_WriteCoord(vCenter[0]);
gi.MSG_WriteCoord(vCenter[1]);
gi.MSG_WriteCoord(vCenter[2]);
gi.MSG_WriteByte(m_iDebrisType);
gi.MSG_EndCGM();
health = 0;
deadflag = DEAD_DEAD;
health = 0;
deadflag = DEAD_DEAD;
PostEvent( EV_Remove, 0 );
PostEvent(EV_Remove, 0);
// Notify scripts
Unregister( STRING_DEATH );
// Notify scripts
Unregister(STRING_DEATH);
}
void CrateObject::CrateThink
(
Event *ev
)
void CrateObject::CrateThink(Event *ev)
{
// Shake the create if it's on fire
// Shake the create if it's on fire
if( m_vJitterAngles[ 0 ] || m_vJitterAngles[ 2 ] )
{
setAngles( Vector( m_vStartAngles[ 0 ] * 2.0f, m_vStartAngles[ 1 ], m_vStartAngles[ 2 ] * 2.0f ) );
if (m_vJitterAngles[0] || m_vJitterAngles[2]) {
setAngles(Vector(m_vStartAngles[0] * 2.0f, m_vStartAngles[1], m_vStartAngles[2] * 2.0f));
if( m_vJitterAngles[ 0 ] > 0.0f )
{
m_vJitterAngles[ 0 ] -= 1 / 3 * m_fJitterScale;
if (m_vJitterAngles[0] > 0.0f) {
m_vJitterAngles[0] -= 1 / 3 * m_fJitterScale;
if( m_vJitterAngles[ 0 ] > 0.0f )
{
m_vJitterAngles[ 0 ] = 0.0f;
}
}
else if( m_vJitterAngles[ 0 ] < 0.0f )
{
m_vJitterAngles[ 0 ] += 1 / 3 * m_fJitterScale;
if (m_vJitterAngles[0] > 0.0f) {
m_vJitterAngles[0] = 0.0f;
}
} else if (m_vJitterAngles[0] < 0.0f) {
m_vJitterAngles[0] += 1 / 3 * m_fJitterScale;
if( m_vJitterAngles[ 0 ] < 0.0f )
{
m_vJitterAngles[ 0 ] = 0.0f;
}
}
if (m_vJitterAngles[0] < 0.0f) {
m_vJitterAngles[0] = 0.0f;
}
}
m_vJitterAngles[ 0 ] = -m_vJitterAngles[ 0 ];
m_vJitterAngles[0] = -m_vJitterAngles[0];
if( m_vJitterAngles[ 2 ] > 0.0f )
{
m_vJitterAngles[ 2 ] -= 1 / 3 * m_fJitterScale;
if (m_vJitterAngles[2] > 0.0f) {
m_vJitterAngles[2] -= 1 / 3 * m_fJitterScale;
if( m_vJitterAngles[ 2 ] > 0.0f )
{
m_vJitterAngles[ 2 ] = 0.0f;
}
}
else if( m_vJitterAngles[ 2 ] < 0.0f )
{
m_vJitterAngles[ 2 ] += 1 / 3 * m_fJitterScale;
if (m_vJitterAngles[2] > 0.0f) {
m_vJitterAngles[2] = 0.0f;
}
} else if (m_vJitterAngles[2] < 0.0f) {
m_vJitterAngles[2] += 1 / 3 * m_fJitterScale;
if( m_vJitterAngles[ 2 ] < 0.0f )
{
m_vJitterAngles[ 2 ] = 0.0f;
}
}
if (m_vJitterAngles[2] < 0.0f) {
m_vJitterAngles[2] = 0.0f;
}
}
m_vJitterAngles[ 2 ] = -m_vJitterAngles[ 2 ];
m_vJitterAngles[2] = -m_vJitterAngles[2];
PostEvent( EV_Crate_Think, 0.05f );
}
else if( !VectorCompare( angles, m_vStartAngles ) )
{
setAngles( m_vStartAngles );
}
PostEvent(EV_Crate_Think, 0.05f);
} else if (!VectorCompare(angles, m_vStartAngles)) {
setAngles(m_vStartAngles);
}
}
Loaded 100 of 434 files, more files were not shown because too many files have changed in this diff. Show more