FS2_Open
Open source remastering of the Freespace 2 engine
collideshipweapon.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 #include "hud/hudshield.h"
13 #include "hud/hudwingmanstatus.h"
14 #include "io/timer.h"
15 #include "network/multi.h"
16 #include "network/multimsgs.h"
17 #include "network/multiutil.h"
18 #include "object/objcollide.h"
19 #include "object/object.h"
20 #include "parse/scripting.h"
21 #include "playerman/player.h"
22 #include "ship/ship.h"
23 #include "ship/shipfx.h"
24 #include "ship/shiphit.h"
25 #include "weapon/weapon.h"
26 
27 
28 extern float ai_endangered_time(object *ship_objp, object *weapon_objp);
29 int check_inside_radius_for_big_ships( object *ship, object *weapon_obj, obj_pair *pair );
30 float estimate_ship_speed_upper_limit( object *ship, float time );
31 extern float flFrametime;
32 
33 
38 void update_danger_weapon(object *pship_obj, object *weapon_obj)
39 {
40  ai_info *aip;
41 
42  Assert(pship_obj->type == OBJ_SHIP);
43 
44  aip = &Ai_info[Ships[pship_obj->instance].ai_index];
45 
46  if (aip->danger_weapon_objnum == -1) {
47  aip->danger_weapon_objnum = weapon_obj-Objects;
48  aip->danger_weapon_signature = weapon_obj->signature;
50  float danger_old_time, danger_new_time;
51 
52  danger_old_time = ai_endangered_time(pship_obj, &Objects[aip->danger_weapon_objnum]);
53  danger_new_time = ai_endangered_time(pship_obj, weapon_obj);
54 
55  if (danger_new_time < danger_old_time) {
56  aip->danger_weapon_objnum = weapon_obj-Objects;
57  aip->danger_weapon_signature = weapon_obj->signature;
58  }
59  }
60 }
61 
66 void ship_weapon_do_hit_stuff(object *pship_obj, object *weapon_obj, vec3d *world_hitpos, vec3d *hitpos, int quadrant_num, int submodel_num, vec3d /*not a pointer intentionaly*/ hit_dir)
67 {
68  weapon *wp = &Weapons[weapon_obj->instance];
70  ship *shipp = &Ships[pship_obj->instance];
71  float damage;
72  vec3d force;
73 
74  // Apply hit & damage & stuff to weapon
75  weapon_hit(weapon_obj, pship_obj, world_hitpos, quadrant_num);
76 
77  if (wip->damage_time >= 0.0f && wp->lifeleft <= wip->damage_time) {
78  if (wip->atten_damage >= 0.0f) {
79  damage = (((wip->damage - wip->atten_damage) * (wp->lifeleft / wip->damage_time)) + wip->atten_damage);
80  } else {
81  damage = wip->damage * (wp->lifeleft / wip->damage_time);
82  }
83  } else {
84  damage = wip->damage;
85  }
86 
87  // deterine whack whack
88  float blast = wip->mass;
89  vm_vec_copy_scale(&force, &weapon_obj->phys_info.vel, blast );
90 
91  // send player pain packet
92  if ( (MULTIPLAYER_MASTER) && !(shipp->flags & SF_DYING) ){
93  int np_index = multi_find_player_by_object(pship_obj);
94 
95  // if this is a player ship
96  if((np_index >= 0) && (np_index != MY_NET_PLAYER_NUM) && (wip->subtype == WP_LASER)){
97  send_player_pain_packet(&Net_players[np_index], wp->weapon_info_index, wip->damage * weapon_get_damage_scale(wip, weapon_obj, pship_obj), &force, hitpos, quadrant_num);
98  }
99  }
100 
101  ship_apply_local_damage(pship_obj, weapon_obj, world_hitpos, damage, quadrant_num, CREATE_SPARKS, submodel_num);
102 
103  // let the hud shield gauge know when Player or Player target is hit
104  hud_shield_quadrant_hit(pship_obj, quadrant_num);
105 
106  // Let wingman status gauge know a wingman ship was hit
107  if ( (Ships[pship_obj->instance].wing_status_wing_index >= 0) && ((Ships[pship_obj->instance].wing_status_wing_pos >= 0)) ) {
109  }
110 
111  // Apply a wack. This used to be inside of ship_hit... duh! Ship_hit
112  // is to apply damage, not physics, so I moved it here.
113  // don't apply whack for multiplayer_client from laser - will occur with pain packet
114  if (!((wip->subtype == WP_LASER) && MULTIPLAYER_CLIENT) ) {
115  // apply a whack
116  ship_apply_whack( &force, hitpos, pship_obj );
117  }
118 
119 }
120 
121 extern int Framecount;
122 
123 int ship_weapon_check_collision(object *ship_objp, object *weapon_objp, float time_limit = 0.0f, int *next_hit = NULL)
124 {
125  mc_info mc, mc_shield, mc_hull;
126  ship *shipp;
127  ship_info *sip;
128  weapon *wp;
129  weapon_info *wip;
130 
131  Assert( ship_objp != NULL );
132  Assert( ship_objp->type == OBJ_SHIP );
133  Assert( ship_objp->instance >= 0 );
134 
135  shipp = &Ships[ship_objp->instance];
136  sip = &Ship_info[shipp->ship_info_index];
137 
138  Assert( weapon_objp != NULL );
139  Assert( weapon_objp->type == OBJ_WEAPON );
140  Assert( weapon_objp->instance >= 0 );
141 
142  wp = &Weapons[weapon_objp->instance];
143  wip = &Weapon_info[wp->weapon_info_index];
144 
145 
146  Assert( shipp->objnum == OBJ_INDEX(ship_objp));
147 
148  // Make ships that are warping in not get collision detection done
149  if ( shipp->flags & SF_ARRIVING ) return 0;
150 
151  // Return information for AI to detect incoming fire.
152  // Could perhaps be done elsewhere at lower cost --MK, 11/7/97
153  float dist = vm_vec_dist_quick(&ship_objp->pos, &weapon_objp->pos);
154  if (dist < weapon_objp->phys_info.speed) {
155  update_danger_weapon(ship_objp, weapon_objp);
156  }
157 
158  int valid_hit_occurred = 0; // If this is set, then hitpos is set
159  int quadrant_num = -1;
160  polymodel *pm = model_get(sip->model_num);
161 
162  // total time is flFrametime + time_limit (time_limit used to predict collisions into the future)
163  vec3d weapon_end_pos;
164  vm_vec_scale_add( &weapon_end_pos, &weapon_objp->pos, &weapon_objp->phys_info.vel, time_limit );
165 
166 
167  // Goober5000 - I tried to make collision code here much saner... here begin the (major) changes
168  mc_info_init(&mc);
169 
170  // set up collision structs
172  mc.model_num = sip->model_num;
173  mc.submodel_num = -1;
174  mc.orient = &ship_objp->orient;
175  mc.pos = &ship_objp->pos;
176  mc.p0 = &weapon_objp->last_pos;
177  mc.p1 = &weapon_end_pos;
178  mc.lod = sip->collision_lod;
179  memcpy(&mc_shield, &mc, sizeof(mc_info));
180  memcpy(&mc_hull, &mc, sizeof(mc_info));
181 
182  // (btw, these are leftover comments from below...)
183  //
184  // Note: This code is obviously stupid. We want to add the shield point if there is shield to hit, but:
185  // 1. We want the size/color of the hit effect to indicate shield damage done. (i.e., for already-weak shield, smaller effect)
186  // 2. Currently (8/9/97), apply_damage_to_shield() passes lefer damage to hull, which might not make sense. If
187  // wouldn't have collided with hull, shouldn't do damage. Once this is fixed, the code below needs to cast the
188  // vector through to the hull if there is leftover damage.
189  //
190  // WIF2_PIERCE_SHIELDS pierces shields
191  // AL 1-14-97: "Puncture" doesn't mean penetrate shield anymore, it means that it punctures
192  // hull to inflict maximum subsystem damage
193  //
194  // _argv[-1], 16 Jan 2005: Surface shields.
195  // Surface shields allow for shields on a ship without a shield mesh. Good for putting real shields
196  // on the Lucifer. This also fixes the strange bug where shots will occasionally go through the
197  // shield mesh when they shouldn't. I don't know what causes this, but this fixes that -- shields
198  // will absorb it when it hits the hull instead. This has no fancy graphical effect, though.
199  // Someone should make one.
200 
201  // check both kinds of collisions
202  int shield_collision = 0;
203  int hull_collision = 0;
204 
205  // check shields for impact
206  if (!(ship_objp->flags & OF_NO_SHIELDS)) {
207  if (sip->flags2 & SIF2_AUTO_SPREAD_SHIELDS) {
208  // The weapon is not allowed to impact the shield before it reaches this point
209  vec3d shield_ignored_until = weapon_objp->last_pos;
210 
211  float weapon_flown_for = vm_vec_dist(&wp->start_pos, &weapon_objp->last_pos);
212  float min_weapon_span;
213 
214  if (sip->auto_shield_spread_min_span >= 0.0f) {
215  min_weapon_span = sip->auto_shield_spread_min_span;
216  } else {
217  min_weapon_span = sip->auto_shield_spread;
218  }
219 
220  // If weapon hasn't yet flown a distance greater than the maximum ignore
221  // range, then some part of the currently checked range needs to be
222  // ignored
223  if (weapon_flown_for < min_weapon_span) {
224  vm_vec_sub(&shield_ignored_until, &weapon_end_pos, &wp->start_pos);
225  vm_vec_normalize(&shield_ignored_until);
226  vm_vec_scale(&shield_ignored_until, min_weapon_span);
227  vm_vec_add2(&shield_ignored_until, &wp->start_pos);
228  }
229 
230  float this_range = vm_vec_dist(&weapon_objp->last_pos, &weapon_end_pos);
231 
232  // The range during which the weapon is not allowed to collide with the
233  // shield, except if it actually hits the hull
234  float ignored_range;
235 
236  // If the weapon has not yet surpassed the ignore range, calculate the
237  // remaining ignore range
238  if (vm_vec_dist(&wp->start_pos, &shield_ignored_until) > weapon_flown_for)
239  ignored_range = vm_vec_dist(&weapon_objp->last_pos, &shield_ignored_until);
240  else
241  ignored_range = 0.0f;
242 
243  // The range during which the weapon may impact the shield
244  float active_range = this_range - ignored_range;
245 
246  // During the ignored range, we only check for a ray collision with
247  // the model
248  if (ignored_range > 0.0f) {
249  mc_shield.flags = MC_CHECK_MODEL;
250  mc_shield.p1 = &shield_ignored_until;
251 
252  shield_collision = model_collide(&mc_shield);
253 
254  mc_shield.p1 = &weapon_end_pos;
255  mc_shield.hit_dist = mc_shield.hit_dist * (ignored_range / this_range);
256  }
257 
258  // If no collision with the model found in the ignore range, only
259  // then do we check for sphereline collisions with the model during the
260  // non-ignored range
261  if (!shield_collision && weapon_flown_for + this_range > min_weapon_span) {
262  mc_shield.p0 = &shield_ignored_until;
263 
264  mc_shield.p1 = &weapon_end_pos;
265 
266  mc_shield.radius = sip->auto_shield_spread;
267 
268  if (sip->auto_shield_spread_from_lod > -1) {
269  mc_shield.lod = sip->auto_shield_spread_from_lod;
270  }
271 
273 
274  shield_collision = model_collide(&mc_shield);
275 
276  mc_shield.lod = sip->collision_lod;
277  mc_shield.submodel_num = -1;
278 
279  // Because we manipulated p0 and p1 above, hit_dist will be
280  // relative to the values we used, not the values the rest of
281  // the code expects; this fixes that
282  mc_shield.p0 = &weapon_objp->last_pos;
283  mc_shield.p1 = &weapon_end_pos;
284  mc_shield.hit_dist = (ignored_range + (active_range * mc_shield.hit_dist)) / this_range;
285  }
286 
287  if (shield_collision) {
288  // If we used a sphereline check, then the collision point will lie
289  // somewhere on the ship's hull; this re-positions it to lie on the
290  // correct point along the weapon's path
291  if (mc_shield.flags & MC_CHECK_SPHERELINE) {
292  vec3d tempv;
293  vm_vec_sub(&tempv, mc_shield.p1, mc_shield.p0);
294  vm_vec_scale(&tempv, mc_shield.hit_dist);
295  vm_vec_add2(&tempv, mc_shield.p0);
296  mc_shield.hit_point_world = tempv;
297  }
298 
299  // Re-calculate hit_point because it's likely pointing to the wrong
300  // place
301  vec3d tempv;
302  vm_vec_sub(&tempv, &mc_shield.hit_point_world, &ship_objp->pos);
303  vm_vec_rotate(&mc_shield.hit_point, &tempv, &ship_objp->orient);
304  }
305  } else if (sip->flags2 & SIF2_SURFACE_SHIELDS) {
306  if (pm->shield.ntris > 0) {
307  // If there is a shield mesh, we need to check that first
308  mc_shield.flags = MC_CHECK_SHIELD;
309  shield_collision = model_collide(&mc_shield);
310  }
311 
312  if (!shield_collision) {
313  // But if no shield mesh or it was missed, check for a hull collision
314  mc_shield.flags = MC_CHECK_MODEL;
315  shield_collision = model_collide(&mc_shield);
316 
317  // Because we used MC_CHECK_MODEL, the returned hit position might be
318  // in a submodel's frame of reference, so we need to ensure we end up
319  // in the ship's frame of reference
320  vec3d local_pos;
321  vm_vec_sub(&local_pos, &mc_shield.hit_point_world, &ship_objp->pos);
322  vm_vec_rotate(&mc_shield.hit_point, &local_pos, &ship_objp->orient);
323  }
324  } else {
325  // Normal collision check against a shield mesh
326  mc_shield.flags = MC_CHECK_SHIELD;
327  shield_collision = (pm->shield.ntris > 0) ? model_collide(&mc_shield) : 0;
328  }
329  }
330 
331  // If we found a shield collision but were only checking for a simple model
332  // collision, we can re-use the same collision info for the hull as well
333  if (shield_collision && mc_shield.flags == MC_CHECK_MODEL) {
334  memcpy(&mc_hull, &mc_shield, sizeof(mc_info));
335  hull_collision = shield_collision;
336 
337  // The weapon has impacted on the hull, so if it should therefore bypass
338  // the shields altogether, we do it here
339  if (sip->auto_shield_spread_bypass) {
340  shield_collision = 0;
341  }
342  } else {
343  mc_hull.flags = MC_CHECK_MODEL;
344  hull_collision = model_collide(&mc_hull);
345  }
346 
347  if (shield_collision) {
348  // pick out the shield quadrant
349  quadrant_num = get_quadrant(&mc_shield.hit_point, ship_objp);
350 
351  // make sure that the shield is active in that quadrant
352  if (shipp->flags & SF_DYING || !ship_is_shield_up(ship_objp, quadrant_num))
353  quadrant_num = -1;
354 
355  // see if we hit the shield
356  if (quadrant_num >= 0) {
357  // do the hit effect
358  if (mc_shield.shield_hit_tri != -1) {
359  add_shield_point(OBJ_INDEX(ship_objp), mc_shield.shield_hit_tri, &mc_shield.hit_point);
360  }
361 
362  // if this weapon pierces the shield, then do the hit effect, but act like a shield collision never occurred;
363  // otherwise, we have a valid hit on this shield
364  if (wip->wi_flags2 & WIF2_PIERCE_SHIELDS)
365  quadrant_num = -1;
366  else
367  valid_hit_occurred = 1;
368  }
369  }
370 
371  // see which impact we use
372  if (shield_collision && valid_hit_occurred)
373  {
374  memcpy(&mc, &mc_shield, sizeof(mc_info));
375  Assert(quadrant_num >= 0);
376  }
377  else if (hull_collision)
378  {
379  memcpy(&mc, &mc_hull, sizeof(mc_info));
380  valid_hit_occurred = 1;
381  }
382 
383  // check if the hit point is beyond the clip plane when warping out.
384  if ((shipp->flags & SF_DEPART_WARP) &&
385  (shipp->warpout_effect) &&
386  (valid_hit_occurred))
387  {
388  vec3d warp_pnt, hit_direction;
389  matrix warp_orient;
390 
391  shipp->warpout_effect->getWarpPosition(&warp_pnt);
392  shipp->warpout_effect->getWarpOrientation(&warp_orient);
393 
394  vm_vec_sub(&hit_direction, &mc.hit_point_world, &warp_pnt);
395 
396  if (vm_vec_dot(&hit_direction, &warp_orient.vec.fvec) < 0.0f)
397  {
398  valid_hit_occurred = 0;
399  }
400  }
401 
402  // deal with predictive collisions. Find their actual hit time and see if they occured in current frame
403  if (next_hit && valid_hit_occurred) {
404  // find hit time
405  *next_hit = (int) (1000.0f * (mc.hit_dist*(flFrametime + time_limit) - flFrametime) );
406  if (*next_hit > 0)
407  // if hit occurs outside of this frame, do not do damage
408  return 1;
409  }
410 
411  if ( valid_hit_occurred )
412  {
413  wp->collisionOccured = true;
414  memcpy(&wp->collisionInfo, &mc, sizeof(mc_info));
415 
416  Script_system.SetHookObjects(4, "Ship", ship_objp, "Weapon", weapon_objp, "Self",ship_objp, "Object", weapon_objp);
417  bool ship_override = Script_system.IsConditionOverride(CHA_COLLIDEWEAPON, ship_objp);
418 
419  Script_system.SetHookObjects(2, "Self",weapon_objp, "Object", ship_objp);
420  bool weapon_override = Script_system.IsConditionOverride(CHA_COLLIDESHIP, weapon_objp);
421 
422  if(!ship_override && !weapon_override) {
423  if (shield_collision && quadrant_num >= 0) {
424  if ((sip->shield_impact_explosion_anim > -1) && (wip->shield_impact_explosion_radius > 0)) {
426  }
427  }
428  ship_weapon_do_hit_stuff(ship_objp, weapon_objp, &mc.hit_point_world, &mc.hit_point, quadrant_num, mc.hit_submodel, mc.hit_normal);
429  }
430 
431  Script_system.SetHookObjects(2, "Self",ship_objp, "Object", weapon_objp);
432  if(!(weapon_override && !ship_override))
433  Script_system.RunCondition(CHA_COLLIDEWEAPON, '\0', NULL, ship_objp, wp->weapon_info_index);
434 
435  Script_system.SetHookObjects(2, "Self",weapon_objp, "Object", ship_objp);
436  if((weapon_override && !ship_override) || (!weapon_override && !ship_override))
437  Script_system.RunCondition(CHA_COLLIDESHIP, '\0', NULL, weapon_objp);
438 
439  Script_system.RemHookVars(4, "Ship", "Weapon", "Self","Object");
440  }
441  else if ((Missiontime - wp->creation_time > F1_0/2) && (wip->wi_flags & WIF_HOMING) && (wp->homing_object == ship_objp)) {
442  if (dist < wip->shockwave.inner_rad) {
443  vec3d vec_to_ship;
444 
445  vm_vec_normalized_dir(&vec_to_ship, &ship_objp->pos, &weapon_objp->pos);
446 
447  if (vm_vec_dot(&vec_to_ship, &weapon_objp->orient.vec.fvec) < 0.0f) {
448  // check if we're colliding against "invisible" ship
449  if (!(shipp->flags2 & SF2_DONT_COLLIDE_INVIS)) {
450  wp->lifeleft = 0.001f;
451  if (ship_objp == Player_obj)
452  nprintf(("Jim", "Frame %i: Weapon " PTRDIFF_T_ARG " set to detonate, dist = %7.3f.\n", Framecount, OBJ_INDEX(weapon_objp), dist));
453  valid_hit_occurred = 1;
454  }
455  }
456 
457  }
458  }
459 
460  return valid_hit_occurred;
461 }
462 
463 
470 {
471  int did_hit;
472  object *ship = pair->a;
473  object *weapon_obj = pair->b;
474 
475  Assert( ship->type == OBJ_SHIP );
476  Assert( weapon_obj->type == OBJ_WEAPON );
477 
479 
480  // Don't check collisions for player if past first warpout stage.
482  if ( ship == Player_obj )
483  return 0;
484  }
485 
486  if (reject_due_collision_groups(ship, weapon_obj))
487  return 0;
488 
489  // Cull lasers within big ship spheres by casting a vector forward for (1) exit sphere or (2) lifetime of laser
490  // If it does hit, don't check the pair until about 200 ms before collision.
491  // If it does not hit and is within error tolerance, cull the pair.
492 
493  if ( (sip->flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)) && (Weapon_info[Weapons[weapon_obj->instance].weapon_info_index].subtype == WP_LASER) ) {
494  // Check when within ~1.1 radii.
495  // This allows good transition between sphere checking (leaving the laser about 200 ms from radius) and checking
496  // within the sphere with little time between. There may be some time for "small" big ships
497  // Note: culling ships with auto spread shields seems to waste more performance than it saves,
498  // so we're not doing that here
499  if ( !(sip->flags2 & SIF2_AUTO_SPREAD_SHIELDS) && vm_vec_dist_squared(&ship->pos, &weapon_obj->pos) < (1.2f*ship->radius*ship->radius) ) {
500  return check_inside_radius_for_big_ships( ship, weapon_obj, pair );
501  }
502  }
503 
504  did_hit = ship_weapon_check_collision( ship, weapon_obj );
505 
506  if ( !did_hit ) {
507  // Since we didn't hit, check to see if we can disable all future collisions
508  // between these two.
509  return weapon_will_never_hit( weapon_obj, ship, pair );
510  }
511 
512  return 0;
513 }
514 
518 float estimate_ship_speed_upper_limit( object *ship, float time )
519 {
520  float exponent;
521  float delta_v;
522  float factor;
523 
524  delta_v = Ship_info[Ships[ship->instance].ship_info_index].max_vel.xyz.z - ship->phys_info.speed;
525 
526  if (ship->phys_info.forward_accel_time_const == 0) {
527  return ship->phys_info.speed;
528  }
529 
530  exponent = time / ship->phys_info.forward_accel_time_const;
531 
532  factor = 1.0f - (float)exp( -exponent );
533  return ship->phys_info.speed + factor*delta_v;
534 }
535 
536 // maximum error allowed in detecting collisions between laser and big ship inside the radius
537 // this is set for a 150 m radius ship. For ships with larger radius, the error scales according
538 // to the ration of radii, but is never less than 2 m
539 #define ERROR_STD 2
540 
546 int check_inside_radius_for_big_ships( object *ship, object *weapon_obj, obj_pair *pair )
547 {
548  vec3d error_vel; // vel perpendicular to laser
549  float error_vel_mag; // magnitude of error_vel
550  float time_to_max_error, time_to_exit_sphere;
551  float ship_speed_at_exit_sphere, error_at_exit_sphere;
552  float max_error = (float) ERROR_STD / 150.0f * ship->radius;
553  if (max_error < 2)
554  max_error = 2.0f;
555 
556  time_to_exit_sphere = (ship->radius + vm_vec_dist(&ship->pos, &weapon_obj->pos)) / (weapon_obj->phys_info.max_vel.xyz.z - ship->phys_info.max_vel.xyz.z);
557  ship_speed_at_exit_sphere = estimate_ship_speed_upper_limit( ship, time_to_exit_sphere );
558  // update estimated time to exit sphere
559  time_to_exit_sphere = (ship->radius + vm_vec_dist(&ship->pos, &weapon_obj->pos)) / (weapon_obj->phys_info.max_vel.xyz.z - ship_speed_at_exit_sphere);
560  vm_vec_scale_add( &error_vel, &ship->phys_info.vel, &weapon_obj->orient.vec.fvec, -vm_vec_dot(&ship->phys_info.vel, &weapon_obj->orient.vec.fvec) );
561  error_vel_mag = vm_vec_mag_quick( &error_vel );
562  error_vel_mag += 0.5f * (ship->phys_info.max_vel.xyz.z - error_vel_mag)*(time_to_exit_sphere/ship->phys_info.forward_accel_time_const);
563  // error_vel_mag is now average velocity over period
564  error_at_exit_sphere = error_vel_mag * time_to_exit_sphere;
565  time_to_max_error = max_error / error_at_exit_sphere * time_to_exit_sphere;
566 
567  // find the minimum time we can safely check into the future.
568  // limited by (1) time to exit sphere (2) time to weapon expires
569  // if ship_weapon_check_collision comes back with a hit_time > error limit, ok
570  // if ship_weapon_check_collision comes finds no collision, next check time based on error time
571  float limit_time; // furthest time to check (either lifetime or exit sphere)
572  if ( time_to_exit_sphere < Weapons[weapon_obj->instance].lifeleft ) {
573  limit_time = time_to_exit_sphere;
574  } else {
575  limit_time = Weapons[weapon_obj->instance].lifeleft;
576  }
577 
578  // Note: when estimated hit time is less than 200 ms, look at every frame
579  int hit_time; // estimated time of hit in ms
580 
581  // modify ship_weapon_check_collision to do damage if hit_time is negative (ie, hit occurs in this frame)
582  if ( ship_weapon_check_collision( ship, weapon_obj, limit_time, &hit_time ) ) {
583  // hit occured in while in sphere
584  if (hit_time < 0) {
585  // hit occured in the frame
586  return 1;
587  } else if (hit_time > 200) {
588  pair->next_check_time = timestamp(hit_time - 200);
589  return 0;
590  // set next check time to time - 200
591  } else {
592  // set next check time to next frame
593  pair->next_check_time = 1;
594  return 0;
595  }
596  } else {
597  if (limit_time > time_to_max_error) {
598  // no hit, but beyond error tolerance
599  if (1000*time_to_max_error > 200) {
600  pair->next_check_time = timestamp( (int)(1000*time_to_max_error) - 200 );
601  } else {
602  pair->next_check_time = 1;
603  }
604  return 0;
605  } else {
606  // no hit and within error tolerance
607  return 1;
608  }
609  }
610 }
void mc_info_init(mc_info *mc)
Definition: model.h:1138
int model_collide(mc_info *mc_info_obj)
int timestamp(int delta_ms)
Definition: timer.cpp:226
#define SIF2_SURFACE_SHIELDS
Definition: ship.h:922
#define MULTIPLAYER_CLIENT
Definition: multi.h:132
#define MY_NET_PLAYER_NUM
Definition: multi.h:127
fix creation_time
Definition: weapon.h:175
fix Missiontime
Definition: systemvars.cpp:19
char wing_status_wing_pos
Definition: ship.h:553
weapon Weapons[MAX_WEAPONS]
Definition: weapons.cpp:78
vec3d hit_point
Definition: model.h:1123
#define SF_DEPART_WARP
Definition: ship.h:449
vec3d * pos
Definition: model.h:1113
int shield_hit_tri
Definition: model.h:1128
float vm_vec_mag_quick(const vec3d *v)
Definition: vecmat.cpp:371
#define PCM_WARPOUT_STAGE1
Definition: player.h:59
object * homing_object
Definition: weapon.h:177
int objnum
Definition: ship.h:537
#define F1_0
Definition: fix.h:15
void vm_vec_scale_add(vec3d *dest, const vec3d *src1, const vec3d *src2, float k)
Definition: vecmat.cpp:266
int Framecount
Definition: systemvars.cpp:22
polymodel * model_get(int model_num)
Definition: modelread.cpp:3134
weapon_info Weapon_info[MAX_WEAPON_TYPES]
Definition: weapons.cpp:79
Definition: weapon.h:163
char wing_status_wing_index
Definition: ship.h:552
int check_inside_radius_for_big_ships(object *ship, object *weapon_obj, obj_pair *pair)
physics_info phys_info
Definition: object.h:157
int get_quadrant(vec3d *hit_pnt, object *shipobjp)
Definition: shield.cpp:988
int model_num
Definition: ship.h:1189
int model_instance_num
Definition: ship.h:802
Assert(pm!=NULL)
Definition: pstypes.h:88
int ai_index
Definition: ship.h:538
virtual int getWarpOrientation(matrix *output)
Definition: shipfx.cpp:3534
struct vec3d::@225::@227 xyz
vec3d max_vel
Definition: physics.h:49
#define SF2_DONT_COLLIDE_INVIS
Definition: ship.h:486
GLclampf f
Definition: Glext.h:7097
#define OF_NO_SHIELDS
Definition: object.h:110
ai_info Ai_info[MAX_AI_INFO]
Definition: ai.cpp:23
void update_danger_weapon(object *pship_obj, object *weapon_obj)
vec3d * vm_vec_rotate(vec3d *dest, const vec3d *src, const matrix *m)
Definition: vecmat.cpp:933
int lod
Definition: model.h:1118
float factor
Definition: lua.cpp:440
#define SF_ARRIVING
Definition: ship.h:453
Definition: ai.h:329
uint flags
Definition: ship.h:644
float lifeleft
Definition: weapon.h:169
int next_check_time
Definition: objcollide.h:58
float hit_dist
Definition: model.h:1122
int subtype
Definition: weapon.h:326
int reject_due_collision_groups(object *A, object *B)
Definition: objcollide.cpp:165
float weapon_get_damage_scale(weapon_info *wip, object *wep, object *target)
Definition: weapons.cpp:7137
ship * shipp
Definition: lua.cpp:9162
int auto_shield_spread_from_lod
Definition: ship.h:1313
vec3d pos
Definition: object.h:152
void ship_apply_whack(vec3d *force, vec3d *hit_pos, object *objp)
Definition: shiphit.cpp:1740
vec3d * p0
Definition: model.h:1114
hull_check submodel_num
Definition: lua.cpp:5048
script_state Script_system("FS2_Open Scripting")
int signature
Definition: object.h:145
int model_num
Definition: model.h:1110
int weapon_info_index
Definition: weapon.h:164
#define MC_CHECK_SHIELD
Definition: model.h:1170
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
int instance
Definition: object.h:150
object * a
Definition: objcollide.h:55
void vm_vec_add2(vec3d *dest, const vec3d *src)
Definition: vecmat.cpp:178
vec3d start_pos
Definition: weapon.h:170
WarpEffect * warpout_effect
Definition: ship.h:576
vec3d last_pos
Definition: object.h:155
mc_info collisionInfo
Definition: weapon.h:231
int danger_weapon_objnum
Definition: ai.h:482
#define SIF_BIG_SHIP
Definition: ship.h:944
int flags
Definition: model.h:1116
struct matrix::@228::@230 vec
bool auto_shield_spread_bypass
Definition: ship.h:1312
virtual int getWarpPosition(vec3d *output)
Definition: shipfx.cpp:3525
float mass
Definition: weapon.h:358
void vm_vec_scale(vec3d *dest, float s)
Definition: vecmat.cpp:248
int ship_weapon_check_collision(object *ship_objp, object *weapon_objp, float time_limit=0.0f, int *next_hit=NULL)
#define nprintf(args)
Definition: pstypes.h:239
vec3d * p1
Definition: model.h:1115
int flags
Definition: ship.h:1227
float speed
Definition: physics.h:79
#define OBJ_WEAPON
Definition: object.h:33
#define WP_LASER
Definition: weapon.h:27
void weapon_hit(object *weapon_obj, object *other_obj, vec3d *hitpos, int quadrant=-1)
Definition: weapons.cpp:6253
float shield_impact_explosion_radius
Definition: weapon.h:428
void hud_shield_quadrant_hit(object *objp, int quadrant)
Definition: hudshield.cpp:541
int danger_weapon_signature
Definition: ai.h:483
int weapon_will_never_hit(object *obj_weapon, object *other, obj_pair *current_pair)
Definition: objcollide.cpp:730
shield_info shield
Definition: model.h:778
int hit_submodel
Definition: model.h:1125
bool collisionOccured
Definition: weapon.h:230
float vm_vec_normalized_dir(vec3d *dest, const vec3d *end, const vec3d *start)
Definition: vecmat.cpp:591
float vm_vec_dist(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:355
#define PTRDIFF_T_ARG
Definition: clang.h:62
int flags2
Definition: ship.h:1228
Definition: ship.h:534
float radius
Definition: model.h:1117
#define SIF2_AUTO_SPREAD_SHIELDS
Definition: ship.h:934
int collide_ship_weapon(obj_pair *pair)
#define MC_CHECK_SPHERELINE
Definition: model.h:1177
float vm_vec_dist_squared(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:344
int shield_impact_explosion_anim
Definition: ship.h:1443
object Objects[MAX_OBJECTS]
Definition: object.cpp:62
int wi_flags
Definition: weapon.h:384
#define OBJ_INDEX(objp)
Definition: object.h:235
#define CHA_COLLIDEWEAPON
Definition: scripting.h:48
vec3d hit_point_world
Definition: model.h:1124
matrix orient
Definition: object.h:153
int wi_flags2
Definition: weapon.h:385
void vm_vec_copy_scale(vec3d *dest, const vec3d *src, float s)
Definition: vecmat.cpp:257
void add_shield_point(int objnum, int tri_num, vec3d *hit_pos)
Definition: shield.cpp:779
#define OBJ_SHIP
Definition: object.h:32
#define WIF2_PIERCE_SHIELDS
Definition: weapon.h:85
#define SIF_HUGE_SHIP
Definition: ship.h:945
float flFrametime
Definition: fredstubs.cpp:22
int control_mode
Definition: player.h:134
int RunCondition(int condition, char format='\0', void *data=NULL, class object *objp=NULL, int more_data=0)
Definition: scripting.cpp:924
void SetHookObjects(int num,...)
Definition: scripting.cpp:556
void vm_vec_sub(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:168
vec3d vel
Definition: physics.h:77
ship Ships[MAX_SHIPS]
Definition: ship.cpp:122
if(aifft_max_checks<=0)
Definition: aiturret.cpp:1581
typedef float(SCP_EXT_CALLCONV *SCPTRACKIR_PFFLOATVOID)()
#define ERROR_STD
float vm_vec_dist_quick(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:417
player * Player
#define MC_CHECK_MODEL
Definition: model.h:1169
float forward_accel_time_const
Definition: physics.h:59
#define CREATE_SPARKS
Definition: shiphit.h:21
void RemHookVars(unsigned int num,...)
Definition: scripting.cpp:754
int ship_info_index
Definition: ship.h:539
#define MULTIPLAYER_MASTER
Definition: multi.h:130
SCP_vector< ship_info > Ship_info
Definition: ship.cpp:164
void ship_apply_local_damage(object *ship_objp, object *other_obj, vec3d *hitpos, float damage, int quadrant, bool create_spark, int submodel_num, vec3d *hit_normal)
Definition: shiphit.cpp:2359
object * b
Definition: objcollide.h:56
#define WIF_HOMING
Definition: weapon.h:129
void shield_impact_explosion(vec3d *hitpos, object *objp, float radius, int idx)
Definition: weapons.cpp:7263
int model_instance_num
Definition: model.h:1109
float damage_time
Definition: weapon.h:364
float vm_vec_dot(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:312
void hud_wingman_status_start_flash(int wing_index, int wing_pos)
float auto_shield_spread
Definition: ship.h:1311
object * Player_obj
Definition: object.cpp:56
float estimate_ship_speed_upper_limit(object *ship, float time)
uint flags2
Definition: ship.h:645
#define SF_DYING
Definition: ship.h:447
polymodel * pm
Definition: lua.cpp:1598
vec3d hit_normal
Definition: model.h:1129
#define CHA_COLLIDESHIP
Definition: scripting.h:47
uint flags
Definition: object.h:151
float radius
Definition: object.h:154
int collision_lod
Definition: ship.h:1187
int submodel_num
Definition: model.h:1111
char type
Definition: object.h:146
float damage
Definition: weapon.h:363
void ship_weapon_do_hit_stuff(object *pship_obj, object *weapon_obj, vec3d *world_hitpos, vec3d *hitpos, int quadrant_num, int submodel_num, vec3d hit_dir)
int multi_find_player_by_object(object *objp)
Definition: multiutil.cpp:500
#define wp(p)
Definition: modelsinc.h:69
bool IsConditionOverride(int action, object *objp=NULL)
Definition: scripting.cpp:938
net_player Net_players[MAX_PLAYERS]
Definition: multi.cpp:93
float ai_endangered_time(object *ship_objp, object *weapon_objp)
Definition: aicode.cpp:6565
matrix * orient
Definition: model.h:1112
int ntris
Definition: model.h:568
float atten_damage
Definition: weapon.h:365
int ship_is_shield_up(object *obj, int quadrant)
Definition: shield.cpp:964
void send_player_pain_packet(net_player *pl, int weapon_info_index, float damage, vec3d *force, vec3d *hitpos, int quadrant_num)
Definition: multimsgs.cpp:8397
float auto_shield_spread_min_span
Definition: ship.h:1314
float vm_vec_normalize(vec3d *v)
Definition: vecmat.cpp:460