-
Notifications
You must be signed in to change notification settings - Fork 163
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
fix ai behavior when avoiding ship and weapon shockwaves #6378
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14556,7 +14556,11 @@ static int ai_find_shockwave_ship(object *objp) | |
shipp = &Ships[A->instance]; | ||
// Only look at objects in the process of dying. | ||
if (shipp->flags[Ship::Ship_Flags::Dying]) { | ||
float damage = ship_get_exp_damage(objp); | ||
float damage; | ||
if (The_mission.ai_profile->flags[AI::Profile_Flags::Fix_avoid_shockwave_bugs]) | ||
damage = ship_get_exp_damage(A); // A is the object that is actually exploding! | ||
else | ||
damage = ship_get_exp_damage(objp); | ||
|
||
if (damage >= EVADE_SHOCKWAVE_DAMAGE_THRESHOLD) { // Only evade quite large blasts | ||
float dist; | ||
|
@@ -14576,6 +14580,8 @@ static int ai_find_shockwave_ship(object *objp) | |
|
||
int aas_1(object *objp, ai_info *aip, vec3d *safe_pos) | ||
{ | ||
bool fix_bugs = The_mission.ai_profile->flags[AI::Profile_Flags::Fix_avoid_shockwave_bugs]; | ||
|
||
// MAKE SURE safe_pos DOES NOT TAKE US TOWARD THE A SHIP WE'RE ATTACKING. | ||
if (aip->ai_flags[AI::AI_Flags::Avoid_shockwave_weapon]) { | ||
// If we don't currently know of a weapon to avoid, try to find one. | ||
|
@@ -14636,7 +14642,24 @@ int aas_1(object *objp, ai_info *aip, vec3d *safe_pos) | |
} | ||
} | ||
|
||
if (!pos_set) { | ||
if (pos_set) { | ||
// if the object is not a small ship, a surface impact is likely to be some distance away from the ship center, so refine the position | ||
if (fix_bugs && target_ship_obj && !Ship_info[Ships[target_ship_obj->instance].ship_info_index].is_small_ship()) { | ||
mc_info mc; | ||
mc.model_instance_num = Ships[target_ship_obj->instance].model_instance_num; | ||
mc.model_num = Ship_info[Ships[target_ship_obj->instance].ship_info_index].model_num; | ||
mc.orient = &target_ship_obj->orient; | ||
mc.pos = &target_ship_obj->pos; | ||
mc.p0 = &weapon_objp->pos; // Point 1 of ray to check | ||
mc.p1 = &expected_pos; // Point 2 of ray to check | ||
mc.flags = MC_CHECK_MODEL; | ||
|
||
model_collide(&mc); | ||
if (mc.num_hits > 0) { | ||
expected_pos = mc.hit_point_world; | ||
} | ||
} | ||
} else { | ||
float time_scale; | ||
|
||
if (wip->lifetime - weaponp->lifeleft > 5.0f) { | ||
|
@@ -14682,12 +14705,13 @@ int aas_1(object *objp, ai_info *aip, vec3d *safe_pos) | |
Assert(aip->shockwave_object > -1); | ||
object *ship_objp = &Objects[aip->shockwave_object]; | ||
if (ship_objp == objp) { | ||
aip->shockwave_object = -1; | ||
aip->shockwave_object = -1; // this one was already present in retail | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are some additional weapon cases above which also return 0, but don't seem to reset There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There is of course the interesting There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok. I'm fine with whatever you go with, I figured I'd bring it up. |
||
return 0; | ||
} | ||
|
||
if (ship_objp->type != OBJ_SHIP) { | ||
aip->ai_flags.remove(AI::AI_Flags::Avoid_shockwave_ship); | ||
if (fix_bugs) aip->shockwave_object = -1; | ||
return 0; | ||
} | ||
|
||
|
@@ -14701,6 +14725,7 @@ int aas_1(object *objp, ai_info *aip, vec3d *safe_pos) | |
|
||
if (vm_vec_dist_quick(&objp->pos, &ship_objp->pos) > outer_rad*1.5f) { | ||
aip->ai_flags.remove(AI::AI_Flags::Avoid_shockwave_ship); | ||
if (fix_bugs) aip->shockwave_object = -1; | ||
return 0; | ||
} | ||
|
||
|
@@ -14720,16 +14745,37 @@ int aas_1(object *objp, ai_info *aip, vec3d *safe_pos) | |
int ai_avoid_shockwave(object *objp, ai_info *aip) | ||
{ | ||
vec3d safe_pos; | ||
bool fix_bugs = The_mission.ai_profile->flags[AI::Profile_Flags::Fix_avoid_shockwave_bugs]; | ||
|
||
// BIG|HUGE do not respond to shockwaves | ||
// Goober5000 - let's treat shockwave response the same way whether from weapon or ship | ||
if (!Ship_info[Ships[objp->instance].ship_info_index].avoids_shockwaves()) { | ||
// don't come here again | ||
aip->ai_flags.remove(AI::AI_Flags::Avoid_shockwave_ship); | ||
aip->ai_flags.remove(AI::AI_Flags::Avoid_shockwave_weapon); | ||
if (fix_bugs) aip->shockwave_object = -1; | ||
return 0; | ||
} | ||
|
||
// Don't try to evade a homing weapon until it starts homing | ||
if (fix_bugs && aip->ai_flags[AI::AI_Flags::Avoid_shockwave_weapon] && !(aip->ai_flags[AI::AI_Flags::Avoid_shockwave_started])) { | ||
// since the "don't all react right away" timer should only start when the weapon begins homing, we need the actual weapon now... | ||
// so choose the weapon ahead of time using the same technique aas_1() would normally use later | ||
if (aip->shockwave_object == -1) { | ||
aip->shockwave_object = ai_find_shockwave_weapon(objp); | ||
if (aip->shockwave_object == -1) { | ||
aip->ai_flags.remove(AI::AI_Flags::Avoid_shockwave_weapon); | ||
return 0; | ||
} | ||
} | ||
|
||
// if this is a homing weapon that isn't homing, don't react yet | ||
auto wp = &Weapons[Objects[aip->shockwave_object].instance]; | ||
if (Weapon_info[wp->weapon_info_index].is_homing() && IS_VEC_NULL(&wp->homing_pos)) { | ||
return 0; | ||
} | ||
} | ||
|
||
// Don't all react right away. | ||
if (!(aip->ai_flags[AI::AI_Flags::Avoid_shockwave_started])) { | ||
float evadeChance = (aip->ai_shockwave_evade_chance == FLT_MIN) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm loathe to add more collision checks unless absolutely necessary, especially since this appears to be called every frame for a thing which is in the average case unlikely to move much (and also this case doesn't need tons of accuracy, some approximation/lag should be fine), so at the very least the result should probably be cached.
Alternatively, have you considered just using the weapon's
homing_pos
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a fair point, and I had the same reluctance, but I ended up adding it after seeing how many collision checks were used elsewhere in the code, and due to the difficulty of solving this problem without a collision check. I'm certainly open to suggestions though. And I could cache the result, at the cost of adding some additional fields to
ai_info
.The weapon's
homing_pos
will work if the missile is homing on a subsystem, but will not work if the weapon is homing on the actual ship, since the position will be at the center of the ship.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On a large ship, the
homing_pos
shouldn't be the center of the ship, see the usage ofai_big_pick_attack_point
inweapon_home
. They tend to spread themselves over the hull surface on the side facing the missile.