home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / main / collide.c < prev    next >
Text File  |  1998-06-08  |  71KB  |  2,063 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. /*
  14.  * $Source: f:/miner/source/main/rcs/collide.c $
  15.  * $Revision: 2.5 $
  16.  * $Author: john $
  17.  * $Date: 1995/07/26 12:07:46 $
  18.  * 
  19.  * $Log: collide.c $
  20.  * Revision 2.5  1995/07/26  12:07:46  john
  21.  * Made code that pages in weapon_info->robot_hit_vclip not
  22.  * page in unless it is a badass weapon.  Took out old functionallity
  23.  * of using this if no robot exp1_vclip, since all robots have these.
  24.  * 
  25.  * Revision 2.4  1995/03/30  16:36:09  mike
  26.  * text localization.
  27.  * 
  28.  * Revision 2.3  1995/03/24  15:11:13  john
  29.  * Added ugly robot cheat.
  30.  * 
  31.  * Revision 2.2  1995/03/21  14:41:04  john
  32.  * Ifdef'd out the NETWORK code.
  33.  * 
  34.  * Revision 2.1  1995/03/20  18:16:02  john
  35.  * Added code to not store the normals in the segment structure.
  36.  * 
  37.  * Revision 2.0  1995/02/27  11:32:20  john
  38.  * New version 2.0, which has no anonymous unions, builds with
  39.  * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
  40.  * 
  41.  * Revision 1.289  1995/02/22  13:56:06  allender
  42.  * remove anonymous unions from object structure
  43.  * 
  44.  * Revision 1.288  1995/02/11  15:52:45  rob
  45.  * Included text.h.
  46.  * 
  47.  * Revision 1.287  1995/02/11  15:04:11  rob
  48.  * Localized a string.
  49.  * 
  50.  * Revision 1.286  1995/02/11  14:25:41  rob
  51.  * Added invul. controlcen option.
  52.  * 
  53.  * Revision 1.285  1995/02/06  15:53:00  mike
  54.  * create awareness event for player:wall collision.
  55.  * 
  56.  * Revision 1.284  1995/02/05  23:18:17  matt
  57.  * Deal with objects (such as fusion blobs) that get created already
  58.  * poking through a wall
  59.  * 
  60.  * Revision 1.283  1995/02/01  17:51:33  mike
  61.  * fusion bolt can now toast multiple proximity bombs.
  62.  * 
  63.  * Revision 1.282  1995/02/01  17:29:20  john
  64.  * Lintized
  65.  * 
  66.  * Revision 1.281  1995/02/01  15:04:00  rob
  67.  * Changed sound of weapons hitting invulnerable players.
  68.  * 
  69.  * Revision 1.280  1995/01/31  16:16:35  mike
  70.  * Separate smart blobs for robot and player.
  71.  * 
  72.  * Revision 1.279  1995/01/29  15:57:10  rob
  73.  * Fixed another bug with robot_request_change calls.
  74.  * 
  75.  * Revision 1.278  1995/01/28  18:15:06  rob
  76.  * Fixed a bug in multi_request_robot_change.
  77.  * 
  78.  * Revision 1.277  1995/01/27  15:15:44  rob
  79.  * Fixing problems with controlcen damage.
  80.  * 
  81.  * Revision 1.276  1995/01/27  15:13:10  mike
  82.  * comment out mprintf.
  83.  * 
  84.  * Revision 1.275  1995/01/26  22:11:51  mike
  85.  * Purple chromo-blaster (ie, fusion cannon) spruce up (chromification)
  86.  * 
  87.  * Revision 1.274  1995/01/26  18:57:55  rob
  88.  * Changed two uses of digi_play_sample to digi_link_sound_to_pos which
  89.  * made more sense.
  90.  * 
  91.  * Revision 1.273  1995/01/25  23:37:58  mike
  92.  * make persistent objects not hit player more than once.
  93.  * Also, make them hit player before degrading them, else they often did 0 damage.
  94.  * 
  95.  * Revision 1.272  1995/01/25  18:23:54  rob
  96.  * Don't let players pick up powerups in exit tunnel.
  97.  * 
  98.  * Revision 1.271  1995/01/25  13:43:18  rob
  99.  * Added robot transfer for player collisions.
  100.  * Removed mprintf from collide.c on Mike's request.
  101.  * 
  102.  * Revision 1.270  1995/01/25  10:24:01  mike
  103.  * Make sizzle and rock happen in lava even if you're invulnerable.
  104.  * 
  105.  * Revision 1.269  1995/01/22  17:05:33  mike
  106.  * Call multi_robot_request_change when a robot gets whacked by a player or
  107.  * player weapon, if player_num != Player_num
  108.  * 
  109.  * Revision 1.268  1995/01/21  21:20:28  matt
  110.  * Fixed stupid bug
  111.  * 
  112.  * Revision 1.267  1995/01/21  18:47:47  rob
  113.  * Fixed a really dumb bug with player keys.
  114.  * 
  115.  * Revision 1.266  1995/01/21  17:39:30  matt
  116.  * Cleaned up laser/player hit wall confusions
  117.  * 
  118.  * Revision 1.265  1995/01/19  17:44:42  mike
  119.  * damage_force removed, that information coming from strength field.
  120.  * 
  121.  * Revision 1.264  1995/01/18  17:12:56  rob
  122.  * Fixed control stuff for multiplayer.
  123.  * 
  124.  * Revision 1.263  1995/01/18  16:12:33  mike
  125.  * Make control center aware of a cloaked playerr when he fires.
  126.  * 
  127.  * Revision 1.262  1995/01/17  17:48:42  rob
  128.  * Added key syncing for coop players.
  129.  * 
  130.  * Revision 1.261  1995/01/16  19:30:28  rob
  131.  * Fixed an assert error in fireball.c
  132.  * 
  133.  * Revision 1.260  1995/01/16  19:23:51  mike
  134.  * Say Boss_been_hit if he been hit so he gates appropriately.
  135.  * 
  136.  * Revision 1.259  1995/01/16  11:55:16  mike
  137.  * make enemies become aware of player if he damages control center.
  138.  * 
  139.  * Revision 1.258  1995/01/15  16:42:00  rob
  140.  * Fixed problem with robot bumping damage.
  141.  * 
  142.  * Revision 1.257  1995/01/14  19:16:36  john
  143.  * First version of new bitmap paging code.
  144.  * 
  145.  * Revision 1.256  1995/01/03  17:58:37  rob
  146.  * Fixed scoring problems.
  147.  * 
  148.  * Revision 1.255  1994/12/29  12:41:11  rob
  149.  * Tweaking robot exploding in coop.
  150.  * 
  151.  * Revision 1.254  1994/12/28  10:37:59  rob
  152.  * Fixed ifdef of multibot stuff.
  153.  * 
  154.  * Revision 1.253  1994/12/21  19:03:14  rob
  155.  * Fixing score accounting for multiplayer robots
  156.  * 
  157.  * Revision 1.252  1994/12/21  17:36:31  rob
  158.  * Fix hostage pickup problem in network.
  159.  * tweaking robot powerup drops.
  160.  * 
  161.  * Revision 1.251  1994/12/19  20:32:34  rob
  162.  * Remove awareness events from player collisions and lasers that are not the console player.
  163.  * 
  164.  * Revision 1.250  1994/12/19  20:01:22  rob
  165.  * Added multibot.h include.
  166.  * 
  167.  * Revision 1.249  1994/12/19  16:36:41  rob
  168.  * Patches damaging of multiplayer robots.
  169.  * 
  170.  * Revision 1.248  1994/12/14  21:15:18  rob
  171.  * play lava hiss across network.
  172.  * 
  173.  * Revision 1.247  1994/12/14  17:09:09  matt
  174.  * Fixed problem with no sound when lasers hit closed walls, like grates.
  175.  * 
  176.  * Revision 1.246  1994/12/14  09:51:49  mike
  177.  * make any weapon cause proximity bomb detonation.
  178.  * 
  179.  * Revision 1.245  1994/12/13  12:55:25  mike
  180.  * change number of proximity bomb powerups which get dropped.
  181.  * 
  182.  * Revision 1.244  1994/12/12  17:17:53  mike
  183.  * make boss cloak/teleport when get hit, make quad laser 3/4 as powerful.
  184.  * 
  185.  * Revision 1.243  1994/12/12  12:07:51  rob
  186.  * Don't take damage if we're in endlevel sequence.
  187.  * 
  188.  * Revision 1.242  1994/12/11  23:44:52  mike
  189.  * less phys_apply_rot() at higher skill levels.
  190.  * 
  191.  * Revision 1.241  1994/12/11  12:37:02  mike
  192.  * remove stupid robot spinning code.  it was really stupid.  (actually, call here, code in ai.c).
  193.  * 
  194.  * Revision 1.240  1994/12/10  16:44:51  matt
  195.  * Added debugging code to track down door that turns into rock
  196.  * 
  197.  * Revision 1.239  1994/12/09  14:59:19  matt
  198.  * Added system to attach a fireball to another object for rendering purposes,
  199.  * so the fireball always renders on top of (after) the object.
  200.  * 
  201.  * Revision 1.238  1994/12/09  09:57:02  mike
  202.  * Don't allow robots or their weapons to pass through control center.
  203.  * 
  204.  * Revision 1.237  1994/12/08  15:46:03  mike
  205.  * better robot behavior.
  206.  * 
  207.  * Revision 1.236  1994/12/08  12:32:56  mike
  208.  * make boss dying more interesting.
  209.  * 
  210.  * Revision 1.235  1994/12/07  22:49:15  mike
  211.  * tweak rotation due to collision.
  212.  * 
  213.  * Revision 1.234  1994/12/07  16:44:50  mike
  214.  * make bump sound if supposed to, even if not taking damage.
  215.  * 
  216.  * Revision 1.233  1994/12/07  12:55:08  mike
  217.  * tweak rotvel applied from collisions.
  218.  * 
  219.  * Revision 1.232  1994/12/05  19:30:48  matt
  220.  * Fixed horrible segment over-dereferencing
  221.  * 
  222.  * Revision 1.231  1994/12/05  00:32:15  mike
  223.  * do rotvel on badass and bump collisions.
  224.  * 
  225.  * Revision 1.230  1994/12/03  12:49:22  mike
  226.  * don't play bonk sound when you collide with a volatile wall (like lava).
  227.  * 
  228.  * Revision 1.229  1994/12/02  16:51:09  mike
  229.  * make lava sound only happen at 4 Hz.
  230.  * 
  231.  * Revision 1.228  1994/11/30  23:55:27  rob
  232.  * Fixed a bug where a laser hitting a wall was making 2 sounds.
  233.  * 
  234.  * Revision 1.227  1994/11/30  20:11:00  rob
  235.  * Fixed # of dropped laser powerups.
  236.  * 
  237.  * Revision 1.226  1994/11/30  19:19:03  rob
  238.  * Transmit collission sounds for net games.
  239.  * 
  240.  * Revision 1.225  1994/11/30  16:33:01  mike
  241.  * new boss behavior.
  242.  * 
  243.  * Revision 1.224  1994/11/30  15:44:17  mike
  244.  * /2 on boss smart children damage.
  245.  * 
  246.  * Revision 1.223  1994/11/30  14:03:03  mike
  247.  * hook for claw sounds
  248.  * 
  249.  * Revision 1.222  1994/11/29  20:41:09  matt
  250.  * Deleted a bunch of commented-out lines
  251.  * 
  252.  * Revision 1.221  1994/11/27  23:15:08  matt
  253.  * Made changes for new mprintf calling convention
  254.  * 
  255.  * Revision 1.220  1994/11/19  16:11:28  rob
  256.  * Collision damage with walls or lava is counted as suicides in net games
  257.  * 
  258.  * Revision 1.219  1994/11/19  15:20:41  mike
  259.  * rip out unused code and data
  260.  * 
  261.  * Revision 1.218  1994/11/17  18:44:27  rob
  262.  * Added OBJ_GHOST to list of valid player types to create eggs.
  263.  * 
  264.  * Revision 1.217  1994/11/17  14:57:59  mike
  265.  * moved segment validation functions from editor to main.
  266.  * 
  267.  * Revision 1.216  1994/11/16  23:38:36  mike
  268.  * new improved boss teleportation behavior.
  269.  * 
  270.  * Revision 1.215  1994/11/16  12:16:29  mike
  271.  * Enable collisions between robots.  A hack in fvi.c only does this for robots which lunge to attack (eg, green guy)
  272.  * 
  273.  * Revision 1.214  1994/11/15  16:51:50  mike
  274.  * bump player when he hits a volatile wall.
  275.  * 
  276.  * Revision 1.213  1994/11/12  16:38:44  mike
  277.  * allow flares to open doors.
  278.  * 
  279.  * Revision 1.212  1994/11/10  13:09:19  matt
  280.  * Added support for new run-length-encoded bitmaps
  281.  * 
  282.  * Revision 1.211  1994/11/09  17:05:43  matt
  283.  * Fixed problem with volatile walls
  284.  * 
  285.  * Revision 1.210  1994/11/09  12:11:46  mike
  286.  * only award points if ConsoleObject killed robot.
  287.  * 
  288.  * Revision 1.209  1994/11/09  11:11:03  yuan
  289.  * Made wall volatile if either tmap_num1 or tmap_num2 is a volatile wall.
  290.  * 
  291.  * Revision 1.208  1994/11/08  12:20:15  mike
  292.  * moved do_controlcen_destroyed_stuff from here to cntrlcen.c
  293.  * 
  294.  * Revision 1.207  1994/11/02  23:22:08  mike
  295.  * Make ` (backquote, KEY_LAPOSTRO) tell what wall was hit by laser.
  296.  * 
  297.  * Revision 1.206  1994/11/02  18:03:00  rob
  298.  * Fix control_center_been_hit logic so it only cares about the local player.
  299.  * Other players take care of their own control center 'ai'.
  300.  * 
  301.  * Revision 1.205  1994/11/01  19:37:33  rob
  302.  * Changed the max # of consussion missiles to 4.
  303.  * (cause they're lame and clutter things up)
  304.  * 
  305.  * Revision 1.204  1994/11/01  18:06:35  john
  306.  * Tweaked wall banging sound constant.
  307.  * 
  308.  * Revision 1.203  1994/11/01  18:01:40  john
  309.  * Made wall bang less obnoxious, but volume based.
  310.  * 
  311.  * Revision 1.202  1994/11/01  17:11:05  rob
  312.  * Changed some stuff in drop_player_eggs.
  313.  * 
  314.  * Revision 1.201  1994/11/01  12:18:23  john
  315.  * Added sound volume support. Made wall collisions be louder/softer.
  316.  * 
  317.  * Revision 1.200  1994/10/31  13:48:44  rob
  318.  * Fixed bug in opening doors over network/modem.  Added a new message
  319.  * type to multi.c that communicates door openings across the net. 
  320.  * Changed includes in multi.c and wall.c to accomplish this.
  321.  * 
  322.  * Revision 1.199  1994/10/28  14:42:52  john
  323.  * Added sound volumes to all sound calls.
  324.  * 
  325.  * Revision 1.198  1994/10/27  16:58:37  allender
  326.  * added demo recording of monitors blowing up
  327.  * 
  328.  * Revision 1.197  1994/10/26  23:20:52  matt
  329.  * Tone down flash even more
  330.  * 
  331.  * Revision 1.196  1994/10/26  23:01:50  matt
  332.  * Toned down red flash when damaged
  333.  * 
  334.  * Revision 1.195  1994/10/26  15:56:29  yuan
  335.  * Tweaked some palette flashes.
  336.  * 
  337.  * Revision 1.194  1994/10/25  11:32:26  matt
  338.  * Fixed bugs with vulcan powerups in mutliplayer
  339.  * 
  340.  * Revision 1.193  1994/10/25  10:51:18  matt
  341.  * Vulcan cannon powerups now contain ammo count
  342.  * 
  343.  * Revision 1.192  1994/10/24  14:14:05  matt
  344.  * Fixed bug in bump_two_objects()
  345.  * 
  346.  * Revision 1.191  1994/10/23  19:17:04  matt
  347.  * Fixed bug with "no key" messages
  348.  * 
  349.  * Revision 1.190  1994/10/22  00:08:46  matt
  350.  * Fixed up problems with bonus & game sequencing
  351.  * Player doesn't get credit for hostages unless he gets them out alive
  352.  * 
  353.  * Revision 1.189  1994/10/21  20:42:34  mike
  354.  * Clear number of hostages on board between levels.
  355.  * 
  356.  * Revision 1.188  1994/10/20  15:17:43  mike
  357.  * control center in boss handling.
  358.  * 
  359.  * Revision 1.187  1994/10/20  10:09:47  mike
  360.  * Only ever drop 1 shield powerup in multiplayer (as an egg).
  361.  * 
  362.  * Revision 1.186  1994/10/20  09:47:11  mike
  363.  * Fix bug in dropping vulcan ammo in multiplayer.
  364.  * Also control center stuff.
  365.  * 
  366.  * Revision 1.185  1994/10/19  15:14:32  john
  367.  * Took % hits out of player structure, made %kills work properly.
  368.  * 
  369.  * Revision 1.184  1994/10/19  11:33:16  john
  370.  * Fixed hostage rescued percent.
  371.  * 
  372.  * Revision 1.183  1994/10/19  11:16:49  mike
  373.  * Don't allow crazy josh to open locked doors.
  374.  * Don't allow weapons to harm parent.
  375.  * 
  376.  * Revision 1.182  1994/10/18  18:37:01  mike
  377.  * No more hostage killing.  Too much stuff to do to integrate into game.
  378.  * 
  379.  * Revision 1.181  1994/10/18  16:37:35  mike
  380.  * Debug function for Yuan: Show seg:side when hit by puny laser if Show_seg_and_side != 0.
  381.  * 
  382.  * Revision 1.180  1994/10/18  10:53:17  mike
  383.  * Support attack type as a property of a robot, not of being == GREEN_GUY.
  384.  * 
  385.  * Revision 1.179  1994/10/17  21:18:36  mike
  386.  * diminish damage player does to robot due to collision, only took 2-3 hits to kill a josh.
  387.  * 
  388.  * Revision 1.178  1994/10/17  20:30:40  john
  389.  * Made player_hostages_rescued or whatever count properly.
  390.  * 
  391.  * Revision 1.177  1994/10/16  12:42:56  mike
  392.  * Trap bogus amount of vulcan ammo dropping.
  393.  * 
  394.  * Revision 1.176  1994/10/15  19:06:51  mike
  395.  * Drop vulcan ammo if player has it, but no vulcan cannon (when he dies).
  396.  * 
  397.  * Revision 1.175  1994/10/13  15:42:06  mike
  398.  * Remove afterburner.
  399.  * 
  400.  * Revision 1.174  1994/10/13  11:12:57  mike
  401.  * Apply damage to robots.  I hosed it a couple weeks ago when I made the green guy special.
  402.  * 
  403.  */
  404.  
  405.  
  406. #pragma off (unreferenced)
  407. static char rcsid[] = "$Id: collide.c 2.5 1995/07/26 12:07:46 john Exp $";
  408. #pragma on (unreferenced)
  409.  
  410. #pragma off (unreferenced)    //for all the standard-tempate rountines
  411.  
  412. #include <string.h>    // for memset
  413. #include <stdlib.h>
  414. #include <stdio.h>
  415.  
  416. #include "rle.h"
  417. #include "inferno.h"
  418. #include "game.h"
  419. #include "gr.h"
  420. #include "stdlib.h"
  421. #include "bm.h"
  422. //#include "error.h"
  423. #include "mono.h"
  424. #include "3d.h"
  425. #include "segment.h"
  426. #include "texmap.h"
  427. #include "laser.h"
  428. #include "key.h"
  429. #include "gameseg.h"
  430. #include "object.h"
  431. #include "physics.h"
  432. #include "slew.h"        
  433. #include "render.h"
  434. #include "wall.h"
  435. #include "vclip.h"
  436. #include "polyobj.h"
  437. #include "fireball.h"
  438. #include "laser.h"
  439. #include "error.h"
  440. #include "ai.h"
  441. #include "hostage.h"
  442. #include "fuelcen.h"
  443. #include "sounds.h"
  444. #include "robot.h"
  445. #include "weapon.h"
  446. #include "player.h"
  447. #include "gauges.h"
  448. #include "powerup.h"
  449. #include "network.h"
  450. #include "newmenu.h"
  451. #include "scores.h"
  452. #include "effects.h"
  453. #include "textures.h"
  454. #include "multi.h"
  455. #include "cntrlcen.h"
  456. #include "newdemo.h"
  457. #include "endlevel.h"
  458. #include "multibot.h"
  459. #include "piggy.h"
  460. #include "text.h"
  461.  
  462. #ifdef EDITOR
  463. #include "editor\editor.h"
  464. #endif
  465.  
  466. #include "collide.h"
  467.  
  468. int Ugly_robot_cheat = 0;
  469. int Ugly_robot_texture = 0;
  470.  
  471. #define STANDARD_EXPL_DELAY (f1_0/4)
  472.  
  473. //##void collide_fireball_and_wall(object *fireball,fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt)    {
  474. //##    return; 
  475. //##}
  476.  
  477. //    -------------------------------------------------------------------------------------------------------------
  478. //    The only reason this routine is called (as of 10/12/94) is so Brain guys can open doors.
  479. void collide_robot_and_wall( object * robot, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt)
  480. {
  481.     if ((robot->id == ROBOT_BRAIN) || (robot->ctype.ai_info.behavior == AIB_RUN_FROM)) {
  482.         int    wall_num = Segments[hitseg].sides[hitwall].wall_num;
  483.         if (wall_num != -1) {
  484.             if ((Walls[wall_num].type == WALL_DOOR) && (Walls[wall_num].keys == KEY_NONE) && (Walls[wall_num].state == WALL_DOOR_CLOSED) && !(Walls[wall_num].flags & WALL_DOOR_LOCKED)) {
  485.                 mprintf((0, "Trying to open door at segment %i, side %i\n", hitseg, hitwall));
  486.                 wall_open_door(&Segments[hitseg], hitwall);
  487.             }
  488.         }
  489.     }
  490.  
  491.     return;
  492. }
  493.  
  494. //##void collide_hostage_and_wall( object * hostage, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt)    {
  495. //##    return;
  496. //##}
  497.  
  498. //    -------------------------------------------------------------------------------------------------------------
  499.  
  500. int apply_damage_to_clutter(object *clutter, fix damage)
  501. {
  502.     if ( clutter->flags&OF_EXPLODING) return 0;
  503.  
  504.     if (clutter->shields < 0 ) return 0;    //clutter already dead...
  505.  
  506.     clutter->shields -= damage;
  507.  
  508.     if (clutter->shields < 0) {
  509.         explode_object(clutter,0);
  510.         return 1;
  511.     } else
  512.         return 0;
  513. }
  514.  
  515.  
  516. //given the specified force, apply damage from that force to an object
  517. apply_force_damage(object *obj,fix force,object *other_obj)
  518. {
  519.     int    result;
  520.     fix damage;
  521.  
  522.     if (obj->flags & (OF_EXPLODING|OF_SHOULD_BE_DEAD))
  523.         return;        //already exploding or dead
  524.  
  525.     damage = fixdiv(force,obj->mtype.phys_info.mass) / 8;
  526.  
  527. //mprintf((0,"obj %d, damage=%x\n",obj-Objects,damage));
  528.  
  529.     switch (obj->type) {
  530.  
  531.         case OBJ_ROBOT:
  532.  
  533.             if (Robot_info[obj->id].attack_type == 1) {
  534.                 if (other_obj->type == OBJ_WEAPON)
  535.                     result = apply_damage_to_robot(obj,damage/4, other_obj->ctype.laser_info.parent_num);
  536.                 else
  537.                     result = apply_damage_to_robot(obj,damage/4, other_obj-Objects);
  538.             }
  539.             else {
  540.                 if (other_obj->type == OBJ_WEAPON)
  541.                     result = apply_damage_to_robot(obj,damage/2, other_obj->ctype.laser_info.parent_num);
  542.                 else
  543.                     result = apply_damage_to_robot(obj,damage/2, other_obj-Objects);
  544.             }        
  545.  
  546.             if (result && (other_obj->ctype.laser_info.parent_signature == ConsoleObject->signature))
  547.                 add_points_to_score(Robot_info[obj->id].score_value);
  548.             break;
  549.  
  550.         case OBJ_PLAYER:
  551.  
  552.             apply_damage_to_player(obj,other_obj,damage);
  553.             break;
  554.  
  555.         case OBJ_CLUTTER:
  556.  
  557.             apply_damage_to_clutter(obj,damage);
  558.             break;
  559.  
  560.         case OBJ_CNTRLCEN:
  561.  
  562.             apply_damage_to_controlcen(obj,damage, other_obj-Objects);
  563.             break;
  564.  
  565.         case OBJ_WEAPON:
  566.  
  567.             break;        //weapons don't take damage
  568.  
  569.         default:
  570.  
  571.             Int3();
  572.  
  573.     }
  574. }
  575.  
  576. //    -----------------------------------------------------------------------------
  577. void bump_this_object(object *objp, object *other_objp, vms_vector *force, int damage_flag)
  578. {
  579.     fix force_mag;
  580.  
  581.     if (! (objp->mtype.phys_info.flags & PF_PERSISTENT))
  582.         if (objp->type == OBJ_PLAYER) {
  583.             vms_vector force2;
  584.             force2.x = force->x/4;
  585.             force2.y = force->y/4;
  586.             force2.z = force->z/4;
  587.             phys_apply_force(objp,&force2);
  588.             if (damage_flag) {
  589.                 force_mag = vm_vec_mag_quick(&force2);
  590.                 apply_force_damage(objp, force_mag, other_objp);
  591.             }
  592.         } else if ((objp->type == OBJ_ROBOT) || (objp->type == OBJ_CLUTTER) || (objp->type == OBJ_CNTRLCEN)) {
  593.             if (!Robot_info[objp->id].boss_flag) {
  594.                 vms_vector force2;
  595.                 force2.x = force->x/(4 + Difficulty_level);
  596.                 force2.y = force->y/(4 + Difficulty_level);
  597.                 force2.z = force->z/(4 + Difficulty_level);
  598.  
  599.                 phys_apply_force(objp, force);
  600.                 phys_apply_rot(objp, &force2);
  601.                 if (damage_flag) {
  602.                     force_mag = vm_vec_mag_quick(force);
  603.                     apply_force_damage(objp, force_mag, other_objp);
  604.                 }
  605.             }
  606.         }
  607. }
  608.  
  609. //    -----------------------------------------------------------------------------
  610. //deal with two objects bumping into each other.  Apply force from collision
  611. //to each robot.  The flags tells whether the objects should take damage from
  612. //the collision.
  613. void bump_two_objects(object *obj0,object *obj1,int damage_flag)
  614. {
  615.     vms_vector    dv, force;
  616.     object        *t=NULL;
  617.  
  618.     if (obj0->movement_type != MT_PHYSICS)
  619.         t=obj1;
  620.     else if (obj1->movement_type != MT_PHYSICS)
  621.         t=obj0;
  622.  
  623.     if (t) {
  624.         Assert(t->movement_type == MT_PHYSICS);
  625.         vm_vec_copy_scale(&force,&t->mtype.phys_info.velocity,-t->mtype.phys_info.mass);
  626.         phys_apply_force(t,&force);
  627.         return;
  628.     }
  629.  
  630.     vm_vec_sub(&force,&obj0->mtype.phys_info.velocity,&obj1->mtype.phys_info.velocity);
  631.     vm_vec_scale2(&force,2*fixmul(obj0->mtype.phys_info.mass,obj1->mtype.phys_info.mass),(obj0->mtype.phys_info.mass+obj1->mtype.phys_info.mass));
  632.  
  633.     bump_this_object(obj1, obj0, &force, damage_flag);
  634.     vm_vec_negate(&force);
  635.     bump_this_object(obj0, obj1, &force, damage_flag);
  636.  
  637. }
  638.  
  639. void bump_one_object(object *obj0, vms_vector *hit_dir, fix damage)
  640. {
  641.     vms_vector    hit_vec;
  642.  
  643.     hit_vec = *hit_dir;
  644.     vm_vec_scale(&hit_vec, damage);
  645.  
  646.     phys_apply_force(obj0,&hit_vec);
  647.  
  648. }
  649.  
  650. #define DAMAGE_SCALE         128    //    Was 32 before 8:55 am on Thursday, September 15, changed by MK, walls were hurting me more than robots!
  651. #define DAMAGE_THRESHOLD     (F1_0/3)
  652. #define WALL_LOUDNESS_SCALE (20)
  653.  
  654. void collide_player_and_wall( object * player, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt)
  655. {
  656.     fix damage;
  657.  
  658.     if (player->id != Player_num) // Execute only for local player
  659.         return;
  660.  
  661.     //    If this wall does damage, don't make *BONK* sound, we'll be making another sound.
  662.     if (TmapInfo[Segments[hitseg].sides[hitwall].tmap_num].damage > 0)
  663.         return;
  664.  
  665.     wall_hit_process( &Segments[hitseg], hitwall, 20, player->id, player );
  666.  
  667.     //    ** Damage from hitting wall **
  668.     //    If the player has less than 10% shields, don't take damage from bump
  669.     damage = hitspeed / DAMAGE_SCALE;
  670.  
  671.     if (damage >= DAMAGE_THRESHOLD) {
  672.         int    volume;
  673.         volume = (hitspeed-(DAMAGE_SCALE*DAMAGE_THRESHOLD)) / WALL_LOUDNESS_SCALE ;
  674.  
  675.         create_awareness_event(player, PA_WEAPON_WALL_COLLISION);
  676.  
  677.         if ( volume > F1_0 )
  678.             volume = F1_0;
  679.         if (volume > 0 ) {
  680.             digi_link_sound_to_pos( SOUND_PLAYER_HIT_WALL, hitseg, 0, hitpt, 0, volume );
  681.             #ifdef NETWORK
  682.             if (Game_mode & GM_MULTI)
  683.                 multi_send_play_sound(SOUND_PLAYER_HIT_WALL, volume);    
  684.             #endif
  685.         }
  686.  
  687.         if (!(Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE))
  688.             if ( Players[Player_num].shields > f1_0*10 )
  689.                   apply_damage_to_player( player, player, damage );
  690.     }
  691.  
  692.     return;
  693. }
  694.  
  695. fix    Last_volatile_scrape_sound_time = 0;
  696.  
  697. void collide_weapon_and_wall( object * weapon, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt);
  698. void collide_debris_and_wall( object * debris, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt);
  699.  
  700. //this gets called when an object is scraping along the wall
  701. scrape_object_on_wall(object *obj, short hitseg, short hitside, vms_vector * hitpt )
  702. {
  703.     switch (obj->type) {
  704.  
  705.         case OBJ_PLAYER:
  706.  
  707.             if (obj->id==Player_num) {
  708.                 fix d;
  709.                 //mprintf((0, "Scraped segment #%3i, side #%i\n", hitseg, hitside));
  710.                 if ((d=TmapInfo[Segments[hitseg].sides[hitside].tmap_num].damage) > 0) {
  711.                     vms_vector    hit_dir, rand_vec;
  712.                     fix damage = fixmul(d,FrameTime);
  713.         
  714.                     if (!(Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE))
  715.                         apply_damage_to_player( obj, obj, damage );
  716.         
  717.                     PALETTE_FLASH_ADD(f2i(damage*4), 0, 0);    //flash red
  718.                     if ((GameTime > Last_volatile_scrape_sound_time + F1_0/4) || (GameTime < Last_volatile_scrape_sound_time)) {
  719.                         Last_volatile_scrape_sound_time = GameTime;
  720.                         digi_link_sound_to_pos( SOUND_VOLATILE_WALL_HISS,hitseg, 0, hitpt, 0, F1_0 );
  721.                         #ifdef NETWORK
  722.                         if (Game_mode & GM_MULTI)
  723.                             multi_send_play_sound(SOUND_VOLATILE_WALL_HISS, F1_0);
  724.                         #endif
  725.                     }
  726.                     #ifdef COMPACT_SEGS
  727.                     get_side_normal(&Segments[hitseg], hitside, 0, &hit_dir );    
  728.                     #else
  729.                     hit_dir = Segments[hitseg].sides[hitside].normals[0];
  730.                     #endif
  731.                     make_random_vector(&rand_vec);
  732.                     vm_vec_scale_add2(&hit_dir, &rand_vec, F1_0/8);
  733.                     vm_vec_normalize_quick(&hit_dir);
  734.                     bump_one_object(obj, &hit_dir, F1_0*8);
  735.         
  736.                     obj->mtype.phys_info.rotvel.x = (rand() - 16384)/2;
  737.                     obj->mtype.phys_info.rotvel.z = (rand() - 16384)/2;
  738.         
  739.                 } else {
  740.                     //what scrape sound
  741.                     //PLAY_SOUND( SOUND_PLAYER_SCRAPE_WALL );
  742.                 }
  743.         
  744.             }
  745.  
  746.             break;
  747.  
  748.         //these two kinds of objects below shouldn't really slide, so
  749.         //if this scrape routine gets called (which it might if the
  750.         //object (such as a fusion blob) was created already poking
  751.         //through the wall) call the collide routine.
  752.  
  753.         case OBJ_WEAPON:
  754.             collide_weapon_and_wall(obj,0,hitseg,hitside,hitpt); 
  755.             break;
  756.  
  757.         case OBJ_DEBRIS:        
  758.             collide_debris_and_wall(obj,0,hitseg,hitside,hitpt); 
  759.             break;
  760.     }
  761.  
  762. }
  763.  
  764. //if an effect is hit, and it can blow up, then blow it up
  765. //returns true if it blew up
  766. int check_effect_blowup(segment *seg,int side,vms_vector *pnt)
  767. {
  768.     int tm,ec,db;
  769.  
  770.     if ((tm=seg->sides[side].tmap_num2) != 0)
  771.         if ((ec=TmapInfo[tm&0x3fff].eclip_num)!=-1)
  772.            if ((db=Effects[ec].dest_bm_num)!=-1 && !(Effects[ec].flags&EF_ONE_SHOT)) {
  773.                 fix u,v;
  774.                 grs_bitmap *bm = &GameBitmaps[Textures[tm&0x3fff].index];
  775.                 int x,y,t;
  776.  
  777.                 PIGGY_PAGE_IN(Textures[tm&0x3fff]);
  778.  
  779.                 //this can be blown up...did we hit it?
  780.  
  781.                 find_hitpoint_uv(&u,&v,pnt,seg,side,0);    //evil: always say face zero
  782.  
  783.                 x = ((unsigned) f2i(u*bm->bm_w)) % bm->bm_w;
  784.                 y = ((unsigned) f2i(v*bm->bm_h)) % bm->bm_h;
  785.  
  786.                 switch (tm&0xc000) {        //adjust for orientation of paste-on
  787.  
  788.                     case 0x0000:    break;
  789.                     case 0x4000:    t=y; y=x; x=bm->bm_w-t-1; break;
  790.                     case 0x8000:    y=bm->bm_h-y-1; x=bm->bm_w-x-1; break;
  791.                     case 0xc000:    t=x; x=y; y=bm->bm_h-t-1; break;
  792.  
  793.                 }
  794.  
  795.                 //mprintf((0,"u,v = %x,%x   x,y=%x,%x",u,v,x,y));
  796.  
  797.                 
  798.                 if (bm->bm_flags & BM_FLAG_RLE)
  799.                     bm = rle_expand_texture(bm);
  800.  
  801.                 if (bm->bm_data[y*bm->bm_w+x] != 255) {        //not trans, thus on effect
  802.                     int vc,sound_num;
  803.  
  804.                     //mprintf((0,"  HIT!\n"));
  805.  
  806.                     if (Newdemo_state == ND_STATE_RECORDING)
  807.                         newdemo_record_effect_blowup( seg-Segments, side, pnt);
  808.  
  809.                     vc = Effects[ec].dest_vclip;
  810.  
  811.                     object_create_explosion( seg-Segments, pnt, Effects[ec].dest_size, vc );
  812.  
  813.                     if ((sound_num = Vclip[vc].sound_num) != -1)
  814.                           digi_link_sound_to_pos( sound_num, seg-Segments, 0, pnt,  0, F1_0 );
  815.  
  816.                     if ((sound_num=Effects[ec].sound_num)!=-1)        //kill sound
  817.                         digi_kill_sound_linked_to_segment(seg-Segments,side,sound_num);
  818.  
  819.                     if (Effects[ec].dest_eclip!=-1 && Effects[Effects[ec].dest_eclip].segnum==-1) {
  820.                         int bm_num;
  821.                         eclip *new_ec;
  822.  
  823.                         new_ec = &Effects[Effects[ec].dest_eclip];
  824.                         bm_num = new_ec->changing_wall_texture;
  825.  
  826.                         mprintf((0,"bm_num = %d\n",bm_num));
  827.  
  828.                         new_ec->time_left = new_ec->vc.frame_time;
  829.                         new_ec->frame_count = 0;
  830.                         new_ec->segnum = seg-Segments;
  831.                         new_ec->sidenum = side;
  832.                         new_ec->flags |= EF_ONE_SHOT;
  833.                         new_ec->dest_bm_num = Effects[ec].dest_bm_num;
  834.  
  835.                         Assert(bm_num!=0 && seg->sides[side].tmap_num2!=0);
  836.                         seg->sides[side].tmap_num2 = bm_num | (tm&0xc000);        //replace with destoyed
  837.  
  838.                     }
  839.                     else {
  840.                         Assert(db!=0 && seg->sides[side].tmap_num2!=0);
  841.                         seg->sides[side].tmap_num2 = db | (tm&0xc000);        //replace with destoyed
  842.                     }
  843.  
  844.                     return 1;        //blew up!
  845.                 }
  846.                 //else
  847.                 //    mprintf((0,"\n"));
  848.  
  849.             }
  850.  
  851.     return 0;        //didn't blow up
  852. }
  853.  
  854. //these gets added to the weapon's values when the weapon hits a volitle wall
  855. #define VOLATILE_WALL_EXPL_STRENGTH i2f(10)
  856. #define VOLATILE_WALL_IMPACT_SIZE    i2f(3)
  857. #define VOLATILE_WALL_DAMAGE_FORCE    i2f(5)
  858. #define VOLATILE_WALL_DAMAGE_RADIUS    i2f(30)
  859.  
  860. // int Show_seg_and_side = 0;
  861.  
  862. void collide_weapon_and_wall( object * weapon, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt)
  863. {
  864.     segment *seg = &Segments[hitseg];
  865.     int blew_up;
  866.     int wall_type;
  867.     int playernum;
  868.  
  869.     #ifndef NDEBUG
  870.     if (keyd_pressed[KEY_LAPOSTRO])
  871.         if (weapon->ctype.laser_info.parent_num == Players[Player_num].objnum)
  872.             if (weapon->id < 4)
  873.                 mprintf((0, "Your laser hit at segment = %i, side = %i\n", hitseg, hitwall));
  874.     #endif
  875.  
  876.     if (weapon->mtype.phys_info.flags & PF_BOUNCE)
  877.         return;
  878.  
  879.     if ((weapon->mtype.phys_info.velocity.x == 0) && (weapon->mtype.phys_info.velocity.y == 0) && (weapon->mtype.phys_info.velocity.z == 0)) {
  880.         Int3();    //    Contact Matt: This is impossible.  A weapon with 0 velocity hit a wall, which doesn't move.
  881.         return;
  882.     }
  883.  
  884.     blew_up = check_effect_blowup(seg,hitwall,hitpt);
  885.  
  886.     //if ((seg->sides[hitwall].tmap_num2==0) && (TmapInfo[seg->sides[hitwall].tmap_num].flags & TMI_VOLATILE)) {
  887.  
  888.     if (Objects[weapon->ctype.laser_info.parent_num].type == OBJ_PLAYER)
  889.         playernum = Objects[weapon->ctype.laser_info.parent_num].id;
  890.     else
  891.         playernum = -1;        //not a player
  892.  
  893.     wall_type = wall_hit_process( seg, hitwall, weapon->shields, playernum, weapon );
  894.  
  895.     // Wall is volatile if either tmap 1 or 2 is volatile
  896.     if ((TmapInfo[seg->sides[hitwall].tmap_num].flags & TMI_VOLATILE) || (seg->sides[hitwall].tmap_num2 && (TmapInfo[seg->sides[hitwall].tmap_num2&0x3fff].flags & TMI_VOLATILE))) {
  897.         weapon_info *wi = &Weapon_info[weapon->id];
  898.  
  899.         //we've hit a volatile wall
  900.  
  901.         digi_link_sound_to_pos( SOUND_VOLATILE_WALL_HIT,hitseg, 0, hitpt, 0, F1_0 );
  902.  
  903.         object_create_badass_explosion( weapon, hitseg, hitpt, 
  904.             wi->impact_size + VOLATILE_WALL_IMPACT_SIZE,
  905.             VCLIP_VOLATILE_WALL_HIT,
  906.             wi->strength[Difficulty_level]/4+VOLATILE_WALL_EXPL_STRENGTH,    //    diminished by mk on 12/08/94, i was doing 70 damage hitting lava on lvl 1.
  907.             wi->damage_radius+VOLATILE_WALL_DAMAGE_RADIUS,
  908.             wi->strength[Difficulty_level]/2+VOLATILE_WALL_DAMAGE_FORCE,
  909.             weapon->ctype.laser_info.parent_num );
  910.  
  911.     }
  912.     else {
  913.  
  914.         //if it's not the player's weapon, or it is the player's and there
  915.         //is no wall, and no blowing up monitor, then play sound
  916.         if ((weapon->ctype.laser_info.parent_type != OBJ_PLAYER) ||    ((seg->sides[hitwall].wall_num == -1 || wall_type==WHP_NOT_SPECIAL) && !blew_up))
  917.             if ((Weapon_info[weapon->id].wall_hit_sound > -1 ) && (!(weapon->flags & OF_SILENT)))
  918.                 digi_link_sound_to_pos( Weapon_info[weapon->id].wall_hit_sound,weapon->segnum, 0, &weapon->pos, 0, F1_0 );
  919.         
  920.         if ( Weapon_info[weapon->id].wall_hit_vclip > -1 )    {
  921.             if ( Weapon_info[weapon->id].damage_radius )
  922.                 explode_badass_weapon(weapon);
  923.             else
  924.                 object_create_explosion( weapon->segnum, &weapon->pos, Weapon_info[weapon->id].impact_size, Weapon_info[weapon->id].wall_hit_vclip );
  925.         }
  926.     }
  927.  
  928.     if ( weapon->ctype.laser_info.parent_type== OBJ_PLAYER )    {
  929.  
  930.         if (!(weapon->flags & OF_SILENT) && (weapon->ctype.laser_info.parent_num == Players[Player_num].objnum))
  931.             create_awareness_event(weapon, PA_WEAPON_WALL_COLLISION);            // object "weapon" can attract attention to player
  932.     
  933. //        if (weapon->id != FLARE_ID) {
  934. //    We now allow flares to open doors.
  935.         {
  936.             if (weapon->id != FLARE_ID)
  937.                 weapon->flags |= OF_SHOULD_BE_DEAD;
  938.  
  939.             if (!(weapon->flags & OF_SILENT)) {
  940.                 switch (wall_type) {
  941.  
  942.                     case WHP_NOT_SPECIAL:
  943.                         //should be handled above
  944. //                        digi_link_sound_to_pos( Weapon_info[weapon->id].wall_hit_sound, weapon->segnum, 0, &weapon->pos, 0, F1_0 );
  945.                         break;
  946.  
  947.                     case WHP_NO_KEY:
  948.                         //play special hit door sound (if/when we get it)
  949.                         digi_link_sound_to_pos( SOUND_WEAPON_HIT_DOOR, weapon->segnum, 0, &weapon->pos, 0, F1_0 );
  950.                         break;
  951.  
  952.                     case WHP_BLASTABLE:
  953.                         //play special blastable wall sound (if/when we get it)
  954.                         digi_link_sound_to_pos( SOUND_WEAPON_HIT_BLASTABLE, weapon->segnum, 0, &weapon->pos, 0, F1_0 );
  955.                         break;
  956.  
  957.                     case WHP_DOOR:
  958.                         //don't play anything, since door open sound will play
  959.                         break;
  960.                 }
  961.             } // else
  962.                 //mprintf((0, "Weapon %i hits wall, but has silent bit set.\n", weapon-Objects));
  963.         } // else {
  964.             //    if (weapon->lifeleft <= 0)
  965.             //    weapon->flags |= OF_SHOULD_BE_DEAD;
  966.         // }
  967.  
  968.     } else {
  969.         // This is a robot's laser
  970.         weapon->flags |= OF_SHOULD_BE_DEAD;
  971.     }
  972.  
  973.     return;
  974. }
  975.  
  976. //##void collide_camera_and_wall( object * camera, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt)    {
  977. //##    return;
  978. //##}
  979.  
  980. //##void collide_powerup_and_wall( object * powerup, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt)    {
  981. //##    return;
  982. //##}
  983.  
  984. void collide_debris_and_wall( object * debris, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt)    {    
  985.     explode_object(debris,0);
  986.     return;
  987. }
  988.  
  989. //##void collide_fireball_and_fireball( object * fireball1, object * fireball2, vms_vector *collision_point ) {
  990. //##    return; 
  991. //##}
  992.  
  993. //##void collide_fireball_and_robot( object * fireball, object * robot, vms_vector *collision_point ) {
  994. //##    return; 
  995. //##}
  996.  
  997. //##void collide_fireball_and_hostage( object * fireball, object * hostage, vms_vector *collision_point ) {
  998. //##    return; 
  999. //##}
  1000.  
  1001. //##void collide_fireball_and_player( object * fireball, object * player, vms_vector *collision_point ) {
  1002. //##    return; 
  1003. //##}
  1004.  
  1005. //##void collide_fireball_and_weapon( object * fireball, object * weapon, vms_vector *collision_point ) { 
  1006. //##    //weapon->flags |= OF_SHOULD_BE_DEAD;
  1007. //##    return; 
  1008. //##}
  1009.  
  1010. //##void collide_fireball_and_camera( object * fireball, object * camera, vms_vector *collision_point ) { 
  1011. //##    return; 
  1012. //##}
  1013.  
  1014. //##void collide_fireball_and_powerup( object * fireball, object * powerup, vms_vector *collision_point ) { 
  1015. //##    return; 
  1016. //##}
  1017.  
  1018. //##void collide_fireball_and_debris( object * fireball, object * debris, vms_vector *collision_point ) { 
  1019. //##    return; 
  1020. //##}
  1021.  
  1022. //    -------------------------------------------------------------------------------------------------------------------
  1023. void collide_robot_and_robot( object * robot1, object * robot2, vms_vector *collision_point ) { 
  1024. //    mprintf((0, "Coll: [%2i %4i %4i %4i] [%2i %4i %4i %4i] at [%4i %4i %4i]", 
  1025. //        robot1-Objects, f2i(robot1->pos.x), f2i(robot1->pos.y), f2i(robot1->pos.z),
  1026. //        robot2-Objects, f2i(robot2->pos.x), f2i(robot2->pos.y), f2i(robot2->pos.z),
  1027. //        f2i(collision_point->x), f2i(collision_point->y), f2i(collision_point->z)));
  1028.  
  1029.     bump_two_objects(robot1, robot2, 1);
  1030.     return; 
  1031. }
  1032.  
  1033. void collide_robot_and_controlcen( object * obj1, object * obj2, vms_vector *collision_point )
  1034. {
  1035.  
  1036.     if (obj1->type == OBJ_ROBOT) {
  1037.         vms_vector    hitvec;
  1038.         vm_vec_normalize_quick(vm_vec_sub(&hitvec, &obj2->pos, &obj1->pos));
  1039.         bump_one_object(obj1, &hitvec, 0);
  1040.     } else {
  1041.         vms_vector    hitvec;
  1042.         vm_vec_normalize_quick(vm_vec_sub(&hitvec, &obj1->pos, &obj2->pos));
  1043.         bump_one_object(obj2, &hitvec, 0);
  1044.     }
  1045.  
  1046. }
  1047.  
  1048. //##void collide_robot_and_hostage( object * robot, object * hostage, vms_vector *collision_point ) { 
  1049. //##    return; 
  1050. //##}
  1051.  
  1052. void collide_robot_and_player( object * robot, object * player, vms_vector *collision_point ) { 
  1053.     if (player->id == Player_num) {
  1054.         create_awareness_event(player, PA_PLAYER_COLLISION);            // object robot can attract attention to player
  1055.         do_ai_robot_hit_attack(robot, player, collision_point);
  1056.         do_ai_robot_hit(robot, PA_WEAPON_ROBOT_COLLISION);
  1057.     } 
  1058. #ifdef NETWORK
  1059.     else
  1060.         multi_robot_request_change(robot, player->id);
  1061. #endif
  1062.  
  1063.     digi_link_sound_to_pos( SOUND_ROBOT_HIT_PLAYER, player->segnum, 0, collision_point, 0, F1_0 );
  1064.     bump_two_objects(robot, player, 1);
  1065.     return; 
  1066. }
  1067.  
  1068. // Provide a way for network message to instantly destroy the control center
  1069. // without awarding points or anything.
  1070.  
  1071. //    if controlcen == NULL, that means don't do the explosion because the control center
  1072. //    was actually in another object.
  1073. void net_destroy_controlcen(object *controlcen)
  1074. {
  1075.     if (Fuelcen_control_center_destroyed != 1) {
  1076.         int i;
  1077.  
  1078.         do_controlcen_destroyed_stuff(controlcen);
  1079.  
  1080.         if ((controlcen != NULL) && !(controlcen->flags&(OF_EXPLODING|OF_DESTROYED))) {
  1081.             digi_link_sound_to_pos( SOUND_CONTROL_CENTER_DESTROYED, controlcen->segnum, 0, &controlcen->pos, 0, F1_0 );
  1082.             explode_object(controlcen,0);
  1083.         }
  1084.     }
  1085.  
  1086. }
  1087.  
  1088. //    -----------------------------------------------------------------------------
  1089. void apply_damage_to_controlcen(object *controlcen, fix damage, short who)
  1090. {
  1091.     int    whotype;
  1092.  
  1093.     //    Only allow a player to damage the control center.
  1094.  
  1095.     if ((who < 0) || (who > Highest_object_index))
  1096.         return;
  1097.  
  1098.     whotype = Objects[who].type;
  1099.     if (whotype != OBJ_PLAYER) {
  1100.         mprintf((0, "Damage to control center by object of type %i prevented by MK!\n", whotype));
  1101.         return;
  1102.     }
  1103.  
  1104.     #ifdef NETWORK
  1105.     if ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP) && (Players[Player_num].time_level < Netgame.control_invul_time))
  1106.     {
  1107.         if (Objects[who].id == Player_num) {
  1108.             int secs = f2i(Netgame.control_invul_time-Players[Player_num].time_level) % 60;
  1109.             int mins = f2i(Netgame.control_invul_time-Players[Player_num].time_level) / 60;
  1110.             HUD_init_message("%s %d:%02d.", TXT_CNTRLCEN_INVUL, mins, secs);
  1111.         }
  1112.         return;
  1113.     }
  1114.     #endif
  1115.  
  1116.     if (Objects[who].id == Player_num) {
  1117.         Control_center_been_hit = 1;
  1118.         ai_do_cloak_stuff();
  1119.     }
  1120.  
  1121.     if ( controlcen->shields >= 0 )
  1122.         controlcen->shields -= damage;
  1123.  
  1124.     if ( (controlcen->shields < 0) && !(controlcen->flags&(OF_EXPLODING|OF_DESTROYED)) ) {
  1125.         int i;
  1126.  
  1127.         do_controlcen_destroyed_stuff(controlcen);
  1128.  
  1129.         #ifdef NETWORK
  1130.         if (Game_mode & GM_MULTI) {
  1131.             if (who == Players[Player_num].objnum)
  1132.                 add_points_to_score(CONTROL_CEN_SCORE);
  1133.             multi_send_destroy_controlcen((ushort)(controlcen-Objects), Objects[who].id );
  1134.         }
  1135.         #endif
  1136.  
  1137.         if (!(Game_mode & GM_MULTI))
  1138.             add_points_to_score(CONTROL_CEN_SCORE);
  1139.  
  1140.         digi_link_sound_to_pos( SOUND_CONTROL_CENTER_DESTROYED, controlcen->segnum, 0, &controlcen->pos, 0, F1_0 );
  1141.  
  1142.         explode_object(controlcen,0);
  1143.     }
  1144. }
  1145.  
  1146. void collide_player_and_controlcen( object * controlcen, object * player, vms_vector *collision_point )
  1147.     if (player->id == Player_num) {
  1148.         Control_center_been_hit = 1;
  1149.         ai_do_cloak_stuff();                //    In case player cloaked, make control center know where he is.
  1150.     }
  1151.  
  1152.     digi_link_sound_to_pos( SOUND_ROBOT_HIT_PLAYER, player->segnum, 0, collision_point, 0, F1_0 );
  1153.     bump_two_objects(controlcen, player, 1);
  1154.  
  1155.     return; 
  1156. }
  1157.  
  1158. //    If a persistent weapon and other object is not a weapon, weaken it, else kill it.
  1159. //    If both objects are weapons, weaken the weapon.
  1160. void maybe_kill_weapon(object *weapon, object *other_obj)
  1161. {
  1162.     if (weapon->id == PROXIMITY_ID) {
  1163.         weapon->flags |= OF_SHOULD_BE_DEAD;
  1164.         return;
  1165.     }
  1166.  
  1167.     if ((weapon->mtype.phys_info.flags & PF_PERSISTENT) || (other_obj->type == OBJ_WEAPON)) {
  1168.         //    Weapons do a lot of damage to weapons, other objects do much less.
  1169.         if (!(weapon->mtype.phys_info.flags & PF_PERSISTENT)) {
  1170.             if (other_obj->type == OBJ_WEAPON)
  1171.                 weapon->shields -= other_obj->shields/2;
  1172.             else
  1173.                 weapon->shields -= other_obj->shields/4;
  1174.  
  1175.             if (weapon->shields <= 0) {
  1176.                 weapon->shields = 0;
  1177.                 weapon->flags |= OF_SHOULD_BE_DEAD;
  1178.             }
  1179.         }
  1180.     } else
  1181.         weapon->flags |= OF_SHOULD_BE_DEAD;
  1182. }
  1183.  
  1184. void collide_weapon_and_controlcen( object * weapon, object *controlcen, vms_vector *collision_point  )
  1185. {
  1186.  
  1187.     if (weapon->ctype.laser_info.parent_type == OBJ_PLAYER) {
  1188.         fix    damage = weapon->shields;
  1189.  
  1190.         if (Objects[weapon->ctype.laser_info.parent_num].id == Player_num)
  1191.             Control_center_been_hit = 1;
  1192.  
  1193.         if ( Weapon_info[weapon->id].damage_radius )
  1194.             explode_badass_weapon(weapon);
  1195.         else
  1196.             object_create_explosion( controlcen->segnum, collision_point, ((controlcen->size/3)*3)/4, VCLIP_SMALL_EXPLOSION );
  1197.  
  1198.         digi_link_sound_to_pos( SOUND_CONTROL_CENTER_HIT, controlcen->segnum, 0, collision_point, 0, F1_0 );
  1199.  
  1200.         damage = fixmul(damage, weapon->ctype.laser_info.multiplier);
  1201.  
  1202.         apply_damage_to_controlcen(controlcen, damage, weapon->ctype.laser_info.parent_num);
  1203.  
  1204.         maybe_kill_weapon(weapon,controlcen);
  1205.     } else {    //    If robot weapon hits control center, blow it up, make it go away, but do no damage to control center.
  1206.         object_create_explosion( controlcen->segnum, collision_point, ((controlcen->size/3)*3)/4, VCLIP_SMALL_EXPLOSION );
  1207.         maybe_kill_weapon(weapon,controlcen);
  1208.     }
  1209.  
  1210. }
  1211.  
  1212. void collide_weapon_and_clutter( object * weapon, object *clutter, vms_vector *collision_point  )    {
  1213.     short exp_vclip = VCLIP_SMALL_EXPLOSION;
  1214.  
  1215.     if ( clutter->shields >= 0 )
  1216.         clutter->shields -= weapon->shields;
  1217.  
  1218.     digi_link_sound_to_pos( SOUND_LASER_HIT_CLUTTER, weapon->segnum, 0, collision_point, 0, F1_0 );
  1219.  
  1220.     object_create_explosion( clutter->segnum, collision_point, ((clutter->size/3)*3)/4, exp_vclip );
  1221.  
  1222.     if ( (clutter->shields < 0) && !(clutter->flags&(OF_EXPLODING|OF_DESTROYED)))
  1223.         explode_object(clutter,STANDARD_EXPL_DELAY);
  1224.  
  1225.     maybe_kill_weapon(weapon,clutter);
  1226. }
  1227.  
  1228. //--mk, 121094 -- extern void spin_robot(object *robot, vms_vector *collision_point);
  1229.  
  1230. //    ------------------------------------------------------------------------------------------------------
  1231. //    Return 1 if robot died, else return 0
  1232. int apply_damage_to_robot(object *robot, fix damage, int killer_objnum)
  1233. {
  1234.     if ( robot->flags&OF_EXPLODING) return 0;
  1235.  
  1236.     if (robot->shields < 0 ) return 0;    //robot already dead...
  1237.  
  1238. //    if (robot->control_type == CT_REMOTE)
  1239. //        return 0; // Can't damange a robot controlled by another player
  1240.  
  1241.     if (Robot_info[robot->id].boss_flag)
  1242.         Boss_been_hit = 1;
  1243.  
  1244.     robot->shields -= damage;
  1245.  
  1246.     if (robot->shields < 0) {
  1247.  
  1248. #ifndef SHAREWARE
  1249. #ifdef NETWORK
  1250.         if (Game_mode & GM_MULTI) {
  1251.             if (multi_explode_robot_sub(robot-Objects, killer_objnum))
  1252.             {
  1253.                 multi_send_robot_explode(robot-Objects, killer_objnum);
  1254.                 return 1;
  1255.             }
  1256.             else
  1257.                 return 0;
  1258.         }
  1259. #endif
  1260. #endif
  1261.  
  1262.         Players[Player_num].num_kills_level++;
  1263.         Players[Player_num].num_kills_total++;
  1264.  
  1265.         if (Robot_info[robot->id].boss_flag) {
  1266.             start_boss_death_sequence(robot);    //do_controlcen_destroyed_stuff(NULL);
  1267.         } else
  1268.             explode_object(robot,STANDARD_EXPL_DELAY);
  1269.         return 1;
  1270.     } else
  1271.         return 0;
  1272. }
  1273.  
  1274. //    ------------------------------------------------------------------------------------------------------
  1275. void collide_robot_and_weapon( object * robot, object * weapon, vms_vector *collision_point )
  1276.  
  1277.     if (Robot_info[robot->id].boss_flag)
  1278.         Boss_hit_this_frame = 1;
  1279.  
  1280.     if ( Ugly_robot_cheat == 0xBADa55 )    {
  1281.         robot->rtype.pobj_info.tmap_override = Ugly_robot_texture % NumTextures;
  1282.     }
  1283.  
  1284.     //    If a persistent weapon hit robot most recently, quick abort, else we cream the same robot many times,
  1285.     //    depending on frame rate.
  1286.     if (weapon->mtype.phys_info.flags & PF_PERSISTENT) {
  1287.         if (weapon->ctype.laser_info.last_hitobj == robot-Objects)
  1288.             return;
  1289.         else
  1290.             weapon->ctype.laser_info.last_hitobj = robot-Objects;
  1291.  
  1292.         // mprintf((0, "weapon #%i with power %i hits robot #%i.\n", weapon - Objects, f2i(weapon->shields), robot - Objects));
  1293.     }
  1294.  
  1295. //    if (weapon->ctype.laser_info.multiplier)
  1296. //        mprintf((0, "Weapon #%3i hit object %3i in frame %4i: multiplier = %7.3f, power = %i\n", weapon-Objects, robot-Objects, FrameCount, f2fl(weapon->ctype.laser_info.multiplier), f2i(weapon->shields)));
  1297.  
  1298. //mprintf((0, "weapon #%i hits robot #%i.\n", weapon - Objects, robot - Objects));
  1299.  
  1300.     if (weapon->ctype.laser_info.parent_signature == robot->signature)
  1301.         return;
  1302.  
  1303.     if ( Weapon_info[weapon->id].damage_radius )
  1304.         explode_badass_weapon(weapon);
  1305.  
  1306.     if ( (weapon->ctype.laser_info.parent_type==OBJ_PLAYER) && !(robot->flags & OF_EXPLODING) )    {    
  1307.         object *expl_obj=NULL;
  1308.  
  1309.         if (weapon->ctype.laser_info.parent_num == Players[Player_num].objnum) {
  1310.             create_awareness_event(weapon, PA_WEAPON_ROBOT_COLLISION);            // object "weapon" can attract attention to player
  1311.             do_ai_robot_hit(robot, PA_WEAPON_ROBOT_COLLISION);
  1312.         } 
  1313. #ifdef NETWORK
  1314.         else
  1315.             multi_robot_request_change(robot, Objects[weapon->ctype.laser_info.parent_num].id);
  1316. #endif
  1317.  
  1318. //--mk, 121094 --         spin_robot(robot, collision_point);
  1319.  
  1320.         if ( Robot_info[robot->id].exp1_vclip_num > -1 )
  1321.             expl_obj = object_create_explosion( weapon->segnum, collision_point, (robot->size/2*3)/4, Robot_info[robot->id].exp1_vclip_num );
  1322. //NOT_USED        else if ( Weapon_info[weapon->id].robot_hit_vclip > -1 )
  1323. //NOT_USED            expl_obj = object_create_explosion( weapon->segnum, collision_point, Weapon_info[weapon->id].impact_size, Weapon_info[weapon->id].robot_hit_vclip );
  1324.  
  1325.         if (expl_obj)
  1326.             obj_attach(robot,expl_obj);
  1327.  
  1328.         if ( Robot_info[robot->id].exp1_sound_num > -1 )
  1329.             digi_link_sound_to_pos( Robot_info[robot->id].exp1_sound_num, robot->segnum, 0, collision_point, 0, F1_0 );
  1330.  
  1331.         if (!(weapon->flags & OF_HARMLESS)) {
  1332.             fix    damage = weapon->shields;
  1333.  
  1334.             damage = fixmul(damage, weapon->ctype.laser_info.multiplier);
  1335.  
  1336.             if (! apply_damage_to_robot(robot, damage, weapon->ctype.laser_info.parent_num))
  1337.                 bump_two_objects(robot, weapon, 0);        //only bump if not dead. no damage from bump
  1338.             else if (weapon->ctype.laser_info.parent_signature == ConsoleObject->signature)
  1339.                 add_points_to_score(Robot_info[robot->id].score_value);
  1340.         }
  1341.  
  1342.     }
  1343.  
  1344.     maybe_kill_weapon(weapon,robot);
  1345.  
  1346.     return; 
  1347. }
  1348.  
  1349. //##void collide_robot_and_camera( object * robot, object * camera, vms_vector *collision_point ) { 
  1350. //##    return; 
  1351. //##}
  1352.  
  1353. //##void collide_robot_and_powerup( object * robot, object * powerup, vms_vector *collision_point ) { 
  1354. //##    return; 
  1355. //##}
  1356.  
  1357. //##void collide_robot_and_debris( object * robot, object * debris, vms_vector *collision_point ) { 
  1358. //##    return; 
  1359. //##}
  1360.  
  1361. //##void collide_hostage_and_hostage( object * hostage1, object * hostage2, vms_vector *collision_point ) { 
  1362. //##    return; 
  1363. //##}
  1364.  
  1365. void collide_hostage_and_player( object * hostage, object * player, vms_vector *collision_point ) { 
  1366.     // Give player points, etc.
  1367.     if ( player == ConsoleObject )    {
  1368.         add_points_to_score(HOSTAGE_SCORE);
  1369.  
  1370.         // Do effect
  1371.         hostage_rescue(hostage->id);
  1372.  
  1373.         // Remove the hostage object.
  1374.         hostage->flags |= OF_SHOULD_BE_DEAD;
  1375.  
  1376.         #ifdef NETWORK    
  1377.         if (Game_mode & GM_MULTI)
  1378.             multi_send_remobj(hostage-Objects);
  1379.         #endif
  1380.     }
  1381.     return; 
  1382. }
  1383.  
  1384. //--unused-- void collide_hostage_and_weapon( object * hostage, object * weapon, vms_vector *collision_point )
  1385. //--unused-- { 
  1386. //--unused--     //    Cannot kill hostages, as per Matt's edict!
  1387. //--unused--     //    (A fine edict, but in contradiction to the milestone: "Robots attack hostages.")
  1388. //--unused--     hostage->shields -= weapon->shields/2;
  1389. //--unused-- 
  1390. //--unused--     create_awareness_event(weapon, PA_WEAPON_ROBOT_COLLISION);            // object "weapon" can attract attention to player
  1391. //--unused-- 
  1392. //--unused--     //PLAY_SOUND_3D( SOUND_HOSTAGE_KILLED, collision_point, hostage->segnum );
  1393. //--unused--     digi_link_sound_to_pos( SOUND_HOSTAGE_KILLED, hostage->segnum , 0, collision_point, 0, F1_0 );
  1394. //--unused-- 
  1395. //--unused-- 
  1396. //--unused--     if (hostage->shields <= 0) {
  1397. //--unused--         explode_object(hostage,0);
  1398. //--unused--         hostage->flags |= OF_SHOULD_BE_DEAD;
  1399. //--unused--     }
  1400. //--unused-- 
  1401. //--unused--     if ( Weapon_info[weapon->id].damage_radius )
  1402. //--unused--         explode_badass_weapon(weapon);
  1403. //--unused-- 
  1404. //--unused--     maybe_kill_weapon(weapon,hostage);
  1405. //--unused-- 
  1406. //--unused-- }
  1407.  
  1408. //##void collide_hostage_and_camera( object * hostage, object * camera, vms_vector *collision_point ) { 
  1409. //##    return; 
  1410. //##}
  1411.  
  1412. //##void collide_hostage_and_powerup( object * hostage, object * powerup, vms_vector *collision_point ) { 
  1413. //##    return; 
  1414. //##}
  1415.  
  1416. //##void collide_hostage_and_debris( object * hostage, object * debris, vms_vector *collision_point ) { 
  1417. //##    return; 
  1418. //##}
  1419.  
  1420. void collide_player_and_player( object * player1, object * player2, vms_vector *collision_point ) { 
  1421.     digi_link_sound_to_pos( SOUND_ROBOT_HIT_PLAYER, player1->segnum, 0, collision_point, 0, F1_0 );
  1422.     bump_two_objects(player1, player2, 1);
  1423.     return;
  1424. }
  1425.  
  1426. int maybe_drop_primary_weapon_egg(object *player, int weapon_flag, int powerup_num)
  1427. {
  1428.     if (Players[player->id].primary_weapon_flags & weapon_flag)
  1429.         return call_object_create_egg(player, 1, OBJ_POWERUP, powerup_num);
  1430.     else
  1431.         return -1;
  1432. }
  1433.  
  1434. void maybe_drop_secondary_weapon_egg(object *player, int weapon_flag, int powerup_num, int count)
  1435. {
  1436.     if (Players[player->id].secondary_weapon_flags & weapon_flag) {
  1437.         int    i, max_count;
  1438.  
  1439.         max_count = min(count, 3);
  1440.         for (i=0; i<max_count; i++)
  1441.             call_object_create_egg(player, 1, OBJ_POWERUP, powerup_num);
  1442.     }
  1443. }
  1444.  
  1445. void drop_player_eggs(object *player)
  1446. {
  1447. //    mprintf((0, "In drop_player_eggs...\n"));
  1448.  
  1449.     if ((player->type == OBJ_PLAYER) || (player->type == OBJ_GHOST)) {
  1450.         int    num_missiles = 1;
  1451.         int    pnum = player->id;
  1452.         int    objnum;
  1453.  
  1454.         // Seed the random number generator so in net play the eggs will always
  1455.         // drop the same way
  1456.         #ifdef NETWORK
  1457.         if (Game_mode & GM_MULTI) 
  1458.         {
  1459.             Net_create_loc = 0;
  1460.             srand(5483L);
  1461.         }
  1462.         #endif
  1463.  
  1464.         //    If the player dies and he has powerful lasers, create the powerups here.
  1465.  
  1466.         if (Players[pnum].laser_level >= 1)
  1467.             call_object_create_egg(player, (Players[pnum].laser_level), OBJ_POWERUP, POW_LASER);
  1468.  
  1469.         //    Drop quad laser if appropos
  1470.         if (Players[pnum].flags & PLAYER_FLAGS_QUAD_LASERS)
  1471.             call_object_create_egg(player, 1, OBJ_POWERUP, POW_QUAD_FIRE);
  1472.  
  1473.         if (Players[pnum].flags & PLAYER_FLAGS_CLOAKED)
  1474.             call_object_create_egg(player, 1, OBJ_POWERUP, POW_CLOAK);
  1475.  
  1476.         //    Drop the primary weapons
  1477.         objnum = maybe_drop_primary_weapon_egg(player, HAS_VULCAN_FLAG, POW_VULCAN_WEAPON);
  1478.         if (objnum!=-1)
  1479.             Objects[objnum].ctype.powerup_info.count = Players[pnum].primary_ammo[VULCAN_INDEX];
  1480.  
  1481.         maybe_drop_primary_weapon_egg(player, HAS_SPREADFIRE_FLAG, POW_SPREADFIRE_WEAPON);
  1482.         maybe_drop_primary_weapon_egg(player, HAS_PLASMA_FLAG, POW_PLASMA_WEAPON);
  1483.         maybe_drop_primary_weapon_egg(player, HAS_FUSION_FLAG, POW_FUSION_WEAPON);
  1484.  
  1485.         //    Drop the secondary weapons
  1486.         //    Note, proximity weapon only comes in packets of 4.  So drop n/2, but a max of 3 (handled inside maybe_drop..)  Make sense?
  1487.         maybe_drop_secondary_weapon_egg(player, HAS_PROXIMITY_FLAG, POW_PROXIMITY_WEAPON, (Players[player->id].secondary_ammo[PROXIMITY_INDEX]+2)/4);
  1488.         maybe_drop_secondary_weapon_egg(player, HAS_SMART_FLAG, POW_SMARTBOMB_WEAPON, Players[player->id].secondary_ammo[SMART_INDEX]);
  1489.         maybe_drop_secondary_weapon_egg(player, HAS_MEGA_FLAG, POW_MEGA_WEAPON, Players[player->id].secondary_ammo[MEGA_INDEX]);
  1490.  
  1491.         num_missiles = Players[pnum].secondary_ammo[HOMING_INDEX];
  1492.         if (num_missiles > 6)
  1493.             num_missiles = 6;
  1494.         call_object_create_egg(player, num_missiles/4, OBJ_POWERUP, POW_HOMING_AMMO_4);
  1495.         call_object_create_egg(player, num_missiles%4, OBJ_POWERUP, POW_HOMING_AMMO_1);
  1496.  
  1497.         //    If player has vulcan ammo, but no vulcan cannon, drop the ammo.
  1498.         if (!(Players[player->id].primary_weapon_flags & HAS_VULCAN_FLAG)) {
  1499.             int    amount = Players[player->id].primary_ammo[VULCAN_INDEX];
  1500.             if (amount > 200) {
  1501.                 mprintf((0, "Surprising amount of vulcan ammo: %i bullets.\n", amount));
  1502.                 amount = 200;
  1503.             }
  1504.             while (amount > 0) {
  1505.                 call_object_create_egg(player, 1, OBJ_POWERUP, POW_VULCAN_AMMO);
  1506.                 amount -= VULCAN_AMMO_AMOUNT;
  1507.             }
  1508.         }
  1509.  
  1510.         //    Drop the player's missiles.
  1511.         num_missiles = Players[pnum].secondary_ammo[CONCUSSION_INDEX];
  1512.         if (num_missiles > 4)
  1513.             num_missiles = 4;
  1514.  
  1515.         call_object_create_egg(player, num_missiles/4, OBJ_POWERUP, POW_MISSILE_4);
  1516.         call_object_create_egg(player, num_missiles%4, OBJ_POWERUP, POW_MISSILE_1);
  1517.  
  1518.         //    Always drop a shield and energy powerup.
  1519.         if (Game_mode & GM_MULTI) {
  1520.             call_object_create_egg(player, 1, OBJ_POWERUP, POW_SHIELD_BOOST);
  1521.             call_object_create_egg(player, 1, OBJ_POWERUP, POW_ENERGY);
  1522.         }
  1523.  
  1524. //--        //    Drop all the keys.
  1525. //--        if (Players[Player_num].flags & PLAYER_FLAGS_BLUE_KEY) {
  1526. //--            player->contains_count = 1;
  1527. //--            player->contains_type = OBJ_POWERUP;
  1528. //--            player->contains_id = POW_KEY_BLUE;
  1529. //--            object_create_egg(player);
  1530. //--        }
  1531. //--        if (Players[Player_num].flags & PLAYER_FLAGS_RED_KEY) {
  1532. //--            player->contains_count = 1;
  1533. //--            player->contains_type = OBJ_POWERUP;
  1534. //--            player->contains_id = POW_KEY_RED;
  1535. //--            object_create_egg(player);
  1536. //--        }
  1537. //--        if (Players[Player_num].flags & PLAYER_FLAGS_GOLD_KEY) {
  1538. //--            player->contains_count = 1;
  1539. //--            player->contains_type = OBJ_POWERUP;
  1540. //--            player->contains_id = POW_KEY_GOLD;
  1541. //--            object_create_egg(player);
  1542. //--        }
  1543.     }
  1544. }
  1545.  
  1546. void apply_damage_to_player(object *player, object *killer, fix damage)
  1547. {
  1548.     if (Player_is_dead)
  1549.         return;
  1550.  
  1551.     if (Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE)
  1552.         return;
  1553.  
  1554.     if (Endlevel_sequence)
  1555.         return;
  1556.  
  1557.     //for the player, the 'real' shields are maintained in the Players[]
  1558.     //array.  The shields value in the player's object are, I think, not
  1559.     //used anywhere.  This routine, however, sets the objects shields to
  1560.     //be a mirror of the value in the Player structure. 
  1561.  
  1562.     if (player->id == Player_num) {        //is this the local player?
  1563.  
  1564.         if (Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE) {
  1565.  
  1566.             //invincible, so just do blue flash
  1567.  
  1568.             PALETTE_FLASH_ADD(0,0,f2i(damage)*4);    //flash blue
  1569.  
  1570.         } 
  1571.         else {        //take damage, do red flash
  1572.  
  1573.             Players[Player_num].shields -= damage;
  1574.  
  1575.             PALETTE_FLASH_ADD(f2i(damage)*4,-f2i(damage/2),-f2i(damage/2));    //flash red
  1576.  
  1577.         }
  1578.  
  1579.         if (Players[Player_num].shields < 0)    {
  1580.  
  1581.               Players[Player_num].killer_objnum = killer-Objects;
  1582.             
  1583. //            if ( killer && (killer->type == OBJ_PLAYER))
  1584. //                Players[Player_num].killer_objnum = killer-Objects;
  1585.  
  1586.             player->flags |= OF_SHOULD_BE_DEAD;
  1587.  
  1588.         }
  1589.  
  1590.         player->shields = Players[Player_num].shields;        //mirror
  1591.  
  1592.     }
  1593. }
  1594.  
  1595. void collide_player_and_weapon( object * player, object * weapon, vms_vector *collision_point )
  1596. {
  1597.     fix        damage = weapon->shields;
  1598.     object * killer=NULL;
  1599.  
  1600.     damage = fixmul(damage, weapon->ctype.laser_info.multiplier);
  1601.  
  1602.     if (weapon->mtype.phys_info.flags & PF_PERSISTENT)
  1603.         if (weapon->ctype.laser_info.last_hitobj == player-Objects)
  1604.             return;
  1605.         else
  1606.             weapon->ctype.laser_info.last_hitobj = player-Objects;
  1607.  
  1608.     if (player->id == Player_num)
  1609.     {
  1610.         if (!(Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE))
  1611.         {
  1612.             digi_link_sound_to_pos( SOUND_PLAYER_GOT_HIT, player->segnum, 0, collision_point, 0, F1_0 );
  1613.             #ifdef NETWORK
  1614.             if (Game_mode & GM_MULTI)
  1615.                 multi_send_play_sound(SOUND_PLAYER_GOT_HIT, F1_0);
  1616.             #endif
  1617.         }
  1618.         else
  1619.         {
  1620.             digi_link_sound_to_pos( SOUND_WEAPON_HIT_DOOR, player->segnum, 0, collision_point, 0, F1_0);
  1621.             #ifdef NETWORK
  1622.             if (Game_mode & GM_MULTI)
  1623.                 multi_send_play_sound(SOUND_WEAPON_HIT_DOOR, F1_0);
  1624.             #endif
  1625.         }
  1626.     }
  1627.  
  1628.     object_create_explosion( player->segnum, collision_point, i2f(10)/2, VCLIP_PLAYER_HIT );
  1629.     if ( Weapon_info[weapon->id].damage_radius )
  1630.         explode_badass_weapon(weapon);
  1631.  
  1632.     maybe_kill_weapon(weapon,player);
  1633.  
  1634.     bump_two_objects(player, weapon, 0);    //no damage from bump
  1635.  
  1636.     if ( !Weapon_info[weapon->id].damage_radius ) {
  1637.         if ( weapon->ctype.laser_info.parent_num > -1 )
  1638.             killer = &Objects[weapon->ctype.laser_info.parent_num];
  1639.  
  1640. //        if (weapon->id == SMART_HOMING_ID)
  1641. //            damage /= 4;
  1642.  
  1643.         if (!(weapon->flags & OF_HARMLESS))
  1644.             apply_damage_to_player( player, killer, damage);
  1645.     }
  1646.  
  1647.     //    Robots become aware of you if you get hit.
  1648.     ai_do_cloak_stuff();
  1649.  
  1650.     return; 
  1651. }
  1652.  
  1653. //    Nasty robots are the ones that attack you by running into you and doing lots of damage.
  1654. void collide_player_and_nasty_robot( object * player, object * robot, vms_vector *collision_point )
  1655. {
  1656.     digi_link_sound_to_pos( Robot_info[robot->id].claw_sound, player->segnum, 0, collision_point, 0, F1_0 );
  1657.  
  1658.     object_create_explosion( player->segnum, collision_point, i2f(10)/2, VCLIP_PLAYER_HIT );
  1659.  
  1660.     bump_two_objects(player, robot, 0);    //no damage from bump
  1661.  
  1662.     apply_damage_to_player( player, robot, F1_0*(Difficulty_level+1));
  1663.  
  1664.     return; 
  1665. }
  1666.  
  1667. void collide_player_and_materialization_center(object *objp)
  1668. {
  1669.     int    side;
  1670.     vms_vector    exit_dir;
  1671.     segment    *segp = &Segments[objp->segnum];
  1672.  
  1673.     digi_link_sound_to_pos(SOUND_PLAYER_GOT_HIT, objp->segnum, 0, &objp->pos, 0, F1_0);
  1674. //    digi_play_sample( SOUND_PLAYER_GOT_HIT, F1_0 );
  1675.  
  1676.     object_create_explosion( objp->segnum, &objp->pos, i2f(10)/2, VCLIP_PLAYER_HIT );
  1677.  
  1678.     if (objp->id != Player_num)
  1679.         return;
  1680.  
  1681.     for (side=0; side<MAX_SIDES_PER_SEGMENT; side++)
  1682.         if (WALL_IS_DOORWAY(segp, side) & WID_FLY_FLAG) {
  1683.             vms_vector    exit_point, rand_vec;
  1684.  
  1685.             compute_center_point_on_side(&exit_point, segp, side);
  1686.             vm_vec_sub(&exit_dir, &exit_point, &objp->pos);
  1687.             vm_vec_normalize_quick(&exit_dir);
  1688.             make_random_vector(&rand_vec);
  1689.             rand_vec.x /= 4;    rand_vec.y /= 4;    rand_vec.z /= 4;
  1690.             vm_vec_add2(&exit_dir, &rand_vec);
  1691.             vm_vec_normalize_quick(&exit_dir);
  1692.         }
  1693.  
  1694.     bump_one_object(objp, &exit_dir, 64*F1_0);
  1695.  
  1696.     apply_damage_to_player( objp, NULL, 4*F1_0);
  1697.  
  1698.     return; 
  1699.  
  1700. }
  1701.  
  1702. void collide_robot_and_materialization_center(object *objp)
  1703. {
  1704.     int    side;
  1705.     vms_vector    exit_dir;
  1706.     segment *segp=&Segments[objp->segnum];
  1707.  
  1708.     digi_link_sound_to_pos(SOUND_ROBOT_HIT, objp->segnum, 0, &objp->pos, 0, F1_0);
  1709. //    digi_play_sample( SOUND_ROBOT_HIT, F1_0 );
  1710.  
  1711.     if ( Robot_info[objp->id].exp1_vclip_num > -1 )
  1712.         object_create_explosion( objp->segnum, &objp->pos, (objp->size/2*3)/4, Robot_info[objp->id].exp1_vclip_num );
  1713.  
  1714.     for (side=0; side<MAX_SIDES_PER_SEGMENT; side++)
  1715.         if (WALL_IS_DOORWAY(segp, side) & WID_FLY_FLAG) {
  1716.             vms_vector    exit_point;
  1717.  
  1718.             compute_center_point_on_side(&exit_point, segp, side);
  1719.             vm_vec_sub(&exit_dir, &exit_point, &objp->pos);
  1720.             vm_vec_normalize_quick(&exit_dir);
  1721.         }
  1722.  
  1723.     bump_one_object(objp, &exit_dir, 8*F1_0);
  1724.  
  1725.     apply_damage_to_robot( objp, F1_0, -1);
  1726.  
  1727.     return; 
  1728.  
  1729. }
  1730.  
  1731. //##void collide_player_and_camera( object * player, object * camera, vms_vector *collision_point ) { 
  1732. //##    return; 
  1733. //##}
  1734.  
  1735. extern int Network_got_powerup; // HACK!!!
  1736.  
  1737. void collide_player_and_powerup( object * player, object * powerup, vms_vector *collision_point ) { 
  1738.     if (!Endlevel_sequence && !Player_is_dead && (player->id == Player_num )) {
  1739.         int powerup_used;
  1740.  
  1741.         powerup_used = do_powerup(powerup);
  1742.         
  1743.         if (powerup_used)    {
  1744.             powerup->flags |= OF_SHOULD_BE_DEAD;
  1745.             #ifdef NETWORK
  1746.             if (Game_mode & GM_MULTI)
  1747.                 multi_send_remobj(powerup-Objects);
  1748.             #endif
  1749.         }
  1750.     }
  1751. #ifndef SHAREWARE
  1752.     else if ((Game_mode & GM_MULTI_COOP) && (player->id != Player_num))
  1753.     {
  1754.         switch (powerup->id) {
  1755.             case POW_KEY_BLUE:    
  1756.                 Players[player->id].flags |= PLAYER_FLAGS_BLUE_KEY;
  1757.                 break;
  1758.             case POW_KEY_RED:    
  1759.                 Players[player->id].flags |= PLAYER_FLAGS_RED_KEY;
  1760.                 break;
  1761.             case POW_KEY_GOLD:    
  1762.                 Players[player->id].flags |= PLAYER_FLAGS_GOLD_KEY;
  1763.                 break;
  1764.             default:
  1765.                 break;
  1766.         }
  1767.     }
  1768. #endif
  1769.     return; 
  1770. }
  1771.  
  1772. //##void collide_player_and_debris( object * player, object * debris, vms_vector *collision_point ) { 
  1773. //##    return; 
  1774. //##}
  1775.  
  1776. void collide_player_and_clutter( object * player, object * clutter, vms_vector *collision_point ) { 
  1777.     digi_link_sound_to_pos( SOUND_ROBOT_HIT_PLAYER, player->segnum, 0, collision_point, 0, F1_0 );
  1778.     bump_two_objects(clutter, player, 1);
  1779.     return; 
  1780. }
  1781.  
  1782. //    See if weapon1 creates a badass explosion.  If so, create the explosion
  1783. //    Return true if weapon does proximity (as opposed to only contact) damage when it explodes.
  1784. int maybe_detonate_weapon(object *weapon1, object *weapon2, vms_vector *collision_point)
  1785. {
  1786.     if ( Weapon_info[weapon1->id].damage_radius ) {
  1787.         fix    dist;
  1788.  
  1789.         dist = vm_vec_dist_quick(&weapon1->pos, &weapon2->pos);
  1790.         if (dist < F1_0*5) {
  1791.             maybe_kill_weapon(weapon1,weapon2);
  1792.             if (weapon1->flags & OF_SHOULD_BE_DEAD) {
  1793.                 explode_badass_weapon(weapon1);
  1794.                 digi_link_sound_to_pos( Weapon_info[weapon1->id].robot_hit_sound, weapon1->segnum , 0, collision_point, 0, F1_0 );
  1795.             }
  1796.             return 1;
  1797.         } else {
  1798.             weapon1->lifeleft = min(dist/64, F1_0);
  1799.             return 1;
  1800.         }
  1801.     } else
  1802.         return 0;
  1803. }
  1804.  
  1805. void collide_weapon_and_weapon( object * weapon1, object * weapon2, vms_vector *collision_point )
  1806.     if ((Weapon_info[weapon1->id].destroyable) || (Weapon_info[weapon2->id].destroyable)) {
  1807.  
  1808.         //    Bug reported by Adam Q. Pletcher on September 9, 1994, smart bomb homing missiles were toasting each other.
  1809.         if ((weapon1->id == weapon2->id) && (weapon1->ctype.laser_info.parent_num == weapon2->ctype.laser_info.parent_num))
  1810.             return;
  1811.  
  1812.         if (Weapon_info[weapon1->id].destroyable)
  1813.             if (maybe_detonate_weapon(weapon1, weapon2, collision_point))
  1814.                 maybe_kill_weapon(weapon2,weapon1);
  1815.  
  1816.         if (Weapon_info[weapon2->id].destroyable)
  1817.             if (maybe_detonate_weapon(weapon2, weapon1, collision_point))
  1818.                 maybe_kill_weapon(weapon1,weapon2);
  1819.  
  1820.     }
  1821.  
  1822. }
  1823.  
  1824. //##void collide_weapon_and_camera( object * weapon, object * camera, vms_vector *collision_point ) { 
  1825. //##    return; 
  1826. //##}
  1827.  
  1828. //##void collide_weapon_and_powerup( object * weapon, object * powerup, vms_vector *collision_point ) { 
  1829. //##    return; 
  1830. //##}
  1831.  
  1832. void collide_weapon_and_debris( object * weapon, object * debris, vms_vector *collision_point ) { 
  1833.  
  1834.     if ( (weapon->ctype.laser_info.parent_type==OBJ_PLAYER) && !(debris->flags & OF_EXPLODING) )    {    
  1835.         digi_link_sound_to_pos( SOUND_ROBOT_HIT, weapon->segnum , 0, collision_point, 0, F1_0 );
  1836.  
  1837.         explode_object(debris,0);
  1838.         if ( Weapon_info[weapon->id].damage_radius )
  1839.             explode_badass_weapon(weapon);
  1840.         maybe_kill_weapon(weapon,debris);
  1841.         weapon->flags |= OF_SHOULD_BE_DEAD;
  1842.     }
  1843.     return; 
  1844. }
  1845.  
  1846. //##void collide_camera_and_camera( object * camera1, object * camera2, vms_vector *collision_point ) { 
  1847. //##    return; 
  1848. //##}
  1849.  
  1850. //##void collide_camera_and_powerup( object * camera, object * powerup, vms_vector *collision_point ) { 
  1851. //##    return; 
  1852. //##}
  1853.  
  1854. //##void collide_camera_and_debris( object * camera, object * debris, vms_vector *collision_point ) { 
  1855. //##    return; 
  1856. //##}
  1857.  
  1858. //##void collide_powerup_and_powerup( object * powerup1, object * powerup2, vms_vector *collision_point ) { 
  1859. //##    return; 
  1860. //##}
  1861.  
  1862. //##void collide_powerup_and_debris( object * powerup, object * debris, vms_vector *collision_point ) { 
  1863. //##    return; 
  1864. //##}
  1865.  
  1866. //##void collide_debris_and_debris( object * debris1, object * debris2, vms_vector *collision_point ) { 
  1867. //##    return; 
  1868. //##}
  1869.  
  1870. #pragma on (unreferenced)                    // No warnings for unreferenced vars, eh?
  1871.  
  1872. #define COLLISION_OF(a,b) (((a)<<8) + (b))
  1873.  
  1874. #define DO_COLLISION(type1,type2,collision_function)                        \
  1875.     case COLLISION_OF( (type1), (type2) ):                                        \
  1876.         (collision_function)( (A), (B), collision_point );                 \
  1877.         break;                                                                            \
  1878.     case COLLISION_OF( (type2), (type1) ):                                        \
  1879.         (collision_function)( (B), (A), collision_point );                    \
  1880.         break;
  1881.  
  1882. #define DO_SAME_COLLISION(type1,type2,collision_function)                \
  1883.     case COLLISION_OF( (type1), (type1) ):                                        \
  1884.         (collision_function)( (A), (B), collision_point );                 \
  1885.         break;                                                                            
  1886.  
  1887. //these next two macros define a case that does nothing
  1888. #define NO_COLLISION(type1,type2,collision_function)                        \
  1889.     case COLLISION_OF( (type1), (type2) ):                                        \
  1890.         break;                                                                            \
  1891.     case COLLISION_OF( (type2), (type1) ):                                        \
  1892.         break;
  1893.  
  1894. #define NO_SAME_COLLISION(type1,type2,collision_function)                \
  1895.     case COLLISION_OF( (type1), (type1) ):                                        \
  1896.         break;                                                                            
  1897.  
  1898. #define IGNORE_COLLISION(type1,type2,collision_function)                    \
  1899.     case COLLISION_OF( (type1), (type2) ):                                        \
  1900.         break;                                                                            \
  1901.     case COLLISION_OF( (type2), (type1) ):                                        \
  1902.         break;
  1903.  
  1904. #define ERROR_COLLISION(type1,type2,collision_function)                    \
  1905.     case COLLISION_OF( (type1), (type2) ):                                        \
  1906.         Error( "Error in collision type!" );                                    \
  1907.         break;                                                                            \
  1908.     case COLLISION_OF( (type2), (type1) ):                                        \
  1909.         Error( "Error in collision type!" );                                    \
  1910.         break;
  1911.  
  1912. void collide_two_objects( object * A, object * B, vms_vector *collision_point )
  1913. {
  1914.     int collision_type;    
  1915.         
  1916.     collision_type = COLLISION_OF(A->type,B->type);
  1917.  
  1918.     //mprintf( (0, "Object %d of type %d collided with object %d of type %d\n", A-Objects,A->type, B-Objects, B->type ));
  1919.  
  1920.     switch( collision_type )    {
  1921.     NO_SAME_COLLISION( OBJ_FIREBALL, OBJ_FIREBALL,   collide_fireball_and_fireball )
  1922.     DO_SAME_COLLISION( OBJ_ROBOT, OBJ_ROBOT, collide_robot_and_robot )
  1923.     NO_SAME_COLLISION( OBJ_HOSTAGE, OBJ_HOSTAGE,  collide_hostage_and_hostage )
  1924.     DO_SAME_COLLISION( OBJ_PLAYER, OBJ_PLAYER,  collide_player_and_player )
  1925.     DO_SAME_COLLISION( OBJ_WEAPON, OBJ_WEAPON,  collide_weapon_and_weapon )
  1926.     NO_SAME_COLLISION( OBJ_CAMERA, OBJ_CAMERA, collide_camera_and_camera )
  1927.     NO_SAME_COLLISION( OBJ_POWERUP, OBJ_POWERUP,  collide_powerup_and_powerup )
  1928.     NO_SAME_COLLISION( OBJ_DEBRIS, OBJ_DEBRIS,  collide_debris_and_debris )
  1929.     NO_COLLISION( OBJ_FIREBALL, OBJ_ROBOT,   collide_fireball_and_robot )
  1930.     NO_COLLISION( OBJ_FIREBALL, OBJ_HOSTAGE, collide_fireball_and_hostage )
  1931.     NO_COLLISION( OBJ_FIREBALL, OBJ_PLAYER,  collide_fireball_and_player )
  1932.     NO_COLLISION( OBJ_FIREBALL, OBJ_WEAPON,  collide_fireball_and_weapon )
  1933.     NO_COLLISION( OBJ_FIREBALL, OBJ_CAMERA,  collide_fireball_and_camera )
  1934.     NO_COLLISION( OBJ_FIREBALL, OBJ_POWERUP, collide_fireball_and_powerup )
  1935.     NO_COLLISION( OBJ_FIREBALL, OBJ_DEBRIS,  collide_fireball_and_debris )
  1936.     NO_COLLISION( OBJ_ROBOT, OBJ_HOSTAGE, collide_robot_and_hostage )
  1937.     DO_COLLISION( OBJ_ROBOT, OBJ_PLAYER,  collide_robot_and_player )
  1938.     DO_COLLISION( OBJ_ROBOT, OBJ_WEAPON,  collide_robot_and_weapon )
  1939.     NO_COLLISION( OBJ_ROBOT, OBJ_CAMERA,  collide_robot_and_camera )
  1940.     NO_COLLISION( OBJ_ROBOT, OBJ_POWERUP, collide_robot_and_powerup )
  1941.     NO_COLLISION( OBJ_ROBOT, OBJ_DEBRIS,  collide_robot_and_debris )
  1942.     DO_COLLISION( OBJ_HOSTAGE, OBJ_PLAYER,  collide_hostage_and_player )
  1943.     NO_COLLISION( OBJ_HOSTAGE, OBJ_WEAPON,  collide_hostage_and_weapon )
  1944.     NO_COLLISION( OBJ_HOSTAGE, OBJ_CAMERA,  collide_hostage_and_camera )
  1945.     NO_COLLISION( OBJ_HOSTAGE, OBJ_POWERUP, collide_hostage_and_powerup )
  1946.     NO_COLLISION( OBJ_HOSTAGE, OBJ_DEBRIS,  collide_hostage_and_debris )
  1947.     DO_COLLISION( OBJ_PLAYER, OBJ_WEAPON,  collide_player_and_weapon )
  1948.     NO_COLLISION( OBJ_PLAYER, OBJ_CAMERA,  collide_player_and_camera )
  1949.     DO_COLLISION( OBJ_PLAYER, OBJ_POWERUP, collide_player_and_powerup )
  1950.     NO_COLLISION( OBJ_PLAYER, OBJ_DEBRIS,  collide_player_and_debris )
  1951.     DO_COLLISION( OBJ_PLAYER, OBJ_CNTRLCEN, collide_player_and_controlcen )
  1952.     DO_COLLISION( OBJ_PLAYER, OBJ_CLUTTER, collide_player_and_clutter )
  1953.     NO_COLLISION( OBJ_WEAPON, OBJ_CAMERA,  collide_weapon_and_camera )
  1954.     NO_COLLISION( OBJ_WEAPON, OBJ_POWERUP, collide_weapon_and_powerup )
  1955.     DO_COLLISION( OBJ_WEAPON, OBJ_DEBRIS,  collide_weapon_and_debris )
  1956.     NO_COLLISION( OBJ_CAMERA, OBJ_POWERUP, collide_camera_and_powerup )
  1957.     NO_COLLISION( OBJ_CAMERA, OBJ_DEBRIS,  collide_camera_and_debris )
  1958.     NO_COLLISION( OBJ_POWERUP, OBJ_DEBRIS,  collide_powerup_and_debris )
  1959.     DO_COLLISION( OBJ_WEAPON, OBJ_CNTRLCEN, collide_weapon_and_controlcen )
  1960.     DO_COLLISION( OBJ_ROBOT, OBJ_CNTRLCEN, collide_robot_and_controlcen )
  1961.     DO_COLLISION( OBJ_WEAPON, OBJ_CLUTTER, collide_weapon_and_clutter )
  1962.     default:
  1963.         Int3();    //Error( "Unhandled collision_type in collide.c!\n" );
  1964.     }
  1965. }
  1966.  
  1967. #define ENABLE_COLLISION(type1,type2)                    \
  1968.     CollisionResult[type1][type2] = RESULT_CHECK;    \
  1969.     CollisionResult[type2][type1] = RESULT_CHECK;
  1970.  
  1971. #define DISABLE_COLLISION(type1,type2)                    \
  1972.     CollisionResult[type1][type2] = RESULT_NOTHING;    \
  1973.     CollisionResult[type2][type1] = RESULT_NOTHING;
  1974.  
  1975. void collide_init()    {
  1976.     int i, j;
  1977.  
  1978.     for (i=0; i < MAX_OBJECT_TYPES; i++ )
  1979.         for (j=0; j < MAX_OBJECT_TYPES; j++ )
  1980.             CollisionResult[i][j] = RESULT_NOTHING;
  1981.  
  1982.     ENABLE_COLLISION( OBJ_WALL, OBJ_ROBOT );
  1983.     ENABLE_COLLISION( OBJ_WALL, OBJ_WEAPON );
  1984.     ENABLE_COLLISION( OBJ_WALL, OBJ_PLAYER  );
  1985.     DISABLE_COLLISION( OBJ_FIREBALL, OBJ_FIREBALL );
  1986.  
  1987.     ENABLE_COLLISION( OBJ_ROBOT, OBJ_ROBOT );
  1988. //    DISABLE_COLLISION( OBJ_ROBOT, OBJ_ROBOT );    //    ALERT: WARNING: HACK: MK = RESPONSIBLE! TESTING!!
  1989.  
  1990.     DISABLE_COLLISION( OBJ_HOSTAGE, OBJ_HOSTAGE );
  1991.     ENABLE_COLLISION( OBJ_PLAYER, OBJ_PLAYER );
  1992.     ENABLE_COLLISION( OBJ_WEAPON, OBJ_WEAPON );
  1993.     DISABLE_COLLISION( OBJ_CAMERA, OBJ_CAMERA );
  1994.     DISABLE_COLLISION( OBJ_POWERUP, OBJ_POWERUP );
  1995.     DISABLE_COLLISION( OBJ_DEBRIS, OBJ_DEBRIS );
  1996.     DISABLE_COLLISION( OBJ_FIREBALL, OBJ_ROBOT );
  1997.     DISABLE_COLLISION( OBJ_FIREBALL, OBJ_HOSTAGE );
  1998.     DISABLE_COLLISION( OBJ_FIREBALL, OBJ_PLAYER );
  1999.     DISABLE_COLLISION( OBJ_FIREBALL, OBJ_WEAPON );
  2000.     DISABLE_COLLISION( OBJ_FIREBALL, OBJ_CAMERA );
  2001.     DISABLE_COLLISION( OBJ_FIREBALL, OBJ_POWERUP );
  2002.     DISABLE_COLLISION( OBJ_FIREBALL, OBJ_DEBRIS );
  2003.     DISABLE_COLLISION( OBJ_ROBOT, OBJ_HOSTAGE );
  2004.     ENABLE_COLLISION( OBJ_ROBOT, OBJ_PLAYER );
  2005.     ENABLE_COLLISION( OBJ_ROBOT, OBJ_WEAPON );
  2006.     DISABLE_COLLISION( OBJ_ROBOT, OBJ_CAMERA );
  2007.     DISABLE_COLLISION( OBJ_ROBOT, OBJ_POWERUP );
  2008.     DISABLE_COLLISION( OBJ_ROBOT, OBJ_DEBRIS );
  2009.     ENABLE_COLLISION( OBJ_HOSTAGE, OBJ_PLAYER );
  2010.     ENABLE_COLLISION( OBJ_HOSTAGE, OBJ_WEAPON );
  2011.     DISABLE_COLLISION( OBJ_HOSTAGE, OBJ_CAMERA );
  2012.     DISABLE_COLLISION( OBJ_HOSTAGE, OBJ_POWERUP );
  2013.     DISABLE_COLLISION( OBJ_HOSTAGE, OBJ_DEBRIS );
  2014.     ENABLE_COLLISION( OBJ_PLAYER, OBJ_WEAPON );
  2015.     DISABLE_COLLISION( OBJ_PLAYER, OBJ_CAMERA );
  2016.     ENABLE_COLLISION( OBJ_PLAYER, OBJ_POWERUP );
  2017.     DISABLE_COLLISION( OBJ_PLAYER, OBJ_DEBRIS );
  2018.     DISABLE_COLLISION( OBJ_WEAPON, OBJ_CAMERA );
  2019.     DISABLE_COLLISION( OBJ_WEAPON, OBJ_POWERUP );
  2020.     ENABLE_COLLISION( OBJ_WEAPON, OBJ_DEBRIS );
  2021.     DISABLE_COLLISION( OBJ_CAMERA, OBJ_POWERUP );
  2022.     DISABLE_COLLISION( OBJ_CAMERA, OBJ_DEBRIS );
  2023.     DISABLE_COLLISION( OBJ_POWERUP, OBJ_DEBRIS );
  2024.     ENABLE_COLLISION( OBJ_POWERUP, OBJ_WALL );
  2025.     ENABLE_COLLISION( OBJ_WEAPON, OBJ_CNTRLCEN )
  2026.     ENABLE_COLLISION( OBJ_WEAPON, OBJ_CLUTTER )
  2027.     ENABLE_COLLISION( OBJ_PLAYER, OBJ_CNTRLCEN )
  2028.     ENABLE_COLLISION( OBJ_ROBOT, OBJ_CNTRLCEN )
  2029.     ENABLE_COLLISION( OBJ_PLAYER, OBJ_CLUTTER )
  2030.     
  2031.  
  2032. }
  2033.  
  2034. void collide_object_with_wall( object * A, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt )
  2035. {
  2036.  
  2037.     switch( A->type )    {
  2038.     case OBJ_NONE:
  2039.         Error( "A object of type NONE hit a wall!\n");
  2040.         break;
  2041.     case OBJ_PLAYER:        collide_player_and_wall(A,hitspeed,hitseg,hitwall,hitpt); break;
  2042.     case OBJ_WEAPON:        collide_weapon_and_wall(A,hitspeed,hitseg,hitwall,hitpt); break;
  2043.     case OBJ_DEBRIS:        collide_debris_and_wall(A,hitspeed,hitseg,hitwall,hitpt); break;
  2044.  
  2045.     case OBJ_FIREBALL:    break;        //collide_fireball_and_wall(A,hitspeed,hitseg,hitwall,hitpt); 
  2046.     case OBJ_ROBOT:        collide_robot_and_wall(A,hitspeed,hitseg,hitwall,hitpt); break;
  2047.     case OBJ_HOSTAGE:        break;        //collide_hostage_and_wall(A,hitspeed,hitseg,hitwall,hitpt); 
  2048.     case OBJ_CAMERA:        break;        //collide_camera_and_wall(A,hitspeed,hitseg,hitwall,hitpt); 
  2049.     case OBJ_POWERUP:        break;        //collide_powerup_and_wall(A,hitspeed,hitseg,hitwall,hitpt); 
  2050.     case OBJ_GHOST:        break;    //do nothing
  2051.  
  2052.     default:
  2053.         Error( "Unhandled object type hit wall in collide.c\n" );
  2054.     }
  2055. }
  2056.  
  2057.  
  2058.  
  2059. 
  2060.