KnightHawk75
Posts: 1450
Joined: 11/15/2018 Status: offline
|
@Steve04 Attached is mostly working prototype of what you wanted. Needless to say it was more involved than even I thought it would be, namely due to: -A Lack of a 'disengage (drop all)' in Lua. this is actually biggest problem as mentioned already and a recurring issue. -B 1 definite bug in the software (I'll be reporting it shortly) - unit.damage.dp_percent is not updated upon repair even if the actual unit\gui is. This was the single biggest head ache. -C A feature of triggers not working as I would expect, ie you can't trap every 'damage' for a side broadly, only damage events of a type\specific amount. trigger, and even after that it will not trigger again upon 'more' damage. This is in-artfully solved by defining a trigger for every unit. I may submit a feature enhancement request for this, something like [X] trigger fires on every event, or 0 threshold actually triggers for every event. Additionally for in-area-triggers, they seem to only fire on the first unit unit matching the condition at a time, even if the condition is broad. I kinda get why that is the way it is, but again wish there was a way to say "fire this for each unit matching the condition" instead of the "any" way. This worked around with a In-area-trigger for each unit, so that two units can be in the area at the same time and get repaired at roughly the same time without having to wait for one to leave first. -D 2 features just not consistently working (patrol zones area and prosecution zone areas not working for ground units like they do for aircraft), and not breaking engagements when reaching those limits. if A existed this would be fairly easy to workaround. -E A minor issue of units swapped from one mission to another NOT INHERITING their ignored plotted course setting even when they were previously set to at unit and prior mission level. idk if that's by design or not, minor issue easily scripted around. -F An issue with ScenEdit_SetDamage, that actually doesn't really effect this scene in a breaking way but which complicates repair logic in general. Basically DP=X value is internally getting converted to a integer instead of a float or double or decimal. So negating damage "exactly" is impossible, and workarounds that don't end up destroying the unit had to be made. However I still somehow manage to code around all these issues and get something like you wanted. It's hard to explain all the reasons why so much code exists in this sample but the TLDR of it is 50+% of it is to attempt to "work around" A-F, and even it's not perfect though with more time and more code and a couple more events to control other events sure one could get there. In fact if I had to start over I would refactor some of what is included here but half of it was done before coming across certain problems. Anyway... In the attached the 2 units on each side will engage each other for like an hour+, this all depends on settings and some inherent randomness. Upon each unit taking damage said unit will "disengage and head home on a withdraw mission", he will also tell his opponent if that opponent is 'targeting' him still to do the same - no matter if that opponent is damaged or not, and that opponent will check for anyone targeting himself and do the same (this is recursive so to speak, though it's capped at one cycle deep). The "disengagement" problem is solved in two ways, the first is a mission swap + course setting toward the units own "safezone", which doesn't do jack for breaking most engagements...so I invented something else that will that sucks but works - dropping the opposing contacts who are being targeted. There is alot of code related to that because while it's "simple enough", obtaining the right contact object in a semi performant way who is being targeted is a little involved. The main reason it "kinda of sucks" is less about this specific sample and more that we're dropping contacts for the side regardless of who is actually targeting that contact, so in broader sample\scene, this is a sledgehammer approach with lots of downsides - but hey....it got the job done. Now how is damage trapped for if not by triggers, welp every second we lookup all mobile-vehicals and investigate thier damage (and update our records from the last second - if needed), if it's changed then we trigger the aforementioned damage procedure. The things is because of problem B this is NOT reliable and beyond other problems it causes in the case of the above if a unit has already repaired say from 33% damage to 0, welp we know it's really 0, but the unit will keep telling us it's 33% and it will not update till the there is a true damage event in the system (I mean cmo core code here). SO you will see at time a "repaired" unit on his second encounter may not actually "disengage" till he takes damage that causes < or > his previous damage amount. Ie if he took 33% went home to repair now get's hit again to cause 33% damage we'll not pick up that change till he take another hit say... bringing him to 66% or 20%. Just wanted to put that out there in case you wonder why the behavior in the scene is what it is. Now on the repairs, each side is capped to a maximum number, and counts are kept, including saved to the file (that is if you save the running example and reload it - just make sure you have the original saved as different filename). These variable are at the top of the SceneLoad - Startup script that help control things gKH.SceneGlobals.dbglevel gKH.SceneGlobals.ItalyMaxRepairs = 8; -- max number of times Italy units in total can repair. gKH.SceneGlobals.TunMaxRepairs = 8; -- max number of times Tunisian units in total can repair. gKH.SceneGlobals.ItalyRetreatDmg = 30.0; --if dmg >= this then abort engagement gKH.SceneGlobals.TunRetreatDmg = 30.0; --if dmg >= this then abort engagement gKH.SceneGlobals.ItalyRepairCounter = 0; --gets saved to file and reloaded from file if exists. gKH.SceneGlobals.TunRepairCounter = 0; -- gets saved to file and reloaded from file if exists. gKH.SceneGlobals.ItalyRetreatWaypoints = {[1]={latitude='37.048966', longitude='11.015755'}}; -- where to go manually when withdrawing gKH.SceneGlobals.TunRetreatWaypoints = {[1]={latitude='36.954446', longitude='10.974709'}}; --where to go manually when withdrawing gKH.SceneGlobals.ItalySafeZoneRPs = {"RP-750","RP-751","RP-753","RP-754"}; --use overcome some complicated bugs and non-feature in CMO. gKH.SceneGlobals.TunSafeZoneRPs = {"RP-762","RP-763","RP-764","RP-765"}; --use to overcome some complicated bugs and non-feature in CMO. gKH.SceneGlobals.ItalySideGuid = 'IEUKQL-0HM6UAV36E6VC'; --guid id of this side as opposed to name- used during contact related ops gKH.SceneGlobals.TunSideGuid = 'IEUKQL-0HM6UAV36E6VE'; --guid id of this 'side' as opposed to name - used during contact related ops Some notes about these: - The MaxRepairs values are tricky because of prior mentioned problems "repairs" have to allowed to run while in the safezone no matter if they are needed or not - because we can't actually know for sure because unit.damage.dp_percent is half broken. Because of this a side can get charged twice or even 3 or 4 times per-repair if they hang out in the safezone long enough. However I make some attempts to prevent it but they'll not always work. There are ways I could make it work by switching to an event per-unit and disabling the in-area event for that unit while in the zone and having another per-unit NOT-in-area event flip it back on or do that only when disengagement is called, but I didn't cause I was trying to avoid relying on per-unit events and triggers as much as possible and it would tie triggers to unitguids or unitname which again I was trying to avoid, but if starting over I probably would go that route as it would save more code that it would cost and probably work better. If both sides are over over the MaxRepair's then "disengagements" are disabled. TLDR = give each side at least double the repairs you really want them to have as a guide. - RetreatDmg vars - Set this to the amount >= in which you want to trigger a reteat on the taker (who also then triggers retreat on his attackers) - I think the waypoints are self explanatory just remember if you move the safe-zone RP's around make sure the waypoint\course location is updated to still be inside them. - Similarly with the SafeZoneRps var's - if you re-name the RP's or change them they must be changed here. I could pull them dynamically from the mission, but for simplicity I did not. - The SideGuid vars - These are absolutely critical to screwing with and matching contacts, if you delete a side and recreate them they'll need to be changed, similarly throughout the code "Italy" and "Tunisia" exist, I should have made those vars of side1 and side2 but I didn't so those will need to change if side names are changed, probably a dozen places. This again is just a sample to show this 2v2 engagement\withdraw\repair\re-engage \withdraw\repair loop thing can kinda...sorta be done, it would be easier in the future with a couple cmo fixes\enhancements. I've tried this scene over and over again with and without enabling the various mission setting about staying in the patrolzone and weapon ranges and while initial targeting does seem to obey the patrol zone (not PRZ), no engagement is ever actually broken that I ever saw when leaving the PZ or prosecution zones be they the targets or the units on their own -without assistance from code anyway. Special actions - There are 5, 4 related to the debugging log settings, and one to clear the repair count keys from any save (it also reset them in the loaded scene). The logging levels are 0-3 and controls how much stuff is logged to your logs\lua-history-thedate.log file, don't use 3..lol, 2 is pretty insane still when things are actually happening but if you want to follow the code it's like a play-by-play. 0 - is basically errors only, and 1 is maybe all you want to really have on when not trying to track something down or see how things work. 10-15% of the code is all about logging - hey I like to know when and why things are breaking while I work, what can I say. ;) Events - SceneLoad - Loadup the main code, execute bootstrapping routines. ScanForDamgeEverySecond - The trigger and actions associated with looking up everyone's damage constantly. ItalyRepairs - contains the two triggers and one action associated with detecting when in safezone and kicks off possible repairs. TunRepairs - contains the two triggers and one action associated with detecting when in safezone and kicks off possible repairs. Let me know what you think, I'm not "happy" with it (more improvement could be made even as is in 1147.25) but does show one way of how it can be done without actually scripting out each and every shot fired. Playing repeated sessions the whole engagement should last about a least an hour with 30% damage and max repairs set to 8, with Tunisia losing more often than not. (updated ~10am) attachment: KH1h_Scenario-test-1-Limited-atk-OK.zip (contains .scen and the global functions startup script, event action code have to look inside the scene for though those are pretty simple small snippets that call the rest)
Attachment (1)
< Message edited by KnightHawk75 -- 6/13/2021 4:41:32 PM >
|