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

fix ai behavior when avoiding ship and weapon shockwaves #6378

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

Goober5000
Copy link
Contributor

@Goober5000 Goober5000 commented Oct 1, 2024

The FreeSpace AI includes behavior to run away from shockwaves to try to avoid explosion damage. This is implemented for both ships and missiles, although the missile implementation has been buggy ever since retail. There are several issues:

  1. The AI attempts to evade a weapon immediately upon launch. Many missiles have a period of free flight before they start homing on their target. During the free flight period, the homing position is not set. Consequently, the AI will not know the position to avoid and will make assumptions.
  2. The AI assumes the shockwave-producing weapon will detonate at the center of the ship it is targeting, although missiles detonate on the surface. A capital ship is likely to be significantly larger than the weapon's blast radius, leading the AI to believe the detonation will be much farther away than it actually is.
  3. When avoiding ship shockwaves, the shockwave_object field is not cleared when avoiding is complete. This can result in stale references (though not crashes, due to object type checks), causing AI to not avoid future explosions in certain cases.
  4. When avoiding ship shockwaves, the code does not check the correct ship for the amount of damage caused by the shockwave.

All of these issues are now fixed. Since this is a change in AI behavior, these fixes are tied to a new AI profiles flag.

Already tested, but in draft pending additional tests. Tested with both ship and weapon shockwaves.

@Goober5000 Goober5000 added enhancement A new feature or upgrade of an existing feature to add additional functionality. fix A fix for bugs, not-a-bugs, and/or regressions. ai A feature or issue related to the AI algorithms Waiting for Stable Marks a pull request that is to be merged after the next stable release, due to a release cycle Requested by Active Mod A feature request that has been requested by a mod that is actively in development. labels Oct 1, 2024
@Goober5000 Goober5000 added this to the Release 25.0 milestone Oct 1, 2024
@Goober5000 Goober5000 force-pushed the fixed_ai_avoid_weapon_shockwave branch 4 times, most recently from b9beefe to 4e0419d Compare October 7, 2024 03:52
@Goober5000 Goober5000 marked this pull request as ready for review October 7, 2024 04:53
@Goober5000 Goober5000 changed the title fix ai behavior when avoiding weapon shockwaves fix ai behavior when avoiding ship and weapon shockwaves Oct 10, 2024
@Goober5000 Goober5000 force-pushed the fixed_ai_avoid_weapon_shockwave branch from 4e0419d to 73cff97 Compare October 10, 2024 01:33
mc.p1 = &expected_pos; // Point 2 of ray to check
mc.flags = MC_CHECK_MODEL;

model_collide(&mc);
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Member

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 of ai_big_pick_attack_point in weapon_home. They tend to spread themselves over the hull surface on the side facing the missile.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I finally had a chance to get back to this. I modified the code to print debug output every frame to show the coordinates being used. Here is the output for homing on one of the turrets:

expected_pos: [x=7417.05, y=-108.33, z=637.62]    weapon homing_pos: [x=7421.30, y=-106.31, z=630.08]    center of ship: [x=7862.55, y=0.00, z=581.01]    expected-homing: 8.89    expected-center: 461.97    homing-center: 456.52
expected_pos: [x=7417.05, y=-108.33, z=637.62]    weapon homing_pos: [x=7421.30, y=-106.31, z=630.08]    center of ship: [x=7862.55, y=0.00, z=581.01]    expected-homing: 8.89    expected-center: 461.97    homing-center: 456.52
expected_pos: [x=7417.05, y=-108.33, z=637.62]    weapon homing_pos: [x=7421.30, y=-106.31, z=630.08]    center of ship: [x=7862.55, y=0.00, z=581.01]    expected-homing: 8.89    expected-center: 461.97    homing-center: 456.52
expected_pos: [x=7417.05, y=-108.33, z=637.62]    weapon homing_pos: [x=7421.30, y=-106.31, z=630.08]    center of ship: [x=7862.55, y=0.00, z=581.01]    expected-homing: 8.89    expected-center: 461.97    homing-center: 456.52
expected_pos: [x=7417.05, y=-108.33, z=637.62]    weapon homing_pos: [x=7421.30, y=-106.31, z=630.08]    center of ship: [x=7862.55, y=0.00, z=581.01]    expected-homing: 8.89    expected-center: 461.97    homing-center: 456.52
...

And here is the output for homing on the ship with no subsystem selected:

expected_pos: [x=7483.91, y=-133.26, z=826.83]    weapon homing_pos: [x=7862.55, y=0.00, z=581.01]    center of ship: [x=7862.55, y=0.00, z=581.01]    expected-homing: 470.70    expected-center: 470.70    homing-center: 0.00
expected_pos: [x=7483.91, y=-133.26, z=826.83]    weapon homing_pos: [x=7862.55, y=0.00, z=581.01]    center of ship: [x=7862.55, y=0.00, z=581.01]    expected-homing: 470.70    expected-center: 470.70    homing-center: 0.00
expected_pos: [x=7483.91, y=-133.26, z=826.83]    weapon homing_pos: [x=7862.55, y=0.00, z=581.01]    center of ship: [x=7862.55, y=0.00, z=581.01]    expected-homing: 470.70    expected-center: 470.70    homing-center: 0.00
expected_pos: [x=7483.91, y=-133.26, z=826.83]    weapon homing_pos: [x=7862.55, y=0.00, z=581.01]    center of ship: [x=7862.55, y=0.00, z=581.01]    expected-homing: 470.70    expected-center: 470.70    homing-center: 0.00
expected_pos: [x=7483.91, y=-133.26, z=826.83]    weapon homing_pos: [x=7862.55, y=0.00, z=581.01]    center of ship: [x=7862.55, y=0.00, z=581.01]    expected-homing: 470.70    expected-center: 470.70    homing-center: 0.00
...

This confirms what I discovered last month -- the homing_pos is close enough if the weapon is homing on a subsystem (or turret), but is equivalent to the center of the ship if the weapon is homing on the ship.

I took a deeper look through the code and found that the octant picking is never actually called. This is because the wp->pick_big_attack_point_timestamp is always 0 (i.e. invalid) and never elapses. This is actually intentional:

// If player has apect lock, we don't want to find a homing point on the closest
// octant... setting the timestamp to 0 ensures this.
if (wip->is_locked_homing()) {
	wp->pick_big_attack_point_timestamp = 0;
} else {
	wp->pick_big_attack_point_timestamp = 1;
}

Then the "preliminary" attack point, which is used if the octant picking code fails or is bypassed, is set as follows:

if (pp && pp->locking_subsys) {
	wp->big_attack_point = pp->locking_subsys->system_info->pnt;
} else {
	vm_vec_zero(&wp->big_attack_point);
}

So anyway, that was a bit of a detour, but was informative. In any case, I'll figure out a way to cache the expected position so the collision check doesn't need to run every frame.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't that just for player missiles? (Not that I am trying to imply that is an irrelevant case)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, that's a good point -- that is inside a block that checks for the player ship.

code/ai/aicode.cpp Show resolved Hide resolved
@Goober5000 Goober5000 force-pushed the fixed_ai_avoid_weapon_shockwave branch from 73cff97 to 869596d Compare October 21, 2024 04:39
@Goober5000 Goober5000 removed the Waiting for Stable Marks a pull request that is to be merged after the next stable release, due to a release cycle label Oct 28, 2024
@Goober5000 Goober5000 force-pushed the fixed_ai_avoid_weapon_shockwave branch 4 times, most recently from 3b79162 to 7f788a9 Compare November 4, 2024 03:33
@Goober5000 Goober5000 force-pushed the fixed_ai_avoid_weapon_shockwave branch from 7f788a9 to 0e54ccc Compare November 10, 2024 20:00
The FreeSpace AI includes behavior to run away from shockwaves to try to avoid explosion damage.  This is implemented for both ships and missiles, although the missile implementation has been buggy ever since retail.  There are several issues:

1. The AI attempts to evade a weapon immediately upon launch.  Many missiles have a period of free flight before they start homing on their target.  During the free flight period, the homing position is not set.  Consequently, the AI will not know the position to avoid and will make assumptions.
2. The AI assumes the shockwave-producing weapon will detonate at the center of the ship it is targeting, although missiles detonate on the surface.  A capital ship is likely to be significantly larger than the weapon's blast radius, leading the AI to believe the detonation will be much farther away than it actually is.
3. When avoiding ship shockwaves, the `shockwave_object` field is not cleared when avoiding is complete.  This can result in stale references (though not crashes, due to object type checks), causing AI to not avoid future explosions in certain cases.
4. When avoiding ship shockwaves, the code does not check the correct ship for the amount of damage caused by the shockwave.

All of these issues are now fixed.  Since this is a change in AI behavior, these fixes are tied to a new AI profiles flag.
@Goober5000 Goober5000 force-pushed the fixed_ai_avoid_weapon_shockwave branch from 0e54ccc to 03bf756 Compare November 12, 2024 05:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ai A feature or issue related to the AI algorithms enhancement A new feature or upgrade of an existing feature to add additional functionality. fix A fix for bugs, not-a-bugs, and/or regressions. Requested by Active Mod A feature request that has been requested by a mod that is actively in development.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants