Custom Sleeper Scripts/Textures PT.1

Started by Nicant, October 27, 2015, 06:19:32 PM

Previous topic - Next topic

Nicant

Here is my codes for the custom units i made! Make sure you credit all of the code to Telanir! (The codes are just modified versions of the original creep units :P ) Also, you can use any of the codes in your own map! Just make sure you put the images in the right slot in the custom images tab.  ;)
Edit: changed the code boxes into teletype boxes. Hope it made reading easier!  :)
Edit2: got ride of smilies on the post cause it was interfering with the code  ;)
Edit3: Sorry, I forgot to tell you where the images go. :P
Get my Sleeper template if you want to use the custom units! (You can get it here!) I am no longer updating this or part 2 of the thread.
IMPORTANT! Make sure you put the textures in right!!! Below is where the textures go.

Creep Sniper platform as Custom39. (The barrel should go on itself if not, put the barrel on Custom 26!)
Creep Reactor as Custom40.
Creep BomberBase as Custom42. (The actual bomber itself was in the map already so it should work!)
Creep SprayerBase as Custom48
Creep Sprayer Barrel as Custom49

How to put a Creep Sniper in your map!
Spoiler
Step 1: Create a CRPL file by going to your scripts and creating a file named exactly CSniper (You can get to your scripts by pressing the edit map button and going to units.)
Step 2: Copy and paste the Creep Sniper code into your CSniper file.
Step 3: Put the Creep Sniper platform image in Custom39 (The Sniper barrel should go on itself, if not put the barrel on Custom 26)
The sniper should now work however, the sleeper node cannot build the snipers yet. So the next steps are how to make the sleeper node build the snipers.
Step 4: Copy this line of code @RegisterCreep("CSniper.crpl" "SNIPER" 15 30 @UNIT_CONSUMER) Then,put it in line 145 in the "SleeperBase"  Script. The sleeper node should now be able to build the sniper.
Now it should be complete, if something does not work tell me and i will try to help you!
[close]

How to put in a Creep Reactor!
Spoiler
Step 1: Create a CRPL file by going to your scripts and creating a file named exactly CReactor (You can get to your scripts by pressing the edit map button and going to units.)
Step 2: Copy and paste the Creep Reactor code into your CReactor file.
Step 3: Put the Creep Reactor image  in Custom40.
The reactors should now work however, the sleeper node cannot build the reactors yet. So the next steps are how to make the sleeper node build the reactors.
Step 4: Copy this line of code @RegisterCreep("CReactor.crpl" "REACTOR" 5 100 @UNIT_PRODUCER) Then,put it in line 146 in the "SleeperBase"  Script. The sleeper node should now be able to build the Reactor.
Now it should be complete, if something does not work tell me and i will try to help you!
[close]

How to put in a Creep Bomber!
Spoiler
Step 1: Create a CRPL file by going to your scripts and creating a file named exactly CBomberBase (You can get to your scripts by pressing the edit map button and going to units.)
Step 2: Copy and paste the Creep BomberBase code into your CBomberBase file.
Step 3: Put the Creep BomberBase image in Custom42.
The BomberBase will do nothing without another script to make the bomber fly and do stuff.
Step 4: Create another CRPL file by going to your scripts and creating a file named exactly CBomber (You can get to your scripts by pressing the edit map button and going to units.)
Step 5: Copy and paste the Creep Bomber code into your CBomber file.
Step 6: The Creep Bomber texture is already in the map you are editing so you don't do anything with this step.
Step 7: The Bomber and Bomber Base should now work, however we need one more script for the bombs that the bomber drops.
Step 8: Create one last CRPL file by going to your scripts and creating a file named exactly CBomb (You can get to your scripts by pressing the edit map button and going to units.)
Step 9: Copy and paste the Creep Bomb code into your CBomb file.
Step 10: Again the texture for the bomb is already in the map.
Step 11: Everything should work now however, the sleeper node cannot build the Bomber yet. So the next step(s) show you how.
Step 12: Copy this line of code @RegisterCreep("CBomberBase.crpl" "BOMBERBASE" 10 300 @UNIT_PRODUCER) Then,put it in line 147 in the "SleeperBase"  Script. The sleeper node should now be able to build the Bomber.
Now it should be complete, if something does not work tell me and i will try to help you!
[close]
More tutorials coming soon!

Creep Sniper Script:
Spoiler
# CSniper.crpl
# Created on: 10/24/2015 12:22:23 PM
# ------------------------------------------

# VERSION 1.1

# == CUSTOM VARS ==

$reach:25
$cooldown:50
$min_creep:1
$rot_speed:0.1
$damage:3.00

# == DEFAULT VARS ==
# Health is simulated differently because there is no direct
# way to know cannon damage and Digitalis is ONLY damaged by
# player actions.
# A side effect is that every unit will have to support Digitalis.

# Health reduces sharply when unit digitalis is damaged.
$health:5.0
# If digitalis under unit is less than min, damage health.
$minDigitalis:1.0
# Digitalis will restore to this value.
$maxDigitalis:1.4

# CONSTANTS (only modify here, or during initialization)
$DEFAULT_IMAGE:"Custom39"
$BUILD_SOUND:"Misc7"
$CREEPER_FOR_BUILD:300.0
$CREEP_TYPE:"SNIPER"
# Every unit has a forcefield unless range is 0 or below.
# Negative PUSH values will induce a PULL on creeper to "suck it in".
$CREEP_FORCEFIELD_CPUSH:-35000
$CREEP_FORCEFIELD_ACPUSH:1000
$CREEP_FORCEFIELD_RANGE:4

# Creep will activate sleep mode
$SLEEP_DISTANCE:50
$SLEEP_TIME:60
# Enabling hard sleep will allow the AI to activate
# SleepAI when the unit is far away from the action
# or can't do anything for a bit. Otherwise, it is up
# to you to make the unit optimized with @IsSleeping
$SUPPORTS_HARDSLEEP:1
# When a unit is in travel mode it will run an alternate
# AI that is called TravelAI where you can perform tasks
# specific to flying mode. As soon as a unit lands on their
# target position they resume standard AI. If ignoring flight
# is enabled, normal AI will continue to run even during flight.
$IGNORES_FLIGHT:0
$FLIGHT_SPEED:1.0

# RUNTIME (do not modify)
$BUILT_ON_SPAWN:1
$IS_BUILT:0
$S_BASE:-1

# THIS SCRIPT DOES NOT SUPPORT RUNNING WHILE PAUSED.
# However, due to internal bugs occasionally CW3 will still give them frame time
# even though nowhere is it explicitly stated they are allowed to run while paused.
IsPaused if
   1 SuspendMove
   return
endif
# == END DEFAULT ==

once
   self "CRadiusDisplay.crpl" AddScriptToUnit
   self "CRadiusDisplay.crpl" "SCRIPT_NAME" "CSniper.crpl" SetScriptVar
   self "CRadiusDisplay.crpl" "RADIUS_VARNAME" "reach" SetScriptVar
   
   self "main" <-DEFAULT_IMAGE SetImage
   self "barrel" "Custom26" SetImage
   self "barrel" -0.01 SetImagePositionZ
   @RegisterImage("main")
   @RegisterImage("barrel")
   
   # CREATE ABOVE THEN REGISTER CUSTOM (not "main") IMAGES HERE
   # @RegisterImage("barrel")
   
   # Flash without sound
   self CONST_DESTROYMODE 3 SetUnitAttribute
   
   # Set size here
   self CONST_CELLHEIGHT 3 SetUnitAttribute
   self CONST_CELLWIDTH 3 SetUnitAttribute
   
   # Set who can target this unit
   self CONST_NULLIFIERDAMAGES true SetUnitAttribute
   self CONST_BEAMTARGET false SetUnitAttribute
   self CONST_SNIPERTARGET false SetUnitAttribute
   self CONST_SNIPERIGNORELOS false SetUnitAttribute
   
   self CONST_CREATEPZ false SetUnitAttribute
   
   # REQUIRED TO FUNCTION, DO NOT TOUCH
   self CONST_SUPPORTSDIGITALIS true SetUnitAttribute
   self CONST_COUNTSFORVICTORY false SetUnitAttribute
   self CONST_MAXHEALTH <-health SetUnitAttribute
   self CONST_HEALTH <-health SetUnitAttribute
   self CONST_HEALRATE 0.001 SetUnitAttribute
   @CreeperInitialize
   # ==================================
   
   "NULLIFIER" 10 @AddUnitTypePriority
   "SNIPER" 4 @AddUnitTypePriority
   "SPRAYER" 2 @AddUnitTypePriority
   "MORTAR" 2 @AddUnitTypePriority
   "PULSECANNON" 3 @AddUnitTypePriority
endonce

@StandardCreep

@IsBuilt if
   @ConsistentAI
   if(or(not(@IsFlying) <-IGNORES_FLIGHT))
      if (<-SUPPORTS_HARDSLEEP)
         if(@IsSleeping)
            @SleepAI
         else
            @AI
         endif
      else
         @AI
      endif
   else
      @FlightAI
   endif
else
   @Build
endif

:AI
   @HandleTargetExist
   false ->active
   
   GetTimer0 eq0 if
      true ->firing
      CurrentCoords <-reach @GetClosestUnitToCoords ->target
      false ->firing
      <-target -1 neq if
         true ->active
         @RotateAI
         <-isOnTarget if
            CurrentCoords GetCreeper <-min_creep gt and(<-target CONST_ISLANDED GetUnitAttribute) if
               <-target @UnitCoords @Fire
            else
               CurrentCoords GetCreeper 0.6 lte if
                  @RunToCreeper
               endif
            endif
            <-cooldown SetTimer0
         endif
      else
         CurrentCoords <-reach true false false true GetNearestGroundEnemy ->enemyY ->enemyX
         <-enemyY -1 neq if
            true ->active
            <-enemyX <-enemyY @RotateAIToCoords
            <-isOnTarget if
               CurrentCoords GetCreeper <-min_creep gt if
                  <-enemyX <-enemyY @Fire
               else
                  CurrentCoords GetCreeper 0.6 lte if
                     @RunToCreeper
                  endif
               endif
               <-cooldown SetTimer0
            endif
         else
            @FindApproachLocation
            @IsFlying not if
               900 @Sleep
            endif
         endif
      endif
   endif
   
   @HasTarget not and(<-active not and(GetTimer0 eq0)) and(not(@IsSleeping)) if
      45 @Sleep
   endif
   
   #custom code here

:SleepAI
   <-check add(1) ->check
   <-check 150 gte if
      0 2 RandInt eq0 if
         @FindApproachLocation
      endif
      0 ->check
   endif

:ConsistentAI
   <-cold_feet sub(1) ->cold_feet
   @AnimateRecoil
   
:FlightAI
   #custom code here
   
:built
   #custom code here

:death
   #custom code here
   "Explosion1" PlaySound

:RunToCreeper
   <-cold_feet 0 lte if
      450 ->cold_feet
      CurrentCoords 200 false true false false GetNearestGroundEnemy ->creepY ->creepX
      <-creepY -1 neq if
         CurrentCoords <-creepX <-creepY -7 @GetIntermediatePosition ->ix ->iy
      endif
      <-ix <-iy GetCreeper 0 gt and(<-ix <-iy 1 @TerrainAccessible and(not(<-ix <-iy 1 @AreaOccupied))) if
         0 ->C_SLEEP
         <-ix <-iy @SetFlightLandingTarget
         @ExecuteLiftoff
      endif
   endif
   
:FindApproachLocation
   900 ->cold_feet
   CurrentCoords 100 false false false true GetNearestGroundEnemy ->enemyY ->enemyX
   <-enemyY -1 neq if
      CurrentCoords <-enemyX <-enemyY <-reach sub(3) @GetIntermediatePosition ->ix ->iy
   else
      -5000 ->ix
      -5000 ->iy
   endif
   CurrentCoords 100 @GetClosestUnitToCoords ->temp
   CurrentCoords @UnitCoords(<-temp) <-reach sub(3) @GetIntermediatePosition ->ixu ->iyu
   CurrentCoords <-ixu <-iyu Distance CurrentCoords <-ix <-iy Distance lt if
      <-ixu ->ix
      <-iyu ->iy
   endif
   
   -?ix and(-?iy) and(<-ix neq(-1)) and(<-iy neq(-1)) if
      <-ix <-iy GetCreeper 0.1 gt and(<-ix <-iy 1 @TerrainAccessible and(not(<-ix <-iy 1 @AreaOccupied))) if
         0 ->C_SLEEP
         <-ix <-iy @SetFlightLandingTarget
         @ExecuteLiftoff
      endif
   endif
   
:HasTarget
   <-target -1 neq
   
:HandleTargetExist
   -?target not if
      -1 ->target
   endif
   <-target -1 neq if
      <-target CONST_ISDESTROYED GetUnitAttribute if
         -1 ->target
      endif
   endif
   
:AnimateRecoil
   <-barrelOffset add(<-recoil) ->barrelOffset
   <-recoil 1.5 lt if
      <-recoil 1 add ->recoil
   endif
   <-barrelOffset -5 lt if
      -5 ->barrelOffset
   endif
   <-barrelOffset 0 gt if
      0 ->barrelOffset
   endif
   self "barrel" GetImageRotation ->barrot
   <-barrot cos <-barrelOffset mul ->barrelX
   <-barrot sin <-barrelOffset mul ->barrelY
   self "barrel" GetImagePositionZ ->barrelZ
   self "barrel" <-barrelX <-barrelY <-barrelZ SetImagePosition
   
:Fire
   ->fy
   ->fx
   "Weapons24" PlaySound
   -2.5 ->recoil
   
   "CRPLCore" CurrentCoords CreateUnit ->cs
   <-cs "CShot.crpl" AddScriptToUnit
   <-cs "CShot.crpl" "targetX" <-fx SetScriptVar
   <-cs "CShot.crpl" "targetY" <-fy SetScriptVar
   <-cs "CShot.crpl" "payload" CurrentCoords GetCreeper asfloat SetScriptVar
   <-cs "CShot.crpl" "speed" 7  SetScriptVar
   <-cs "CShot.crpl" "damage" <-damage SetScriptVar
   <-cs "main" "Custom36" SetImage
   <-cs "main" 0.25 0.25 SetImageScale
   CurrentCoords 0 SetCreeper

:RotateAIToCoords
   ->ratcY
   ->ratcX
   self "barrel" GetImageRotation ->c_brot
   CurrentCoords <-ratcX <-ratcY <-c_brot <-rot_speed @RotateToAngle ->c_brot ->isOnTarget
   self "barrel" <-c_brot SetImageRotation

:RotateAI
   self "barrel" GetImageRotation ->c_brot
   CurrentCoords <-target @UnitCoords <-c_brot <-rot_speed @RotateToAngle ->c_brot ->isOnTarget
   self "barrel" <-c_brot SetImageRotation
   
# Function :RotateToAngle
# Takes an initial position and a target position,
# calculates an angle, and then returns an angle
# restricted by the specified speed and angle.
# This function can allow for slow rotations.
# It will also return a boolean value which is
# true if the angle directly faces the target.
# Notation: x y x2 y2 f1 f2 - b1 f1
# eg. CurrentCoords <-targetUnit @UnitCoords <-angle 0.03 @RotateToAngle ->newAngle ->isOnTarget
:RotateToAngle
   asfloat ->rta_maxRot
   asfloat ->rta_curAngle
   asfloat ->rta_targetY
   asfloat ->rta_targetX
   asfloat ->rta_curY
   asfloat ->rta_curX

   <-rta_targetX <-rta_curX sub ->rta_deltaX
   #(vertical 0 is TOP-left)
   #cell-y is flipped so we instead subtract target-y from current-y
   <-rta_curY <-rta_targetY sub ->rta_deltaY
   <-rta_deltaY <-rta_deltaX atan2 ->rta_desiredAngle

   <-rta_curAngle <-rta_desiredAngle ShortestAngle ->rta_rot

   <-rta_rot <-rta_maxRot gt if
      <-rta_maxRot ->rta_rot
   else
      <-rta_rot <-rta_maxRot neg lt if
         <-rta_maxRot neg ->rta_rot
      endif
   endif

   <-rta_rot abs 0.0001 lt if
      1 ->rta_onTarget
   else
      0 ->rta_onTarget
   endif

   <-rta_curAngle <-rta_rot add ->rta_rot

   <-rta_onTarget
   <-rta_rot
   
# ===============================
# ===== STANDARD CREEP CODE =====
# ===============================

# Bare minimum required code to run each tick.
# Ensures that player can damage sleeping Creeps.
:StandardCreep
   if(not(@IsFlying))
      @CreepSleep
      CurrentCoords GetCreeper 0 lt if
         self 0.05 Damage
      endif
      CurrentCoords GetDigitalis <-minDigitalis lt if
         self 0.30 Damage
      endif
      @IsBuilt if
         @Repair
      endif
   endif
   @AnimateFlight


:RandomFixCoord
   while not(@IsPointOnMap(<-RF_X <-RF_Y)) repeat
      CurrentCoords 10 RandCoordsInRange ->RF_Y ->RF_X
   endwhile
   <-RF_Y
   <-RF_X
   
# Function :IsPointOnMap
# Takes a set of cell-coordinates and returns true
# if the coordinates are on the map.
# Notation: x y - b1
# eg. -1 -1 @IsPointOnMap ->onMap #(will return false)
:IsPointOnMap
   ->pom_pointY
   ->pom_pointX
   1 ->pom_onMap
   <-pom_pointY MapHeight gt if
      0 ->pom_onMap
   endif
   <-pom_pointY 0 lt if
      0 ->pom_onMap
   endif
   <-pom_pointX MapWidth gt if
      0 ->pom_onMap
   endif
   <-pom_pointX 0 lt if
      0 ->pom_onMap
   endif
   <-pom_onMap
   
:AnimateFlight
   -?C_FLIGHT if
      self "main" 1 GetImageScaleX ->C_FX
      <-C_FLIGHT if
         # Liftoff
         <-C_FX 1.3 lt if
            <-C_FX 0.02 add ->C_FSN
            GetListCount(<-C_IMAGES) 0 do
               self GetListElement(<-C_IMAGES I) <-C_FSN <-C_FSN SetImageScale
            loop
         else
            GetQueuedMoveCount eq0 if
               <-C_FLIGHT_MOVE if
                  false ->C_FLIGHT_MOVE
                  @ExecuteLanding
               else
                  self CONST_BEAMTARGET true SetUnitAttribute
                  true ->C_FLIGHT_MOVE
                  if(not(@IsPointOnMap(<-C_FLIGHT_X <-C_FLIGHT_Y)))
                     @RandomFixCoord ->C_FLIGHT_X ->C_FLIGHT_Y
                  else
                     <-C_FLIGHT_X <-C_FLIGHT_Y <-FLIGHT_SPEED QueueMove
                  endif
                  true ->C_FLYING
               endif
            endif
         endif
      else
         # Landing
         <-C_FX 1 gt if
            <-C_FX 0.02 sub ->C_FSN
            GetListCount(<-C_IMAGES) 0 do
               self GetListElement(<-C_IMAGES I) <-C_FSN <-C_FSN SetImageScale
            loop
         else
            11 CurrentPixelCoords 0.01 1 1 0.03 CreateEffect
            "UnitLand" PlaySound
            --C_FLIGHT
            self CONST_BEAMTARGET false SetUnitAttribute
            <-CREEP_FORCEFIELD_RANGE <-CREEP_FORCEFIELD_CPUSH <-CREEP_FORCEFIELD_ACPUSH 0 true EnableTowerField
            CurrentCoords GetDigitalisGrowth neq0 ->C_DIGITALIS_PRESENT
            CurrentCoords true SetDigitalisGrowth
            CurrentCoords 1.0 SetDigitalis
         endif
      endif
   endif

:SetFlightLandingTarget
   -?C_FLIGHT_X and(-?C_FLIGHT_Y) if
      <-C_FLIGHT_X <-C_FLIGHT_Y GetUnitAttribute(self CONST_CELLWIDTH) sub(1) div(2) FALSE @AddOccupy
   endif
   ->C_FLIGHT_Y
   ->C_FLIGHT_X
   
   <-C_FLIGHT_X <-C_FLIGHT_Y GetUnitAttribute(self CONST_CELLWIDTH) sub(1) div(2) TRUE @AddOccupy
   -?C_FLIGHT and(<-C_FLYING) if
      AbortMove
      <-C_FLIGHT_X <-C_FLIGHT_Y <-FLIGHT_SPEED QueueMove
   endif

# Function :AddOccupy
# Returns whether or not a certain area is occupied by one or
# more other units. Radius is measured in cells.
# Notation: x y f1 b1 -
# eg. CurrentCoords 3 false @AddOccupy #this would allow another unit to land
:AddOccupy
   ->OC_ADD
   ->OC_RAD
   ->OC_Y
   ->OC_X
   
   <-OC_RAD mul(2) add(1) ->OC_LENGTH
   <-OC_RAD ->OC_MID
   
   <-OC_LENGTH 0 do
      <-OC_LENGTH 0 do
         <-OC_Y I add <-OC_MID sub ->OC_AOY
         <-OC_X J add <-OC_MID sub ->OC_AOX
         <-OC_AOX <-OC_AOY GetCellOccupiedCount ->OC_COUNT
         <-OC_ADD if
            <-OC_AOX <-OC_AOY <-OC_COUNT add(1) SetCellOccupiedCount
         else
            <-OC_AOX <-OC_AOY <-OC_COUNT sub(1) SetCellOccupiedCount
         endif
      loop
   loop
   
:ExecuteLiftoff
   <-C_DIGITALIS_PRESENT not if
      CurrentCoords 0 SetDigitalis
      CurrentCoords false SetDigitalisGrowth
      true ->C_DIGITALIS_PRESENT
   endif
   self CONST_TAKEMAPSPACE false SetUnitAttribute
   "UnitTakeOff" PlaySound
   true ->C_FLIGHT
   false ->C_FLYING
   DisableTowerField
   
   # Beams deal significantly less damage, therefore, lower health to
   # within acceptable parameters.
   self CONST_HEALTH dup2 GetUnitAttribute div(1.5) SetUnitAttribute
   self CONST_MAXHEALTH dup2 GetUnitAttribute div(1.5) SetUnitAttribute
   
   GetListCount(<-C_IMAGES) 0 do
      GetListElement(<-C_IMAGES I) ->EX_IM
      self <-EX_IM GetImagePositionZ ->EX_ZPOS
      self <-EX_IM <-EX_ZPOS sub(0.1) SetImagePositionZ
   loop

:ExecuteLanding
   self CONST_TAKEMAPSPACE true SetUnitAttribute
   false ->IS_SLEEPING
   false ->C_FLIGHT
   false ->C_FLYING
   
   # Restore health back to normal values.
   self CONST_MAXHEALTH dup2 GetUnitAttribute mul(1.5) SetUnitAttribute
   self CONST_HEALTH dup2 GetUnitAttribute mul(1.5) SetUnitAttribute
   
   GetListCount(<-C_IMAGES) 0 do
      GetListElement(<-C_IMAGES I) ->EX_IM
      self <-EX_IM GetImagePositionZ ->EX_ZPOS
      self <-EX_IM <-EX_ZPOS add(0.1) SetImagePositionZ
   loop

:IsFlying
   -?C_FLIGHT

:Build
   CurrentCoords GetCreeper ->C_CRP
   <-CREEPER_FOR_BUILD 0 lte if
      @FinishBuild
   else
      <-C_CRP 0 gt if
         self CONST_MAXAMMOAC GetUnitAttribute self CONST_AMMOAC GetUnitAttribute sub ->C_CRPN
         <-C_CRP <-C_CRPN gt if
            <-C_CRP <-C_CRPN sub ->C_LEFT
            CurrentCoords <-C_LEFT SetCreeper
            @FinishBuild
         else
            self CONST_AMMOAC dup2 GetUnitAttribute <-C_CRP add SetUnitAttribute
            CurrentCoords 0 SetCreeper
         endif
      endif
   endif

:FinishBuild
   GetListCount(<-C_IMAGES) 0 do
      GetListElement(<-C_IMAGES I) 255 @SetImageAlpha
   loop
   
   self CONST_AMMO 0 SetUnitAttribute
   self CONST_MAXAMMOAC 0 SetUnitAttribute
   self CONST_SHOWAMMOACBAR false SetUnitAttribute
   true ->IS_BUILT
   <-CREEP_FORCEFIELD_RANGE <-CREEP_FORCEFIELD_CPUSH <-CREEP_FORCEFIELD_ACPUSH 0 true EnableTowerField
   <-BUILD_SOUND PlaySound
   @built

:CreepSleep
   @IsBuilt if
      <-C_SLEEP 0 lte if
         false ->IS_SLEEPING
         CurrentCoords <-SLEEP_DISTANCE @GetClosestUnitToCoords ->C_UNIT
         <-C_UNIT eq(-1) if
            <-SLEEP_TIME @Sleep
         endif
      endif
      <-C_SLEEP 1 sub ->C_SLEEP
   endif
      
:Repair
   CurrentCoords GetDigitalis <-minDigitalis lt if
      CurrentCoords CurrentCoords GetDigitalis 0.16 add SetDigitalis
   else
      CurrentCoords GetDigitalis <-maxDigitalis lt if
         CurrentCoords CurrentCoords GetDigitalis 0.0006 add SetDigitalis
      endif
   endif

:Sleep
   ->C_SLEEP
   true ->IS_SLEEPING
   
:IsSleeping
   <-IS_SLEEPING
   
:IsBuilt
   <-IS_BUILT

:destroyed
   -?C_FLIGHT_X and(-?C_FLIGHT_Y) if
      <-C_FLIGHT_X <-C_FLIGHT_Y GetUnitAttribute(self CONST_CELLWIDTH) sub(1) div(2) FALSE @AddOccupy
   endif
   <-C_DIGITALIS_PRESENT not if
      CurrentCoords 0 SetDigitalis
      CurrentCoords false SetDigitalisGrowth
   endif
   DisableTowerField
   @death

:CreeperInitialize
   <-BUILT_ON_SPAWN not if
      GetListCount(<-C_IMAGES) 0 do
         GetListElement(<-C_IMAGES I) 125 @SetImageAlpha
      loop
      
      self CONST_MAXAMMOAC <-CREEPER_FOR_BUILD SetUnitAttribute
      self CONST_AMMOAC 0 SetUnitAttribute
      self CONST_SHOWAMMOACBAR true SetUnitAttribute
      
      0.2   <-CREEPER_FOR_BUILD mul sqrt ->C_RANGE
      <-C_RANGE 5 lt if
         5 ->C_RANGE
      endif
      8000 <-C_RANGE mul neg ->C_PULL
      
      <-C_RANGE <-C_PULL 0 0 true EnableTowerField
   else
      0 ->CREEPER_FOR_BUILD
   endif
   false ->IS_SLEEPING
   0 ->C_SLEEP
   300 ->C_SLEEPCHECK
   #150 ->C_SLEEPTIME
   
   CurrentCoords GetDigitalisGrowth neq0 ->C_DIGITALIS_PRESENT
   CurrentCoords true SetDigitalisGrowth
   CurrentCoords 1.0 SetDigitalis

:RegisterImage
   ->ri_name
   if(not(-?C_IMAGES))
      CreateList ->C_IMAGES
   endif
   if(not(<-C_IMAGES <-ri_name @DoesListContain))
      <-C_IMAGES <-ri_name AppendToList
   endif

:SetImageAlpha
   ->si_alpha_new
   ->si_image
   self <-si_image GetImageColor ->si_alpha ->si_blue ->si_green ->si_red
   self <-si_image <-si_red <-si_green <-si_blue <-si_alpha_new SetImageColor

:BeginList
   StackSize ->BL_I
   
:BuildList
   StackSize ->BL_M
   CreateList ->BL_L
   <-BL_M <-BL_I do
      ->BL_O
      <-BL_L <-BL_O AppendToList
   loop
   <-BL_L
   
# Function :GetClosestUnitToCoords
# Warning: use this convenience function sparingly, tens of CRPL Cores
# running this all at once every frame can slow the game down.
# Filters all nearby units and grabs the ones you're looking for.
# Notation: x y f1 - u
# eg. CurrentCoords 10 @GetClosestUnitToCoords ->unit
# If all units are outside of the maxDistance or none found returns integer value '-1'.
:GetClosestUnitToCoords
   asfloat ->gcu_mdist
   asfloat ->gcu_y
   asfloat ->gcu_x
   
   -?gcu_types not if
      @BeginList
   endif
   # Reference: https://knucklecracker.com/wiki/doku.php?id=crpl:docs:getunittype
   # Place Unit Types that you /WANT/ to look for here.
   # Simply comment '#' out any that you don't want. All this area does is push strings to the stack.
   "COMMANDNODE"
   "COLLECTOR" "RELAY" "REACTOR" "OREMINE" "SIPHON" "TERP" "GUPPY"
   "PULSECANNON" "MORTAR" "STRAFER" "BOMBER" "SPRAYER" "NULLIFIER" "BEAM" "SNIPER"
   "FORGE" "BERTHA" "THOR"
   #"GUPPYAIR" "STRAFERAIR" "BOMBERAIR"
   #"POWERZONE" "OREDEPOSIT" "RESOURCEPACK" "TOTEM"
   #"AOO" "SHIELDKEY" "TECHARTIFACT" "MESSAGEARTIFACT"
   #"CRPLCORE" #Not recommended as this will grab literally any CRPL Core.
   #"EMITTER" "SPORETOWER" "RUNNERNEST" "AETOWER" "INHIBITOR"
   #"RUNNER"
   # =====
   # If accepted types have never been set, create a list and store it to stay efficient
   # instead of recreating it every time.
   -?gcu_types not if
      @BuildList ->gcu_types
   endif

   #initialize unit
   -1 ->gcu_unit
   999999 ->gcu_unitd

   #retrieve /all/ nearby units
   
   # x y distance boolean(true-square, false-circle)
   # unit checks have been ordered in perceived processing complexity
   <-gcu_x <-gcu_y <-gcu_mdist false GetAllUnitsInRange ->gcu_count
   <-gcu_count neq0 if
      <-gcu_count 0 do
         ->gcu_tempunit
         <-gcu_tempunit CONST_ISLANDED GetUnitAttribute if
            @UnitCoords(<-gcu_tempunit) GetTerrain lte(CurrentCoords GetTerrain) or(<-firing not) if
               <-gcu_tempunit GetUnitType ->gcu_t
               #get the distance
               <-gcu_x <-gcu_y @UnitCoords(<-gcu_tempunit) Distance ->gcu_d
               <-gcu_d <-gcu_t @GetUnitTypePriority asfloat div ->gcu_d
               #is that distance closer?
               <-gcu_d <-gcu_unitd lt if
                  #do we care about this unit type?
                  <-gcu_types <-gcu_t @DoesListContain if
                     #set our new baseline distance and unit
                     <-gcu_d ->gcu_unitd
                     <-gcu_tempunit ->gcu_unit
                  endif
               endif
            endif
         endif
      loop
   endif
   
   <-gcu_unit

# Function :GetUnitTypePriority
# Returns values defined by you for unit value.
# Defaults to 1.
# Notation: s1 - f1
# eg. "COLLECTOR" @GetUnitTypePriority ->priority
:GetUnitTypePriority
   ->cp_type
   1 ->cp_rank
   -?cp_types and(-?cp_ranks) if
      <-cp_types GetListCount 0 do
         <-cp_types I GetListElement eq(<-cp_type) if
            <-cp_ranks I GetListElement asfloat
            return
         endif
      loop
   endif
   <-cp_rank

# Function :ClearUnitTypePriorities
# Removes all defined unit type priorities.
# Notation: -
# eg. @ClearUnitTypePriorities
:ClearUnitTypePriorities
   --cp_ranks
   --cp_types

# Function :AddUnitTypePriority
# This function an object, then a list and returns a boolean value.
# The higher the unit priority, the more it is favoured by :GetClosestUnitToCoords
# Notation: s1 f1 -
# eg. "NULLIFIER" 5 @AddUnitTypePriority
:AddUnitTypePriority
   asfloat ->cp_rank
   ->cp_type
   -?cp_rank not -?cp_types not or if
      CreateList ->cp_types
      CreateList ->cp_ranks
   endif
   <-cp_types <-cp_type AppendToList
   <-cp_ranks <-cp_rank AppendToList
   
# Function :DoesListContain
# This function an object, then a list and returns a boolean value.
# Notation: L1 n1 - b1
# eg. <-myList <-myValue @DoesListContain ->contains
:DoesListContain
   ->dl_value
   ->dl_list
   false ->dl_contained

   <-dl_list GetListCount 0 do
      <-dl_list I GetListElement eq(<-dl_value) if
         true ->dl_contained
         break
      endif
   loop

   <-dl_contained
   
# Function :UnitCoords
# Simple convenience method. Takes a unit and returns the coordinates.
# 'CurrentCoords' and 'self @UnitCoords' are equivalent.
# Notation: n1 - x y
# eg. <-myUnitID @UnitCoords ->unitX ->unitY
:UnitCoords
   asint ->uc_u
   <-uc_u CONST_COORDX GetUnitAttribute
   <-uc_u CONST_COORDY GetUnitAttribute

# Function :TerrainAccessible
# Returns whether or not there is smooth terrain available
# of equivalent height in a certain area of specified radius.
# Radius is measured in cells.
# Area of radius 0 is 1 cell, area of radius 1 is 9 cells, etc.
# Notation: x y i1 - b1
# eg. 10 10 5 @TerrainAccessible ->accessible
:TerrainAccessible
   ->ta_rad
   ->ta_y
   ->ta_x
   
   -1 ->ta_fr
   <-ta_rad mul(2) add(1) ->ta_length
   <-ta_rad ->ta_mid

   <-ta_length 0 do
      <-ta_length 0 do
         <-ta_y I add <-ta_mid sub ->ta_aoy
         <-ta_x J add <-ta_mid sub ->ta_aox
         <-ta_aox <-ta_aoy GetTerrain ->ta_terr
         <-ta_terr 0 lt if
            false
            return
         else
            <-ta_fr -1 eq if
               <-ta_terr ->ta_fr
            else
               <-ta_fr <-ta_terr neq if
                  false
                  return
               endif
            endif
         endif
      loop
   loop
   true

# Function :AreaOccupied
# Returns whether or not a certain area is occupied by one or
# more other units. Radius is measured in cells.
# Notation: x y i1 - b1
# eg. 10 10 5 @AreaOccupied ->occupied
:AreaOccupied
   ->ao_rad
   ->ao_y
   ->ao_x

   <-ao_rad mul(2) add(1) ->ao_length
   <-ao_rad ->ao_mid

   <-ao_length 0 do
      <-ao_length 0 do
         <-ao_y I add <-ao_mid sub ->ao_aoy
         <-ao_x J add <-ao_mid sub ->ao_aox
         <-ao_aox <-ao_aoy GetCellOccupiedCount 0 gt if
            true
            return
         endif
      loop
   loop
   false

# Function :GetIntermediatePosition
# Uses two points and a distance to find a position that is
# between the two points, but X distance away from the target.
# Notation: x y x2 y2 f1 - y x
# eg. CurrentPosition @GetUnitCoords(<-targetUnit) 10 @GetIntermediatePosition swap QueueMove
:GetIntermediatePosition
   asfloat ->gip_dist
   asfloat ->gip_ty
   asfloat ->gip_tx
   asfloat ->gip_y
   asfloat ->gip_x

   <-gip_tx <-gip_ty <-gip_x <-gip_y @GetAngle ->gip_a
   <-gip_a <-gip_dist @GetVector ->gip_vx ->gip_vy
   <-gip_ty <-gip_vy add
   <-gip_tx <-gip_vx add
   
# Function :GetVector
# Uses an angle, and speed and returns a vector
# You can add the vector to a position to get a moving effect
# Notation: f1 f2 - y x
# eg. <-angle 1.5 @GetVector ->x ->y
:GetVector
   asfloat ->gv_vrsm
   asfloat ->gv_vrAngle

   <-gv_vrAngle sin ->gv_vrY
   <-gv_vrAngle cos ->gv_vrX
   <-gv_vrX <-gv_vrY @NormalizeVector ->gv_vrX ->gv_vrY
   <-gv_vrY <-gv_vrsm mul ->gv_vrY
   <-gv_vrX <-gv_vrsm mul ->gv_vrX
   <-gv_vrY neg
   <-gv_vrX

# Function :NormalizeVector
# Takes an (x,y) coordinate and returns it in terms of 0 to 1,
# with 1 being the maximum length (traveling directly up/down or left/right)
# and 0 being the minimum.
# Notation: x y - y x
# eg. <-vectorX <-vectorY @NormalizeVector ->vectorX ->vectorY
:NormalizeVector
   asfloat ->nv_theY
   asfloat ->nv_theX
   <-nv_theX <-nv_theY @GetLength ->nv_length
   <-nv_theY <-nv_length div ->nv_ny
   <-nv_theX <-nv_length div ->nv_nx
   <-nv_ny
   <-nv_nx

# Function :GetLength
# Takes a width and height and calculates a length.
# Notation: x y - f1
# eg. 4 3 @GetLength ->length #(will return 5)
:GetLength
   asfloat ->gl_theY
   asfloat ->gl_theX
   <-gl_theX 2.0 pow <-gl_theY 2.0 pow add sqrt
   
# Function :GetAngle
# Takes an initial position and a target position,
# then calculates an angle to face the target.
# Value returned in radians.
# Notation: x y x2 y2 - f1
# eg. CurrentCoords <-targetUnit @UnitCoords @GetAngle ->angle
:GetAngle
   asfloat ->ga_targetY
   asfloat ->ga_targetX
   asfloat ->ga_curY
   asfloat ->ga_curX

   <-ga_targetX <-ga_curX sub ->ga_deltaX
   <-ga_curY <-ga_targetY sub ->ga_deltaY
   <-ga_deltaY <-ga_deltaX atan2 ->ga_desiredAngle
   <-ga_desiredAngle
   
[close]

Creep Reactor Script:
Spoiler
# CReactor.crpl
# Created on: 10/24/2015 4:23:06 PM
# ------------------------------------------

# VERSION 1.0

# == CUSTOM VARS ==

$amount:25
$interval:12

# == DEFAULT VARS ==
# Health is simulated differently because there is no direct
# way to know cannon damage and Digitalis is ONLY damaged by
# player actions.
# A side effect is that every unit will have to support Digitalis.

# Health reduces sharply when unit digitalis is damaged.
$health:2.5
# If digitalis under unit is less than min, damage health.
$minDigitalis:1.0
# Digitalis will restore to this value.
$maxDigitalis:1.2

# CONSTANTS (only modify here, or during initialization)
$DEFAULT_IMAGE:"Custom40"
$BUILD_SOUND:"Misc7"
$CREEPER_FOR_BUILD:20.0
$CREEP_TYPE:"COLLECTOR"
# Every unit has a forcefield unless range is 0 or below.
# Negative PUSH values will induce a PULL on creeper to "suck it in".
$CREEP_FORCEFIELD_CPUSH:10000
$CREEP_FORCEFIELD_ACPUSH:1000
$CREEP_FORCEFIELD_RANGE:8

# Creep will activate sleep mode
$SLEEP_DISTANCE:50
$SLEEP_TIME:1800
# Enabling hard sleep will allow the AI to activate
# SleepAI when the unit is far away from the action
# or can't do anything for a bit. Otherwise, it is up
# to you to make the unit optimized with @IsSleeping
$SUPPORTS_HARDSLEEP:0
# When a unit is in travel mode it will run an alternate
# AI that is called TravelAI where you can perform tasks
# specific to flying mode. As soon as a unit lands on their
# target position they resume standard AI. If ignoring flight
# is enabled, normal AI will continue to run even during flight.
$IGNORES_FLIGHT:0
$FLIGHT_SPEED:1.0

# RUNTIME (do not modify)
$BUILT_ON_SPAWN:1
$IS_BUILT:0
$S_BASE:-1

# THIS SCRIPT DOES NOT SUPPORT RUNNING WHILE PAUSED.
# However, due to internal bugs occasionally CW3 will still give them frame time
# even though nowhere is it explicitly stated they are allowed to run while paused.
IsPaused if
   1 SuspendMove
   return
endif
# == END DEFAULT ==

once
   self "main" <-DEFAULT_IMAGE SetImage
   @RegisterImage("main")
   
   # CREATE ABOVE THEN REGISTER CUSTOM (not "main") IMAGES HERE
   # @RegisterImage("barrel")
   
   # Flash without sound
   self CONST_DESTROYMODE 3 SetUnitAttribute
   
   # Set size here
   self CONST_CELLHEIGHT 2 SetUnitAttribute
   self CONST_CELLWIDTH 2 SetUnitAttribute
   
   #SetPopupText("Emits a small amount of
   #creeper that pools up.")
   #SetPopupTextY(20)
   
   # Set who can target this unit
   self CONST_NULLIFIERDAMAGES true SetUnitAttribute
   self CONST_BEAMTARGET false SetUnitAttribute
   self CONST_SNIPERTARGET false SetUnitAttribute
   self CONST_SNIPERIGNORELOS false SetUnitAttribute
   
   self CONST_CREATEPZ false SetUnitAttribute
   
   # REQUIRED TO FUNCTION, DO NOT TOUCH
   self CONST_SUPPORTSDIGITALIS true SetUnitAttribute
   self CONST_COUNTSFORVICTORY false SetUnitAttribute
   self CONST_MAXHEALTH <-health SetUnitAttribute
   self CONST_HEALTH <-health SetUnitAttribute
   self CONST_HEALRATE 0.001 SetUnitAttribute
   @CreeperInitialize
   # ==================================
endonce

@StandardCreep

@IsBuilt if
   @ConsistentAI
   if(or(not(@IsFlying) <-IGNORES_FLIGHT))
      if (<-SUPPORTS_HARDSLEEP)
         if(@IsSleeping)
            @SleepAI
         else
            @AI
         endif
      else
         @AI
      endif
   else
      @FlightAI
   endif
else
   @Build
endif

:AI
   GetTimer0 eq0 if
      CurrentCoords <-amount AddCreeper
      <-interval SetTimer0
   endif

:SleepAI
   

:FlightAI


:ConsistentAI
   #custom code here, runs every tick regardless of circumstance
   
:built
   

:death
   #custom code here
   "Explosion1" PlaySound

# ===============================
# ===== STANDARD CREEP CODE =====
# ===============================

# Bare minimum required code to run each tick.
# Ensures that player can damage sleeping Creeps.
:StandardCreep
   if(not(@IsFlying))
      #@CreepSleep
      CurrentCoords GetCreeper 0 lt if
         self 0.05 Damage
      endif
      CurrentCoords GetDigitalis <-minDigitalis lt if
         self 0.30 Damage
      endif
      @IsBuilt if
         @Repair
      endif
   endif
   @AnimateFlight

:RandomFixCoord
   while not(@IsPointOnMap(<-RF_X <-RF_Y)) repeat
      CurrentCoords 10 RandCoordsInRange ->RF_Y ->RF_X
   endwhile
   <-RF_Y
   <-RF_X
   
# Function :IsPointOnMap
# Takes a set of cell-coordinates and returns true
# if the coordinates are on the map.
# Notation: x y - b1
# eg. -1 -1 @IsPointOnMap ->onMap #(will return false)
:IsPointOnMap
   ->pom_pointY
   ->pom_pointX
   1 ->pom_onMap
   <-pom_pointY MapHeight gt if
      0 ->pom_onMap
   endif
   <-pom_pointY 0 lt if
      0 ->pom_onMap
   endif
   <-pom_pointX MapWidth gt if
      0 ->pom_onMap
   endif
   <-pom_pointX 0 lt if
      0 ->pom_onMap
   endif
   <-pom_onMap
   
:AnimateFlight
   -?C_FLIGHT if
      self "main" 1 GetImageScaleX ->C_FX
      <-C_FLIGHT if
         # Liftoff
         <-C_FX 1.3 lt if
            <-C_FX 0.02 add ->C_FSN
            GetListCount(<-C_IMAGES) 0 do
               self GetListElement(<-C_IMAGES I) <-C_FSN <-C_FSN SetImageScale
            loop
         else
            GetQueuedMoveCount eq0 if
               <-C_FLIGHT_MOVE if
                  false ->C_FLIGHT_MOVE
                  @ExecuteLanding
               else
                  self CONST_BEAMTARGET true SetUnitAttribute
                  true ->C_FLIGHT_MOVE
                  if(not(@IsPointOnMap(<-C_FLIGHT_X <-C_FLIGHT_Y)))
                     @RandomFixCoord ->C_FLIGHT_X ->C_FLIGHT_Y
                  else
                     <-C_FLIGHT_X <-C_FLIGHT_Y <-FLIGHT_SPEED QueueMove
                  endif
                  true ->C_FLYING
               endif
            endif
         endif
      else
         # Landing
         <-C_FX 1 gt if
            <-C_FX 0.02 sub ->C_FSN
            GetListCount(<-C_IMAGES) 0 do
               self GetListElement(<-C_IMAGES I) <-C_FSN <-C_FSN SetImageScale
            loop
         else
            11 CurrentPixelCoords 0.01 1 1 0.03 CreateEffect
            "UnitLand" PlaySound
            --C_FLIGHT
            self CONST_BEAMTARGET false SetUnitAttribute
            <-CREEP_FORCEFIELD_RANGE <-CREEP_FORCEFIELD_CPUSH <-CREEP_FORCEFIELD_ACPUSH 0 true EnableTowerField
            CurrentCoords GetDigitalisGrowth neq0 ->C_DIGITALIS_PRESENT
            CurrentCoords true SetDigitalisGrowth
            CurrentCoords 1.0 SetDigitalis
         endif
      endif
   endif

:SetFlightLandingTarget
   -?C_FLIGHT_X and(-?C_FLIGHT_Y) if
      <-C_FLIGHT_X <-C_FLIGHT_Y GetUnitAttribute(self CONST_CELLWIDTH) sub(1) div(2) FALSE @AddOccupy
   endif
   ->C_FLIGHT_Y
   ->C_FLIGHT_X
   
   <-C_FLIGHT_X <-C_FLIGHT_Y GetUnitAttribute(self CONST_CELLWIDTH) sub(1) div(2) TRUE @AddOccupy
   -?C_FLIGHT and(<-C_FLYING) if
      AbortMove
      <-C_FLIGHT_X <-C_FLIGHT_Y <-FLIGHT_SPEED QueueMove
   endif

# Function :AddOccupy
# Returns whether or not a certain area is occupied by one or
# more other units. Radius is measured in cells.
# Notation: x y f1 b1 -
# eg. CurrentCoords 3 false @AddOccupy #this would allow another unit to land
:AddOccupy
   ->OC_ADD
   ->OC_RAD
   ->OC_Y
   ->OC_X
   
   <-OC_RAD mul(2) add(1) ->OC_LENGTH
   <-OC_RAD ->OC_MID
   
   <-OC_LENGTH 0 do
      <-OC_LENGTH 0 do
         <-OC_Y I add <-OC_MID sub ->OC_AOY
         <-OC_X J add <-OC_MID sub ->OC_AOX
         <-OC_AOX <-OC_AOY GetCellOccupiedCount ->OC_COUNT
         <-OC_ADD if
            <-OC_AOX <-OC_AOY <-OC_COUNT add(1) SetCellOccupiedCount
         else
            <-OC_AOX <-OC_AOY <-OC_COUNT sub(1) SetCellOccupiedCount
         endif
      loop
   loop
   
:ExecuteLiftoff
   <-C_DIGITALIS_PRESENT not if
      CurrentCoords 0 SetDigitalis
      CurrentCoords false SetDigitalisGrowth
      true ->C_DIGITALIS_PRESENT
   endif
   self CONST_TAKEMAPSPACE false SetUnitAttribute
   "UnitTakeOff" PlaySound
   true ->C_FLIGHT
   false ->C_FLYING
   DisableTowerField
   
   # Beams deal significantly less damage, therefore, lower health to
   # within acceptable parameters.
   self CONST_HEALTH dup2 GetUnitAttribute div(3.5) SetUnitAttribute
   self CONST_MAXHEALTH dup2 GetUnitAttribute div(3.5) SetUnitAttribute
   
   GetListCount(<-C_IMAGES) 0 do
      GetListElement(<-C_IMAGES I) ->EX_IM
      self <-EX_IM GetImagePositionZ ->EX_ZPOS
      self <-EX_IM <-EX_ZPOS sub(0.1) SetImagePositionZ
   loop

:ExecuteLanding
   self CONST_TAKEMAPSPACE true SetUnitAttribute
   false ->IS_SLEEPING
   false ->C_FLIGHT
   false ->C_FLYING
   
   # Restore health back to normal values.
   self CONST_MAXHEALTH dup2 GetUnitAttribute mul(3.5) SetUnitAttribute
   self CONST_HEALTH dup2 GetUnitAttribute mul(3.5) SetUnitAttribute
   
   GetListCount(<-C_IMAGES) 0 do
      GetListElement(<-C_IMAGES I) ->EX_IM
      self <-EX_IM GetImagePositionZ ->EX_ZPOS
      self <-EX_IM <-EX_ZPOS add(0.1) SetImagePositionZ
   loop

:IsFlying
   -?C_FLIGHT

:Build
   CurrentCoords GetCreeper ->C_CRP
   <-CREEPER_FOR_BUILD 0 lte if
      @FinishBuild
   else
      <-C_CRP 0 gt if
         self CONST_MAXAMMOAC GetUnitAttribute self CONST_AMMOAC GetUnitAttribute sub ->C_CRPN
         <-C_CRP <-C_CRPN gt if
            <-C_CRP <-C_CRPN sub ->C_LEFT
            CurrentCoords <-C_LEFT SetCreeper
            @FinishBuild
         else
            self CONST_AMMOAC dup2 GetUnitAttribute <-C_CRP add SetUnitAttribute
            CurrentCoords 0 SetCreeper
         endif
      endif
   endif

:FinishBuild
   GetListCount(<-C_IMAGES) 0 do
      GetListElement(<-C_IMAGES I) 255 @SetImageAlpha
   loop
   
   self CONST_AMMO 0 SetUnitAttribute
   self CONST_MAXAMMOAC 0 SetUnitAttribute
   self CONST_SHOWAMMOACBAR false SetUnitAttribute
   true ->IS_BUILT
   <-CREEP_FORCEFIELD_RANGE <-CREEP_FORCEFIELD_CPUSH <-CREEP_FORCEFIELD_ACPUSH 0 true EnableTowerField
   <-BUILD_SOUND PlaySound
   @built

:CreepSleep
   @IsBuilt if
      <-C_SLEEP 0 lte if
         false ->IS_SLEEPING
         CurrentCoords <-SLEEP_DISTANCE @GetClosestUnitToCoords ->C_UNIT
         <-C_UNIT eq(-1) if
            <-SLEEP_TIME @Sleep
         endif
      endif
      <-C_SLEEP 1 sub ->C_SLEEP
   endif
      
:Repair
   CurrentCoords GetDigitalis <-minDigitalis lt if
      CurrentCoords CurrentCoords GetDigitalis 0.16 add SetDigitalis
   else
      CurrentCoords GetDigitalis <-maxDigitalis lt if
         CurrentCoords CurrentCoords GetDigitalis 0.0006 add SetDigitalis
      endif
   endif

:Sleep
   ->C_SLEEP
   true ->IS_SLEEPING
   
:IsSleeping
   <-IS_SLEEPING
   
:IsBuilt
   <-IS_BUILT

:destroyed
   -?C_FLIGHT_X and(-?C_FLIGHT_Y) if
      <-C_FLIGHT_X <-C_FLIGHT_Y GetUnitAttribute(self CONST_CELLWIDTH) sub(1) div(2) FALSE @AddOccupy
   endif
   <-C_DIGITALIS_PRESENT not if
      CurrentCoords 0 SetDigitalis
      CurrentCoords false SetDigitalisGrowth
   endif
   DisableTowerField
   @death

:CreeperInitialize
   <-BUILT_ON_SPAWN not if
      GetListCount(<-C_IMAGES) 0 do
         GetListElement(<-C_IMAGES I) 125 @SetImageAlpha
      loop
      
      self CONST_MAXAMMOAC <-CREEPER_FOR_BUILD SetUnitAttribute
      self CONST_AMMOAC 0 SetUnitAttribute
      self CONST_SHOWAMMOACBAR true SetUnitAttribute
      
      0.2   <-CREEPER_FOR_BUILD mul sqrt ->C_RANGE
      <-C_RANGE 5 lt if
         5 ->C_RANGE
      endif
      8000 <-C_RANGE mul neg ->C_PULL
      
      <-C_RANGE <-C_PULL 0 0 true EnableTowerField
   else
      0 ->CREEPER_FOR_BUILD
   endif
   false ->IS_SLEEPING
   0 ->C_SLEEP
   1800 ->C_SLEEPCHECK
   #150 ->C_SLEEPTIME
   
   CurrentCoords GetDigitalisGrowth neq0 ->C_DIGITALIS_PRESENT
   CurrentCoords true SetDigitalisGrowth
   CurrentCoords 1.0 SetDigitalis

:RegisterImage
   ->ri_name
   if(not(-?C_IMAGES))
      CreateList ->C_IMAGES
   endif
   if(not(<-C_IMAGES <-ri_name @DoesListContain))
      <-C_IMAGES <-ri_name AppendToList
   endif

:SetImageAlpha
   ->si_alpha_new
   ->si_image
   self <-si_image GetImageColor ->si_alpha ->si_blue ->si_green ->si_red
   self <-si_image <-si_red <-si_green <-si_blue <-si_alpha_new SetImageColor

# Function :GetClosestUnitToCoords
# Warning: use this convenience function sparingly, tens of CRPL Cores
# running this all at once every frame can slow the game down.
# Notation: x y f1 - u
# eg. CurrentCoords 10 @GetClosestUnitToCoords ->unit
# If all units are outside of the maxDistance or none found returns integer value '-1'.
:GetClosestUnitToCoords
   asfloat ->gcu_mdist
   asfloat ->gcu_y
   asfloat ->gcu_x
   StackSize ->gcu_szmin

   # Reference: https://knucklecracker.com/wiki/doku.php?id=crpl:docs:getunittype
   # Place Unit Types that you /WANT/ to look for here.
   # Simply comment '#' out any that you don't want. All this area does is push strings to the stack.
   "COMMANDNODE"
   "COLLECTOR" "RELAY" "REACTOR" "OREMINE" "SIPHON" "TERP" "GUPPY"
   "PULSECANNON" "MORTAR" "STRAFER" "BOMBER" "SPRAYER" "NULLIFIER" "BEAM" "SNIPER"
   "FORGE" "BERTHA" "THOR"
   "GUPPYAIR" "STRAFERAIR" "BOMBERAIR"
   #"POWERZONE" "OREDEPOSIT" "RESOURCEPACK" "TOTEM"
   #"AOO" "SHIELDKEY" "TECHARTIFACT" "MESSAGEARTIFACT"
   #"CRPLCORE" #Not recommended as this will grab literally any CRPL Core.
   #"EMITTER" "SPORETOWER" "RUNNERNEST" "AETOWER" "INHIBITOR"
   #"RUNNER"
   # =====

   #Finding the boundary stack size (how many elements were added to stack)
   #and then forming a list from the units we want.
   StackSize ->gcu_szmax
   CreateList ->gcu_types
   <-gcu_szmax <-gcu_szmin do
      ->gcu_t
      <-gcu_types <-gcu_t AppendToList
   loop

   #initialize unit
   -1 ->gcu_unit
   999999 ->gcu_unitd

   #retrieve /all/ nearby units
   
   # x y distance boolean(true-square, false-circle)
   # unit checks have been ordered in perceived processing complexity
   <-gcu_x <-gcu_y <-gcu_mdist false GetAllUnitsInRange ->gcu_count
   <-gcu_count neq0 if
      <-gcu_count 0 do
         ->gcu_tempunit
         <-gcu_tempunit GetUnitType ->gcu_t
         #get the distance
         <-gcu_x <-gcu_y @UnitCoords(<-gcu_tempunit) Distance ->gcu_d
         #is that distance closer?
         <-gcu_d <-gcu_unitd lt if
            #do we care about this unit type?
            <-gcu_types <-gcu_t @DoesListContain if
               #set our new baseline distance and unit
               <-gcu_d ->gcu_unitd
               <-gcu_tempunit ->gcu_unit
            endif
         endif
      loop
   endif
   
   <-gcu_unit
   
# Function :DoesListContain
# This function an object, then a list and returns a boolean value.
# Notation: L1 n1 - b1
# eg. <-myList <-myValue @DoesListContain ->contains
:DoesListContain
   ->dl_value
   ->dl_list
   false ->dl_contained

   <-dl_list GetListCount 0 do
      <-dl_list I GetListElement eq(<-dl_value) if
         true ->dl_contained
         break
      endif
   loop

   <-dl_contained
   
# Function :UnitCoords
# Simple convenience method. Takes a unit and returns the coordinates.
# 'CurrentCoords' and 'self @UnitCoords' are equivalent.
# Notation: n1 - x y
# eg. <-myUnitID @UnitCoords ->unitX ->unitY
:UnitCoords
   asint ->uc_u
   <-uc_u CONST_COORDX GetUnitAttribute
   <-uc_u CONST_COORDY GetUnitAttribute
[close]

Creep Bomber Pad Script:
Spoiler
# CBomberBase.crpl
# Created on: 10/25/2015 1:53:09 PM
# ------------------------------------------

# VERSION 1.0

# == CUSTOM VARS ==

$shipAmmo:12
$shipPayload:15.0
$BombDamage:5.0
$shipReach:20.0
$shipCooldown:30
$shipHealth:5.0
$shipSightRadius:120
$shipSpeed:1.4
$shipRotSpeed:0.06

$creeperForUpkeep:300

$WIPE_AMMO:0
$AMMO_FULL:0

# == DEFAULT VARS ==
# Health is simulated differently because there is no direct
# way to know cannon damage and Digitalis is ONLY damaged by
# player actions.
# A side effect is that every unit will have to support Digitalis.

# Health reduces sharply when unit digitalis is damaged.
$health:5.0
# If digitalis under unit is less than min, damage health.
$minDigitalis:1.0
# Digitalis will restore to this value.
$maxDigitalis:1.2

# CONSTANTS (only modify here, or during initialization)
$DEFAULT_IMAGE:"Custom42"
$BUILD_SOUND:"Misc22"
$CREEPER_FOR_BUILD:1000.0
$CREEP_TYPE:"BOMBERBASE"
# Every unit has a forcefield unless range is 0 or below.
# Negative PUSH values will induce a PULL on creeper to "suck it in".
$CREEP_FORCEFIELD_CPUSH:-100000
$CREEP_FORCEFIELD_ACPUSH:0
$CREEP_FORCEFIELD_RANGE:5

# Creep will activate sleep mode
$SLEEP_DISTANCE:1
$SLEEP_TIME:1800
# Enabling hard sleep will allow the AI to activate
# SleepAI when the unit is far away from the action
# or can't do anything for a bit. Otherwise, it is up
# to you to make the unit optimized with @IsSleeping
$SUPPORTS_HARDSLEEP:0
# When a unit is in travel mode it will run an alternate
# AI that is called TravelAI where you can perform tasks
# specific to flying mode. As soon as a unit lands on their
# target position they resume standard AI. If ignoring flight
# is enabled, normal AI will continue to run even during flight.
$IGNORES_FLIGHT:0
$FLIGHT_SPEED:1.0

# RUNTIME (do not modify)
$BUILT_ON_SPAWN:1
$IS_BUILT:0
$S_BASE:-1

# THIS SCRIPT DOES NOT SUPPORT RUNNING WHILE PAUSED.
# However, due to internal bugs occasionally CW3 will still give them frame time
# even though nowhere is it explicitly stated they are allowed to run while paused.
IsPaused if
   1 SuspendMove
   return
endif
# == END DEFAULT ==

once
   self "main" <-DEFAULT_IMAGE SetImage
   @RegisterImage("main")
   
   # CREATE ABOVE THEN REGISTER CUSTOM (not "main") IMAGES HERE
   # @RegisterImage("barrel")
   
   # Flash without sound
   self CONST_DESTROYMODE 3 SetUnitAttribute
   
   # Set size here
   self CONST_CELLHEIGHT 3 SetUnitAttribute
   self CONST_CELLWIDTH 3 SetUnitAttribute
   
   # Set who can target this unit
   self CONST_NULLIFIERDAMAGES true SetUnitAttribute
   self CONST_BEAMTARGET false SetUnitAttribute
   self CONST_SNIPERTARGET false SetUnitAttribute
   self CONST_SNIPERIGNORELOS false SetUnitAttribute
   
   self CONST_CREATEPZ false SetUnitAttribute
   
   # REQUIRED TO FUNCTION, DO NOT TOUCH
   self CONST_SUPPORTSDIGITALIS true SetUnitAttribute
   self CONST_COUNTSFORVICTORY false SetUnitAttribute
   self CONST_MAXHEALTH <-health SetUnitAttribute
   self CONST_HEALTH <-health SetUnitAttribute
   self CONST_HEALRATE 0.001 SetUnitAttribute
   @CreeperInitialize
   # ==================================
endonce

@StandardCreep

@IsBuilt if
   @ConsistentAI
   if(or(not(@IsFlying) <-IGNORES_FLIGHT))
      if (<-SUPPORTS_HARDSLEEP)
         if(@IsSleeping)
            @SleepAI
         else
            @AI
         endif
      else
         @AI
      endif
   else
      @FlightAI
   endif
else
   @Build
endif

:AI
   <-WIPE_AMMO if
      @SetAmmo(0)
      false ->WIPE_AMMO
   endif
   @NeedsAmmo not ->AMMO_FULL
   
   if(@NeedsAmmo)
      @Refuel
   else
      @HasShip not if
         @SetAmmo(0)
         @BuildShip
      endif
   endif

:BuildShip
   "Misc15" PlaySound
   
   11 CurrentPixelCoords -0.1 1.0 1.0 0.03 CreateEffect
   
   "CRPLCore" CurrentCoords CreateUnit ->st
   <-st "CBomber.crpl" AddScriptToUnit
   <-st "CBomber.crpl" "C_BOMBER_BASE" self SetScriptVar
   <-st "CBomber.crpl" "ammo" <-shipAmmo SetScriptVar
   <-st "CBomber.crpl" "payload" <-shipPayload SetScriptVar
   <-st "CBomber.crpl" "health" <-shipHealth SetScriptVar
   <-st "CBomber.crpl" "sightRadius" <-shipSightRadius SetScriptVar
   <-st "CBomber.crpl" "reach" <-shipReach SetScriptVar
   <-st "CBomber.crpl" "cooldown" <-shipCooldown SetScriptVar
   <-st "CBomber.crpl" "BombDamage" <-shipDamage SetScriptVar
   <-st "CBomber.crpl" "speed" <-shipSpeed SetScriptVar
   <-st "CBomber.crpl" "rotSpeed" <-shipRotSpeed SetScriptVar
   
:HasShip
   "C_BOMBER_BASE" self GetCoresWithVar ->num
   <-num neq0 if
      <-num 0 do
         ->garbage
      loop
      TRUE
   else
      FALSE
   endif

:Refuel
   CurrentCoords GetCreeper ->_crp
   @AmmoNeeded <-_crp lt if
      CurrentCoords <-_crp @AmmoNeeded sub SetCreeper
      @MaxAmmo @SetAmmo
   else
      CurrentCoords 0 SetCreeper
      @Ammo <-_crp add @SetAmmo
   endif
   
:NeedsAmmo
   @Ammo @MaxAmmo approximately eq(false)

:AmmoNeeded
   @MaxAmmo @Ammo sub

:SetAmmo
   ->_ammo
   self CONST_AMMO <-_ammo SetUnitAttribute

:MaxAmmo
   <-creeperForUpkeep

:Ammo
   self CONST_AMMO GetUnitAttribute
   
:ConsistentAI
   #custom code here, runs every tick regardless of circumstance
   
:SleepAI
   
   #custom code here

:FlightAI
   #custom code here
   
:built
   self CONST_MAXAMMO @MaxAmmo SetUnitAttribute
   self CONST_AMMO 0 SetUnitAttribute
   self CONST_SHOWAMMOBAR true SetUnitAttribute

:death
   #custom code here
   "Explosion1" PlaySound

# ===============================
# ===== STANDARD CREEP CODE =====
# ===============================


# Bare minimum required code to run each tick.
# Ensures that player can damage sleeping Creeps.
:StandardCreep
   if(not(@IsFlying))
      #@CreepSleep
      CurrentCoords GetCreeper 0 lt if
         self 0.05 Damage
      endif
      CurrentCoords GetDigitalis <-minDigitalis lt if
         self 0.30 Damage
      endif
      @IsBuilt if
         @Repair
      endif
   endif
   @AnimateFlight


:RandomFixCoord
   while not(@IsPointOnMap(<-RF_X <-RF_Y)) repeat
      CurrentCoords 10 RandCoordsInRange ->RF_Y ->RF_X
   endwhile
   <-RF_Y
   <-RF_X
   
# Function :IsPointOnMap
# Takes a set of cell-coordinates and returns true
# if the coordinates are on the map.
# Notation: x y - b1
# eg. -1 -1 @IsPointOnMap ->onMap #(will return false)
:IsPointOnMap
   ->pom_pointY
   ->pom_pointX
   1 ->pom_onMap
   <-pom_pointY MapHeight gt if
      0 ->pom_onMap
   endif
   <-pom_pointY 0 lt if
      0 ->pom_onMap
   endif
   <-pom_pointX MapWidth gt if
      0 ->pom_onMap
   endif
   <-pom_pointX 0 lt if
      0 ->pom_onMap
   endif
   <-pom_onMap
   
:AnimateFlight
   -?C_FLIGHT if
      self "main" 1 GetImageScaleX ->C_FX
      <-C_FLIGHT if
         # Liftoff
         <-C_FX 1.3 lt if
            <-C_FX 0.02 add ->C_FSN
            GetListCount(<-C_IMAGES) 0 do
               self GetListElement(<-C_IMAGES I) <-C_FSN <-C_FSN SetImageScale
            loop
         else
            GetQueuedMoveCount eq0 if
               <-C_FLIGHT_MOVE if
                  false ->C_FLIGHT_MOVE
                  @ExecuteLanding
               else
                  self CONST_BEAMTARGET true SetUnitAttribute
                  true ->C_FLIGHT_MOVE
                  if(not(@IsPointOnMap(<-C_FLIGHT_X <-C_FLIGHT_Y)))
                     @RandomFixCoord ->C_FLIGHT_X ->C_FLIGHT_Y
                  else
                     <-C_FLIGHT_X <-C_FLIGHT_Y <-FLIGHT_SPEED QueueMove
                  endif
                  true ->C_FLYING
               endif
            endif
         endif
      else
         # Landing
         <-C_FX 1 gt if
            <-C_FX 0.02 sub ->C_FSN
            GetListCount(<-C_IMAGES) 0 do
               self GetListElement(<-C_IMAGES I) <-C_FSN <-C_FSN SetImageScale
            loop
         else
            11 CurrentPixelCoords 0.01 1 1 0.03 CreateEffect
            "UnitLand" PlaySound
            --C_FLIGHT
            self CONST_BEAMTARGET false SetUnitAttribute
            <-CREEP_FORCEFIELD_RANGE <-CREEP_FORCEFIELD_CPUSH <-CREEP_FORCEFIELD_ACPUSH 0 true EnableTowerField
            CurrentCoords GetDigitalisGrowth neq0 ->C_DIGITALIS_PRESENT
            CurrentCoords true SetDigitalisGrowth
            CurrentCoords 1.0 SetDigitalis
         endif
      endif
   endif

:SetFlightLandingTarget
   -?C_FLIGHT_X and(-?C_FLIGHT_Y) if
      <-C_FLIGHT_X <-C_FLIGHT_Y GetUnitAttribute(self CONST_CELLWIDTH) sub(1) div(2) FALSE @AddOccupy
   endif
   ->C_FLIGHT_Y
   ->C_FLIGHT_X
   
   <-C_FLIGHT_X <-C_FLIGHT_Y GetUnitAttribute(self CONST_CELLWIDTH) sub(1) div(2) TRUE @AddOccupy
   -?C_FLIGHT and(<-C_FLYING) if
      AbortMove
      <-C_FLIGHT_X <-C_FLIGHT_Y <-FLIGHT_SPEED QueueMove
   endif

# Function :AddOccupy
# Returns whether or not a certain area is occupied by one or
# more other units. Radius is measured in cells.
# Notation: x y f1 b1 -
# eg. CurrentCoords 3 false @AddOccupy #this would allow another unit to land
:AddOccupy
   ->OC_ADD
   ->OC_RAD
   ->OC_Y
   ->OC_X
   
   <-OC_RAD mul(2) add(1) ->OC_LENGTH
   <-OC_RAD ->OC_MID
   
   <-OC_LENGTH 0 do
      <-OC_LENGTH 0 do
         <-OC_Y I add <-OC_MID sub ->OC_AOY
         <-OC_X J add <-OC_MID sub ->OC_AOX
         <-OC_AOX <-OC_AOY GetCellOccupiedCount ->OC_COUNT
         <-OC_ADD if
            <-OC_AOX <-OC_AOY <-OC_COUNT add(1) SetCellOccupiedCount
         else
            <-OC_AOX <-OC_AOY <-OC_COUNT sub(1) SetCellOccupiedCount
         endif
      loop
   loop
   
:ExecuteLiftoff
   <-C_DIGITALIS_PRESENT not if
      CurrentCoords 0 SetDigitalis
      CurrentCoords false SetDigitalisGrowth
      true ->C_DIGITALIS_PRESENT
   endif
   self CONST_TAKEMAPSPACE false SetUnitAttribute
   "UnitTakeOff" PlaySound
   true ->C_FLIGHT
   false ->C_FLYING
   DisableTowerField
   
   # Beams deal significantly less damage, therefore, lower health to
   # within acceptable parameters.
   self CONST_HEALTH dup2 GetUnitAttribute div(3.5) SetUnitAttribute
   self CONST_MAXHEALTH dup2 GetUnitAttribute div(3.5) SetUnitAttribute
   
   GetListCount(<-C_IMAGES) 0 do
      GetListElement(<-C_IMAGES I) ->EX_IM
      self <-EX_IM GetImagePositionZ ->EX_ZPOS
      self <-EX_IM <-EX_ZPOS sub(0.1) SetImagePositionZ
   loop

:ExecuteLanding
   self CONST_TAKEMAPSPACE true SetUnitAttribute
   false ->IS_SLEEPING
   false ->C_FLIGHT
   false ->C_FLYING
   
   # Restore health back to normal values.
   self CONST_MAXHEALTH dup2 GetUnitAttribute mul(3.5) SetUnitAttribute
   self CONST_HEALTH dup2 GetUnitAttribute mul(3.5) SetUnitAttribute
   
   GetListCount(<-C_IMAGES) 0 do
      GetListElement(<-C_IMAGES I) ->EX_IM
      self <-EX_IM GetImagePositionZ ->EX_ZPOS
      self <-EX_IM <-EX_ZPOS add(0.1) SetImagePositionZ
   loop

:IsFlying
   -?C_FLIGHT

:Build
   CurrentCoords GetCreeper ->C_CRP
   <-CREEPER_FOR_BUILD 0 lte if
      @FinishBuild
   else
      <-C_CRP 0 gt if
         self CONST_MAXAMMOAC GetUnitAttribute self CONST_AMMOAC GetUnitAttribute sub ->C_CRPN
         <-C_CRP <-C_CRPN gt if
            <-C_CRP <-C_CRPN sub ->C_LEFT
            CurrentCoords <-C_LEFT SetCreeper
            @FinishBuild
         else
            self CONST_AMMOAC dup2 GetUnitAttribute <-C_CRP add SetUnitAttribute
            CurrentCoords 0 SetCreeper
         endif
      endif
   endif

:FinishBuild
   GetListCount(<-C_IMAGES) 0 do
      GetListElement(<-C_IMAGES I) 255 @SetImageAlpha
   loop
   
   self CONST_AMMO 0 SetUnitAttribute
   self CONST_MAXAMMOAC 0 SetUnitAttribute
   self CONST_SHOWAMMOACBAR false SetUnitAttribute
   true ->IS_BUILT
   <-CREEP_FORCEFIELD_RANGE <-CREEP_FORCEFIELD_CPUSH <-CREEP_FORCEFIELD_ACPUSH 0 true EnableTowerField
   <-BUILD_SOUND PlaySound
   @built

:CreepSleep
   @IsBuilt if
      <-C_SLEEP 0 lte if
         false ->IS_SLEEPING
         CurrentCoords <-SLEEP_DISTANCE @GetClosestUnitToCoords ->C_UNIT
         <-C_UNIT eq(-1) if
            <-SLEEP_TIME @Sleep
         endif
      endif
      <-C_SLEEP 1 sub ->C_SLEEP
   endif
      
:Repair
   CurrentCoords GetDigitalis <-minDigitalis lt if
      CurrentCoords CurrentCoords GetDigitalis 0.16 add SetDigitalis
   else
      CurrentCoords GetDigitalis <-maxDigitalis lt if
         CurrentCoords CurrentCoords GetDigitalis 0.0006 add SetDigitalis
      endif
   endif

:Sleep
   ->C_SLEEP
   true ->IS_SLEEPING
   
:IsSleeping
   <-IS_SLEEPING
   
:IsBuilt
   <-IS_BUILT

:destroyed
   -?C_FLIGHT_X and(-?C_FLIGHT_Y) if
      <-C_FLIGHT_X <-C_FLIGHT_Y GetUnitAttribute(self CONST_CELLWIDTH) sub(1) div(2) FALSE @AddOccupy
   endif
   <-C_DIGITALIS_PRESENT not if
      CurrentCoords 0 SetDigitalis
      CurrentCoords false SetDigitalisGrowth
   endif
   DisableTowerField
   @death

:CreeperInitialize
   <-BUILT_ON_SPAWN not if
      GetListCount(<-C_IMAGES) 0 do
         GetListElement(<-C_IMAGES I) 125 @SetImageAlpha
      loop
      
      self CONST_MAXAMMOAC <-CREEPER_FOR_BUILD SetUnitAttribute
      self CONST_AMMOAC 0 SetUnitAttribute
      self CONST_SHOWAMMOACBAR true SetUnitAttribute
      
      0.2   <-CREEPER_FOR_BUILD mul sqrt ->C_RANGE
      <-C_RANGE 5 lt if
         5 ->C_RANGE
      endif
      8000 <-C_RANGE mul neg ->C_PULL
      
      <-C_RANGE <-C_PULL 0 0 true EnableTowerField
   else
      0 ->CREEPER_FOR_BUILD
   endif
   false ->IS_SLEEPING
   0 ->C_SLEEP
   300 ->C_SLEEPCHECK
   #150 ->C_SLEEPTIME
   
   CurrentCoords GetDigitalisGrowth neq0 ->C_DIGITALIS_PRESENT
   CurrentCoords true SetDigitalisGrowth
   CurrentCoords 1.0 SetDigitalis

:RegisterImage
   ->ri_name
   if(not(-?C_IMAGES))
      CreateList ->C_IMAGES
   endif
   if(not(<-C_IMAGES <-ri_name @DoesListContain))
      <-C_IMAGES <-ri_name AppendToList
   endif

:SetImageAlpha
   ->si_alpha_new
   ->si_image
   self <-si_image GetImageColor ->si_alpha ->si_blue ->si_green ->si_red
   self <-si_image <-si_red <-si_green <-si_blue <-si_alpha_new SetImageColor

:BeginList
   StackSize ->BL_I
   
:BuildList
   StackSize ->BL_M
   CreateList ->BL_L
   <-BL_M <-BL_I do
      ->BL_O
      <-BL_L <-BL_O AppendToList
   loop
   <-BL_L
   
# Function :GetClosestUnitToCoords
# Warning: use this convenience function sparingly, tens of CRPL Cores
# running this all at once every frame can slow the game down.
# Filters all nearby units and grabs the ones you're looking for.
# Notation: x y f1 - u
# eg. CurrentCoords 10 @GetClosestUnitToCoords ->unit
# If all units are outside of the maxDistance or none found returns integer value '-1'.
:GetClosestUnitToCoords
   asfloat ->gcu_mdist
   asfloat ->gcu_y
   asfloat ->gcu_x
   
   -?gcu_types not if
      @BeginList
   endif
   # Reference: https://knucklecracker.com/wiki/doku.php?id=crpl:docs:getunittype
   # Place Unit Types that you /WANT/ to look for here.
   # Simply comment '#' out any that you don't want. All this area does is push strings to the stack.
   "COMMANDNODE"
   "COLLECTOR" "RELAY" "REACTOR" "OREMINE" "SIPHON" "TERP" "GUPPY"
   "PULSECANNON" "MORTAR" "STRAFER" "BOMBER" "SPRAYER" "NULLIFIER" "BEAM" "SNIPER"
   "FORGE" "BERTHA" "THOR"
   "GUPPYAIR" "STRAFERAIR" "BOMBERAIR"
   "POWERZONE" "OREDEPOSIT" "RESOURCEPACK" "TOTEM"
   "AOO" "SHIELDKEY" "TECHARTIFACT" "MESSAGEARTIFACT"
   #"CRPLCORE" #Not recommended as this will grab literally any CRPL Core.
   "EMITTER" "SPORETOWER" "RUNNERNEST" "AETOWER" "INHIBITOR"
   "RUNNER"
   # =====
   # If accepted types have never been set, create a list and store it to stay efficient
   # instead of recreating it every time.
   -?gcu_types not if
      @BuildList ->gcu_types
   endif

   #initialize unit
   -1 ->gcu_unit
   999999 ->gcu_unitd

   #retrieve /all/ nearby units
   
   # x y distance boolean(true-square, false-circle)
   # unit checks have been ordered in perceived processing complexity
   <-gcu_x <-gcu_y <-gcu_mdist false GetAllUnitsInRange ->gcu_count
   <-gcu_count neq0 if
      <-gcu_count 0 do
         ->gcu_tempunit
         <-gcu_tempunit GetUnitType ->gcu_t
         #get the distance
         <-gcu_x <-gcu_y @UnitCoords(<-gcu_tempunit) Distance ->gcu_d
         <-gcu_d <-gcu_t @GetUnitTypePriority asfloat div ->gcu_d
         #is that distance closer?
         <-gcu_d <-gcu_unitd lt if
            #do we care about this unit type?
            <-gcu_types <-gcu_t @DoesListContain if
               #set our new baseline distance and unit
               <-gcu_d ->gcu_unitd
               <-gcu_tempunit ->gcu_unit
            endif
         endif
      loop
   endif
   
   <-gcu_unit

# Function :GetUnitTypePriority
# Returns values defined by you for unit value.
# Defaults to 1.
# Notation: s1 - f1
# eg. "COLLECTOR" @GetUnitTypePriority ->priority
:GetUnitTypePriority
   ->cp_type
   1 ->cp_rank
   -?cp_types and(-?cp_ranks) if
      <-cp_types GetListCount 0 do
         <-cp_types I GetListElement eq(<-cp_type) if
            <-cp_ranks I GetListElement asfloat
            return
         endif
      loop
   endif
   <-cp_rank

# Function :ClearUnitTypePriorities
# Removes all defined unit type priorities.
# Notation: -
# eg. @ClearUnitTypePriorities
:ClearUnitTypePriorities
   --cp_ranks
   --cp_types

# Function :AddUnitTypePriority
# This function an object, then a list and returns a boolean value.
# The higher the unit priority, the more it is favoured by :GetClosestUnitToCoords
# Notation: s1 f1 -
# eg. "NULLIFIER" 5 @AddUnitTypePriority
:AddUnitTypePriority
   asfloat ->cp_rank
   ->cp_type
   -?cp_rank not -?cp_types not or if
      CreateList ->cp_types
      CreateList ->cp_ranks
   endif
   <-cp_types <-cp_type AppendToList
   <-cp_ranks <-cp_rank AppendToList
   
# Function :DoesListContain
# This function an object, then a list and returns a boolean value.
# Notation: L1 n1 - b1
# eg. <-myList <-myValue @DoesListContain ->contains
:DoesListContain
   ->dl_value
   ->dl_list
   false ->dl_contained

   <-dl_list GetListCount 0 do
      <-dl_list I GetListElement eq(<-dl_value) if
         true ->dl_contained
         break
      endif
   loop

   <-dl_contained
   
# Function :UnitCoords
# Simple convenience method. Takes a unit and returns the coordinates.
# 'CurrentCoords' and 'self @UnitCoords' are equivalent.
# Notation: n1 - x y
# eg. <-myUnitID @UnitCoords ->unitX ->unitY
:UnitCoords
   asint ->uc_u
   <-uc_u CONST_COORDX GetUnitAttribute
   <-uc_u CONST_COORDY GetUnitAttribute
[close]

Make sure you go to the part 2 of this post! (I ran out of room and it did not let me put any thing else in this post :P ) Part 2 of the post!
Also i used the texture in that was already in the map for the bomber so sorry if you wanted the texture for it.  :P
CW4 hype!!

rer24

We shall end the infinite cycle of madness!

Nicant

CW4 hype!!

Nicant

CW4 hype!!

rer24

We shall end the infinite cycle of madness!

rer24

Just reminding you to put the sprayer and guppy scripts in here. Thanks!
We shall end the infinite cycle of madness!

Nicant

Quote from: rer24 on November 29, 2015, 02:19:04 PM
Just reminding you to put the sprayer and guppy scripts in here. Thanks!
Ok! I forgot to because i got caught up into something else.
CW4 hype!!