Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions code/ai/ai_profiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,8 @@ void parse_ai_profiles_tbl(const char *filename)

set_flag(profile, "$glide decay requires thrust:", AIPF2_GLIDE_DECAY_REQUIRES_THRUST, AIP_FLAG2);

set_flag(profile, "$countermeasures decoy a missile once:", AIPF2_COUNTERMEASURES_DECOY_ONCE, AIP_FLAG2);

profile->bay_arrive_speed_mult = 1.0f;
profile->bay_depart_speed_mult = 1.0f;
if (optional_string("$bay arrive speed multiplier:")) {
Expand Down
1 change: 1 addition & 0 deletions code/ai/ai_profiles.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
#define AIPF2_STRICT_TURRET_TAGGED_ONLY_TARGETING (1 << 14)
#define AIPF2_ASPECT_INVULNERABILITY_FIX (1 << 15)
#define AIPF2_GLIDE_DECAY_REQUIRES_THRUST (1 << 16)
#define AIPF2_COUNTERMEASURES_DECOY_ONCE (1 << 17)

// AI Path types
#define AI_PATH_MODE_NORMAL 0
Expand Down
1 change: 1 addition & 0 deletions code/weapon/weapon.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,7 @@ typedef struct weapon {

int cmeasure_ignore_objnum; // Ignoring this countermeasure. It's failed to attract this weapon.
int cmeasure_chase_objnum; // Chasing this countermeasure. Don't maybe ignore in future.
SCP_vector<int>* cmeasure_ignore_list;

// corkscrew info (taken out for now)
short cscrew_index; // corkscrew info index
Expand Down
58 changes: 53 additions & 5 deletions code/weapon/weapons.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3859,6 +3859,11 @@ void weapon_delete(object *obj)
snd_stop(wp->hud_in_flight_snd_sig);
}

if (wp->cmeasure_ignore_list != nullptr) {
delete wp->cmeasure_ignore_list;
wp->cmeasure_ignore_list = nullptr;
}

wp->objnum = -1;
Num_weapons--;
Assert(Num_weapons >= 0);
Expand Down Expand Up @@ -4090,19 +4095,61 @@ void find_homing_object_cmeasures_1(object *weapon_objp)
if (dist < cm_wip->cm_effective_rad)
{
float chance;
bool cmeasure_once = The_mission.ai_profile->flags2 & AIPF2_COUNTERMEASURES_DECOY_ONCE;
if (cmeasure_once) {
if (wp->cmeasure_ignore_list == nullptr) {
wp->cmeasure_ignore_list = new SCP_vector<int>;
wp->cmeasure_ignore_list->reserve(cm_wip->shots * 2); // guesstimate the number of CMs this weapon will see
}
else {
bool found = false;
for (auto ii = wp->cmeasure_ignore_list->cbegin(); ii != wp->cmeasure_ignore_list->cend(); ++ii) {
if (objp->signature == *ii) {
nprintf(("CounterMeasures", "Weapon (%s-%04i) already seen CounterMeasure (%s-%04i) Frame: %i\n",
wip->name, weapon_objp->instance, cm_wip->name, objp->signature, Framecount));
found = true;
break;
}
}
if (found) {
continue;
}
}
}

if (wip->wi_flags & WIF_HOMING_ASPECT) {
// aspect seeker this likely to chase a countermeasure
chance = cm_wip->cm_aspect_effectiveness/wip->seeker_strength;
} else {
// heat seeker and javelin HS this likely to chase a countermeasure
chance = cm_wip->cm_heat_effectiveness/wip->seeker_strength;
}
if ((objp->signature != wp->cmeasure_ignore_objnum) && (objp->signature != wp->cmeasure_chase_objnum))
{

if (cmeasure_once) {
wp->cmeasure_ignore_list->push_back(objp->signature); // this CM has had its chance; ignore in future
if (frand() >= chance) {
wp->cmeasure_ignore_objnum = objp->signature; // Don't process this countermeasure again.
} else {
wp->cmeasure_chase_objnum = objp->signature; // Don't process this countermeasure again.
nprintf(("CounterMeasures", "Weapon (%s-%04i) ignoring CounterMeasure (%s-%04i) Frame: %i\n",
wip->name, weapon_objp->instance, cm_wip->name, objp->signature, Framecount));
continue; // no decoy, no need to adjust homing object below
}
else {
// since we don't set cmeasure_ignore_objnum, it'll be -1 and thus not trigger the comparison below
nprintf(("CounterMeasures", "Weapon (%s-%04i) chasing CounterMeasure (%s-%04i) Frame: %i\n",
wip->name, weapon_objp->instance, cm_wip->name, objp->signature, Framecount));
}
}
else {
if ((objp->signature != wp->cmeasure_ignore_objnum) && (objp->signature != wp->cmeasure_chase_objnum))
{
if (frand() >= chance) {
wp->cmeasure_ignore_objnum = objp->signature; // Don't process this countermeasure again.
nprintf(("CounterMeasures", "Weapon (%s-%04i) ignoring CounterMeasure (%s-%04i) Frame: %i\n",
wip->name, weapon_objp->instance, cm_wip->name, objp->signature, Framecount));
} else {
wp->cmeasure_chase_objnum = objp->signature; // Don't process this countermeasure again.
nprintf(("CounterMeasures", "Weapon (%s-%04i) chasing CounterMeasure (%s-%04i) Frame: %i\n",
wip->name, weapon_objp->instance, cm_wip->name, objp->signature, Framecount));
}
}
}

Expand Down Expand Up @@ -5349,6 +5396,7 @@ int weapon_create( vec3d * pos, matrix * porient, int weapon_type, int parent_ob
wp->target_sig = -1;
wp->cmeasure_ignore_objnum = -1;
wp->cmeasure_chase_objnum = -1;
wp->cmeasure_ignore_list = nullptr;
wp->det_range = wip->det_range;

// Init the thruster info
Expand Down