2020#include " scripting/api/objs/model.h"
2121#include " scripting/api/objs/vecmath.h"
2222#include " playerman/player.h"
23+ #include " prop/prop.h"
2324#include " ship/ship.h"
2425#include " ship/shiphit.h"
2526
@@ -413,3 +414,266 @@ int collide_asteroid_ship( obj_pair * pair )
413414 return 0 ;
414415 }
415416}
417+
418+ /* *
419+ * Checks debris-prop collisions.
420+ * @param pair obj_pair pointer to the two objects. pair->a is debris and pair->b is prop.
421+ * @return 1 if all future collisions between these can be ignored
422+ */
423+ int collide_debris_prop (obj_pair* pair)
424+ {
425+ float dist;
426+ object* debris_objp = pair->a ;
427+ object* prop_objp = pair->b ;
428+
429+ Assert (debris_objp->type == OBJ_DEBRIS);
430+ Assert (prop_objp->type == OBJ_PROP);
431+
432+ if (reject_due_collision_groups (debris_objp, prop_objp))
433+ return 0 ;
434+
435+ dist = vm_vec_dist (&debris_objp->pos , &prop_objp->pos );
436+ if (dist < debris_objp->radius + prop_objp->radius ) {
437+ int hit;
438+ vec3d hitpos;
439+ // create and initialize ship_ship_hit_info struct
440+ collision_info_struct debris_hit_info;
441+ init_collision_info_struct (&debris_hit_info);
442+
443+ if (debris_objp->radius > prop_objp->radius ) {
444+ debris_hit_info.heavy = debris_objp;
445+ debris_hit_info.light = prop_objp;
446+ }
447+ else {
448+ debris_hit_info.heavy = prop_objp;
449+ debris_hit_info.light = debris_objp;
450+ }
451+
452+ hit = prop_check_collision (prop_objp, debris_objp, &hitpos, &debris_hit_info);
453+ if (hit)
454+ {
455+ bool ship_override = false , debris_override = false ;
456+
457+ // get submodel handle if scripting needs it
458+ bool has_submodel = (debris_hit_info.heavy_submodel_num >= 0 );
459+ scripting::api::submodel_h smh (debris_hit_info.heavy_model_num , debris_hit_info.heavy_submodel_num );
460+
461+ // TODO PROP
462+ /*
463+ if (scripting::hooks::OnDebrisCollision->isActive()) {
464+ ship_override = scripting::hooks::OnDebrisCollision->isOverride(scripting::hooks::CollisionConditions{ {ship_objp, debris_objp} },
465+ scripting::hook_param_list(scripting::hook_param("Self", 'o', ship_objp),
466+ scripting::hook_param("Object", 'o', debris_objp),
467+ scripting::hook_param("Ship", 'o', ship_objp),
468+ scripting::hook_param("Debris", 'o', debris_objp),
469+ scripting::hook_param("Hitpos", 'o', hitpos)));
470+ }
471+
472+ if (scripting::hooks::OnShipCollision->isActive()) {
473+ debris_override = scripting::hooks::OnShipCollision->isOverride(scripting::hooks::CollisionConditions{ {ship_objp, debris_objp} },
474+ scripting::hook_param_list(scripting::hook_param("Self", 'o', debris_objp),
475+ scripting::hook_param("Object", 'o', ship_objp),
476+ scripting::hook_param("Ship", 'o', ship_objp),
477+ scripting::hook_param("Debris", 'o', debris_objp),
478+ scripting::hook_param("Hitpos", 'o', hitpos),
479+ scripting::hook_param("ShipSubmodel", 'o', scripting::api::l_Submodel.Set(smh), has_submodel && (debris_hit_info.heavy == ship_objp))));
480+ }*/
481+
482+ if (!ship_override && !debris_override)
483+ {
484+ // do collision physics
485+ calculate_ship_ship_collision_physics (&debris_hit_info);
486+
487+ if (debris_hit_info.impulse < 0 .5f )
488+ return 0 ;
489+
490+ float debris_damage = debris_hit_info.impulse / debris_objp->phys_info .mass ; // ie, delta velocity of debris
491+
492+ // apply damage to debris
493+ // no need for force, already handled in calculate_ship_ship_collision_physics
494+ debris_hit (debris_objp, prop_objp, &hitpos, debris_damage, nullptr ); // speed => damage
495+
496+ collide_ship_ship_do_sound (&hitpos, prop_objp, debris_objp,false );
497+ }
498+
499+ if (scripting::hooks::OnDebrisCollision->isActive () && !(debris_override && !ship_override)) {
500+ // TODO PROP
501+ /*
502+ scripting::hooks::OnDebrisCollision->run(scripting::hooks::CollisionConditions{ {ship_objp, debris_objp} },
503+ scripting::hook_param_list(scripting::hook_param("Self", 'o', ship_objp),
504+ scripting::hook_param("Object", 'o', debris_objp),
505+ scripting::hook_param("Ship", 'o', ship_objp),
506+ scripting::hook_param("Debris", 'o', debris_objp),
507+ scripting::hook_param("Hitpos", 'o', hitpos)));
508+ */
509+ }
510+ if (scripting::hooks::OnShipCollision->isActive () && ((debris_override && !ship_override) || (!debris_override && !ship_override)))
511+ {
512+ // TODO PROP
513+ /*
514+ scripting::hooks::OnShipCollision->run(scripting::hooks::CollisionConditions{ {ship_objp, debris_objp} },
515+ scripting::hook_param_list(scripting::hook_param("Self", 'o', debris_objp),
516+ scripting::hook_param("Object", 'o', ship_objp),
517+ scripting::hook_param("Ship", 'o', ship_objp),
518+ scripting::hook_param("Debris", 'o', debris_objp),
519+ scripting::hook_param("Hitpos", 'o', hitpos),
520+ scripting::hook_param("ShipSubmodel", 'o', scripting::api::l_Submodel.Set(smh), has_submodel && (debris_hit_info.heavy == ship_objp))));
521+ */
522+ }
523+
524+ return 0 ;
525+ }
526+ }
527+ else { // Bounding spheres don't intersect, set timestamp for next collision check.
528+ float debris_speed;
529+ float time;
530+
531+ debris_speed = debris_objp->phys_info .speed ;
532+
533+ time = 1000 .0f * (dist - prop_objp->radius - debris_objp->radius - 10 .0f ) / (debris_speed); // 10.0f is a safety factor
534+ time -= 200 .0f ; // allow one frame slow frame at ~5 fps
535+
536+ if (time > 100 ) {
537+ pair->next_check_time = timestamp (fl2i (time));
538+ }
539+ else {
540+ pair->next_check_time = timestamp (0 ); // check next time
541+ }
542+ }
543+
544+ return 0 ;
545+ }
546+
547+ /* *
548+ * Checks asteroid-prop collisions.
549+ * @param pair obj_pair pointer to the two objects. pair->a is asteroid and pair->b is prop.
550+ * @return 1 if all future collisions between these can be ignored
551+ */
552+ int collide_asteroid_prop (obj_pair* pair)
553+ {
554+ if (!Asteroids_enabled)
555+ return 0 ;
556+
557+ float dist;
558+ object* asteroid_objp = pair->a ;
559+ object* prop_objp = pair->b ;
560+
561+ if (asteroid_objp->hull_strength < 0 .0f )
562+ return 0 ;
563+
564+ Assert (asteroid_objp->type == OBJ_ASTEROID);
565+ Assert (prop_objp->type == OBJ_PROP);
566+
567+ dist = vm_vec_dist (&asteroid_objp->pos , &prop_objp->pos );
568+
569+ if (dist < asteroid_objp->radius + prop_objp->radius ) {
570+ int hit;
571+ vec3d hitpos;
572+ // create and initialize ship_ship_hit_info struct
573+ collision_info_struct asteroid_hit_info;
574+ init_collision_info_struct (&asteroid_hit_info);
575+
576+ if (asteroid_objp->radius > prop_objp->radius ) {
577+ asteroid_hit_info.heavy = asteroid_objp;
578+ asteroid_hit_info.light = prop_objp;
579+ }
580+ else {
581+ asteroid_hit_info.heavy = prop_objp;
582+ asteroid_hit_info.light = asteroid_objp;
583+ }
584+
585+ hit = prop_check_collision (prop_objp, prop_objp, &hitpos, &asteroid_hit_info);
586+ if (hit)
587+ {
588+ bool ship_override = false , asteroid_override = false ;
589+
590+ // get submodel handle if scripting needs it
591+ bool has_submodel = (asteroid_hit_info.heavy_submodel_num >= 0 );
592+ scripting::api::submodel_h smh (asteroid_hit_info.heavy_model_num , asteroid_hit_info.heavy_submodel_num );
593+
594+ // Scripting support (WMC)
595+ // TODO PROP
596+ /*
597+ if (scripting::hooks::OnAsteroidCollision->isActive()) {
598+ ship_override = scripting::hooks::OnAsteroidCollision->isOverride(scripting::hooks::CollisionConditions{ {ship_objp, asteroid_objp} },
599+ scripting::hook_param_list(scripting::hook_param("Self", 'o', ship_objp),
600+ scripting::hook_param("Object", 'o', asteroid_objp),
601+ scripting::hook_param("Ship", 'o', ship_objp),
602+ scripting::hook_param("Asteroid", 'o', asteroid_objp),
603+ scripting::hook_param("Hitpos", 'o', hitpos)));
604+ }
605+ if (scripting::hooks::OnShipCollision->isActive()) {
606+ asteroid_override = scripting::hooks::OnShipCollision->isOverride(scripting::hooks::CollisionConditions{ {ship_objp, asteroid_objp} },
607+ scripting::hook_param_list(scripting::hook_param("Self", 'o', asteroid_objp),
608+ scripting::hook_param("Object", 'o', ship_objp),
609+ scripting::hook_param("Ship", 'o', ship_objp),
610+ scripting::hook_param("Asteroid", 'o', asteroid_objp),
611+ scripting::hook_param("Hitpos", 'o', hitpos),
612+ scripting::hook_param("ShipSubmodel", 'o', scripting::api::l_Submodel.Set(smh), has_submodel && (asteroid_hit_info.heavy == ship_objp))));
613+ }*/
614+
615+ if (!ship_override && !asteroid_override)
616+ {
617+ float asteroid_damage;
618+
619+ vec3d asteroid_vel = asteroid_objp->phys_info .vel ;
620+
621+ // do collision physics
622+ calculate_ship_ship_collision_physics (&asteroid_hit_info);
623+
624+ if (asteroid_hit_info.impulse < 0 .5f )
625+ return 0 ;
626+
627+ asteroid_damage = asteroid_hit_info.impulse / asteroid_objp->phys_info .mass ; // ie, delta velocity of asteroid
628+
629+ // apply damage to asteroid
630+ asteroid_hit (asteroid_objp, prop_objp, &hitpos, asteroid_damage, nullptr ); // speed => damage
631+
632+ collide_ship_ship_do_sound (&hitpos, prop_objp, asteroid_objp, false );
633+ }
634+
635+ // TODO PROP
636+ /*
637+ if (scripting::hooks::OnAsteroidCollision->isActive() && !(asteroid_override && !ship_override)) {
638+ scripting::hooks::OnAsteroidCollision->run(scripting::hooks::CollisionConditions{ {ship_objp, asteroid_objp} },
639+ scripting::hook_param_list(scripting::hook_param("Self", 'o', ship_objp),
640+ scripting::hook_param("Object", 'o', asteroid_objp),
641+ scripting::hook_param("Ship", 'o', ship_objp),
642+ scripting::hook_param("Asteroid", 'o', asteroid_objp),
643+ scripting::hook_param("Hitpos", 'o', hitpos)));
644+ }
645+ if (scripting::hooks::OnShipCollision->isActive() && ((asteroid_override && !ship_override) || (!asteroid_override && !ship_override)))
646+ {
647+ scripting::hooks::OnShipCollision->run(scripting::hooks::CollisionConditions{ {ship_objp, asteroid_objp} },
648+ scripting::hook_param_list(scripting::hook_param("Self", 'o', asteroid_objp),
649+ scripting::hook_param("Object", 'o', ship_objp),
650+ scripting::hook_param("Ship", 'o', ship_objp),
651+ scripting::hook_param("Asteroid", 'o', asteroid_objp),
652+ scripting::hook_param("Hitpos", 'o', hitpos),
653+ scripting::hook_param("ShipSubmodel", 'o', scripting::api::l_Submodel.Set(smh), has_submodel && (asteroid_hit_info.heavy == ship_objp))));
654+ }*/
655+
656+ return 0 ;
657+ }
658+
659+ return 0 ;
660+ }
661+ else {
662+ // estimate earliest time at which pair can hit
663+ float asteroid_max_speed, time;
664+
665+ asteroid_max_speed = vm_vec_mag (&asteroid_objp->phys_info .vel ); // Asteroid... vel gets reset, not max vel.z
666+ asteroid_max_speed = MAX (asteroid_max_speed, 10 .0f );
667+
668+ time = 1000 .0f * (dist - prop_objp->radius - asteroid_objp->radius - 10 .0f ) / (asteroid_max_speed); // 10.0f is a safety factor
669+ time -= 200 .0f ; // allow one frame slow frame at ~5 fps
670+
671+ if (time > 100 ) {
672+ pair->next_check_time = timestamp (fl2i (time));
673+ }
674+ else {
675+ pair->next_check_time = timestamp (0 ); // check next time
676+ }
677+ return 0 ;
678+ }
679+ }
0 commit comments