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

Fixing Cyclops futily slow beaming a stinger by instead making it inch forwards #4698

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

danfireman
Copy link
Contributor

@danfireman danfireman commented May 25, 2022

Fixes #3338

TODO:

  • Further restrict when inching happens. Only do it when attack moving or attacking the slow beamed target
  • Be more careful about removing commands to specifically only remove when it's an inching move command
  • Verify performance drop when a hundred cyclops are spammed is under 1%

@GoogleFrog
Copy link
Contributor

I feel like the engine is meant to have something that sets which weapon is for aiming. Failing that, how much range does slowbeam need to lose for the main gun to fire at reasonable elevation differences? If the fix is as simple as 20 less slowbeam range, then perhaps that's the one to go for.

@danfireman
Copy link
Contributor Author

danfireman commented Jul 10, 2022

After a bit of looking I couldn't find any way to use the engine for this.

The slow beam needs to lose about 60 range before a modest slope or a hill 1.5 lotus high prevents it from just sitting there.
However, this is not a viable solution as losing any range at all means a Cyclops on attack move won't move into slow beam range against stingers or other static things like a afk paladin. It also can't catch and kill Dante any more and is MUCH easier for scalpels and domis to kite (two units tank really struggles against).

Shall I go ahead with my TODOs above on the assumption this will be merged?

@GoogleFrog
Copy link
Contributor

I was planning to look prior to the next update. I'll have a look now and make some comments.

end

local cyclopsi = {}
local cyclopsDefID = UnitDefNames["tankheavyassault"].id
Copy link
Contributor

Choose a reason for hiding this comment

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

Ideally this would be a customParam so that people could make similar units use the same behaviour, or so that modders could easily remove this behaviour if they're using cyclops for a different purpose.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Switched

local spGiveOrderToUnit = Spring.GiveOrderToUnit
local spGetUnitPosition = Spring.GetUnitPosition
local spGetTeamUnitsByDefs = Spring.GetTeamUnitsByDefs
local Echo = Spring.Echo
Copy link
Contributor

Choose a reason for hiding this comment

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

This should at least be spEcho, although in practice I never localise Spring.Echo.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done



function gadget:UnitCreated(unitID, unitDefID, teamId)
if unitDefID == cyclopsDefID then
Copy link
Contributor

Choose a reason for hiding this comment

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

See customparam comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

end
end

function gadget:UnitGiven(unitID, unitDefID, newTeamID, teamID)
Copy link
Contributor

Choose a reason for hiding this comment

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

Unit given is redundant if the behaviour is completely team agnostic.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed

end
end

function gadget:Initialize()
Copy link
Contributor

Choose a reason for hiding this comment

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

I like to put Init at the bottom of the gadget, with create/destroy above, with more frequent logic and callins above that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Moved

end

function gadget:GameFrame(frame)
for cyclopsId, _ in pairs(cyclopsi) do
Copy link
Contributor

Choose a reason for hiding this comment

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

Ideally pairs would not be used. IterableMap with ApplySelf fits. It would even cleanly implement my next suggestion, which is that cyclops probably doesn't need to be checked every frame, and that we may as well stagger the checks over frames.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

"IterableMap with ApplySelf " <- no idea what this is

I'd say you want to check the Cyclops often enough to make the inching forwards fairly smooth, so probably not less than once every 3 frames. Will wait to know more about this "ApplySelf" business before making a change.

Copy link
Contributor

Choose a reason for hiding this comment

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

Grep iterableMap.

local tx, ty, tz = spGetUnitPosition(slowBeamTargetID)
local nx, nz = x * 0.95 + tx * 0.05, z * 0.95 + tz * 0.05
local ny = math.max(0, Spring.GetGroundHeight(nx, nz))
local cmd1 = spGetUnitCommands(cyclopsId, 1)[1]
Copy link
Contributor

Choose a reason for hiding this comment

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

The unit might not have any commands, which would cause a crash. Also when getting the head of the queue you should use the callout that returns a non-table bunch of arguments that correspond to the first command.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added check for not having commands.

Not idea what you're referring to by the second sentence. Can't see anything relevant except GetUnitCommands at https://springrts.com/wiki/Lua_SyncedRead#CommandQueues

Copy link
Member

Choose a reason for hiding this comment

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

Spring.GetUnitCurrentCommand, search the zk repo for examples (it's not on wiki)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Errors when I try and use this.

Comment on lines 63 to 66
spGiveOrderToUnit(cyclopsId, CMD.REMOVE, {1, cmd1.tag}, {"ctrl"})
end
spGiveOrderToUnit(cyclopsId, CMD.INSERT, {0, CMD.MOVE, CMD.OPT_INTERNAL, nx, ny, nz}, CMD.OPT_ALT)
end
Copy link
Contributor

Choose a reason for hiding this comment

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

Why are commands being removed and move commands inserted? Firstly, this should probably be CMD_RAW_MOVE. But secondly, does this need to be a command at all? It might be neater to implement this behaviour using a short move goal.

Copy link
Contributor

Choose a reason for hiding this comment

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

Won't the internal check fail for attack commands the player issued? This sort of comment is a poor substitute for testing though, which I have not found the time to do.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The intent is to remove any existing inch-forwards command (otherwise you get a whole bunch of them and they mess things up).

Using CMD_RAW_MOVE seems to result in the Cyclops not inching.

No idea what a short move goal is.

Copy link
Contributor

Choose a reason for hiding this comment

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

Move goals are direct orders for units to move somewhere. They sit below the command system. They can be neater for unit AI because they don't mess with commands at all.

Copy link
Contributor Author

@danfireman danfireman Sep 26, 2022

Choose a reason for hiding this comment

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

That's not very helpful to me actually implementing it as I have no idea what you're talking about.

Copy link
Member

Choose a reason for hiding this comment

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

Spring.SetUnitMoveGoal(unitID, x, y, z, radius) makes the unit move towards given point (and be satisfied once in given radius)

@GoogleFrog
Copy link
Contributor

image
I tried to move a Cyclops through Crab range and it gave itself a small move order and became stuck. The units in this picture are immobile.

image
This time I spawned a Cyclops in range and tried to move away. It got to the point where it could no longer fire, then got stuck on a small move order towards the Crab.

image
Moving a Cyclops away from a Nimbus is impossible.

@GoogleFrog
Copy link
Contributor

GoogleFrog commented Nov 5, 2022

I don't see any part of the code that would deal with these cases.

"IterableMap with ApplySelf " <- no idea what this is

Grep for examples. Eg
image

image
Grep for examples again. Other gadgets use it. Experiment a bit.

@sprunk sprunk marked this pull request as draft January 26, 2024 16:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cyclops will not fire its' main weapon against elevated targets
3 participants