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

Issue #1084 - Allow choosing target tile for meleeing adjacent targets #1106

Merged

Conversation

Iridar
Copy link
Contributor

@Iridar Iridar commented Dec 7, 2021

Fixes #1084

Also adds a couple helper methods into CHHelpers to be used by this issue or mods.


I've traced the problem to X2MeleePathingPawn::UpdateMeleeTarget(), which calls very native class'X2AbilityTarget_MovingMelee'.static.SelectAttackTile().

When melee-ing adjacent targets, SelectAttackTile() only writes one tile into the PossibleTiles out array.

I suggest addressing this issue by inserting custom unreal script logic that will run in case SelectAttackTile() gives only one tile. Said custom logic will simply take a look at the target, and insert more tiles into the PossibleTiles array.

If it sounds good, I could use some help in setting up that custom logic so that we only insert tiles that are actually reachable by the soldier.

@Iridar Iridar self-assigned this Dec 7, 2021
@Iridar
Copy link
Contributor Author

Iridar commented Dec 7, 2021

Hmm I just realized class'X2AbilityTarget_MovingMelee'.static.IsValidAttackTile() exists, I'll see if that can be used here.

@Iridar
Copy link
Contributor Author

Iridar commented Dec 8, 2021

Okay, I generally got it working, the only problem is that now I'm unable to attack from the tile the attacker is standing on. I.e. the situation is reversed, previously you could only attack from the original tile, now you can attack from every tile except the original one.

The tile the attacker is standing on is selected by default, but once you move the cursor from it, you cannot return, until you cancel out ability target.

I think some piece of logic somewhere disallows attacking from the original tile, because that tile is occupied, and doesn't check that it's occupied by the unit itself. Currently looking for that logic.

@Iridar
Copy link
Contributor Author

Iridar commented Dec 8, 2021

Traced the problem to XComPathingPawn::RebuildPathingInformation() but oh boy there's a lotta code there.

@Iridar
Copy link
Contributor Author

Iridar commented Dec 8, 2021

Apparently Cursor.GetCursorFeetLocation() raises the Z of the returned tile if the cursor is hovering on a tile occupied by a unit (the melee attacker). So CursorTile will never be directly equal to AttackerUnit.TileLocation, which borks the game's logic in at least two separate places.

@Iridar
Copy link
Contributor Author

Iridar commented Dec 8, 2021

Disregard the previous comment, it was only one place. Should be working now. Note: I've added support only for mouse targeting, I don't know if the controller targeting requires special handling in this regard and don't plan to do a single thing about it.

@Iridar Iridar added ready-to-review A pull request is ready to be reviewed and removed help wanted labels Dec 8, 2021
@Iridar Iridar added this to the 1.24.0 milestone Dec 8, 2021
@Iridar
Copy link
Contributor Author

Iridar commented Dec 10, 2021

Note to self: investigate maybe using this:

// Find all adjacent tiles to target that are valid for melee attacking. This only looks at tiles adjacent to the target.
// ( Currently written only for attackers of UnitSize 1. )
static native function bool FindTilesForMeleeAttack(XComGameState_Unit Target, out Array Tiles);

@Iridar Iridar added waiting-on-author A pull request is waiting on changes from the author and removed ready-to-review A pull request is ready to be reviewed labels Dec 15, 2021
@Iridar
Copy link
Contributor Author

Iridar commented Jan 19, 2022

static native function bool FindTilesForMeleeAttack(XComGameState_Unit Target, out Array Tiles);

The moment I started looking into it, I realized that this function only takes a unit as the potential target, so it wouldn't work for destructible objects like alien relay. The code that is currently in this PR does work in this case.

In theory I could try using the FindTilesForMeleeAttack() against units and my own code against destructible objects, but I don't think it's worth the effort and added complexity. My code is simple and not calculation-intensive, and the calling function itself is not hot code, it runs once when the targeting method selects the specific target.

As such, I think current implementation should stand.

@Iridar Iridar added ready-to-review A pull request is ready to be reviewed and removed waiting-on-author A pull request is waiting on changes from the author labels Jan 19, 2022
@Iridar
Copy link
Contributor Author

Iridar commented Jan 27, 2022

Current version of this PR does not properly interact with large units, like Sectopods, working on a fix.

@Iridar Iridar added waiting-on-author A pull request is waiting on changes from the author and removed ready-to-review A pull request is ready to be reviewed labels Jan 27, 2022
@Iridar Iridar force-pushed the 1084-allow-adjacent-melee-targeting branch from 7bbb8c7 to d1b4137 Compare January 27, 2022 18:41
@Iridar
Copy link
Contributor Author

Iridar commented Jan 27, 2022

Current code can probably be further optimized, particularly this cycle:

foreach DestructibleActor.AssociatedTiles(AssociatedTile)
{
	AdjacentTiles = class'CHHelpers'.static.GetTilesAdjacentToTile(AssociatedTile);

	// There is no FindTilesForMeleeAttack() equivalent for non-unit targets, so we have to manually test each potential attack tile.
	foreach AdjacentTiles(AdjacentTile)
	{
		if (class'Helpers'.static.FindTileInList(AdjacentTile, PossibleTiles) != INDEX_NONE)
			continue;

		if (class'X2AbilityTarget_MovingMelee'.static.IsValidAttackTile(UnitState, AdjacentTile, AssociatedTile, ActiveCache))
		{	
			PossibleTiles.AddItem(AdjacentTile);
		}
	}
}

The IsValidAttackTile() ends up getting called A LOT, since for every AssociatedTile, the GetTilesAdjacentToTile() returns 8 tiles, and some of those adjacent tiles may be inside the Destructible itself (in the AssociatedTiles array), so it would be pointless to test them as valid tiles to attack from.

There is also some overlap, as one adjacent tile can be adjacent to multiple associated tiles.

If the Destructible occupies several levels vertically, then we end up collecting and testing adjacent tiles that hang in the air as well.

I'm inclined to keep the code as is, as it seems to work just fine, and arguably the native function will run faster than any pre-validation logic we can run in Unreal Script anyway.

@Iridar Iridar added ready-to-review A pull request is ready to be reviewed and removed waiting-on-author A pull request is waiting on changes from the author labels Jan 27, 2022
@Iridar
Copy link
Contributor Author

Iridar commented Jan 28, 2022

@Xymanek done everything you asked.

@Xymanek
Copy link
Member

Xymanek commented Feb 5, 2022

Additional test cases to verify:

  • Attacking large units (sectopods, etc)
  • Ramps. There are "small" ramps (~1 half cover elevation change) and "big" ramps (1 floor elevation change). Need to test cases when either the attacker, the target or both are standing on a ramp tile

…awn.uc

Co-authored-by: Xymanek <xymanek@outlook.com>
…awn.uc

Co-authored-by: Xymanek <xymanek@outlook.com>
@Iridar
Copy link
Contributor Author

Iridar commented Feb 7, 2022

Targeting on very mild slopes like this roof works fine: https://imgur.com/SnuqQat

And I already tested it multiple times for Sectopods, but here's a retest: https://imgur.com/a/e8AWSN3

However, you were right to be concerned about slopes: https://imgur.com/a/3mheYs2

@Xymanek Xymanek added waiting-on-author A pull request is waiting on changes from the author and removed ready-to-review A pull request is ready to be reviewed labels Feb 7, 2022
@Iridar Iridar added ready-to-review A pull request is ready to be reviewed and removed waiting-on-author A pull request is waiting on changes from the author labels Feb 8, 2022
@Xymanek Xymanek merged commit 8e64963 into X2CommunityCore:master Feb 17, 2022
@Iridar Iridar deleted the 1084-allow-adjacent-melee-targeting branch October 29, 2023 06:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ready-to-review A pull request is ready to be reviewed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Moving melee targeting doesn't allow tile choice if adjacent
2 participants