How to make the "barrel" turn to a direction? (This should be the last question)

Started by Nicant, December 15, 2016, 09:31:57 PM

Previous topic - Next topic

Nicant

Okay, This is the last question i need answered for the custom module i'm making. What i'm asking is how do i get the barrel form my module to point at a particular direction? I know this involves the commands, Distance, ShortestAngle, and Atan2, but i do not know how to use them correctly in order to achieve this. I was looking at how PF did it with his Decoupler and Sniper weapons, but it is very confusing and only targets particles, not units. If anybody knows a thing that could push me in the right direction please tell me. Any help will be much appreciated and this should be the last question for my module until i bump into something else. :)
CW4 hype!!

GoodMorning

To point is easy. To find the angle:

TargetY CurrentY sub TargetX CuttentX sub atan2

Then SetImageRotation to this angle. Offset it if your barrel image needs it.

To track, make a series of small movements, and check after each if you are looking sufficiently close.
A narrative is a lightly-marked path to another reality.

planetfall

The version from DecouplerWeapon, with comments:


<-py <-y sub <-px <-x sub atan2 ->targetAngle #get the angle from the turret to the target.
<-targetAngle <-BarrelAngle ShortestAngle ->dist #find the angle between the current barrel and the target angle.
#for this gun, turn speed is 0.08 radians per tick
<-dist abs 0.08 lt if #The results of TargetAngle can be positive or negative. If it's between -0.08 and 0.08, it can turn to the target in one tick.
<-targetAngle ->BarrelAngle
CurrentCoords GetLand eq0 if
#fire
endif
else
#If the angle difference is too great, the sign of the result of ShortestAngle will tell us which way to turn.
<-dist 0 gt if
<-BarrelAngle 0.08 sub ->BarrelAngle
else
<-BarrelAngle 0.08 add ->BarrelAngle
endif
endif
Pretty sure I'm supposed to be banned, someone might want to get on that.

Quote from: GoodMorning on December 01, 2016, 05:58:30 PM"Build a ladder to the moon" is simple as a sentence, but actually doing it is not.

Nicant

Quote from: GoodMorning on December 16, 2016, 02:51:34 AM
To point is easy. To find the angle:

TargetY CurrentY sub TargetX CuttentX sub atan2

Then SetImageRotation to this angle. Offset it if your barrel image needs it.

To track, make a series of small movements, and check after each if you are looking sufficiently close.

Quote from: planetfall on December 16, 2016, 07:24:27 AM
The version from DecouplerWeapon, with comments:


<-py <-y sub <-px <-x sub atan2 ->targetAngle #get the angle from the turret to the target.
<-targetAngle <-BarrelAngle ShortestAngle ->dist #find the angle between the current barrel and the target angle.
#for this gun, turn speed is 0.08 radians per tick
<-dist abs 0.08 lt if #The results of TargetAngle can be positive or negative. If it's between -0.08 and 0.08, it can turn to the target in one tick.
<-targetAngle ->BarrelAngle
CurrentCoords GetLand eq0 if
#fire
endif
else
#If the angle difference is too great, the sign of the result of ShortestAngle will tell us which way to turn.
<-dist 0 gt if
<-BarrelAngle 0.08 sub ->BarrelAngle
else
<-BarrelAngle 0.08 add ->BarrelAngle
endif
endif


Ok, thanks! I will try both of these!
CW4 hype!!

Nicant

OK, i am officially clueless right now. The code for whatever reason should be detecting stunners, but for whatever reason is not. Here is the entire map that i'm using to test/build my custom module... The module that i'm having trouble with right now is called "OverCharger". If anyone has a clue or knows why it is not working, please, please, let me know. Any help will be Greatly appreciated!
CW4 hype!!

Oblivion

Change TargetType GetUnitCoords into TargetX GetUnitCoords.
TargetType holds the ID of the Unit
TargetX is the actual Unit

Idk what is up with the loop error thing
~Memes have been scientifrically proven to be the very essence of life unto itself~

Nicant

Quote from: Oblivion on December 16, 2016, 04:46:24 PM
Change TargetType GetUnitCoords into TargetX GetUnitCoords.
TargetType holds the ID of the Unit
TargetX is the actual Unit

Idk what is up with the loop error thing

Doing that does not seem to do anything because the script for whatever reason will not find stunners. Still good catch though, it makes the code a little bit shorter.
CW4 hype!!

GoodMorning

I'm rewriting to make it work.

However, I wonder how it ever got this broken. You even broke V's compiler. I'll send him a PM. Please don't change the map in the above post, he'll likely need it.

I.e.: You wrote:

if
do
endif
loop

(I think. It's hard to be sure, I fixed that partway through making the indenting consistent. We use the indenting to make the code readable.)
A narrative is a lightly-marked path to another reality.

GoodMorning

I think I've fixed it.


# --OverCharger-- 12/13/2016 5:37:20 PM
once
# Set up image(s). You NEED to set image layer to Ships, otherwise your module will render behind ships.
Self "main" "Custom0_128" SetImage
Self "Base" "Custom1_128" SetImage
Self "main" "Ships" SetImageLayer
Self "Base" "Ships" SetImageLayer
Self "main" 2 SetImageOrder
Self "Base" 1 SetImageOrder
Self "main" 1 1 SetImageScale
Self "Base" 1 1 SetImageScale
Self "ShipModule.prpl" "Ship" GetScriptVar ->Ship
<-Ship.ShipIsEnemy ->IsEnemy
-1 ->target
0 ->Trigger
0 ->BarrelAngle
endonce

#The heading of the ship the module is attached to.
Self "ShipModule.prpl" "ShipAngle" GetScriptVar ->ShipAngle

#The amount the heading has changed in the last frame (in radians)
Self "ShipModule.prpl" "delta" GetScriptVar ->Delta

#Whether the module exists.
#0 = hull destroyed
#1 = under construction
#2 = built
Self "ShipModule.prpl" "exist" GetScriptVar ->Exist

#If the module is destroyed, make it invisible and prevent the rest of the script from running.
<-Exist eq0 if
self "main" 0 0 0 0 SetImageColor
return
endif

#make module align with ship
#self "main" <-ShipAngle SetImageRotation #Disabled this so i could see if the barrel was aiming correctly.
self "base" <-ShipAngle SetImageRotation

IsPaused if
return
endif

#This is better found in-context, as CurrentX and CurrentY are likely faster then refread and refwrite.
# CurrentX ->x
# CurrentY ->y

<-Exist 1 eq if
# if under construction, make the module semi transparent.
# also use this for things like resetting turret rotation or cooldown if the module is destroyed and rebuilt
self "main" 255 255 255 128 SetImageColor
else
self "main" 255 255 255 255 SetImageColor
# I don't know of a way to read the Fire Multiple property on some enemy ships, which increases their fire rate.
# Instead, this script pretends that all enemy ships have amp gems.
<-Ship.ShipHasAmp <-IsEnemy or ->GemPresent #Whay do all opponents get automatic amp?
#code your module's abilities here

CurrentX CurrentY 9999 1 GetAllUnitsInRange ->Targets #Use 1 for a box search, it makes it somewhat faster.
<-Targets GetListCount 0 do
<-Targets[I] ->Target
<-Target GetUnitType ->TargetType
<-TargetType "Stunner" eq <-TargetType "Stunner(Clone)" eq or if     #Insert If It is Stunner here code
<-Target Trace
<-Target.UnitCoordX ->px
<-Target.UnitCoordY ->py
Self "main" GetImageRotation ->BarrelAngle
<-BarrelAngle Trace

<-py CurrentY sub <-px CurrentX sub Trace2
<-py CurrentY sub <-px CurrentX sub atan2 ->targetAngle #get the angle from the turret to the target.
<-targetAngle Trace
<-targetAngle <-BarrelAngle ShortestAngle ->dist #find the angle between the current barrel and the target angle.
#for this gun, turn speed is 0.08 radians per tick
<-dist abs 0.08 lt if #The results of TargetAngle can be positive or negative. If it's between -0.08 and 0.08, it can turn to the target in one tick.
<-targetAngle ->BarrelAngle
CurrentCoords GetLand eq0 if
#fire


endif
else
#If the angle difference is too great, the sign of the result of ShortestAngle will tell us which way to turn.
<-dist 0 gt if
<-BarrelAngle 0.08 sub ->BarrelAngle
else
<-BarrelAngle 0.08 add ->BarrelAngle
endif
endif
endif
loop
Self "main" <-BarrelAngle SetImageRotation
endif


:awake
# I dunno, I like to have all my scrpts OWP and exit partway through, I doubt it's caused by the brain chip.
1 OperateWhilePaused


I hope this is helpful? (Oh, and something is still going wrong with the image order. I'm not sure what, but changing the order of "main" to 3 in-editor fixed it.)
A narrative is a lightly-marked path to another reality.

Nicant

Quote from: GoodMorning on December 16, 2016, 05:31:45 PM
I think I've fixed it.


# --OverCharger-- 12/13/2016 5:37:20 PM
once
# Set up image(s). You NEED to set image layer to Ships, otherwise your module will render behind ships.
Self "main" "Custom0_128" SetImage
Self "Base" "Custom1_128" SetImage
Self "main" "Ships" SetImageLayer
Self "Base" "Ships" SetImageLayer
Self "main" 2 SetImageOrder
Self "Base" 1 SetImageOrder
Self "main" 1 1 SetImageScale
Self "Base" 1 1 SetImageScale
Self "ShipModule.prpl" "Ship" GetScriptVar ->Ship
<-Ship.ShipIsEnemy ->IsEnemy
-1 ->target
0 ->Trigger
0 ->BarrelAngle
endonce

#The heading of the ship the module is attached to.
Self "ShipModule.prpl" "ShipAngle" GetScriptVar ->ShipAngle

#The amount the heading has changed in the last frame (in radians)
Self "ShipModule.prpl" "delta" GetScriptVar ->Delta

#Whether the module exists.
#0 = hull destroyed
#1 = under construction
#2 = built
Self "ShipModule.prpl" "exist" GetScriptVar ->Exist

#If the module is destroyed, make it invisible and prevent the rest of the script from running.
<-Exist eq0 if
self "main" 0 0 0 0 SetImageColor
return
endif

#make module align with ship
#self "main" <-ShipAngle SetImageRotation #Disabled this so i could see if the barrel was aiming correctly.
self "base" <-ShipAngle SetImageRotation

IsPaused if
return
endif

#This is better found in-context, as CurrentX and CurrentY are likely faster then refread and refwrite.
# CurrentX ->x
# CurrentY ->y

<-Exist 1 eq if
# if under construction, make the module semi transparent.
# also use this for things like resetting turret rotation or cooldown if the module is destroyed and rebuilt
self "main" 255 255 255 128 SetImageColor
else
self "main" 255 255 255 255 SetImageColor
# I don't know of a way to read the Fire Multiple property on some enemy ships, which increases their fire rate.
# Instead, this script pretends that all enemy ships have amp gems.
<-Ship.ShipHasAmp <-IsEnemy or ->GemPresent #Whay do all opponents get automatic amp?
#code your module's abilities here

CurrentX CurrentY 9999 1 GetAllUnitsInRange ->Targets #Use 1 for a box search, it makes it somewhat faster.
<-Targets GetListCount 0 do
<-Targets[I] ->Target
<-Target GetUnitType ->TargetType
<-TargetType "Stunner" eq <-TargetType "Stunner(Clone)" eq or if     #Insert If It is Stunner here code
<-Target Trace
<-Target.UnitCoordX ->px
<-Target.UnitCoordY ->py
Self "main" GetImageRotation ->BarrelAngle
<-BarrelAngle Trace

<-py CurrentY sub <-px CurrentX sub Trace2
<-py CurrentY sub <-px CurrentX sub atan2 ->targetAngle #get the angle from the turret to the target.
<-targetAngle Trace
<-targetAngle <-BarrelAngle ShortestAngle ->dist #find the angle between the current barrel and the target angle.
#for this gun, turn speed is 0.08 radians per tick
<-dist abs 0.08 lt if #The results of TargetAngle can be positive or negative. If it's between -0.08 and 0.08, it can turn to the target in one tick.
<-targetAngle ->BarrelAngle
CurrentCoords GetLand eq0 if
#fire


endif
else
#If the angle difference is too great, the sign of the result of ShortestAngle will tell us which way to turn.
<-dist 0 gt if
<-BarrelAngle 0.08 sub ->BarrelAngle
else
<-BarrelAngle 0.08 add ->BarrelAngle
endif
endif
endif
loop
Self "main" <-BarrelAngle SetImageRotation
endif


:awake
# I dunno, I like to have all my scrpts OWP and exit partway through, I doubt it's caused by the brain chip.
1 OperateWhilePaused


I hope this is helpful? (Oh, and something is still going wrong with the image order. I'm not sure what, but changing the order of "main" to 3 in-editor fixed it.)

Yes! Thank you very much it now works now! The image order will sometimes do that for whatever reason. Thanks though! :)
CW4 hype!!

knucracker

Quote from: GoodMorning on December 16, 2016, 05:27:59 PM
I'm rewriting to make it work.

However, I wonder how it ever got this broken. You even broke V's compiler. I'll send him a PM. Please don't change the map in the above post, he'll likely need it.

I.e.: You wrote:

if
do
endif
loop

(I think. It's hard to be sure, I fixed that partway through making the indenting consistent. We use the indenting to make the code readable.)


Yes... very interesting.  This compiles:

if (0)
do (10 0)
trace(I)
endif
loop


The reason is that "endif" is just a command like any other.  It doesn't do anything other than mark a spot to jump to when the "if" condition if false.  So in the above code, the "if" will jump to the "loop" command.  That will make a prpl core encounter a "loop" having never encountered the "do".  It catches that error at run time and spits out a warning that says "Loop stack vars not present at line: 7".

If the "if" has been true, the code would have worked correctly.  The endif in the middle of the do/loop would have been benign.

The PRPL compiler should have caught this situation (it catches a range of nesting errors).  But it doesn't catch this case where an if is overlapping a do/loop.  This same problem should exist in CW3 and have been present since 2013 :)  I don't know that I will do anything about it (not for PF and CW3).

GoodMorning

I doubt that it will ever come up again, but just drawing your attention.
A narrative is a lightly-marked path to another reality.