mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-08 07:28:22 -10:00
One of the features requested in #5378 (specifically the one requested in #5274), this adds a new "$Contrails use absolute speed:" option to game_settings.tbl, which makes the `ct_below_limit()` function check `objp->phys_info.speed` instead of `objp->phys_info.fspeed`. This allows contrails to appear when moving in a direction other than forwards.
448 lines
10 KiB
C++
448 lines
10 KiB
C++
/*
|
|
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
|
*
|
|
* All source code herein is the property of Volition, Inc. You may not sell
|
|
* or otherwise commercially exploit the source or things you created based on the
|
|
* source.
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
#include "mission/missionparse.h"
|
|
#include "ship/ship.h"
|
|
#include "ship/shipcontrails.h"
|
|
|
|
|
|
|
|
// ----------------------------------------------------------------------------------------------
|
|
// CONTRAIL DEFINES/VARS
|
|
//
|
|
|
|
// ----------------------------------------------------------------------------------------------
|
|
// CONTRAIL FORWARD DECLARATIONS
|
|
//
|
|
|
|
// if the object is below the limit for contrails
|
|
int ct_below_limit(object *objp);
|
|
|
|
// Goober0500
|
|
bool ct_display_contrails();
|
|
|
|
// if an object has active contrails
|
|
int ct_has_contrails(ship *shipp);
|
|
|
|
// update active contrails - moving existing ones, adding new ones where necessary
|
|
void ct_update_contrails(ship *shipp);
|
|
|
|
// create new contrails
|
|
void ct_create_contrails(ship *shipp);
|
|
|
|
|
|
// determine if the ship has AB trails
|
|
int ct_has_ABtrails(ship *shipp);
|
|
|
|
// update active ABtrails - moving existing ones, adding new ones where necessary
|
|
void ct_update_ABtrails(ship *shipp);
|
|
|
|
// create new ABtrails
|
|
void ct_create_ABtrails(ship *shipp);
|
|
|
|
void ct_ship_process_ABtrails(ship *shipp);
|
|
|
|
// ----------------------------------------------------------------------------------------------
|
|
// CONTRAIL FUNCTIONS
|
|
//
|
|
|
|
// call during level initialization
|
|
void ct_level_init()
|
|
{
|
|
}
|
|
|
|
// call during level shutdown
|
|
void ct_level_close()
|
|
{
|
|
}
|
|
|
|
// call when a ship is created to initialize its contrail stuff
|
|
void ct_ship_create(ship *shipp)
|
|
{
|
|
int idx;
|
|
Assert(shipp != NULL);
|
|
|
|
// null out the ct indices for this guy
|
|
for(idx=0; idx<MAX_SHIP_CONTRAILS; idx++){
|
|
shipp->trail_ptr[idx] = NULL;
|
|
}
|
|
|
|
for(idx=0; idx<MAX_SHIP_CONTRAILS; idx++){
|
|
shipp->ABtrail_ptr[idx] = NULL;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
// call when a ship is deleted to free up its contrail stuff
|
|
void ct_ship_delete(ship *shipp)
|
|
{
|
|
int idx;
|
|
|
|
Assert(shipp != NULL);
|
|
// free up any contrails this guy may have had
|
|
for(idx=0; idx<MAX_SHIP_CONTRAILS; idx++){
|
|
if(shipp->trail_ptr[idx] != NULL){
|
|
trail_object_died(shipp->trail_ptr[idx]);
|
|
shipp->trail_ptr[idx] = NULL;
|
|
}
|
|
if(shipp->ABtrail_ptr[idx] != NULL){
|
|
trail_object_died(shipp->ABtrail_ptr[idx]);
|
|
shipp->ABtrail_ptr[idx] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
// call each frame for processing a ship's contrails
|
|
void ct_ship_process(ship *shipp)
|
|
{
|
|
// seems like as good a place as any -Bobboau
|
|
if (shipp->ab_info[0].texture.bitmap_id != -1)
|
|
ct_ship_process_ABtrails(shipp);
|
|
|
|
Assert(shipp != NULL);
|
|
Assert(shipp->objnum >= 0);
|
|
|
|
// if trails aren't enabled, return
|
|
if (!ct_display_contrails()) {
|
|
return;
|
|
}
|
|
|
|
int idx;
|
|
object *objp;
|
|
objp = &Objects[shipp->objnum];
|
|
|
|
// if this is not a ship, we don't care
|
|
if((objp->type != OBJ_SHIP) || (Ship_info[Ships[objp->instance].ship_info_index].ct_count <= 0)){
|
|
return;
|
|
}
|
|
|
|
Assert(objp->instance >= 0);
|
|
shipp = &Ships[objp->instance];
|
|
|
|
// if the object is below the critical limit
|
|
if(ct_below_limit(objp)){
|
|
// kill any active trails he has
|
|
for(idx=0; idx<MAX_SHIP_CONTRAILS; idx++){
|
|
if(shipp->trail_ptr[idx] != NULL){
|
|
trail_object_died(shipp->trail_ptr[idx]);
|
|
shipp->trail_ptr[idx] = NULL;
|
|
}
|
|
}
|
|
|
|
// don't create or update trails if we're not moving fast enough
|
|
return;
|
|
}
|
|
|
|
|
|
// if the object already has contrails
|
|
if(ct_has_contrails(shipp)){
|
|
ct_update_contrails(shipp);
|
|
}
|
|
// otherwise add new ones
|
|
else {
|
|
ct_create_contrails(shipp);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------------
|
|
// CONTRAIL FORWARD DEFINITIONS - test stuff
|
|
//
|
|
|
|
// if the object is below the limit for contrails
|
|
int ct_below_limit(object *objp)
|
|
{
|
|
if (Contrails_use_absolute_speed)
|
|
return objp->phys_info.speed < (float) The_mission.contrail_threshold;
|
|
return objp->phys_info.fspeed < (float) The_mission.contrail_threshold;
|
|
}
|
|
|
|
// if a ship has active contrails
|
|
int ct_has_contrails(ship *shipp)
|
|
{
|
|
int idx;
|
|
|
|
for(idx=0; idx<MAX_SHIP_CONTRAILS; idx++){
|
|
if(shipp->trail_ptr[idx] != NULL){
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
// no contrails
|
|
return 0;
|
|
}
|
|
|
|
// update active contrails - moving existing ones, adding new ones where necessary
|
|
void ct_update_contrails(ship *shipp)
|
|
{
|
|
// if trails aren't enabled, return
|
|
if (!ct_display_contrails()) {
|
|
return;
|
|
}
|
|
|
|
vec3d v1;
|
|
int idx;
|
|
ship_info *sip;
|
|
object *objp;
|
|
|
|
// get object and ship info
|
|
Assert(shipp != NULL);
|
|
Assert(shipp->objnum >= 0);
|
|
Assert(shipp->ship_info_index >= 0);
|
|
objp = &Objects[shipp->objnum];
|
|
sip = &Ship_info[shipp->ship_info_index];
|
|
|
|
// process each contrail
|
|
for(idx=0; idx<MAX_SHIP_CONTRAILS; idx++){
|
|
// if this is a valid contrail
|
|
if(shipp->trail_ptr[idx] != NULL){
|
|
// get the point for the contrail
|
|
vm_vec_unrotate(&v1, &sip->ct_info[idx].pt, &objp->orient);
|
|
vm_vec_add2(&v1, &objp->pos);
|
|
|
|
// if the spew stamp has elapsed
|
|
if(trail_stamp_elapsed(shipp->trail_ptr[idx])){
|
|
trail_add_segment(shipp->trail_ptr[idx], &v1, &objp->orient);
|
|
trail_set_stamp(shipp->trail_ptr[idx]);
|
|
} else {
|
|
trail_set_segment(shipp->trail_ptr[idx], &v1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// create new contrails
|
|
void ct_create_contrails(ship *shipp)
|
|
{
|
|
#ifdef MULTIPLAYER_BETA_BUILD
|
|
return;
|
|
#else
|
|
|
|
// if trails aren't enabled, return
|
|
if (!ct_display_contrails()) {
|
|
return;
|
|
}
|
|
|
|
vec3d v1;
|
|
int idx;
|
|
ship_info *sip;
|
|
object *objp;
|
|
|
|
// get object and ship info
|
|
Assert(shipp != NULL);
|
|
Assert(shipp->objnum >= 0);
|
|
Assert(shipp->ship_info_index >= 0);
|
|
objp = &Objects[shipp->objnum];
|
|
sip = &Ship_info[shipp->ship_info_index];
|
|
|
|
|
|
for(idx=0; idx<sip->ct_count; idx++)
|
|
{
|
|
//if (this is a neb mision and this is a neb trail) or an ABtrail -Bobboau
|
|
shipp->trail_ptr[idx] = trail_create(&sip->ct_info[idx]);
|
|
|
|
if(shipp->trail_ptr[idx] != NULL)
|
|
{
|
|
// add the point
|
|
vm_vec_unrotate(&v1, &sip->ct_info[idx].pt, &objp->orient);
|
|
vm_vec_add2(&v1, &objp->pos);
|
|
trail_add_segment(shipp->trail_ptr[idx], &v1, &objp->orient);
|
|
trail_add_segment(shipp->trail_ptr[idx], &v1, &objp->orient);
|
|
}
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
|
|
// call each frame for processing a ship's ABtrails
|
|
void ct_ship_process_ABtrails(ship *shipp)
|
|
{
|
|
int idx;
|
|
object *objp;
|
|
ship_info* sip;
|
|
|
|
Assert(shipp != NULL);
|
|
Assert(shipp->objnum >= 0);
|
|
objp = &Objects[shipp->objnum];
|
|
sip=&Ship_info[shipp->ship_info_index];
|
|
|
|
// if this is not a ship, we don't care
|
|
if((objp->type != OBJ_SHIP) || (Ships[objp->instance].ab_count <= 0)){
|
|
return;
|
|
}
|
|
|
|
// if the ship has no afterburner trail bitmap, don't bother with anything
|
|
if (sip->afterburner_trail.bitmap_id < 0)
|
|
return;
|
|
|
|
|
|
Assert(objp->instance >= 0);
|
|
shipp = &Ships[objp->instance];
|
|
|
|
|
|
if(!(objp->phys_info.flags & PF_AFTERBURNER_ON)){ //if the after burners aren't on -Bobboau
|
|
for(idx=0; idx<MAX_SHIP_CONTRAILS; idx++){
|
|
if(shipp->ABtrail_ptr[idx] != NULL)
|
|
{
|
|
trail_object_died(shipp->ABtrail_ptr[idx]);
|
|
shipp->ABtrail_ptr[idx] = NULL;
|
|
}
|
|
}
|
|
|
|
//No more abtrails
|
|
return;
|
|
}
|
|
|
|
// if the object already has ABtrails
|
|
if(ct_has_ABtrails(shipp)){
|
|
ct_update_ABtrails(shipp);
|
|
}
|
|
// otherwise add new ones
|
|
else {
|
|
ct_create_ABtrails(shipp);
|
|
}
|
|
|
|
/* if(shipp->ab_info->stamp > timestamp( (int)(shipp->ab_info->max_life * 1000) ) ){
|
|
for(idx=0; idx<MAX_SHIP_CONTRAILS; idx++){
|
|
if(shipp->ABtrail_num[idx] >= 0){
|
|
trail_object_died(shipp->ABtrail_num[idx]);
|
|
shipp->ABtrail_num[idx] = (short)-1;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
|
|
|
|
// create new ABtrails
|
|
void ct_create_ABtrails(ship *shipp)
|
|
{
|
|
vec3d v1;
|
|
int idx;
|
|
ship_info *sip;
|
|
object *objp;
|
|
|
|
// get object and ship info
|
|
Assert(shipp != NULL);
|
|
Assert(shipp->objnum >= 0);
|
|
Assert(shipp->ship_info_index >= 0);
|
|
objp = &Objects[shipp->objnum];
|
|
sip = &Ship_info[shipp->ship_info_index];
|
|
|
|
// if the ship has no afterburner trail bitmap, don't bother with anything
|
|
if (sip->afterburner_trail.bitmap_id < 0)
|
|
return;
|
|
|
|
if(objp->phys_info.flags & PF_AFTERBURNER_ON){//AB trails-Bobboau
|
|
|
|
for(idx=0; idx<shipp->ab_count; idx++)
|
|
{
|
|
|
|
shipp->ABtrail_ptr[idx] = trail_create(&shipp->ab_info[idx]);
|
|
if(shipp->ABtrail_ptr[idx] != NULL)
|
|
{
|
|
// get the point for the contrail
|
|
vm_vec_unrotate(&v1, &shipp->ab_info[idx].pt, &objp->orient);
|
|
vm_vec_add2(&v1, &objp->pos);
|
|
// if the spew stamp has elapsed
|
|
if(trail_stamp_elapsed(shipp->ABtrail_ptr[idx])){
|
|
trail_add_segment(shipp->ABtrail_ptr[idx], &v1, &objp->orient);
|
|
trail_set_stamp(shipp->ABtrail_ptr[idx]);
|
|
} else {
|
|
trail_set_segment(shipp->ABtrail_ptr[idx], &v1);
|
|
}
|
|
}
|
|
}
|
|
/* if( objp == Player_obj){
|
|
HUD_printf("trailnum %d", shipp->ABtrail_num[0]);
|
|
}
|
|
*/
|
|
|
|
}
|
|
}
|
|
|
|
// update active ABtrails - moving existing ones, adding new ones where necessary
|
|
void ct_update_ABtrails(ship *shipp)
|
|
{
|
|
vec3d v1;
|
|
int idx;
|
|
ship_info *sip;
|
|
object *objp;
|
|
|
|
// get object and ship info
|
|
Assert(shipp != NULL);
|
|
Assert(shipp->objnum >= 0);
|
|
Assert(shipp->ship_info_index >= 0);
|
|
objp = &Objects[shipp->objnum];
|
|
sip = &Ship_info[shipp->ship_info_index];
|
|
|
|
// if the ship has no afterburner trail bitmap, don't bother with anything
|
|
if (sip->afterburner_trail.bitmap_id < 0)
|
|
return;
|
|
|
|
for(idx=0; idx<MAX_SHIP_CONTRAILS; idx++){
|
|
if(objp->phys_info.flags & PF_AFTERBURNER_ON){//ABtrails
|
|
if(shipp->ABtrail_ptr[idx] != NULL){
|
|
// get the point for the contrail
|
|
vm_vec_unrotate(&v1, &shipp->ab_info[idx].pt, &objp->orient);
|
|
vm_vec_add2(&v1, &objp->pos);
|
|
|
|
// if the spew stamp has elapsed
|
|
if(trail_stamp_elapsed(shipp->ABtrail_ptr[idx])){
|
|
trail_add_segment(shipp->ABtrail_ptr[idx], &v1, &objp->orient);
|
|
trail_set_stamp(shipp->ABtrail_ptr[idx]);
|
|
} else {
|
|
trail_set_segment(shipp->ABtrail_ptr[idx], &v1);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
// if a ship has active ABtrails
|
|
int ct_has_ABtrails(ship *shipp)
|
|
{
|
|
int idx;
|
|
ship_info* sip=&Ship_info[shipp->ship_info_index];
|
|
|
|
// if the ship has no afterburner trail bitmap, don't bother with anything
|
|
if (sip->afterburner_trail.bitmap_id < 0)
|
|
return 0;
|
|
|
|
for(idx=0; idx<MAX_SHIP_CONTRAILS; idx++){
|
|
if(shipp->ABtrail_ptr[idx] != NULL){
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
|
|
// no contrails
|
|
return 0;
|
|
}
|
|
|
|
bool ct_display_contrails()
|
|
{
|
|
bool display;
|
|
|
|
// normally display trails in a full nebula environment
|
|
display = (The_mission.flags[Mission::Mission_Flags::Fullneb]) ? true : false;
|
|
|
|
// toggle according to flag
|
|
if (The_mission.flags[Mission::Mission_Flags::Toggle_ship_trails])
|
|
display = !display;
|
|
|
|
return display;
|
|
}
|