From 22f9081bf7e130a6c189da9a6d0c041ac5ad7542 Mon Sep 17 00:00:00 2001 From: niffiwan Date: Mon, 2 Nov 2015 22:04:55 +1000 Subject: [PATCH] Allow countermeasures to decoy missiles once only Adds ai_profiles flag $countermeasures decoy a missile once: Also (re)adds logging to make it easier to figure out what the countermeasures are doing. Try adding "+countermeasures" to your debug_filter.cfg file. --- code/ai/ai_profiles.cpp | 2 ++ code/ai/ai_profiles.h | 1 + code/weapon/weapon.h | 1 + code/weapon/weapons.cpp | 58 +++++++++++++++++++++++++++++++++++++---- 4 files changed, 57 insertions(+), 5 deletions(-) diff --git a/code/ai/ai_profiles.cpp b/code/ai/ai_profiles.cpp index cc421fe4964..7c3951be75b 100644 --- a/code/ai/ai_profiles.cpp +++ b/code/ai/ai_profiles.cpp @@ -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:")) { diff --git a/code/ai/ai_profiles.h b/code/ai/ai_profiles.h index 5a493ed0012..144f0df5fb0 100644 --- a/code/ai/ai_profiles.h +++ b/code/ai/ai_profiles.h @@ -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 diff --git a/code/weapon/weapon.h b/code/weapon/weapon.h index a10e966e25f..5844c9be03a 100644 --- a/code/weapon/weapon.h +++ b/code/weapon/weapon.h @@ -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* cmeasure_ignore_list; // corkscrew info (taken out for now) short cscrew_index; // corkscrew info index diff --git a/code/weapon/weapons.cpp b/code/weapon/weapons.cpp index 57752d1cb62..6f8700bf121 100755 --- a/code/weapon/weapons.cpp +++ b/code/weapon/weapons.cpp @@ -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); @@ -4090,6 +4095,28 @@ 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; + 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; @@ -4097,12 +4124,32 @@ void find_homing_object_cmeasures_1(object *weapon_objp) // 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)); + } } } @@ -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