Difference between revisions of "Sensor degradation with range or facing"

From FreeSpace Wiki
Jump to: navigation, search
(Improved comments)
(Improved comments)
Line 1: Line 1:
The following event is based on an idea by SypheDMar, as proposed in #freespace. It will, in theory, make a set of fighters either be invisible, show up as a fuzzy radar blip, or be fully targetable, all depending on their range to the player as well as whether the player is facing them (or more specifically if he has them within a 60-degree forward cone). Detailed explanation below, but without further ado, the event itself:
+
The following event is based on an idea by SypheDMar, as proposed in #freespace. It will, in theory, make a set of fighters either be invisible, show up as a fuzzy radar blip, or be fully targetable, all depending on their range to the player as well as whether the player is facing them (or more specifically if he has them within a 60-degree forward cone).
 +
 
 +
==Nested 'when'-based event==
 +
 
 +
The following version of the event demonstrates a number of things, not the least of which are nested 'when' operators, shared argument list between the nested whens, and considerable use of and/or-operators to fine tune triggers. Detailed explanation below, but without further ado, the event itself:
  
 
  - <span style="color:red">op</span> when-argument
 
  - <span style="color:red">op</span> when-argument
Line 106: Line 110:
 
           # <argument>
 
           # <argument>
  
Note the use of nested 'when' operators to cover three distinct sets of possibilities within the same event, which allows them to draw on the same argument list. This is not terribly important in this particular case, as no arguments are invalidated or revalidated, but it is kept as one event for demonstration purposes. If one prefers, the event could easily be split in three without any change in functionality (one for each distance bracket).
+
Note the use of nested 'when' operators to cover three distinct sets of possibilities (in this case, distance brackets, but anything goes) within the same event, which allows them to draw on the same argument list. This is not terribly important in this particular case, as no arguments are invalidated or revalidated, but it is kept as one event for demonstration purposes. If one prefers, the event could easily be split in three without any change in functionality (one for each distance bracket).
 +
 
 +
The trigger conditions for each distance bracket are complicated by the fact that for this example, the direction the player is facing is also taken into account - If a ship is within a 60-degree forward cone of the player, it can be targeted at a significantly greater distance than otherwise. To account for this, each distance bracket actually has two distinct sets of trigger conditions, one for when the player is facing the right way, and one for when he isn't. And each of those sets in itself may require multiple conditions. This is all accomplished with a combination of [[and]] operators and [[or]] operators, allowing very precise tuning of when an given action should be triggered.
 +
 
 +
Finally, each distance bracket has a further condition which checks whether the ship currently being looked at is already set up for the bracket. Why? There's no point changing anything if nothing needs to be changed, and it's a waste of resources to, say, go setting invisibility flags for twenty ships every frame if they already have it set. It isn't strictly necessary to include such a check, but optimising where you can is a good habit to get into.
 +
 
 +
==If-then-else-based Event==
  
 
Now, using the above event (or three seperate ones), every distance bracket will get checked every frame against the argument list. Which, on the surface of it, is exactly what you want. But what if you could make it so the distance brackets are checked in turn, the next one in line only checked if the first one fails? That would surely save some CPU cycles. The thing is, you can. FreeSpace_Open now includes an [[if-then-else]] operator, which will let us do precisely that:
 
Now, using the above event (or three seperate ones), every distance bracket will get checked every frame against the argument list. Which, on the surface of it, is exactly what you want. But what if you could make it so the distance brackets are checked in turn, the next one in line only checked if the first one fails? That would surely save some CPU cycles. The thing is, you can. FreeSpace_Open now includes an [[if-then-else]] operator, which will let us do precisely that:

Revision as of 13:22, 19 February 2011

The following event is based on an idea by SypheDMar, as proposed in #freespace. It will, in theory, make a set of fighters either be invisible, show up as a fuzzy radar blip, or be fully targetable, all depending on their range to the player as well as whether the player is facing them (or more specifically if he has them within a 60-degree forward cone).

Nested 'when'-based event

The following version of the event demonstrates a number of things, not the least of which are nested 'when' operators, shared argument list between the nested whens, and considerable use of and/or-operators to fine tune triggers. Detailed explanation below, but without further ado, the event itself:

- op when-argument
   - op any-of
      # <list of ships for which to apply range/facing-based targetability>
   - op true
   - op when
      - op and
         - op not
            - op is-ship-stealthy
               # <argument>
         - op or
            - op and
               - op >
                  - op distance
                     # <argument>
                     # Alpha 1
                  # 3000
               - op facing
                  # <argument>
                  # 60
            - op and
               - op >
                  - op distance
                     # <argument>
                     # Alpha 1
                  # 1000
               - op not
                  - op facing
                     # <argument>
                     # 60
      - op ship-stealthy
         # <argument>
   - op when
      - op and
         - op or
            - op is-ship-visible
               # <argument>
            - op is-ship-stealthy
               # <argument>
         - op or
            - op and
               - op <=
                  - op distance
                     # <argument>
                     # Alpha 1
                  # 3000
               - op >
                  - op distance
                     # <argument>
                     # Alpha 1
                  # 1000
               - op facing
                  # <argument>
                  # 60
            - op and
               - op <=
                  - op distance
                     # <argument>
                     # Alpha 1
                  # 1000
               - op >
                  - op distance
                     # <argument>
                     # Alpha 1
                  # 300
               - op not
                  - op facing
                     # <argument>
                     # 60
      - op ship-invisible
         # <argument>
      - op ship-unstealthy
         # <argument>
   - op when
      - op and
         - op or
            - op not
               - op is-ship-visible
                  # <argument>
            - op is-ship-stealthy
               # <argument>
         - op or
            - op and
               - op <=
                  - op distance
                     # <argument>
                     # Alpha 1
                  # 1000
               - op facing
                  # <argument>
                  # 60
            - op and
               - op <=
                  - op distance
                     # <argument>
                     # Alpha 1
                  # 300
               - op not
                  - op facing
                     # <argument>
                     # 60
      - op ship-visible
         # <argument>
      - op ship-unstealthy
         # <argument>

Note the use of nested 'when' operators to cover three distinct sets of possibilities (in this case, distance brackets, but anything goes) within the same event, which allows them to draw on the same argument list. This is not terribly important in this particular case, as no arguments are invalidated or revalidated, but it is kept as one event for demonstration purposes. If one prefers, the event could easily be split in three without any change in functionality (one for each distance bracket).

The trigger conditions for each distance bracket are complicated by the fact that for this example, the direction the player is facing is also taken into account - If a ship is within a 60-degree forward cone of the player, it can be targeted at a significantly greater distance than otherwise. To account for this, each distance bracket actually has two distinct sets of trigger conditions, one for when the player is facing the right way, and one for when he isn't. And each of those sets in itself may require multiple conditions. This is all accomplished with a combination of and operators and or operators, allowing very precise tuning of when an given action should be triggered.

Finally, each distance bracket has a further condition which checks whether the ship currently being looked at is already set up for the bracket. Why? There's no point changing anything if nothing needs to be changed, and it's a waste of resources to, say, go setting invisibility flags for twenty ships every frame if they already have it set. It isn't strictly necessary to include such a check, but optimising where you can is a good habit to get into.

If-then-else-based Event

Now, using the above event (or three seperate ones), every distance bracket will get checked every frame against the argument list. Which, on the surface of it, is exactly what you want. But what if you could make it so the distance brackets are checked in turn, the next one in line only checked if the first one fails? That would surely save some CPU cycles. The thing is, you can. FreeSpace_Open now includes an if-then-else operator, which will let us do precisely that:

- op when-argument
   - op any-of
      # <list of ships for which to apply range/facing-based targetability>
   - op true
   - op if-then-else
      - op and
         - op not
            - op is-ship-stealthy
               # <argument>
         - op or
            - op and
               - op >
                  - op distance
                     # <argument>
                     # Alpha 1
                  # 3000
               - op facing
                  # <argument>
                  # 60
            - op and
               - op >
                  - op distance
                     # <argument>
                     # Alpha 1
                  # 1000
               - op not
                  - op facing
                     # <argument>
                     # 60
      - op ship-stealthy
         # <argument>
      - op if-then-else
         - op and
            - op or
               - op is-ship-visible
                  # <argument>
               - op is-ship-stealthy
                  # <argument>
            - op or
               - op and
                  - op <=
                     - op distance
                        # <argument>
                        # Alpha 1
                     # 3000
                  - op >
                     - op distance
                        # <argument>
                        # Alpha 1
                     # 1000
                  - op facing
                     # <argument>
                     # 60
               - op and
                  - op <=
                     - op distance
                        # <argument>
                        # Alpha 1
                     # 1000
                  - op >
                     - op distance
                        # <argument>
                        # Alpha 1
                     # 300
                  - op not
                     - op facing
                        # <argument>
                        # 60
         - op when
            - op true
            - op ship-invisible
               # <argument>
            - op ship-unstealthy
               # <argument>
         - op when
            - op and
               - op or
                  - op not
                     - op is-ship-visible
                        # <argument>
                  - op is-ship-stealthy
                     # <argument>
               - op or
                  - op and
                     - op <=
                        - op distance
                           # <argument>
                           # Alpha 1
                        # 1000
                     - op facing
                        # <argument>
                        # 60
                  - op and
                     - op <=
                        - op distance
                           # <argument>
                           # Alpha 1
                        # 300
                     - op not
                        - op facing
                           # <argument>
                           # 60
            - op ship-visible
               # <argument>
            - op ship-unstealthy
               # <argument>

In the revised event above, if-then-else is used to check the three distance brackets in sequence. If a ship is shown to place within a bracket, it acts on that and breaks out, whereas if a ship is not within the bracket being checked, it moves on to the next bracket and checks that instead. This reduces the amount of checks that happen compared to the first version of the event, and as a result will place a slightly lower demand on system resources. And while this is generally not a noticable effect, every CPU cycle does count.

Note the use of an additional nested 'when' in the second 'if-then-else'. This is necessary as there is more than one action to be taken, and only the second argument of the 'if-then-else' operator is the action to be taken if it is true - Third and beyond is for when it is false. Hence, the 'when' is used to group two actions into one argument.

Also note that the last case is not an 'if-then-else', but a 'when', just as in the first version of the event. This is because it is the last case, and as such there is no 'else' if this fails as well. However, it is NOT a default case which will always be carried out should the other two fail. Were that the case, the actions in it could simply be tacked onto the third-and-beyond argument of the second 'if-then-else', with no need for the 'when'.