2024-04-16 03:43:29 +00:00
|
|
|
/*
|
|
|
|
* $Logfile: /DescentIII/Main/physics/Collide.cpp $
|
|
|
|
* $Revision: 239 $
|
|
|
|
* $Date: 9/20/01 5:33p $
|
|
|
|
* $Author: Matt $
|
|
|
|
*
|
|
|
|
* Descent III collision code
|
|
|
|
*
|
|
|
|
* $Log: /DescentIII/Main/physics/Collide.cpp $
|
|
|
|
*
|
|
|
|
* 239 9/20/01 5:33p Matt
|
|
|
|
* Fixed weird omega cannon bugs (I hope) by only letting the omega
|
|
|
|
* particles collide from inside AquireElectricalTarget().
|
|
|
|
*
|
|
|
|
* 238 11/04/99 5:35p Chris
|
|
|
|
* Levels with forcefields with a custom bouce sound don't cause damage
|
|
|
|
*
|
|
|
|
* 237 10/20/99 5:40p Chris
|
|
|
|
* Added the Red Guidebot
|
|
|
|
*
|
|
|
|
* 236 10/08/99 4:29p Chris
|
|
|
|
* Added the forcefield and glass breaking override options
|
|
|
|
*
|
|
|
|
* 235 5/24/99 1:26a Matt
|
|
|
|
* Correctly deal with hit_info == NULL being passed to collision
|
|
|
|
* routines.
|
|
|
|
*
|
|
|
|
* 234 5/21/99 2:55a Matt
|
|
|
|
* When an object is bounced-out and needs to be killed, call
|
|
|
|
* DestroyObject() if it's already dying. Before the code just set the
|
|
|
|
* dead flag, which caused robots to disappear if they bumped into
|
|
|
|
* something while dying.
|
|
|
|
*
|
|
|
|
* 233 5/20/99 9:03p Matt
|
|
|
|
* Changed trigger system so that collisions with rendered portals don't
|
|
|
|
* set off triggers on the portals.
|
|
|
|
*
|
|
|
|
* 232 5/19/99 1:23p Matt
|
|
|
|
* Fixed (hopefully) yet more collision problems introduced by my recent
|
|
|
|
* changes.
|
|
|
|
*
|
|
|
|
* 231 5/18/99 10:15p Matt
|
|
|
|
* Fixed bug with weapon spawning that I introduced last night.
|
|
|
|
*
|
|
|
|
* 230 5/18/99 10:57a Chris
|
|
|
|
* Various bug fixes
|
|
|
|
*
|
|
|
|
* 229 5/17/99 9:09p Matt
|
|
|
|
* Made objects with lava behave like walls with lava; flares don't stick,
|
|
|
|
* player catches on fire.
|
|
|
|
*
|
|
|
|
* 228 5/17/99 6:07p Chris
|
|
|
|
* GB doesn't damage players - PF_LOCK_MASK objects always do...
|
|
|
|
*
|
|
|
|
* 227 5/11/99 5:50p Chris
|
|
|
|
* Buildings don't collide with each other
|
|
|
|
*
|
|
|
|
* 226 5/08/99 4:27p Chris
|
|
|
|
* Hearing code
|
|
|
|
*
|
|
|
|
* 225 5/08/99 3:31p Matt
|
|
|
|
* Deal with weapons hitting water.
|
|
|
|
*
|
|
|
|
* 224 5/07/99 10:56p Chris
|
|
|
|
* GB avoids forcefields, lava, and volatile surfaces... If he accidently
|
|
|
|
* hits one of these, he ignores the collision (i.e. no effects). It make
|
|
|
|
* him look smarter.
|
|
|
|
*
|
|
|
|
* 223 4/30/99 3:28p Matt
|
|
|
|
* Weapons now make a special sound when colliding with lava & volatile
|
|
|
|
* surfaces, instead of the standard hit-wall sound.
|
|
|
|
*
|
|
|
|
* 222 4/29/99 6:48p Matt
|
|
|
|
* Made volatile surfaces apply damage and lava surfaces catch the player
|
|
|
|
* on fire. Both now generate the steam puff effect.
|
|
|
|
*
|
|
|
|
* 221 4/29/99 2:17a Samir
|
|
|
|
* adjusted some sound priority stuff
|
|
|
|
*
|
|
|
|
* 220 4/23/99 6:44p Matt
|
|
|
|
* Changed weapons to keep going after breaking glass.
|
|
|
|
*
|
|
|
|
* 219 4/21/99 4:27p Chris
|
|
|
|
*
|
|
|
|
* 218 4/21/99 3:45p Chris
|
|
|
|
*
|
|
|
|
* 217 4/21/99 3:43p Chris
|
|
|
|
*
|
|
|
|
* 216 4/21/99 2:56p Chris
|
|
|
|
* Made player-player collisions almost complete in-elastic
|
|
|
|
*
|
|
|
|
* 215 4/21/99 1:30p Matt
|
|
|
|
* Make breakable glass use the new breakable flag, instead of
|
|
|
|
* piggybacking on the destroyable flag.
|
|
|
|
*
|
|
|
|
* 214 4/21/99 11:06a Kevin
|
|
|
|
* new ps_rand and ps_srand to replace rand & srand
|
|
|
|
*
|
|
|
|
* 213 4/21/99 10:12a Chris
|
|
|
|
* Tweaked robot/player damage
|
|
|
|
*
|
|
|
|
* 212 4/21/99 3:33a Chris
|
|
|
|
* Collisions between robots and players cause damage to both robots and
|
|
|
|
* players (robots get more damage)
|
|
|
|
*
|
|
|
|
* 211 4/19/99 12:03p Jason
|
|
|
|
* added checking for fireball collisions
|
|
|
|
*
|
|
|
|
* 210 4/19/99 4:02a Jeff
|
|
|
|
* fixed min/max for Linux
|
|
|
|
*
|
|
|
|
* 209 4/18/99 10:55p Chris
|
|
|
|
* Added ignore own concussive blasts
|
|
|
|
*
|
|
|
|
* 208 4/16/99 8:18p Jason
|
|
|
|
* make impact spawning weapons work with doors
|
|
|
|
*
|
|
|
|
* 207 4/14/99 1:42a Jeff
|
|
|
|
* fixed case mismatched #includes
|
|
|
|
*
|
|
|
|
* 206 4/12/99 6:15p Samir
|
|
|
|
* Sound priorities pass 1
|
|
|
|
*
|
|
|
|
* 205 4/06/99 6:24p Jason
|
|
|
|
* various fixes for multiplayer
|
|
|
|
*
|
|
|
|
* 204 3/23/99 4:10p Jason
|
|
|
|
* more tweaks for line sparks
|
|
|
|
*
|
|
|
|
* 203 3/23/99 12:50p Jason
|
|
|
|
* added line sparks
|
|
|
|
*
|
|
|
|
* 202 3/22/99 6:41p Jason
|
|
|
|
* fixed client side weapons not reacting correctly to bouncing code
|
|
|
|
*
|
|
|
|
* 201 3/22/99 1:47p Matt
|
|
|
|
* Moved breaking glass code from collide.cpp to damage.cpp
|
|
|
|
*
|
|
|
|
* 200 3/16/99 4:16p Matt
|
|
|
|
* Made mass driver spin the victim more. (Jason had reduced it from 0.25
|
|
|
|
* to 0.05; I've moved it back up to 0.12 at Andy's request.)
|
|
|
|
*
|
|
|
|
* 199 3/12/99 7:46p Jeff
|
|
|
|
* record wall hit collisions to demo file
|
|
|
|
*
|
|
|
|
* 198 3/11/99 5:55p Jason
|
|
|
|
* fixed player spin with mass driver
|
|
|
|
*
|
|
|
|
* 197 3/05/99 2:12p Matt
|
|
|
|
* Fixed bug (in a slightly hacky way) where energy weapons would cause
|
|
|
|
* glass to switch to the damaged texture. For a real fix, we need a
|
|
|
|
* separate breakable glass flag for textures.
|
|
|
|
*
|
|
|
|
* 196 3/03/99 10:52a Chris
|
|
|
|
* Energy weapons push again
|
|
|
|
*
|
|
|
|
* 195 3/03/99 5:44a Chris
|
|
|
|
* Max secondary burn time of 10 seconds
|
|
|
|
*
|
|
|
|
* 194 3/01/99 3:18p Jason
|
|
|
|
* made powerups work correctly in multiplayer
|
|
|
|
*
|
|
|
|
* 193 2/28/99 11:29p Chris
|
|
|
|
* Improved robot-wall reactions
|
|
|
|
*
|
|
|
|
* 192 2/22/99 2:03p Jason
|
|
|
|
* added different damages for players and generics
|
|
|
|
*
|
|
|
|
* 191 2/21/99 4:35p Chris
|
|
|
|
* Improving the level goal system... Not done.
|
|
|
|
*
|
|
|
|
* 190 2/20/99 10:31a Kevin
|
|
|
|
* OEM Beta 1 fixs
|
|
|
|
*
|
|
|
|
* 189 2/19/99 12:35p Chris
|
|
|
|
* Player can fly through markers
|
|
|
|
*
|
|
|
|
* 188 2/17/99 4:50p Jason
|
|
|
|
* fixed destroyable face/breakable glass bug
|
|
|
|
*
|
|
|
|
* 187 2/17/99 1:26p Matt
|
|
|
|
* Fixed the die angle system for weapons (changing it around a little in
|
|
|
|
* the process: now all non-weapons (which don't use the system) should
|
|
|
|
* have dot == -1, weapons that die at any angle have dot == 0, and
|
|
|
|
* setting dot == 1 means it never dies).
|
|
|
|
*
|
|
|
|
* 186 2/16/99 8:16a Chris
|
|
|
|
* Fixed a bug - THANKS!
|
|
|
|
*
|
|
|
|
* 185 2/10/99 1:48p Matt
|
|
|
|
* Changed object handle symbolic constants
|
|
|
|
*
|
|
|
|
* 184 2/09/99 2:38p Jason
|
|
|
|
* added destroyable faces
|
|
|
|
*
|
|
|
|
* 183 2/02/99 8:44a Chris
|
|
|
|
* I made buildings with AI work correctly (ie really big robots should be
|
|
|
|
* buildings)
|
|
|
|
* anim to and from states are now shorts instead of bytes
|
|
|
|
*
|
|
|
|
* 182 1/31/99 7:26p Matt
|
|
|
|
* Renamed a bunch of functions to have HUD capitalized
|
|
|
|
*
|
|
|
|
* 181 1/29/99 5:09p Chris
|
|
|
|
* Made changes for ROCKS
|
|
|
|
*
|
|
|
|
* 180 1/28/99 6:17p Jason
|
|
|
|
* added markers
|
|
|
|
*
|
|
|
|
* 179 1/26/99 6:39p Jason
|
|
|
|
* added wall effects code
|
|
|
|
*
|
|
|
|
* 178 1/25/99 5:59p Matt
|
|
|
|
* Patched the masses of objects
|
|
|
|
*
|
|
|
|
* 177 1/24/99 8:18p Chris
|
|
|
|
* Updated AI and OSIRIS. Externalized fireball constants for spew and
|
|
|
|
* sparks. Added CreateRandomSparks to OSIRIS, renamed a bunch of AI
|
|
|
|
* Notify names to use underscores. Fixed a memory access leak in the
|
|
|
|
* matcen effect code.
|
|
|
|
*
|
|
|
|
* 176 1/23/99 5:16p Chris
|
|
|
|
* Bounds fixed acos and asin stuff (-1.0000000000001 could cause really
|
|
|
|
* bad things to happen with rot. vels)
|
|
|
|
*
|
|
|
|
* 175 1/20/99 10:50a Jason
|
|
|
|
* added new terrain
|
|
|
|
*
|
|
|
|
* 174 1/20/99 2:13a Chris
|
|
|
|
* It is now possible for robots to have special immunities, resistances,
|
|
|
|
* and vunerabilities
|
|
|
|
*
|
|
|
|
* 173 1/18/99 12:12a Jeff
|
|
|
|
* removed weapon collide event, combined it in general collide event.
|
|
|
|
* general collide event handles more collides. Added a room collide
|
|
|
|
* event
|
|
|
|
*
|
|
|
|
* 172 1/15/99 3:59a Jeff
|
|
|
|
* added two new multiplayer DLL events for weapon collisions. Added two
|
|
|
|
* new fields to DLLInfo data, point and normal, which are filled out for
|
|
|
|
* collision events.
|
|
|
|
*
|
|
|
|
* 170 1/10/99 7:35p Matt
|
|
|
|
* Added missing break to DO_COLLISION macor
|
|
|
|
*
|
|
|
|
* 169 1/10/99 6:49a Jeff
|
|
|
|
* Some initial work to get linux version to compile
|
|
|
|
*
|
|
|
|
* 168 1/08/99 2:56p Samir
|
|
|
|
* Ripped out OSIRIS1.
|
|
|
|
*
|
|
|
|
* 167 1/01/99 4:10p Chris
|
|
|
|
* Added some const parameters, improved ray cast object collide/rejection
|
|
|
|
* code
|
|
|
|
*
|
|
|
|
* 166 12/21/98 10:50a Chris
|
|
|
|
* You can now push walking objects
|
|
|
|
*
|
|
|
|
* 165 12/17/98 12:08p Jeff
|
|
|
|
* first checkin of new implementation of OSIRIS (old OSIRIS no longer
|
|
|
|
* works)
|
|
|
|
*
|
|
|
|
* 164 11/19/98 3:54p Chris
|
|
|
|
*
|
|
|
|
* 163 11/19/98 3:51p Chris
|
|
|
|
* Shooting dying robots makes them blow up faster (but now not as
|
|
|
|
* quickly)
|
|
|
|
*
|
|
|
|
* 162 11/13/98 4:25p Jason
|
|
|
|
* changes for better weapon effects
|
|
|
|
*
|
|
|
|
* 161 11/13/98 1:00p Chris
|
|
|
|
* Fixed a math problem with the new collision response code. Zero rad
|
|
|
|
* particles where causing i1 or i2 to be zero. c1 = c1/i1 -> it was
|
|
|
|
* going to infinity. So, I made a floor threshold for i1 and i2
|
|
|
|
*
|
|
|
|
* 160 11/11/98 2:46p Kevin
|
|
|
|
* Demo recording system work
|
|
|
|
*
|
|
|
|
* 159 11/10/98 5:17p Jeff
|
|
|
|
* peppered in some more forcefeedback effects
|
|
|
|
*
|
|
|
|
* 158 10/30/98 5:17p Chris
|
|
|
|
* Players only get 1/4 the rotational velocity of an impulse
|
|
|
|
*
|
|
|
|
* 157 10/29/98 1:45p Chris
|
|
|
|
* Checked in the better collision response code
|
|
|
|
*
|
|
|
|
* 156 10/22/98 12:57p Chris
|
|
|
|
* Added sounds to player/player and player/robot collisions
|
|
|
|
*
|
|
|
|
* 155 10/20/98 1:26p Jason
|
|
|
|
* took out spawning on direct hits
|
|
|
|
*
|
|
|
|
* 154 10/20/98 12:10p Chris
|
|
|
|
*
|
|
|
|
* 153 10/19/98 8:38p Matt
|
|
|
|
* Don't make a sound when colliding with lava, since the lava will start
|
|
|
|
* you on fire, which will make sound.
|
|
|
|
*
|
|
|
|
* 152 10/19/98 7:19p Matt
|
|
|
|
* Added system to support different types of damage to the player and
|
|
|
|
* have these different types make different sounds.
|
|
|
|
*
|
|
|
|
* 151 10/18/98 2:09p Matt
|
|
|
|
* Made the backquote/flare thing go away in release versions, and made it
|
|
|
|
* work for terrain cells.
|
|
|
|
*
|
|
|
|
* 150 10/17/98 12:25p Chris
|
|
|
|
* Fixed attached flares
|
|
|
|
*
|
|
|
|
* 149 10/16/98 5:25p Chris
|
|
|
|
* Fixed sticky code
|
|
|
|
*
|
|
|
|
* 148 10/16/98 4:33p Chris
|
|
|
|
*
|
|
|
|
* 147 10/16/98 4:18p Chris
|
|
|
|
* Fixed the 'flare thing'
|
|
|
|
*
|
|
|
|
* 146 10/16/98 3:39p Chris
|
|
|
|
* Improved the object linking system and AI and physics
|
|
|
|
*
|
|
|
|
* 145 10/15/98 4:51p Chris
|
|
|
|
* Speed up dying for player too
|
|
|
|
*
|
|
|
|
* 144 10/15/98 4:49p Chris
|
|
|
|
* Speed up dying if the robot is getting hit
|
|
|
|
*
|
|
|
|
* 143 10/12/98 2:27p Matt
|
|
|
|
* Fixed code to print room:face when backquote/tilde held down and flare
|
|
|
|
* hits the wall.
|
|
|
|
*
|
|
|
|
* 142 10/12/98 10:04a Chris
|
|
|
|
* Wall hits cannot kill the player
|
|
|
|
*
|
|
|
|
* 141 10/09/98 7:57p Chris
|
|
|
|
* Added the flare room/wall cheat
|
|
|
|
*
|
|
|
|
* 140 10/09/98 7:47p Chris
|
|
|
|
* Added ObjSetDeadFlag
|
|
|
|
*
|
|
|
|
* 139 10/08/98 12:00p Kevin
|
|
|
|
* Demo system work
|
|
|
|
*
|
|
|
|
* 138 10/05/98 7:23p Jason
|
|
|
|
* implemented destroyable lights (first draft)
|
|
|
|
*
|
|
|
|
* 137 10/01/98 6:56p Jason
|
|
|
|
* turned off energy weapon hit effects if the object getting hit is the
|
|
|
|
* viewer - this helps cut down on the general clutter in heavy combat
|
|
|
|
*
|
|
|
|
* 136 9/29/98 4:48p Chris
|
|
|
|
* Working on multiplayer collisions
|
|
|
|
*
|
|
|
|
* 135 9/23/98 5:04p Chris
|
|
|
|
* Raised the collide wall damage threshold
|
|
|
|
*
|
|
|
|
* 134 9/23/98 3:47p Chris
|
|
|
|
* Increased the speed to cause damage from wall hits
|
|
|
|
*
|
|
|
|
* 133 9/22/98 12:23p Chris
|
|
|
|
* Further improvements to wall hitting
|
|
|
|
*
|
|
|
|
* 132 9/21/98 8:32p Chris
|
|
|
|
* Another improvement to the forcefield stuff
|
|
|
|
*
|
|
|
|
* 131 9/21/98 8:19p Chris
|
|
|
|
* Improved volatile and forcefield hits
|
|
|
|
*
|
|
|
|
* 130 9/21/98 1:08p Chris
|
|
|
|
* Improved lava handling
|
|
|
|
*
|
|
|
|
* 129 9/21/98 1:04p Chris
|
|
|
|
*
|
|
|
|
* 128 9/21/98 1:03p Chris
|
|
|
|
*
|
|
|
|
* 127 9/21/98 1:01p Chris
|
|
|
|
* Fixed more volatile problems
|
|
|
|
*
|
|
|
|
* 126 9/21/98 11:44a Chris
|
|
|
|
* Fixed the volatile terrain crash bug
|
|
|
|
*
|
|
|
|
* 125 9/18/98 7:45p Chris
|
|
|
|
* Lava works - needs tweaking.
|
|
|
|
*
|
|
|
|
* 124 8/25/98 7:27p Chris
|
|
|
|
* Improved the scorch code
|
|
|
|
*
|
|
|
|
* 123 8/25/98 7:23p Chris
|
|
|
|
* Made weapons explode even if they break glass
|
|
|
|
*
|
|
|
|
* 122 8/25/98 12:35p Chris
|
|
|
|
* Fixed a small reversed normal bug
|
|
|
|
*
|
|
|
|
* 121 8/19/98 2:48p Jason
|
|
|
|
* fixed some weapon firing and weapon exploding bugs
|
|
|
|
*
|
|
|
|
* 120 8/18/98 7:12p Chris
|
|
|
|
* Improved FUSION behavior.
|
|
|
|
*
|
|
|
|
* 119 8/12/98 12:26p Chris
|
|
|
|
*
|
|
|
|
* 118 8/05/98 11:16a Matt
|
|
|
|
* Added trigger checks when weapons and the player collide with walls.
|
|
|
|
*
|
|
|
|
* 117 8/03/98 5:56p Jason
|
|
|
|
* got fusion cannon working correctly
|
|
|
|
*
|
|
|
|
* 116 7/31/98 11:52a Chris
|
|
|
|
* Weapons can be persistent. Added ability for objects to be manually
|
|
|
|
* set for no object collisions.
|
|
|
|
*
|
|
|
|
* 115 7/30/98 11:09a Jason
|
|
|
|
* added weapons that freeze and deform terrain
|
|
|
|
*
|
|
|
|
* 114 7/22/98 4:36p Jason
|
|
|
|
* took out bugs from observer mode
|
|
|
|
*
|
|
|
|
* 113 7/17/98 10:12a Chris
|
|
|
|
*
|
|
|
|
* 112 7/01/98 12:56p Jason
|
|
|
|
* more changes for countermeasures
|
|
|
|
*
|
|
|
|
* 111 7/01/98 12:12p Jason
|
|
|
|
* added countermeasures
|
|
|
|
*
|
|
|
|
* 110 6/24/98 3:56p Jason
|
|
|
|
* added code for new omega cannon
|
|
|
|
*
|
|
|
|
* 109 6/15/98 3:23p Chris
|
|
|
|
* Single point walker update
|
|
|
|
*
|
|
|
|
* 108 6/15/98 7:53a Chris
|
|
|
|
* Fixed a comment'ed out variable
|
|
|
|
*
|
|
|
|
* 107 6/15/98 7:52a Chris
|
|
|
|
* Removed the new "cool" physics
|
|
|
|
*
|
|
|
|
* 106 6/11/98 12:48p Jason
|
|
|
|
* added better spewing weapons
|
|
|
|
*
|
|
|
|
* 105 6/04/98 12:00p Matt
|
|
|
|
* Took out Napalm Rocket hack that I added for the E3 demo.
|
|
|
|
*
|
|
|
|
* 104 6/02/98 10:43p Chris
|
|
|
|
* Multipoint collision detection enabled
|
|
|
|
*
|
|
|
|
* 103 6/01/98 9:23p Chris
|
|
|
|
* Fixed a bunch of collision problems
|
|
|
|
*
|
|
|
|
* 102 5/27/98 6:18p Matt
|
|
|
|
* Super hack to reduce impact damage of napalm rocket (for E3 only)
|
|
|
|
*
|
|
|
|
* 101 5/27/98 6:08p Chris
|
|
|
|
* Added weapon to generic sound
|
|
|
|
*
|
|
|
|
* 100 5/26/98 4:17p Jason
|
|
|
|
* made scripts/dlls not collide every single frame
|
|
|
|
*
|
|
|
|
* 99 5/26/98 3:58p Matt
|
|
|
|
* Only matter weapons now break glass.
|
|
|
|
*
|
|
|
|
* 98 5/25/98 8:36p Matt
|
|
|
|
* Added code to set different sizes for different weapon scorch marks.
|
|
|
|
* Also, don't leave scorch marks on lights.
|
|
|
|
*
|
|
|
|
* 97 5/22/98 12:34p Matt
|
|
|
|
* Added scorch mark/bullet hole system.
|
|
|
|
*
|
|
|
|
* 96 5/22/98 11:59a Chris
|
|
|
|
* Fixed improper uses of FindSoundName and made the proper static sounds
|
|
|
|
*
|
|
|
|
* 95 5/19/98 4:42a Chris
|
|
|
|
* Added shockwave's -- enjoy. :)
|
|
|
|
*
|
|
|
|
* 94 5/07/98 2:52p Chris
|
|
|
|
* Removed a bounce mprintf
|
|
|
|
*
|
|
|
|
* 93 5/07/98 2:40p Chris
|
|
|
|
* Added death_dot and bounce sound for weapons
|
|
|
|
*
|
|
|
|
* 92 5/07/98 2:22p Chris
|
|
|
|
* Hit die dot
|
|
|
|
*
|
|
|
|
* 91 5/06/98 7:07p Samir
|
|
|
|
* when player is completely dead, don't call script too.
|
|
|
|
*
|
|
|
|
* 90 5/05/98 3:42p Chris
|
|
|
|
* Code cleanup and fixed the collide_XXX_with_wall code. The wall_normal
|
|
|
|
* was know by fvi; so, it is passed to the function (instead of
|
|
|
|
* generating it again)
|
|
|
|
*
|
|
|
|
* 89 5/04/98 3:51p Matt
|
|
|
|
* Finished (for now) with breaking glass.
|
|
|
|
*
|
|
|
|
* 88 5/04/98 1:00p Jason
|
|
|
|
* changed the way weapon explosions work
|
|
|
|
*
|
|
|
|
* 87 5/04/98 12:47p Matt
|
|
|
|
* Improvements to the breaking glass system, though I don't consider it
|
|
|
|
* anywhere near done yet.
|
|
|
|
*
|
|
|
|
* 86 5/03/98 10:24p Matt
|
|
|
|
* Partially completed breaking glass code, checked in so Chris can fix a
|
|
|
|
* bug
|
|
|
|
*
|
|
|
|
* 85 4/23/98 7:14p Chris
|
|
|
|
* Changed non-moving objects to player collisions
|
|
|
|
*
|
|
|
|
* 84 4/22/98 9:43p Chris
|
|
|
|
* More AI improvements
|
|
|
|
*
|
|
|
|
* 83 4/22/98 3:25p Jason
|
|
|
|
* changes for multiplayer debugging
|
|
|
|
*
|
|
|
|
* 82 4/20/98 4:47p Chris
|
|
|
|
* Made collision stuff more accurate
|
|
|
|
*
|
|
|
|
* 81 4/17/98 2:00p Jason
|
|
|
|
* added cool object effects
|
|
|
|
*
|
|
|
|
* 80 4/15/98 12:56p Chris
|
|
|
|
* Reformatted some code
|
|
|
|
*
|
|
|
|
* 79 4/09/98 5:18p Jason
|
|
|
|
* got guided working in multiplayer
|
|
|
|
*
|
|
|
|
* 78 4/09/98 12:05p Chris
|
|
|
|
* Added parenting for all object types. :)
|
|
|
|
*
|
|
|
|
* 77 4/08/98 11:16a Chris
|
|
|
|
* Fixed powerup pickup bug
|
|
|
|
*
|
|
|
|
* 76 4/07/98 4:25p Chris
|
|
|
|
* Added support for buddy bot
|
|
|
|
*
|
|
|
|
* 75 4/06/98 11:59a Chris
|
|
|
|
* Fixed powerup/powerup hack
|
|
|
|
*
|
|
|
|
* 74 3/31/98 5:56p Jason
|
|
|
|
* changes for multiplay
|
|
|
|
*
|
|
|
|
* 73 3/30/98 5:12p Jason
|
|
|
|
* more changes for game/dll integration
|
|
|
|
*
|
|
|
|
* 72 3/20/98 9:34p Jason
|
|
|
|
* added SetObjectDeadFlag inlined function
|
|
|
|
*
|
|
|
|
* 71 3/20/98 6:39p Jason
|
|
|
|
* 100.0 to 1.0 for volume
|
|
|
|
*
|
|
|
|
* 70 3/20/98 3:54p Chris
|
|
|
|
* Working on adding sounds to the game. :)
|
|
|
|
*
|
|
|
|
* 69 3/20/98 3:21p Chris
|
|
|
|
* Added player hit by weapon sound.
|
|
|
|
*
|
|
|
|
* 68 3/20/98 2:59p Chris
|
|
|
|
* Added a wall hit sound for the player and added support for a base
|
|
|
|
* volume for 3d sounds
|
|
|
|
*
|
|
|
|
* 67 3/19/98 7:15p Jason
|
|
|
|
* more changes for multiplayer
|
|
|
|
*
|
|
|
|
* 66 3/19/98 3:44p Chris
|
|
|
|
* Multiplayer enchancement for collisions
|
|
|
|
*
|
|
|
|
* 65 3/19/98 3:27p Chris
|
|
|
|
* Did some collision code for multiplayer.
|
|
|
|
*
|
|
|
|
* 64 3/18/98 5:45p Jason
|
|
|
|
* more multiplayer script integration
|
|
|
|
*
|
|
|
|
* 63 3/17/98 6:17p Jason
|
|
|
|
* added gamemode collide stuff
|
|
|
|
*
|
|
|
|
* 62 3/17/98 11:27a Chris
|
|
|
|
* Added object bump notifies for AI
|
|
|
|
*
|
|
|
|
* 61 3/13/98 5:55p Chris
|
|
|
|
* Added the new collision spheres
|
|
|
|
*
|
|
|
|
* 60 2/23/98 5:46p Chris
|
|
|
|
* Removed some old code.
|
|
|
|
*
|
|
|
|
* 59 2/18/98 11:48a Craig
|
|
|
|
*
|
|
|
|
* 58 2/11/98 4:10p Jason
|
|
|
|
* got spawning impact weapons working
|
|
|
|
*
|
|
|
|
* 57 2/05/98 2:54p Jason
|
|
|
|
* changes for explosions
|
|
|
|
*
|
|
|
|
* 56 2/05/98 2:02p Chris
|
|
|
|
* Fixed the hitseg and hitwall in collide_object_with_wall and
|
|
|
|
* scrape_object_with_wall
|
|
|
|
*
|
|
|
|
* 55 2/04/98 6:09p Matt
|
|
|
|
* Changed object room number to indicate a terrain cell via a flag. Got
|
|
|
|
* rid of the object flag which used to indicate terrain.
|
|
|
|
*
|
|
|
|
* 54 1/30/98 2:54p Matt
|
|
|
|
* Took script calls out of bump_two_objects, since they alread existed in
|
|
|
|
* collide_two_objects
|
|
|
|
*
|
|
|
|
* 53 1/29/98 5:48p Matt
|
|
|
|
* Got rid of marker objects
|
|
|
|
*
|
|
|
|
* 52 1/29/98 4:16p Matt
|
|
|
|
* Fixed some problems from my last changes
|
|
|
|
*
|
|
|
|
* 51 1/29/98 3:11p Matt
|
|
|
|
* Clean up a bit: deleted commented-out code, removed leftover D1/D2
|
|
|
|
* stuff, removed references to hostage objects
|
|
|
|
*
|
|
|
|
* 50 1/28/98 12:00p Jason
|
|
|
|
* more changes for multiplayer
|
|
|
|
*
|
|
|
|
* 49 1/26/98 11:01a Jason
|
|
|
|
* incremental checkin for multiplayer
|
|
|
|
*
|
|
|
|
* 48 1/23/98 11:21a Jason
|
|
|
|
* incremental multiplayer checkin
|
|
|
|
*
|
|
|
|
* 47 1/21/98 6:09p Jason
|
|
|
|
* Got player deaths working in multiplayer
|
|
|
|
*
|
|
|
|
* 46 1/21/98 3:05p Samir
|
|
|
|
* Changed a function call to StartPlayerExplosion
|
|
|
|
*
|
|
|
|
* 45 1/21/98 1:11p Jason
|
|
|
|
* incremental checkin for multiplayer
|
|
|
|
*
|
|
|
|
* 44 1/20/98 12:10p Jason
|
|
|
|
* implemented vis effect system
|
|
|
|
*
|
|
|
|
* 43 1/19/98 10:04a Matt
|
|
|
|
* Added new object handle system
|
|
|
|
*
|
|
|
|
* 42 1/14/98 7:57p Chris
|
|
|
|
* Improving the awareness system
|
|
|
|
*
|
|
|
|
* 41 1/14/98 1:23p Jason
|
|
|
|
* made ApplyDamageToGeneric send the weapons parent as the killer
|
|
|
|
*
|
|
|
|
* 40 1/09/98 4:13p Chris
|
|
|
|
* Reformatted some code
|
|
|
|
*
|
|
|
|
* 39 1/09/98 4:11p Chris
|
|
|
|
* Removed a mprintf
|
|
|
|
*
|
|
|
|
* 38 12/22/97 6:19p Chris
|
|
|
|
* Moved weapon battery firing sound off the projectile (weapon) and into
|
|
|
|
* the weapon battery.
|
|
|
|
*
|
|
|
|
* 37 12/15/97 11:03a Jason
|
|
|
|
* make sparks only when successfully hit
|
|
|
|
*
|
|
|
|
* 36 12/12/97 6:13p Jason
|
|
|
|
* added sparks
|
|
|
|
*
|
|
|
|
* 35 12/10/97 2:36p Jason
|
|
|
|
* added random small explosions
|
|
|
|
*
|
|
|
|
* 34 12/04/97 12:15p Jason
|
|
|
|
* gave designers the ability to set their own weapon-to-wall hit vclips
|
|
|
|
*
|
|
|
|
* 33 12/01/97 9:54a Chris
|
|
|
|
* Added support for concussive forces, generalized robot collisions to
|
|
|
|
* generic collisions
|
|
|
|
*
|
|
|
|
* 32 11/20/97 1:38p Chris
|
|
|
|
* No rotation is applied to player objects
|
|
|
|
*
|
|
|
|
* 31 11/13/97 5:06p Chris
|
|
|
|
* Added support for clutter to weapon collisions
|
|
|
|
*
|
|
|
|
* 30 11/05/97 6:42p Jason
|
|
|
|
* took out stupid blast ring
|
|
|
|
*
|
|
|
|
* 29 10/29/97 1:29p Chris
|
|
|
|
* Added PF_STICK for weapons
|
|
|
|
*
|
|
|
|
* 28 10/24/97 2:30p Jason
|
|
|
|
* more changes for explosions
|
|
|
|
*
|
|
|
|
* 27 10/23/97 11:14a Jason
|
|
|
|
* changed some fireball DEFINEs
|
|
|
|
*
|
|
|
|
* 26 10/22/97 7:26p Samir
|
|
|
|
* Player death mostly working. Damn hangup still occurs. Freaky.
|
|
|
|
*
|
|
|
|
* 25 10/22/97 4:30p Chris
|
|
|
|
* We can now slew between the mine and the terrain
|
|
|
|
*
|
|
|
|
* 24 10/22/97 11:44a Jason
|
|
|
|
* changes for explosion system
|
|
|
|
*
|
|
|
|
* 23 10/21/97 4:15p Chris
|
|
|
|
* Incremental integration of the fvi/physics/collide code
|
|
|
|
*
|
|
|
|
* 22 10/20/97 4:46p Jason
|
|
|
|
* changes for explosions
|
|
|
|
*
|
|
|
|
* 21 10/20/97 11:55a Chris
|
|
|
|
* Added some support for the new collide system.
|
|
|
|
*
|
|
|
|
* 20 10/16/97 3:46p Chris
|
|
|
|
* Incremental improvements
|
|
|
|
*
|
|
|
|
* 19 10/03/97 3:47p Chris
|
|
|
|
* Moved script calls to bump two objects (so building can have scripts)
|
|
|
|
*
|
|
|
|
* 18 10/03/97 3:45p Chris
|
|
|
|
* Added some bumping force by weapons
|
|
|
|
*
|
|
|
|
* 17 10/03/97 3:18p Samir
|
|
|
|
* Added script hook to bump_this_object
|
|
|
|
*
|
|
|
|
* 16 10/02/97 11:34a Chris
|
|
|
|
* Added support for external room collisions
|
|
|
|
*
|
|
|
|
* 15 10/01/97 4:51p Samir
|
|
|
|
* Include damage.h
|
|
|
|
*
|
|
|
|
* 14 9/19/97 9:37p Chris
|
|
|
|
* Attempted to fix door collisions -- almost there, but not quite
|
|
|
|
*
|
|
|
|
* 13 9/15/97 5:17a Chris
|
|
|
|
* Removed the Explosion Vclips since they do not play correctly in
|
|
|
|
* Hardware
|
|
|
|
* Added support for building collisons.
|
|
|
|
* working on SPhere to non-moving sphere collisions
|
|
|
|
*
|
|
|
|
* 12 9/12/97 6:36p Chris
|
|
|
|
* Added building collisions
|
|
|
|
*
|
|
|
|
* 11 9/05/97 12:27p Samir
|
|
|
|
* Player takes damage and set death if needed.
|
|
|
|
*
|
|
|
|
* 10 9/04/97 12:03p Matt
|
|
|
|
* Got rid of warnings
|
|
|
|
*
|
|
|
|
* 9 9/03/97 2:13p Chris
|
|
|
|
* Working on improving the debris system and partical explosions
|
|
|
|
*
|
|
|
|
* 8 8/21/97 7:53p Chris
|
|
|
|
*
|
|
|
|
* 7 8/21/97 7:52p Chris
|
|
|
|
*
|
|
|
|
* 6 8/18/97 1:46a Chris
|
|
|
|
* Allowed for robot damage and destoyable objects.
|
|
|
|
* Also, allowed weapons to bounce
|
|
|
|
*
|
|
|
|
* 5 8/14/97 11:44a Samir
|
|
|
|
* Don't kill powerups. Let script do it.
|
|
|
|
*
|
|
|
|
* 4 8/12/97 3:32p Samir
|
|
|
|
* collisions call script code now too.
|
|
|
|
*
|
|
|
|
* 3 8/11/97 1:54p Matt
|
|
|
|
* Ripped out robot & powerup pages, and added generic page
|
|
|
|
*
|
|
|
|
* 2 7/28/97 1:16p Chris
|
|
|
|
* Allow for player and robots to be hit by weapons and correct parenting
|
|
|
|
* of weapons.
|
|
|
|
*
|
|
|
|
* 16 5/19/97 5:39 PM Jeremy
|
|
|
|
* removed "we hit a robot" mprintf
|
|
|
|
*
|
|
|
|
* 15 5/15/97 6:09p Chris
|
|
|
|
*
|
|
|
|
* 14 5/13/97 5:52p Chris
|
|
|
|
* Added ability to exit and enter mine. Also did some
|
|
|
|
* incremental improvements.
|
|
|
|
*
|
|
|
|
* 13 5/05/97 5:41a Chris
|
|
|
|
* Added some better polygon collision code. It is still rough though.
|
|
|
|
*
|
|
|
|
* 12 4/29/97 8:03a Chris
|
|
|
|
* Improved the sound code. High-level sound now
|
|
|
|
* fully uses the flags in the sound page and it
|
|
|
|
* resulted in a simpilier coding interface :)
|
|
|
|
*
|
|
|
|
* 11 4/24/97 5:42p Jason
|
|
|
|
* got fireball vclips working
|
|
|
|
*
|
|
|
|
* 10 4/24/97 12:28p Jason
|
|
|
|
* added sound when weapon hits a wall
|
|
|
|
*
|
|
|
|
* 9 4/24/97 3:25a Chris
|
|
|
|
* // Added some more support for 3d sounds
|
|
|
|
*
|
|
|
|
* 8 4/23/97 6:34p Chris
|
|
|
|
* // Incremental collision stuff.
|
|
|
|
*
|
|
|
|
* 7 4/23/97 6:06p Jason
|
|
|
|
* made player ship and weapons work correctly together (first pass)
|
|
|
|
*
|
|
|
|
* 6 4/17/97 3:10p Chris
|
|
|
|
* Added edge of world object delete. Also did some incremental
|
|
|
|
* improvements.
|
|
|
|
*
|
|
|
|
* 5 4/11/97 3:05a Chris
|
|
|
|
* Allowed robot sphere collision
|
|
|
|
*
|
|
|
|
* 4 3/15/97 1:29p Chris
|
|
|
|
*
|
|
|
|
* $NoKeywords: $
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include "collide.h"
|
|
|
|
#include "PHYSICS.H"
|
|
|
|
#include "pserror.h"
|
|
|
|
#include "mono.h"
|
|
|
|
#include "object.h"
|
|
|
|
#include "player.h"
|
|
|
|
#include "hlsoundlib.h"
|
|
|
|
#include "weapon.h"
|
|
|
|
#include "damage.h"
|
|
|
|
#include "fireball.h"
|
|
|
|
#include "sounds.h"
|
|
|
|
#include "AIMain.h"
|
|
|
|
#include "multi.h"
|
|
|
|
#include "game.h"
|
|
|
|
#include "soundload.h"
|
|
|
|
#include "game2dll.h"
|
|
|
|
#include "scorch.h"
|
|
|
|
#include "ddio.h"
|
|
|
|
#include "vecmat.h"
|
|
|
|
#include "trigger.h"
|
|
|
|
#include "lighting.h"
|
|
|
|
#include "hud.h"
|
|
|
|
#include "D3ForceFeedback.h"
|
|
|
|
#include "demofile.h"
|
|
|
|
#include "osiris_dll.h"
|
|
|
|
#include "marker.h"
|
|
|
|
#include "hud.h"
|
|
|
|
#include "levelgoal.h"
|
|
|
|
#include "psrand.h"
|
|
|
|
|
|
|
|
#ifdef __LINUX__
|
|
|
|
#define max(a,b) ((a>b)?a:b)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define PLAYER_ROTATION_BY_FORCE_SCALAR 0.12f
|
|
|
|
#define NONPLAYER_ROTATION_BY_FORCE_SCALAR 1.0f
|
|
|
|
|
|
|
|
ubyte CollisionResult[MAX_OBJECT_TYPES][MAX_OBJECT_TYPES];
|
|
|
|
ubyte CollisionRayResult[MAX_OBJECT_TYPES];
|
|
|
|
|
|
|
|
bool IsOKToApplyForce(object *objp)
|
|
|
|
{
|
|
|
|
if(Game_mode & GM_MULTI)
|
|
|
|
{
|
|
|
|
if(objp->type == OBJ_PLAYER)
|
|
|
|
{
|
|
|
|
if(objp != Player_object)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(objp->type!=OBJ_WEAPON && objp->type!=OBJ_POWERUP && Netgame.local_role != LR_SERVER)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (objp->mtype.phys_info.mass == 0.0)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (objp->movement_type != MT_PHYSICS && objp->movement_type != MT_WALKING)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if(objp->mtype.phys_info.flags & PF_PERSISTENT)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (objp->mtype.phys_info.flags & PF_LOCK_MASK) // Not done!
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// -----------------------------------------------------------------------------
|
|
|
|
void bump_this_object(object *objp, object *other_objp, vector *force, vector *collision_pnt, int damage_flag)
|
|
|
|
{
|
|
|
|
// float force_mag;
|
|
|
|
|
|
|
|
if(objp->type == OBJ_PLAYER)
|
|
|
|
{
|
|
|
|
if((Game_mode & GM_MULTI) && (objp != Player_object))
|
|
|
|
return;
|
|
|
|
|
|
|
|
phys_apply_force(objp,force);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if((Game_mode & GM_MULTI) && (objp->type != OBJ_PLAYER && objp->type!=OBJ_POWERUP) && (Netgame.local_role != LR_SERVER))
|
|
|
|
return;
|
|
|
|
|
|
|
|
phys_apply_force(objp,force);
|
|
|
|
phys_apply_rot(objp,force);
|
|
|
|
}
|
|
|
|
|
|
|
|
// if (! (objp->mtype.phys_info.flags & PF_PERSISTENT))
|
|
|
|
// if (objp->type == OBJ_PLAYER) {
|
|
|
|
// vector force2;
|
|
|
|
// force2 = forcex/4;
|
|
|
|
|
|
|
|
// phys_apply_force(objp,&force2);
|
|
|
|
|
|
|
|
// if (damage_flag && ((other_objp->type != OBJ_ROBOT) || !Robot_info[other_objp->id].companion)) {
|
|
|
|
// force_mag = vm_vec_mag_quick(&force2);
|
|
|
|
// apply_force_damage(objp, force_mag, other_objp);
|
|
|
|
// }
|
|
|
|
// } else if ((objp->type == OBJ_ROBOT) || (objp->type == OBJ_CLUTTER) || (objp->type == OBJ_CNTRLCEN)) {
|
|
|
|
// if (!Robot_info[objp->id].boss_flag) {
|
|
|
|
// vector force2;
|
|
|
|
// force2.x = force->x/(4 + Difficulty_level);
|
|
|
|
// force2.y = force->y/(4 + Difficulty_level);
|
|
|
|
// force2.z = force->z/(4 + Difficulty_level);
|
|
|
|
|
|
|
|
// phys_apply_force(objp, force);
|
|
|
|
// phys_apply_rot(objp, &force2);
|
|
|
|
// if (damage_flag) {
|
|
|
|
// force_mag = vm_vec_mag_quick(force);
|
|
|
|
// apply_force_damage(objp, force_mag, other_objp);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
void bump_one_object(object *obj0, vector *hit_dir, float damage)
|
|
|
|
{
|
|
|
|
vector hit_vec;
|
|
|
|
|
|
|
|
hit_vec = *hit_dir;
|
|
|
|
vm_vec_scale(&hit_vec, damage);
|
|
|
|
|
|
|
|
phys_apply_force(obj0,&hit_vec);
|
|
|
|
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
//#define DAMAGE_SCALE 128 // Was 32 before 8:55 am on Thursday, September 15, changed by MK, walls were hurting me more than robots!
|
|
|
|
//#define DAMAGE_THRESHOLD (F1_0/3)
|
|
|
|
//#define WALL_LOUDNESS_SCALE (20)
|
|
|
|
|
|
|
|
//float force_force = 50.0;
|
|
|
|
|
|
|
|
typedef struct v{
|
|
|
|
float i,j;
|
|
|
|
} vec2d;
|
|
|
|
|
|
|
|
#define cross(v0,v1) (((v0)->i * (v1)->j) - ((v0)->j * (v1)->i))
|
|
|
|
|
|
|
|
//finds the uv coords of the given point on the given seg & side
|
|
|
|
//fills in u & v. if l is non-NULL fills it in also
|
|
|
|
void FindHitpointUV(float *u,float *v,vector *point,room *rp,int facenum)
|
|
|
|
{
|
|
|
|
face *fp = &rp->faces[facenum];
|
|
|
|
int ii,jj;
|
|
|
|
vec2d pnt[3],checkp,vec0,vec1;
|
|
|
|
float *t;
|
|
|
|
float k0,k1;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
//1. find what plane to project this wall onto to make it a 2d case
|
|
|
|
|
|
|
|
GetIJ(&fp->normal,&ii,&jj);
|
|
|
|
|
|
|
|
//2. compute u,v of intersection point
|
|
|
|
|
|
|
|
//Copy face points into 2d verts array
|
|
|
|
for (i=0;i<3;i++) {
|
|
|
|
t = &rp->verts[fp->face_verts[i]].x;
|
|
|
|
pnt[i].i = t[ii];
|
|
|
|
pnt[i].j = t[jj];
|
|
|
|
}
|
|
|
|
t = &point->x;
|
|
|
|
checkp.i = t[ii];
|
|
|
|
checkp.j = t[jj];
|
|
|
|
|
|
|
|
//vec from 1 -> 0
|
|
|
|
vec0.i = pnt[0].i - pnt[1].i;
|
|
|
|
vec0.j = pnt[0].j - pnt[1].j;
|
|
|
|
|
|
|
|
//vec from 1 -> 2
|
|
|
|
vec1.i = pnt[2].i - pnt[1].i;
|
|
|
|
vec1.j = pnt[2].j - pnt[1].j;
|
|
|
|
|
|
|
|
k1 = -((cross(&checkp,&vec0) + cross(&vec0,&pnt[1])) / cross(&vec0,&vec1));
|
2024-04-16 13:45:15 +00:00
|
|
|
if (abs((int)vec0.i) > abs((int)vec0.j))
|
2024-04-16 03:43:29 +00:00
|
|
|
k0 = ((-k1 * vec1.i) + checkp.i - pnt[1].i) / vec0.i;
|
|
|
|
else
|
|
|
|
k0 = ((-k1 * vec1.j) + checkp.j - pnt[1].j) / vec0.j;
|
|
|
|
|
|
|
|
//mprintf(0," k0,k1 = %x,%x\n",k0,k1);
|
|
|
|
|
|
|
|
*u = fp->face_uvls[1].u + (k0 * (fp->face_uvls[0].u - fp->face_uvls[1].u)) + (k1 * (fp->face_uvls[2].u - fp->face_uvls[1].u));
|
|
|
|
*v = fp->face_uvls[1].v + (k0 * (fp->face_uvls[0].v - fp->face_uvls[1].v)) + (k1 * (fp->face_uvls[2].v - fp->face_uvls[1].v));
|
|
|
|
|
|
|
|
//mprintf(0," u,v = %x,%x\n",*u,*v);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Creates some effects where a weapon has collided with a wall
|
|
|
|
void DoWallEffects (object *weapon,int surface_tmap)
|
|
|
|
{
|
|
|
|
texture *texp = &GameTextures[surface_tmap];
|
|
|
|
|
|
|
|
if (texp->flags & (TF_VOLATILE+TF_LAVA+TF_WATER))
|
|
|
|
{
|
|
|
|
// Create some lava steam
|
|
|
|
if ((texp->flags & TF_WATER) || ((ps_rand()%4)==0))
|
|
|
|
{
|
|
|
|
int visnum=VisEffectCreate (VIS_FIREBALL,MED_SMOKE_INDEX,weapon->roomnum,&weapon->pos);
|
|
|
|
if (visnum>=0)
|
|
|
|
{
|
|
|
|
vis_effect *vis=&VisEffects[visnum];
|
|
|
|
|
|
|
|
vis->lifetime=.9f;
|
|
|
|
vis->lifeleft=.9f;
|
|
|
|
|
|
|
|
vis->movement_type=MT_PHYSICS;
|
|
|
|
vis->size=3.0;
|
|
|
|
vm_MakeZero (&vis->velocity);
|
|
|
|
vis->velocity.y=10;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (texp->flags & TF_RUBBLE)
|
|
|
|
{
|
|
|
|
if ((ps_rand()%4)==0)
|
|
|
|
{
|
|
|
|
int num_rubble=(ps_rand()%3)+1;
|
|
|
|
int bm_handle=GetTextureBitmap(texp-GameTextures,0);
|
|
|
|
ushort *data=bm_data(bm_handle,0);
|
|
|
|
|
|
|
|
ushort color=data[(bm_w(bm_handle,0)*(bm_h(bm_handle,0)/2))+(bm_w(bm_handle,0)/2)];
|
|
|
|
|
|
|
|
for (int i=0;i<num_rubble;i++)
|
|
|
|
{
|
|
|
|
int visnum;
|
|
|
|
|
|
|
|
visnum=VisEffectCreate (VIS_FIREBALL,RUBBLE1_INDEX+(ps_rand()%2),weapon->roomnum,&weapon->pos);
|
|
|
|
|
|
|
|
if (visnum>=0)
|
|
|
|
{
|
|
|
|
vis_effect *vis=&VisEffects[visnum];
|
|
|
|
|
|
|
|
vis->movement_type=MT_PHYSICS;
|
|
|
|
vis->mass=100;
|
|
|
|
vis->drag=.1f;
|
|
|
|
|
|
|
|
vis->phys_flags|=PF_GRAVITY|PF_NO_COLLIDE;
|
|
|
|
|
|
|
|
if ((ps_rand()%3)==0)
|
|
|
|
{
|
|
|
|
vis->velocity.x=(ps_rand()%100)-50;
|
|
|
|
vis->velocity.y=-((ps_rand()%200)-30);
|
|
|
|
vis->velocity.z=(ps_rand()%100)-50;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
vis->velocity.x=(ps_rand()%300)-50;
|
|
|
|
vis->velocity.y=-((ps_rand()%200)-30);
|
|
|
|
vis->velocity.z=(ps_rand()%300)-50;
|
|
|
|
}
|
|
|
|
|
|
|
|
vm_NormalizeVectorFast (&vis->velocity);
|
|
|
|
vis->velocity*=4+(ps_rand()%20);
|
|
|
|
vis->size=.5+(((ps_rand()%11)-5)*.05);
|
|
|
|
vis->flags|=VF_USES_LIFELEFT;
|
|
|
|
float lifetime=1.0+(((ps_rand()%11)-5)*.1);
|
|
|
|
vis->lifeleft=lifetime;
|
|
|
|
vis->lifetime=lifetime;
|
|
|
|
vis->lighting_color=color;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define FORCEFIELD_DAMAGE 5.0f
|
|
|
|
|
|
|
|
void DeformTerrain (vector *pos,int depth,float size);
|
|
|
|
|
|
|
|
//Check for lava, volatile, or water surface. If contact, make special sound & kill the weapon
|
|
|
|
void check_for_special_surface(object *weapon,int surface_tmap,vector *surface_normal,float hit_dot)
|
|
|
|
{
|
|
|
|
bool f_forcefield,f_volatile,f_lava,f_water;
|
|
|
|
|
|
|
|
f_forcefield = (GameTextures[surface_tmap].flags & TF_FORCEFIELD) != 0;
|
|
|
|
f_volatile = (GameTextures[surface_tmap].flags & TF_VOLATILE) != 0;
|
|
|
|
f_lava = (GameTextures[surface_tmap].flags & TF_LAVA) != 0;
|
|
|
|
f_water = (GameTextures[surface_tmap].flags & TF_WATER) != 0;
|
|
|
|
|
|
|
|
//Kill the weapon if the surface is volatile, lava, or water
|
|
|
|
if (f_volatile || f_lava || f_water) {
|
|
|
|
int snd;
|
|
|
|
ain_hear hear;
|
|
|
|
hear.f_directly_player = false;
|
|
|
|
|
|
|
|
if (f_water)
|
|
|
|
{
|
|
|
|
snd = SOUND_WEAPON_HIT_WATER;
|
|
|
|
hear.hostile_level = 0.2f;
|
|
|
|
hear.curiosity_level = 0.3f;
|
|
|
|
}
|
|
|
|
else if (f_volatile || f_lava)
|
|
|
|
{
|
|
|
|
snd = SOUND_WEAPON_HIT_LAVA;
|
|
|
|
hear.hostile_level = 0.1f;
|
|
|
|
hear.curiosity_level = 0.5f;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
Int3();
|
|
|
|
|
|
|
|
hear.max_dist = Sounds[snd].max_distance;
|
|
|
|
Sound_system.Play3dSound(snd, SND_PRIORITY_NORMAL, weapon);
|
|
|
|
AINotify(weapon, AIN_HEAR_NOISE, (void *)&hear);
|
|
|
|
|
|
|
|
if (! f_water)
|
|
|
|
DoWeaponExploded (weapon, surface_normal);
|
|
|
|
|
|
|
|
SetObjectDeadFlag (weapon);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//Process a collision between a weapon and a wall
|
|
|
|
//Returns true if the weapon hits the wall, and false if should keep going though the wall (for breakable glass)
|
|
|
|
bool collide_weapon_and_wall( object * weapon, fix hitspeed, int hitseg, int hitwall, vector * hitpnt, vector *wall_normal, float hit_dot)
|
|
|
|
{
|
|
|
|
bool f_forcefield;
|
|
|
|
bool f_volatile,f_lava,f_water;
|
|
|
|
//mprintf((0, "Weapon hit wall, how nice.\n"));
|
|
|
|
|
|
|
|
//#ifndef RELEASE
|
|
|
|
if ((stricmp(Weapons[weapon->id].name,"Yellow flare") == 0) &&
|
|
|
|
(weapon->parent_handle == Player_object->handle) &&
|
|
|
|
(KEY_STATE(KEY_LAPOSTRO)))
|
|
|
|
if (ROOMNUM_OUTSIDE(hitseg))
|
|
|
|
AddHUDMessage("Terrain cell %d",CELLNUM(hitseg));
|
|
|
|
else
|
|
|
|
AddHUDMessage("Room %d face %d",hitseg,hitwall);
|
|
|
|
//#endif
|
|
|
|
|
|
|
|
//Check if forcefield
|
|
|
|
int tmap;
|
|
|
|
if (!ROOMNUM_OUTSIDE(hitseg)) //Make sure we've hit a wall, and not terrain
|
|
|
|
{
|
|
|
|
tmap = Rooms[hitseg].faces[hitwall].tmap;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tmap = Terrain_tex_seg[Terrain_seg[CELLNUM(hitseg)].texseg_index].tex_index;
|
|
|
|
}
|
|
|
|
f_forcefield = (GameTextures[tmap].flags & TF_FORCEFIELD) != 0;
|
|
|
|
f_volatile = (GameTextures[tmap].flags & TF_VOLATILE) != 0;
|
|
|
|
f_lava = (GameTextures[tmap].flags & TF_LAVA) != 0;
|
|
|
|
f_water = (GameTextures[tmap].flags & TF_WATER) != 0;
|
|
|
|
|
|
|
|
|
|
|
|
if(f_forcefield && !(Weapons[weapon->id].flags & WF_MATTER_WEAPON))
|
|
|
|
{
|
|
|
|
ain_hear hear;
|
|
|
|
hear.f_directly_player = false;
|
|
|
|
hear.hostile_level = 0.9f;
|
|
|
|
hear.curiosity_level = 0.1f;
|
|
|
|
|
|
|
|
if(sound_override_force_field == -1)
|
|
|
|
hear.max_dist = Sounds[SOUND_FORCEFIELD_BOUNCE].max_distance;
|
|
|
|
else
|
|
|
|
hear.max_dist = Sounds[sound_override_force_field].max_distance;
|
|
|
|
|
|
|
|
AINotify(weapon, AIN_HEAR_NOISE, (void *)&hear);
|
|
|
|
|
|
|
|
if(sound_override_force_field == -1)
|
|
|
|
Sound_system.Play3dSound(SOUND_FORCEFIELD_BOUNCE,SND_PRIORITY_HIGH,weapon);
|
|
|
|
else
|
|
|
|
Sound_system.Play3dSound(sound_override_force_field,SND_PRIORITY_HIGH,weapon);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Check for destroyable or breakable face
|
|
|
|
if (! ROOMNUM_OUTSIDE(hitseg)) //First, make sure we've hit a wall, and not terrain
|
|
|
|
{
|
|
|
|
room *rp = &Rooms[hitseg];
|
|
|
|
face *fp = &rp->faces[hitwall];
|
|
|
|
|
|
|
|
//Check for a trigger on this wall
|
|
|
|
CheckTrigger(hitseg,hitwall,weapon,TT_COLLIDE);
|
|
|
|
|
|
|
|
// Check for a destroyable face
|
|
|
|
if ((GameTextures[fp->tmap].flags & TF_DESTROYABLE) && !(fp->flags & FF_DESTROYED))
|
|
|
|
{
|
|
|
|
int visnum=CreateFireball (hitpnt,SHATTER_INDEX+(ps_rand()%2),hitseg,VISUAL_FIREBALL);
|
|
|
|
|
|
|
|
if (visnum>=0)
|
|
|
|
{
|
|
|
|
// Alter the size of this explosion based on the face size
|
|
|
|
vector verts[MAX_VERTS_PER_FACE];
|
|
|
|
vector center;
|
|
|
|
for (int t=0;t<fp->num_verts;t++)
|
|
|
|
verts[t]=rp->verts[fp->face_verts[t]];
|
|
|
|
|
|
|
|
float size=sqrt(vm_GetCentroid (¢er,verts,fp->num_verts));
|
|
|
|
VisEffects[visnum].size=(size/2);
|
|
|
|
}
|
|
|
|
|
|
|
|
CreateRandomSparks (20,hitpnt,hitseg);
|
|
|
|
|
|
|
|
if(sound_override_glass_breaking == -1)
|
|
|
|
Sound_system.Play3dSound(SOUND_BREAKING_GLASS,SND_PRIORITY_HIGH,weapon);
|
|
|
|
else
|
|
|
|
Sound_system.Play3dSound(sound_override_glass_breaking,SND_PRIORITY_HIGH,weapon);
|
|
|
|
|
|
|
|
fp->flags|=FF_DESTROYED;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Check for a breakable face: If the texture is breakable and it's on a portal
|
|
|
|
//and hit with a matter weapon, break it
|
|
|
|
if ((fp->portal_num != -1) && (GameTextures[fp->tmap].flags & TF_BREAKABLE) && (Weapons[weapon->id].flags & WF_MATTER_WEAPON)) {
|
|
|
|
|
|
|
|
//Do the breaking glass stuff
|
|
|
|
if (!((Game_mode & GM_MULTI) && Netgame.local_role==LR_CLIENT))
|
|
|
|
BreakGlassFace(rp,hitwall,hitpnt,&weapon->mtype.phys_info.velocity);
|
|
|
|
|
|
|
|
ain_hear hear;
|
|
|
|
hear.f_directly_player = false;
|
|
|
|
hear.hostile_level = 0.9f;
|
|
|
|
hear.curiosity_level = 1.0f;
|
|
|
|
if(sound_override_glass_breaking == -1)
|
|
|
|
hear.max_dist = Sounds[SOUND_BREAKING_GLASS].max_distance;
|
|
|
|
else
|
|
|
|
hear.max_dist = Sounds[sound_override_glass_breaking].max_distance;
|
|
|
|
AINotify(weapon, AIN_HEAR_NOISE, (void *)&hear);
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//Add a scorch
|
|
|
|
if ((Weapons[weapon->id].scorch_handle != -1) && !f_water && !f_volatile && !f_lava)
|
|
|
|
AddScorch(hitseg,hitwall,hitpnt,Weapons[weapon->id].scorch_handle,Weapons[weapon->id].scorch_size);
|
|
|
|
|
|
|
|
if (ROOMNUM_OUTSIDE(hitseg))
|
|
|
|
{
|
|
|
|
if (Weapons[weapon->id].terrain_damage_size>0 && Weapons[weapon->id].terrain_damage_depth>0)
|
|
|
|
{
|
|
|
|
DeformTerrain (&weapon->pos,Weapons[weapon->id].terrain_damage_depth,Weapons[weapon->id].terrain_damage_size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//Do special smoke, etc.
|
|
|
|
DoWallEffects (weapon,tmap);
|
|
|
|
|
|
|
|
//look for lava, volatile, water
|
|
|
|
check_for_special_surface(weapon,tmap,wall_normal,hit_dot);
|
|
|
|
|
|
|
|
//If dead, we're done
|
|
|
|
if (weapon->flags & OF_DEAD)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
//If done bouncing, kill the weapon
|
|
|
|
if ((weapon->mtype.phys_info.num_bounces <= 0) && !(weapon->mtype.phys_info.flags & PF_STICK) && (hit_dot > weapon->mtype.phys_info.hit_die_dot))
|
|
|
|
{
|
|
|
|
int snd;
|
|
|
|
ain_hear hear;
|
|
|
|
hear.f_directly_player = false;
|
|
|
|
|
|
|
|
snd = Weapons[weapon->id].sounds[WSI_IMPACT_WALL];
|
|
|
|
hear.hostile_level = 0.9f;
|
|
|
|
hear.curiosity_level = 0.1f;
|
|
|
|
|
|
|
|
if (snd != SOUND_NONE_INDEX)
|
|
|
|
{
|
|
|
|
hear.max_dist = Sounds[snd].max_distance;
|
|
|
|
Sound_system.Play3dSound(snd, SND_PRIORITY_NORMAL, weapon);
|
|
|
|
AINotify(weapon, AIN_HEAR_NOISE, (void *)&hear);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check to see if we should spawn
|
|
|
|
if ((Weapons[weapon->id].flags & WF_SPAWNS_IMPACT) && Weapons[weapon->id].spawn_count>0 && Weapons[weapon->id].spawn_handle>=0)
|
|
|
|
CreateImpactSpawnFromWeapon (weapon, wall_normal);
|
|
|
|
|
|
|
|
if ((Weapons[weapon->id].flags & WF_SPAWNS_ROBOT) && (Weapons[weapon->id].flags & WF_COUNTERMEASURE) && Weapons[weapon->id].robot_spawn_handle>=0)
|
|
|
|
CreateRobotSpawnFromWeapon (weapon);
|
|
|
|
|
|
|
|
DoWeaponExploded (weapon, wall_normal);
|
|
|
|
|
|
|
|
SetObjectDeadFlag (weapon);
|
|
|
|
}
|
|
|
|
else { //weapon is bouncing
|
|
|
|
|
|
|
|
if (Weapons[weapon->id].sounds[WSI_BOUNCE]!=SOUND_NONE_INDEX)
|
|
|
|
{
|
|
|
|
Sound_system.Play3dSound(Weapons[weapon->id].sounds[WSI_BOUNCE], SND_PRIORITY_HIGH, weapon);
|
|
|
|
|
|
|
|
if(Weapons[weapon->id].sounds[WSI_BOUNCE] > -1)
|
|
|
|
{
|
|
|
|
ain_hear hear;
|
|
|
|
hear.f_directly_player = false;
|
|
|
|
hear.hostile_level = 0.20f;
|
|
|
|
hear.curiosity_level = 0.6f;
|
|
|
|
hear.max_dist = Sounds[Weapons[weapon->id].sounds[WSI_BOUNCE]].max_distance;
|
|
|
|
AINotify(weapon, AIN_HEAR_NOISE, (void *)&hear);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Prints out a marker hud message if needed
|
|
|
|
void collide_player_and_marker( object * playerobj, object * marker_obj, vector *collision_point, vector *collision_normal, bool f_reverse_normal, fvi_info *hit_info )
|
|
|
|
{
|
|
|
|
if (playerobj->id==Player_num)
|
|
|
|
{
|
|
|
|
char str[100];
|
|
|
|
sprintf (str,"Marker: %s",MarkerMessages[marker_obj->id]);
|
|
|
|
AddHUDMessage (str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define MIN_WALL_HIT_SOUND_VEL 40.0f
|
|
|
|
#define MAX_WALL_HIT_SOUND_VEL 120.0f
|
|
|
|
#define MIN_PLAYER_WALL_SOUND_TIME .1f
|
|
|
|
#define WALL_DAMAGE 0.5f
|
|
|
|
#define MIN_WALL_HIT_DAMAGE_SHIELDS 5
|
|
|
|
#define MIN_WALL_DAMAGE_SPEED 65.0
|
|
|
|
|
|
|
|
#define VOLATILE_DAMAGE 7.0f //damage per hit
|
|
|
|
|
|
|
|
void collide_player_and_wall( object * playerobj, float hitspeed, int hitseg, int hitwall, vector * hitpt, vector *wall_normal, float hit_dot)
|
|
|
|
{
|
|
|
|
float volume = MAX_GAME_VOLUME;
|
|
|
|
bool f_volatile,f_lava;
|
|
|
|
bool f_forcefield;
|
|
|
|
int tmap;
|
|
|
|
|
|
|
|
if(playerobj->flags & OF_DYING)
|
|
|
|
playerobj->ctype.dying_info.delay_time *= 0.9f;
|
|
|
|
|
|
|
|
//Check for a trigger on this wall
|
|
|
|
if (! ROOMNUM_OUTSIDE(hitseg)) //Make sure we've hit a wall, and not terrain
|
|
|
|
{
|
|
|
|
CheckTrigger(hitseg,hitwall,playerobj,TT_COLLIDE);
|
|
|
|
tmap = Rooms[hitseg].faces[hitwall].tmap;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tmap = Terrain_tex_seg[Terrain_seg[CELLNUM(hitseg)].texseg_index].tex_index;
|
|
|
|
}
|
|
|
|
f_lava = (GameTextures[tmap].flags & TF_LAVA) != 0;
|
|
|
|
f_volatile = (GameTextures[tmap].flags & TF_VOLATILE) != 0;
|
|
|
|
f_forcefield = (GameTextures[tmap].flags & TF_FORCEFIELD) != 0;
|
|
|
|
|
|
|
|
if(f_lava)
|
|
|
|
{
|
|
|
|
if(!((Game_mode & GM_MULTI) && (Netgame.local_role==LR_CLIENT)))
|
|
|
|
{
|
|
|
|
int id = FindWeaponName("NapalmBlob");
|
|
|
|
if(id >= 0)
|
|
|
|
SetNapalmDamageEffect(playerobj,NULL,id);
|
|
|
|
else
|
|
|
|
Int3();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//If volatile, make the sound & apply damage
|
|
|
|
if (f_volatile)
|
|
|
|
{
|
|
|
|
if(playerobj == Player_object)
|
|
|
|
{
|
|
|
|
if ((!(Game_mode & GM_MULTI)) || Netgame.local_role==LR_SERVER)
|
|
|
|
ApplyDamageToPlayer (playerobj, playerobj, PD_VOLATILE_HISS, VOLATILE_DAMAGE);
|
|
|
|
else {
|
|
|
|
Multi_requested_damage_type = PD_VOLATILE_HISS;
|
|
|
|
Multi_requested_damage_amount+=(VOLATILE_DAMAGE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(f_forcefield)
|
|
|
|
{
|
|
|
|
if(playerobj == Player_object && sound_override_force_field == -1)
|
|
|
|
{
|
|
|
|
if ((!(Game_mode & GM_MULTI)) || Netgame.local_role==LR_SERVER)
|
|
|
|
ApplyDamageToPlayer (playerobj, playerobj, PD_ENERGY_WEAPON, FORCEFIELD_DAMAGE);
|
|
|
|
else {
|
|
|
|
Multi_requested_damage_type = PD_ENERGY_WEAPON;
|
|
|
|
Multi_requested_damage_amount+=(FORCEFIELD_DAMAGE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(sound_override_force_field == -1)
|
|
|
|
Sound_system.Play3dSound(SOUND_FORCEFIELD_BOUNCE, SND_PRIORITY_HIGH, playerobj, MAX_GAME_VOLUME);
|
|
|
|
else
|
|
|
|
Sound_system.Play3dSound(sound_override_force_field, SND_PRIORITY_HIGH, playerobj, MAX_GAME_VOLUME);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if(f_forcefield || f_lava || f_volatile)
|
|
|
|
{
|
|
|
|
ain_hear hear;
|
|
|
|
hear.f_directly_player = true;
|
|
|
|
hear.hostile_level = 0.90f;
|
|
|
|
hear.curiosity_level = 0.6f;
|
|
|
|
if(sound_override_force_field == -1)
|
|
|
|
hear.max_dist = Sounds[SOUND_FORCEFIELD_BOUNCE].max_distance;
|
|
|
|
else
|
|
|
|
hear.max_dist = Sounds[sound_override_force_field].max_distance;
|
|
|
|
AINotify(playerobj, AIN_HEAR_NOISE, (void *)&hear);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do sound stuff when a player hits a wall
|
|
|
|
if(!f_forcefield && !f_volatile && !f_lava && hitspeed > MIN_WALL_HIT_SOUND_VEL && Players[playerobj->id].last_hit_wall_sound_time + MIN_PLAYER_WALL_SOUND_TIME < Gametime)
|
|
|
|
{
|
|
|
|
if(hitspeed < MAX_WALL_HIT_SOUND_VEL)
|
|
|
|
{
|
|
|
|
volume = MAX_GAME_VOLUME * (hitspeed - MIN_WALL_HIT_SOUND_VEL)/(MAX_WALL_HIT_SOUND_VEL - MIN_WALL_HIT_SOUND_VEL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(hitspeed > MIN_WALL_DAMAGE_SPEED)
|
|
|
|
{
|
|
|
|
if(playerobj == Player_object && playerobj->shields >= MIN_WALL_HIT_DAMAGE_SHIELDS)
|
|
|
|
{
|
|
|
|
if ((!(Game_mode & GM_MULTI)) || Netgame.local_role==LR_SERVER)
|
|
|
|
ApplyDamageToPlayer (playerobj, playerobj, PD_WALL_HIT, WALL_DAMAGE);
|
|
|
|
else {
|
|
|
|
Multi_requested_damage_type = PD_WALL_HIT;
|
|
|
|
Multi_requested_damage_amount+=(WALL_DAMAGE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Sound_system.Play3dSound(SOUND_PLAYER_HIT_WALL, SND_PRIORITY_NORMAL, playerobj, volume);
|
|
|
|
if(Demo_flags==DF_RECORDING)
|
|
|
|
DemoWrite3DSound(SOUND_PLAYER_HIT_WALL,OBJNUM(playerobj),1,volume);
|
|
|
|
|
|
|
|
ain_hear hear;
|
|
|
|
hear.f_directly_player = true;
|
|
|
|
hear.hostile_level = 0.10f;
|
|
|
|
hear.curiosity_level = 0.5f;
|
|
|
|
hear.max_dist = Sounds[SOUND_PLAYER_HIT_WALL].max_distance * volume;
|
|
|
|
AINotify(playerobj, AIN_HEAR_NOISE, (void *)&hear);
|
|
|
|
|
|
|
|
Players[playerobj->id].last_hit_wall_sound_time = Gametime;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Players[playerobj->id].flags & PLAYER_FLAGS_DYING)
|
|
|
|
StartPlayerExplosion(playerobj->id);
|
|
|
|
|
|
|
|
//Do ForceFeedback
|
|
|
|
//----------------
|
|
|
|
if(playerobj->id == Player_num && ForceIsEnabled() )
|
|
|
|
{
|
|
|
|
DoForceForWall(playerobj,hitspeed,hitseg,hitwall,wall_normal);
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
void collide_generic_and_wall( object * genericobj, float hitspeed, int hitseg, int hitwall, vector * hitpt, vector *wall_normal, float hit_dot)
|
|
|
|
{
|
|
|
|
bool f_volatile,f_lava;
|
|
|
|
bool f_forcefield;
|
|
|
|
float volume = MAX_GAME_VOLUME;
|
|
|
|
|
|
|
|
//Check for a trigger on this wall
|
|
|
|
int tmap;
|
|
|
|
if (! ROOMNUM_OUTSIDE(hitseg)) //Make sure we've hit a wall, and not terrain
|
|
|
|
{
|
|
|
|
CheckTrigger(hitseg,hitwall,genericobj,TT_COLLIDE);
|
|
|
|
tmap = Rooms[hitseg].faces[hitwall].tmap;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
tmap = Terrain_tex_seg[Terrain_seg[CELLNUM(hitseg)].texseg_index].tex_index;
|
|
|
|
}
|
|
|
|
f_forcefield = (GameTextures[tmap].flags & TF_FORCEFIELD) != 0;
|
|
|
|
f_volatile = (GameTextures[tmap].flags & TF_VOLATILE) != 0;
|
|
|
|
f_lava = (GameTextures[tmap].flags & TF_LAVA) != 0;
|
|
|
|
|
|
|
|
if(IS_GUIDEBOT(genericobj))
|
|
|
|
{
|
|
|
|
f_forcefield = false;
|
|
|
|
f_volatile = false;
|
|
|
|
f_lava = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(f_lava)
|
|
|
|
{
|
|
|
|
if(!((Game_mode & GM_MULTI) && (Netgame.local_role==LR_CLIENT)))
|
|
|
|
{
|
|
|
|
int id = FindWeaponName("NapalmBlob");
|
|
|
|
if(id >= 0)
|
|
|
|
SetNapalmDamageEffect(genericobj,NULL,id);
|
|
|
|
else
|
|
|
|
Int3();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//If volatile, make the sound & apply damage
|
|
|
|
if (f_volatile && !((Game_mode & GM_MULTI) && (Netgame.local_role==LR_CLIENT))) {
|
|
|
|
ApplyDamageToGeneric(genericobj, genericobj, GD_VOLATILE_HISS, VOLATILE_DAMAGE);
|
|
|
|
Sound_system.Play3dSound(SOUND_VOLATILE_HISS, SND_PRIORITY_HIGHEST, genericobj, MAX_GAME_VOLUME);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(f_forcefield && !((Game_mode & GM_MULTI) && (Netgame.local_role==LR_CLIENT)))
|
|
|
|
{
|
|
|
|
if(sound_override_force_field == -1)
|
|
|
|
{
|
|
|
|
Sound_system.Play3dSound(SOUND_FORCEFIELD_BOUNCE, SND_PRIORITY_LOW, genericobj, MAX_GAME_VOLUME);
|
|
|
|
ApplyDamageToGeneric(genericobj, genericobj, GD_ENERGY, FORCEFIELD_DAMAGE);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Sound_system.Play3dSound(sound_override_force_field, SND_PRIORITY_LOW, genericobj, MAX_GAME_VOLUME);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(genericobj->control_type != CT_AI)
|
|
|
|
{
|
|
|
|
if(!f_forcefield && !f_volatile && !f_lava && hitspeed > MIN_WALL_HIT_SOUND_VEL)
|
|
|
|
{
|
|
|
|
if(hitspeed < MAX_WALL_HIT_SOUND_VEL)
|
|
|
|
{
|
|
|
|
volume = MAX_GAME_VOLUME * (hitspeed - MIN_WALL_HIT_SOUND_VEL)/(MAX_WALL_HIT_SOUND_VEL - MIN_WALL_HIT_SOUND_VEL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(hitspeed > MIN_WALL_DAMAGE_SPEED)
|
|
|
|
{
|
|
|
|
if ((!(Game_mode & GM_MULTI)) || Netgame.local_role==LR_SERVER)
|
|
|
|
{
|
|
|
|
ApplyDamageToGeneric(genericobj, genericobj, GD_PHYSICS, WALL_DAMAGE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Sound_system.Play3dSound(SOUND_PLAYER_HIT_WALL, SND_PRIORITY_LOW, genericobj, volume);
|
|
|
|
if(Demo_flags==DF_RECORDING)
|
|
|
|
DemoWrite3DSound(SOUND_PLAYER_HIT_WALL,OBJNUM(genericobj),1,volume);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float Last_volatile_scrape_sound_time = 0;
|
|
|
|
|
|
|
|
//this gets called when an object is scraping along the wall
|
|
|
|
void scrape_object_on_wall(object *obj, int hitseg, int hitwall, vector * hitpt, vector *wall_normal )
|
|
|
|
{
|
|
|
|
/* switch (obj->type) {
|
|
|
|
|
|
|
|
case OBJ_PLAYER:
|
|
|
|
|
|
|
|
if (obj->id==Player_num) {
|
|
|
|
int type;
|
|
|
|
|
|
|
|
//mprintf((0, "Scraped segment #%3i, side #%i\n", hitseg, hitside));
|
|
|
|
|
|
|
|
if ((type=check_volatile_wall(obj,hitseg,hitside,hitpt))!=0) {
|
|
|
|
vector hit_dir, rand_vec;
|
|
|
|
|
|
|
|
if ((GameTime > Last_volatile_scrape_sound_time + F1_0/4) || (GameTime < Last_volatile_scrape_sound_time)) {
|
|
|
|
int sound = (type==1)?SOUND_VOLATILE_WALL_HISS:SOUND_SHIP_IN_WATER;
|
|
|
|
|
|
|
|
Last_volatile_scrape_sound_time = GameTime;
|
|
|
|
|
|
|
|
digi_link_sound_to_pos( sound, hitseg, 0, hitpt, 0, F1_0 );
|
|
|
|
if (Game_mode & GM_MULTI)
|
|
|
|
multi_send_play_sound(sound, F1_0);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef COMPACT_SEGS
|
|
|
|
get_side_normal(&Segments[hitseg], higside, 0, &hit_dir );
|
|
|
|
#else
|
|
|
|
hit_dir = Segments[hitseg].sides[hitside].normals[0];
|
|
|
|
#endif
|
|
|
|
|
|
|
|
make_random_vector(&rand_vec);
|
|
|
|
vm_vec_scale_add2(&hit_dir, &rand_vec, F1_0/8);
|
|
|
|
vm_vec_normalize_quick(&hit_dir);
|
|
|
|
bump_one_object(obj, &hit_dir, F1_0*8);
|
|
|
|
}
|
|
|
|
|
|
|
|
//@@} else {
|
|
|
|
//@@ //what scrape sound
|
|
|
|
//@@ //PLAY_SOUND( SOUND_PLAYER_SCRAPE_WALL );
|
|
|
|
//@@}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
//these two kinds of objects below shouldn't really slide, so
|
|
|
|
//if this scrape routine gets called (which it might if the
|
|
|
|
//object (such as a fusion blob) was created already poking
|
|
|
|
//through the wall) call the collide routine.
|
|
|
|
|
|
|
|
case OBJ_WEAPON:
|
|
|
|
collide_weapon_and_wall(obj,0,hitseg,hitside,hitpt);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case OBJ_DEBRIS:
|
|
|
|
collide_debris_and_wall(obj,0,hitseg,hitside,hitpt);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
void apply_damage_to_player(object *playerobj, object *killer, float damage)
|
|
|
|
{
|
|
|
|
if (Player_is_dead)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (Endlevel_sequence)
|
|
|
|
return;
|
|
|
|
|
|
|
|
//for the player, the 'real' shields are maintained in the Players[]
|
|
|
|
//array. The shields value in the player's object are, I think, not
|
|
|
|
//used anywhere. This routine, however, sets the objects shields to
|
|
|
|
//be a mirror of the value in the Player structure.
|
|
|
|
|
|
|
|
if (playerobj->id == Player_num) { //is this the local player?
|
|
|
|
|
|
|
|
// MK: 08/14/95: This code can never be reached. See the return about 12 lines up.
|
|
|
|
// -- if (Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE) {
|
|
|
|
// --
|
|
|
|
// -- //invincible, so just do blue flash
|
|
|
|
// --
|
|
|
|
// -- PALETTE_FLASH_ADD(0,0,f2i(damage)*4); //flash blue
|
|
|
|
// --
|
|
|
|
// -- }
|
|
|
|
// -- else { //take damage, do red flash
|
|
|
|
|
|
|
|
Players[Player_num].shields -= damage;
|
|
|
|
|
|
|
|
PALETTE_FLASH_ADD(f2i(damage)*4,-f2i(damage/2),-f2i(damage/2)); //flash red
|
|
|
|
|
|
|
|
// -- }
|
|
|
|
|
|
|
|
if (Players[Player_num].shields < 0) {
|
|
|
|
|
|
|
|
Players[Player_num].killer_objnum = killer-Objects;
|
|
|
|
|
|
|
|
// if ( killer && (killer->type == OBJ_PLAYER))
|
|
|
|
// Players[Player_num].killer_objnum = killer-Objects;
|
|
|
|
|
|
|
|
playerobj->flags |= OF_DEAD;
|
|
|
|
|
|
|
|
if (Buddy_objnum != -1)
|
|
|
|
if ((killer->type == OBJ_ROBOT) && (Robot_info[killer->id].companion))
|
|
|
|
Buddy_sorry_time = GameTime;
|
|
|
|
}
|
|
|
|
// -- removed, 09/06/95, MK -- else if (Players[Player_num].shields < LOSE_WEAPON_THRESHOLD) {
|
|
|
|
// -- removed, 09/06/95, MK -- int randnum = ps_rand();
|
|
|
|
// -- removed, 09/06/95, MK --
|
|
|
|
// -- removed, 09/06/95, MK -- if (floatmul(Players[Player_num].shields, randnum) < damage/4) {
|
|
|
|
// -- removed, 09/06/95, MK -- if (ps_rand() > 20000) {
|
|
|
|
// -- removed, 09/06/95, MK -- destroy_secondary_weapon(Secondary_weapon);
|
|
|
|
// -- removed, 09/06/95, MK -- } else if (Primary_weapon == 0) {
|
|
|
|
// -- removed, 09/06/95, MK -- if (Players[Player_num].flags & PLAYER_FLAGS_QUAD_LASERS)
|
|
|
|
// -- removed, 09/06/95, MK -- destroy_primary_weapon(MAX_PRIMARY_WEAPONS); // This means to destroy quad laser.
|
|
|
|
// -- removed, 09/06/95, MK -- else if (Players[Player_num].laser_level > 0)
|
|
|
|
// -- removed, 09/06/95, MK -- destroy_primary_weapon(Primary_weapon);
|
|
|
|
// -- removed, 09/06/95, MK -- } else
|
|
|
|
// -- removed, 09/06/95, MK -- destroy_primary_weapon(Primary_weapon);
|
|
|
|
// -- removed, 09/06/95, MK -- } else
|
|
|
|
// -- removed, 09/06/95, MK -- ; // mprintf((0, "%8x > %8x, so don't lose weapon.\n", floatmul(Players[Player_num].shields, randnum), damage/4));
|
|
|
|
// -- removed, 09/06/95, MK -- }
|
|
|
|
|
|
|
|
playerobj->shields = Players[Player_num].shields; //mirror
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
void CollideAnglesToMatrix(matrix *m, float p, float h, float b)
|
|
|
|
{
|
|
|
|
float sinp,cosp,sinb,cosb,sinh,cosh;
|
|
|
|
|
|
|
|
sinp = sin(p); cosp = cos(p);
|
|
|
|
sinb = sin(b); cosb = cos(b);
|
|
|
|
sinh = sin(h); cosh = cos(h);
|
|
|
|
|
|
|
|
m->rvec.x = cosb*cosh;
|
|
|
|
m->rvec.y = cosb*sinp*sinh - cosp*sinb;
|
|
|
|
m->rvec.z = cosb*cosp*sinh + sinb*sinp;
|
|
|
|
|
|
|
|
m->uvec.x = cosh*sinb;
|
|
|
|
m->uvec.y = sinb*sinp*sinh + cosp*cosb;
|
|
|
|
m->uvec.z = sinb*cosp*sinh - cosb*sinp;
|
|
|
|
|
|
|
|
m->fvec.x = -sinh;
|
|
|
|
m->fvec.y = sinp*cosh;
|
|
|
|
m->fvec.z = cosp*cosh;
|
|
|
|
}
|
|
|
|
|
|
|
|
vector *CollideExtractAnglesFromMatrix(vector *a,matrix *m)
|
|
|
|
{
|
|
|
|
float sinh,cosh,sinp,sinb;
|
|
|
|
|
|
|
|
sinh = -m->fvec.x;
|
|
|
|
if(sinh < -1.0f) sinh = -1.0f;
|
|
|
|
else if(sinh > 1.0f) sinh = 1.0f;
|
|
|
|
a->y = asin(sinh);
|
|
|
|
|
|
|
|
cosh = cos(a->y);
|
|
|
|
ASSERT(cosh != 0.0);
|
|
|
|
|
|
|
|
sinp = m->fvec.y/cosh;
|
|
|
|
if(sinp < -1.0f) sinp = -1.0f;
|
|
|
|
else if(sinp > 1.0f) sinp = 1.0f;
|
|
|
|
|
|
|
|
sinb = m->uvec.x/cosh;
|
|
|
|
if(sinb < -1.0f) sinb = -1.0f;
|
|
|
|
else if(sinb > 1.0f) sinb = 1.0f;
|
|
|
|
|
|
|
|
a->x = asin(sinp);
|
|
|
|
a->z = asin(sinb);
|
|
|
|
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertEulerToAxisAmount(vector *e, vector *n, float *w)
|
|
|
|
{
|
|
|
|
float rotspeed = vm_GetMagnitude(e);
|
|
|
|
matrix rotmat;
|
|
|
|
vector e_n;
|
|
|
|
float scale = rotspeed/.0001f;
|
|
|
|
|
|
|
|
// If there isn't a rotation, return something valid
|
|
|
|
if(rotspeed == 0.0f || scale == 0.0f)
|
|
|
|
{
|
|
|
|
*n = Zero_vector;
|
|
|
|
n->y = 1.0f;
|
|
|
|
*w = 0.0f;
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
e_n = *e / scale;
|
|
|
|
|
|
|
|
// vector f;
|
|
|
|
CollideAnglesToMatrix(&rotmat, e_n.x, e_n.y, e_n.z);
|
|
|
|
|
|
|
|
// mprintf((0, "F %f, %f, %f\n", XYZ(&rotmat.fvec)));
|
|
|
|
// mprintf((0, "R %f, %f, %f\n", XYZ(&rotmat.rvec)));
|
|
|
|
// mprintf((0, "U %f, %f, %f\n", XYZ(&rotmat.uvec)));
|
|
|
|
|
|
|
|
// CollideExtractAnglesFromMatrix(&f, &rotmat);
|
|
|
|
|
|
|
|
// mprintf((0, "Before %f, %f, %f\n", XYZ(&e_n)));
|
|
|
|
// mprintf((0, "After %f, %f, %f\n", XYZ(&f)));
|
|
|
|
|
|
|
|
// This is from Graphics Gems 1 p.467 I am converting from a angle vector
|
|
|
|
// to the normal of that rotation (you can also get the angle about that normal, but
|
|
|
|
// we don't need it)
|
|
|
|
n->x = rotmat.uvec.z - rotmat.fvec.y;
|
|
|
|
n->y = rotmat.fvec.x - rotmat.rvec.z;
|
|
|
|
n->z = rotmat.rvec.y - rotmat.uvec.x;
|
|
|
|
|
|
|
|
if(*n != Zero_vector)
|
|
|
|
{
|
|
|
|
vm_NormalizeVector(n);
|
|
|
|
|
|
|
|
float ct = (rotmat.rvec.x + rotmat.uvec.y + rotmat.fvec.z - 1.0f)/2.0f;
|
|
|
|
if(ct < -1.0f) ct = -1.0f;
|
|
|
|
else if(ct > 1.0f) ct = 1.0f;
|
|
|
|
|
|
|
|
float v = acos(ct);
|
|
|
|
float z = sin(v);
|
|
|
|
|
|
|
|
// if(v < 0.0)
|
|
|
|
// *w = -rotspeed;
|
|
|
|
// else
|
|
|
|
*w = rotspeed * ((2.0f * PI)/(65535.0f));
|
|
|
|
|
|
|
|
if(z >= 0.0f)
|
|
|
|
*n *= -1.0f;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*w = 0.0f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void ConvertAxisAmountToEuler(vector *n, float *w, vector *e)
|
|
|
|
{
|
|
|
|
float s;
|
|
|
|
float c;
|
|
|
|
float t;
|
|
|
|
|
|
|
|
float scale = *w/.0001f;
|
|
|
|
float w_n = .0001f;
|
|
|
|
vector s_result;
|
|
|
|
|
|
|
|
if(*w == 0.0f)
|
|
|
|
{
|
|
|
|
*e = Zero_vector;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
s = sin(.0001);
|
|
|
|
c = cos(.0001);
|
|
|
|
t = 1.0f - c;
|
|
|
|
|
|
|
|
matrix rotmat;
|
|
|
|
const float sx = s * n->x;
|
|
|
|
const float sy = s * n->y;
|
|
|
|
const float sz = s * n->z;
|
|
|
|
const float txy = t * n->x * n->y;
|
|
|
|
const float txz = t * n->x * n->z;
|
|
|
|
const float tyz = t * n->y * n->z;
|
|
|
|
const float txx = t * n->x * n->x;
|
|
|
|
const float tyy = t * n->y * n->y;
|
|
|
|
const float tzz = t * n->z * n->z;
|
|
|
|
|
|
|
|
rotmat.rvec.x = txx + c;
|
|
|
|
rotmat.rvec.y = txy - sz;
|
|
|
|
rotmat.rvec.z = txz + sy;
|
|
|
|
rotmat.uvec.x = txy + sz;
|
|
|
|
rotmat.uvec.y = tyy + c;
|
|
|
|
rotmat.uvec.z = tyz - sx;
|
|
|
|
rotmat.fvec.x = txz - sy;
|
|
|
|
rotmat.fvec.y = tyz + sx;
|
|
|
|
rotmat.fvec.z = tzz + c;
|
|
|
|
|
|
|
|
CollideExtractAnglesFromMatrix(&s_result, &rotmat);
|
|
|
|
|
|
|
|
e->x = (s_result.x) * scale * (65535.0f/(2.0*PI));
|
|
|
|
e->y = (s_result.y) * scale * (65535.0f/(2.0*PI));
|
|
|
|
e->z = (s_result.z) * scale * (65535.0f/(2.0*PI));
|
|
|
|
}
|
|
|
|
|
|
|
|
void bump_obj_against_fixed(object *obj, vector *collision_point, vector *collision_normal)
|
|
|
|
{
|
|
|
|
ASSERT(_finite(obj->mtype.phys_info.rotvel.x) != 0);
|
|
|
|
ASSERT(_finite(obj->mtype.phys_info.rotvel.y) != 0);
|
|
|
|
ASSERT(_finite(obj->mtype.phys_info.rotvel.z) != 0);
|
|
|
|
ASSERT(_finite(obj->mtype.phys_info.velocity.x) != 0);
|
|
|
|
ASSERT(_finite(obj->mtype.phys_info.velocity.y) != 0);
|
|
|
|
ASSERT(_finite(obj->mtype.phys_info.velocity.z) != 0);
|
|
|
|
|
|
|
|
if(!IsOKToApplyForce(obj))
|
|
|
|
return;
|
|
|
|
|
|
|
|
vector r1 = *collision_point - obj->pos;
|
|
|
|
vector w1;
|
|
|
|
vector n1;
|
|
|
|
float temp1;
|
|
|
|
|
|
|
|
float j;
|
|
|
|
|
|
|
|
matrix o_t1 = obj->orient;
|
|
|
|
vm_TransposeMatrix(&o_t1);
|
|
|
|
|
|
|
|
vector cmp1 = obj->mtype.phys_info.rotvel * o_t1;
|
|
|
|
|
|
|
|
ConvertEulerToAxisAmount(&cmp1, &n1, &temp1);
|
|
|
|
|
|
|
|
n1 *= temp1;
|
|
|
|
|
|
|
|
if(temp1 != 0.0f)
|
|
|
|
{
|
|
|
|
vm_CrossProduct(&w1, &n1, &r1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
w1 = Zero_vector;
|
|
|
|
}
|
|
|
|
|
|
|
|
vector p1 = obj->mtype.phys_info.velocity + w1;
|
|
|
|
float v_rel;
|
|
|
|
|
|
|
|
float m1 = obj->mtype.phys_info.mass;
|
|
|
|
|
|
|
|
ASSERT(m1 != 0.0f);
|
|
|
|
if(m1 <= 0.0f) m1 = 0.00000001f;
|
|
|
|
|
|
|
|
v_rel = *collision_normal * (p1);
|
|
|
|
|
|
|
|
float e = obj->mtype.phys_info.coeff_restitution;
|
|
|
|
|
|
|
|
vector c1;
|
|
|
|
vector cc1;
|
|
|
|
float cv1;
|
|
|
|
|
|
|
|
// matrix i1;
|
|
|
|
// matrix i2;
|
|
|
|
float i1 = (2.0f/5.0f)*m1*obj->size*obj->size;
|
|
|
|
|
|
|
|
if(i1 < .0000001)
|
|
|
|
i1 = .0000001f;
|
|
|
|
|
|
|
|
vm_CrossProduct(&c1, &r1, collision_normal);
|
|
|
|
|
|
|
|
c1 = c1/i1;
|
|
|
|
|
|
|
|
vm_CrossProduct(&cc1, &c1, &r1);
|
|
|
|
|
|
|
|
cv1 = (*collision_normal)*c1;
|
|
|
|
|
|
|
|
j = (-(1.0f + e))*v_rel;
|
|
|
|
j /= (1/m1 + cv1);
|
|
|
|
|
|
|
|
obj->mtype.phys_info.velocity += ((j*(*collision_normal))/m1);
|
|
|
|
|
|
|
|
vector jcn = j * (*collision_normal);
|
|
|
|
|
|
|
|
vm_CrossProduct(&c1, &r1, &jcn);
|
|
|
|
|
|
|
|
n1 = (c1)/i1;
|
|
|
|
|
|
|
|
temp1 = vm_NormalizeVector(&n1);
|
|
|
|
|
|
|
|
vector txx1;
|
|
|
|
|
|
|
|
ConvertAxisAmountToEuler(&n1, &temp1, &txx1);
|
|
|
|
|
|
|
|
obj->mtype.phys_info.rotvel += (txx1*obj->orient);
|
|
|
|
|
|
|
|
ASSERT(_finite(obj->mtype.phys_info.rotvel.x) != 0);
|
|
|
|
ASSERT(_finite(obj->mtype.phys_info.rotvel.y) != 0);
|
|
|
|
ASSERT(_finite(obj->mtype.phys_info.rotvel.z) != 0);
|
|
|
|
ASSERT(_finite(obj->mtype.phys_info.velocity.x) != 0);
|
|
|
|
ASSERT(_finite(obj->mtype.phys_info.velocity.y) != 0);
|
|
|
|
ASSERT(_finite(obj->mtype.phys_info.velocity.z) != 0);
|
|
|
|
|
|
|
|
//hack rotvel
|
|
|
|
/* vector v = obj->mtype.phys_info.velocity;
|
|
|
|
vector c = *collision_normal;
|
|
|
|
|
|
|
|
if(v != Zero_vector)
|
|
|
|
{
|
|
|
|
vm_NormalizeVector(&v);
|
|
|
|
|
|
|
|
if(v != c)
|
|
|
|
{
|
|
|
|
float rad = vm_VectorDistance(&obj->pos, collision_point);
|
|
|
|
float rotvel = vm_GetMagnitude(&obj->mtype.phys_info.velocity)*((2*PI*rad));
|
|
|
|
vector r;
|
|
|
|
vector e;
|
|
|
|
|
|
|
|
vm_CrossProduct(&r, &v, &c);
|
|
|
|
vm_NormalizeVector(&r);
|
|
|
|
|
|
|
|
ConvertAxisAmountToEuler(&r, &rotvel, &e);
|
|
|
|
|
|
|
|
matrix rrr = obj->orient;
|
|
|
|
// vm_TransposeMatrix(&rrr);
|
|
|
|
obj->mtype.phys_info.rotvel = rrr * r;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
obj->mtype.phys_info.rotvel = Zero_vector;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
obj->mtype.phys_info.rotvel = Zero_vector;
|
|
|
|
}*/
|
|
|
|
}
|
|
|
|
|
|
|
|
void bump_two_objects(object *object0, object *object1, vector *collision_point, vector *collision_normal, int damage_flag)
|
|
|
|
{
|
|
|
|
// vector force; //dv,
|
|
|
|
object *t = NULL;
|
|
|
|
object *other = NULL;
|
|
|
|
|
|
|
|
// Determine if a moving object hits a non-moving object
|
|
|
|
if((object0->movement_type != MT_PHYSICS && object0->movement_type != MT_WALKING) ||
|
|
|
|
(object0->movement_type == MT_PHYSICS && object0->mtype.phys_info.velocity == Zero_vector && (object0->mtype.phys_info.flags & PF_LOCK_MASK) && (object0->mtype.phys_info.flags & PF_POINT_COLLIDE_WALLS)))
|
|
|
|
{
|
|
|
|
t = object1;
|
|
|
|
other = object0;
|
|
|
|
*collision_normal *= -1.0f;
|
|
|
|
}
|
|
|
|
if((object1->movement_type != MT_PHYSICS && object1->movement_type != MT_WALKING) ||
|
|
|
|
(object1->movement_type == MT_PHYSICS && object1->mtype.phys_info.velocity == Zero_vector && (object1->mtype.phys_info.flags & PF_LOCK_MASK) && (object1->mtype.phys_info.flags & PF_POINT_COLLIDE_WALLS)))
|
|
|
|
{
|
|
|
|
t = object0;
|
|
|
|
other = object1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we hit a non-moving object...
|
|
|
|
if (t)
|
|
|
|
{
|
|
|
|
// chrishack -- walker hack
|
|
|
|
if(t->movement_type != MT_PHYSICS && t->movement_type != MT_WALKING)
|
|
|
|
{
|
|
|
|
t->mtype.phys_info.velocity = Zero_vector;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(t->mtype.phys_info.flags & PF_PERSISTENT)
|
|
|
|
return;
|
|
|
|
|
|
|
|
vector moved_v;
|
|
|
|
float wall_part;
|
|
|
|
|
|
|
|
float luke_test;
|
|
|
|
|
|
|
|
if(t->type == OBJ_PLAYER)
|
|
|
|
{
|
|
|
|
luke_test = vm_GetMagnitude(&t->mtype.phys_info.velocity);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(t->flags & OF_DEAD))
|
|
|
|
{
|
|
|
|
// bump_obj_against_fixed(t, collision_point, collision_normal);
|
|
|
|
// }
|
|
|
|
///*
|
|
|
|
// Find hit speed
|
|
|
|
moved_v = t->pos - t->last_pos;
|
|
|
|
wall_part = *collision_normal * t->mtype.phys_info.velocity;
|
|
|
|
|
|
|
|
if (t->mtype.phys_info.flags & PF_BOUNCE)
|
|
|
|
{
|
|
|
|
wall_part *= 2.0; //Subtract out wall part twice to achieve bounce
|
|
|
|
|
|
|
|
// New bounceness code
|
|
|
|
if ((t->mtype.phys_info.flags & PF_BOUNCE) && (t->mtype.phys_info.num_bounces != PHYSICS_UNLIMITED_BOUNCE))
|
|
|
|
{
|
|
|
|
if(t->mtype.phys_info.num_bounces == 0)
|
|
|
|
{
|
|
|
|
ASSERT (t->type!=OBJ_PLAYER);
|
|
|
|
if (t->flags & OF_DYING) {
|
|
|
|
ASSERT((t->control_type == CT_DYING) || (t->control_type == CT_DYING_AND_AI));
|
|
|
|
DestroyObject(t,50.0,t->ctype.dying_info.death_flags);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
SetObjectDeadFlag (t);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
t->mtype.phys_info.num_bounces--;
|
|
|
|
|
|
|
|
t->mtype.phys_info.velocity += *collision_normal * (wall_part * -1.0f);
|
|
|
|
|
|
|
|
if(t->mtype.phys_info.coeff_restitution != 1.0f)
|
|
|
|
t->mtype.phys_info.velocity -= (t->mtype.phys_info.velocity * (1.0f - t->mtype.phys_info.coeff_restitution));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
float wall_force;
|
|
|
|
|
|
|
|
wall_force = t->mtype.phys_info.thrust * *collision_normal;
|
|
|
|
t->mtype.phys_info.thrust += *collision_normal * (wall_force * -1.001); // 1.001 so that we are not quite tangential
|
|
|
|
|
|
|
|
// Update velocity from wall hit.
|
|
|
|
t->mtype.phys_info.velocity += *collision_normal * (wall_part * -1.001); // 1.001 so that we are not quite tangential
|
|
|
|
if(t->type == OBJ_PLAYER)
|
|
|
|
{
|
|
|
|
float real_vel;
|
|
|
|
|
|
|
|
real_vel = vm_NormalizeVector(&t->mtype.phys_info.velocity);
|
|
|
|
t->mtype.phys_info.velocity *= ((real_vel + luke_test)/2.0f);
|
|
|
|
//obj->mtype.phys_info.velocity *= (luke_test);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Weapons should face their new heading. This is so missiles are pointing in the correct direct.
|
|
|
|
if (t->type == OBJ_WEAPON && (t->mtype.phys_info.flags & (PF_BOUNCE | PF_GRAVITY | PF_WIND )))
|
|
|
|
vm_VectorToMatrix(&t->orient, &t->mtype.phys_info.velocity, &t->orient.uvec, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Return it to the original direction
|
|
|
|
if(object0->movement_type != MT_PHYSICS && object0->movement_type != MT_WALKING)
|
|
|
|
{
|
|
|
|
*collision_normal *= -1.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
//Do ForceFeedback stuff for non-moving objects
|
|
|
|
//-----------------------------------------
|
|
|
|
if(ForceIsEnabled()){
|
|
|
|
|
|
|
|
if(object0->type==OBJ_PLAYER && object0->id==Player_num){
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//*/
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// force = object0->mtype.phys_info.velocity - object1->mtype.phys_info.velocity;
|
|
|
|
// force *= 2*(object0->mtype.phys_info.mass * object1->mtype.phys_info.mass)/(object0->mtype.phys_info.mass + object1->mtype.phys_info.mass);
|
|
|
|
|
|
|
|
// if(!(object1->mtype.phys_info.flags & PF_PERSISTENT))
|
|
|
|
// bump_this_object(object1, object0, &force, collision_point, damage_flag);
|
|
|
|
//
|
|
|
|
// force = -force;
|
|
|
|
//
|
|
|
|
// if(!(object0->mtype.phys_info.flags & PF_PERSISTENT))
|
|
|
|
// bump_this_object(object0, object1, &force, collision_point, damage_flag);
|
|
|
|
|
|
|
|
|
|
|
|
// vector r_vel = object0->mtype.phys_info.velocity - object1->mtype.phys_info.velocity;
|
|
|
|
//Add this back
|
|
|
|
|
|
|
|
ASSERT(_finite(object1->mtype.phys_info.rotvel.x) != 0);
|
|
|
|
ASSERT(_finite(object1->mtype.phys_info.rotvel.y) != 0);
|
|
|
|
ASSERT(_finite(object1->mtype.phys_info.rotvel.z) != 0);
|
|
|
|
ASSERT(_finite(object0->mtype.phys_info.rotvel.x) != 0);
|
|
|
|
ASSERT(_finite(object0->mtype.phys_info.rotvel.y) != 0);
|
|
|
|
ASSERT(_finite(object0->mtype.phys_info.rotvel.z) != 0);
|
|
|
|
ASSERT(_finite(object1->mtype.phys_info.velocity.x) != 0);
|
|
|
|
ASSERT(_finite(object1->mtype.phys_info.velocity.y) != 0);
|
|
|
|
ASSERT(_finite(object1->mtype.phys_info.velocity.z) != 0);
|
|
|
|
ASSERT(_finite(object0->mtype.phys_info.velocity.x) != 0);
|
|
|
|
ASSERT(_finite(object0->mtype.phys_info.velocity.y) != 0);
|
|
|
|
ASSERT(_finite(object0->mtype.phys_info.velocity.z) != 0);
|
|
|
|
|
|
|
|
vector r1 = *collision_point - object0->pos;
|
|
|
|
vector r2 = *collision_point - object1->pos;
|
|
|
|
vector w1;
|
|
|
|
vector w2;
|
|
|
|
vector n1;
|
|
|
|
vector n2;
|
|
|
|
float temp1;
|
|
|
|
float temp2;
|
|
|
|
|
|
|
|
float j;
|
|
|
|
|
|
|
|
matrix o_t1 = object0->orient;
|
|
|
|
matrix o_t2 = object1->orient;
|
|
|
|
|
|
|
|
vm_TransposeMatrix(&o_t1);
|
|
|
|
vm_TransposeMatrix(&o_t2);
|
|
|
|
|
|
|
|
vector cmp1 = object0->mtype.phys_info.rotvel * o_t1;
|
|
|
|
vector cmp2 = object1->mtype.phys_info.rotvel * o_t2;
|
|
|
|
|
|
|
|
ConvertEulerToAxisAmount(&cmp1, &n1, &temp1);
|
|
|
|
ConvertEulerToAxisAmount(&cmp2, &n2, &temp2);
|
|
|
|
|
|
|
|
n1 *= temp1;
|
|
|
|
n2 *= temp2;
|
|
|
|
|
|
|
|
if(temp1 != 0.0f)
|
|
|
|
{
|
|
|
|
vm_CrossProduct(&w1, &n1, &r1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
w1 = Zero_vector;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(temp2 != 0.0f)
|
|
|
|
{
|
|
|
|
vm_CrossProduct(&w2, &n2, &r2);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
w2 = Zero_vector;
|
|
|
|
}
|
|
|
|
|
|
|
|
vector p1 = object0->mtype.phys_info.velocity + w1;
|
|
|
|
vector p2 = object1->mtype.phys_info.velocity + w2;
|
|
|
|
float v_rel;
|
|
|
|
|
|
|
|
float m1 = object0->mtype.phys_info.mass;
|
|
|
|
float m2 = object1->mtype.phys_info.mass;
|
|
|
|
|
|
|
|
bool f_force_1 = IsOKToApplyForce(object0);
|
|
|
|
bool f_force_2 = IsOKToApplyForce(object1);
|
|
|
|
|
|
|
|
ASSERT(m1 != 0.0f && m2 != 0.0f);
|
|
|
|
if(m1 <= 0.0f) m1 = 0.00000001f;
|
|
|
|
if(m2 <= 0.0f) m2 = 0.00000001f;
|
|
|
|
|
|
|
|
v_rel = *collision_normal * (p1 - p2);
|
|
|
|
|
|
|
|
float e;
|
|
|
|
|
|
|
|
if(object0->type == OBJ_PLAYER && object1->type == OBJ_PLAYER)
|
|
|
|
e = 0.015f;
|
|
|
|
else if((object0->type == OBJ_WEAPON || object1->type == OBJ_WEAPON) && (object0->type != OBJ_PLAYER && object1->type != OBJ_PLAYER))
|
|
|
|
e = 1.0f;
|
|
|
|
else if((object0->type == OBJ_CLUTTER && object1->type == OBJ_PLAYER) || (object0->type == OBJ_PLAYER && object1->type == OBJ_CLUTTER))
|
|
|
|
e = 0.5f;
|
|
|
|
else
|
|
|
|
e = 0.1f;
|
|
|
|
|
|
|
|
vector c1;
|
|
|
|
vector c2;
|
|
|
|
vector cc1;
|
|
|
|
vector cc2;
|
|
|
|
float cv1;
|
|
|
|
float cv2;
|
|
|
|
|
|
|
|
// matrix i1;
|
|
|
|
// matrix i2;
|
|
|
|
float i1 = (2.0f/5.0f)*m1*object0->size*object0->size;
|
|
|
|
float i2 = (2.0f/5.0f)*m2*object1->size*object1->size;
|
|
|
|
|
|
|
|
if(i1 < .0000001)
|
|
|
|
i1 = .0000001f;
|
|
|
|
if(i2 < .0000001)
|
|
|
|
i2 = .0000001f;
|
|
|
|
|
|
|
|
vm_CrossProduct(&c1, &r1, collision_normal);
|
|
|
|
vm_CrossProduct(&c2, &r2, collision_normal);
|
|
|
|
|
|
|
|
c1 = c1/i1;
|
|
|
|
c2 = c2/i2;
|
|
|
|
|
|
|
|
vm_CrossProduct(&cc1, &c1, &r1);
|
|
|
|
vm_CrossProduct(&cc2, &c2, &r2);
|
|
|
|
|
|
|
|
cv1 = (*collision_normal)*c1;
|
|
|
|
cv2 = (*collision_normal)*c2;
|
|
|
|
|
|
|
|
j = (-(1.0f + e))*v_rel;
|
|
|
|
j /= (1/m1 + 1/m2 + cv1 + cv2);
|
|
|
|
|
|
|
|
if(f_force_1)
|
|
|
|
object0->mtype.phys_info.velocity += ((j*(*collision_normal))/m1);
|
|
|
|
|
|
|
|
if(f_force_2)
|
|
|
|
object1->mtype.phys_info.velocity -= ((j*(*collision_normal))/m2);
|
|
|
|
|
|
|
|
vector jcn = j * (*collision_normal);
|
|
|
|
|
|
|
|
vm_CrossProduct(&c1, &r1, &jcn);
|
|
|
|
vm_CrossProduct(&c2, &r2, &jcn);
|
|
|
|
|
|
|
|
n1 = (c1)/i1;
|
|
|
|
n2 = (c2)/i2;
|
|
|
|
|
|
|
|
temp1 = vm_NormalizeVector(&n1);
|
|
|
|
temp2 = vm_NormalizeVector(&n2);
|
|
|
|
|
|
|
|
vector txx1;
|
|
|
|
vector txx2;
|
|
|
|
|
|
|
|
ConvertAxisAmountToEuler(&n1, &temp1, &txx1);
|
|
|
|
ConvertAxisAmountToEuler(&n2, &temp2, &txx2);
|
|
|
|
|
|
|
|
float rotscale1, rotscale2;
|
|
|
|
|
|
|
|
if(object0->type == OBJ_PLAYER)
|
|
|
|
rotscale1 = PLAYER_ROTATION_BY_FORCE_SCALAR;
|
|
|
|
else
|
|
|
|
rotscale1 = NONPLAYER_ROTATION_BY_FORCE_SCALAR;
|
|
|
|
|
|
|
|
if(object1->type == OBJ_PLAYER)
|
|
|
|
rotscale2 = PLAYER_ROTATION_BY_FORCE_SCALAR;
|
|
|
|
else
|
|
|
|
rotscale2 = NONPLAYER_ROTATION_BY_FORCE_SCALAR;
|
|
|
|
|
|
|
|
if(f_force_1)
|
|
|
|
object0->mtype.phys_info.rotvel += (txx1*object0->orient) * rotscale1;
|
|
|
|
|
|
|
|
if(f_force_2)
|
|
|
|
object1->mtype.phys_info.rotvel += (txx2*object1->orient) * rotscale2;
|
|
|
|
|
|
|
|
ASSERT(_finite(object1->mtype.phys_info.rotvel.x) != 0);
|
|
|
|
ASSERT(_finite(object1->mtype.phys_info.rotvel.y) != 0);
|
|
|
|
ASSERT(_finite(object1->mtype.phys_info.rotvel.z) != 0);
|
|
|
|
ASSERT(_finite(object0->mtype.phys_info.rotvel.x) != 0);
|
|
|
|
ASSERT(_finite(object0->mtype.phys_info.rotvel.y) != 0);
|
|
|
|
ASSERT(_finite(object0->mtype.phys_info.rotvel.z) != 0);
|
|
|
|
ASSERT(_finite(object1->mtype.phys_info.velocity.x) != 0);
|
|
|
|
ASSERT(_finite(object1->mtype.phys_info.velocity.y) != 0);
|
|
|
|
ASSERT(_finite(object1->mtype.phys_info.velocity.z) != 0);
|
|
|
|
ASSERT(_finite(object0->mtype.phys_info.velocity.x) != 0);
|
|
|
|
ASSERT(_finite(object0->mtype.phys_info.velocity.y) != 0);
|
|
|
|
ASSERT(_finite(object0->mtype.phys_info.velocity.z) != 0);
|
|
|
|
|
|
|
|
//Do ForceFeedback stuff for moving objects
|
|
|
|
//-----------------------------------------
|
|
|
|
if(ForceIsEnabled()){
|
|
|
|
|
|
|
|
if(object0->type==OBJ_PLAYER && object0->id==Player_num){
|
|
|
|
//v is the force vector
|
|
|
|
vector v;
|
|
|
|
v = -1.0 * v_rel * (*collision_normal);
|
|
|
|
|
|
|
|
//Was it weapon->player collide
|
|
|
|
switch(object1->type){
|
|
|
|
case OBJ_WEAPON:
|
|
|
|
//Do force effect for player/weapon collision
|
|
|
|
DoForceForWeapon(object0,object1,&v);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Catch things on fire if possible
|
|
|
|
if (object0->effect_info && object1->effect_info)
|
|
|
|
{
|
|
|
|
// One of these objects must be burning
|
|
|
|
if ((object0->effect_info->type_flags & EF_NAPALMED) || (object1->effect_info->type_flags & EF_NAPALMED))
|
|
|
|
{
|
|
|
|
// Both cannot be burning
|
|
|
|
if (!(object0->effect_info->type_flags & EF_NAPALMED) || !(object1->effect_info->type_flags & EF_NAPALMED))
|
|
|
|
{
|
|
|
|
object *src_obj,*dest_obj;
|
|
|
|
if (object0->effect_info->type_flags & EF_NAPALMED)
|
|
|
|
{
|
|
|
|
src_obj=object0;
|
|
|
|
dest_obj=object1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src_obj=object1;
|
|
|
|
dest_obj=object0;
|
|
|
|
}
|
|
|
|
|
|
|
|
dest_obj->effect_info->type_flags|=EF_NAPALMED;
|
|
|
|
|
|
|
|
dest_obj->effect_info->damage_time=max(1.0,src_obj->effect_info->damage_time/3.0);
|
|
|
|
dest_obj->effect_info->damage_per_second=src_obj->effect_info->damage_per_second;
|
|
|
|
|
|
|
|
// We need this cap (as the gb burns forever
|
|
|
|
if(dest_obj->effect_info->damage_time > 10.0f)
|
|
|
|
{
|
|
|
|
dest_obj->effect_info->damage_time = 10.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
dest_obj->effect_info->last_damage_time=0;
|
|
|
|
|
|
|
|
dest_obj->effect_info->damage_handle=src_obj->handle;
|
|
|
|
|
|
|
|
if (dest_obj->effect_info->sound_handle == SOUND_NONE_INDEX)
|
|
|
|
dest_obj->effect_info->sound_handle = Sound_system.Play3dSound(SOUND_PLAYER_BURNING, SND_PRIORITY_HIGHEST, dest_obj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void collide_player_and_player( object * p1, object * p2, vector *collision_point, vector *collision_normal, bool f_reverse_normal, fvi_info *hit_info )
|
|
|
|
{
|
|
|
|
if(f_reverse_normal)
|
|
|
|
*collision_normal *= -1.0f;
|
|
|
|
|
|
|
|
vector rvel = p1->mtype.phys_info.velocity - p2->mtype.phys_info.velocity;
|
|
|
|
float speed = vm_NormalizeVector(&rvel);
|
|
|
|
float scalar;
|
|
|
|
|
|
|
|
if(speed <= MIN_WALL_HIT_SOUND_VEL)
|
|
|
|
{
|
|
|
|
scalar = 0.0f;
|
|
|
|
}
|
|
|
|
else if(speed >= MAX_WALL_HIT_SOUND_VEL)
|
|
|
|
{
|
|
|
|
scalar = 1.0f;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
scalar = (speed - MIN_WALL_HIT_SOUND_VEL)/(MAX_WALL_HIT_SOUND_VEL - MIN_WALL_HIT_SOUND_VEL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(scalar > .01)
|
|
|
|
{
|
|
|
|
pos_state cur_pos;
|
|
|
|
cur_pos.position = collision_point;
|
|
|
|
cur_pos.orient = &p1->orient;
|
|
|
|
cur_pos.roomnum = p1->roomnum;
|
|
|
|
|
|
|
|
Sound_system.Play3dSound(SOUND_PLAYER_HIT_WALL, SND_PRIORITY_HIGHEST, &cur_pos, MAX_GAME_VOLUME * scalar);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
bump_two_objects(p1, p2, collision_point, collision_normal, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "polymodel.h"
|
|
|
|
|
|
|
|
void collide_generic_and_player( object * robotobj, object * playerobj, vector *collision_point, vector *collision_normal, bool f_reverse_normal, fvi_info *hit_info )
|
|
|
|
{
|
|
|
|
if(f_reverse_normal)
|
|
|
|
*collision_normal *= -1.0f;
|
|
|
|
|
|
|
|
vector rvel;
|
|
|
|
if(robotobj->movement_type == MT_PHYSICS || robotobj->movement_type == MT_WALKING)
|
|
|
|
{
|
|
|
|
rvel = robotobj->mtype.phys_info.velocity;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
rvel = Zero_vector;
|
|
|
|
}
|
|
|
|
rvel -= playerobj->mtype.phys_info.velocity;
|
|
|
|
float speed = vm_NormalizeVector(&rvel);
|
|
|
|
float scalar;
|
|
|
|
|
|
|
|
if(speed <= MIN_WALL_HIT_SOUND_VEL)
|
|
|
|
{
|
|
|
|
scalar = 0.0f;
|
|
|
|
}
|
|
|
|
else if(speed >= MAX_WALL_HIT_SOUND_VEL)
|
|
|
|
{
|
|
|
|
scalar = 1.0f;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
scalar = (speed - MIN_WALL_HIT_SOUND_VEL)/(MAX_WALL_HIT_SOUND_VEL - MIN_WALL_HIT_SOUND_VEL);
|
|
|
|
}
|
|
|
|
|
|
|
|
//Check for lava surface on an object
|
|
|
|
if ((robotobj->type == OBJ_BUILDING) && hit_info) {
|
|
|
|
poly_model *pm = GetPolymodelPointer(robotobj->rtype.pobj_info.model_num);
|
|
|
|
int tmap = pm->textures[pm->submodel[hit_info->hit_subobject[0]].faces[hit_info->hit_face[0]].texnum];
|
|
|
|
|
|
|
|
if (GameTextures[tmap].flags & TF_LAVA) {
|
|
|
|
if(!((Game_mode & GM_MULTI) && (Netgame.local_role==LR_CLIENT)))
|
|
|
|
{
|
|
|
|
int id = FindWeaponName("NapalmBlob");
|
|
|
|
if(id >= 0)
|
|
|
|
SetNapalmDamageEffect(playerobj,NULL,id);
|
|
|
|
else
|
|
|
|
Int3();
|
|
|
|
}
|
|
|
|
scalar = 0; //don't make collide sound
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(scalar > .01 || (robotobj->mtype.phys_info.flags & PF_LOCK_MASK))
|
|
|
|
{
|
|
|
|
pos_state cur_pos;
|
|
|
|
cur_pos.position = collision_point;
|
|
|
|
cur_pos.orient = &playerobj->orient;
|
|
|
|
cur_pos.roomnum = playerobj->roomnum;
|
|
|
|
|
|
|
|
Sound_system.Play3dSound(SOUND_PLAYER_HIT_WALL, SND_PRIORITY_HIGHEST, &cur_pos, MAX_GAME_VOLUME * scalar);
|
|
|
|
|
|
|
|
ain_hear hear;
|
|
|
|
hear.f_directly_player = true;
|
|
|
|
hear.hostile_level = 0.10f;
|
|
|
|
hear.curiosity_level = 0.5f;
|
|
|
|
hear.max_dist = Sounds[SOUND_PLAYER_HIT_WALL].max_distance * scalar;
|
|
|
|
AINotify(playerobj, AIN_HEAR_NOISE, (void *)&hear);
|
|
|
|
|
|
|
|
if((scalar > .25f && (robotobj->movement_type == MT_WALKING || robotobj->movement_type == MT_PHYSICS)) || ((robotobj->mtype.phys_info.flags & PF_LOCK_MASK) && (robotobj->mtype.phys_info.flags & PF_POINT_COLLIDE_WALLS)))
|
|
|
|
{
|
|
|
|
if(!(IS_GUIDEBOT(robotobj)))
|
|
|
|
{
|
|
|
|
if(robotobj->shields <= 1.0f)
|
|
|
|
{
|
|
|
|
ApplyDamageToGeneric(robotobj, playerobj, GD_PHYSICS, 2.0f);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ApplyDamageToGeneric(robotobj, playerobj, GD_PHYSICS, 5.0f * Frametime * scalar);
|
|
|
|
}
|
|
|
|
if(scalar < 1.0f && (robotobj->mtype.phys_info.flags & PF_LOCK_MASK) && (robotobj->mtype.phys_info.flags & PF_POINT_COLLIDE_WALLS))
|
|
|
|
scalar = 1.0f;
|
|
|
|
|
|
|
|
ApplyDamageToPlayer(playerobj, playerobj, PD_WALL_HIT, 2.0f * Frametime * scalar);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//mprintf((0, "We hit a robot\n"));
|
|
|
|
if(robotobj->control_type == CT_AI)
|
|
|
|
{
|
|
|
|
AINotify(robotobj, AIN_BUMPED_OBJ, (void *)playerobj);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if((GameTextures[Rooms[hitseg].faces[hitwall].tmap].flags & TF_VOLATILE) && !((Game_mode & GM_MULTI) && (Netgame.local_role==LR_CLIENT)))
|
|
|
|
{
|
|
|
|
int id = FindWeaponName("NapalmBlob");
|
|
|
|
if(id >= 0)
|
|
|
|
{
|
|
|
|
int objnum = ObjCreate(OBJ_WEAPON, id, playerobj->roomnum, &playerobj->pos, NULL, playerobj->handle);
|
|
|
|
|
|
|
|
if(objnum >= 0)
|
|
|
|
{
|
|
|
|
object *weapon = &Objects[objnum];
|
|
|
|
float damage_to_apply = Weapons[weapon->id].damage;
|
|
|
|
|
|
|
|
// Factor in multiplier
|
|
|
|
damage_to_apply *= weapon->ctype.laser_info.multiplier;
|
|
|
|
|
|
|
|
ApplyDamageToPlayer(playerobj, weapon, 0);
|
|
|
|
|
|
|
|
SetObjectDeadFlag(objnum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
bump_two_objects(robotobj, playerobj, collision_point, collision_normal, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void MakeWeaponStick(object *weapon, object *parent, fvi_info *hit_info)
|
|
|
|
{
|
|
|
|
weapon->mtype.obj_link_info.parent_handle = parent->handle;
|
|
|
|
weapon->mtype.obj_link_info.fvec = hit_info->hit_subobj_fvec;
|
|
|
|
weapon->mtype.obj_link_info.uvec = hit_info->hit_subobj_uvec;
|
|
|
|
weapon->mtype.obj_link_info.pos = hit_info->hit_subobj_pos;
|
|
|
|
weapon->mtype.obj_link_info.sobj_index = hit_info->hit_subobject[0];
|
|
|
|
weapon->movement_type = MT_OBJ_LINKED;
|
|
|
|
}
|
|
|
|
|
|
|
|
void collide_generic_and_weapon( object * robotobj, object * weapon, vector *collision_point, vector *collision_normal, bool f_reverse_normal, fvi_info *hit_info )
|
|
|
|
{
|
|
|
|
object *parent_obj;
|
|
|
|
float damage_to_apply;
|
|
|
|
ubyte electrical= (Weapons[weapon->id].flags & WF_ELECTRICAL)?1:0;
|
|
|
|
bool f_stick = ((weapon->mtype.phys_info.flags & PF_STICK) != 0);
|
|
|
|
bool f_energy = ((Weapons[weapon->id].flags & WF_MATTER_WEAPON) == 0);
|
|
|
|
int damage_type;
|
|
|
|
|
|
|
|
//Check for lava & volatile surfaces on an object
|
|
|
|
if ((robotobj->type == OBJ_BUILDING) && hit_info) {
|
|
|
|
poly_model *pm = GetPolymodelPointer(robotobj->rtype.pobj_info.model_num);
|
|
|
|
int tmap = pm->textures[pm->submodel[hit_info->hit_subobject[0]].faces[hit_info->hit_face[0]].texnum];
|
|
|
|
vector *normal = &hit_info->hit_wallnorm[0];
|
|
|
|
|
|
|
|
DoWallEffects (weapon,tmap);
|
|
|
|
|
|
|
|
check_for_special_surface(weapon,tmap,normal,1.0);
|
|
|
|
|
|
|
|
//If object died, stop processing
|
|
|
|
if (weapon->flags & OF_DEAD)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(Weapons[weapon->id].flags & WF_NAPALM)
|
|
|
|
damage_type = GD_FIRE;
|
|
|
|
else if(Weapons[weapon->id].flags & WF_MATTER_WEAPON)
|
|
|
|
damage_type = GD_MATTER;
|
|
|
|
else if(Weapons[weapon->id].flags & WF_ELECTRICAL)
|
|
|
|
damage_type = GD_ELECTRIC;
|
|
|
|
else
|
|
|
|
damage_type = GD_ENERGY;
|
|
|
|
|
|
|
|
if(f_reverse_normal)
|
|
|
|
*collision_normal *= -1.0f;
|
|
|
|
|
|
|
|
if(robotobj->flags & OF_DYING)
|
|
|
|
robotobj->ctype.dying_info.delay_time *= 0.975f;
|
|
|
|
|
|
|
|
if (Weapons[weapon->id].sounds[WSI_IMPACT_WALL]!=SOUND_NONE_INDEX)
|
|
|
|
{
|
|
|
|
Sound_system.Play3dSound(Weapons[weapon->id].sounds[WSI_IMPACT_WALL], SND_PRIORITY_HIGH, weapon);
|
|
|
|
|
|
|
|
ain_hear hear;
|
|
|
|
hear.f_directly_player = false;
|
|
|
|
if(robotobj->control_type == CT_AI)
|
|
|
|
{
|
|
|
|
hear.hostile_level = 1.0f;
|
|
|
|
hear.curiosity_level = 0.1f;
|
|
|
|
}
|
|
|
|
else if(robotobj->type == OBJ_DOOR)
|
|
|
|
{
|
|
|
|
hear.hostile_level = 0.5f;
|
|
|
|
hear.curiosity_level = 1.0f;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
hear.hostile_level = .9f;
|
|
|
|
hear.curiosity_level = 0.5f;
|
|
|
|
}
|
|
|
|
|
|
|
|
hear.max_dist = Sounds[Weapons[weapon->id].sounds[WSI_IMPACT_WALL]].max_distance;
|
|
|
|
AINotify(weapon, AIN_HEAR_NOISE, (void *)&hear);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do weapon explosion stuff
|
|
|
|
DoWeaponExploded (weapon,collision_normal,collision_point);
|
|
|
|
|
|
|
|
// Check to see if we should spawn
|
|
|
|
if (robotobj->type==OBJ_DOOR && !(Game_mode & GM_MULTI))
|
|
|
|
{
|
|
|
|
if ((Weapons[weapon->id].flags & WF_SPAWNS_IMPACT) && Weapons[weapon->id].spawn_count>0 && Weapons[weapon->id].spawn_handle>=0)
|
|
|
|
CreateImpactSpawnFromWeapon (weapon,collision_normal);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((Weapons[weapon->id].flags & WF_SPAWNS_ROBOT) && (Weapons[weapon->id].flags & WF_COUNTERMEASURE) && Weapons[weapon->id].robot_spawn_handle>=0)
|
|
|
|
CreateRobotSpawnFromWeapon (weapon);
|
|
|
|
|
|
|
|
parent_obj = ObjGet(weapon->parent_handle);
|
|
|
|
|
|
|
|
if((parent_obj) && (parent_obj->control_type == CT_AI))
|
|
|
|
{
|
|
|
|
AINotify(parent_obj, AIN_WHIT_OBJECT, (void *)robotobj);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(robotobj->control_type == CT_AI)
|
|
|
|
{
|
|
|
|
AINotify(robotobj, AIN_HIT_BY_WEAPON, (void *)weapon);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (electrical)
|
|
|
|
{
|
|
|
|
damage_to_apply=Weapons[weapon->id].generic_damage*Frametime;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
damage_to_apply=Weapons[weapon->id].generic_damage;
|
|
|
|
|
|
|
|
// Factor in multiplier
|
|
|
|
damage_to_apply*=weapon->ctype.laser_info.multiplier;
|
|
|
|
|
|
|
|
if (ApplyDamageToGeneric(robotobj, weapon, damage_type, damage_to_apply))
|
|
|
|
{
|
|
|
|
if (Weapons[weapon->id].sounds[WSI_IMPACT_ROBOT]!=SOUND_NONE_INDEX)
|
|
|
|
{
|
|
|
|
Sound_system.Play3dSound(Weapons[weapon->id].sounds[WSI_IMPACT_ROBOT], SND_PRIORITY_HIGHEST, weapon);
|
|
|
|
}
|
|
|
|
if (!electrical)
|
|
|
|
{
|
|
|
|
light_info *li=&Weapons[weapon->id].lighting_info;
|
|
|
|
ushort color=GR_RGB16(li->red_light2*255,li->green_light2*255,li->blue_light2*255);
|
|
|
|
CreateRandomLineSparks (3+ps_rand()%6,&weapon->pos,weapon->roomnum,color);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
if(Demo_flags == DF_RECORDING)
|
|
|
|
{
|
|
|
|
DemoWriteCollideGenericWeapon( robotobj, weapon, collision_point, collision_normal, f_reverse_normal, hit_info );
|
|
|
|
}
|
|
|
|
else if(Demo_flags == DF_PLAYBACK)
|
|
|
|
{
|
|
|
|
//During playback we don't need the code below (actually it won't work)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!electrical)
|
|
|
|
{
|
|
|
|
|
|
|
|
bump_two_objects(robotobj, weapon, collision_point, collision_normal, 0);
|
|
|
|
|
|
|
|
if(!f_stick || (hit_info == NULL))
|
|
|
|
{
|
|
|
|
if((robotobj->lighting_render_type == LRT_LIGHTMAPS) || !(weapon->mtype.phys_info.flags & PF_PERSISTENT))
|
|
|
|
SetObjectDeadFlag (weapon);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MakeWeaponStick(weapon, robotobj, hit_info);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void collide_player_and_weapon( object * playerobj, object * weapon, vector *collision_point, vector *collision_normal, bool f_reverse_normal, fvi_info *hit_info )
|
|
|
|
{
|
|
|
|
object *parent_obj;
|
|
|
|
float damage_to_apply;
|
|
|
|
ubyte electrical=Weapons[weapon->id].flags & WF_ELECTRICAL?1:0;
|
|
|
|
bool f_stick = ((weapon->mtype.phys_info.flags & PF_STICK) != 0);
|
|
|
|
|
|
|
|
if(f_reverse_normal)
|
|
|
|
*collision_normal *= -1.0f;
|
|
|
|
|
|
|
|
parent_obj = ObjGet(weapon->parent_handle);
|
|
|
|
|
|
|
|
if((parent_obj) && (parent_obj->control_type == CT_AI))
|
|
|
|
{
|
|
|
|
AINotify(parent_obj, AIN_WHIT_OBJECT, (void *)playerobj);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do weapon explosion stuff
|
|
|
|
DoWeaponExploded (weapon,collision_normal,collision_point,playerobj);
|
|
|
|
|
|
|
|
|
|
|
|
// Check to see if we should spawn
|
|
|
|
/*if ((Weapons[weapon->id].flags & WF_SPAWNS_IMPACT) && Weapons[weapon->id].spawn_count>0 && Weapons[weapon->id].spawn_handle>=0)
|
|
|
|
CreateImpactSpawnFromWeapon (weapon,collision_normal);*/
|
|
|
|
|
|
|
|
if ((Weapons[weapon->id].flags & WF_SPAWNS_ROBOT) && (Weapons[weapon->id].flags & WF_COUNTERMEASURE) && Weapons[weapon->id].robot_spawn_handle>=0)
|
|
|
|
CreateRobotSpawnFromWeapon (weapon);
|
|
|
|
|
|
|
|
if (electrical)
|
|
|
|
damage_to_apply=Weapons[weapon->id].player_damage*Frametime;
|
|
|
|
else
|
|
|
|
damage_to_apply=Weapons[weapon->id].player_damage;
|
|
|
|
|
|
|
|
// Factor in multiplier
|
|
|
|
damage_to_apply*=weapon->ctype.laser_info.multiplier;
|
|
|
|
|
|
|
|
int damage_type = electrical ? PD_ENERGY_WEAPON : PD_MATTER_WEAPON;
|
|
|
|
|
|
|
|
if (ApplyDamageToPlayer(playerobj, weapon, damage_type, damage_to_apply))
|
|
|
|
{
|
|
|
|
// we were damaged!
|
|
|
|
if (Weapons[weapon->id].sounds[WSI_IMPACT_ROBOT]!=SOUND_NONE_INDEX)
|
|
|
|
Sound_system.Play3dSound(Weapons[weapon->id].sounds[WSI_IMPACT_ROBOT], SND_PRIORITY_NORMAL, weapon);
|
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
if(Demo_flags == DF_RECORDING)
|
|
|
|
{
|
|
|
|
DemoWriteCollidePlayerWeapon( playerobj, weapon, collision_point, collision_normal, f_reverse_normal, hit_info );
|
|
|
|
}
|
|
|
|
else if(Demo_flags == DF_PLAYBACK)
|
|
|
|
{
|
|
|
|
//During playback we don't need the code below (actually it won't work)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!electrical)
|
|
|
|
{
|
|
|
|
bump_two_objects(playerobj, weapon, collision_point, collision_normal, 0);
|
|
|
|
|
|
|
|
if(!f_stick || (hit_info == NULL))
|
|
|
|
{
|
|
|
|
if(!(weapon->mtype.phys_info.flags & PF_PERSISTENT))
|
|
|
|
SetObjectDeadFlag (weapon);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
MakeWeaponStick(weapon, playerobj, hit_info);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#define COLLISION_OF(a,b) (((a)<<8) + (b))
|
|
|
|
|
|
|
|
#define DO_COLLISION(type1,type2,collision_function) case COLLISION_OF( (type1), (type2) ): (collision_function)( (A), (B), collision_point, collision_normal, false, hit_info); break; case COLLISION_OF( (type2), (type1) ): (collision_function)( (B), (A), collision_point, collision_normal, true, hit_info); break;
|
|
|
|
|
|
|
|
#define DO_SAME_COLLISION(type1,type2,collision_function) case COLLISION_OF( (type1), (type1) ): (collision_function)( (A), (B), collision_point, collision_normal, false, hit_info); break;
|
|
|
|
|
|
|
|
#define NO_COLLISION(type1,type2) case COLLISION_OF( (type1), (type2) ): case COLLISION_OF( (type2), (type1) ): break;
|
|
|
|
|
|
|
|
void check_lg_inform(object *A, object *B)
|
|
|
|
{
|
|
|
|
if(A->flags & (OF_INFORM_PLAYER_COLLIDE_TO_LG | OF_INFORM_PLAYER_WEAPON_COLLIDE_TO_LG))
|
|
|
|
{
|
|
|
|
if(B->type == OBJ_PLAYER)
|
|
|
|
{
|
|
|
|
bool f_pwc = (A->flags & OF_INFORM_PLAYER_WEAPON_COLLIDE_TO_LG) != 0;
|
|
|
|
int type;
|
|
|
|
|
|
|
|
if(f_pwc)
|
|
|
|
{
|
|
|
|
type = OF_INFORM_PLAYER_WEAPON_COLLIDE_TO_LG;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
type = OF_INFORM_PLAYER_COLLIDE_TO_LG;
|
|
|
|
}
|
|
|
|
|
|
|
|
Level_goals.Inform(LIT_OBJECT, type, A->handle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(A->flags & OF_INFORM_PLAYER_WEAPON_COLLIDE_TO_LG)
|
|
|
|
{
|
|
|
|
if(B->type == OBJ_WEAPON)
|
|
|
|
{
|
|
|
|
object *parent = ObjGetUltimateParent(B);
|
|
|
|
|
|
|
|
if(parent && parent->type == OBJ_PLAYER)
|
|
|
|
{
|
|
|
|
Level_goals.Inform(LIT_OBJECT, OF_INFORM_PLAYER_WEAPON_COLLIDE_TO_LG, A->handle);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void collide_two_objects( object * A, object * B, vector *collision_point, vector *collision_normal, fvi_info *hit_info)
|
|
|
|
{
|
|
|
|
int collision_type;
|
|
|
|
int a_num=A-Objects;
|
|
|
|
int b_num=B-Objects;
|
|
|
|
ubyte a_good=0,b_good=0;
|
|
|
|
ubyte a_hittime_good=1,b_hittime_good=1;
|
|
|
|
|
|
|
|
//Only do omega particle collisions if specifically allowed
|
|
|
|
extern bool Enable_omega_collions;
|
|
|
|
if (((A->type == OBJ_WEAPON) && (A->id == OMEGA_INDEX)) || ((B->type == OBJ_WEAPON) && (B->id == OMEGA_INDEX)))
|
|
|
|
if (! Enable_omega_collions)
|
|
|
|
return;
|
|
|
|
|
|
|
|
ASSERT(CollisionResult[A->type][B->type] != RESULT_NOTHING);
|
|
|
|
|
|
|
|
collision_type = COLLISION_OF(A->type,B->type);
|
|
|
|
|
|
|
|
check_lg_inform(A, B);
|
|
|
|
check_lg_inform(B, A);
|
|
|
|
|
|
|
|
//mprintf( (0, "Object %d of type %d collided with object %d of type %d\n", A-Objects,A->type, B-Objects, B->type ));
|
|
|
|
|
|
|
|
// COLLISION SCRIPT HOOK
|
|
|
|
if (Game_mode & GM_MULTI)
|
|
|
|
{
|
|
|
|
ASSERT (!(A->flags & OF_DEAD));
|
|
|
|
ASSERT (!(B->flags & OF_DEAD));
|
|
|
|
|
|
|
|
// Make sure we have good scripts to call
|
|
|
|
if (A->type==OBJ_PLAYER || A->type==OBJ_ROBOT || A->type==OBJ_POWERUP || A->type==OBJ_WEAPON || A->type==OBJ_BUILDING || A->type==OBJ_DOOR || A->type==OBJ_CLUTTER)
|
|
|
|
a_good=1;
|
|
|
|
if (B->type==OBJ_PLAYER || B->type==OBJ_ROBOT || B->type==OBJ_POWERUP || B->type==OBJ_WEAPON || B->type==OBJ_BUILDING || B->type==OBJ_DOOR || B->type==OBJ_CLUTTER)
|
|
|
|
b_good=1;
|
|
|
|
|
|
|
|
if (A->type==OBJ_PLAYER && (Players[A->id].flags & (PLAYER_FLAGS_DYING|PLAYER_FLAGS_DEAD)))
|
|
|
|
a_good=0;
|
|
|
|
if (B->type==OBJ_PLAYER && (Players[B->id].flags & (PLAYER_FLAGS_DYING|PLAYER_FLAGS_DEAD)))
|
|
|
|
b_good=0;
|
|
|
|
|
|
|
|
if (A->type==OBJ_POWERUP && A->effect_info->last_object_hit==b_num && (Gametime-A->effect_info->last_object_hit_time)<1)
|
|
|
|
{
|
|
|
|
a_good = 0;
|
|
|
|
a_hittime_good=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (B->type==OBJ_POWERUP && B->effect_info->last_object_hit==a_num && (Gametime-B->effect_info->last_object_hit_time)<1)
|
|
|
|
{
|
|
|
|
b_good = 0;
|
|
|
|
b_hittime_good=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a_good && b_good)
|
|
|
|
{
|
|
|
|
DLLInfo.me_handle=A->handle;
|
|
|
|
DLLInfo.it_handle=B->handle;
|
|
|
|
DLLInfo.collide_info.point.x = collision_point->x;
|
|
|
|
DLLInfo.collide_info.point.y = collision_point->y;
|
|
|
|
DLLInfo.collide_info.point.z = collision_point->z;
|
|
|
|
DLLInfo.collide_info.normal.x = collision_normal->x;
|
|
|
|
DLLInfo.collide_info.normal.y = collision_normal->y;
|
|
|
|
DLLInfo.collide_info.normal.z = collision_normal->z;
|
|
|
|
CallGameDLL (EVT_GAMECOLLIDE,&DLLInfo);
|
|
|
|
|
|
|
|
DLLInfo.me_handle=B->handle;
|
|
|
|
DLLInfo.it_handle=A->handle;
|
|
|
|
CallGameDLL (EVT_GAMECOLLIDE,&DLLInfo);
|
|
|
|
|
|
|
|
// Update static variables
|
|
|
|
if (A->type==OBJ_POWERUP)
|
|
|
|
{
|
|
|
|
A->effect_info->last_object_hit=b_num;
|
|
|
|
A->effect_info->last_object_hit_time=Gametime;
|
|
|
|
}
|
|
|
|
if (B->type==OBJ_POWERUP)
|
|
|
|
{
|
|
|
|
B->effect_info->last_object_hit=a_num;
|
|
|
|
B->effect_info->last_object_hit_time=Gametime;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call script only if its ok to
|
|
|
|
int ok_to_call_script=1;
|
|
|
|
if (A->type==OBJ_PLAYER && (Players[A->id].flags & (PLAYER_FLAGS_DYING|PLAYER_FLAGS_DEAD)))
|
|
|
|
ok_to_call_script=0;
|
|
|
|
if (B->type==OBJ_PLAYER && (Players[B->id].flags & (PLAYER_FLAGS_DYING|PLAYER_FLAGS_DEAD)))
|
|
|
|
ok_to_call_script=0;
|
|
|
|
|
|
|
|
// Check to see if we should call the script
|
|
|
|
if ((Game_mode & GM_MULTI))
|
|
|
|
{
|
|
|
|
if ((A->type==OBJ_POWERUP || B->type==OBJ_POWERUP) && (a_hittime_good==0 || b_hittime_good==0))
|
|
|
|
ok_to_call_script=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ok_to_call_script)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (!(Game_mode & GM_MULTI))
|
|
|
|
{
|
|
|
|
ASSERT (!(A->flags & OF_DEAD));
|
|
|
|
ASSERT (!(B->flags & OF_DEAD));
|
|
|
|
}
|
|
|
|
tOSIRISEventInfo ei;
|
|
|
|
ei.evt_collide.it_handle = B->handle;
|
|
|
|
Osiris_CallEvent(A,EVT_COLLIDE,&ei);
|
|
|
|
|
|
|
|
ei.evt_collide.it_handle = A->handle;
|
|
|
|
Osiris_CallEvent(B,EVT_COLLIDE,&ei);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch( collision_type )
|
|
|
|
{
|
|
|
|
DO_COLLISION( OBJ_PLAYER, OBJ_WEAPON, collide_player_and_weapon )
|
|
|
|
DO_COLLISION( OBJ_PLAYER, OBJ_MARKER, collide_player_and_marker )
|
|
|
|
|
|
|
|
DO_COLLISION( OBJ_ROBOT, OBJ_PLAYER, collide_generic_and_player )
|
|
|
|
DO_COLLISION( OBJ_BUILDING, OBJ_PLAYER, collide_generic_and_player )
|
|
|
|
DO_COLLISION( OBJ_DOOR, OBJ_PLAYER, collide_generic_and_player )
|
|
|
|
DO_COLLISION( OBJ_ROOM, OBJ_VIEWER, collide_generic_and_player )
|
|
|
|
DO_COLLISION( OBJ_ROOM, OBJ_PLAYER, collide_generic_and_player )
|
|
|
|
DO_COLLISION( OBJ_CLUTTER, OBJ_PLAYER, collide_generic_and_player )
|
|
|
|
|
|
|
|
DO_COLLISION( OBJ_ROBOT, OBJ_WEAPON, collide_generic_and_weapon )
|
|
|
|
DO_COLLISION( OBJ_CLUTTER, OBJ_WEAPON, collide_generic_and_weapon )
|
|
|
|
DO_COLLISION( OBJ_BUILDING, OBJ_WEAPON, collide_generic_and_weapon )
|
|
|
|
DO_COLLISION( OBJ_ROOM, OBJ_WEAPON, collide_generic_and_weapon )
|
|
|
|
DO_COLLISION( OBJ_DOOR, OBJ_WEAPON, collide_generic_and_weapon )
|
|
|
|
|
|
|
|
DO_SAME_COLLISION(OBJ_PLAYER, OBJ_PLAYER, collide_player_and_player )
|
|
|
|
|
|
|
|
//Handled by the script, so no code
|
|
|
|
NO_COLLISION( OBJ_PLAYER, OBJ_POWERUP )
|
|
|
|
NO_COLLISION (OBJ_POWERUP, OBJ_WEAPON)
|
|
|
|
|
|
|
|
default:
|
|
|
|
bump_two_objects(A, B, collision_point, collision_normal, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if((A->type == OBJ_PLAYER && B->type == OBJ_POWERUP && (B->flags & OF_DEAD)) || (B->type == OBJ_PLAYER && A->type == OBJ_POWERUP && (A->flags & OF_DEAD)))
|
|
|
|
{
|
|
|
|
ain_hear hear;
|
|
|
|
hear.f_directly_player = true;
|
|
|
|
hear.hostile_level = 0.05f;
|
|
|
|
hear.curiosity_level = 1.0f;
|
|
|
|
|
|
|
|
hear.max_dist = Sounds[SOUND_POWERUP_PICKUP].max_distance;
|
|
|
|
if(A->type == OBJ_PLAYER)
|
|
|
|
AINotify(A, AIN_HEAR_NOISE, (void *)&hear);
|
|
|
|
else
|
|
|
|
AINotify(B, AIN_HEAR_NOISE, (void *)&hear);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#define ENABLE_COLLISION_SPHERE_SPHERE(type1,type2) CollisionResult[type1][type2] = RESULT_CHECK_SPHERE_SPHERE; CollisionResult[type2][type1] = RESULT_CHECK_SPHERE_SPHERE;
|
|
|
|
|
|
|
|
#define ENABLE_COLLISION_SPHERE_POLY(type1,type2) CollisionResult[type1][type2] = RESULT_CHECK_SPHERE_POLY; CollisionResult[type2][type1] = RESULT_CHECK_POLY_SPHERE;
|
|
|
|
|
|
|
|
#define ENABLE_COLLISION_POLY_SPHERE(type1,type2) CollisionResult[type1][type2] = RESULT_CHECK_POLY_SPHERE; CollisionResult[type2][type1] = RESULT_CHECK_SPHERE_POLY;
|
|
|
|
|
|
|
|
#define ENABLE_COLLISION_BBOX_POLY(type1,type2) CollisionResult[type1][type2] = RESULT_CHECK_BBOX_POLY; CollisionResult[type2][type1] = RESULT_CHECK_POLY_BBOX;
|
|
|
|
|
|
|
|
#define ENABLE_COLLISION_POLY_BBOX(type1,type2) CollisionResult[type1][type2] = RESULT_CHECK_POLY_BBOX; CollisionResult[type2][type1] = RESULT_CHECK_BBOX_POLY;
|
|
|
|
|
|
|
|
#define ENABLE_COLLISION_BBOX_BBOX(type1,type2) CollisionResult[type1][type2] = RESULT_CHECK_BBOX_BBOX; CollisionResult[type2][type1] = RESULT_CHECK_BBOX_BBOX;
|
|
|
|
|
|
|
|
#define ENABLE_COLLISION_BBOX_SPHERE(type1,type2) CollisionResult[type1][type2] = RESULT_CHECK_BBOX_SPHERE; CollisionResult[type2][type1] = RESULT_CHECK_SPHERE_BBOX;
|
|
|
|
|
|
|
|
#define ENABLE_COLLISION_SPHERE_BBOX(type1,type2) CollisionResult[type1][type2] = RESULT_CHECK_SPHERE_BBOX; CollisionResult[type2][type1] = RESULT_CHECK_BBOX_SPHERE;
|
|
|
|
|
|
|
|
#define ENABLE_COLLISION_SPHERE_ROOM(type1,type2) CollisionResult[type1][type2] = RESULT_CHECK_SPHERE_ROOM; CollisionResult[type2][type1] = RESULT_CHECK_SPHERE_ROOM;
|
|
|
|
|
|
|
|
#define ENABLE_COLLISION_BBOX_ROOM(type1,type2) CollisionResult[type1][type2] = RESULT_CHECK_BBOX_ROOM; CollisionResult[type2][type1] = RESULT_CHECK_BBOX_ROOM;
|
|
|
|
|
|
|
|
#define DISABLE_COLLISION(type1,type2) CollisionResult[type1][type2] = RESULT_NOTHING; CollisionResult[type2][type1] = RESULT_NOTHING;
|
|
|
|
|
|
|
|
void CollideInit() {
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
for (i=0; i < MAX_OBJECT_TYPES; i++ )
|
|
|
|
for (j=0; j < MAX_OBJECT_TYPES; j++ )
|
|
|
|
{
|
|
|
|
CollisionResult[i][j] = RESULT_NOTHING;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i=0; i < MAX_OBJECT_TYPES; i++ )
|
|
|
|
{
|
|
|
|
CollisionRayResult[i] = RESULT_NOTHING;
|
|
|
|
}
|
|
|
|
CollisionRayResult[OBJ_ROBOT] = RESULT_CHECK_SPHERE_POLY;
|
|
|
|
CollisionRayResult[OBJ_PLAYER] = RESULT_CHECK_SPHERE_POLY;
|
|
|
|
CollisionRayResult[OBJ_WEAPON] = RESULT_CHECK_SPHERE_POLY;
|
|
|
|
CollisionRayResult[OBJ_POWERUP] = RESULT_CHECK_SPHERE_POLY;
|
|
|
|
CollisionRayResult[OBJ_CLUTTER] = RESULT_CHECK_SPHERE_POLY;
|
|
|
|
CollisionRayResult[OBJ_BUILDING] = RESULT_CHECK_SPHERE_POLY;
|
|
|
|
CollisionRayResult[OBJ_DOOR] = RESULT_CHECK_SPHERE_POLY;
|
|
|
|
CollisionRayResult[OBJ_ROOM] = RESULT_CHECK_SPHERE_POLY;
|
|
|
|
|
|
|
|
for(i=0; i < MAX_OBJECT_TYPES; i++)
|
|
|
|
{
|
|
|
|
ENABLE_COLLISION_SPHERE_ROOM( i, OBJ_ROOM )
|
|
|
|
}
|
|
|
|
|
|
|
|
ENABLE_COLLISION_POLY_SPHERE( OBJ_WALL, OBJ_ROBOT )
|
|
|
|
ENABLE_COLLISION_POLY_SPHERE( OBJ_WALL, OBJ_WEAPON )
|
|
|
|
ENABLE_COLLISION_POLY_SPHERE( OBJ_WALL, OBJ_PLAYER )
|
|
|
|
ENABLE_COLLISION_SPHERE_SPHERE( OBJ_ROBOT, OBJ_ROBOT )
|
|
|
|
// ENABLE_COLLISION_SPHERE_SPHERE( OBJ_BUILDING, OBJ_BUILDING )
|
|
|
|
ENABLE_COLLISION_POLY_SPHERE( OBJ_PLAYER, OBJ_FIREBALL )
|
|
|
|
ENABLE_COLLISION_SPHERE_SPHERE( OBJ_PLAYER, OBJ_PLAYER )
|
|
|
|
ENABLE_COLLISION_SPHERE_SPHERE( OBJ_PLAYER, OBJ_MARKER )
|
|
|
|
ENABLE_COLLISION_SPHERE_SPHERE( OBJ_MARKER, OBJ_PLAYER )
|
|
|
|
ENABLE_COLLISION_SPHERE_SPHERE( OBJ_WEAPON, OBJ_WEAPON )
|
|
|
|
ENABLE_COLLISION_POLY_SPHERE( OBJ_ROBOT, OBJ_PLAYER )
|
|
|
|
// ENABLE_COLLISION_SPHERE_SPHERE( OBJ_ROBOT, OBJ_PLAYER )
|
|
|
|
ENABLE_COLLISION_POLY_SPHERE( OBJ_ROBOT, OBJ_WEAPON )
|
|
|
|
|
|
|
|
ENABLE_COLLISION_POLY_SPHERE( OBJ_PLAYER, OBJ_WEAPON )
|
|
|
|
ENABLE_COLLISION_SPHERE_SPHERE( OBJ_PLAYER, OBJ_POWERUP )
|
|
|
|
ENABLE_COLLISION_SPHERE_SPHERE( OBJ_POWERUP, OBJ_WALL )
|
|
|
|
ENABLE_COLLISION_SPHERE_POLY( OBJ_WEAPON, OBJ_CLUTTER )
|
|
|
|
ENABLE_COLLISION_SPHERE_POLY( OBJ_PLAYER, OBJ_CLUTTER )
|
|
|
|
ENABLE_COLLISION_SPHERE_SPHERE( OBJ_CLUTTER, OBJ_CLUTTER )
|
|
|
|
ENABLE_COLLISION_SPHERE_POLY( OBJ_ROBOT, OBJ_CLUTTER )
|
|
|
|
ENABLE_COLLISION_SPHERE_POLY( OBJ_PLAYER, OBJ_BUILDING )
|
|
|
|
ENABLE_COLLISION_SPHERE_POLY( OBJ_ROBOT, OBJ_BUILDING )
|
|
|
|
ENABLE_COLLISION_SPHERE_POLY( OBJ_WEAPON, OBJ_BUILDING )
|
|
|
|
ENABLE_COLLISION_SPHERE_POLY( OBJ_CLUTTER, OBJ_BUILDING )
|
|
|
|
ENABLE_COLLISION_SPHERE_POLY( OBJ_CLUTTER, OBJ_DOOR )
|
|
|
|
ENABLE_COLLISION_SPHERE_POLY( OBJ_BUILDING, OBJ_DOOR )
|
|
|
|
|
|
|
|
ENABLE_COLLISION_SPHERE_ROOM( OBJ_PLAYER, OBJ_ROOM )
|
|
|
|
ENABLE_COLLISION_SPHERE_ROOM( OBJ_ROBOT, OBJ_ROOM )
|
|
|
|
ENABLE_COLLISION_SPHERE_ROOM( OBJ_WEAPON, OBJ_ROOM )
|
|
|
|
ENABLE_COLLISION_SPHERE_ROOM( OBJ_VIEWER, OBJ_ROOM )
|
|
|
|
|
|
|
|
ENABLE_COLLISION_SPHERE_POLY( OBJ_PLAYER, OBJ_DOOR )
|
|
|
|
ENABLE_COLLISION_SPHERE_POLY( OBJ_ROBOT, OBJ_DOOR )
|
|
|
|
ENABLE_COLLISION_SPHERE_POLY( OBJ_WEAPON, OBJ_DOOR )
|
|
|
|
DISABLE_COLLISION( OBJ_POWERUP, OBJ_POWERUP )
|
|
|
|
}
|
|
|
|
|
|
|
|
//Process a collision between an object and a wall
|
|
|
|
//Returns true if the object hits the wall, and false if should keep going though the wall (for breakable glass)
|
|
|
|
bool collide_object_with_wall( object * A, float hitspeed, int hitseg, int hitwall, vector * hitpt, vector *wall_normal, float hit_dot )
|
|
|
|
{
|
|
|
|
ubyte do_event = 0;
|
|
|
|
bool ret = true;
|
|
|
|
|
|
|
|
switch( A->type ) {
|
|
|
|
case OBJ_NONE:
|
|
|
|
Error( "A object of type NONE hit a wall!\n");
|
|
|
|
break;
|
|
|
|
case OBJ_PLAYER: collide_player_and_wall(A,hitspeed,hitseg,hitwall,hitpt, wall_normal, hit_dot); do_event = 1; break;
|
|
|
|
case OBJ_WEAPON: ret = collide_weapon_and_wall(A,hitspeed,hitseg,hitwall,hitpt, wall_normal, hit_dot); do_event = 1; break;
|
|
|
|
case OBJ_DEBRIS: break; // chrishack -- collide_debris_and_wall(A,hitspeed,hitseg,hitwall,hitpt); break;
|
|
|
|
case OBJ_FIREBALL: break; //collide_fireball_and_wall(A,hitspeed,hitseg,hitwall,hitpt);
|
|
|
|
case OBJ_CLUTTER:
|
|
|
|
case OBJ_BUILDING:
|
|
|
|
case OBJ_ROBOT: collide_generic_and_wall(A,hitspeed,hitseg,hitwall,hitpt, wall_normal, hit_dot); do_event = 1; break;
|
|
|
|
case OBJ_VIEWER: break; //collide_camera_and_wall(A,hitspeed,hitseg,hitwall,hitpt);
|
|
|
|
case OBJ_POWERUP: break; //collide_powerup_and_wall(A,hitspeed,hitseg,hitwall,hitpt);
|
|
|
|
case OBJ_GHOST: break; //do nothing
|
|
|
|
case OBJ_OBSERVER: break; // do nothing
|
|
|
|
case OBJ_SPLINTER: break;
|
|
|
|
case OBJ_MARKER: break;
|
|
|
|
case OBJ_SHARD:
|
|
|
|
if(sound_override_glass_breaking == -1)
|
|
|
|
Sound_system.Play3dSound(SOUND_BREAKING_GLASS,SND_PRIORITY_NORMAL,A,MAX_GAME_VOLUME/10);
|
|
|
|
else
|
|
|
|
Sound_system.Play3dSound(sound_override_glass_breaking,SND_PRIORITY_NORMAL,A,MAX_GAME_VOLUME/10);
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
mprintf((0, "Unhandled collision of object type %d and wall\n", A->type));
|
|
|
|
// Error( "Unhandled object type hit wall in collide.c\n" );
|
|
|
|
}
|
|
|
|
|
|
|
|
if(do_event && (Game_mode&GM_MULTI))
|
|
|
|
{
|
|
|
|
//call multiplayer event
|
|
|
|
DLLInfo.me_handle=A->handle;
|
|
|
|
DLLInfo.it_handle=OBJECT_HANDLE_NONE;
|
|
|
|
DLLInfo.collide_info.point.x = hitpt->x;
|
|
|
|
DLLInfo.collide_info.point.y = hitpt->y;
|
|
|
|
DLLInfo.collide_info.point.z = hitpt->z;
|
|
|
|
DLLInfo.collide_info.normal.x = wall_normal->x;
|
|
|
|
DLLInfo.collide_info.normal.y = wall_normal->y;
|
|
|
|
DLLInfo.collide_info.normal.z = wall_normal->z;
|
|
|
|
DLLInfo.collide_info.hitspeed = hitspeed;
|
|
|
|
DLLInfo.collide_info.hit_dot = hit_dot;
|
|
|
|
DLLInfo.collide_info.hitseg = hitseg;
|
|
|
|
DLLInfo.collide_info.hitwall = hitwall;
|
|
|
|
CallGameDLL (EVT_GAMEWALLCOLLIDE,&DLLInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|