Beispiel #1
0
/* 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 );
	}
}				
Beispiel #7
0
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");
    }

}
Beispiel #8
0
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");
    }

}
Beispiel #9
0
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");
    }

}
Beispiel #10
0
Datei: weapon.c Projekt: zid/naev
/**
 * @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);
	}
	

}