Skip to content

Add support for QuadPoint trigger zones - #243

Merged
rp- merged 1 commit into
pydcs:masterfrom
bobmoretti:user/bobmoretti/quad-trigger-zone
Jul 25, 2022
Merged

Add support for QuadPoint trigger zones#243
rp- merged 1 commit into
pydcs:masterfrom
bobmoretti:user/bobmoretti/quad-trigger-zone

Conversation

@bobmoretti

Copy link
Copy Markdown
Contributor

Retain existing trigger zone compatibility, assume circular if type parameter not given.
Updated loadtest.miz to include new trigger zone types and fields.

@bobmoretti
bobmoretti marked this pull request as draft July 24, 2022 23:28
@bobmoretti
bobmoretti force-pushed the user/bobmoretti/quad-trigger-zone branch 3 times, most recently from 327e7ae to 1781be6 Compare July 25, 2022 00:12
Retain existing trigger zone compatibility, assume circular if `type` parameter not given.
Updated loadtest.miz to include new trigger zone types and fields.
@bobmoretti
bobmoretti force-pushed the user/bobmoretti/quad-trigger-zone branch from 1781be6 to 5190f0b Compare July 25, 2022 00:14
@bobmoretti
bobmoretti marked this pull request as ready for review July 25, 2022 00:29
@rp-
rp- merged commit 142b9da into pydcs:master Jul 25, 2022
@DanAlbert

Copy link
Copy Markdown
Collaborator

FYI even quad zones have a radius defined in the miz. Don't ask me what the hell it means, but that property should maybe be re-exposed on the base type to more accurately represent the miz.

@Raffson

Raffson commented Aug 19, 2022

Copy link
Copy Markdown
Contributor

I disagree with re-exposing the property, I think a polymorphic method should be added to decide whether a given point is in a trigger zone. That should allow for an easy usage of both trigger zones.

As for the implementation details on deciding whether a point lies in a quad-point trigger zone, leave that up to me. I already have a solution in mind 👍

@DanAlbert

Copy link
Copy Markdown
Collaborator

If the property isn't retained we can't reserialize the miz correctly.

@bobmoretti

bobmoretti commented Aug 19, 2022

Copy link
Copy Markdown
Contributor Author

Sorry if I broke something. I haven't looked at this for a few weeks, so bear with me and correct anything that I get wrong here...

As far as I recall for quad trigger zones, the radius parameter is only used in the mission editor UI -- it has no in-game function.

The previous behavior totally broke quad zones -- I wrote a script to help update my friend's mission, and deserializing/reserializing it via PyDCS broke all of his quad zone bridge destruction triggers. Hence this PR.

See #207 for an issue where DCS had a similarly meaningless parameter. PyDCS had elected to keep it. Eventually a DCS update came along causing DCS to no longer emit this attribute, which caused PyDCS to fail to deserialize new missions. Since it seemed useless, and quad triggers work just fine without this parameter, I elected to not include the radius parameter (although providing it as part of the base class did cross my mind).

I think my intention was that TriggerZone be only an abstract interface, and that it should never be instantiated on my own. I guess this comes down to questions like

  • How stable an API does PyDCS aim to expose?
  • What is PyDCS's policy for breaking changes, especially in the context of DCS
  • If we make breaking changes, is there a comms channel we can use to inform users of PyDCS that action is required?

If the property isn't retained we can't reserialize the miz correctly.

@DanAlbert Can you elaborate here? I see two possibilities

  1. If the TriggerZone was created by deserializing a .miz file, then everything that impacts gameplay is preserved
  2. If it was created via Python (à la Liberation) then it should make an explicit choice of TriggerZoneCircular or TriggerZoneQuadPoint, and everything that impacts gameplay is preserved, since the TriggerZone object should polymorphically serialize itself with the correct values.

Unless I'm mistaken, the only downside to the current behavior is that the mission editor UI looks a little different for QuadPoints.

But please correct me if I'm wrong!

@Raffson

Raffson commented Aug 19, 2022

Copy link
Copy Markdown
Contributor

Sorry if I broke something. I haven't looked at this for a few weeks, so bear with me and correct anything that I get wrong here...

No need to apologize, I think none of us really knew how to handle this properly until now. At the end of the day it's good that we're running into this problem.

Your second suggestion is what I have in mind, basically a function to test whether a point is inside a trigger zone.

@Raffson

Raffson commented Aug 19, 2022

Copy link
Copy Markdown
Contributor

If the property isn't retained we can't reserialize the miz correctly.

I just opened up test_quad_trigger_zone.miz in the ME, I can confirm this causes problems. When trying to change the type of the zone back to circular, the ME is partly bugged. For starters it won't enable the radius automatically, nor can you select the the zone after deselecting it. To "un-bug" the ME you have to reselect the zone via the "View trigger zones list".

So that means we'll need both a way to test if something is in the zone, as well as re-expose the radius property.

Good catch @DanAlbert 👍

@DanAlbert

Copy link
Copy Markdown
Collaborator

Sorry if I broke something.

No worries, you've broken far less than I have :)

As far as I recall for quad trigger zones, the radius parameter is only used in the mission editor UI -- it has no in-game function.

In general, the types in pydcs try to mirror the data in the miz. This is sometimes needed for serialization (as it turns out what the case here, though it isn't always). It might not have a gameplay effect, but those properties can be useful to programs that read an ME generated miz (as Liberation does).

I guess this comes down to questions like

I can take a stab at these, but @rp- is the real decision maker :)

How stable an API does PyDCS aim to expose?

Avoid breaking the API when it's easy and safe to do so, but so far every time I've had a good reason to break the API it's been accepted :) There are not that many (direct) users of pydcs, so breaks usually aren't too hard to accommodate.

What is PyDCS's policy for breaking changes, especially in the context of DCS

Generally want to be able to read any miz, but write the newest schema. The APIs are generally shaped to match the newest schema, but I'm sure there are exceptions.

I think the answer for "how does pydcs support old versions of DCS?" is "use an old version of pydcs". HEAD usually works for the latest open beta and that's all that's "tested".

If we make breaking changes, is there a comms channel we can use to inform users of PyDCS that action is required?

Watching this project is what I've done. I don't believe there's a discord for pydcs, though it might be time to create one? Up to @rp- I think.

If the property isn't retained we can't reserialize the miz correctly.

@DanAlbert Can you elaborate here?

@Raffson beat me to it: gameplay isn't always the only thing that matters :)

So that means we'll need both a way to test if something is in the zone, as well as re-expose the radius property.

Good catch @DanAlbert 👍

Cool, thanks for verifying that 👍

@bobmoretti

Copy link
Copy Markdown
Contributor Author

@DanAlbert Can you elaborate here?

@Raffson beat me to it: gameplay isn't always the only thing that matters :)

Sorry, I still don't fully understand the use case... can you guys give me an example of where a user would need this test?

@Raffson

Raffson commented Aug 20, 2022

Copy link
Copy Markdown
Contributor

Sorry, I still don't fully understand the use case... can you guys give me an example of where a user would need this test?

Re-exposing the radius is needed in order to prevent the ME from getting bugged if you open the mission and wish to manipulate the trigger.

The "test" I referred to is needed in Liberation. I believe it's scenery_group.py that used to test if "white trigger zones" are located within a "blue trigger zone" by using radius. For quad-points this wasn't necessarily a correct determination, and now that there's a distinction being made it would make sense to have polymorphic methods for both circular and quad-point zones to check if something is located inside the zone.

For quad-points this proves to be somewhat trickier. Yes, I know there's another method that tries to compare areas of triangles that can be formed between the points, but I'm afraid things get just as complicated as my current implementation in case of angles that are bigger than 180°, sort of like the second screenshot I uploaded in #251.

@bobmoretti

Copy link
Copy Markdown
Contributor Author

Ok, thanks... still trying to understand... is the idea to find out whether the intersection between two polygons is nonempty? Or a polygon and circle?

Does this functionality really belong in PyDCS? Can/should liberation implement this routine separately?

@Raffson

Raffson commented Aug 20, 2022

Copy link
Copy Markdown
Contributor

Ok, thanks... still trying to understand... is the idea to find out whether the intersection between two polygons is nonempty? Or a polygon and circle?

I created a method that tests whether a point is inside a zone (so nothing like checking for intersected zone or such, yet...), so it's pretty general. The point in question could be the location of a unit, the center of another trigger zone like Liberation does, etc.

Does this functionality really belong in PyDCS? Can/should liberation implement this routine separately?

Imo yes, pydcs is more a library than an application, and good libraries usually provide a bunch of useful things with it, and I would say adding the capability to test if a something is inside a trigger zone falls under "useful things". Though I really wonder, why do you doubt whether this should be included in pydcs? Is there a particular reason for your doubt?

Comment thread dcs/triggers.py

# DCS mission format misspells the plural of "vertex". We follow this convention within PyDCS.
class TriggerZoneQuadPoint(TriggerZone):
def __init__(self, _id, position: mapping.Point, verticies: List[mapping.Point],

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What is this position? I know that the miz needs this for serialization, but I don't understand if there are any restrictions on how I pick it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@bobmoretti, any idea?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Sorry, it's been a couple months since I've looked at this, but I believe this parameter refers to the icon location in the mission editor. e.g. the "X" icon in the image below.

Here I modified one of the unit tests to create a quad trigger zone centered in Sukhumi, but place the position parameter on top of Gudauta. You can see that the name and icon for the zone are over Gudauta, while the actual trigger zone area is centered on Sukhumi.

caucasus = dcs.terrain.Caucasus()
m = dcs.mission.Mission(terrain=caucasus)
zone_center: dcs.mapping.Point = caucasus.sukhumi_babushara().position
other_point: dcs.mapping.Point = caucasus.gudauta().position
ZONE_RADIUS_M = 30000.0
offsets = [(ZONE_RADIUS_M, 0.0), (0.0, ZONE_RADIUS_M),
               (-ZONE_RADIUS_M, 0.0), (0.0, -ZONE_RADIUS_M)]
offsets = [dcs.mapping.Vector2(*o) for o in offsets]
verts = [zone_center + o for o in offsets]
m.triggers.add_triggerzone_quad(other_point, verts, False, "quad zone")
m.save('missions/test_quad_trigger_zone.miz')

image

As far as I know, this position only has an effect on the editor and not to gameplay. If I edit the zone vertices in the mission editor, DCS moves the marker (and thus this position parameter). It seems like DCS places the icon at the centroid of the convex hull of the quad.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Ah, alright then. I'll push a change to document that behavior, and potentially just remove it from the API? It seems doubtful that anyone making these zones actually cares, so we could just place it arbitrarily at the midpoint and simplify the API.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That's a good call. I guess I can't really think of a use case (since as soon as the user edits the zone in the ME the marker will be repositioned). But perhaps expose the position parameter optionally, defaulting to the centroid if unspecified?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants