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! (https://knucklecracker.com/forums/index.php?topic=19643.0)) 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!
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!
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!
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
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
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
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! (https://knucklecracker.com/forums/index.php?topic=19487.0)
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
Just reminding you to put the sprayer and guppy scripts in here. Thanks!