// ------------------------------------------------------------------------------------ // shockwave_move() // // Simulate a single shockwave. If the shockwave radius exceeds outer_radius, then // delete the shockwave. // // input: ojbp => object pointer that points to shockwave object // frametime => time to simulate shockwave // void shockwave_move(object *shockwave_objp, float frametime) { shockwave *sw; object *objp; float blast,damage; int i; Assert(shockwave_objp->type == OBJ_SHOCKWAVE); Assert(shockwave_objp->instance >= 0 && shockwave_objp->instance < MAX_SHOCKWAVES); sw = &Shockwaves[shockwave_objp->instance]; // if the shockwave has a delay on it if(sw->delay_stamp != -1){ if(timestamp_elapsed(sw->delay_stamp)){ sw->delay_stamp = -1; } else { return; } } sw->time_elapsed += frametime; /* if ( sw->time_elapsed > sw->total_time ) { shockwave_objp->flags |= OF_SHOULD_BE_DEAD; } */ shockwave_set_framenum(shockwave_objp->instance); sw->radius += (frametime * sw->speed); if ( sw->radius > sw->outer_radius ) { sw->radius = sw->outer_radius; shockwave_objp->flags |= OF_SHOULD_BE_DEAD; return; } // blast ships and asteroids for ( objp = GET_FIRST(&obj_used_list); objp !=END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) { if ( (objp->type != OBJ_SHIP) && (objp->type != OBJ_ASTEROID) ) { continue; } if ( objp->type == OBJ_SHIP ) { // don't blast navbuoys if ( ship_get_SIF(objp->instance) & SIF_NAVBUOY ) { continue; } } // only apply damage to a ship once from a shockwave for ( i = 0; i < sw->num_objs_hit; i++ ) { if ( objp->signature == sw->obj_sig_hitlist[i] ){ break; } } if ( i < sw->num_objs_hit ){ continue; } if ( weapon_area_calc_damage(objp, &sw->pos, sw->inner_radius, sw->outer_radius, sw->blast, sw->damage, &blast, &damage, sw->radius) == -1 ){ continue; } // okay, we have damage applied, record the object signature so we don't repeatedly apply damage Assert(sw->num_objs_hit < SW_MAX_OBJS_HIT); if ( sw->num_objs_hit >= SW_MAX_OBJS_HIT) { sw->num_objs_hit--; } switch(objp->type) { case OBJ_SHIP: sw->obj_sig_hitlist[sw->num_objs_hit++] = objp->signature; ship_apply_global_damage(objp, shockwave_objp, &sw->pos, damage ); weapon_area_apply_blast(NULL, objp, &sw->pos, blast, 1); break; case OBJ_ASTEROID: asteroid_hit(objp, NULL, NULL, damage); break; default: Int3(); break; } // If this shockwave hit the player, play shockwave impact sound if ( objp == Player_obj ) { snd_play( &Snds[SND_SHOCKWAVE_IMPACT], 0.0f, MAX(0.4f, damage/Weapon_info[sw->weapon_info_index].damage) ); } } // end for }
/** * Simulate a single shockwave. If the shockwave radius exceeds outer_radius, then * delete the shockwave. * * @param shockwave_objp object pointer that points to shockwave object * @param frametime time to simulate shockwave */ void shockwave_move(object *shockwave_objp, float frametime) { shockwave *sw; object *objp; float blast,damage; int i; Assert(shockwave_objp->type == OBJ_SHOCKWAVE); Assert(shockwave_objp->instance >= 0 && shockwave_objp->instance < MAX_SHOCKWAVES); sw = &Shockwaves[shockwave_objp->instance]; // if the shockwave has a delay on it if(sw->delay_stamp != -1){ if(timestamp_elapsed(sw->delay_stamp)){ sw->delay_stamp = -1; } else { return; } } sw->time_elapsed += frametime; shockwave_set_framenum(shockwave_objp->instance); sw->radius += (frametime * sw->speed); if ( sw->radius > sw->outer_radius ) { sw->radius = sw->outer_radius; shockwave_objp->flags |= OF_SHOULD_BE_DEAD; return; } // blast ships and asteroids // And (some) weapons for ( objp = GET_FIRST(&obj_used_list); objp !=END_OF_LIST(&obj_used_list); objp = GET_NEXT(objp) ) { if ( (objp->type != OBJ_SHIP) && (objp->type != OBJ_ASTEROID) && (objp->type != OBJ_WEAPON)) { continue; } if ( objp->type == OBJ_WEAPON ) { // only apply to missiles with hitpoints weapon_info* wip = &Weapon_info[Weapons[objp->instance].weapon_info_index]; if (wip->weapon_hitpoints <= 0 || !(wip->wi_flags2 & WIF2_TAKES_SHOCKWAVE_DAMAGE)) continue; if (sw->weapon_info_index >= 0) { if (Weapon_info[sw->weapon_info_index].wi_flags2 & WIF2_CIWS) { continue; } } } if ( objp->type == OBJ_SHIP ) { // don't blast navbuoys if ( ship_get_SIF(objp->instance) & SIF_NAVBUOY ) { continue; } } // only apply damage to a ship once from a shockwave for ( i = 0; i < sw->num_objs_hit; i++ ) { if ( objp->signature == sw->obj_sig_hitlist[i] ){ break; } } if ( i < sw->num_objs_hit ){ continue; } if ( weapon_area_calc_damage(objp, &sw->pos, sw->inner_radius, sw->outer_radius, sw->blast, sw->damage, &blast, &damage, sw->radius) == -1 ){ continue; } // okay, we have damage applied, record the object signature so we don't repeatedly apply damage Assert(sw->num_objs_hit < SW_MAX_OBJS_HIT); if ( sw->num_objs_hit >= SW_MAX_OBJS_HIT) { sw->num_objs_hit--; } weapon_info* wip = NULL; switch(objp->type) { case OBJ_SHIP: sw->obj_sig_hitlist[sw->num_objs_hit++] = objp->signature; // If we're doing an AoE Electronics shockwave, do the electronics stuff. -MageKing17 if ( (sw->weapon_info_index >= 0) && (Weapon_info[sw->weapon_info_index].wi_flags3 & WIF3_AOE_ELECTRONICS) && !(objp->flags & OF_INVULNERABLE) ) { weapon_do_electronics_effect(objp, &sw->pos, sw->weapon_info_index); } ship_apply_global_damage(objp, shockwave_objp, &sw->pos, damage ); weapon_area_apply_blast(NULL, objp, &sw->pos, blast, 1); break; case OBJ_ASTEROID: asteroid_hit(objp, NULL, NULL, damage); break; case OBJ_WEAPON: wip = &Weapon_info[Weapons[objp->instance].weapon_info_index]; if (wip->armor_type_idx >= 0) damage = Armor_types[wip->armor_type_idx].GetDamage(damage, shockwave_get_damage_type_idx(shockwave_objp->instance),1.0f); objp->hull_strength -= damage; if (objp->hull_strength < 0.0f) { Weapons[objp->instance].lifeleft = 0.01f; Weapons[objp->instance].weapon_flags |= WF_DESTROYED_BY_WEAPON; } break; default: Int3(); break; } // If this shockwave hit the player, play shockwave impact sound if ( objp == Player_obj ) { float full_damage, vol_scale; if (sw->weapon_info_index >= 0) { full_damage = Weapon_info[sw->weapon_info_index].damage; } else { full_damage = sw->damage; } if (full_damage != 0.0f) { vol_scale = MAX(0.4f, damage/full_damage); } else { vol_scale = 1.0f; } snd_play( &Snds[SND_SHOCKWAVE_IMPACT], 0.0f, vol_scale ); } } // end for }