GetCreeperInRange CRPL call?

Started by CobraKill, August 09, 2013, 12:09:22 AM

Previous topic - Next topic

CobraKill

Is there a GetCreeperInRange command in CRPL, and I'm just missing it? I know there is the IsCreeperInRange call, but I'm not sure it can return the X and Y coordinates.

Basically, I'm trying to edit the PatrolGun script to create a beam weapon to destroy the closest creeper and digitals in range. I need to edit the targeting so it can return the creeper/digitals X and Y closesr to the core and destroy them. Is it even possible to do this as of now? If it is, I must be just missing it.

Code Attached.

# Beam Weapon.crpl
# Created on: 2/4/2013 3:31:03 PM
# ------------------------------------------

$range:9

<-firing if
"Firing" trace
GetTimer0 eq0 if
@Kaboom
else
@Fire
endif
else
GetTimer0 eq0 if
@GetClosestUnit
<-closestUnit neq0 if
"Closest Unit " <-closestUnit trace2
self "beam" "Custom1" SetImage
self "beam" 0 255 255 255 SetImageColor
self "beam" 1.5 SetImageScaleY
@Fire
endif
# For efficiency, wait a second before scanning for new units.
# We also will wait if firing.  This will make the beam track the unit
# before everything explodes.
20 SetTimer0
endif
endif

:Kaboom
<-closestUnit 2 Destroy
self 1 Destroy

:Fire
TRUE ->firing

<-closestUnit CONST_ISDESTROYED GetUnitAttribute if
FALSE ->firing
SetImage(self "beam" "NONE")
SetImage(self "damage" "NONE")
return
endif

<-closestUnit CONST_PIXELCOORDX GetUnitAttribute ->targetX
<-closestUnit CONST_PIXELCOORDY GetUnitAttribute ->targetY

self CONST_PIXELCOORDX GetUnitAttribute ->selfX
self CONST_PIXELCOORDY GetUnitAttribute ->selfY

<-targetX <-selfX sub ->deltaX
<-targetY <-selfY sub ->deltaY
<-deltaY <-deltaX atan2 ->angle
<-selfX <-selfY <-targetX <-targetY Distance ->distance
<-distance 24 div ->beamScaleX

<-deltaX 2 div ->beamX
<-deltaY 2 div ->beamY

SetImagePosition(self "beam" <-beamX <-beamY -0.02)
SetImageScaleX(self "beam" <-beamScaleX)
SetImageRotation(self "beam" <-angle)

<-img 4 lt if 4 ->img endif
<-img 7 gt if 4 ->img endif

SetImage(self "damage" concat("Custom" <-img) )
SetImagePosition(self "damage" <-deltaX <-deltaY -0.1)

<-img 1 add ->img


# Func :GetClosestUnit
# Finds the nearest unit in "range".
# Returns the unit uid of the closest unit, or 0 if no unit is in range
# "closestUnit" contains the return value on return
# "unitCount" contains the number of units in range
# "closestDistance" containts the distance to the closest unit
:GetClosestUnit
99999999 ->closestDistance
0 ->closestUnit
#All 'player' units are returned, including power zones and artifacts.  If you don't want them to be targeted, they must be excluded...
GetUnitsInRange(CurrentCoords <-range)  ->unitCount
do (<-unitCount 0)
->unit
CurrentCoords <-unit CONST_COORDX GetUnitAttribute <-unit CONST_COORDY GetUnitAttribute Distance ->d
if (<-d lt(<-closestDistance))
GetUnitType(<-unit) ->ut
if ( not(<-ut eq ("POWERZONE") or (<-ut eq ("TECHARTIFACT")) or (<-ut eq("MESSAGEARTIFACT")) or (<-ut eq("SHIELDKEY"))) )
<-d ->closestDistance
<-unit ->closestUnit
endif
endif
loop
<-closestUnit
# EndFunc


I'll add the ammo consumption later because it's pretty simple.
Never trust a computer that doesn't fit through your nearest window.

knucracker

#1
There isn't a 'GetClosestCreeeper' call currently.  You can of course write your own using GetCreeper and iterating over cells, but that won't be super efficient and could run into performance issues if many things are doing it over a relatively large range.

The function that you describe isn't super simple.  There are a range of possible options.  The simplest would be GetNearestCreeper(X Y RANGE).  That can be done handily and easily understood.  What if you want it to find AC instead?  What if you want it to find the nearest of Creeper or Digitalis?  What if you want it to preference Creeper on the same level like a Pulse Cannon does?  Is terrain supposed to block LOS?  Complexity explosion... welcome to the tortured world of software API design.

So there can be different functions for each thing, that is one answer (lets ignore same-level biasing for now).
GetNearestCreeper(X,Y,R,LOS), GetNearestAntiCreeper(X,Y,R,LOS), GetNearestDigitalis(X,Y,R,LOS)

That is clean and easy to understand, but not as efficient or easy to use in the scenario described in your question. To find the nearest of Creeper or Digitalis, you have to make two calls then use the one that returns the closest result.  So you have to use a Distance function on each resulting coordinate pair.  Worse, you are scanning an area twice since you have to call two functions.

The other way to solve this problem is with a MOAF (Mother Of All Functions).  GetNearestGroundEnemy(X,Y,R,LOS,C,AC,D).  Here X and Y are the starting coordinates, R is the range (inclusive), LOS is a bool for whether terrain blocks line of sight, C,AC,D are bools for whether to look at Creeper, AntiCreeper, Digitalis.

This MOAF can be used in scenarios like you describe, or for things that blast only AC, only C, or even both.  

Of course, then what about finding the densest Creeper rather than the nearest?  :)

Anyway, I can probably add in the MOAF version.  That's basically what I use internally, so it may not be that hard to expose to CRPL.

CobraKill

Well I didn't realize I opened a can of worms. This would open up even more options for CRPL weaponry though.
Never trust a computer that doesn't fit through your nearest window.

knucracker

I hear ya....
In Meso and Farbor, I added in so much more stuff to CRPL that it became possible to script units.  That is what harvesters are, or the Golden Golems.  The take-off, the shadow, the motion, the mist, the blue ore packets... all of that in the Farbor mission is in CRPL.

So having a 3d party weapon on a map that you can hook up to, power, and it shoots at Creeper... the only thing stopping that is the addition of this function.  I just described Meso, except there I used AC, shields, and roving cores that explode.  Btw, those golems in Meso use a 'GetDeepestCreeperCell' call that returns the densest creeper cell on the entire map...

So can or worms or not, the new API is a consistent thing to add in.

rytan451

Is there any update on this? As far as I can see from the reference, this CRPL method isn't available.

(Sorry if it's considered more appropriate to create a new topic rather than wake an old one)

Builder17

Quote from: rytan451 on December 21, 2019, 08:57:51 AM
Is there any update on this? As far as I can see from the reference, this CRPL method isn't available.

(Sorry if it's considered more appropriate to create a new topic rather than wake an old one)

You can use do loop to check square area for total creeper, please explain your script idea and I can help you further

cornucanis

Quote from: rytan451 on December 21, 2019, 08:57:51 AM
Is there any update on this? As far as I can see from the reference, this CRPL method isn't available.


Actually, I think knuckracker did end up adding in the command he mentioned in his first post, GetNearestGroundEnemy. I haven't tested this method personally, but it's on the wiki and seems to be what knucracker was describing here. That commmand will return the location of the nearest creeper, digitalis, or anti-creeper.