Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement Mantis 1947, treat ship comm systems the same as player comm systems #2342

Merged
merged 7 commits into from May 10, 2020
1 change: 1 addition & 0 deletions code/ai/ai_flags.h
Expand Up @@ -84,6 +84,7 @@ namespace AI {
Assist_scoring_scales_with_damage,
Beams_damage_weapons,
Big_ships_can_attack_beam_turrets_on_untargeted_ships,
Check_comms_for_non_player_ships,
Disable_linked_fire_penalty,
Disable_weapon_damage_scaling,
Dont_insert_random_turret_fire_delay,
Expand Down
2 changes: 2 additions & 0 deletions code/ai/ai_profiles.cpp
Expand Up @@ -371,6 +371,8 @@ void parse_ai_profiles_tbl(const char *filename)

set_flag(profile, "$navigation subsystem governs warpout capability:", AI::Profile_Flags::Navigation_subsys_governs_warp);

set_flag(profile, "$check communications for non-player ships:", AI::Profile_Flags::Check_comms_for_non_player_ships);

set_flag(profile, "$ignore lower bound for minimum speed of docked ship:", AI::Profile_Flags::No_min_dock_speed_cap);

set_flag(profile, "$disable linked fire penalty:", AI::Profile_Flags::Disable_linked_fire_penalty);
Expand Down
4 changes: 4 additions & 0 deletions code/ai/aicode.cpp
Expand Up @@ -66,6 +66,7 @@
#include "ship/ship.h"
#include "ship/shipfx.h"
#include "ship/shiphit.h"
#include "ship/subsysdamage.h"
#include "weapon/beam.h"
#include "weapon/flak.h"
#include "weapon/swarm.h"
Expand Down Expand Up @@ -14528,6 +14529,9 @@ void process_friendly_hit_message( int message, object *objp )
if (Ships[objp->instance].flags[Ship::Ship_Flags::No_builtin_messages]) {
index = -1;
}
if (The_mission.ai_profile->flags[AI::Profile_Flags::Check_comms_for_non_player_ships] && hud_communications_state(&Ships[objp->instance]) <= COMM_DAMAGED) {
index = -1;
}

// Karajorma - pick a random ship to send Command messages if command is silenced.
if (index < 0 && (The_mission.flags[Mission::Mission_Flags::No_builtin_command]) ) {
Expand Down
118 changes: 43 additions & 75 deletions code/hud/hudsquadmsg.cpp
Expand Up @@ -238,8 +238,9 @@ SCP_vector<squadmsg_history> Squadmsg_history;
// forward declarations
void hud_add_issued_order(const char *name, int order);
void hud_update_last_order(char *target, int order_source, int special_index);
int hud_squadmsg_is_target_order_valid(int order, int find_order, ai_info *aip = NULL );
int hud_squadmsg_ship_order_valid( int shipnum, int order );
bool hud_squadmsg_is_target_order_valid(int order, int find_order, ai_info *aip = nullptr);
bool hud_squadmsg_ship_valid(ship *shipp, object *objp = nullptr);
bool hud_squadmsg_ship_order_valid( int shipnum, int order );

// function to set up variables needed when messaging mode is started
void hud_squadmsg_start()
Expand Down Expand Up @@ -300,31 +301,15 @@ bool hud_squadmsg_exist_fighters( )
{
objp = &Objects[so->objnum];
shipp = &Ships[objp->instance];
Assert ( shipp->objnum != -1 );
Assertion(shipp->objnum != -1, "hud_squadmsg_exist_fighters() discovered that ship #%d ('%s') has an objnum of -1. Since the ship was retrieved from its object number (%d), this should be impossible; get a coder!\n", objp->instance, shipp->ship_name, so->objnum);

// check fighter is accepting orders
if (shipp->orders_accepted == 0)
continue;

// be sure ship is on correct team
#ifdef NDEBUG
if (shipp->team != Player_ship->team)
continue;
#else
if (!Msg_enemies && (shipp->team != Player_ship->team))
continue;
#endif

// cannot be my ship or an instructor
if ((objp == Player_obj) || is_instructor(objp))
continue;

// ship must be a fighter/bomber
if ( !(Ship_info[shipp->ship_info_index].is_fighter_bomber()) )
if (!(Ship_info[shipp->ship_info_index].is_fighter_bomber()))
continue;

// this ship satisfies everything
return true;
if (hud_squadmsg_ship_valid(shipp, objp))
return true;
}

return false;
Expand All @@ -337,7 +322,7 @@ bool hud_squadmsg_ship_valid(ship *shipp, object *objp)
if (!objp) // For simplicity's sake, allow it to be called with just the ship pointer
objp = &Objects[shipp->objnum];

// ships must be able to receive a message
// ships must be able to receive orders
if ( Ship_info[shipp->ship_info_index].class_type < 0 || !(Ship_types[Ship_info[shipp->ship_info_index].class_type].flags[Ship::Type_Info_Flags::AI_accept_player_orders]) )
return false;

Expand Down Expand Up @@ -374,6 +359,10 @@ bool hud_squadmsg_ship_valid(ship *shipp, object *objp)
return false;
}

// maybe check comm system
if (The_mission.ai_profile->flags[AI::Profile_Flags::Check_comms_for_non_player_ships] && hud_communications_state(shipp) != COMM_OK)
return false;

// If we got to this point, the ship must be valid.
return true;
}
Expand Down Expand Up @@ -420,14 +409,14 @@ int hud_squadmsg_count_ships(int add_to_menu)
}

// routine to return true if a wing should be put onto the messaging menu
int hud_squadmsg_wing_valid(wing *wingp)
bool hud_squadmsg_wing_valid(wing *wingp)
{
int idx, ship_num;

// a couple of special cases to account for before adding to count (or to menu). Don't count
// wings that are leaving or left.
if ( wingp->flags[Ship::Wing_Flags::Gone, Ship::Wing_Flags::Departing] )
return 0;
return false;

// Goober5000 - instead of checking wing leader, let's check all ships in wing;
// there are several significant cases when e.g. wings contain ships of different IFFs
Expand All @@ -436,34 +425,13 @@ int hud_squadmsg_wing_valid(wing *wingp)
ship_num = wingp->ship_index[idx];
Assert(ship_num >= 0);

// don't check player
if (ship_num == SHIP_INDEX(Player_ship))
continue;

// be sure ship is on same team
#ifdef NDEBUG
if (Ships[ship_num].team != Player_ship->team)
continue;
#else
if (!Msg_enemies && (Ships[ship_num].team != Player_ship->team))
continue;
#endif

// check if ship is accepting orders
if (Ships[ship_num].orders_accepted == 0)
continue;

// if doing a message shortcut is being used, be sure the ship can "accept" the command.
if ( Msg_shortcut_command >= 0 && !(Ships[ship_num].orders_accepted & Msg_shortcut_command) )
return 0;


// at least one ship in this wing is valid, and that's all we need
return 1;
// if at least one ship in this wing is valid, that's all we need
if (hud_squadmsg_ship_valid(&Ships[ship_num]))
return true;
}

// no ships in the wing were valid
return 0;
return false;
}

// function like above, except for wings
Expand Down Expand Up @@ -766,8 +734,8 @@ void hud_squadmsg_repair_rearm_abort( int toggle_state, object *obj)
}

// Goober5000 - redone and added a bit
// returns 1 if an order is valid for a ship. Applies to things like departure when engines are blown, etc.
int hud_squadmsg_ship_order_valid( int shipnum, int order )
// returns true if an order is valid for a ship. Applies to things like departure when engines are blown, etc.
bool hud_squadmsg_ship_order_valid( int shipnum, int order )
{
// Goober5000
Assert( shipnum >= 0 && shipnum < MAX_SHIPS );
Expand All @@ -778,7 +746,7 @@ int hud_squadmsg_ship_order_valid( int shipnum, int order )
case DEPART_ITEM:
// disabled ships can't depart.
if (shipp->flags[Ship::Ship_Flags::Disabled])
return 0;
return false;

// Goober5000: also can't depart if no subspace drives and no valid mothership
if (shipp->flags[Ship::Ship_Flags::No_subspace_drive])
Expand All @@ -788,21 +756,21 @@ int hud_squadmsg_ship_order_valid( int shipnum, int order )
{
int anchor_shipnum = ship_name_lookup(Parse_names[shipp->departure_anchor]);
if (anchor_shipnum >= 0 && ship_useful_for_departure(anchor_shipnum, shipp->departure_path_mask))
return 1;
return true;
}

return 0;
return false;
}

break;
}
return 1;
return true;
}

// returns true or false if the Players target is valid for the given order
// find_order is true when we need to search the comm_orders array for the order entry. We have
// to do this action in some cases since all we know is the actual "value" of the order
int hud_squadmsg_is_target_order_valid(int order, int find_order, ai_info *aip )
bool hud_squadmsg_is_target_order_valid(int order, int find_order, ai_info *aip )
{
int target_objnum, i;
ship *shipp, *ordering_shipp;
Expand All @@ -823,77 +791,77 @@ int hud_squadmsg_is_target_order_valid(int order, int find_order, ai_info *aip )

// orders which don't operate on targets are always valid
if ( !(Comm_orders[order].item & TARGET_MESSAGES) )
return 1;
return true;

target_objnum = aip->target_objnum;

// order isn't valid if there is no player target
if ( target_objnum == -1 ) {
return 0;
return false;
}

objp = &Objects[target_objnum];

ordering_shipp = &Ships[aip->shipnum];

// target isn't a ship, then return 0
// target isn't a ship, then return false
if ( (objp->type != OBJ_SHIP) && (objp->type != OBJ_WEAPON) )
return 0;
return false;

// if it's a weapon, then it needs to be a WIF_BOMB weapon. Only attack order valid, and only
// valid on bombs not on the player's team
// MageKing17: Now also works on WIF3_FIGHTER_INTERCEPTABLE weapons.
if ( objp->type == OBJ_WEAPON ) {

if (Weapons[objp->instance].lssm_stage==3){
return 0;
return false;
}

if ( (Comm_orders[order].item == ATTACK_TARGET_ITEM )
&& ((Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Bomb]) || (Weapon_info[Weapons[objp->instance].weapon_info_index].wi_flags[Weapon::Info_Flags::Fighter_Interceptable]))
&& (Weapons[objp->instance].team != ordering_shipp->team) )

return 1;
&& (Weapons[objp->instance].team != ordering_shipp->team) ) {
return true;
}

return 0;
return false;
}

Assert( objp->type == OBJ_SHIP );

shipp = &Ships[objp->instance];

// if target is a navbouy, return 0
// if target is a navbouy, return false
if ( Ship_info[shipp->ship_info_index].flags[Ship::Info_Flags::Navbuoy] ){
return 0;
return false;
}

// if we are messaging a ship, and that ship is our target, no target type orders are ever active
if ( (Squad_msg_mode == SM_MODE_SHIP_COMMAND) && (Objects[target_objnum].instance == Msg_instance) ){
return 0;
return false;
}

// if the order is a disable order or depart, and the ship is disabled, order isn't active
if ( (Comm_orders[order].item == DISABLE_TARGET_ITEM) && (shipp->flags[Ship::Ship_Flags::Disabled]) ){
return 0;
return false;
}

// same as above except for disarmed.
if ( (Comm_orders[order].item == DISARM_TARGET_ITEM) && ((shipp->subsys_info[SUBSYSTEM_TURRET].type_count == 0) || (shipp->subsys_info[SUBSYSTEM_TURRET].aggregate_current_hits <= 0.0f)) ){
return 0;
return false;
}

// if order is disable subsystem, and no subsystem targeted or no hits, then order not valid
if ( (Comm_orders[order].item == DISABLE_SUBSYSTEM_ITEM) && ((aip->targeted_subsys == NULL) || (aip->targeted_subsys->current_hits <= 0.0f)) ){
return 0;
return false;
}

// check based on target's and player's team
if ( (shipp->team == ordering_shipp->team) && (FRIENDLY_TARGET_MESSAGES & Comm_orders[order].item) ){
return 1;
return true;
} else if ( (shipp->team != ordering_shipp->team) && (ENEMY_TARGET_MESSAGES & Comm_orders[order].item) ){
return 1;
return true;
} else {
return 0;
return false;
}
}

Expand Down
12 changes: 6 additions & 6 deletions code/hud/hudtarget.cpp
Expand Up @@ -4556,7 +4556,7 @@ int hud_sensors_ok(ship *sp, int show_msg)
}
}

int hud_communications_state(ship *sp)
int hud_communications_state(ship *sp, bool for_death_scream)
{
float str;

Expand All @@ -4570,18 +4570,18 @@ int hud_communications_state(ship *sp)
if ((sp == Player_ship) && (sp->flags[Ship::Ship_Flags::Dying]))
return COMM_OK;

// Goober5000 - check for scrambled communications
if ( emp_active_local() || sp->flags[Ship::Ship_Flags::Scramble_messages] )
return COMM_SCRAMBLED;

str = ship_get_subsystem_strength( sp, SUBSYSTEM_COMMUNICATION );
str = ship_get_subsystem_strength( sp, SUBSYSTEM_COMMUNICATION, for_death_scream );

if ( (str <= 0.01) || ship_subsys_disrupted(sp, SUBSYSTEM_COMMUNICATION) ) {
return COMM_DESTROYED;
} else if ( str < MIN_COMM_STR_TO_MESSAGE ) {
return COMM_DAMAGED;
}

// Goober5000 - check for scrambled communications
if (emp_active_local() || sp->flags[Ship::Ship_Flags::Scramble_messages])
return COMM_SCRAMBLED;

return COMM_OK;
}

Expand Down
2 changes: 1 addition & 1 deletion code/hud/hudtarget.h
Expand Up @@ -125,7 +125,7 @@ void hud_update_weapon_flash();
void hud_process_homing_missiles(void);

int hud_sensors_ok(ship *sp, int show_msg = 1);
int hud_communications_state(ship *sp);
int hud_communications_state(ship *sp, bool for_death_scream = false);

int hud_get_best_primary_bank(float *range);
void hud_target_toggle_hidden_from_sensors();
Expand Down