beyond-all-reason / spring

A powerful free cross-platform RTS game engine
https://beyond-all-reason.github.io/spring/
Other
182 stars 95 forks source link

Fault with 'nochasecategory' sometimes incorrectly invalidating viable targets #1471

Open TheSilverHornet opened 2 months ago

TheSilverHornet commented 2 months ago

To prune a long story short, fight command uses Enemy_InLos_ValidTarget to see if a target is valid, which in turn uses bool CMobileCAI::IsValidTarget

Which contains

if (owner->unitDef->noChaseCategory & enemy->category) return false

therefore in 'some cases' (I can't see why not all, however), fight commands will not realise an enemy that is in the 'nochasecategory' is something it should consider as a real target and stop moving when in range of.

Nochasecategory is intended to be what it says on the tin, eg a unit will still shoot and engage with units there, but not pursue if they run away. The code seems to not always amount to that end result.

https://github.com/beyond-all-reason/spring/blob/ab88be7e235eba1417dbfa07e95277b480283c0b/rts/Game/GameHelper.cpp#L491

https://github.com/beyond-all-reason/spring/blob/ab88be7e235eba1417dbfa07e95277b480283c0b/rts/Sim/Units/CommandAI/MobileCAI.cpp#L573

Discord discussions and more clips start around here: https://discord.com/channels/549281623154229250/724924957074915358/1233044341866369074

Example, this unit has 'nochasecategory="ALL"', will shoot a target as expected, but will not halt when fight-moved into range. (However razorbacks with same tag, do halt correctly when given same command, so there is something else at play too)

When the nochasecategory tag is removed, they will halt at fight distance correctly.

https://github.com/beyond-all-reason/spring/assets/37483246/de0a582f-e943-458d-833d-ee69cbce1134

https://github.com/beyond-all-reason/spring/assets/37483246/bbbad070-dd74-456e-99ae-ffee42cdda0e

TheSilverHornet commented 2 months ago

Units.zip corvoyr.zip ( Unit bos/cob and unitdef for the test unit above )

sprunk commented 2 months ago

Make a new tag because this behaviour (shoot a unit but don't stop for it) is useful.

GoogleFrog commented 1 month ago

I want units to not stop and shoot at nochase targets on Fight. To me this looked like intended behaviour.

TheSilverHornet commented 1 month ago

I want units to not stop and shoot at nochase targets on Fight. To me this looked like intended behaviour.

To me that's more a 'nohalt' than 'nochase'. I don't mind how it's available really, although the tag feels misnomer, so if another tag is created to allow 'halting at engagement range with valid targets but then not chasing them' that would work too.

The other issue is it's inconsistent if it applies or not, some other combination of tags is relevant. I had something very interesting with another branch that showed individual tags of the can* family made it apply or not, when combined, but not individually. Not yet sure what the exact combination that toggles it is though (with all applied, it will be ignored).

GoogleFrog commented 1 month ago

I think it helps to think about behaviours in terms of commands, when possible, so I don't know why you're talking in terms of chasing and halting. It's useful because a lot of complex behaviours are implemented via commands, which then implement simple behaviours, and doing it this way makes things more transparent to the player.

As far as I'm aware, all noChase does is stop units giving themselves Attack commands on some set of targets. The behaviour applies to Fight, Patrol, and while idle, as these are the ways that units can give themselves Attack commands. Your new tag sounds fine, but it is going to have to deal with Attack commands that are gained via Fight, when the target unit moves away. Games currently don't have much control over when such Attack commands are cancelled. I would possibly use it for a few things.

Also, naming things is hard, so I don't think a name not quite matching a behaviour is justification by itself for changing anything.

sprunk commented 1 month ago

However razorbacks with same tag, do halt correctly when given same command, so there is something else at play too

The razorback was idle for a moment before you gave the fight command and managed to give itself an attack command in that time. image

TheSilverHornet commented 1 month ago

I talk in outcomes as that's what matters, eg results. The commands/'intent' aren't consistently followed by units, whereas the actions/outcomes are tangible results to compare to.

I dug into this a while ago now and can't recall all of what I found about it offhand, but 'some units' with fight command and nochase will halt when they see something, others will blissfully walk on in. The pattern to which it is, is very nonobvious, and potentially relies on negating other tags that the unit might otherwise need to function. I'm not looking to solve everything about the jank (especially as it's inscrutable), I just need in some way, a unit to reliably be able to halt when it sees a valid weapon target (and ideally -only- a valid weapon target), without also chasing it when the the target retreats. 'defensivestance' might work well as a tag, perhaps?

TheSilverHornet commented 1 month ago

However razorbacks with same tag, do halt correctly when given same command, so there is something else at play too

The razorback was idle for a moment before you gave the fight command and managed to give itself an attack command in that time.

Noted in that case, good spot. Another more recent example then, mineclearing boats will try to autoattack boats (and halt) even when those boats aren't valid weapon targets, AND are included in nochase. Minelaying vehicles on the other hand will ignore everything, and the difference is in their can* tags seemingly, exact combination to trigger is unclear, but it's not any given one of them.

(The bug in that case is very minor and has minimal gameplay impact, but it might help as a test case to chase down what is causing some of the difference in behaviour)