Farbor-Like Ships (help needed)

Started by planetfall, January 21, 2014, 09:34:43 PM

Previous topic - Next topic

planetfall

Hello all, I'm new here, as no doubt you can tell.

I'm trying to create ships like the ones in Farbor (go out, collect something, return, unload fake packets, repeat), except going to emitters instead of ore deposits.

However, depending on which of the two methods for rotating the image I use, it either rotates on the launch pad forever (the version commented out here) or flips around and then just sits there (the "active" one).

The relevant part of my horrendously long and no doubt unoptimized code:

<-mode 2 eq if
<-target CONST_ISDESTROYED GetUnitAttribute 0 eq if
<-child CONST_ISDESTROYED GetUnitAttribute 1 eq if
"CRPLCORE" <-target CONST_COORDX GetUnitAttribute <-target CONST_COORDY GetUnitAttribute CreateUnit ->child
<-child "marker.crpl" AddScriptToUnit
<-child "marker.crpl" "parent" SetScriptVar
endif
<-target CONST_COORDY GetUnitAttribute CurrentY sub
<-target CONST_COORDX GetUnitAttribute CurrentX sub
atan2 ->heading
<-launch if
0 ->launch
GetQueuedMoveCount 0 eq if
<-target CONST_COORDX GetUnitAttribute <-target CONST_COORDY GetUnitAttribute 2 QueueMove
endif
else
1 ->launch
Self "main" <-heading SetImageRotation
#8 0 do
# <-launch 0 eq if
# Self "main" GetImageRotation <-heading ShortestAngle 0 gt if
# Self "main" Self "main" GetImageRotation 0.005 sub SetImageRotation
# <-ang 2 eq if
# 1 ->launch
# 0 ->ang
# else
# 1 ->ang
# endif
# else
# Self "main" Self "main" GetImageRotation 0.005 add SetImageRotation
# <-ang 1 eq if
# 1 ->launch
# 0 ->ang
# else
# 2 ->ang
# endif
# endif
# endif
#loop
endif
else
1 ->mode
endif
CurrentX <-target CONST_COORDX GetUnitAttribute eq CurrentY <-target CONST_COORDY GetUnitAttribute eq <-parent <-target neq and and if
3 ->mode
<-child CONST_CREATEPZ 0 SetUnitAttribute
<-child 0 Destroy
10 SetTimer0
endif
endif


Thanks.
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.

Michionlion

I can't find where you set target, but it sounds like something is wonky there.  Try giving it fixed coords to go to, and see if it works then.  If not, then I'm wrong...
"Remember kids, the only difference between science and messing around is writing it down."
                                                                                                                         - Adam Savage

My website
My CW1, and CW2 maps!

eduran

1) You could load up Farbor in the editor (http://knucklecracker.com/forums/index.php?topic=14675.0), copy the script used there and modify the target selection to match your needs. Or just copy the function that rotates the ships.

2) It is hard to tell what is going wrong with only part of the code. I can see a few minor issues, but nothing that should prevent the QueueMove command from working. I agree with Michionlion, there is probably something wrong with your target selection.

planetfall

Quote from: Michionlion on January 21, 2014, 11:41:34 PM
I can't find where you set target, but it sounds like something is wonky there.  Try giving it fixed coords to go to, and see if it works then.  If not, then I'm wrong...

Well, it does correctly create a core on the emitter and give it marker.crpl. Maybe it should follow child instead of target...?

Quote from: eduran on January 22, 2014, 04:44:41 AM
1) You could load up Farbor in the editor (http://knucklecracker.com/forums/index.php?topic=14675.0), copy the script used there and modify the target selection to match your needs. Or just copy the function that rotates the ships.

And I suppose that's what I get for coming here and not reading around. That's probably what I'll do this afternoon when I have more time. Thanks!
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.

Michionlion

#4
"Remember kids, the only difference between science and messing around is writing it down."
                                                                                                                         - Adam Savage

My website
My CW1, and CW2 maps!

planetfall

Quote from: Michionlion on January 22, 2014, 09:25:15 AM
You should be able to directly get the GUID of the emitter, with sometime like http://knucklecracker.com/wiki/doku.php?id=crpl:docs:getenemyunitsinrange or http://knucklecracker.com/wiki/doku.php?id=crpl:docs:getallunitsinrange.

That was already being done, and stored in the variable target (though not in the code I showed you).

Well, I mostly redid the script, compiled, failed, checked, double-checked and now I'm stuck. Here it is in its entirety.

# collectorship.crpl
# Created on: 1/22/2014 5:57:11 PM
# ------------------------------------------

once
Self "main" "Custom4" SetImage
Self CONST_CREATEPZ 0 SetUnitAttribute
Self CONST_COUNTSFORVICTORY 0 SetUnitAttribute
Self CONST_SNIPERTARGET 1 SetUnitAttribute
Self CONST_NULLIFIERDAMAGES 0 SetUnitAttribute
Self CONST_MAXAMMO 10 SetUnitAttribute
Self CONST_AMMO 0 SetUnitAttribute
Self "main" 0 0 255 255 SetImageColor
"CollectorShip" ->coretype
Self "main" -2 SetImagePositionZ
0 ->mode
14 CurrentCoords CellToPixel -1 1 1 0.1 CreateEffect
60 Delay
14 CurrentCoords CellToPixel -1 1 1 0.1 CreateEffect
60 Delay
Self CONST_SNIPERTARGET 1 SetUnitAttribute
<-parent ->target
endonce

<-parent CONST_ISDESTROYED GetUnitAttribute 1 eq if
Self 0 Destroy
endif

<-mode 0 eq if
Self CONST_AMMO GetUnitAttribute 1 gte if
CurrentCoords IsDigitalisConnected if
"coretype" "CmdNode" GetCoresWithVar CONST_AMMO GetUnitAttribute 200 lt if
"CRPLCORE" CurrentCoords CreateUnit ->packet
<-packet "packet_in.crpl" AddScriptToUnit
Self CONST_AMMO Self CONST_AMMO GetUnitAttribute 1 sub SetUnitAttribute
endif
endif
45 SetTimer0
else
1 ->mode
endif
endif

<-mode 1 eq if
@FindTarget
<-parent <-target neq if
2 ->mode
"CRPLCORE" <-target CONST_COORDX GetUnitAttribute <-target CONST_COORDY GetUnitAttribute CreateUnit ->child
<-child "marker.crpl" AddScriptToUnit
<-child "marker.crpl" "parent" SetScriptVar
endif
endif

<-mode 2 eq if
<-target CONST_ISDESTROYED GetUnitAttribute 1 eq if
@FindTarget
<-child 3 Destroy
"CRPLCORE" <-target CONST_COORDX GetUnitAttribute <-target CONST_COORDY GetUnitAttribute CreateUnit ->child
<-child "marker.crpl" AddScriptToUnit
<-child "marker.crpl" "parent" SetScriptVar
endif
<-target <-parent eq if
4 ->mode
else
0 ->correctAngle
@Turn
<-correctAngle if
GetQueuedMoveCount neq0 if
<-target CONST_COORDX GetUnitAttribute <-target CONST_COORDY GetUnitAttribute 3 QueueMove
endif
else
AbortMove
ClearQueuedMoves
endif
endif
<-target CONST_COORDX GetUnitAttribute CurrentX eq <-target CONST_COORDY GetUnitAttribute CurrentY eq and GetQueuedMoveCount eq0 and if
3 ->mode
endif
endif

<-mode 3 eq if
<-target CONST_ISDESTROYED GetUnitAttribute 1 eq if
@FindTarget
<-child 3 Destroy
"CRPLCORE" <-target CONST_COORDX GetUnitAttribute <-target CONST_COORDY GetUnitAttribute CreateUnit ->child
<-child "marker.crpl" AddScriptToUnit
<-child "marker.crpl" "parent" SetScriptVar
endif
<-target <-parent eq if
4 ->mode
else
Self CONST_AMMO GetUnitAttribute 0.01 add SetUnitAttribute
Self CONST_AMMO GetUnitAttribute 10 eq if
4 ->mode
<-parent ->target
endif
endif
endif

<-mode 4 eq if
0 ->correctAngle
@Turn
<-correctAngle if
GetQueuedMoveCount neq0 if
<-target CONST_COORDX GetUnitAttribute <-target CONST_COORDY GetUnitAttribute 3 QueueMove
endif
else
AbortMove
ClearQueuedMoves
endif
<-target CONST_COORDX GetUnitAttribute CurrentX eq <-target CONST_COORDY GetUnitAttribute CurrentY eq and GetQueuedMoveCount eq0 and if
0 ->mode
endif
endif

:FindTarget
999 ->range
<-parent ->target
0 0 999 GetEnemyUnitsInRange
0 do
->unit
<-unit GetUnitType "EMITTER" eq if
<-unit CONST_COORDX GetUnitAttribute <-parentCONST_COORDX sub 2 pow
<-unit CONST_COORDY GetUnitAttribute <-parentCONST_COORDY sub 2 pow
add sqrt ->test
<-test <-range lt if
<-unit CONST_COORDX GetUnitAttribute <-unit CONST_COORDY GetUnitAttribute 1 GetEnemyUnitsInRange ->count
<-count 1 eq if
pop
<-test ->range
<-unit ->target
else
<-count 0 do
pop
loop
endif
endif
endif
loop

:Turn
#This is from the farbor harvesters, edited a bit.
CurrentCoords ->y ->x
<-target CONST_COORDX GetUnitAttribute sub(<-x) ->dx
<-y sub(<-target CONST_COORDY GetUnitAttribute) ->dy
atan2(<-dy <-dx) ->targetAngle
GetImageRotation(Self "Main") ->currentAngle
ShortestAngle(<-currentAngle <-targetAngle) ->shortestAngle
if (abs(<-shortestAngle) 0.04 lt )
SetImageRotation(Self "Main" <-targetAngle)
1 ->correctAngle
else
if (<-shortestAngle lt(0))
<-currentAngle sub(<-rotateSpeed) ->currentAngle
else
<-currentAngle add(<-rotateSpeed) ->currentAngle
endif
SetImageRotation(Self "Main" <-currentAngle)
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.

eduran

#6
Here is a list of mistakes I found:
line issues
--------------------------------------------
32 GetCoresWithVar returns the number of cores found and their UIDs -> you need a 'pop' between GetCoresWithVar and CONST_AMMO
38 Timer0 does nothing
50/60/87 missing 'Self' between "parent" and SetScriptVar
68/104 use eq0 instead of neq0
76/111 GetQueuedMoveCount is never 0 because you are queueing a new move right before that statement; either remove the check or stop queuing moves when you reach the target
92 missing one 'Self CONST_AMMO' for SetUnitAttribute
123/124 missing GetUnitAttribute after '<-parent CONST_COORDX/Y'; also, CRPL has a 'Distance' command that you could use here
149ff use <-rotateSpeed instead of 0.04 and initialize rotateSpeed; alternatively replace all instances of '<-rotateSpeed' with 0.04

I doubt that this list is complete, but it should give you something to start with.

And some suggestions:

1) Adding a few comments can make reading code of that length a lot easier, especially for someone (like me ;D) who did not write it. Just add a line here and there about what the following code is supposed to do.

2) At the start of the blocks for mode 2 and 3 you check if the target is still alive. If it's dead, you repeat the steps of mode 1. Instead of copy/pasting the code, you could just jump back to that state. In the case of mode 3, doing that is actually required, otherwise you only select a new target, but never move there.

3) I get the impression that you wrote the entire script in one go and then started testing it. In my experience it is better to go step by step. Implement your target selection and test it. If it works, implement the movement to the target and fiddle around with that until it works. Only then add the next step. Otherwise the amount of code you have to check for errors can be overwhelming.

4) Use the trace log. Get started by adding 'ShowTraceLog' to your 'once' block. That will give you access to a number of helpful warning messages. Once these are fixed you can add individual 'Trace' commands. For example, adding something like 'Trace2("mode:" <-mode)' at the end of the script allows you to track where the script is getting stuck.