1 /* $Id: collide.c,v 1.12 2003-03-27 01:23:18 btb Exp $ */
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
17 * Routines to handle collisions
20 * Revision 1.3 1995/11/08 17:15:21 allender
21 * make collide_player_and_weapon play player_hit_sound if
22 * shareware and not my playernum
24 * Revision 1.2 1995/10/31 10:24:37 allender
27 * Revision 1.1 1995/05/16 15:23:34 allender
30 * Revision 2.5 1995/07/26 12:07:46 john
31 * Made code that pages in weapon_info->robot_hit_vclip not
32 * page in unless it is a badass weapon. Took out old functionallity
33 * of using this if no robot exp1_vclip, since all robots have these.
35 * Revision 2.4 1995/03/30 16:36:09 mike
38 * Revision 2.3 1995/03/24 15:11:13 john
39 * Added ugly robot cheat.
41 * Revision 2.2 1995/03/21 14:41:04 john
42 * Ifdef'd out the NETWORK code.
44 * Revision 2.1 1995/03/20 18:16:02 john
45 * Added code to not store the normals in the segment structure.
47 * Revision 2.0 1995/02/27 11:32:20 john
48 * New version 2.0, which has no anonymous unions, builds with
49 * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
51 * Revision 1.289 1995/02/22 13:56:06 allender
52 * remove anonymous unions from object structure
54 * Revision 1.288 1995/02/11 15:52:45 rob
57 * Revision 1.287 1995/02/11 15:04:11 rob
60 * Revision 1.286 1995/02/11 14:25:41 rob
61 * Added invul. controlcen option.
63 * Revision 1.285 1995/02/06 15:53:00 mike
64 * create awareness event for player:wall collision.
66 * Revision 1.284 1995/02/05 23:18:17 matt
67 * Deal with objects (such as fusion blobs) that get created already
68 * poking through a wall
70 * Revision 1.283 1995/02/01 17:51:33 mike
71 * fusion bolt can now toast multiple proximity bombs.
73 * Revision 1.282 1995/02/01 17:29:20 john
76 * Revision 1.281 1995/02/01 15:04:00 rob
77 * Changed sound of weapons hitting invulnerable players.
79 * Revision 1.280 1995/01/31 16:16:35 mike
80 * Separate smart blobs for robot and player.
82 * Revision 1.279 1995/01/29 15:57:10 rob
83 * Fixed another bug with robot_request_change calls.
85 * Revision 1.278 1995/01/28 18:15:06 rob
86 * Fixed a bug in multi_request_robot_change.
88 * Revision 1.277 1995/01/27 15:15:44 rob
89 * Fixing problems with controlcen damage.
91 * Revision 1.276 1995/01/27 15:13:10 mike
92 * comment out mprintf.
94 * Revision 1.275 1995/01/26 22:11:51 mike
95 * Purple chromo-blaster (ie, fusion cannon) spruce up (chromification)
97 * Revision 1.274 1995/01/26 18:57:55 rob
98 * Changed two uses of digi_play_sample to digi_link_sound_to_pos which
101 * Revision 1.273 1995/01/25 23:37:58 mike
102 * make persistent objects not hit player more than once.
103 * Also, make them hit player before degrading them, else they often did 0 damage.
105 * Revision 1.272 1995/01/25 18:23:54 rob
106 * Don't let players pick up powerups in exit tunnel.
108 * Revision 1.271 1995/01/25 13:43:18 rob
109 * Added robot transfer for player collisions.
110 * Removed mprintf from collide.c on Mike's request.
112 * Revision 1.270 1995/01/25 10:24:01 mike
113 * Make sizzle and rock happen in lava even if you're invulnerable.
115 * Revision 1.269 1995/01/22 17:05:33 mike
116 * Call multi_robot_request_change when a robot gets whacked by a player or
117 * player weapon, if player_num != Player_num
119 * Revision 1.268 1995/01/21 21:20:28 matt
122 * Revision 1.267 1995/01/21 18:47:47 rob
123 * Fixed a really dumb bug with player keys.
125 * Revision 1.266 1995/01/21 17:39:30 matt
126 * Cleaned up laser/player hit wall confusions
128 * Revision 1.265 1995/01/19 17:44:42 mike
129 * damage_force removed, that information coming from strength field.
131 * Revision 1.264 1995/01/18 17:12:56 rob
132 * Fixed control stuff for multiplayer.
134 * Revision 1.263 1995/01/18 16:12:33 mike
135 * Make control center aware of a cloaked playerr when he fires.
137 * Revision 1.262 1995/01/17 17:48:42 rob
138 * Added key syncing for coop players.
140 * Revision 1.261 1995/01/16 19:30:28 rob
141 * Fixed an assert error in fireball.c
143 * Revision 1.260 1995/01/16 19:23:51 mike
144 * Say Boss_been_hit if he been hit so he gates appropriately.
146 * Revision 1.259 1995/01/16 11:55:16 mike
147 * make enemies become aware of player if he damages control center.
149 * Revision 1.258 1995/01/15 16:42:00 rob
150 * Fixed problem with robot bumping damage.
152 * Revision 1.257 1995/01/14 19:16:36 john
153 * First version of new bitmap paging code.
155 * Revision 1.256 1995/01/03 17:58:37 rob
156 * Fixed scoring problems.
158 * Revision 1.255 1994/12/29 12:41:11 rob
159 * Tweaking robot exploding in coop.
161 * Revision 1.254 1994/12/28 10:37:59 rob
162 * Fixed ifdef of multibot stuff.
164 * Revision 1.253 1994/12/21 19:03:14 rob
165 * Fixing score accounting for multiplayer robots
167 * Revision 1.252 1994/12/21 17:36:31 rob
168 * Fix hostage pickup problem in network.
169 * tweaking robot powerup drops.
171 * Revision 1.251 1994/12/19 20:32:34 rob
172 * Remove awareness events from player collisions and lasers that are not the console player.
174 * Revision 1.250 1994/12/19 20:01:22 rob
175 * Added multibot.h include.
177 * Revision 1.249 1994/12/19 16:36:41 rob
178 * Patches damaging of multiplayer robots.
180 * Revision 1.248 1994/12/14 21:15:18 rob
181 * play lava hiss across network.
183 * Revision 1.247 1994/12/14 17:09:09 matt
184 * Fixed problem with no sound when lasers hit closed walls, like grates.
186 * Revision 1.246 1994/12/14 09:51:49 mike
187 * make any weapon cause proximity bomb detonation.
189 * Revision 1.245 1994/12/13 12:55:25 mike
190 * change number of proximity bomb powerups which get dropped.
192 * Revision 1.244 1994/12/12 17:17:53 mike
193 * make boss cloak/teleport when get hit, make quad laser 3/4 as powerful.
195 * Revision 1.243 1994/12/12 12:07:51 rob
196 * Don't take damage if we're in endlevel sequence.
198 * Revision 1.242 1994/12/11 23:44:52 mike
199 * less phys_apply_rot() at higher skill levels.
201 * Revision 1.241 1994/12/11 12:37:02 mike
202 * remove stupid robot spinning code. it was really stupid. (actually, call here, code in ai.c).
204 * Revision 1.240 1994/12/10 16:44:51 matt
205 * Added debugging code to track down door that turns into rock
207 * Revision 1.239 1994/12/09 14:59:19 matt
208 * Added system to attach a fireball to another object for rendering purposes,
209 * so the fireball always renders on top of (after) the object.
211 * Revision 1.238 1994/12/09 09:57:02 mike
212 * Don't allow robots or their weapons to pass through control center.
214 * Revision 1.237 1994/12/08 15:46:03 mike
215 * better robot behavior.
217 * Revision 1.236 1994/12/08 12:32:56 mike
218 * make boss dying more interesting.
220 * Revision 1.235 1994/12/07 22:49:15 mike
221 * tweak rotation due to collision.
223 * Revision 1.234 1994/12/07 16:44:50 mike
224 * make bump sound if supposed to, even if not taking damage.
226 * Revision 1.233 1994/12/07 12:55:08 mike
227 * tweak rotvel applied from collisions.
229 * Revision 1.232 1994/12/05 19:30:48 matt
230 * Fixed horrible segment over-dereferencing
232 * Revision 1.231 1994/12/05 00:32:15 mike
233 * do rotvel on badass and bump collisions.
235 * Revision 1.230 1994/12/03 12:49:22 mike
236 * don't play bonk sound when you collide with a volatile wall (like lava).
238 * Revision 1.229 1994/12/02 16:51:09 mike
239 * make lava sound only happen at 4 Hz.
241 * Revision 1.228 1994/11/30 23:55:27 rob
242 * Fixed a bug where a laser hitting a wall was making 2 sounds.
244 * Revision 1.227 1994/11/30 20:11:00 rob
245 * Fixed # of dropped laser powerups.
247 * Revision 1.226 1994/11/30 19:19:03 rob
248 * Transmit collission sounds for net games.
250 * Revision 1.225 1994/11/30 16:33:01 mike
253 * Revision 1.224 1994/11/30 15:44:17 mike
254 * /2 on boss smart children damage.
256 * Revision 1.223 1994/11/30 14:03:03 mike
257 * hook for claw sounds
259 * Revision 1.222 1994/11/29 20:41:09 matt
260 * Deleted a bunch of commented-out lines
262 * Revision 1.221 1994/11/27 23:15:08 matt
263 * Made changes for new mprintf calling convention
265 * Revision 1.220 1994/11/19 16:11:28 rob
266 * Collision damage with walls or lava is counted as suicides in net games
268 * Revision 1.219 1994/11/19 15:20:41 mike
269 * rip out unused code and data
271 * Revision 1.218 1994/11/17 18:44:27 rob
272 * Added OBJ_GHOST to list of valid player types to create eggs.
274 * Revision 1.217 1994/11/17 14:57:59 mike
275 * moved segment validation functions from editor to main.
277 * Revision 1.216 1994/11/16 23:38:36 mike
278 * new improved boss teleportation behavior.
280 * Revision 1.215 1994/11/16 12:16:29 mike
281 * Enable collisions between robots. A hack in fvi.c only does this for robots which lunge to attack (eg, green guy)
283 * Revision 1.214 1994/11/15 16:51:50 mike
284 * bump player when he hits a volatile wall.
286 * Revision 1.213 1994/11/12 16:38:44 mike
287 * allow flares to open doors.
289 * Revision 1.212 1994/11/10 13:09:19 matt
290 * Added support for new run-length-encoded bitmaps
292 * Revision 1.211 1994/11/09 17:05:43 matt
293 * Fixed problem with volatile walls
295 * Revision 1.210 1994/11/09 12:11:46 mike
296 * only award points if ConsoleObject killed robot.
298 * Revision 1.209 1994/11/09 11:11:03 yuan
299 * Made wall volatile if either tmap_num1 or tmap_num2 is a volatile wall.
301 * Revision 1.208 1994/11/08 12:20:15 mike
302 * moved do_controlcen_destroyed_stuff from here to cntrlcen.c
304 * Revision 1.207 1994/11/02 23:22:08 mike
305 * Make ` (backquote, KEY_LAPOSTRO) tell what wall was hit by laser.
307 * Revision 1.206 1994/11/02 18:03:00 rob
308 * Fix control_center_been_hit logic so it only cares about the local player.
309 * Other players take care of their own control center 'ai'.
311 * Revision 1.205 1994/11/01 19:37:33 rob
312 * Changed the max # of consussion missiles to 4.
313 * (cause they're lame and clutter things up)
315 * Revision 1.204 1994/11/01 18:06:35 john
316 * Tweaked wall banging sound constant.
318 * Revision 1.203 1994/11/01 18:01:40 john
319 * Made wall bang less obnoxious, but volume based.
321 * Revision 1.202 1994/11/01 17:11:05 rob
322 * Changed some stuff in drop_player_eggs.
324 * Revision 1.201 1994/11/01 12:18:23 john
325 * Added sound volume support. Made wall collisions be louder/softer.
327 * Revision 1.200 1994/10/31 13:48:44 rob
328 * Fixed bug in opening doors over network/modem. Added a new message
329 * type to multi.c that communicates door openings across the net.
330 * Changed includes in multi.c and wall.c to accomplish this.
332 * Revision 1.199 1994/10/28 14:42:52 john
333 * Added sound volumes to all sound calls.
335 * Revision 1.198 1994/10/27 16:58:37 allender
336 * added demo recording of monitors blowing up
338 * Revision 1.197 1994/10/26 23:20:52 matt
339 * Tone down flash even more
341 * Revision 1.196 1994/10/26 23:01:50 matt
342 * Toned down red flash when damaged
344 * Revision 1.195 1994/10/26 15:56:29 yuan
345 * Tweaked some palette flashes.
347 * Revision 1.194 1994/10/25 11:32:26 matt
348 * Fixed bugs with vulcan powerups in mutliplayer
350 * Revision 1.193 1994/10/25 10:51:18 matt
351 * Vulcan cannon powerups now contain ammo count
353 * Revision 1.192 1994/10/24 14:14:05 matt
354 * Fixed bug in bump_two_objects()
356 * Revision 1.191 1994/10/23 19:17:04 matt
357 * Fixed bug with "no key" messages
359 * Revision 1.190 1994/10/22 00:08:46 matt
360 * Fixed up problems with bonus & game sequencing
361 * Player doesn't get credit for hostages unless he gets them out alive
363 * Revision 1.189 1994/10/21 20:42:34 mike
364 * Clear number of hostages on board between levels.
366 * Revision 1.188 1994/10/20 15:17:43 mike
367 * control center in boss handling.
369 * Revision 1.187 1994/10/20 10:09:47 mike
370 * Only ever drop 1 shield powerup in multiplayer (as an egg).
372 * Revision 1.186 1994/10/20 09:47:11 mike
373 * Fix bug in dropping vulcan ammo in multiplayer.
374 * Also control center stuff.
376 * Revision 1.185 1994/10/19 15:14:32 john
377 * Took % hits out of player structure, made %kills work properly.
379 * Revision 1.184 1994/10/19 11:33:16 john
380 * Fixed hostage rescued percent.
382 * Revision 1.183 1994/10/19 11:16:49 mike
383 * Don't allow crazy josh to open locked doors.
384 * Don't allow weapons to harm parent.
386 * Revision 1.182 1994/10/18 18:37:01 mike
387 * No more hostage killing. Too much stuff to do to integrate into game.
389 * Revision 1.181 1994/10/18 16:37:35 mike
390 * Debug function for Yuan: Show seg:side when hit by puny laser if Show_seg_and_side != 0.
392 * Revision 1.180 1994/10/18 10:53:17 mike
393 * Support attack type as a property of a robot, not of being == GREEN_GUY.
395 * Revision 1.179 1994/10/17 21:18:36 mike
396 * diminish damage player does to robot due to collision, only took 2-3 hits to kill a josh.
398 * Revision 1.178 1994/10/17 20:30:40 john
399 * Made player_hostages_rescued or whatever count properly.
401 * Revision 1.177 1994/10/16 12:42:56 mike
402 * Trap bogus amount of vulcan ammo dropping.
404 * Revision 1.176 1994/10/15 19:06:51 mike
405 * Drop vulcan ammo if player has it, but no vulcan cannon (when he dies).
407 * Revision 1.175 1994/10/13 15:42:06 mike
408 * Remove afterburner.
410 * Revision 1.174 1994/10/13 11:12:57 mike
411 * Apply damage to robots. I hosed it a couple weeks ago when I made the green guy special.
443 #include "fireball.h"
461 #include "textures.h"
465 #include "cntrlcen.h"
467 #include "endlevel.h"
468 #include "multibot.h"
480 #include "editor/editor.h"
486 #define STANDARD_EXPL_DELAY (f1_0/4)
488 //##void collide_fireball_and_wall(object *fireball,fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt) {
492 // -------------------------------------------------------------------------------------------------------------
493 // The only reason this routine is called (as of 10/12/94) is so Brain guys can open doors.
494 void collide_robot_and_wall( object * robot, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt)
496 ai_local *ailp = &Ai_local_info[robot-Objects];
498 if ((robot->id == ROBOT_BRAIN) || (robot->ctype.ai_info.behavior == AIB_RUN_FROM) || (Robot_info[robot->id].companion == 1) || (robot->ctype.ai_info.behavior == AIB_SNIPE)) {
499 int wall_num = Segments[hitseg].sides[hitwall].wall_num;
500 if (wall_num != -1) {
501 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)) {
502 // -- mprintf((0, "Trying to open door at segment %i, side %i\n", hitseg, hitwall));
503 wall_open_door(&Segments[hitseg], hitwall);
504 // -- Changed from this, 10/19/95, MK: Don't want buddy getting stranded from player
505 //-- } else if ((Robot_info[robot->id].companion == 1) && (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)) {
506 } else if ((Robot_info[robot->id].companion == 1) && (Walls[wall_num].type == WALL_DOOR)) {
507 if ((ailp->mode == AIM_GOTO_PLAYER) || (Escort_special_goal == ESCORT_GOAL_SCRAM)) {
508 if (Walls[wall_num].keys != KEY_NONE) {
509 if (Walls[wall_num].keys & Players[Player_num].flags)
510 wall_open_door(&Segments[hitseg], hitwall);
511 } else if (!(Walls[wall_num].flags & WALL_DOOR_LOCKED))
512 wall_open_door(&Segments[hitseg], hitwall);
514 } else if (Robot_info[robot->id].thief) { // Thief allowed to go through doors to which player has key.
515 if (Walls[wall_num].keys != KEY_NONE)
516 if (Walls[wall_num].keys & Players[Player_num].flags)
517 wall_open_door(&Segments[hitseg], hitwall);
525 //##void collide_hostage_and_wall( object * hostage, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt) {
529 // -------------------------------------------------------------------------------------------------------------
531 int apply_damage_to_clutter(object *clutter, fix damage)
533 if ( clutter->flags&OF_EXPLODING) return 0;
535 if (clutter->shields < 0 ) return 0; //clutter already dead...
537 clutter->shields -= damage;
539 if (clutter->shields < 0) {
540 explode_object(clutter,0);
546 char Monster_mode = 0; // A cheat. Do massive damage when collide.
548 //given the specified force, apply damage from that force to an object
549 void apply_force_damage(object *obj,fix force,object *other_obj)
554 if (obj->flags & (OF_EXPLODING|OF_SHOULD_BE_DEAD))
555 return; //already exploding or dead
557 damage = fixdiv(force,obj->mtype.phys_info.mass) / 8;
559 if ((other_obj->type == OBJ_PLAYER) && Monster_mode)
562 //mprintf((0,"obj %d, damage=%x\n",obj-Objects,damage));
568 if (Robot_info[obj->id].attack_type == 1) {
569 if (other_obj->type == OBJ_WEAPON)
570 result = apply_damage_to_robot(obj,damage/4, other_obj->ctype.laser_info.parent_num);
572 result = apply_damage_to_robot(obj,damage/4, other_obj-Objects);
575 if (other_obj->type == OBJ_WEAPON)
576 result = apply_damage_to_robot(obj,damage/2, other_obj->ctype.laser_info.parent_num);
578 result = apply_damage_to_robot(obj,damage/2, other_obj-Objects);
581 if (result && (other_obj->ctype.laser_info.parent_signature == ConsoleObject->signature))
582 add_points_to_score(Robot_info[obj->id].score_value);
587 // If colliding with a claw type robot, do damage proportional to FrameTime because you can collide with those
588 // bots every frame since they don't move.
589 if ( (other_obj->type == OBJ_ROBOT) && (Robot_info[other_obj->id].attack_type) )
590 damage = fixmul(damage, FrameTime*2);
592 // Make trainee easier.
593 if (Difficulty_level == 0)
596 apply_damage_to_player(obj,other_obj,damage);
601 apply_damage_to_clutter(obj,damage);
606 apply_damage_to_controlcen(obj,damage, other_obj-Objects);
611 break; //weapons don't take damage
620 // -----------------------------------------------------------------------------
621 void bump_this_object(object *objp, object *other_objp, vms_vector *force, int damage_flag)
625 if (! (objp->mtype.phys_info.flags & PF_PERSISTENT))
627 if (objp->type == OBJ_PLAYER) {
629 force2.x = force->x/4;
630 force2.y = force->y/4;
631 force2.z = force->z/4;
632 phys_apply_force(objp,&force2);
633 if (damage_flag && ((other_objp->type != OBJ_ROBOT) || !Robot_info[other_objp->id].companion)) {
634 force_mag = vm_vec_mag_quick(&force2);
635 apply_force_damage(objp, force_mag, other_objp);
637 } else if ((objp->type == OBJ_ROBOT) || (objp->type == OBJ_CLUTTER) || (objp->type == OBJ_CNTRLCEN)) {
638 if (!Robot_info[objp->id].boss_flag) {
640 force2.x = force->x/(4 + Difficulty_level);
641 force2.y = force->y/(4 + Difficulty_level);
642 force2.z = force->z/(4 + Difficulty_level);
644 phys_apply_force(objp, force);
645 phys_apply_rot(objp, &force2);
647 force_mag = vm_vec_mag_quick(force);
648 apply_force_damage(objp, force_mag, other_objp);
655 // -----------------------------------------------------------------------------
656 //deal with two objects bumping into each other. Apply force from collision
657 //to each robot. The flags tells whether the objects should take damage from
659 void bump_two_objects(object *obj0,object *obj1,int damage_flag)
664 if (obj0->movement_type != MT_PHYSICS)
666 else if (obj1->movement_type != MT_PHYSICS)
670 Assert(t->movement_type == MT_PHYSICS);
671 vm_vec_copy_scale(&force,&t->mtype.phys_info.velocity,-t->mtype.phys_info.mass);
672 phys_apply_force(t,&force);
676 vm_vec_sub(&force,&obj0->mtype.phys_info.velocity,&obj1->mtype.phys_info.velocity);
677 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));
679 bump_this_object(obj1, obj0, &force, damage_flag);
680 vm_vec_negate(&force);
681 bump_this_object(obj0, obj1, &force, damage_flag);
685 void bump_one_object(object *obj0, vms_vector *hit_dir, fix damage)
690 vm_vec_scale(&hit_vec, damage);
692 phys_apply_force(obj0,&hit_vec);
696 #define DAMAGE_SCALE 128 // Was 32 before 8:55 am on Thursday, September 15, changed by MK, walls were hurting me more than robots!
697 #define DAMAGE_THRESHOLD (F1_0/3)
698 #define WALL_LOUDNESS_SCALE (20)
700 fix force_force = i2f(50);
702 void collide_player_and_wall( object * playerobj, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt)
705 char ForceFieldHit=0;
706 int tmap_num,tmap_num2;
708 if (playerobj->id != Player_num) // Execute only for local player
711 tmap_num = Segments[hitseg].sides[hitwall].tmap_num;
713 // If this wall does damage, don't make *BONK* sound, we'll be making another sound.
714 if (TmapInfo[tmap_num].damage > 0)
717 if (TmapInfo[tmap_num].flags & TMI_FORCE_FIELD) {
720 PALETTE_FLASH_ADD(0, 0, 60); //flash blue
722 //knock player around
723 force.x = 40*(d_rand() - 16384);
724 force.y = 40*(d_rand() - 16384);
725 force.z = 40*(d_rand() - 16384);
726 phys_apply_rot(playerobj, &force);
730 Tactile_apply_force (&force,&playerobj->orient);
734 digi_link_sound_to_pos( SOUND_FORCEFIELD_BOUNCE_PLAYER, hitseg, 0, hitpt, 0, f1_0 );
736 if (Game_mode & GM_MULTI)
737 multi_send_play_sound(SOUND_FORCEFIELD_BOUNCE_PLAYER, f1_0);
746 force.x = -playerobj->mtype.phys_info.velocity.x;
747 force.y = -playerobj->mtype.phys_info.velocity.y;
748 force.z = -playerobj->mtype.phys_info.velocity.z;
749 Tactile_do_collide(&force, &playerobj->orient);
753 wall_hit_process( &Segments[hitseg], hitwall, 20, playerobj->id, playerobj );
756 // ** Damage from hitting wall **
757 // If the player has less than 10% shields, don't take damage from bump
758 // Note: Does quad damage if hit a force field - JL
759 damage = (hitspeed / DAMAGE_SCALE) * (ForceFieldHit*8 + 1);
761 tmap_num2 = Segments[hitseg].sides[hitwall].tmap_num2;
763 //don't do wall damage and sound if hit lava or water
764 if ((TmapInfo[tmap_num].flags & (TMI_WATER|TMI_VOLATILE)) || (tmap_num2 && (TmapInfo[tmap_num2&0x3fff].flags & (TMI_WATER|TMI_VOLATILE))))
767 if (damage >= DAMAGE_THRESHOLD) {
769 volume = (hitspeed-(DAMAGE_SCALE*DAMAGE_THRESHOLD)) / WALL_LOUDNESS_SCALE ;
771 create_awareness_event(playerobj, PA_WEAPON_WALL_COLLISION);
775 if (volume > 0 && !ForceFieldHit) { // uhhhgly hack
776 digi_link_sound_to_pos( SOUND_PLAYER_HIT_WALL, hitseg, 0, hitpt, 0, volume );
778 if (Game_mode & GM_MULTI)
779 multi_send_play_sound(SOUND_PLAYER_HIT_WALL, volume);
783 if (!(Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE))
784 if ( Players[Player_num].shields > f1_0*10 || ForceFieldHit)
785 apply_damage_to_player( playerobj, playerobj, damage );
787 // -- No point in doing this unless we compute a reasonable hitpt. Currently it is just the player's position. --MK, 01/18/96
788 // -- if (!(TmapInfo[Segments[hitseg].sides[hitwall].tmap_num].flags & TMI_FORCE_FIELD)) {
789 // -- vms_vector hitpt1;
792 // -- vm_vec_avg(&hitpt1, hitpt, &Objects[Players[Player_num].objnum].pos);
793 // -- hitseg1 = find_point_seg(&hitpt1, Objects[Players[Player_num].objnum].segnum);
794 // -- if (hitseg1 != -1)
795 // -- object_create_explosion( hitseg, hitpt, Weapon_info[0].impact_size, Weapon_info[0].wall_hit_vclip );
803 fix Last_volatile_scrape_sound_time = 0;
805 void collide_weapon_and_wall( object * weapon, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt);
806 void collide_debris_and_wall( object * debris, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt);
808 //see if wall is volatile or water
809 //if volatile, cause damage to player
810 //returns 1=lava, 2=water
811 int check_volatile_wall(object *obj,int segnum,int sidenum,vms_vector *hitpt)
813 fix tmap_num,d,water;
815 Assert(obj->type==OBJ_PLAYER);
817 tmap_num = Segments[segnum].sides[sidenum].tmap_num;
819 d = TmapInfo[tmap_num].damage;
820 water = (TmapInfo[tmap_num].flags & TMI_WATER);
822 if (d > 0 || water) {
824 if (obj->id == Player_num) {
827 fix damage = fixmul(d,FrameTime);
829 if (Difficulty_level == 0)
832 if (!(Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE))
833 apply_damage_to_player( obj, obj, damage );
837 Tactile_Xvibrate (50,25);
840 PALETTE_FLASH_ADD(f2i(damage*4), 0, 0); //flash red
843 obj->mtype.phys_info.rotvel.x = (d_rand() - 16384)/2;
844 obj->mtype.phys_info.rotvel.z = (d_rand() - 16384)/2;
852 if (TactileStick && !(FrameCount & 15))
853 Tactile_Xvibrate_clear ();
860 //this gets called when an object is scraping along the wall
861 void scrape_object_on_wall(object *obj, short hitseg, short hitside, vms_vector * hitpt )
867 if (obj->id==Player_num) {
870 //mprintf((0, "Scraped segment #%3i, side #%i\n", hitseg, hitside));
872 if ((type=check_volatile_wall(obj,hitseg,hitside,hitpt))!=0) {
873 vms_vector hit_dir, rand_vec;
875 if ((GameTime > Last_volatile_scrape_sound_time + F1_0/4) || (GameTime < Last_volatile_scrape_sound_time)) {
876 int sound = (type==1)?SOUND_VOLATILE_WALL_HISS:SOUND_SHIP_IN_WATER;
878 Last_volatile_scrape_sound_time = GameTime;
880 digi_link_sound_to_pos( sound, hitseg, 0, hitpt, 0, F1_0 );
882 if (Game_mode & GM_MULTI)
883 multi_send_play_sound(sound, F1_0);
888 get_side_normal(&Segments[hitseg], higside, 0, &hit_dir );
890 hit_dir = Segments[hitseg].sides[hitside].normals[0];
893 make_random_vector(&rand_vec);
894 vm_vec_scale_add2(&hit_dir, &rand_vec, F1_0/8);
895 vm_vec_normalize_quick(&hit_dir);
896 bump_one_object(obj, &hit_dir, F1_0*8);
900 //@@ //what scrape sound
901 //@@ //PLAY_SOUND( SOUND_PLAYER_SCRAPE_WALL );
908 //these two kinds of objects below shouldn't really slide, so
909 //if this scrape routine gets called (which it might if the
910 //object (such as a fusion blob) was created already poking
911 //through the wall) call the collide routine.
914 collide_weapon_and_wall(obj,0,hitseg,hitside,hitpt);
918 collide_debris_and_wall(obj,0,hitseg,hitside,hitpt);
924 //if an effect is hit, and it can blow up, then blow it up
925 //returns true if it blew up
926 int check_effect_blowup(segment *seg,int side,vms_vector *pnt, object *blower, int force_blowup_flag)
932 // If this wall has a trigger and the blower-upper is not the player or the buddy, abort!
936 if (blower->ctype.laser_info.parent_type == OBJ_ROBOT)
937 if (Robot_info[Objects[blower->ctype.laser_info.parent_num].id].companion)
940 if (!(ok_to_blow || (blower->ctype.laser_info.parent_type == OBJ_PLAYER))) {
941 int trigger_num, wall_num;
943 wall_num = seg->sides[side].wall_num;
944 if ( wall_num != -1 ) {
945 trigger_num = Walls[wall_num].trigger;
947 if (trigger_num != -1)
954 if ((tm=seg->sides[side].tmap_num2) != 0) {
956 tmf = tm&0xc000; //tm flags
957 tm &= 0x3fff; //tm without flags
959 //check if it's an animation (monitor) or casts light
960 if ((((ec=TmapInfo[tm].eclip_num)!=-1) && ((db=Effects[ec].dest_bm_num)!=-1 && !(Effects[ec].flags&EF_ONE_SHOT))) || (ec==-1 && (TmapInfo[tm].destroyed!=-1))) {
962 grs_bitmap *bm = &GameBitmaps[Textures[tm].index];
965 PIGGY_PAGE_IN(Textures[tm]);
967 //this can be blown up...did we hit it?
969 if (!force_blowup_flag) {
970 find_hitpoint_uv(&u,&v,NULL,pnt,seg,side,0); //evil: always say face zero
972 x = ((unsigned) f2i(u*bm->bm_w)) % bm->bm_w;
973 y = ((unsigned) f2i(v*bm->bm_h)) % bm->bm_h;
975 switch (tmf) { //adjust for orientation of paste-on
977 case 0x4000: t=y; y=x; x=bm->bm_w-t-1; break;
978 case 0x8000: y=bm->bm_h-y-1; x=bm->bm_w-x-1; break;
979 case 0xc000: t=x; x=y; y=bm->bm_h-t-1; break;
982 //mprintf((0,"u,v = %x,%x x,y=%x,%x",u,v,x,y));
984 if (bm->bm_flags & BM_FLAG_RLE)
985 bm = rle_expand_texture(bm);
988 if (force_blowup_flag || (bm->bm_data[y*bm->bm_w+x] != TRANSPARENCY_COLOR)) { //not trans, thus on effect
994 if ((Game_mode & GM_MULTI) && Netgame.AlwaysLighting)
995 if (!(ec!=-1 && db!=-1 && !(Effects[ec].flags&EF_ONE_SHOT)))
999 //mprintf((0," HIT!\n"));
1001 //note: this must get called before the texture changes,
1002 //because we use the light value of the texture to change
1003 //the static light in the segment
1004 subtract_light(seg-Segments,side);
1006 if (Newdemo_state == ND_STATE_RECORDING)
1007 newdemo_record_effect_blowup( seg-Segments, side, pnt);
1010 dest_size = Effects[ec].dest_size;
1011 vc = Effects[ec].dest_vclip;
1013 dest_size = i2f(20);
1017 object_create_explosion( seg-Segments, pnt, dest_size, vc );
1019 if (ec!=-1 && db!=-1 && !(Effects[ec].flags&EF_ONE_SHOT)) {
1021 if ((sound_num = Vclip[vc].sound_num) != -1)
1022 digi_link_sound_to_pos( sound_num, seg-Segments, 0, pnt, 0, F1_0 );
1024 if ((sound_num=Effects[ec].sound_num)!=-1) //kill sound
1025 digi_kill_sound_linked_to_segment(seg-Segments,side,sound_num);
1027 if (Effects[ec].dest_eclip!=-1 && Effects[Effects[ec].dest_eclip].segnum==-1) {
1031 new_ec = &Effects[Effects[ec].dest_eclip];
1032 bm_num = new_ec->changing_wall_texture;
1034 mprintf((0,"bm_num = %d\n",bm_num));
1036 new_ec->time_left = new_ec->vc.frame_time;
1037 new_ec->frame_count = 0;
1038 new_ec->segnum = seg-Segments;
1039 new_ec->sidenum = side;
1040 new_ec->flags |= EF_ONE_SHOT;
1041 new_ec->dest_bm_num = Effects[ec].dest_bm_num;
1043 Assert(bm_num!=0 && seg->sides[side].tmap_num2!=0);
1044 seg->sides[side].tmap_num2 = bm_num | tmf; //replace with destoyed
1048 Assert(db!=0 && seg->sides[side].tmap_num2!=0);
1049 seg->sides[side].tmap_num2 = db | tmf; //replace with destoyed
1053 seg->sides[side].tmap_num2 = TmapInfo[tm].destroyed | tmf;
1055 //assume this is a light, and play light sound
1056 digi_link_sound_to_pos( SOUND_LIGHT_BLOWNUP, seg-Segments, 0, pnt, 0, F1_0 );
1060 return 1; //blew up!
1065 return 0; //didn't blow up
1068 // Copied from laser.c!
1069 #define MIN_OMEGA_BLOBS 3 // No matter how close the obstruction, at this many blobs created.
1070 #define MIN_OMEGA_DIST (F1_0*3) // At least this distance between blobs, unless doing so would violate MIN_OMEGA_BLOBS
1071 #define DESIRED_OMEGA_DIST (F1_0*5) // This is the desired distance between blobs. For distances > MIN_OMEGA_BLOBS*DESIRED_OMEGA_DIST, but not very large, this will apply.
1072 #define MAX_OMEGA_BLOBS 16 // No matter how far away the obstruction, this is the maximum number of blobs.
1073 #define MAX_OMEGA_DIST (MAX_OMEGA_BLOBS * DESIRED_OMEGA_DIST) // Maximum extent of lightning blobs.
1075 // -------------------------------------------------
1076 // Return true if ok to do Omega damage.
1077 int ok_to_do_omega_damage(object *weapon)
1079 int parent_sig = weapon->ctype.laser_info.parent_signature;
1080 int parent_num = weapon->ctype.laser_info.parent_num;
1082 if (!(Game_mode & GM_MULTI))
1085 if (Objects[parent_num].signature != parent_sig)
1086 mprintf((0, "Parent of omega blob not consistent with object information.\n"));
1088 fix dist = vm_vec_dist_quick(&Objects[parent_num].pos, &weapon->pos);
1090 if (dist > MAX_OMEGA_DIST) {
1091 // -- mprintf((0, "Not doing damage in frame %i, too far away.\n", FrameCount));
1094 ; // -- mprintf((0, "*** Doing damage in frame %i ***\n", FrameCount));
1100 //these gets added to the weapon's values when the weapon hits a volitle wall
1101 #define VOLATILE_WALL_EXPL_STRENGTH i2f(10)
1102 #define VOLATILE_WALL_IMPACT_SIZE i2f(3)
1103 #define VOLATILE_WALL_DAMAGE_FORCE i2f(5)
1104 #define VOLATILE_WALL_DAMAGE_RADIUS i2f(30)
1106 // int Show_seg_and_side = 0;
1108 void collide_weapon_and_wall( object * weapon, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt)
1110 segment *seg = &Segments[hitseg];
1116 if (weapon->id == OMEGA_ID)
1117 if (!ok_to_do_omega_damage(weapon))
1120 // If this is a guided missile and it strikes fairly directly, clear bounce flag.
1121 if (weapon->id == GUIDEDMISS_ID) {
1124 dot = vm_vec_dot(&weapon->orient.fvec, &Segments[hitseg].sides[hitwall].normals[0]);
1125 mprintf((0, "Guided missile dot = %7.3f\n", f2fl(dot)));
1126 if (dot < -F1_0/6) {
1127 mprintf((0, "Guided missile loses bounciness.\n"));
1128 weapon->mtype.phys_info.flags &= ~PF_BOUNCE;
1132 //if an energy weapon hits a forcefield, let it bounce
1133 if ((TmapInfo[seg->sides[hitwall].tmap_num].flags & TMI_FORCE_FIELD) &&
1134 !(weapon->type == OBJ_WEAPON && Weapon_info[weapon->id].energy_usage==0)) {
1137 digi_link_sound_to_pos( SOUND_FORCEFIELD_BOUNCE_WEAPON, hitseg, 0, hitpt, 0, f1_0 );
1139 if (Game_mode & GM_MULTI)
1140 multi_send_play_sound(SOUND_FORCEFIELD_BOUNCE_WEAPON, f1_0);
1143 return; //bail here. physics code will bounce this object
1147 if (keyd_pressed[KEY_LAPOSTRO])
1148 if (weapon->ctype.laser_info.parent_num == Players[Player_num].objnum) {
1149 // MK: Real pain when you need to know a seg:side and you've got quad lasers.
1150 mprintf((0, "Your laser hit at segment = %i, side = %i\n", hitseg, hitwall));
1151 HUD_init_message("Hit at segment = %i, side = %i", hitseg, hitwall);
1153 subtract_light(hitseg, hitwall);
1154 else if (weapon->id == FLARE_ID)
1155 add_light(hitseg, hitwall);
1159 //@@Cursegp = &Segments[hitseg];
1160 //@@Curside = hitwall;
1164 if ((weapon->mtype.phys_info.velocity.x == 0) && (weapon->mtype.phys_info.velocity.y == 0) && (weapon->mtype.phys_info.velocity.z == 0)) {
1165 Int3(); // Contact Matt: This is impossible. A weapon with 0 velocity hit a wall, which doesn't move.
1169 blew_up = check_effect_blowup(seg,hitwall,hitpt, weapon, 0);
1171 //if ((seg->sides[hitwall].tmap_num2==0) && (TmapInfo[seg->sides[hitwall].tmap_num].flags & TMI_VOLATILE)) {
1173 if ((weapon->ctype.laser_info.parent_type == OBJ_ROBOT) && (Robot_info[Objects[weapon->ctype.laser_info.parent_num].id].companion==1)) {
1176 if (Game_mode & GM_MULTI)
1178 Int3(); // Get Jason!
1183 playernum = Player_num; //if single player, he's the player's buddy
1188 if (Objects[weapon->ctype.laser_info.parent_num].type == OBJ_PLAYER)
1189 playernum = Objects[weapon->ctype.laser_info.parent_num].id;
1191 playernum = -1; //not a player (thus a robot)
1194 if (blew_up) { //could be a wall switch
1195 //for wall triggers, always say that the player shot it out. This is
1196 //because robots can shoot out wall triggers, and so the trigger better
1198 // NO -- Changed by MK, 10/18/95. We don't want robots blowing puzzles. Only player or buddy can open!
1199 check_trigger(seg,hitwall,weapon->ctype.laser_info.parent_num,1);
1202 if (weapon->id == EARTHSHAKER_ID)
1205 wall_type = wall_hit_process( seg, hitwall, weapon->shields, playernum, weapon );
1207 // Wall is volatile if either tmap 1 or 2 is volatile
1208 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))) {
1209 weapon_info *wi = &Weapon_info[weapon->id];
1212 //we've hit a volatile wall
1214 digi_link_sound_to_pos( SOUND_VOLATILE_WALL_HIT,hitseg, 0, hitpt, 0, F1_0 );
1216 //for most weapons, use volatile wall hit. For mega, use its special vclip
1217 vclip = (weapon->id == MEGA_ID)?Weapon_info[weapon->id].robot_hit_vclip:VCLIP_VOLATILE_WALL_HIT;
1219 // New by MK: If powerful badass, explode as badass, not due to lava, fixes megas being wimpy in lava.
1220 if (wi->damage_radius >= VOLATILE_WALL_DAMAGE_RADIUS/2) {
1221 // -- mprintf((0, "Big weapon doing badass in lava instead.\n"));
1222 explode_badass_weapon(weapon,hitpt);
1224 object_create_badass_explosion( weapon, hitseg, hitpt,
1225 wi->impact_size + VOLATILE_WALL_IMPACT_SIZE,
1227 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.
1228 wi->damage_radius+VOLATILE_WALL_DAMAGE_RADIUS,
1229 wi->strength[Difficulty_level]/2+VOLATILE_WALL_DAMAGE_FORCE,
1230 weapon->ctype.laser_info.parent_num );
1233 weapon->flags |= OF_SHOULD_BE_DEAD; //make flares die in lava
1236 else if ((TmapInfo[seg->sides[hitwall].tmap_num].flags & TMI_WATER) || (seg->sides[hitwall].tmap_num2 && (TmapInfo[seg->sides[hitwall].tmap_num2&0x3fff].flags & TMI_WATER))) {
1237 weapon_info *wi = &Weapon_info[weapon->id];
1241 // MK: 09/13/95: Badass in water is 1/2 normal intensity.
1242 if ( Weapon_info[weapon->id].matter ) {
1244 digi_link_sound_to_pos( SOUND_MISSILE_HIT_WATER,hitseg, 0, hitpt, 0, F1_0 );
1246 if ( Weapon_info[weapon->id].damage_radius ) {
1248 digi_link_sound_to_object(SOUND_BADASS_EXPLOSION, weapon-Objects, 0, F1_0);
1250 // MK: 09/13/95: Badass in water is 1/2 normal intensity.
1251 object_create_badass_explosion( weapon, hitseg, hitpt,
1253 wi->robot_hit_vclip,
1254 wi->strength[Difficulty_level]/4,
1256 wi->strength[Difficulty_level]/2,
1257 weapon->ctype.laser_info.parent_num );
1260 object_create_explosion( weapon->segnum, &weapon->pos, Weapon_info[weapon->id].impact_size, Weapon_info[weapon->id].wall_hit_vclip );
1263 digi_link_sound_to_pos( SOUND_LASER_HIT_WATER,hitseg, 0, hitpt, 0, F1_0 );
1264 object_create_explosion( weapon->segnum, &weapon->pos, Weapon_info[weapon->id].impact_size, VCLIP_WATER_HIT );
1267 weapon->flags |= OF_SHOULD_BE_DEAD; //make flares die in water
1272 if (weapon->mtype.phys_info.flags & PF_BOUNCE) {
1274 //do special bound sound & effect
1279 //if it's not the player's weapon, or it is the player's and there
1280 //is no wall, and no blowing up monitor, then play sound
1281 if ((weapon->ctype.laser_info.parent_type != OBJ_PLAYER) || ((seg->sides[hitwall].wall_num == -1 || wall_type==WHP_NOT_SPECIAL) && !blew_up))
1282 if ((Weapon_info[weapon->id].wall_hit_sound > -1 ) && (!(weapon->flags & OF_SILENT)))
1283 digi_link_sound_to_pos( Weapon_info[weapon->id].wall_hit_sound,weapon->segnum, 0, &weapon->pos, 0, F1_0 );
1285 if ( Weapon_info[weapon->id].wall_hit_vclip > -1 ) {
1286 if ( Weapon_info[weapon->id].damage_radius )
1287 explode_badass_weapon(weapon,hitpt);
1289 object_create_explosion( weapon->segnum, &weapon->pos, Weapon_info[weapon->id].impact_size, Weapon_info[weapon->id].wall_hit_vclip );
1294 // If weapon fired by player or companion...
1295 if (( weapon->ctype.laser_info.parent_type== OBJ_PLAYER ) || robot_escort) {
1297 if (!(weapon->flags & OF_SILENT) && (weapon->ctype.laser_info.parent_num == Players[Player_num].objnum))
1298 create_awareness_event(weapon, PA_WEAPON_WALL_COLLISION); // object "weapon" can attract attention to player
1300 // if (weapon->id != FLARE_ID) {
1301 // We now allow flares to open doors.
1304 if (((weapon->id != FLARE_ID) || (weapon->ctype.laser_info.parent_type != OBJ_PLAYER)) && !(weapon->mtype.phys_info.flags & PF_BOUNCE))
1305 weapon->flags |= OF_SHOULD_BE_DEAD;
1307 //don't let flares stick in force fields
1308 if ((weapon->id == FLARE_ID) && (TmapInfo[seg->sides[hitwall].tmap_num].flags & TMI_FORCE_FIELD))
1309 weapon->flags |= OF_SHOULD_BE_DEAD;
1311 if (!(weapon->flags & OF_SILENT)) {
1312 switch (wall_type) {
1314 case WHP_NOT_SPECIAL:
1315 //should be handled above
1316 //digi_link_sound_to_pos( Weapon_info[weapon->id].wall_hit_sound, weapon->segnum, 0, &weapon->pos, 0, F1_0 );
1320 //play special hit door sound (if/when we get it)
1321 digi_link_sound_to_pos( SOUND_WEAPON_HIT_DOOR, weapon->segnum, 0, &weapon->pos, 0, F1_0 );
1323 if (Game_mode & GM_MULTI)
1324 multi_send_play_sound( SOUND_WEAPON_HIT_DOOR, F1_0 );
1330 //play special blastable wall sound (if/when we get it)
1331 if ((Weapon_info[weapon->id].wall_hit_sound > -1 ) && (!(weapon->flags & OF_SILENT)))
1332 digi_link_sound_to_pos( SOUND_WEAPON_HIT_BLASTABLE, weapon->segnum, 0, &weapon->pos, 0, F1_0 );
1336 //don't play anything, since door open sound will play
1340 //mprintf((0, "Weapon %i hits wall, but has silent bit set.\n", weapon-Objects));
1342 // if (weapon->lifeleft <= 0)
1343 // weapon->flags |= OF_SHOULD_BE_DEAD;
1347 // This is a robot's laser
1348 if (!(weapon->mtype.phys_info.flags & PF_BOUNCE))
1349 weapon->flags |= OF_SHOULD_BE_DEAD;
1355 //##void collide_camera_and_wall( object * camera, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt) {
1359 //##void collide_powerup_and_wall( object * powerup, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt) {
1363 void collide_debris_and_wall( object * debris, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt) {
1364 explode_object(debris,0);
1368 //##void collide_fireball_and_fireball( object * fireball1, object * fireball2, vms_vector *collision_point ) {
1372 //##void collide_fireball_and_robot( object * fireball, object * robot, vms_vector *collision_point ) {
1376 //##void collide_fireball_and_hostage( object * fireball, object * hostage, vms_vector *collision_point ) {
1380 //##void collide_fireball_and_player( object * fireball, object * player, vms_vector *collision_point ) {
1384 //##void collide_fireball_and_weapon( object * fireball, object * weapon, vms_vector *collision_point ) {
1385 //## //weapon->flags |= OF_SHOULD_BE_DEAD;
1389 //##void collide_fireball_and_camera( object * fireball, object * camera, vms_vector *collision_point ) {
1393 //##void collide_fireball_and_powerup( object * fireball, object * powerup, vms_vector *collision_point ) {
1397 //##void collide_fireball_and_debris( object * fireball, object * debris, vms_vector *collision_point ) {
1401 // -------------------------------------------------------------------------------------------------------------------
1402 void collide_robot_and_robot( object * robot1, object * robot2, vms_vector *collision_point ) {
1403 // mprintf((0, "Coll: [%2i %4i %4i %4i] [%2i %4i %4i %4i] at [%4i %4i %4i]",
1404 // robot1-Objects, f2i(robot1->pos.x), f2i(robot1->pos.y), f2i(robot1->pos.z),
1405 // robot2-Objects, f2i(robot2->pos.x), f2i(robot2->pos.y), f2i(robot2->pos.z),
1406 // f2i(collision_point->x), f2i(collision_point->y), f2i(collision_point->z)));
1408 bump_two_objects(robot1, robot2, 1);
1412 void collide_robot_and_controlcen( object * obj1, object * obj2, vms_vector *collision_point )
1415 if (obj1->type == OBJ_ROBOT) {
1417 vm_vec_normalize_quick(vm_vec_sub(&hitvec, &obj2->pos, &obj1->pos));
1418 bump_one_object(obj1, &hitvec, 0);
1421 vm_vec_normalize_quick(vm_vec_sub(&hitvec, &obj1->pos, &obj2->pos));
1422 bump_one_object(obj2, &hitvec, 0);
1427 //##void collide_robot_and_hostage( object * robot, object * hostage, vms_vector *collision_point ) {
1431 fix Last_thief_hit_time;
1433 void collide_robot_and_player( object * robot, object * playerobj, vms_vector *collision_point )
1435 int steal_attempt = 0;
1438 if (robot->flags&OF_EXPLODING)
1441 collision_seg = find_point_seg(collision_point, playerobj->segnum);
1442 if (collision_seg != -1)
1443 object_create_explosion( collision_seg, collision_point, Weapon_info[0].impact_size, Weapon_info[0].wall_hit_vclip );
1445 if (playerobj->id == Player_num) {
1446 if (Robot_info[robot->id].companion) // Player and companion don't collide.
1448 if (Robot_info[robot->id].kamikaze) {
1449 apply_damage_to_robot(robot, robot->shields+1, playerobj-Objects);
1450 if (playerobj == ConsoleObject)
1451 add_points_to_score(Robot_info[robot->id].score_value);
1454 if (Robot_info[robot->id].thief) {
1455 if (Ai_local_info[robot-Objects].mode == AIM_THIEF_ATTACK) {
1456 Last_thief_hit_time = GameTime;
1457 attempt_to_steal_item(robot, playerobj->id);
1459 } else if (GameTime - Last_thief_hit_time < F1_0*2)
1460 return; // ZOUNDS! BRILLIANT! Thief not collide with player if not stealing!
1461 // NO! VERY DUMB! makes thief look very stupid if player hits him while cloaked! -AP
1463 Last_thief_hit_time = GameTime;
1466 create_awareness_event(playerobj, PA_PLAYER_COLLISION); // object robot can attract attention to player
1467 do_ai_robot_hit_attack(robot, playerobj, collision_point);
1468 do_ai_robot_hit(robot, PA_WEAPON_ROBOT_COLLISION);
1472 multi_robot_request_change(robot, playerobj->id);
1475 // added this if to remove the bump sound if it's the thief.
1476 // A "steal" sound was added and it was getting obscured by the bump. -AP 10/3/95
1477 // Changed by MK to make this sound unless the robot stole.
1478 if ((!steal_attempt) && !Robot_info[robot->id].energy_drain)
1479 digi_link_sound_to_pos( SOUND_ROBOT_HIT_PLAYER, playerobj->segnum, 0, collision_point, 0, F1_0 );
1481 bump_two_objects(robot, playerobj, 1);
1485 // Provide a way for network message to instantly destroy the control center
1486 // without awarding points or anything.
1488 // if controlcen == NULL, that means don't do the explosion because the control center
1489 // was actually in another object.
1490 void net_destroy_controlcen(object *controlcen)
1492 if (Control_center_destroyed != 1) {
1494 do_controlcen_destroyed_stuff(controlcen);
1496 if ((controlcen != NULL) && !(controlcen->flags&(OF_EXPLODING|OF_DESTROYED))) {
1497 digi_link_sound_to_pos( SOUND_CONTROL_CENTER_DESTROYED, controlcen->segnum, 0, &controlcen->pos, 0, F1_0 );
1498 explode_object(controlcen,0);
1504 // -----------------------------------------------------------------------------
1505 void apply_damage_to_controlcen(object *controlcen, fix damage, short who)
1509 // Only allow a player to damage the control center.
1511 if ((who < 0) || (who > Highest_object_index))
1514 whotype = Objects[who].type;
1515 if (whotype != OBJ_PLAYER) {
1516 mprintf((0, "Damage to control center by object of type %i prevented by MK!\n", whotype));
1521 if ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP) && (Players[Player_num].time_level < Netgame.control_invul_time))
1523 if (Objects[who].id == Player_num) {
1524 int secs = f2i(Netgame.control_invul_time-Players[Player_num].time_level) % 60;
1525 int mins = f2i(Netgame.control_invul_time-Players[Player_num].time_level) / 60;
1526 HUD_init_message("%s %d:%02d.", TXT_CNTRLCEN_INVUL, mins, secs);
1532 if (Objects[who].id == Player_num) {
1533 Control_center_been_hit = 1;
1534 ai_do_cloak_stuff();
1537 if ( controlcen->shields >= 0 )
1538 controlcen->shields -= damage;
1540 if ( (controlcen->shields < 0) && !(controlcen->flags&(OF_EXPLODING|OF_DESTROYED)) ) {
1542 do_controlcen_destroyed_stuff(controlcen);
1545 if (Game_mode & GM_MULTI) {
1546 if (who == Players[Player_num].objnum)
1547 add_points_to_score(CONTROL_CEN_SCORE);
1548 multi_send_destroy_controlcen((ushort)(controlcen-Objects), Objects[who].id );
1552 if (!(Game_mode & GM_MULTI))
1553 add_points_to_score(CONTROL_CEN_SCORE);
1555 digi_link_sound_to_pos( SOUND_CONTROL_CENTER_DESTROYED, controlcen->segnum, 0, &controlcen->pos, 0, F1_0 );
1557 explode_object(controlcen,0);
1561 void collide_player_and_controlcen( object * controlcen, object * playerobj, vms_vector *collision_point )
1563 if (playerobj->id == Player_num) {
1564 Control_center_been_hit = 1;
1565 ai_do_cloak_stuff(); // In case player cloaked, make control center know where he is.
1568 digi_link_sound_to_pos( SOUND_ROBOT_HIT_PLAYER, playerobj->segnum, 0, collision_point, 0, F1_0 );
1569 bump_two_objects(controlcen, playerobj, 1);
1574 void collide_player_and_marker( object * marker, object * playerobj, vms_vector *collision_point )
1576 mprintf ((0,"Collided with marker %d!\n",marker->id));
1578 if (playerobj->id==Player_num) {
1581 if (Game_mode & GM_MULTI)
1583 drawn = HUD_init_message ("MARKER %s: %s",Players[marker->id/2].callsign,MarkerMessage[marker->id]);
1587 if (MarkerMessage[marker->id][0])
1588 drawn = HUD_init_message("MARKER %d: %s", marker->id+1,MarkerMessage[marker->id]);
1590 drawn = HUD_init_message("MARKER %d", marker->id+1);
1594 digi_play_sample( SOUND_MARKER_HIT, F1_0 );
1596 detect_escort_goal_accomplished(marker-Objects);
1600 // If a persistent weapon and other object is not a weapon, weaken it, else kill it.
1601 // If both objects are weapons, weaken the weapon.
1602 void maybe_kill_weapon(object *weapon, object *other_obj)
1604 if ((weapon->id == PROXIMITY_ID) || (weapon->id == SUPERPROX_ID) || (weapon->id == PMINE_ID)) {
1605 weapon->flags |= OF_SHOULD_BE_DEAD;
1609 // Changed, 10/12/95, MK: Make weapon-weapon collisions always kill both weapons if not persistent.
1610 // Reason: Otherwise you can't use proxbombs to detonate incoming homing missiles (or mega missiles).
1611 if (weapon->mtype.phys_info.flags & PF_PERSISTENT) {
1612 // Weapons do a lot of damage to weapons, other objects do much less.
1613 if (!(weapon->mtype.phys_info.flags & PF_PERSISTENT)) {
1614 if (other_obj->type == OBJ_WEAPON)
1615 weapon->shields -= other_obj->shields/2;
1617 weapon->shields -= other_obj->shields/4;
1619 if (weapon->shields <= 0) {
1620 weapon->shields = 0;
1621 weapon->flags |= OF_SHOULD_BE_DEAD; // weapon->lifeleft = 1;
1625 weapon->flags |= OF_SHOULD_BE_DEAD; // weapon->lifeleft = 1;
1627 // -- if ((weapon->mtype.phys_info.flags & PF_PERSISTENT) || (other_obj->type == OBJ_WEAPON)) {
1628 // -- // Weapons do a lot of damage to weapons, other objects do much less.
1629 // -- if (!(weapon->mtype.phys_info.flags & PF_PERSISTENT)) {
1630 // -- if (other_obj->type == OBJ_WEAPON)
1631 // -- weapon->shields -= other_obj->shields/2;
1633 // -- weapon->shields -= other_obj->shields/4;
1635 // -- if (weapon->shields <= 0) {
1636 // -- weapon->shields = 0;
1637 // -- weapon->flags |= OF_SHOULD_BE_DEAD;
1641 // -- weapon->flags |= OF_SHOULD_BE_DEAD;
1644 void collide_weapon_and_controlcen( object * weapon, object *controlcen, vms_vector *collision_point )
1647 if (weapon->id == OMEGA_ID)
1648 if (!ok_to_do_omega_damage(weapon))
1651 if (weapon->ctype.laser_info.parent_type == OBJ_PLAYER) {
1652 fix damage = weapon->shields;
1654 if (Objects[weapon->ctype.laser_info.parent_num].id == Player_num)
1655 Control_center_been_hit = 1;
1657 if ( Weapon_info[weapon->id].damage_radius )
1658 explode_badass_weapon(weapon,collision_point);
1660 object_create_explosion( controlcen->segnum, collision_point, controlcen->size*3/20, VCLIP_SMALL_EXPLOSION );
1662 digi_link_sound_to_pos( SOUND_CONTROL_CENTER_HIT, controlcen->segnum, 0, collision_point, 0, F1_0 );
1664 damage = fixmul(damage, weapon->ctype.laser_info.multiplier);
1666 apply_damage_to_controlcen(controlcen, damage, weapon->ctype.laser_info.parent_num);
1668 maybe_kill_weapon(weapon,controlcen);
1669 } else { // If robot weapon hits control center, blow it up, make it go away, but do no damage to control center.
1670 object_create_explosion( controlcen->segnum, collision_point, controlcen->size*3/20, VCLIP_SMALL_EXPLOSION );
1671 maybe_kill_weapon(weapon,controlcen);
1676 void collide_weapon_and_clutter( object * weapon, object *clutter, vms_vector *collision_point ) {
1677 short exp_vclip = VCLIP_SMALL_EXPLOSION;
1679 if ( clutter->shields >= 0 )
1680 clutter->shields -= weapon->shields;
1682 digi_link_sound_to_pos( SOUND_LASER_HIT_CLUTTER, weapon->segnum, 0, collision_point, 0, F1_0 );
1684 object_create_explosion( clutter->segnum, collision_point, ((clutter->size/3)*3)/4, exp_vclip );
1686 if ( (clutter->shields < 0) && !(clutter->flags&(OF_EXPLODING|OF_DESTROYED)))
1687 explode_object(clutter,STANDARD_EXPL_DELAY);
1689 maybe_kill_weapon(weapon,clutter);
1692 //--mk, 121094 -- extern void spin_robot(object *robot, vms_vector *collision_point);
1694 extern object *explode_badass_object(object *objp, fix damage, fix distance, fix force);
1696 int Final_boss_is_dead = 0;
1697 fix Final_boss_countdown_time = 0;
1699 // ------------------------------------------------------------------------------------------------------
1700 void do_final_boss_frame(void)
1703 if (!Final_boss_is_dead)
1706 if (!Control_center_destroyed)
1709 if (Final_boss_countdown_time == 0)
1710 Final_boss_countdown_time = F1_0*2;
1712 Final_boss_countdown_time -= FrameTime;
1713 if (Final_boss_countdown_time > 0)
1716 gr_palette_fade_out( gr_palette, 256, 0 );
1717 start_endlevel_sequence(); //pretend we hit the exit trigger
1721 // ------------------------------------------------------------------------------------------------------
1722 // This is all the ugly stuff we do when you kill the final boss so that you don't die or something
1723 // which would ruin the logic of the cut sequence.
1724 void do_final_boss_hacks(void)
1726 if (Player_is_dead) {
1727 Int3(); // Uh-oh, player is dead. Try to rescue him.
1731 if (Players[Player_num].shields <= 0)
1732 Players[Player_num].shields = 1;
1734 // If you're not invulnerable, get invulnerable!
1735 if (!(Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE)) {
1736 Players[Player_num].invulnerable_time = GameTime;
1737 Players[Player_num].flags |= PLAYER_FLAGS_INVULNERABLE;
1739 if (!(Game_mode & GM_MULTI))
1740 buddy_message("Nice job, %s!", Players[Player_num].callsign);
1742 Final_boss_is_dead = 1;
1745 extern int Buddy_dude_cheat;
1746 extern int multi_all_players_alive();
1747 void multi_send_finish_game ();
1749 // ------------------------------------------------------------------------------------------------------
1750 // Return 1 if robot died, else return 0
1751 int apply_damage_to_robot(object *robot, fix damage, int killer_objnum)
1755 char i,temp_stolen[MAX_STOLEN_ITEMS];
1758 if ( robot->flags&OF_EXPLODING) return 0;
1760 if (robot->shields < 0 ) return 0; //robot already dead...
1762 if (Robot_info[robot->id].boss_flag)
1763 Boss_hit_time = GameTime;
1765 // Buddy invulnerable on level 24 so he can give you his important messages. Bah.
1766 // Also invulnerable if his cheat for firing weapons is in effect.
1767 if (Robot_info[robot->id].companion) {
1768 // if ((Current_mission_num == Builtin_mission_num && Current_level_num == Last_level) || Buddy_dude_cheat)
1770 if ((Current_mission_num == Builtin_mission_num && Current_level_num == Last_level) )
1775 // if (robot->control_type == CT_REMOTE)
1776 // return 0; // Can't damange a robot controlled by another player
1778 // -- MK, 10/21/95, unused! -- if (Robot_info[robot->id].boss_flag)
1779 // Boss_been_hit = 1;
1781 robot->shields -= damage;
1783 // Do unspeakable hacks to make sure player doesn't die after killing boss. Or before, sort of.
1784 if (Robot_info[robot->id].boss_flag)
1786 if ((Current_mission_num == Builtin_mission_num) && Current_level_num == Last_level)
1788 if (robot->shields < 0)
1791 if (Game_mode & GM_MULTI)
1793 if (!multi_all_players_alive()) // everyones gotta be alive
1797 multi_send_finish_game();
1798 do_final_boss_hacks();
1804 { // NOTE LINK TO ABOVE!!!
1805 if ((Players[Player_num].shields < 0) || Player_is_dead)
1806 robot->shields = 1; // Sorry, we can't allow you to kill the final boss after you've died. Rough luck.
1808 do_final_boss_hacks();
1812 if (robot->shields < 0) {
1814 if (Game_mode & GM_MULTI) {
1815 if (Robot_info[robot->id].thief)
1821 for (i=0;i<MAX_STOLEN_ITEMS;i++)
1822 temp_stolen[(int)i]=Stolen_items[(int)i];
1824 if (multi_explode_robot_sub(robot-Objects, killer_objnum,Robot_info[robot->id].thief))
1827 for (i=0;i<MAX_STOLEN_ITEMS;i++)
1828 Stolen_items[(int)i]=temp_stolen[(int)i];
1830 multi_send_robot_explode(robot-Objects, killer_objnum,Robot_info[robot->id].thief);
1833 for (i=0;i<MAX_STOLEN_ITEMS;i++)
1834 Stolen_items[(int)i]=255;
1843 Players[Player_num].num_kills_level++;
1844 Players[Player_num].num_kills_total++;
1846 if (Robot_info[robot->id].boss_flag) {
1847 start_boss_death_sequence(robot); //do_controlcen_destroyed_stuff(NULL);
1848 } else if (Robot_info[robot->id].death_roll) {
1849 start_robot_death_sequence(robot); //do_controlcen_destroyed_stuff(NULL);
1851 if (robot->id == SPECIAL_REACTOR_ROBOT)
1852 special_reactor_stuff();
1853 //if (Robot_info[robot->id].smart_blobs)
1854 // create_smart_children(robot, Robot_info[robot->id].smart_blobs);
1855 //if (Robot_info[robot->id].badass)
1856 // explode_badass_object(robot, F1_0*Robot_info[robot->id].badass, F1_0*40, F1_0*150);
1857 if (Robot_info[robot->id].kamikaze)
1858 explode_object(robot,1); // Kamikaze, explode right away, IN YOUR FACE!
1860 explode_object(robot,STANDARD_EXPL_DELAY);
1867 extern int boss_spew_robot(object *objp, vms_vector *pos);
1869 //--ubyte Boss_teleports[NUM_D2_BOSSES] = {1,1,1,1,1,1}; // Set byte if this boss can teleport
1870 //--ubyte Boss_cloaks[NUM_D2_BOSSES] = {1,1,1,1,1,1}; // Set byte if this boss can cloak
1871 //--ubyte Boss_spews_bots_energy[NUM_D2_BOSSES] = {1,1,0,0,1,1}; // Set byte if boss spews bots when hit by energy weapon.
1872 //--ubyte Boss_spews_bots_matter[NUM_D2_BOSSES] = {0,0,1,0,1,1}; // Set byte if boss spews bots when hit by matter weapon.
1873 //--ubyte Boss_invulnerable_energy[NUM_D2_BOSSES] = {0,0,1,1,0,0}; // Set byte if boss is invulnerable to energy weapons.
1874 //--ubyte Boss_invulnerable_matter[NUM_D2_BOSSES] = {0,0,0,1,0,0}; // Set byte if boss is invulnerable to matter weapons.
1875 //--ubyte Boss_invulnerable_spot[NUM_D2_BOSSES] = {0,0,0,0,1,1}; // Set byte if boss is invulnerable in all but a certain spot. (Dot product fvec|vec_to_collision < BOSS_INVULNERABLE_DOT)
1877 //#define BOSS_INVULNERABLE_DOT 0 // If a boss is invulnerable over most of his body, fvec(dot)vec_to_collision must be less than this for damage to occur.
1878 int Boss_invulnerable_dot = 0;
1880 int Buddy_gave_hint_count = 5;
1881 fix Last_time_buddy_gave_hint = 0;
1883 // ------------------------------------------------------------------------------------------------------
1884 // Return true if damage done to boss, else return false.
1885 int do_boss_weapon_collision(object *robot, object *weapon, vms_vector *collision_point)
1892 d2_boss_index = Robot_info[robot->id].boss_flag - BOSS_D2;
1894 Assert((d2_boss_index >= 0) && (d2_boss_index < NUM_D2_BOSSES));
1896 // See if should spew a bot.
1897 if (weapon->ctype.laser_info.parent_type == OBJ_PLAYER)
1898 if ((Weapon_info[weapon->id].matter && Boss_spews_bots_matter[d2_boss_index]) || (!Weapon_info[weapon->id].matter && Boss_spews_bots_energy[d2_boss_index])) {
1899 if (Boss_spew_more[d2_boss_index])
1900 if (d_rand() > 16384) {
1901 if (boss_spew_robot(robot, collision_point) != -1)
1902 Last_gate_time = GameTime - Gate_interval - 1; // Force allowing spew of another bot.
1904 boss_spew_robot(robot, collision_point);
1907 if (Boss_invulnerable_spot[d2_boss_index]) {
1911 // Boss only vulnerable in back. See if hit there.
1912 vm_vec_sub(&tvec1, collision_point, &robot->pos);
1913 vm_vec_normalize_quick(&tvec1); // Note, if BOSS_INVULNERABLE_DOT is close to F1_0 (in magnitude), then should probably use non-quick version.
1914 dot = vm_vec_dot(&tvec1, &robot->orient.fvec);
1915 mprintf((0, "Boss hit vec dot = %7.3f\n", f2fl(dot)));
1917 if (dot > Boss_invulnerable_dot) {
1921 segnum = find_point_seg(collision_point, robot->segnum);
1922 digi_link_sound_to_pos( SOUND_WEAPON_HIT_DOOR, segnum, 0, collision_point, 0, F1_0);
1925 if (Last_time_buddy_gave_hint == 0)
1926 Last_time_buddy_gave_hint = d_rand()*32 + F1_0*16;
1928 if (Buddy_gave_hint_count) {
1929 if (Last_time_buddy_gave_hint + F1_0*20 < GameTime) {
1932 Buddy_gave_hint_count--;
1933 Last_time_buddy_gave_hint = GameTime;
1934 sval = (d_rand()*4) >> 15;
1936 case 0: buddy_message("Hit him in the back!"); break;
1937 case 1: buddy_message("He's invulnerable there!"); break;
1938 case 2: buddy_message("Get behind him and fire!"); break;
1941 buddy_message("Hit the glowing spot!"); break;
1946 // Cause weapon to bounce.
1947 // Make a copy of this weapon, because the physics wants to destroy it.
1948 if (!Weapon_info[weapon->id].matter) {
1949 new_obj = obj_create(weapon->type, weapon->id, weapon->segnum, &weapon->pos,
1950 &weapon->orient, weapon->size, weapon->control_type, weapon->movement_type, weapon->render_type);
1952 if (new_obj != -1) {
1953 vms_vector vec_to_point;
1954 vms_vector weap_vec;
1957 if (weapon->render_type == RT_POLYOBJ) {
1958 Objects[new_obj].rtype.pobj_info.model_num = Weapon_info[Objects[new_obj].id].model_num;
1959 Objects[new_obj].size = fixdiv(Polygon_models[Objects[new_obj].rtype.pobj_info.model_num].rad,Weapon_info[Objects[new_obj].id].po_len_to_width_ratio);
1962 Objects[new_obj].mtype.phys_info.mass = Weapon_info[weapon->type].mass;
1963 Objects[new_obj].mtype.phys_info.drag = Weapon_info[weapon->type].drag;
1964 vm_vec_zero(&Objects[new_obj].mtype.phys_info.thrust);
1966 vm_vec_sub(&vec_to_point, collision_point, &robot->pos);
1967 vm_vec_normalize_quick(&vec_to_point);
1968 weap_vec = weapon->mtype.phys_info.velocity;
1969 speed = vm_vec_normalize_quick(&weap_vec);
1970 vm_vec_scale_add2(&vec_to_point, &weap_vec, -F1_0*2);
1971 vm_vec_scale(&vec_to_point, speed/4);
1972 Objects[new_obj].mtype.phys_info.velocity = vec_to_point;
1976 } else if ((Weapon_info[weapon->id].matter && Boss_invulnerable_matter[d2_boss_index]) || (!Weapon_info[weapon->id].matter && Boss_invulnerable_energy[d2_boss_index])) {
1979 segnum = find_point_seg(collision_point, robot->segnum);
1980 digi_link_sound_to_pos( SOUND_WEAPON_HIT_DOOR, segnum, 0, collision_point, 0, F1_0);
1987 extern int Robots_kill_robots_cheat;
1989 // ------------------------------------------------------------------------------------------------------
1990 void collide_robot_and_weapon( object * robot, object * weapon, vms_vector *collision_point )
1993 int boss_invul_flag=0;
1995 if (weapon->id == OMEGA_ID)
1996 if (!ok_to_do_omega_damage(weapon))
1999 if (Robot_info[robot->id].boss_flag) {
2000 Boss_hit_time = GameTime;
2001 if (Robot_info[robot->id].boss_flag >= BOSS_D2) {
2002 damage_flag = do_boss_weapon_collision(robot, weapon, collision_point);
2003 boss_invul_flag = !damage_flag;
2007 // Put in at request of Jasen (and Adam) because the Buddy-Bot gets in their way.
2008 // MK has so much fun whacking his butt around the mine he never cared...
2009 if ((Robot_info[robot->id].companion) && ((weapon->ctype.laser_info.parent_type != OBJ_ROBOT) && !Robots_kill_robots_cheat))
2012 if (weapon->id == EARTHSHAKER_ID)
2015 // If a persistent weapon hit robot most recently, quick abort, else we cream the same robot many times,
2016 // depending on frame rate.
2017 if (weapon->mtype.phys_info.flags & PF_PERSISTENT) {
2018 if (weapon->ctype.laser_info.last_hitobj == robot-Objects)
2021 weapon->ctype.laser_info.last_hitobj = robot-Objects;
2023 // mprintf((0, "weapon #%i with power %i hits robot #%i.\n", weapon - Objects, f2i(weapon->shields), robot - Objects));
2026 if (weapon->ctype.laser_info.parent_signature == robot->signature)
2029 // Changed, 10/04/95, put out blobs based on skill level and power of weapon doing damage.
2030 // Also, only a weapon hit from a player weapon causes smart blobs.
2031 if ((weapon->ctype.laser_info.parent_type == OBJ_PLAYER) && (Robot_info[robot->id].energy_blobs))
2032 if ((robot->shields > 0) && Weapon_is_energy[weapon->id]) {
2036 probval = (Difficulty_level+2) * min(weapon->shields, robot->shields);
2037 probval = Robot_info[robot->id].energy_blobs * probval/(NDL*32);
2039 num_blobs = probval >> 16;
2040 if (2*d_rand() < (probval & 0xffff))
2044 create_smart_children(robot, num_blobs);
2047 // Note: If weapon hits an invulnerable boss, it will still do badass damage, including to the boss,
2048 // unless this is trapped elsewhere.
2049 if ( Weapon_info[weapon->id].damage_radius )
2051 if (boss_invul_flag) { //don't make badass sound
2052 weapon_info *wi = &Weapon_info[weapon->id];
2054 //this code copied from explode_badass_weapon()
2056 object_create_badass_explosion( weapon, weapon->segnum, collision_point,
2058 wi->robot_hit_vclip,
2059 wi->strength[Difficulty_level],
2060 wi->damage_radius,wi->strength[Difficulty_level],
2061 weapon->ctype.laser_info.parent_num );
2064 else //normal badass explosion
2065 explode_badass_weapon(weapon,collision_point);
2068 if ( ((weapon->ctype.laser_info.parent_type==OBJ_PLAYER) || Robots_kill_robots_cheat) && !(robot->flags & OF_EXPLODING) ) {
2069 object *expl_obj=NULL;
2071 if (weapon->ctype.laser_info.parent_num == Players[Player_num].objnum) {
2072 create_awareness_event(weapon, PA_WEAPON_ROBOT_COLLISION); // object "weapon" can attract attention to player
2073 do_ai_robot_hit(robot, PA_WEAPON_ROBOT_COLLISION);
2077 multi_robot_request_change(robot, Objects[weapon->ctype.laser_info.parent_num].id);
2080 if ( Robot_info[robot->id].exp1_vclip_num > -1 )
2081 expl_obj = object_create_explosion( weapon->segnum, collision_point, (robot->size/2*3)/4, Robot_info[robot->id].exp1_vclip_num );
2082 else if ( Weapon_info[weapon->id].robot_hit_vclip > -1 )
2083 expl_obj = object_create_explosion( weapon->segnum, collision_point, Weapon_info[weapon->id].impact_size, Weapon_info[weapon->id].robot_hit_vclip );
2086 obj_attach(robot,expl_obj);
2088 if ( damage_flag && (Robot_info[robot->id].exp1_sound_num > -1 ))
2089 digi_link_sound_to_pos( Robot_info[robot->id].exp1_sound_num, robot->segnum, 0, collision_point, 0, F1_0 );
2091 if (!(weapon->flags & OF_HARMLESS)) {
2092 fix damage = weapon->shields;
2095 damage = fixmul(damage, weapon->ctype.laser_info.multiplier);
2099 // Cut Gauss damage on bosses because it just breaks the game. Bosses are so easy to
2100 // hit, and missing a robot is what prevents the Gauss from being game-breaking.
2101 if (weapon->id == GAUSS_ID)
2102 if (Robot_info[robot->id].boss_flag)
2103 damage = damage * (2*NDL-Difficulty_level)/(2*NDL);
2105 if (! apply_damage_to_robot(robot, damage, weapon->ctype.laser_info.parent_num))
2106 bump_two_objects(robot, weapon, 0); //only bump if not dead. no damage from bump
2107 else if (weapon->ctype.laser_info.parent_signature == ConsoleObject->signature) {
2108 add_points_to_score(Robot_info[robot->id].score_value);
2109 detect_escort_goal_accomplished(robot-Objects);
2114 // If Gauss Cannon, spin robot.
2115 if ((robot != NULL) && (!Robot_info[robot->id].companion) && (!Robot_info[robot->id].boss_flag) && (weapon->id == GAUSS_ID)) {
2116 ai_static *aip = &robot->ctype.ai_info;
2118 if (aip->SKIP_AI_COUNT * FrameTime < F1_0) {
2119 aip->SKIP_AI_COUNT++;
2120 robot->mtype.phys_info.rotthrust.x = fixmul((d_rand() - 16384), FrameTime * aip->SKIP_AI_COUNT);
2121 robot->mtype.phys_info.rotthrust.y = fixmul((d_rand() - 16384), FrameTime * aip->SKIP_AI_COUNT);
2122 robot->mtype.phys_info.rotthrust.z = fixmul((d_rand() - 16384), FrameTime * aip->SKIP_AI_COUNT);
2123 robot->mtype.phys_info.flags |= PF_USES_THRUST;
2130 maybe_kill_weapon(weapon,robot);
2135 //##void collide_robot_and_camera( object * robot, object * camera, vms_vector *collision_point ) {
2139 //##void collide_robot_and_powerup( object * robot, object * powerup, vms_vector *collision_point ) {
2143 //##void collide_robot_and_debris( object * robot, object * debris, vms_vector *collision_point ) {
2147 //##void collide_hostage_and_hostage( object * hostage1, object * hostage2, vms_vector *collision_point ) {
2151 void collide_hostage_and_player( object * hostage, object * player, vms_vector *collision_point ) {
2152 // Give player points, etc.
2153 if ( player == ConsoleObject ) {
2154 detect_escort_goal_accomplished(hostage-Objects);
2155 add_points_to_score(HOSTAGE_SCORE);
2158 hostage_rescue(hostage->id);
2160 // Remove the hostage object.
2161 hostage->flags |= OF_SHOULD_BE_DEAD;
2164 if (Game_mode & GM_MULTI)
2165 multi_send_remobj(hostage-Objects);
2171 //--unused-- void collide_hostage_and_weapon( object * hostage, object * weapon, vms_vector *collision_point )
2173 //--unused-- // Cannot kill hostages, as per Matt's edict!
2174 //--unused-- // (A fine edict, but in contradiction to the milestone: "Robots attack hostages.")
2175 //--unused-- hostage->shields -= weapon->shields/2;
2177 //--unused-- create_awareness_event(weapon, PA_WEAPON_ROBOT_COLLISION); // object "weapon" can attract attention to player
2179 //--unused-- //PLAY_SOUND_3D( SOUND_HOSTAGE_KILLED, collision_point, hostage->segnum );
2180 //--unused-- digi_link_sound_to_pos( SOUND_HOSTAGE_KILLED, hostage->segnum , 0, collision_point, 0, F1_0 );
2183 //--unused-- if (hostage->shields <= 0) {
2184 //--unused-- explode_object(hostage,0);
2185 //--unused-- hostage->flags |= OF_SHOULD_BE_DEAD;
2188 //--unused-- if ( Weapon_info[weapon->id].damage_radius )
2189 //--unused-- explode_badass_weapon(weapon);
2191 //--unused-- maybe_kill_weapon(weapon,hostage);
2195 //##void collide_hostage_and_camera( object * hostage, object * camera, vms_vector *collision_point ) {
2199 //##void collide_hostage_and_powerup( object * hostage, object * powerup, vms_vector *collision_point ) {
2203 //##void collide_hostage_and_debris( object * hostage, object * debris, vms_vector *collision_point ) {
2207 void collide_player_and_player( object * player1, object * player2, vms_vector *collision_point ) {
2208 digi_link_sound_to_pos( SOUND_ROBOT_HIT_PLAYER, player1->segnum, 0, collision_point, 0, F1_0 );
2209 bump_two_objects(player1, player2, 1);
2213 int maybe_drop_primary_weapon_egg(object *playerobj, int weapon_index)
2215 int weapon_flag = HAS_FLAG(weapon_index);
2218 powerup_num = Primary_weapon_to_powerup[weapon_index];
2220 if (Players[playerobj->id].primary_weapon_flags & weapon_flag)
2221 return call_object_create_egg(playerobj, 1, OBJ_POWERUP, powerup_num);
2226 void maybe_drop_secondary_weapon_egg(object *playerobj, int weapon_index, int count)
2228 int weapon_flag = HAS_FLAG(weapon_index);
2231 powerup_num = Secondary_weapon_to_powerup[weapon_index];
2233 if (Players[playerobj->id].secondary_weapon_flags & weapon_flag) {
2236 max_count = min(count, 3);
2237 for (i=0; i<max_count; i++)
2238 call_object_create_egg(playerobj, 1, OBJ_POWERUP, powerup_num);
2242 void drop_missile_1_or_4(object *playerobj,int missile_index)
2244 int num_missiles,powerup_id;
2246 num_missiles = Players[playerobj->id].secondary_ammo[missile_index];
2247 powerup_id = Secondary_weapon_to_powerup[missile_index];
2249 if (num_missiles > 10)
2252 call_object_create_egg(playerobj, num_missiles/4, OBJ_POWERUP, powerup_id+1);
2253 call_object_create_egg(playerobj, num_missiles%4, OBJ_POWERUP, powerup_id);
2256 // -- int Items_destroyed = 0;
2258 void drop_player_eggs(object *playerobj)
2260 // mprintf((0, "In drop_player_eggs...\n"));
2262 if ((playerobj->type == OBJ_PLAYER) || (playerobj->type == OBJ_GHOST)) {
2264 int pnum = playerobj->id;
2269 // -- Items_destroyed = 0;
2271 // Seed the random number generator so in net play the eggs will always
2272 // drop the same way
2274 if (Game_mode & GM_MULTI)
2281 // If the player had smart mines, maybe arm one of them.
2283 while ((Players[playerobj->id].secondary_ammo[SMART_MINE_INDEX]%4==1) && (d_rand() < rthresh)) {
2287 make_random_vector(&randvec);
2289 vm_vec_add(&tvec, &playerobj->pos, &randvec);
2290 newseg = find_point_seg(&tvec, playerobj->segnum);
2292 Laser_create_new(&randvec, &tvec, newseg, playerobj-Objects, SUPERPROX_ID, 0);
2295 // If the player had proximity bombs, maybe arm one of them.
2297 if ((Game_mode & GM_MULTI) && !(Game_mode & GM_HOARD))
2300 while ((Players[playerobj->id].secondary_ammo[PROXIMITY_INDEX]%4==1) && (d_rand() < rthresh)) {
2304 make_random_vector(&randvec);
2306 vm_vec_add(&tvec, &playerobj->pos, &randvec);
2307 newseg = find_point_seg(&tvec, playerobj->segnum);
2309 Laser_create_new(&randvec, &tvec, newseg, playerobj-Objects, PROXIMITY_ID, 0);
2314 // If the player dies and he has powerful lasers, create the powerups here.
2316 if (Players[pnum].laser_level > MAX_LASER_LEVEL)
2317 call_object_create_egg(playerobj, Players[pnum].laser_level-MAX_LASER_LEVEL, OBJ_POWERUP, POW_SUPER_LASER);
2318 else if (Players[pnum].laser_level >= 1)
2319 call_object_create_egg(playerobj, Players[pnum].laser_level, OBJ_POWERUP, POW_LASER); // Note: laser_level = 0 for laser level 1.
2321 // Drop quad laser if appropos
2322 if (Players[pnum].flags & PLAYER_FLAGS_QUAD_LASERS)
2323 call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_QUAD_FIRE);
2325 if (Players[pnum].flags & PLAYER_FLAGS_CLOAKED)
2326 call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_CLOAK);
2328 if (Players[pnum].flags & PLAYER_FLAGS_MAP_ALL)
2329 call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_FULL_MAP);
2331 if (Players[pnum].flags & PLAYER_FLAGS_AFTERBURNER)
2332 call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_AFTERBURNER);
2334 if (Players[pnum].flags & PLAYER_FLAGS_AMMO_RACK)
2335 call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_AMMO_RACK);
2337 if (Players[pnum].flags & PLAYER_FLAGS_CONVERTER)
2338 call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_CONVERTER);
2340 if (Players[pnum].flags & PLAYER_FLAGS_HEADLIGHT)
2341 call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_HEADLIGHT);
2343 // drop the other enemies flag if you have it
2346 if ((Game_mode & GM_CAPTURE) && (Players[pnum].flags & PLAYER_FLAGS_FLAG))
2348 if ((get_team (pnum)==TEAM_RED))
2349 call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_FLAG_BLUE);
2351 call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_FLAG_RED);
2355 if (Game_mode & GM_HOARD)
2361 mprintf ((0,"HOARD MODE: Dropping %d orbs\n",Players[pnum].secondary_ammo[PROXIMITY_INDEX]));
2363 max_count = min(Players[pnum].secondary_ammo[PROXIMITY_INDEX], 12);
2364 for (i=0; i<max_count; i++)
2365 call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_HOARD_ORB);
2369 //Drop the vulcan, gauss, and ammo
2370 vulcan_ammo = Players[pnum].primary_ammo[VULCAN_INDEX];
2371 if ((Players[pnum].primary_weapon_flags & HAS_FLAG(VULCAN_INDEX)) && (Players[pnum].primary_weapon_flags & HAS_FLAG(GAUSS_INDEX)))
2372 vulcan_ammo /= 2; //if both vulcan & gauss, each gets half
2373 if (vulcan_ammo < VULCAN_AMMO_AMOUNT)
2374 vulcan_ammo = VULCAN_AMMO_AMOUNT; //make sure gun has at least as much as a powerup
2375 objnum = maybe_drop_primary_weapon_egg(playerobj, VULCAN_INDEX);
2377 Objects[objnum].ctype.powerup_info.count = vulcan_ammo;
2378 objnum = maybe_drop_primary_weapon_egg(playerobj, GAUSS_INDEX);
2380 Objects[objnum].ctype.powerup_info.count = vulcan_ammo;
2382 // Drop the rest of the primary weapons
2383 maybe_drop_primary_weapon_egg(playerobj, SPREADFIRE_INDEX);
2384 maybe_drop_primary_weapon_egg(playerobj, PLASMA_INDEX);
2385 maybe_drop_primary_weapon_egg(playerobj, FUSION_INDEX);
2387 maybe_drop_primary_weapon_egg(playerobj, HELIX_INDEX);
2388 maybe_drop_primary_weapon_egg(playerobj, PHOENIX_INDEX);
2390 objnum = maybe_drop_primary_weapon_egg(playerobj, OMEGA_INDEX);
2392 Objects[objnum].ctype.powerup_info.count = (playerobj->id==Player_num)?Omega_charge:MAX_OMEGA_CHARGE;
2394 // Drop the secondary weapons
2395 // Note, proximity weapon only comes in packets of 4. So drop n/2, but a max of 3 (handled inside maybe_drop..) Make sense?
2397 if (!(Game_mode & GM_HOARD))
2398 maybe_drop_secondary_weapon_egg(playerobj, PROXIMITY_INDEX, (Players[playerobj->id].secondary_ammo[PROXIMITY_INDEX])/4);
2400 maybe_drop_secondary_weapon_egg(playerobj, SMART_INDEX, Players[playerobj->id].secondary_ammo[SMART_INDEX]);
2401 maybe_drop_secondary_weapon_egg(playerobj, MEGA_INDEX, Players[playerobj->id].secondary_ammo[MEGA_INDEX]);
2403 maybe_drop_secondary_weapon_egg(playerobj, SMART_MINE_INDEX,(Players[playerobj->id].secondary_ammo[SMART_MINE_INDEX])/4);
2404 maybe_drop_secondary_weapon_egg(playerobj, SMISSILE5_INDEX, Players[playerobj->id].secondary_ammo[SMISSILE5_INDEX]);
2406 // Drop the player's missiles in packs of 1 and/or 4
2407 drop_missile_1_or_4(playerobj,HOMING_INDEX);
2408 drop_missile_1_or_4(playerobj,GUIDED_INDEX);
2409 drop_missile_1_or_4(playerobj,CONCUSSION_INDEX);
2410 drop_missile_1_or_4(playerobj,SMISSILE1_INDEX);
2411 drop_missile_1_or_4(playerobj,SMISSILE4_INDEX);
2413 // If player has vulcan ammo, but no vulcan cannon, drop the ammo.
2414 if (!(Players[playerobj->id].primary_weapon_flags & HAS_VULCAN_FLAG)) {
2415 int amount = Players[playerobj->id].primary_ammo[VULCAN_INDEX];
2417 mprintf((0, "Surprising amount of vulcan ammo: %i bullets.\n", amount));
2420 while (amount > 0) {
2421 call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_VULCAN_AMMO);
2422 amount -= VULCAN_AMMO_AMOUNT;
2426 // Always drop a shield and energy powerup.
2427 if (Game_mode & GM_MULTI) {
2428 call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_SHIELD_BOOST);
2429 call_object_create_egg(playerobj, 1, OBJ_POWERUP, POW_ENERGY);
2432 //-- // Drop all the keys.
2433 //-- if (Players[Player_num].flags & PLAYER_FLAGS_BLUE_KEY) {
2434 //-- playerobj->contains_count = 1;
2435 //-- playerobj->contains_type = OBJ_POWERUP;
2436 //-- playerobj->contains_id = POW_KEY_BLUE;
2437 //-- object_create_egg(playerobj);
2439 //-- if (Players[Player_num].flags & PLAYER_FLAGS_RED_KEY) {
2440 //-- playerobj->contains_count = 1;
2441 //-- playerobj->contains_type = OBJ_POWERUP;
2442 //-- playerobj->contains_id = POW_KEY_RED;
2443 //-- object_create_egg(playerobj);
2445 //-- if (Players[Player_num].flags & PLAYER_FLAGS_GOLD_KEY) {
2446 //-- playerobj->contains_count = 1;
2447 //-- playerobj->contains_type = OBJ_POWERUP;
2448 //-- playerobj->contains_id = POW_KEY_GOLD;
2449 //-- object_create_egg(playerobj);
2452 // -- if (Items_destroyed) {
2453 // -- if (Items_destroyed == 1)
2454 // -- HUD_init_message("%i item was destroyed.", Items_destroyed);
2456 // -- HUD_init_message("%i items were destroyed.", Items_destroyed);
2457 // -- Items_destroyed = 0;
2463 // -- removed, 09/06/95, MK -- void destroy_primary_weapon(int weapon_index)
2464 // -- removed, 09/06/95, MK -- {
2465 // -- removed, 09/06/95, MK -- if (weapon_index == MAX_PRIMARY_WEAPONS) {
2466 // -- removed, 09/06/95, MK -- HUD_init_message("Quad lasers destroyed!");
2467 // -- removed, 09/06/95, MK -- Players[Player_num].flags &= ~PLAYER_FLAGS_QUAD_LASERS;
2468 // -- removed, 09/06/95, MK -- update_laser_weapon_info();
2469 // -- removed, 09/06/95, MK -- } else if (weapon_index == 0) {
2470 // -- removed, 09/06/95, MK -- Assert(Players[Player_num].laser_level > 0);
2471 // -- removed, 09/06/95, MK -- HUD_init_message("%s degraded!", Text_string[104+weapon_index]); // Danger! Danger! Use of literal! Danger!
2472 // -- removed, 09/06/95, MK -- Players[Player_num].laser_level--;
2473 // -- removed, 09/06/95, MK -- update_laser_weapon_info();
2474 // -- removed, 09/06/95, MK -- } else {
2475 // -- removed, 09/06/95, MK -- HUD_init_message("%s destroyed!", Text_string[104+weapon_index]); // Danger! Danger! Use of literal! Danger!
2476 // -- removed, 09/06/95, MK -- Players[Player_num].primary_weapon_flags &= ~(1 << weapon_index);
2477 // -- removed, 09/06/95, MK -- auto_select_weapon(0);
2478 // -- removed, 09/06/95, MK -- }
2479 // -- removed, 09/06/95, MK --
2480 // -- removed, 09/06/95, MK -- }
2481 // -- removed, 09/06/95, MK --
2482 // -- removed, 09/06/95, MK -- void destroy_secondary_weapon(int weapon_index)
2483 // -- removed, 09/06/95, MK -- {
2484 // -- removed, 09/06/95, MK -- if (Players[Player_num].secondary_ammo <= 0)
2485 // -- removed, 09/06/95, MK -- return;
2486 // -- removed, 09/06/95, MK --
2487 // -- removed, 09/06/95, MK -- HUD_init_message("%s destroyed!", Text_string[114+weapon_index]); // Danger! Danger! Use of literal! Danger!
2488 // -- removed, 09/06/95, MK -- if (--Players[Player_num].secondary_ammo[weapon_index] == 0)
2489 // -- removed, 09/06/95, MK -- auto_select_weapon(1);
2490 // -- removed, 09/06/95, MK --
2491 // -- removed, 09/06/95, MK -- }
2492 // -- removed, 09/06/95, MK --
2493 // -- removed, 09/06/95, MK -- #define LOSE_WEAPON_THRESHOLD (F1_0*30)
2495 extern fix Buddy_sorry_time;
2497 void apply_damage_to_player(object *playerobj, object *killer, fix damage)
2502 if (Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE)
2505 if (Endlevel_sequence)
2508 //for the player, the 'real' shields are maintained in the Players[]
2509 //array. The shields value in the player's object are, I think, not
2510 //used anywhere. This routine, however, sets the objects shields to
2511 //be a mirror of the value in the Player structure.
2513 if (playerobj->id == Player_num) { //is this the local player?
2515 // MK: 08/14/95: This code can never be reached. See the return about 12 lines up.
2516 // -- if (Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE) {
2518 // -- //invincible, so just do blue flash
2520 // -- PALETTE_FLASH_ADD(0,0,f2i(damage)*4); //flash blue
2523 // -- else { //take damage, do red flash
2525 Players[Player_num].shields -= damage;
2527 PALETTE_FLASH_ADD(f2i(damage)*4,-f2i(damage/2),-f2i(damage/2)); //flash red
2531 if (Players[Player_num].shields < 0) {
2533 Players[Player_num].killer_objnum = killer-Objects;
2535 // if ( killer && (killer->type == OBJ_PLAYER))
2536 // Players[Player_num].killer_objnum = killer-Objects;
2538 playerobj->flags |= OF_SHOULD_BE_DEAD;
2540 if (Buddy_objnum != -1)
2541 if (killer && (killer->type == OBJ_ROBOT) && (Robot_info[killer->id].companion))
2542 Buddy_sorry_time = GameTime;
2544 // -- removed, 09/06/95, MK -- else if (Players[Player_num].shields < LOSE_WEAPON_THRESHOLD) {
2545 // -- removed, 09/06/95, MK -- int randnum = d_rand();
2546 // -- removed, 09/06/95, MK --
2547 // -- removed, 09/06/95, MK -- if (fixmul(Players[Player_num].shields, randnum) < damage/4) {
2548 // -- removed, 09/06/95, MK -- if (d_rand() > 20000) {
2549 // -- removed, 09/06/95, MK -- destroy_secondary_weapon(Secondary_weapon);
2550 // -- removed, 09/06/95, MK -- } else if (Primary_weapon == 0) {
2551 // -- removed, 09/06/95, MK -- if (Players[Player_num].flags & PLAYER_FLAGS_QUAD_LASERS)
2552 // -- removed, 09/06/95, MK -- destroy_primary_weapon(MAX_PRIMARY_WEAPONS); // This means to destroy quad laser.
2553 // -- removed, 09/06/95, MK -- else if (Players[Player_num].laser_level > 0)
2554 // -- removed, 09/06/95, MK -- destroy_primary_weapon(Primary_weapon);
2555 // -- removed, 09/06/95, MK -- } else
2556 // -- removed, 09/06/95, MK -- destroy_primary_weapon(Primary_weapon);
2557 // -- removed, 09/06/95, MK -- } else
2558 // -- removed, 09/06/95, MK -- ; // mprintf((0, "%8x > %8x, so don't lose weapon.\n", fixmul(Players[Player_num].shields, randnum), damage/4));
2559 // -- removed, 09/06/95, MK -- }
2561 playerobj->shields = Players[Player_num].shields; //mirror
2566 void collide_player_and_weapon( object * playerobj, object * weapon, vms_vector *collision_point )
2568 fix damage = weapon->shields;
2569 object * killer=NULL;
2571 // In multiplayer games, only do damage to another player if in first frame.
2572 // This is necessary because in multiplayer, due to varying framerates, omega blobs actually
2573 // have a bit of a lifetime. But they start out with a lifetime of ONE_FRAME_TIME, and this
2574 // gets bashed to 1/4 second in laser_do_weapon_sequence. This bashing occurs for visual purposes only.
2575 if (weapon->id == OMEGA_ID)
2576 if (!ok_to_do_omega_damage(weapon))
2579 // Don't collide own smart mines unless direct hit.
2580 if (weapon->id == SUPERPROX_ID)
2581 if (playerobj-Objects == weapon->ctype.laser_info.parent_num)
2582 if (vm_vec_dist_quick(collision_point, &playerobj->pos) > playerobj->size)
2585 if (weapon->id == EARTHSHAKER_ID)
2588 damage = fixmul(damage, weapon->ctype.laser_info.multiplier);
2590 if (Game_mode & GM_MULTI)
2591 damage = fixmul(damage, Weapon_info[weapon->id].multi_damage_scale);
2594 if (weapon->mtype.phys_info.flags & PF_PERSISTENT)
2596 if (weapon->ctype.laser_info.last_hitobj == playerobj-Objects)
2599 weapon->ctype.laser_info.last_hitobj = playerobj-Objects;
2602 if (playerobj->id == Player_num)
2604 if (!(Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE))
2606 digi_link_sound_to_pos( SOUND_PLAYER_GOT_HIT, playerobj->segnum, 0, collision_point, 0, F1_0 );
2608 if (Game_mode & GM_MULTI)
2609 multi_send_play_sound(SOUND_PLAYER_GOT_HIT, F1_0);
2614 digi_link_sound_to_pos( SOUND_WEAPON_HIT_DOOR, playerobj->segnum, 0, collision_point, 0, F1_0);
2616 if (Game_mode & GM_MULTI)
2617 multi_send_play_sound(SOUND_WEAPON_HIT_DOOR, F1_0);
2622 object_create_explosion( playerobj->segnum, collision_point, i2f(10)/2, VCLIP_PLAYER_HIT );
2623 if ( Weapon_info[weapon->id].damage_radius )
2624 explode_badass_weapon(weapon,collision_point);
2626 maybe_kill_weapon(weapon,playerobj);
2628 bump_two_objects(playerobj, weapon, 0); //no damage from bump
2630 if ( !Weapon_info[weapon->id].damage_radius ) {
2631 if ( weapon->ctype.laser_info.parent_num > -1 )
2632 killer = &Objects[weapon->ctype.laser_info.parent_num];
2634 // if (weapon->id == SMART_HOMING_ID)
2637 if (!(weapon->flags & OF_HARMLESS))
2638 apply_damage_to_player( playerobj, killer, damage);
2641 // Robots become aware of you if you get hit.
2642 ai_do_cloak_stuff();
2647 // Nasty robots are the ones that attack you by running into you and doing lots of damage.
2648 void collide_player_and_nasty_robot( object * playerobj, object * robot, vms_vector *collision_point )
2650 // if (!(Robot_info[robot->id].energy_drain && Players[playerobj->id].energy))
2651 digi_link_sound_to_pos( Robot_info[robot->id].claw_sound, playerobj->segnum, 0, collision_point, 0, F1_0 );
2653 object_create_explosion( playerobj->segnum, collision_point, i2f(10)/2, VCLIP_PLAYER_HIT );
2655 bump_two_objects(playerobj, robot, 0); //no damage from bump
2657 apply_damage_to_player( playerobj, robot, F1_0*(Difficulty_level+1));
2662 void collide_player_and_materialization_center(object *objp)
2665 vms_vector exit_dir;
2666 segment *segp = &Segments[objp->segnum];
2668 digi_link_sound_to_pos(SOUND_PLAYER_GOT_HIT, objp->segnum, 0, &objp->pos, 0, F1_0);
2669 // digi_play_sample( SOUND_PLAYER_GOT_HIT, F1_0 );
2671 object_create_explosion( objp->segnum, &objp->pos, i2f(10)/2, VCLIP_PLAYER_HIT );
2673 if (objp->id != Player_num)
2676 for (side=0; side<MAX_SIDES_PER_SEGMENT; side++)
2677 if (WALL_IS_DOORWAY(segp, side) & WID_FLY_FLAG) {
2678 vms_vector exit_point, rand_vec;
2680 compute_center_point_on_side(&exit_point, segp, side);
2681 vm_vec_sub(&exit_dir, &exit_point, &objp->pos);
2682 vm_vec_normalize_quick(&exit_dir);
2683 make_random_vector(&rand_vec);
2684 rand_vec.x /= 4; rand_vec.y /= 4; rand_vec.z /= 4;
2685 vm_vec_add2(&exit_dir, &rand_vec);
2686 vm_vec_normalize_quick(&exit_dir);
2689 bump_one_object(objp, &exit_dir, 64*F1_0);
2691 apply_damage_to_player( objp, objp, 4*F1_0); // Changed, MK, 2/19/96, make killer the player, so if you die in matcen, will say you killed yourself
2697 void collide_robot_and_materialization_center(object *objp)
2700 vms_vector exit_dir;
2701 segment *segp=&Segments[objp->segnum];
2703 digi_link_sound_to_pos(SOUND_ROBOT_HIT, objp->segnum, 0, &objp->pos, 0, F1_0);
2704 // digi_play_sample( SOUND_ROBOT_HIT, F1_0 );
2706 if ( Robot_info[objp->id].exp1_vclip_num > -1 )
2707 object_create_explosion( objp->segnum, &objp->pos, (objp->size/2*3)/4, Robot_info[objp->id].exp1_vclip_num );
2709 for (side=0; side<MAX_SIDES_PER_SEGMENT; side++)
2710 if (WALL_IS_DOORWAY(segp, side) & WID_FLY_FLAG) {
2711 vms_vector exit_point;
2713 compute_center_point_on_side(&exit_point, segp, side);
2714 vm_vec_sub(&exit_dir, &exit_point, &objp->pos);
2715 vm_vec_normalize_quick(&exit_dir);
2718 bump_one_object(objp, &exit_dir, 8*F1_0);
2720 apply_damage_to_robot( objp, F1_0, -1);
2726 //##void collide_player_and_camera( object * playerobj, object * camera, vms_vector *collision_point ) {
2730 extern int Network_got_powerup; // HACK!!!
2732 void collide_player_and_powerup( object * playerobj, object * powerup, vms_vector *collision_point ) {
2733 if (!Endlevel_sequence && !Player_is_dead && (playerobj->id == Player_num )) {
2736 powerup_used = do_powerup(powerup);
2739 powerup->flags |= OF_SHOULD_BE_DEAD;
2741 if (Game_mode & GM_MULTI)
2742 multi_send_remobj(powerup-Objects);
2747 else if ((Game_mode & GM_MULTI_COOP) && (playerobj->id != Player_num))
2749 switch (powerup->id) {
2751 Players[playerobj->id].flags |= PLAYER_FLAGS_BLUE_KEY;
2754 Players[playerobj->id].flags |= PLAYER_FLAGS_RED_KEY;
2757 Players[playerobj->id].flags |= PLAYER_FLAGS_GOLD_KEY;
2767 //##void collide_player_and_debris( object * playerobj, object * debris, vms_vector *collision_point ) {
2771 void collide_player_and_clutter( object * playerobj, object * clutter, vms_vector *collision_point ) {
2772 digi_link_sound_to_pos( SOUND_ROBOT_HIT_PLAYER, playerobj->segnum, 0, collision_point, 0, F1_0 );
2773 bump_two_objects(clutter, playerobj, 1);
2777 // See if weapon1 creates a badass explosion. If so, create the explosion
2778 // Return true if weapon does proximity (as opposed to only contact) damage when it explodes.
2779 int maybe_detonate_weapon(object *weapon1, object *weapon2, vms_vector *collision_point)
2781 if ( Weapon_info[weapon1->id].damage_radius ) {
2784 dist = vm_vec_dist_quick(&weapon1->pos, &weapon2->pos);
2785 if (dist < F1_0*5) {
2786 maybe_kill_weapon(weapon1,weapon2);
2787 if (weapon1->flags & OF_SHOULD_BE_DEAD) {
2788 explode_badass_weapon(weapon1,collision_point);
2789 digi_link_sound_to_pos( Weapon_info[weapon1->id].robot_hit_sound, weapon1->segnum , 0, collision_point, 0, F1_0 );
2793 weapon1->lifeleft = min(dist/64, F1_0);
2800 void collide_weapon_and_weapon( object * weapon1, object * weapon2, vms_vector *collision_point )
2802 // -- Does this look buggy??: if (weapon1->id == PMINE_ID && weapon1->id == PMINE_ID)
2803 if (weapon1->id == PMINE_ID && weapon2->id == PMINE_ID)
2804 return; //these can't blow each other up
2806 if (weapon1->id == OMEGA_ID) {
2807 if (!ok_to_do_omega_damage(weapon1))
2809 } else if (weapon2->id == OMEGA_ID) {
2810 if (!ok_to_do_omega_damage(weapon2))
2814 if ((Weapon_info[weapon1->id].destroyable) || (Weapon_info[weapon2->id].destroyable)) {
2816 // Bug reported by Adam Q. Pletcher on September 9, 1994, smart bomb homing missiles were toasting each other.
2817 if ((weapon1->id == weapon2->id) && (weapon1->ctype.laser_info.parent_num == weapon2->ctype.laser_info.parent_num))
2820 if (Weapon_info[weapon1->id].destroyable)
2821 if (maybe_detonate_weapon(weapon1, weapon2, collision_point))
2822 maybe_detonate_weapon(weapon2,weapon1, collision_point);
2824 if (Weapon_info[weapon2->id].destroyable)
2825 if (maybe_detonate_weapon(weapon2, weapon1, collision_point))
2826 maybe_detonate_weapon(weapon1,weapon2, collision_point);
2832 //##void collide_weapon_and_camera( object * weapon, object * camera, vms_vector *collision_point ) {
2836 //##void collide_weapon_and_powerup( object * weapon, object * powerup, vms_vector *collision_point ) {
2840 void collide_weapon_and_debris( object * weapon, object * debris, vms_vector *collision_point ) {
2842 // Hack! Prevent debris from causing bombs spewed at player death to detonate!
2843 if ((weapon->id == PROXIMITY_ID) || (weapon->id == SUPERPROX_ID)) {
2844 if (weapon->ctype.laser_info.creation_time + F1_0/2 > GameTime)
2848 if ( (weapon->ctype.laser_info.parent_type==OBJ_PLAYER) && !(debris->flags & OF_EXPLODING) ) {
2849 digi_link_sound_to_pos( SOUND_ROBOT_HIT, weapon->segnum , 0, collision_point, 0, F1_0 );
2851 explode_object(debris,0);
2852 if ( Weapon_info[weapon->id].damage_radius )
2853 explode_badass_weapon(weapon,collision_point);
2854 maybe_kill_weapon(weapon,debris);
2855 weapon->flags |= OF_SHOULD_BE_DEAD;
2860 //##void collide_camera_and_camera( object * camera1, object * camera2, vms_vector *collision_point ) {
2864 //##void collide_camera_and_powerup( object * camera, object * powerup, vms_vector *collision_point ) {
2868 //##void collide_camera_and_debris( object * camera, object * debris, vms_vector *collision_point ) {
2872 //##void collide_powerup_and_powerup( object * powerup1, object * powerup2, vms_vector *collision_point ) {
2876 //##void collide_powerup_and_debris( object * powerup, object * debris, vms_vector *collision_point ) {
2880 //##void collide_debris_and_debris( object * debris1, object * debris2, vms_vector *collision_point ) {
2885 /* DPH: Put these macros on one long line to avoid CR/LF problems on linux */
2886 #define COLLISION_OF(a,b) (((a)<<8) + (b))
2888 #define DO_COLLISION(type1,type2,collision_function) case COLLISION_OF( (type1), (type2) ): (collision_function)( (A), (B), collision_point ); break; case COLLISION_OF( (type2), (type1) ): (collision_function)( (B), (A), collision_point ); break;
2890 #define DO_SAME_COLLISION(type1,type2,collision_function) case COLLISION_OF( (type1), (type1) ): (collision_function)( (A), (B), collision_point ); break;
2892 //these next two macros define a case that does nothing
2893 #define NO_COLLISION(type1,type2,collision_function) case COLLISION_OF( (type1), (type2) ): break; case COLLISION_OF( (type2), (type1) ): break;
2895 #define NO_SAME_COLLISION(type1,type2,collision_function) case COLLISION_OF( (type1), (type1) ): break;
2897 /* DPH: These ones are never used so I'm not going to bother */
2899 #define IGNORE_COLLISION(type1,type2,collision_function) \
2900 case COLLISION_OF( (type1), (type2) ): \
2902 case COLLISION_OF( (type2), (type1) ): \
2905 #define ERROR_COLLISION(type1,type2,collision_function) \
2906 case COLLISION_OF( (type1), (type2) ): \
2907 Error( "Error in collision type!" ); \
2909 case COLLISION_OF( (type2), (type1) ): \
2910 Error( "Error in collision type!" ); \
2914 void collide_two_objects( object * A, object * B, vms_vector *collision_point )
2918 collision_type = COLLISION_OF(A->type,B->type);
2920 //mprintf( (0, "Object %d of type %d collided with object %d of type %d\n", A-Objects,A->type, B-Objects, B->type ));
2922 switch( collision_type ) {
2923 NO_SAME_COLLISION( OBJ_FIREBALL, OBJ_FIREBALL, collide_fireball_and_fireball )
2924 DO_SAME_COLLISION( OBJ_ROBOT, OBJ_ROBOT, collide_robot_and_robot )
2925 NO_SAME_COLLISION( OBJ_HOSTAGE, OBJ_HOSTAGE, collide_hostage_and_hostage )
2926 DO_SAME_COLLISION( OBJ_PLAYER, OBJ_PLAYER, collide_player_and_player )
2927 DO_SAME_COLLISION( OBJ_WEAPON, OBJ_WEAPON, collide_weapon_and_weapon )
2928 NO_SAME_COLLISION( OBJ_CAMERA, OBJ_CAMERA, collide_camera_and_camera )
2929 NO_SAME_COLLISION( OBJ_POWERUP, OBJ_POWERUP, collide_powerup_and_powerup )
2930 NO_SAME_COLLISION( OBJ_DEBRIS, OBJ_DEBRIS, collide_debris_and_debris )
2931 NO_SAME_COLLISION( OBJ_MARKER, OBJ_MARKER, NULL )
2932 NO_COLLISION( OBJ_FIREBALL, OBJ_ROBOT, collide_fireball_and_robot )
2933 NO_COLLISION( OBJ_FIREBALL, OBJ_HOSTAGE, collide_fireball_and_hostage )
2934 NO_COLLISION( OBJ_FIREBALL, OBJ_PLAYER, collide_fireball_and_player )
2935 NO_COLLISION( OBJ_FIREBALL, OBJ_WEAPON, collide_fireball_and_weapon )
2936 NO_COLLISION( OBJ_FIREBALL, OBJ_CAMERA, collide_fireball_and_camera )
2937 NO_COLLISION( OBJ_FIREBALL, OBJ_POWERUP, collide_fireball_and_powerup )
2938 NO_COLLISION( OBJ_FIREBALL, OBJ_DEBRIS, collide_fireball_and_debris )
2939 NO_COLLISION( OBJ_ROBOT, OBJ_HOSTAGE, collide_robot_and_hostage )
2940 DO_COLLISION( OBJ_ROBOT, OBJ_PLAYER, collide_robot_and_player )
2941 DO_COLLISION( OBJ_ROBOT, OBJ_WEAPON, collide_robot_and_weapon )
2942 NO_COLLISION( OBJ_ROBOT, OBJ_CAMERA, collide_robot_and_camera )
2943 NO_COLLISION( OBJ_ROBOT, OBJ_POWERUP, collide_robot_and_powerup )
2944 NO_COLLISION( OBJ_ROBOT, OBJ_DEBRIS, collide_robot_and_debris )
2945 DO_COLLISION( OBJ_HOSTAGE, OBJ_PLAYER, collide_hostage_and_player )
2946 NO_COLLISION( OBJ_HOSTAGE, OBJ_WEAPON, collide_hostage_and_weapon )
2947 NO_COLLISION( OBJ_HOSTAGE, OBJ_CAMERA, collide_hostage_and_camera )
2948 NO_COLLISION( OBJ_HOSTAGE, OBJ_POWERUP, collide_hostage_and_powerup )
2949 NO_COLLISION( OBJ_HOSTAGE, OBJ_DEBRIS, collide_hostage_and_debris )
2950 DO_COLLISION( OBJ_PLAYER, OBJ_WEAPON, collide_player_and_weapon )
2951 NO_COLLISION( OBJ_PLAYER, OBJ_CAMERA, collide_player_and_camera )
2952 DO_COLLISION( OBJ_PLAYER, OBJ_POWERUP, collide_player_and_powerup )
2953 NO_COLLISION( OBJ_PLAYER, OBJ_DEBRIS, collide_player_and_debris )
2954 DO_COLLISION( OBJ_PLAYER, OBJ_CNTRLCEN, collide_player_and_controlcen )
2955 DO_COLLISION( OBJ_PLAYER, OBJ_CLUTTER, collide_player_and_clutter )
2956 NO_COLLISION( OBJ_WEAPON, OBJ_CAMERA, collide_weapon_and_camera )
2957 NO_COLLISION( OBJ_WEAPON, OBJ_POWERUP, collide_weapon_and_powerup )
2958 DO_COLLISION( OBJ_WEAPON, OBJ_DEBRIS, collide_weapon_and_debris )
2959 NO_COLLISION( OBJ_CAMERA, OBJ_POWERUP, collide_camera_and_powerup )
2960 NO_COLLISION( OBJ_CAMERA, OBJ_DEBRIS, collide_camera_and_debris )
2961 NO_COLLISION( OBJ_POWERUP, OBJ_DEBRIS, collide_powerup_and_debris )
2962 DO_COLLISION( OBJ_WEAPON, OBJ_CNTRLCEN, collide_weapon_and_controlcen )
2963 DO_COLLISION( OBJ_ROBOT, OBJ_CNTRLCEN, collide_robot_and_controlcen )
2964 DO_COLLISION( OBJ_WEAPON, OBJ_CLUTTER, collide_weapon_and_clutter )
2966 DO_COLLISION( OBJ_MARKER, OBJ_PLAYER, collide_player_and_marker)
2967 NO_COLLISION( OBJ_MARKER, OBJ_ROBOT, NULL)
2968 NO_COLLISION( OBJ_MARKER, OBJ_HOSTAGE, NULL)
2969 NO_COLLISION( OBJ_MARKER, OBJ_WEAPON, NULL)
2970 NO_COLLISION( OBJ_MARKER, OBJ_CAMERA, NULL)
2971 NO_COLLISION( OBJ_MARKER, OBJ_POWERUP, NULL)
2972 NO_COLLISION( OBJ_MARKER, OBJ_DEBRIS, NULL)
2975 Int3(); //Error( "Unhandled collision_type in collide.c!\n" );
2979 #define ENABLE_COLLISION(type1,type2) \
2980 CollisionResult[type1][type2] = RESULT_CHECK; \
2981 CollisionResult[type2][type1] = RESULT_CHECK;
2983 #define DISABLE_COLLISION(type1,type2) \
2984 CollisionResult[type1][type2] = RESULT_NOTHING; \
2985 CollisionResult[type2][type1] = RESULT_NOTHING;
2987 void collide_init() {
2990 for (i=0; i < MAX_OBJECT_TYPES; i++ )
2991 for (j=0; j < MAX_OBJECT_TYPES; j++ )
2992 CollisionResult[i][j] = RESULT_NOTHING;
2994 ENABLE_COLLISION( OBJ_WALL, OBJ_ROBOT );
2995 ENABLE_COLLISION( OBJ_WALL, OBJ_WEAPON );
2996 ENABLE_COLLISION( OBJ_WALL, OBJ_PLAYER );
2997 DISABLE_COLLISION( OBJ_FIREBALL, OBJ_FIREBALL );
2999 ENABLE_COLLISION( OBJ_ROBOT, OBJ_ROBOT );
3000 // DISABLE_COLLISION( OBJ_ROBOT, OBJ_ROBOT ); // ALERT: WARNING: HACK: MK = RESPONSIBLE! TESTING!!
3002 DISABLE_COLLISION( OBJ_HOSTAGE, OBJ_HOSTAGE );
3003 ENABLE_COLLISION( OBJ_PLAYER, OBJ_PLAYER );
3004 ENABLE_COLLISION( OBJ_WEAPON, OBJ_WEAPON );
3005 DISABLE_COLLISION( OBJ_CAMERA, OBJ_CAMERA );
3006 DISABLE_COLLISION( OBJ_POWERUP, OBJ_POWERUP );
3007 DISABLE_COLLISION( OBJ_DEBRIS, OBJ_DEBRIS );
3008 DISABLE_COLLISION( OBJ_FIREBALL, OBJ_ROBOT );
3009 DISABLE_COLLISION( OBJ_FIREBALL, OBJ_HOSTAGE );
3010 DISABLE_COLLISION( OBJ_FIREBALL, OBJ_PLAYER );
3011 DISABLE_COLLISION( OBJ_FIREBALL, OBJ_WEAPON );
3012 DISABLE_COLLISION( OBJ_FIREBALL, OBJ_CAMERA );
3013 DISABLE_COLLISION( OBJ_FIREBALL, OBJ_POWERUP );
3014 DISABLE_COLLISION( OBJ_FIREBALL, OBJ_DEBRIS );
3015 DISABLE_COLLISION( OBJ_ROBOT, OBJ_HOSTAGE );
3016 ENABLE_COLLISION( OBJ_ROBOT, OBJ_PLAYER );
3017 ENABLE_COLLISION( OBJ_ROBOT, OBJ_WEAPON );
3018 DISABLE_COLLISION( OBJ_ROBOT, OBJ_CAMERA );
3019 DISABLE_COLLISION( OBJ_ROBOT, OBJ_POWERUP );
3020 DISABLE_COLLISION( OBJ_ROBOT, OBJ_DEBRIS );
3021 ENABLE_COLLISION( OBJ_HOSTAGE, OBJ_PLAYER );
3022 ENABLE_COLLISION( OBJ_HOSTAGE, OBJ_WEAPON );
3023 DISABLE_COLLISION( OBJ_HOSTAGE, OBJ_CAMERA );
3024 DISABLE_COLLISION( OBJ_HOSTAGE, OBJ_POWERUP );
3025 DISABLE_COLLISION( OBJ_HOSTAGE, OBJ_DEBRIS );
3026 ENABLE_COLLISION( OBJ_PLAYER, OBJ_WEAPON );
3027 DISABLE_COLLISION( OBJ_PLAYER, OBJ_CAMERA );
3028 ENABLE_COLLISION( OBJ_PLAYER, OBJ_POWERUP );
3029 DISABLE_COLLISION( OBJ_PLAYER, OBJ_DEBRIS );
3030 DISABLE_COLLISION( OBJ_WEAPON, OBJ_CAMERA );
3031 DISABLE_COLLISION( OBJ_WEAPON, OBJ_POWERUP );
3032 ENABLE_COLLISION( OBJ_WEAPON, OBJ_DEBRIS );
3033 DISABLE_COLLISION( OBJ_CAMERA, OBJ_POWERUP );
3034 DISABLE_COLLISION( OBJ_CAMERA, OBJ_DEBRIS );
3035 DISABLE_COLLISION( OBJ_POWERUP, OBJ_DEBRIS );
3036 ENABLE_COLLISION( OBJ_POWERUP, OBJ_WALL );
3037 ENABLE_COLLISION( OBJ_WEAPON, OBJ_CNTRLCEN )
3038 ENABLE_COLLISION( OBJ_WEAPON, OBJ_CLUTTER )
3039 ENABLE_COLLISION( OBJ_PLAYER, OBJ_CNTRLCEN )
3040 ENABLE_COLLISION( OBJ_ROBOT, OBJ_CNTRLCEN )
3041 ENABLE_COLLISION( OBJ_PLAYER, OBJ_CLUTTER )
3043 ENABLE_COLLISION( OBJ_PLAYER, OBJ_MARKER );
3047 void collide_object_with_wall( object * A, fix hitspeed, short hitseg, short hitwall, vms_vector * hitpt )
3052 Error( "A object of type NONE hit a wall!\n");
3054 case OBJ_PLAYER: collide_player_and_wall(A,hitspeed,hitseg,hitwall,hitpt); break;
3055 case OBJ_WEAPON: collide_weapon_and_wall(A,hitspeed,hitseg,hitwall,hitpt); break;
3056 case OBJ_DEBRIS: collide_debris_and_wall(A,hitspeed,hitseg,hitwall,hitpt); break;
3058 case OBJ_FIREBALL: break; //collide_fireball_and_wall(A,hitspeed,hitseg,hitwall,hitpt);
3059 case OBJ_ROBOT: collide_robot_and_wall(A,hitspeed,hitseg,hitwall,hitpt); break;
3060 case OBJ_HOSTAGE: break; //collide_hostage_and_wall(A,hitspeed,hitseg,hitwall,hitpt);
3061 case OBJ_CAMERA: break; //collide_camera_and_wall(A,hitspeed,hitseg,hitwall,hitpt);
3062 case OBJ_POWERUP: break; //collide_powerup_and_wall(A,hitspeed,hitseg,hitwall,hitpt);
3063 case OBJ_GHOST: break; //do nothing
3066 Error( "Unhandled object type hit wall in collide.c\n" );