/* In theory this should only be called with both first and second being projectiles */ static void col_projectile(entity *proj, entity *second) { entity *shooter; point pt; switch( second->class ) { case PROJECTILE: /* Projectile hits second */ if( (shooter = findent(proj->pid)) != NULL ) { pt.x = proj->x; pt.y = proj->y; weapon_hit( shooter, second, pt, proj->weapon); } /* Second hits projectile */ if( (shooter = findent(second->pid)) != NULL ) { pt.x = second->x; pt.y = second->y; weapon_hit( shooter, proj, pt, second->weapon); } break; default: printf("NOT HANDLED!\n"); } }
// Checks debris-weapon collisions. pair->a is debris and pair->b is weapon. // Returns 1 if all future collisions between these can be ignored int collide_debris_weapon( obj_pair * pair ) { vector hitpos; int hit; object *pdebris = pair->a; object *weapon = pair->b; Assert( pdebris->type == OBJ_DEBRIS ); Assert( weapon->type == OBJ_WEAPON ); // first check the bounding spheres of the two objects. hit = fvi_segment_sphere(&hitpos, &weapon->last_pos, &weapon->pos, &pdebris->pos, pdebris->radius); if (hit) { hit = debris_check_collision(pdebris, weapon, &hitpos ); if ( !hit ) return 0; weapon_hit( weapon, pdebris, &hitpos ); debris_hit( pdebris, weapon, &hitpos, Weapon_info[Weapons[weapon->instance].weapon_info_index].damage ); return 0; } else { return weapon_will_never_hit( weapon, pdebris, pair ); } }
// Checks debris-weapon collisions. pair->a is debris and pair->b is weapon. // Returns 1 if all future collisions between these can be ignored int collide_asteroid_weapon( obj_pair * pair ) { #if !(defined(FS2_DEMO) || defined(FS1_DEMO)) if (!Asteroids_enabled) return 0; vector hitpos; int hit; object *pasteroid = pair->a; object *weapon = pair->b; Assert( pasteroid->type == OBJ_ASTEROID); Assert( weapon->type == OBJ_WEAPON ); // first check the bounding spheres of the two objects. hit = fvi_segment_sphere(&hitpos, &weapon->last_pos, &weapon->pos, &pasteroid->pos, pasteroid->radius); if (hit) { hit = asteroid_check_collision(pasteroid, weapon, &hitpos ); if ( !hit ) return 0; weapon_hit( weapon, pasteroid, &hitpos ); asteroid_hit( pasteroid, weapon, &hitpos, Weapon_info[Weapons[weapon->instance].weapon_info_index].damage ); return 0; } else { return weapon_will_never_hit( weapon, pasteroid, pair ); } #else return 0; #endif }
/** * Deal with weapon-ship hit stuff. * Separated from check_collision routine below because of multiplayer reasons. */ 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) { weapon *wp = &Weapons[weapon_obj->instance]; weapon_info *wip = &Weapon_info[wp->weapon_info_index]; ship *shipp = &Ships[pship_obj->instance]; float damage; vec3d force; vec3d worldNormal; model_instance_find_world_dir(&worldNormal, &hit_dir, shipp->model_instance_num, submodel_num, &pship_obj->orient); // Apply hit & damage & stuff to weapon weapon_hit(weapon_obj, pship_obj, world_hitpos, quadrant_num, &worldNormal); if (wip->damage_time >= 0.0f && wp->lifeleft <= wip->damage_time) { if (wip->atten_damage >= 0.0f) { damage = (((wip->damage - wip->atten_damage) * (wp->lifeleft / wip->damage_time)) + wip->atten_damage); } else { damage = wip->damage * (wp->lifeleft / wip->damage_time); } } else { damage = wip->damage; } // deterine whack whack float blast = wip->mass; vm_vec_copy_scale(&force, &weapon_obj->phys_info.vel, blast ); // send player pain packet if ( (MULTIPLAYER_MASTER) && !(shipp->flags[Ship::Ship_Flags::Dying]) ) { int np_index = multi_find_player_by_object(pship_obj); // if this is a player ship if((np_index >= 0) && (np_index != MY_NET_PLAYER_NUM) && (wip->subtype == WP_LASER)) { 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); } } ship_apply_local_damage(pship_obj, weapon_obj, world_hitpos, damage, quadrant_num, CREATE_SPARKS, submodel_num); // let the hud shield gauge know when Player or Player target is hit hud_shield_quadrant_hit(pship_obj, quadrant_num); // Let wingman status gauge know a wingman ship was hit if ( (Ships[pship_obj->instance].wing_status_wing_index >= 0) && ((Ships[pship_obj->instance].wing_status_wing_pos >= 0)) ) { hud_wingman_status_start_flash(shipp->wing_status_wing_index, shipp->wing_status_wing_pos); } // Apply a wack. This used to be inside of ship_hit... duh! Ship_hit // is to apply damage, not physics, so I moved it here. // don't apply whack for multiplayer_client from laser - will occur with pain packet if (!((wip->subtype == WP_LASER) && MULTIPLAYER_CLIENT) ) { // apply a whack ship_apply_whack( &force, hitpos, pship_obj ); } }
/** * Checks debris-weapon collisions. * @param pair obj_pair pointer to the two objects. pair->a is debris and pair->b is weapon. * @return 1 if all future collisions between these can be ignored */ int collide_asteroid_weapon( obj_pair * pair ) { if (!Asteroids_enabled) return 0; vec3d hitpos, hitnormal; int hit; object *pasteroid = pair->a; object *weapon_obj = pair->b; Assert( pasteroid->type == OBJ_ASTEROID); Assert( weapon_obj->type == OBJ_WEAPON ); // first check the bounding spheres of the two objects. hit = fvi_segment_sphere(&hitpos, &weapon_obj->last_pos, &weapon_obj->pos, &pasteroid->pos, pasteroid->radius); if (hit) { hit = asteroid_check_collision(pasteroid, weapon_obj, &hitpos, NULL, &hitnormal); if ( !hit ) return 0; Script_system.SetHookObjects(4, "Weapon", weapon_obj, "Asteroid", pasteroid, "Self", weapon_obj, "Object", pasteroid); bool weapon_override = Script_system.IsConditionOverride(CHA_COLLIDEASTEROID, weapon_obj); Script_system.SetHookObjects(2, "Self",pasteroid, "Object", weapon_obj); bool asteroid_override = Script_system.IsConditionOverride(CHA_COLLIDEWEAPON, pasteroid); if(!weapon_override && !asteroid_override) { weapon_hit( weapon_obj, pasteroid, &hitpos, -1, &hitnormal); asteroid_hit( pasteroid, weapon_obj, &hitpos, Weapon_info[Weapons[weapon_obj->instance].weapon_info_index].damage ); } Script_system.SetHookObjects(2, "Self", weapon_obj, "Object", pasteroid); if(!(asteroid_override && !weapon_override)) Script_system.RunCondition(CHA_COLLIDEASTEROID, '\0', NULL, weapon_obj); Script_system.SetHookObjects(2, "Self", pasteroid, "Object", weapon_obj); if((asteroid_override && !weapon_override) || (!asteroid_override && !weapon_override)) Script_system.RunCondition(CHA_COLLIDEWEAPON, '\0', NULL, pasteroid, Weapons[weapon_obj->instance].weapon_info_index); Script_system.RemHookVars(4, "Weapon", "Asteroid", "Self", "Object"); return 0; } else { return weapon_will_never_hit( weapon_obj, pasteroid, pair ); } }
/** * Checks debris-weapon collisions. * @param pair obj_pair pointer to the two objects. pair->a is debris and pair->b is weapon. * @return 1 if all future collisions between these can be ignored */ int collide_debris_weapon( obj_pair * pair ) { vec3d hitpos, hitnormal; int hit; object *pdebris = pair->a; object *weapon_obj = pair->b; Assert( pdebris->type == OBJ_DEBRIS ); Assert( weapon_obj->type == OBJ_WEAPON ); // first check the bounding spheres of the two objects. hit = fvi_segment_sphere(&hitpos, &weapon_obj->last_pos, &weapon_obj->pos, &pdebris->pos, pdebris->radius); if (hit) { hit = debris_check_collision(pdebris, weapon_obj, &hitpos, NULL, &hitnormal ); if ( !hit ) return 0; Script_system.SetHookObjects(4, "Weapon", weapon_obj, "Debris", pdebris, "Self", weapon_obj, "Object", pdebris); bool weapon_override = Script_system.IsConditionOverride(CHA_COLLIDEDEBRIS, weapon_obj); Script_system.SetHookObjects(2, "Self", pdebris, "Object", weapon_obj); bool debris_override = Script_system.IsConditionOverride(CHA_COLLIDEWEAPON, pdebris); if(!weapon_override && !debris_override) { weapon_hit( weapon_obj, pdebris, &hitpos, -1, &hitnormal ); debris_hit( pdebris, weapon_obj, &hitpos, Weapon_info[Weapons[weapon_obj->instance].weapon_info_index].damage ); } Script_system.SetHookObjects(2, "Self", weapon_obj, "Object", pdebris); if(!(debris_override && !weapon_override)) Script_system.RunCondition(CHA_COLLIDEDEBRIS, '\0', NULL, weapon_obj); Script_system.SetHookObjects(2, "Self", pdebris, "Object", weapon_obj); if((debris_override && !weapon_override) || (!debris_override && !weapon_override)) Script_system.RunCondition(CHA_COLLIDEWEAPON, '\0', NULL, pdebris, Weapons[weapon_obj->instance].weapon_info_index); Script_system.RemHookVars(4, "Weapon", "Debris", "Self", "Object"); return 0; } else { return weapon_will_never_hit( weapon_obj, pdebris, pair ); } }
static void col_baddie(entity *baddie, entity *second) { entity *shooter; point pt; int damage; switch( second->class ) { case BADDIE: /* Do damage if baddies are fighting */ if( baddie->target == second ) { if( (damage = baddie->type_info->touchdamage / server.fps) < 1 ) damage = 1; /* Correct for rounding down */ second->health -= damage; second->target = baddie; } else if( second->target == baddie ) { if( (damage = second->type_info->touchdamage / server.fps) < 1 ) damage = 1; /* Correct for rounding down */ baddie->health -= damage; baddie->target = second; } break; case NEUTRAL: /* Nothing.... */ break; case ITEM: /* item_collision(second, baddie); */ break; case PROJECTILE: shooter = findent(second->pid); pt.x = second->x; pt.y = second->y; weapon_hit( shooter, baddie, pt, second->weapon); second->health = 0; /* Remove projectile */ break; default: printf("NOT HANDLED!\n"); } }
static void col_goodie(entity *goodie, entity *second) { entity *shooter; point pt; int damage; switch( second->class ) { case GOODIE: /* Nothing.... */ break; case BADDIE: /* Touch damage is delt over a second */ if( (damage = second->type_info->touchdamage / server.fps ) < 1 ) damage = 1; /* Correct for rounding down */ goodie->health -= damage; if( goodie->health <= 0 ) entity_killed(second, goodie, pt, 0); /* Slow the baddie down while he does damage */ second->x_v *= 0.25; second->y_v *= 0.25; break; case NEUTRAL: /* Nothing... */ break; case ITEM: item_collision(second, goodie); break; case PROJECTILE: shooter = findent(second->pid); pt.x = second->x; pt.y = second->y; weapon_hit( shooter, goodie, pt, second->weapon ); second->health = 0; /* Remove projectile */ break; default: printf("NOT HANDLED!\n"); } }
static void col_neutral(entity *neutral, entity *second) { entity *shooter; point pt; switch( second->class ) { case NEUTRAL: break; case ITEM: /* Nothing.... */ break; case PROJECTILE: shooter = findent(second->pid); pt.x = second->x; pt.y = second->y; weapon_hit( shooter, neutral, pt, second->weapon); second->health = 0; /* Remove projectile */ break; default: printf("NOT HANDLED!\n"); } }
/** * @brief Updates an individual weapon. * * @param w Weapon to update. * @param dt Current delta tick. * @param layer Layer to which the weapon belongs. */ static void weapon_update( Weapon* w, const double dt, WeaponLayer layer ) { int i, psx,psy; glTexture *gfx; Vector2d crash[2]; Pilot *p; /* Get the sprite direction to speed up calculations. */ if (!outfit_isBeam(w->outfit)) { gfx = outfit_gfx(w->outfit); gl_getSpriteFromDir( &w->sx, &w->sy, gfx, w->solid->dir ); } for (i=0; i<pilot_nstack; i++) { p = pilot_stack[i]; psx = pilot_stack[i]->tsx; psy = pilot_stack[i]->tsy; if (w->parent == pilot_stack[i]->id) continue; /* pilot is self */ /* Beam weapons have special collisions. */ if (outfit_isBeam(w->outfit)) { /* Check for collision. */ if (weapon_checkCanHit(w,p) && CollideLineSprite( &w->solid->pos, w->solid->dir, w->outfit->u.bem.range, p->ship->gfx_space, psx, psy, &p->solid->pos, crash)) { weapon_hitBeam( w, p, layer, crash, dt ); /* No return because beam can still think, it's not * destroyed like the other weapons.*/ } } /* smart weapons only collide with their target */ else if (weapon_isSmart(w)) { if ((pilot_stack[i]->id == w->target) && (w->status != WEAPON_STATUS_OK) && /* Must not be locking on. */ weapon_checkCanHit(w,p) && CollideSprite( gfx, w->sx, w->sy, &w->solid->pos, p->ship->gfx_space, psx, psy, &p->solid->pos, &crash[0] )) { weapon_hit( w, p, layer, &crash[0] ); return; /* Weapon is destroyed. */ } } /* dumb weapons hit anything not of the same faction */ else { if (weapon_checkCanHit(w,p) && CollideSprite( gfx, w->sx, w->sy, &w->solid->pos, p->ship->gfx_space, psx, psy, &p->solid->pos, &crash[0] )) { weapon_hit( w, p, layer, &crash[0] ); return; /* Weapon is destroyed. */ } } } /* smart weapons also get to think their next move */ if (weapon_isSmart(w)) (*w->think)(w,dt); /* Update the solid position. */ (*w->solid->update)(w->solid, dt); /* Update the sound. */ sound_updatePos(w->voice, w->solid->pos.x, w->solid->pos.y, w->solid->vel.x, w->solid->vel.y); }
// function to actually deal with weapon-ship hit stuff. separated from check_collision routine below // because of multiplayer reasons. void ship_weapon_do_hit_stuff(object *ship_obj, object *weapon_obj, vec3d *world_hitpos, vec3d *hitpos, int quadrant_num, int submodel_num, vec3d /*not a pointer intentionaly*/ hit_dir) { weapon *wp = &Weapons[weapon_obj->instance]; weapon_info *wip = &Weapon_info[wp->weapon_info_index]; ship *shipp = &Ships[ship_obj->instance]; float damage; vec3d force; // Apply hit & damage & stuff to weapon weapon_hit(weapon_obj, ship_obj, world_hitpos); damage = wip->damage; // deterine whack whack float blast = wip->mass; vm_vec_copy_scale(&force, &weapon_obj->phys_info.vel, blast ); // send player pain packet if ( (MULTIPLAYER_MASTER) && !(shipp->flags & SF_DYING) ){ int np_index = multi_find_player_by_object(ship_obj); // if this is a player ship if((np_index >= 0) && (np_index != MY_NET_PLAYER_NUM) && (wip->subtype == WP_LASER)){ send_player_pain_packet(&Net_players[np_index], wp->weapon_info_index, wip->damage * weapon_get_damage_scale(wip, weapon_obj, ship_obj), &force, hitpos); } } ship_apply_local_damage(ship_obj, weapon_obj, world_hitpos, damage, quadrant_num, CREATE_SPARKS, submodel_num); // let the hud shield gauge know when Player or Player target is hit hud_shield_quadrant_hit(ship_obj, quadrant_num); // Let wingman status gauge know a wingman ship was hit if ( (Ships[ship_obj->instance].wing_status_wing_index >= 0) && ((Ships[ship_obj->instance].wing_status_wing_pos >= 0)) ) { hud_wingman_status_start_flash(shipp->wing_status_wing_index, shipp->wing_status_wing_pos); } // Apply a wack. This used to be inside of ship_hit... duh! Ship_hit // is to apply damage, not physics, so I moved it here. // don't apply whack for multiplayer_client from laser - will occur with pain packet if (!((wip->subtype == WP_LASER) && MULTIPLAYER_CLIENT) ) { // apply a whack ship_apply_whack( &force, hitpos, ship_obj ); } if( (quadrant_num == -1) && Cmdline_decals ){ weapon_info *wip = &Weapon_info[Weapons[weapon_obj->instance].weapon_info_index]; decal_point dec; dec.orient = weapon_obj->orient; vec3d hit_fvec; vm_vec_negate(&hit_dir); vm_vec_avg(&hit_fvec, &hit_dir, &weapon_obj->orient.vec.fvec); vm_vec_normalize(&hit_fvec); dec.orient.vec.fvec = hit_fvec; vm_fix_matrix(&dec.orient); dec.pnt.xyz = hitpos->xyz; dec.radius = wip->decal_rad; if ( (dec.radius > 0) && (wip->decal_texture.bitmap_id > -1) ) decal_create(ship_obj, &dec, submodel_num, wip->decal_texture.bitmap_id, wip->decal_backface_texture.bitmap_id, wip->decal_glow_texture_id, wip->decal_burn_texture_id, wip->decal_burn_time); } }