• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Accuracy of guns?

Status
Not open for further replies.
Level 6
Joined
Feb 16, 2014
Messages
193
So heres what i wanted to happen -
I use the item ability(M202A2) then it creates a dummy unit at the position of the Caster then that dummy unit shoots at the Target point of ability being cast(it works) but the main problem is that it wont shoot randomly(like the farther u shoot it the worse the accuracy gets)Every 100 distance from where u shoot,then the region where the projectile will randomly land increases.
  • M202A2
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Use M202A2
    • Actions
      • Set UnitLoc = (Position of (Casting unit))
      • Set PointOfShot = ((Integer((Distance between (Position of (Casting unit)) and (Target point of ability being cast)))) + 100)
      • Unit - Create 1 M202A2 for (Owner of (Casting unit)) at UnitLoc facing Default building facing degrees
      • Unit - Add a 1.50 second Generic expiration timer to (Last created unit)
      • For each (Integer PointOfShot) from 1 to 10, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Level of Add Accuracy for (Triggering unit)) Equal to 0
            • Then - Actions
              • Unit - Order (Last created unit) to Attack Ground (Random point in (Region centered at (Target point of ability being cast) with size ((0.00 + 60.00), (0.00 + 60.00))))
            • Else - Actions
      • Custom script: call RemoveLocation(udg_UnitLoc)
Yes the bullets spread but only a little(The region with size of 60)the region still doesnt increase in size even when i shoot it far away,i want it to be that the farther u shoot then the region where the bullet or projectile lands randomly increases size. Please help :ogre_rage: As for that ability in the condition of the If/Then/Else i also tried that without that condition but still the same happens
 
Last edited:
Level 5
Joined
Feb 17, 2011
Messages
95
Here is an idea, find an angle between shooter and target, and add +/- some angle to it, and shoot towards that angle. The further the target is, higher will be the chance to miss. You could also add accuracy (as angle) to the formula. Simply:

angle(unitLoc to pointOfShot) +/- accuracy

Edit:
If you shoot at the region of the same size, it can't get less accurate as the target moves away. Instead of 60x60 region, use something like "pointOfShot / 10" for region width and length.
Edit:
Instead of "pointOfShot / 10" you could, again, use accuracy as angle, and base formula on that. For example
"pointOfShot * tan(accuracy) * 2", and use that as region width and height. Or even:
"pointOfShot * tan(1/level of accuracy * accuracy) * 2"
 
Last edited:
Level 6
Joined
Feb 16, 2014
Messages
193
Here is an idea, find an angle between shooter and target, and add +/- some angle to it, and shoot towards that angle. The further the target is, higher will be the chance to miss. You could also add accuracy (as angle) to the formula. Simply:

angle(unitLoc to pointOfShot) +/- accuracy

Edit:
If you shoot at the region of the same size, it can't get less accurate as the target moves away. Instead of 60x60 region, use something like "pointOfShot / 10" for region width and length.
Edit:
Instead of "pointOfShot / 10" you could, again, use accuracy as angle, and base formula on that. For example
"pointOfShot * tan(accuracy) * 2", and use that as region width and height. Or even:
"pointOfShot * tan(1/level of accuracy * accuracy) * 2"
If i put it in 10x10 region then wheres the challenge of that,players would just be able to hit each other everytime.Example:
I see and enemy and shoot him,the distance when i used the ability is like 100 then the region where the projectile will randomly land is 60x60 but when its 300 then it will be 180x180 the size of the region(thats what i wanted to do).Though your idea is good i can't understand some of it,what is tan?
 
Level 25
Joined
Sep 26, 2009
Messages
2,381
First off, that trigger will never work well.
Everything in that trigger will happen instantly, without anything elsewhere interfering or changing.
Your loop that loops 10 times will always return the same result. So if this statement inside loop is true:
  • (Level of Add Accuracy for (Triggering unit)) Equal to 0
in the first iteration, it will return true for all the remaining iterations, same for if it is false.
Hence the loop looses its purpose.
Also, I'm not sure what you're expecting of the loop, but the way the "For each (integer variable) from X to Y" loop works is that when it is initiated, it changes the value of "integer variable" you put there to value X and with each iteration of the loop, it increases value of the variable by 1, until the value in the variable is higher than Y in which case it stops the loop.
So if you do this:
  • Set PointOfShot = ((Integer((Distance between (Position of (Casting unit)) and (Target point of ability being cast)))) + 100)
and 2 lines later you use PointOfShot as the integer variable for the loop, you're rewriting what you saved into the variable before the loop.
Not to say you actually don't use PointOfShot anywhere, so the whole action there is redundant.

You're not using any variables in your equations.
You write that you want the region size increase with increased distance, but what do you actually do in your code? You sum 0.00 + 60.00... what else can this return than 60.00?

You order the unit you created (I guess that's an actual bullet) to move to point. Do know, tho, that the unit will not travel in straight line, due to how wc3 handles unit movement, which in your case will look terrible, since the bullet's travel path will not be a straight line, but a curve which of course does not happen in real world.


Your trigger leaks. You incorrectly use variables.
Basically, when you use the "(Center/Random Point of "Region")", "(Position of (unit))" and any other action which has something to do with locations, you create a location.

For example in only this part of trigger you create 3 locations:
  • Set UnitLoc = (Position of (Casting unit))
    • Set PointOfShot = ((Integer((Distance between (Position of (Casting unit)) and (Target point of ability being cast)))) + 100)
Those are: (Position of (Casting unit)), (Position of (Casting unit)) and (Target point of ability being cast).
Only the first one is correctly set into variable UnitLoc and later destroyed. The other two are not, hence only these two lines produced 2 memory leaks.
Instead of calling (Position of (Casting unit)) all the time, use the variable "UnitLoc".

Lastly, change (Casting unit) for (Triggering unit). Triggering unit is a unit which starts the trigger, which in your case is the same unit as the one who casts the spell (aka (Casting unit)), but (Triggering unit) is more efficient and better choice for various reasons.

Now I would solve this problem with same approach as bajaist - using angles.
You can easily determine the angle between attacker and the target. If you add to this angle some random amount from an interval of let's say [-10,10], then the shot won't be accurate. Check the pic below.

attachment.php


The black line is the direct line from attacker to target. If you add some random value to the angle of the line, the shot won't be accurate. In the pic, the random angle is alpha. As you can see, the red line, which is the original black line offset by alpha, will not hit the target.
You can also see, that with target's increasing distance from attacker, the chances of the shot to hit the target are decreasing as shown by the blue and gray arrows.
 

Attachments

  • angle.jpg
    angle.jpg
    17.1 KB · Views: 180
Level 6
Joined
Feb 16, 2014
Messages
193
First off, that trigger will never work well.
Everything in that trigger will happen instantly, without anything elsewhere interfering or changing.
Your loop that loops 10 times will always return the same result. So if this statement inside loop is true:
  • (Level of Add Accuracy for (Triggering unit)) Equal to 0
in the first iteration, it will return true for all the remaining iterations, same for if it is false.
Hence the loop looses its purpose.
Also, I'm not sure what you're expecting of the loop, but the way the "For each (integer variable) from X to Y" loop works is that when it is initiated, it changes the value of "integer variable" you put there to value X and with each iteration of the loop, it increases value of the variable by 1, until the value in the variable is higher than Y in which case it stops the loop.
So if you do this:
  • Set PointOfShot = ((Integer((Distance between (Position of (Casting unit)) and (Target point of ability being cast)))) + 100)
and 2 lines later you use PointOfShot as the integer variable for the loop, you're rewriting what you saved into the variable before the loop.
Not to say you actually don't use PointOfShot anywhere, so the whole action there is redundant.

You're not using any variables in your equations.
You write that you want the region size increase with increased distance, but what do you actually do in your code? You sum 0.00 + 60.00... what else can this return than 60.00?

You order the unit you created (I guess that's an actual bullet) to move to point. Do know, tho, that the unit will not travel in straight line, due to how wc3 handles unit movement, which in your case will look terrible, since the bullet's travel path will not be a straight line, but a curve which of course does not happen in real world.


Your trigger leaks. You incorrectly use variables.
Basically, when you use the "(Center/Random Point of "Region")", "(Position of (unit))" and any other action which has something to do with locations, you create a location.

For example in only this part of trigger you create 3 locations:
  • Set UnitLoc = (Position of (Casting unit))
    • Set PointOfShot = ((Integer((Distance between (Position of (Casting unit)) and (Target point of ability being cast)))) + 100)
Those are: (Position of (Casting unit)), (Position of (Casting unit)) and (Target point of ability being cast).
Only the first one is correctly set into variable UnitLoc and later destroyed. The other two are not, hence only these two lines produced 2 memory leaks.
Instead of calling (Position of (Casting unit)) all the time, use the variable "UnitLoc".

Lastly, change (Casting unit) for (Triggering unit). Triggering unit is a unit which starts the trigger, which in your case is the same unit as the one who casts the spell (aka (Casting unit)), but (Triggering unit) is more efficient and better choice for various reasons.

Now I would solve this problem with same approach as bajaist - using angles.
You can easily determine the angle between attacker and the target. If you add to this angle some random amount from an interval of let's say [-10,10], then the shot won't be accurate. Check the pic below.

attachment.php


The black line is the direct line from attacker to target. If you add some random value to the angle of the line, the shot won't be accurate. In the pic, the random angle is alpha. As you can see, the red line, which is the original black line offset by alpha, will not hit the target.
You can also see, that with target's increasing distance from attacker, the chances of the shot to hit the target are decreasing as shown by the blue and gray arrows.
You have a point,though(in the blue colored text) i made a mortar team dummy unit with the Weapon Type - Artillery so when its ordered to "attack ground" it will not move there but it will fire a projectile in that area because its weapon type is artillery.Though that is what i want to do(the green colored text)
 
Level 6
Joined
Feb 16, 2014
Messages
193
Maybe ill try this instead though theres a problem
  • If - Conditions
    • (Integer((Distance between (Position of (Triggering unit)) and (Position of (Target unit of ability being cast))))) Less than or Equal to 700
How do i make it like 0-700 instead of only less than or equal to 700
 
Level 6
Joined
Feb 16, 2014
Messages
193
LOL i found it out by my self after all
  • PG Mark I
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to PG Mark I
    • Actions
      • Set UnitLoc = (Position of (Casting unit))
      • Set Range3 = ((Distance between (Position of (Casting unit)) and (Target point of ability being cast)) / ((Real((Agility of (Casting unit) (Include bonuses)))) + 3.00))
      • Unit - Create 1 PG Mark I for (Owner of (Casting unit)) at UnitLoc facing Default building facing degrees
      • Unit - Add a 3.00 second Generic expiration timer to (Last created unit)
      • Unit - Order (Last created unit) to Attack Ground (Random point in (Region centered at (Target point of ability being cast) with size (Range3, Range3)))
      • Custom script: call RemoveLocation(udg_UnitLoc)
Agility is the Accuracy level of the unit/hero
 
Level 25
Joined
Sep 26, 2009
Messages
2,381
A more complicated approach, but certainly a possibility. However you have numerous memory leaks in that trigger. For efficiency sake you should remove those leaks.
You have 4 memory leaks (location leaks) in your trigger.
 
Level 6
Joined
Feb 16, 2014
Messages
193
Ok i'll try to remove those leaks.
@deathismyfriend should i use 2 variables for that or 1 is enough?

Is this ok now?
  • PG Mark I
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to PG Mark I
    • Actions
      • Set UnitLoc = (Position of (Triggering unit))
      • Set AbltTarget = (Target point of ability being cast)
      • Set RPoint = (Random point in (Region centered at AbltTarget with size (Range3, Range3)))
      • Set Range3 = ((Distance between UnitLoc and AbltTarget) / ((Real((Agility of (Triggering unit) (Include bonuses)))) + 3.00))
      • Unit - Create 1 PG Mark I for (Owner of (Triggering unit)) at UnitLoc facing Default building facing degrees
      • Unit - Add a 3.00 second Generic expiration timer to (Last created unit)
      • Unit - Order (Last created unit) to Attack Ground RPoint
      • Custom script: call RemoveLocation(udg_UnitLoc)
      • Custom script: call RemoveLocation(udg_AbltTarget)
      • Custom script: call RemoveLocation(udg_RPoint)
 
Last edited by a moderator:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,201
I would use point with polar offset with this.
RPoint = UnitLoc offset by Range3 towards random angle.
That is not functionally the same as what he wanted?

Surely the accuracy should use a Gaussian model independent on target distance? For nearby targets this will be accurate as they fill up more arc and so are exposed to more probability of being hit. As targets are further away and fill up less of the arc their probability of being hit decreases so shots become less accurate.

The current implementation might be open to exploit where a player can land an accurate long shot simply by targeting close by to use a lower inaccuracy bracket.
 
Level 6
Joined
Feb 16, 2014
Messages
193
The region leaks.

I would use point with polar offset with this.
RPoint = UnitLoc offset by Range3 towards random angle.
  • Set RPoint = (Random point in (Region centered at UnitLoc with size (Range3, Range3)))
  • Custom script: call RemoveLocation(udg_AbltTarget)
But i removed the location,shouldn't that remove the leak as well?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,201
But i removed the location,shouldn't that remove the leak as well?
No it does not remove the rect you are leaking.

You need to use this native to remove it.
JASS:
native RemoveRect takes rect whichRect returns nothing

Which should look something like this when used.
JASS:
call RemoveRect(rect)

So your trigger needs to do this.
  • Set RRect = (Region centered at UnitLoc with size (Range3, Range3))
  • Set RPoint = (Random point in (RRect))
  • Custom script: call RemoveRect(udg_RRect)
You still need to remove RPoint once you are done with it however I am sure you know all about location leaks.

Rects are what GUI calls "Regions" however they are not to be confused with real JASS regions which are a completely different object type used for completely different purposes.
 
Level 6
Joined
Feb 16, 2014
Messages
193
Is this correct now?
  • PG Mark I
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to PG Mark I
    • Actions
      • Set UnitLoc = (Position of (Triggering unit))
      • Set AbltTarget = (Target point of ability being cast)
      • Set Range3 = ((Distance between UnitLoc and AbltTarget) / ((Real((Agility of (Triggering unit) (Include bonuses)))) + 3.00))
      • Set RPoint = (Region centered at AbltTarget with size (Range3, Range3))
      • Set ShootRegion = (Random point in RPoint)
      • Unit - Create 1 PG Mark I for (Owner of (Triggering unit)) at UnitLoc facing Default building facing degrees
      • Unit - Add a 3.00 second Generic expiration timer to (Last created unit)
      • Unit - Order (Last created unit) to Attack Ground ShootRegion
      • Custom script: call RemoveLocation(udg_UnitLoc)
      • Custom script: call RemoveLocation(udg_AbltTarget)
      • Custom script: call RemoveRect(udg_RPoint)
 
Status
Not open for further replies.
Top