Author Topic: Been attempting to implement knockback - Some results  (Read 11102 times)

Offline WeaponMaster

  • Newbie Mark III
  • *
  • Posts: 46
Been attempting to implement knockback - Some results
« on: May 18, 2019, 11:32:54 pm »
I've been doing a bit of messing around in the code to try to implement one of the previous mechanics in AI War 1, knockback (or translocating shots ala AI War 1). There's some moderate success so far:

https://youtu.be/LRzaRUalo3c - Video demonstrating the knockback working properly ( Knockback = 3000, mass limit = 5 )


There's also some issues and concerns with my code as it is currently:

1. If the shot kills the ship outright and there's another ship stacked inside of it, the stacked ship doesn't inherit knockback (fixed for stacks, leaving unchanged for ships that spawn on death (hydra heads))
2. As seen in the video, ships that are knocked back kinda pause for a moment before moving again.
3. As a concern, I'm not really sure if this will play well in multiplayer when it comes out (momentary desyncs)
4. Minor concern that I'll probably ignore, if a weapon has AoE and hits a bunch of ships under a shield... the knockback on the shield would be pretty insane since it stacks linearly. ( 3000 knockback with 800 range AoE - https://youtu.be/zz-bxcihMLQ )
5. The way movement planning is coded now, ships can't preemptively "move forward" to counteract the knockback, they will only start moving back into range on the next frame.


How it functions so far:

1. base_knockback_per_shot="some positive or negative integer" and knockback_to_ships_mass_tx_less_than="some mass value" must be defined in the XML, optionally added_knockback_per_shot_per_mark="some positive or negative integer". Positive numbers for knockback to push away, negative to pull towards.
2. If the ship is mobile, not protected by a shield (but it can push back things with bubble shields), and has less or equal mass than the number defined (and some other fail conditions I'm forgetting right now) then knockback is calculated. The formula is: Knockback Distance = (base + per_mark * mark level) * ( 1 - (target ship mass / (mass limit * 2)) ). So a ship can receive between 100% and 50% of the knockback depending on how heavy it is, to differentiate weights.
3. The knockback from multiple shots in a frame gets pooled together, and is then applied during movement planning for the next frame. For Chris - this knockback arcenpoint is pooled, cleared from pool, and serialized, but I'm still unsure of how to test if its working properly.


The Guts (Arcen people PM me on the forum and I can provide my source files if you want to help out and look)

ArcenCore:
      EntitySystemTypeData: Added the variables BaseKnockbackPerShot, AddedKnockbackPerShot, and KnockbackPerShotToShipsMass_tXLessThan. XML reading is set up, and knockback total is calculated in the ForMark section

      EntitySystem: Added public int GetKnockbackPowerAgainst, returning the knockback from the above equation if it passes checks

      GameEntity_Squad: Added public ArcenPoint KnockbackToBeAppliedNextFrame, public void TakeKnockback that adds to the ArcenPoint, and added a TakeKnockback call to TakeDamage for when protecting shields take damage, and when unprotected ships take damage. TakeKnockback also accepts an optional override angle for knocking in other directions, set the override to a negative number to calculate normally.

ArcenExternal:
      MovementPlanning: Added Inner_HandleSquadKnockback that gets called at the very beginning of movement planning for each ship. If that ships' KnockbackToBeAppliedNextFrame.X != 0, set FramePlan_DoMove to true, and set up NextMovePoint and CurrentPlannedMove to current position + knockback offset. After that, do the normal movement code; if the code were to report CurrentPlannedMove=ZeroZeroPoint, it first checks that DoMove is still false so it doesn't cancel knockback. When calculating the next move for the frame at the very end, it adds the knockback to the resulting point (you will get knocked back farther if moving away, knocked back less if moving towards it).
« Last Edit: May 19, 2019, 04:50:55 pm by WeaponMaster »

Offline WeaponMaster

  • Newbie Mark III
  • *
  • Posts: 46
Re: Been attempting to implement knockback - Some results
« Reply #1 on: May 19, 2019, 12:52:50 am »
I'd also like to point out, there's an incoming bug the moment the game version rolls over to 1.000. For loading setting files (and apparently deserializing save files?), the game only checks the minor version.

This leads to a bug with me testing my current files, as I gave it a version at random of 1.100 and now loading settings doesn't work, and I can't load save games (pressing the load button does nothing).

Offline AnnoyingOrange

  • Jr. Member Mark II
  • **
  • Posts: 71
Re: Been attempting to implement knockback - Some results
« Reply #2 on: May 19, 2019, 05:33:45 am »
This looks promising, it's already much smoother than AIWC's teleporting knockback.

Offline WeaponMaster

  • Newbie Mark III
  • *
  • Posts: 46
Re: Been attempting to implement knockback - Some results
« Reply #3 on: May 19, 2019, 05:43:17 pm »
Need a bit of help with having the knockback be inherited. I set up inheriting the knockback in EjectEntireStackFromMyselfIfPresent, but doesn't seem to be transferring. I don't think that movement planning is somehow running inbetween TakeDamage giving knockback and DoOnDeathInCombat because they get called sequentially; TakeDamage > TakeKnockback > DoOnDestructionLogic > DoOnDeathInCombat > EjectEntireStackFromMyselfIfPresent > newSquad.KnockbackToBeAppliedNextFrame = this.KnockbackToBeAppliedNextFrame.

Is it maybe a problem with how movement works in the Unity engine? The very first frame the new ship is alive, it should set its next move point to the knockback vector and then clear the knockback. Somehow it is clearing the knockback without setting the next move order?

Is there any way to delay my knockback check for exactly one frame after creation?

Debug Log shows that the knockback did transfer, but movement planning did not move them (two ships that spawned from unstacking):
5/19/2019 5:40:23 PM   Ship <Vanguard> ID <9863> just ran inner_handlesquadknockback successfully and set knockback to 0
5/19/2019 5:40:23 PM   Ship <Vanguard> ID <9864> just ran inner_handlesquadknockback successfully and set knockback to 0

Offline WeaponMaster

  • Newbie Mark III
  • *
  • Posts: 46
Re: Been attempting to implement knockback - Some results
« Reply #4 on: May 19, 2019, 07:04:17 pm »
Alternatively I could have something like "Apply 20% of the remaining knockback this frame, if the knockback is less than 100, set to 0".

For a 3,000 unit knockback it would be - 600, 480, 384, 307... Actually this is decaying too slowly, it'll look weird.

500 + 10% of remaining: 800, 720, 648, 583, 249. Then ships that inherit knockback would only lose 800 knockback distance from not getting the first frame of knockback.

Still doesn't work: https://youtu.be/JceNuz9hq_A

Since this file is in the external code that's provided by Arcen, I'll post it to get more direct feedback. I'm really at a loss because I don't know exactly how these frameplan variables work.
« Last Edit: May 19, 2019, 08:17:54 pm by WeaponMaster »

Offline x4000

  • Chris McElligott Park, Arcen Founder and Lead Dev
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 31,651
Re: Been attempting to implement knockback - Some results
« Reply #5 on: May 20, 2019, 11:08:55 am »
I've only had time to skim some of this, as it's long, but I read the summary parts in the most depth.  So if I missed something, please just let me know.  In general, here are some of my thoughts in no particular order:

1. I'm extremely happy to hear about this feature, as it's something that people have been wanting for certain types of ships (military command stations, etc) for a while now.  I'm also glad to hear that it's working better than in the first game, ala the teleporting thing that I (I think I?) implemented there.

2. With ships having a momentary pause before being able to move again, I feel like that's... not the end of the world?  If anything, that sort of pause gives a little more "weight" to the effect, and a lot of action games use that sort of thing intentionally.  Not knowing why exactly that is happening might be concerning, but I'm not super duper worried about it.

3. For the stuff you've added, I'm totally cool with you going ahead and merging that into the main code branch.  Worst case with this, we just don't assign any units to use this feature and it thus affects nothing as far as 0.900 or 1.0 goes.  But it sounds like you've honestly solved most of the problems that are really that severe.

4. The desync issue with multiplayer is a mild concern, but I'd have to look at exactly how that is implemented to know if it's a concern for real.  If all of this is in the short term planning, sim execution, shot hitting, etc sections... then there should be no desyncs unless possibly it's a slight floating-point error if you're using that for the angle of pushback.  But those errors would be so small that they would likely not be visibly noticeable, and forcefields will be causing the same sort of desyncs, and that's only on certain processor combos, and multiplayer is going to be built to auto-repair from stuff like that.  So the bottom line is that when multiplayer is in full swing it might cause some extra traffic for re-syncing as well as some visual inconsistencies between players, but we can iron that out as needed when the time comes.  It's not something that would be game-breaking.

5. You mentioned knockback on forcefields and how that stacks... honestly I think that this is going to be something that is ripe for abuse if we can knock AI forcefieleds around in general, or if they can knock ours around.  I feel like if something projects a bubble forcefield, that should automatically make it immune to knockback, same as being immobile does.  There are just so many exploits on the player side, and on the AI side it's likely to annoy players hugely and require babysitting forcefields covering turrets, etc.  So better to just dodge that in general.

6. Thanks for the note on the bug with the major version not being checked correctly.  That said, I'm not sure what is wrong with the code.  Second pair of eyes would be helpful:

Code: [Select]
public Boolean GetGreaterThanOrEqualTo( int MajorVersion, int MinorVersion )
        {
            if ( this.MajorVersion < MajorVersion )
                return false;
            if ( this.MajorVersion > MajorVersion )
                return true;
            if ( this.MinorVersion < MinorVersion )
                return false;
            return true;
        }

7. When it comes to the frame planning and movement, none of this is using the Unity Engine's code.  It's all custom to either Keith or myself or some combo.  You may be running into a threading issue, but I'm not positive.  There are a few things where it kicks off a bunch of stuff that runs simultaneously and independently, and I believe movement as well as "ships getting hit by stuff" are two of those things.  In that regard, you can never count on those happening in a specific order, since different cores on your machine are working on those at different speeds.

THAT said, a lot of the "ship actually getting hit by something" happens on the main thread.  You can check if you're on the main thread by running Engine_Universal.CalculateIsCurrentThreadMainThead().  If that returns true where you are setting the knockback variables, then that is almost certainly meaning that no short-term background threads are running at the moment.  Long-term background threads ARE almost always running, though, so you'd get strange results messing with something they normally set.  If you're setting the knockback variables while not on the main thread, then that's going to be a separate thread from the short term movement planning thread, and so there's your problem.

The workaround for threading issues of this sort would be to have a variable on the entity itself (the GameEntity_Squad), and have that set by the knockback-setting code and then read later by the movement thread... although even that could have timing issues.  Running this through a GameCommand would absolutely make sure that this is synchronous, but it would also introduce quite a bit of lag between the ship getting hit and being knocked back (maybe half a second of lag).

It MAY be that you should do a couple of other things, instead:

a. When you are setting the amount of knockback to apply, specify on what frame it should start running, and make that the current frame plus one if you like.  Or plus two if you're paranoid and 200ms feels acceptable in delay.

b. When you're reading the amount of knockback to use, only read stuff that is <= the current frame, and most importantly only clear that stuff.

c. You might be able to avoid the problems in general by having these things not ever call Clear() on the knockback stuff that is being inherited.  Instead only doing Remove( i ) calls, iterating backwards.  But I'll admit I haven't been looking at this code yet, since I can't do a simple diff inside svn.  If you check in the stuff and have a repro save you want me to test out, I don't mind untangling that bit for you.

Thanks for all your work on this!

Cheers,
Chris
Have ideas or bug reports for one of our games?  Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline WeaponMaster

  • Newbie Mark III
  • *
  • Posts: 46
Re: Been attempting to implement knockback - Some results
« Reply #6 on: May 20, 2019, 08:58:17 pm »
I think the issue with the files loading is that settings and game saves aren't saving the major version in the file. When I try loading from 1.100 I get the error "File too old!", which shouldn't make sense from the code you posted.
« Last Edit: May 20, 2019, 09:43:14 pm by WeaponMaster »

Offline x4000

  • Chris McElligott Park, Arcen Founder and Lead Dev
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 31,651
Re: Been attempting to implement knockback - Some results
« Reply #7 on: May 21, 2019, 10:52:59 am »
I think the issue with the files loading is that settings and game saves aren't saving the major version in the file. When I try loading from 1.100 I get the error "File too old!", which shouldn't make sense from the code you posted.

Hmm, that's a terrifying prospect, because it would mean all savegames were broken again.  But it's actually saving by the internalname of the GameVersionTable, so that's not it.  It's something... else.  Either it isn't reading MajorVersion or MinorVersion right from the GameVersion xml, or it's not doing some sort of comparison properly.  I'm not really sure.

The good news is that it shouldn't affect actual savegames, because the data they are storing is agnostic about all that.  This is either a bug in the GameVersion.cs file, or the GameVersion xml, most likely.  If you have time to debug this some it would certainly be welcome, as you might be able to find the fix by just throwing in some ArcenDebugging.Log() stuff to see what the data actually is.  But if not that's totally cool, it would be something to throw on mantis and I can get to it prior to 1.0.

Thanks for finding this!
Have ideas or bug reports for one of our games?  Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline RocketAssistedPuffin

  • Arcen Volunteer
  • Sr. Member
  • *****
  • Posts: 260
Re: Been attempting to implement knockback - Some results
« Reply #8 on: May 21, 2019, 02:13:51 pm »
Ooh, I like this. Already have a few ideas for it, as well as for the knocking things towards the firer.

5. You mentioned knockback on forcefields and how that stacks... honestly I think that this is going to be something that is ripe for abuse if we can knock AI forcefieleds around in general, or if they can knock ours around.  I feel like if something projects a bubble forcefield, that should automatically make it immune to knockback, same as being immobile does.  There are just so many exploits on the player side, and on the AI side it's likely to annoy players hugely and require babysitting forcefields covering turrets, etc.  So better to just dodge that in general.

I'd agree that forcefields should be immune. We could limit it via the mass stat, but then you can't do fun things like Artillery Golems being able to shove big targets around.

Is it possible for things like Vacuum and Repulse shots? I.e, hit a target, pull in 5 targets in X range Y distance towards the thing hit. Basically being able to clump or spread out hostiles. I don't have an idea for Repulse, but it'd be a consequence of having Vacuum, which I do have some ideas for.

Sadly I must wait for the next release to test any of it.
Autistic, so apologies for any communication difficulties!

Offline x4000

  • Chris McElligott Park, Arcen Founder and Lead Dev
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 31,651
Re: Been attempting to implement knockback - Some results
« Reply #9 on: May 21, 2019, 03:12:20 pm »
Sorry I've been not too communicative lately, Puffin -- are you still having compiler issues?  I'm trying to plow through the lobby and a few other things, but I still have some emails I need to get to responding to with you.

Forcefields being immune is something we can probably just put in as a direct thing.  If the TypeData.shieldRadius > 0, then it's immune.

I don't see any reason why vacuum shots wouldn't be viable, and that's definitely interesting!
Have ideas or bug reports for one of our games?  Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline Draco18s

  • Resident Velociraptor
  • Core Member Mark V
  • *****
  • Posts: 4,251
Re: Been attempting to implement knockback - Some results
« Reply #10 on: May 21, 2019, 03:18:13 pm »
I don't see any reason why vacuum shots wouldn't be viable, and that's definitely interesting!

Black Hole shots ;)
You can't really use a vacuum in space.
(Mechanically, I love this idea; one of the Use items in Risk of Rain 2 does this and its hilarious to black-hole a bunch of things into a small area and then use an AOE attack on them)

Offline RocketAssistedPuffin

  • Arcen Volunteer
  • Sr. Member
  • *****
  • Posts: 260
Re: Been attempting to implement knockback - Some results
« Reply #11 on: May 21, 2019, 03:31:15 pm »
Sorry I've been not too communicative lately, Puffin -- are you still having compiler issues?  I'm trying to plow through the lobby and a few other things, but I still have some emails I need to get to responding to with you.

Yea, though now I have an additional problem (TypeLoadException: VTable setup of type FrontEndLinkImplementation failed) so I can't get to the menu either now. There's no hurry really on responding to anything though. I'm fine with using the Steam build and just waiting.

Yea vacuum is the wrong term to use. I was going to use attractor, but then...didn't, for a reason I have forgotten.

I think I have an idea for Repulse too - being able to spread AI ship groups to the sides, then use traditional Translocation to push them back into very dispersed patterns, instead of a focused blob.
Autistic, so apologies for any communication difficulties!

Offline x4000

  • Chris McElligott Park, Arcen Founder and Lead Dev
  • Arcen Staff
  • Zenith Council Member Mark III
  • *****
  • Posts: 31,651
Re: Been attempting to implement knockback - Some results
« Reply #12 on: May 21, 2019, 03:40:21 pm »
Yea, though now I have an additional problem (TypeLoadException: VTable setup of type FrontEndLinkImplementation failed) so I can't get to the menu either now. There's no hurry really on responding to anything though. I'm fine with using the Steam build and just waiting.

So, the way around this would be to copy the AIWar2.exe and AIWar2_Data folders from your Steam folder into your root svn folder.  After that, if you run the normal build process, all should be well.  If not, then please definitely email me.  It's not a crisis from my end, and you certainly don't owe me anything, but I hate having you on a delay where you can't see the new cool stuff and make tweaks if you feel inclined.
Have ideas or bug reports for one of our games?  Mantis for Suggestions and Bug Reports. Thanks for helping to make our games better!

Offline RocketAssistedPuffin

  • Arcen Volunteer
  • Sr. Member
  • *****
  • Posts: 260
Re: Been attempting to implement knockback - Some results
« Reply #13 on: May 21, 2019, 06:40:17 pm »
So I did what you suggested which fixed that, and also gave me an idea, so I re-read the conversation we had about the other problem. I tried looking for every instance of ArcenUniversal, and found a bunch outdated, seemingly at random (including a few in ReliableDlls! Which explains why copying those over didn't work). So I copied over the Steam ReliableDlls over, and now that problem is gone! Another check and all Universal files are up to date. The only oddity from this is a few dll.meta files in ModdingAndGUI > Assets > ArcenDLL say they're outdated, but that's it.

I was going to say the last remaining problem was the camera, but ran the build process again with the current revision of InputCaching.cs, and now it...works. So huh, I've had problems coming from outdated dlls for a while now. Hopefully gone for good.

Regarding translocation, there's a variety of ideas there. If say, the ability for a weapon system to fire on death would return, then it's possible for something like Self Destruct Guardians to bring ships towards themselves, or Repulsive Mines that could detonate, doing damage then push AI ships back into more Mines, on the other side of the wormhole? There's even the possibility, since fast units would likely not be slowed for long by translocation, of synergy with Snipers to fill that gap, instead of Snipers being just a rather situational thing. That'd mean unit speed has more of a direct combat effect too, possibly. Or even (this one is strange), Etherjets that yank stuff into their Tractors. Not great at defending a Station from the front, but if they're behind the enemy force...they can pull back even Strikecraft that would normally be immune to Tractors and Gravity.

Definitely very interested in this kind of mechanic. Something was bugging me lately about the game, and I think it's possibly the lack of such things currently, after a conversation today and ruling out a bunch of stuff from Classic. So there might be some...weird things done with this.
« Last Edit: May 21, 2019, 06:47:10 pm by RocketAssistedPuffin »
Autistic, so apologies for any communication difficulties!

Offline WeaponMaster

  • Newbie Mark III
  • *
  • Posts: 46
Re: Been attempting to implement knockback - Some results
« Reply #14 on: May 21, 2019, 07:09:19 pm »
I've made forcefields immune to knockback completely, and I'm working on an extension to the TakeKnockback method to have AoE shots calculate the knockback angle from the primary target right now. I'll attach it to an XML tag knockback_at_target_location in the weapon definition.

An interesting idea for an AI eye that I have is for kind of a black hole eye. It could accomplish its purpose with only two weapons: a 15,000 range self AoE that applies a negative knockback to "suck" ships in, and a short range tesla coil with high damage to kill ships that get sucked all the way in. It might be a bit too annoying, so the knockback would need to be low enough so that only the slowest of ships (pike ships, mlrs ships) are doomed, while only making it hard for other ships to travel through the planet.