Knuckle Cracker

Creeper World 3 => The Coder's Corner => Topic started by: ShadowDragon7015 on May 28, 2013, 09:57:53 PM

Title: This isn't working
Post by: ShadowDragon7015 on May 28, 2013, 09:57:53 PM
CurrentCoords -10 AddCreeper
Delay 10
CurrentCoords 10 AddCreeper
Delay 10
SetTerrain
91 185 2
CurrentCoords -10 AddCreeper
Delay 10
CurrentCoords 10 AddCreeper
Delay 10
SetTerrain
88 188 2
CurrentCoords -10 AddCreeper
Delay 10
CurrentCoords 10 AddCreeper
Delay 10
SetTerrain
94 188 2
CurrentCoords -10 AddCreeper
Delay 10
CurrentCoords 10 AddCreeper
Delay 10
SetTerrain
91 191 2
CurrentCoords -10 AddCreeper
Delay 10
CurrentCoords 10 AddCreeper
Delay 10
SetVoid
91 185
CurrentCoords -10 AddCreeper
Delay 10
CurrentCoords 10 AddCreeper
Delay 10
SetVoid
88 188
CurrentCoords -10 AddCreeper
Delay 10
CurrentCoords 10 AddCreeper
Delay 10
SetVoid
94 188
CurrentCoords -10 AddCreeper
Delay 10
CurrentCoords 10 AddCreeper
Delay 10
SetVoid
91 191

I'm having trouble with this making the terrain move up and down all it does now is raise the terrain to level 10 in 3 of the 4 spots
Title: Re: This isn't working
Post by: J on May 29, 2013, 03:51:21 AM
You have to put up the arguments first.
So instead of:
Delay 10
SetTerrain
91 185 2

You'll have to write:
10 Delay
91 185 2 SetTerrain

Hope that helps
Title: Re: This isn't working
Post by: Molay on May 29, 2013, 08:22:05 AM
So, I modified it a bit.
First, I added a function for the repetitive part (the setcreeper part) to make the code a bit clearer.
Second, I used the warp operator. By the structure of your code, it looks like you're more familiar with the non-reverse notations, and the warp operator works very well for that :)

Overall, the code should be much smaller now and much easier to look at.

# ShadowDragon1.crpl
# Created on: 5/29/2013 2:06:17 PM
# Created by: ShadowDragon7015
# ---------------------------------

@spawnCreeper
SetTerrain(91 185 2)
@spawnCreeper
SetTerrain(88 188 2)
@spawnCreeper
SetTerrain(94 188 2)
@spawnCreeper
SetTerrain(91 191 2)
@spawnCreeper
SetVoid(91 185)
@spawnCreeper
SetVoid(88 188)
@spawnCreeper
SetVoid(94 188)
@spawnCreeper
SetVoid(91 191)

:spawnCreeper
CurrentCoords -10 AddCreeper
Delay(10)
CurrentCoords 10 AddCreeper
Delay(10)


It looks pretty cool when you put the creeplecore in the middle of the terraforming, kinda like a little factory of sorts. Neat stuff :)
Title: Re: This isn't working
Post by: ShadowDragon7015 on May 29, 2013, 05:19:43 PM
Thanks Molay it worked perfectly!
Title: Re: This isn't working
Post by: ShadowDragon7015 on June 16, 2013, 12:26:47 AM
i need to make this smaller and make it possible to change the variables multiple times in one CRPL core please help
$X:154
$Y:253
$RANGE:3
$UNITTYPE:"RELAY"
$DESTROYTYPE:2

@KillUnitsInRange(<-X <-Y <-RANGE <-UNITTYPE <-DESTROYTYPE)

# Usage @KillUnitsInRange(x y range "UNITTYPE" destroyType)
:KillUnitsInRange
   ->destroyType
   ->unitType
   ->range
   ->y
   ->x
   do (GetUnitsInRange(<-x <-y <-range) 0)
      ->unitUID
      if (GetUnitType(<-unitUID) eq(<-unitType))
         Destroy(<-unitUID <-destroyType)
      endif
   loop
Title: Re: This isn't working
Post by: knucracker on June 16, 2013, 09:23:21 AM
You can add the same script to a single core more than once.  So if you just need to target two ranges on the map, or two unit types in the same location, you can just add the Killer.crpl script to a core twice then configure it differently for each one (without changing any of the code).

Now if you are wanting to kill different unit types (say 4 different things) in the same range, then it would be more efficient to modify the code to take a list of unit types to destroy.  This could be done by adding  $UNITTYPE2, $UNITTYPE3, $UNITTYPE4, etc. variables and checking for any of them in the 'if' that's inside GetUnitsInRange.  Or you could ask me to add a string 'split' function to CRPL so you could put all of the items in one variable and separate them with spaces.  Or you could ask me to add array support to CRPL and the editor, so you could add them as an array of data.

Or, if you just want to get it done, copy and paste the 'if' clause inside GetUnitsInRange and type in each unit type that you want to kill.

Title: Re: This isn't working
Post by: ShadowDragon7015 on June 16, 2013, 12:30:05 PM
Can you add an array so it takes multiple units and multiple coordinates?
Title: Re: This isn't working
Post by: knucracker on June 16, 2013, 01:48:39 PM
So you want to nuke some number of units (by type) in more than one range?

If that is the case it would better to loop through all units on the map and do the range calculations and type checking in that one loop.  GetUnitsInRange is going to be the expensive call, so you only want to do that once.  Just do it at coords 0,0 with a range of like 9999.  That will get all units on the map.  Then you can check the type of each unit and the range of each unit and destroy as appropriate.

Unfortunately, I'm not going to take the 15 minutes it would take to write that for you since I've got a full plate already.  But you already have examples of all of the requires API's necessary to do this.
Title: Re: This isn't working
Post by: ShadowDragon7015 on June 16, 2013, 01:54:03 PM
i want to kill units that get put on certain spots throughout the map
Title: Re: This isn't working
Post by: knucracker on June 16, 2013, 01:59:07 PM
How many spots and are the spots just single coordinates (no range necessary)?  Are you wanting to kill any player unit, or only units of certain types.  If certain types, how many?
Title: Re: This isn't working
Post by: ShadowDragon7015 on June 16, 2013, 02:19:46 PM
set single spots and i want to kill relays and collectors on those spots
Title: Re: This isn't working
Post by: knucracker on June 16, 2013, 02:31:52 PM
If somebody builds a relay one cell to the right of one of your spots, what should happen?  Note that units take up 3x3 areas.
Title: Re: This isn't working
Post by: ShadowDragon7015 on June 16, 2013, 02:33:33 PM
i want to prevent them from putting them on powerzones.  8)
Title: Re: This isn't working
Post by: knucracker on June 16, 2013, 03:13:37 PM
Ok, so your actual requirement for your map is:
- Prevent the player from building collectors and relays on power zones.

That means you would like to 'destroy' the unit before it is even built, correct?  Else the player would waste time building a relay only to have it blow up.

In the next build I have added a 'GetUnitAt' call that will return a unit at any coordinates you specify.  It will return any unit, even if it is building.  Unfortunately, it only returns one unit.  So stacked units (like a unit on a power zone) means you would get unpredictable results.

The GetUnitsInRange calls only return units that are built.

You need a more fundamental API that returns all units regardless of state, then you need to check to see if any collectors or relays overlap any power zones.  That would work but what a pain.

An IsOverPowerZone call would be nice in this case.  So you'd want something like this to work:

do (GetAllUnitsInRange(0 0 999) 0)
      ->unitUID
      GetUnitType(<-unitUID) ->unitType
      if (<-unitType eq("COLLECTOR) or (<-unitType eq("RELAY")))
         if (IsOverPowerZone(<-unitUID))
            Destroy(<-unitUID 0)
         endif
      endif
loop

Title: Re: This isn't working
Post by: ShadowDragon7015 on June 16, 2013, 09:43:33 PM
If the IsOverPowerZone function existed that would work perfectly, yes.
Title: Re: This isn't working
Post by: ShadowDragon7015 on September 04, 2013, 08:32:12 PM
I'm trying to get this to work. It is supposed to wait for all other enemy units to die before it activates but it automatically activates at the moment can someone please help?

# Can't fight this.crpl
# Created on: 5/29/2013 10:46:25 PM
# ------------------------------------------
if
(GetEnemyUnitsInRange(0 0 9999)) eq 1
QueueMove(RandCoords 3)
SetCreeper (currentcoords 200)
delay(15)
endif
Title: Re: This isn't working
Post by: knucracker on September 04, 2013, 08:37:32 PM
You probably mean:
if ( GetEnemyUnitsInRange(0 0 9999) eq (1) )

You have the parenthesis messed up in your 'if'.

Withour parens it would be:
0 0 9999 GetEnemyUnitsInRange 1 eq if
Title: Re: This isn't working
Post by: ShadowDragon7015 on September 04, 2013, 09:28:33 PM
now it isn't moving.
Title: Re: This isn't working
Post by: knucracker on September 05, 2013, 09:28:23 AM
The condition probably is never true, then.
Put a trace inside the condition. (And a ShowTraceLog at the top of the script).

Aside from that, what you have in the condition doesn't really look 'healthy'.  You are going to call QueueMove twice a second whether your unit is already moving or not.  That will build up an ever growing list of movements.

Inside your outer 'if' that checks for enemy units, you want a nested 'if' that calls GetQueuedMoveCount.  Only of that is 0 do you want to queue a new move.

Lastly, why are you checking for enemy units equal to 1?  I don't know anything about your mission and what counts and enemy or not... but just trace the result of GetEnemyUnitsInRange and see what the number is.  It is probably either 0 or more than 1...
Title: Re: This isn't working
Post by: J on September 05, 2013, 10:54:41 AM
if he checks if there's only one enemy left, that means that is the core that is running that script.
if (GetEnemyUnitsInRange(0 0 9999) eq (1))
if (GetQueuedMoveCount eq (0))
 QueueMove(RandCoords 3)
 SetCreeper (currentcoords 200)
endif
endif
if you want to emit creeper twice a second instead of when it queues a new movement, use timing functions outside the GetQueuedMoveCount block of code
if (GetEnemyUnitsInRange(0 0 9999) eq (1))
if (GetQueuedMoveCount eq (0))
 QueueMove(RandCoords 3)
endif
GetTimer0 0 lte if
 SetCreeper (currentcoords 200)
 15 SetTimer0
endif
endif