User Tools

Site Tools


crpl:crpltutorial:easycrpl

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
crpl:crpltutorial:easycrpl [2015/04/13 09:51] – created Karsten75crpl:crpltutorial:easycrpl [2019/05/05 13:13] (current) – Small change for code highlighting Karsten75
Line 1: Line 1:
-==== EasyCRPL ====+<-[[cw3:creeper_world_3|CW3 Home]]<- [[crpl:start|CRPL Home]] 
 + 
 +===== EasyCRPL ====
 +== Version 1.1 == 
 + 
 + 
 +<code 4rpl>#============================================= 
 +# ===== :EasyCRPL: Collection by Telanir ===== 
 +# --VERSION: 1.1 
 +# CREDITS: 
 +# Big thanks to Knuckle Cracker (knucracker) for an amazing game and lots of well commented source! 
 +# Big thanks to Tyler21 for a contribution of Forcefield code using Field cells! 
 +
 +# Usage: Simply paste this script at the bottom of your 
 +# project to get the full benefits of the pre-written code. 
 +# You can also just copy-paste parts of this you need. 
 +
 +# EasyCRPL is a collection of scripts from various community 
 +# projects, members, and maps that have been created by myself 
 +# or modified to meet a more generic purpose. 
 +
 +# ----- 
 +# A List of all available functions and their notation: 
 +# @FunctionName: order of input - order of output with last object on top of the stack 
 +# x - X coordinate 
 +# y - Y coordinate 
 +# n - numerical value 
 +# i - integer value 
 +# f - float value 
 +# b - boolean value 
 +# s - string value 
 +# u - unit id, integer value 
 +# L - list 
 +# * - any value 
 +
 +# NOTE: Non-pixel coords are flipped vertically 
 +# with (0,0) being top-left, whereas pixel (0,0) 
 +# is the bottom left. 
 +
 +# -- Special Code -- 
 +# This code can be used at any time if it is in your 
 +# script, and generally comes in blocks of functions. 
 +# Forcefield Manager: A custom forcefield manager that helps safely create functional forcefields. 
 +# @SetForcefieldProperties:  
 +
 +# List-Builder: Two simple functions that will safely create a list without touching the stack. 
 +# @BeginList [* *...] @BuildList 
 +# @DoesListContain: L1 * - b1 
 +#  
 +# Pre-Built Beam: A beam with a customizable color, alpha, and width. 
 +# @SetBeamProperties: s1 i1 i2 i3 i4 i5 i6 f1 - 
 +# @AnimateBeam:
 +# @SetBeamTarget: u - 
 +# @TargetBeam: x y b1 - 
 +# @DestroyBeam:
 +
 +# -- Various Convenience Methods -- 
 +
 +# SPECIAL METHODS, READ COMMENTS ABOVE CODE 
 +# -- 
 +# @GetClosestUnit: x y f1 L1 - u 
 +# @GetAllUnits: x y f1 L1 - [u1 u2...]i1 
 +# @CRPLMatchesValue: u s1 * - b1 
 +# -- 
 +
 +# @GetCreeperInRadius: x y f1 - f2 
 +# @SetImageAlpha: s1 i1 - 
 +# @TerrainAccessible: x y i1 - b1 
 +# @AreaOccupied: x y i1 - b1 
 +# @AddOccupy: x y i1 b1 - 
 +# -- Cell-Related Code -- 
 +# @UnitCoords: u - x y 
 +# @MovePosition: x y x2 y2 f1 f2 - x y 
 +# @GetVector: f1 f2 - x y 
 +# @NormalizeVector: x y - x y 
 +# @GetLength: x y - f1 
 +# @GetAngle: x y x2 y2 - f1 
 +# @RotateToAngle: x y x2 y2 f1 f2 - b1 f1 
 +# @IsPointOnMap: x y - b1 
 +# -- Pixel-Related Code -- 
 +# @UnitPixelCoords: u - x y 
 +# @SetPixelCoords: x y - 
 +# @MovePixelPosition: x y x2 y2 f1 f2 - x y 
 +# @GetPixelVector: f1 f2 - x y 
 +# @GetPixelAngle: x y x2 y2 - f1 
 +# @RotateToPixelAngle: x y x2 y2 f1 f2 - b1 f1 
 +
 +# Wiki CRPL Reference: http://knucklecracker.com/wiki/doku.php?id=crpl:crplreference 
 +#============================================= 
 + 
 +#====================================== 
 +#======== FORCEFIELD MANAGER ========== 
 +#====================================== 
 +  
 +# Sets the Forcefield properties. 
 +# Order goes: RANGE CPUSH ACPUSH 
 +# The higher the PUSH values the more the 
 +# forcefield repels from the epicenter. 
 +# Values are in millionths per unit of creeper moved. 
 +# Notation: f1 i1 i2 - 
 +# 12.5 100000 100000 @SetForcefieldProperties 
 +:SetForcefieldProperties 
 + -?FF_INITIALIZED not if 
 + ->FF_ACPUSH 
 + ->FF_CPUSH 
 + ->FF_RANGE 
 + true ->FF_INITIALIZED 
 + -?FF_X or(-?FF_Y) not if 
 + CurrentCoords ->FF_Y ->FF_X 
 + endif 
 + endif 
 +  
 +# Function :SetForcefieldCoords 
 +# Sets the coordinates of future forcefields. 
 +# If a previous forcefield was present it removes 
 +# the old one and creates a new one. 
 +# Notation: x y - 
 +# e.g. CurrentCoords @SetForcefieldCoords 
 +:SetForcefieldCoords 
 + -?FORCEFIELD_AVAILABLE if 
 + @WipeForcefield 
 + ->FF_Y 
 + ->FF_X 
 + @CreateForcefield 
 + else 
 + ->FF_Y 
 + ->FF_X 
 + endif 
 + 
 +# Function :OverrideWipeForcefieldProperties 
 +# By default initializing forcefield properties locks the 
 +# method and helps prevent leftover forcefields. 
 +:OverrideWipeForcefieldProperties 
 + @WipeForcefield 
 + 0 ->FF_ACPUSH 
 + 0 ->FF_CPUSH 
 + 0 ->FF_RANGE 
 + --FF_INITIALIZED 
 + 
 +# Function :WipeForcefield 
 +# Safe method to wipe forcefield, if there is none it will be ignored. 
 +# Notation: - 
 +# e.g. @WipeForcefield 
 +:WipeForcefield 
 + -?FF_INITIALIZED if 
 + -?FORCEFIELD_AVAILABLE if 
 + --FORCEFIELD_AVAILABLE 
 + @ModifyForcefield(<-FF_X <-FF_Y <-FF_RANGE <-FF_CPUSH neg <-FF_ACPUSH neg) 
 + endif 
 + endif 
 + 
 +# Function :CreateForcefield 
 +# Creates a Forcefield with the initialized parameters. 
 +# Notation: - 
 +# e.g. @CreateForcefield 
 +:CreateForcefield 
 + -?FF_INITIALIZED if 
 + -?FORCEFIELD_AVAILABLE not if 
 + true ->FORCEFIELD_AVAILABLE 
 + @ModifyForcefield(<-FF_X <-FF_Y <-FF_RANGE <-FF_CPUSH <-FF_ACPUSH) 
 + endif 
 + endif 
 +  
 +# Major props to Tyler, thanks for helping make forcefields work as intended. 
 +# Function :ModifyForcefield 
 +# Adds input creeper and anti-creeper to surrounding field cells with 
 +# strength decreasing with distance form the epicenter. 
 +# Negative values will modify the forces in opposite directions and 0 will change nothing. 
 +# Notation: x y f1 i1 i2 - 
 +# e.g. CurrentCoords 10 100000 -100000 @ModifyForcefield 
 +:ModifyForcefield 
 +neg ->SF_ACPUSH 
 +neg ->SF_CPUSH 
 +asfloat ->SF_RANGE # float-value is required for the div operations 
 +->SF_Y 
 +->SF_X 
 + 
 +<-SF_RANGE 2 mul 1 add 0  
 +do 
 + <-SF_RANGE 2 mul 1 add 0  
 + do 
 + <-SF_X J add <-SF_RANGE sub ->xCell 
 + <-SF_Y I add <-SF_RANGE sub ->yCell 
 +  
 + <-xCell neq(<-SF_X) or(<-yCell neq(<-SF_Y)) if 
 + <-SF_X <-SF_Y <-xCell <-yCell Distance ->SF_DIST 
 + <-SF_DIST lte(<-SF_RANGE) if 
 + <-SF_DIST neg add(<-SF_RANGE) div(<-SF_RANGE) mul(0.7) add(0.3) ->SF_MOD 
 + <-SF_ACPUSH mul(<-SF_MOD) asint ->SF_ACPUSHMOD 
 + <-SF_CPUSH mul(<-SF_MOD) asint ->SF_CPUSHMOD 
 + @GetVector(@GetAngle(<-xCell <-yCell <-SF_X <-SF_Y) <-SF_CPUSHMOD) ->cRLCell ->cUDCell 
 + @GetVector(@GetAngle(<-xCell <-yCell <-SF_X <-SF_Y) <-SF_ACPUSHMOD) ->acUDCell ->acRLCell 
 + GetFieldCell(<-xCell <-yCell) ->oacRLCell ->oacUDCell ->ocRLCell ->ocUDCell 
 + SetFieldCell(<-xCell <-yCell <-cUDCell add(<-ocUDCell) <-cRLCell add(<-ocRLCell) <-acUDCell add(<-oacUDCell) <-acRLCell add(<-oacRLCell)) # n1, n2, n3 and n4 are for creeper U(+)/D(-), creeper R(+)/L(-), AC U/D and AC R/L 
 + endif 
 + endif 
 + loop 
 +loop 
 + 
 +#====================================== 
 +#=========== LIST-BUILDER ============= 
 +#====================================== 
 + 
 +# How to use: 
 +# If you ever need to quickly build a list of X units then 
 +# you can use these two functions to do it in one line. 
 +# You can use this in conjuction with @DoesListContain listed in the index. 
 +# e.g. @BeginList "COLLECTOR" "RELAY" "COMMANDNODE" "PULSECANNON" "MORTAR" @BuildList ->newList 
 + 
 +:BeginList 
 + StackSize ->BL_I 
 +  
 +:BuildList 
 + StackSize ->BL_M 
 + CreateList ->BL_L 
 + <-BL_M <-BL_I do 
 + ->BL_O 
 + <-BL_L <-BL_O PrependToList 
 + loop 
 + <-BL_L 
 + 
 +# 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 
 + 
 +#====================================== 
 +#=========== PRE-BUILT BEAM =========== 
 +#====================================== 
 +# How to use: 
 +# Copy the 4 beam methods into your code. 
 +# @AnimateBeam needs to run /every/ script invocation. 
 +# Use @SetBeamProperties at any time to change the 
 +# appearence of the beam. 
 +# Use @TargetBeam at any time to focus the beam on something, 
 +# if it is moving, keep calling @TargetBeam. 
 +# When finished, call @DestroyBeam and the beam will vanish! 
 +
 +# Warning: DO NOT USE @BeamInit! 
 + 
 +# Function: :SetBeamProperties 
 +# Sets the properties of the beam. 
 +# Alpha, red, green, and blue range from 0 - 255  
 +# With 0 being transparent and 255 being opaque 
 +# The string is the "Beam" item, it can be found here: 
 +# http://knucklecracker.com/wiki/doku.php?id=crpl:custom_image_repository 
 +# The two integers after the image name are the indexes for 
 +# the damage icons. If your "Damage 0" is at "Custom1" then write 1, 
 +# then if your "Damage 3" is at "Custom4" then write 4 after. 
 +# Notation: s1 i1 i2 i3 i4 i5 i6 f1 - 
 +# eg. "Custom0" 1 4 255 0 0 255 1.5 @SetBeamProperties 
 +:SetBeamProperties 
 + ->BM_SCALEY 
 + ->BM_ALPHA 
 + ->BM_BLUE 
 + ->BM_GREEN 
 + ->BM_RED 
 + ->BM_DAMAGEINDEXEND 
 + ->BM_DAMAGEINDEXSTART 
 + ->BM_IMAGE 
 + true ->BM_SET 
 + -?BM_ACTIVE if 
 + @BeamInit 
 + endif 
 + 
 +# Function: :AnimateBeam 
 +# Animates the beam and the explosion animation. 
 +# The boolean indicates whether it is a pixel position. 
 +# Notation: - 
 +# eg. @AnimateBeam 
 +:AnimateBeam 
 + -?BM_ACTIVE and(-?BM_SET) if 
 + if(<-BM_TOG) 
 + <-BM_X <-BM_Y ->BM_PY ->BM_PX 
 + else 
 + <-BM_X <-BM_Y CellToPixel ->BM_PY ->BM_PX 
 + endif 
 +  
 + -?BM_T if 
 + GetUnitType(<-BM_T) ->BM_TT 
 + if(<-BM_TT eq("BOMBERAIR") or(<-BM_TT eq("STRAFERAIR"))) 
 + <-BM_PY add(27) ->BM_PY 
 + endif 
 + if(<-BM_TT eq("GUPPYAIR")) 
 + <-BM_PY add(10) ->BM_PY 
 + endif 
 + endif 
 +  
 + self CONST_PIXELCOORDX GetUnitAttribute ->BM_SX 
 + self CONST_PIXELCOORDY GetUnitAttribute ->BM_SY 
 + 
 + <-BM_PX <-BM_SX sub ->BM_DX 
 + <-BM_PY <-BM_SY sub ->BM_DY 
 + <-BM_DY <-BM_DX atan2 ->BM_A 
 + <-BM_SX <-BM_SY <-BM_PX <-BM_PY Distance ->BM_D 
 + <-BM_D 24 div ->BM_SCX 
 +  
 + <-BM_DX 2 div ->BM_PPX 
 + <-BM_DY 2 div ->BM_PPY  
 +  
 + SetImagePosition(self "beam" <-BM_PPX <-BM_PPY -0.1)  
 + SetImageScaleX(self "beam" <-BM_SCX) 
 + SetImageRotation(self "beam" <-BM_A)  
 +  
 + <-BM_DAMAGEINDEXSTART neq(-1) and(<-BM_DAMAGEINDEXEND neq(-1)) if 
 + <-B_IMG add(1) ->B_IMG 
 + <-B_IMG <-BM_DAMAGEINDEXSTART lt if <-BM_DAMAGEINDEXSTART ->B_IMG endif 
 + <-B_IMG <-BM_DAMAGEINDEXEND gt if <-BM_DAMAGEINDEXSTART ->B_IMG endif 
 + SetImage(self "damage" concat("Custom" <-B_IMG)) 
 + SetImagePosition(self "damage" <-BM_DX <-BM_DY -0.1)  
 + endif 
 + endif 
 +  
 +# Function: :SetBeamTarget 
 +# The purpose of this function is for the main 
 +# @AnimateBeam function to be aware if the target 
 +# is a certain type of unit. It will automatically 
 +# make corrections for flying units. 
 +# Use -1 if the target is a non-unit. 
 +:SetBeamTarget 
 + ->BT_T 
 + <-BT_T eq(-1) if 
 + --BM_T 
 + else 
 + <-BT_T ->BM_T 
 + endif 
 + 
 +# Function: :TargetBeam 
 +# Focuses the beam on a target location. 
 +# If a beam does not exist, makes one. 
 +# The boolean value indicates whether or not the 
 +# new position is a pixel position. 
 +# IF THE ENEMY IS AN 'AIR' SUFFIX ENEMY (aka STRAFERAIR) 
 +# YOU MUST USE @SetBeamTarget TO CORRECT THE Y-OFFSET. 
 +# Notation: x y b1 - 
 +# eg. @UnitCoords(<-targetUnit) false @TargetBeam 
 +# eg. 100 100 true @TargetBeam 
 +:TargetBeam 
 + ->BM_TOG 
 + ->BM_Y 
 + ->BM_X 
 + -?BM_SET not if 
 + # Set some default values. 
 + "Custom0" 1 4 255 0 0 255 1.5 @SetBeamProperties 
 + endif 
 + <-BM_ACTIVE not if 
 + true ->BM_ACTIVE 
 + @BeamInit 
 + endif 
 + 
 +# Function: :DestroyBeam 
 +# Removes the active beam, if there is one. 
 +# Notation: - 
 +# eg. @DestroyBeam 
 +:DestroyBeam 
 + -?BM_ACTIVE if 
 + --BM_ACTIVE 
 + self "beam" "NONE" SetImage 
 + self "damage" "NONE" SetImage 
 + endif 
 +  
 +# Function: :BeamInit 
 +# Used by the Beam script to update Beam appearance. 
 +:BeamInit 
 + self "beam" <-BM_IMAGE SetImage 
 + self "beam" <-BM_RED <-BM_GREEN <-BM_BLUE <-BM_ALPHA SetImageColor 
 + self "beam" <-BM_SCALEY SetImageScaleY 
 + self "beam" -0.04 SetImagePositionZ 
 + 
 +#====================================== 
 +#==== VARIOUS CONVENIENCE METHODS ===== 
 +#====================================== 
 + 
 +# Function :GetClosestUnit 
 +# WARNING: use this convenience function sparingly, tens of CRPL Cores 
 +# running this all at once every frame will slow the game down significantly. 
 +
 +# This function uses a flexible algorithm to filter 
 +# units within a certain distance and retrieve the one 
 +# closest to the position given to the function. 
 +# It requires a position, a maximum distance, and an 
 +# instruction list. 
 +
 +# The instruction list can contain multiple objects (but at least one is needed). 
 +# An instruction follows this format: "unittype:parameter1,parameter2,parameter3=value,parameter4=value..." 
 +# All applicable unit types can be found on: 
 +# https://knucklecracker.com/wiki/doku.php?id=crpl:docs:getunittype 
 +
 +# The following parameters are acceptable: 
 +# LANDED BUILT RANK=value 
 +# LANDED and BUILT can accept modifiers. * means __either__, - means NOT, no modifier means IS 
 +# If the parameter is none of the three, and the unit type is defined as "CRPLCORE" the assumed 
 +# parameter type is a CRPLCore variable which is defined like so: myVar=myVal 
 +
 +# The unit type can be substituted by ALL which will affect all instructions, ALL must be in the 
 +# beginning of the list or it will be assumed to be a unit type.  
 +# ALL does not accept RANK or script variables as parameters. 
 +#  
 +# == EXAMPLE == 
 +# @BeginList "ALL:BUILT" "COLLECTOR" "relay:*built,rank=0.5" "pulsecannon:-landed,rank=2" "crplcore:emit=3.5" @BuildList ->instructions 
 +# CurrentCoords 50 <-instructions @GetClosestUnit ->unit 
 +#  
 +# Explanation: All of the instructions within the list are acceptable. The only time the parameters are 
 +# case sensitive is when defining script parameters. CONST_ISLANDED and CONST_ISBUILDING do not affect CRPLCores. 
 +# According to these instructions, to get the closest unit within a range of 50 we will accept any built collector, 
 +# any relay that is built or not but we give the a half the normal rank so the algorithm will treat them as if 
 +# they are twice the distance away from anything else in the way. A collector and relay at the same distance will 
 +# always return the collector. Next we prioritize any flying pulse cannon and override the ALL parameter, we 
 +# then also look for any CRPLCores we made that had a script variable of "emit" that is equal to 3.5. 
 +
 +# Notation: x y f1 L1 - u 
 +# e.g. CurrentCoords 50 <-instructionList @GetClosestUnit ->unit 
 +:GetClosestUnit 
 + ->un_list 
 + asfloat ->un_dist 
 + asfloat ->un_y 
 + asfloat ->un_x 
 +  
 + -1 ->un_unit 
 + -1 ->un_udist 
 +  
 + <-un_x <-un_y <-un_dist <-un_list @GetAllUnits ->un_count 
 + <-un_count neq0 if 
 + <-un_count 0 do 
 + ->un_temp 
 + <-un_temp GetUnitType ->un_type 
 + # GET INSTRUCTION FOR THIS UNIT TYPE 
 + <-un_instructions GetListCount 0 do 
 + <-un_instructions GetListElement(I) ->un_inst 
 + # found correct instruction 
 + <-un_inst StartsWith(<-un_type) if 
 + <-un_inst Split(" ") ->un_ilist 
 + <-un_ilist GetListElement(3) asfloat ->une_rank 
 +  
 + # now we apply the priority and get the closest unit 
 + <-un_x <-un_y @UnitCoords(<-un_temp) Distance div(<-une_rank) ->un_tdist 
 + <-un_tdist lt(<-un_udist) or(<-un_udist eq(-1)) if 
 + <-un_tdist ->un_udist 
 + <-un_temp ->un_unit 
 + endif 
 + break 
 + endif 
 + loop 
 + loop 
 + endif 
 + <-un_unit 
 + 
 +# Function :GetAllUnits 
 +# Grabs all units of specified instruction within a radius of 
 +# a given point. Read :GetClosestUnit for more info. 
 +# Notation: x y f1 L1 - [u1 u2...]i1 
 +# e.g.  
 +# CurrentCoords 50 <-instructionList @GetAllUnits ->unitCount 
 +# <-unitCount 0 do 
 +# # code here 
 +# loop 
 +:GetAllUnits 
 + ->un_list 
 + asfloat ->un_dist 
 + asfloat ->un_y 
 + asfloat ->un_x 
 +  
 + CreateList ->un_units 
 + --un_all_landed 
 + --un_all_built 
 +  
 + <-un_list GetListCount gt(0) if 
 + <-un_list GetListElement(0) ToUpper ->un_elm 
 + <-un_elm StartsWith("ALL") if 
 + <-un_elm StringReplace("ALL:" "") ->un_elm 
 + <-un_elm Split(",") ->un_values 
 + <-un_values GetListCount 0 do 
 + <-un_values GetListElement(I) ->un_elm 
 + <-un_elm ToUpper EndsWith("LANDED") if 
 + <-un_elm StartsWith("-") if 
 + false ->un_all_landed 
 + else 
 + true ->un_all_landed 
 + endif 
 + endif 
 + <-un_elm ToUpper EndsWith("BUILT") if 
 + <-un_elm StartsWith("-") if 
 + false ->un_all_built 
 + else 
 + true ->un_all_built 
 + endif 
 + endif 
 + loop 
 + endif 
 + endif 
 +  
 + CreateList ->un_instructions 
 + <-un_list GetListCount 0 do 
 + "" ->compile_task 
 + "" ->un_type 
 + 1.0 ->rank 
 +  
 + --un_landed_req 
 + --un_built_req 
 +  
 + -?un_all_landed if <-un_all_landed ->un_landed_req endif 
 + -?un_all_built if <-un_all_built ->un_built_req endif 
 +  
 + <-un_list GetListElement(I) ->un_elm 
 + <-un_elm Split(":") ->un_lelm 
 +  
 + <-un_lelm GetListElement(0) ToUpper ->un_type 
 +  
 + <-un_type ->compile_task 
 + "" ->append_task 
 +  
 + <-un_lelm GetListCount gt(1) if 
 + <-un_lelm GetListElement(1) ->un_elm 
 + <-un_elm StringReplace(<-un_type concat(":") "") ->un_elm 
 + <-un_elm Split(",") ->un_values 
 + <-un_values GetListCount 0 do 
 + <-un_values GetListElement(I) ->un_elm 
 + true ->definingVariable 
 + <-un_elm ToUpper EndsWith("LANDED") if 
 + <-un_elm StartsWith("-") if 
 + false ->un_landed_req 
 + else 
 + true ->un_landed_req 
 + endif 
 + <-un_elm StartsWith("*") if 
 + --un_landed_req 
 + endif 
 + false ->definingVariable 
 + endif 
 + <-un_elm ToUpper EndsWith("BUILT") if 
 + <-un_elm StartsWith("-") if 
 + false ->un_built_req 
 + else 
 + true ->un_built_req 
 + endif 
 + <-un_elm StartsWith("*") if 
 + --un_built_req 
 + endif 
 + false ->definingVariable 
 + endif 
 + <-un_elm ToUpper StartsWith("RANK") if 
 + <-un_elm Split("=") ->un_rankl 
 + <-un_rankl GetListElement(1) asfloat ->rank 
 + false ->definingVariable 
 + endif 
 +  
 + <-definingVariable and(<-un_type eq("CRPLCORE")) if 
 + <-un_elm Split("=") ->un_varl 
 + <-append_task concat(" ") concat(<-un_varl GetListElement(0)) concat(" ") concat(<-un_varl GetListElement(1) StringReplace("true" "1") StringReplace("false" "0")) ->append_task 
 + endif 
 + loop 
 + endif 
 + # 2 means not applicable 
 + <-compile_task concat(" ") ->compile_task 
 + -?un_built_req if <-compile_task concat(<-un_built_req) else <-compile_task concat("2") endif ->compile_task 
 + <-compile_task concat(" ") ->compile_task 
 + -?un_landed_req if <-compile_task concat(<-un_landed_req) else <-compile_task concat("2") endif ->compile_task 
 + <-compile_task concat(" ") ->compile_task 
 + <-compile_task concat(<-rank) ->compile_task 
 + <-compile_task concat(<-append_task) ->un_instruction 
 + <-un_instructions AppendToList(<-un_instruction) 
 + loop 
 +  
 + <-un_x <-un_y <-un_dist false GetAllUnitsInRange ->un_count 
 + <-un_count neq0 if 
 + <-un_count 0 do 
 + ->un_temp 
 + <-un_temp neq(self) if 
 + <-un_temp GetUnitType ->un_type 
 + # GET INSTRUCTION FOR THIS UNIT TYPE 
 + <-un_instructions GetListCount 0 do 
 + <-un_instructions GetListElement(I) ->un_inst 
 + <-un_inst StartsWith(<-un_type) if 
 + <-un_inst Split(" ") ->un_ilist 
 + --une_built 
 + --une_landed 
 + # 0 is the type 
 + <-un_ilist GetListElement(1) ->une_t <-une_t neq(2) if <-une_t ->une_built endif 
 + <-un_ilist GetListElement(2) ->une_t <-une_t neq(2) if <-une_t ->une_landed endif 
 + <-un_ilist GetListElement(3) asfloat ->une_rank 
 +  
 + false ->skip 
 + <-un_type eq("CRPLCORE") if 
 + 4 ->unc_index 
 + while <-unc_index lt(<-un_ilist GetListCount) repeat 
 + <-un_ilist GetListElement(<-unc_index) ->unc_var 
 + <-unc_index add(1) ->unc_index 
 + <-un_ilist GetListElement(<-unc_index) ->unc_val 
 + <-unc_index add(1) ->unc_index 
 + <-un_temp <-unc_var <-unc_val @CRPLMatchesValue ->unc_match 
 + <-unc_match not if 
 + true ->skip 
 + endif 
 + endwhile 
 + endif 
 + not(<-skip) if 
 + # MATCH VALUES 
 + <-un_type @BuildApplies if 
 + -?une_built if GetUnitAttribute(<-un_temp CONST_ISBUILDING) eq(<-une_built) ->skip endif 
 + endif 
 + <-un_type @LandedApplies if 
 + -?une_landed and(not(<-skip)) if GetUnitAttribute(<-un_temp CONST_ISLANDED) neq(<-une_landed) ->skip endif 
 + endif 
 + not(<-skip) if 
 + <-un_units AppendToList(<-un_temp) 
 + endif 
 + endif 
 + break 
 + endif 
 + loop 
 + endif 
 + loop 
 + endif 
 + <-un_units GetListCount 0 do 
 + <-un_units GetListElement(I) 
 + loop 
 + <-un_units GetListCount 
 +  
 +:BuildApplies 
 + ->ba_type 
 + # list of what DOESN'
 + -?ba_applies not if 
 + @BeginList 
 + "GUPPYAIR" "BOMBERAIR" "STRAFERAIR" "CRPLCORE" "EMITTER" "SPORETOWER" "RUNNER" "RUNNERNEST" 
 + "AETOWER" "INHIBITOR" "POWERZONE" "OREDEPOSIT" "RESOURCEPACK" "TOTEM" "AOO" "SHIELDKEY" 
 + "MESSAGEARTIFACT" 
 + @BuildList ->ba_applies 
 + endif 
 + not(<-applies @DoesListContain(<-ba_type)) 
 + 
 +:LandedApplies 
 + ->la_type 
 + # list of what DOES 
 + -?la_applies not if 
 + @BeginList 
 + "TERP" "SHIELD" "PULSECANNON" "MORTAR" "SPRAYER" "BEAM" "SNIPER" 
 + @BuildList ->la_applies 
 + endif 
 + <-la_applies @DoesListContain(<-la_type) 
 +  
 +# Function :CRPLMatchesValue 
 +# Takes a unit, a value and a variable and determines 
 +# without a given script whether or not the CRPLCore 
 +# has a variable with that value. 
 +# Notation: u s1 * - b1 
 +# e.g. self "myVar" 5 @CRPLMatchesValue ->matchesValue 
 +:CRPLMatchesValue 
 + ->uv_val 
 + ->uv_var 
 + ->uv_unit 
 + false ->uv_found 
 +  
 + <-uv_var <-uv_val GetCoresWithVar ->uv_count 
 + <-uv_count neq(0) if 
 + <-uv_count 0 do 
 + ->uv_temp 
 + <-uv_temp eq(<-uv_unit) if 
 + true ->uv_found 
 + endif 
 + loop 
 + endif 
 + <-uv_found 
 + 
 +# Function :GetCreeperInRadius 
 +# Returns the SUM of all creeper in a certain square 
 +# around an origin. If there is anti-creeper present this 
 +# value may go into the negatives. 
 +# Notation: x y f1 - f2 
 +# eg. CurrentCoords 1 @GetCreeperInRadius ->sumcreepergrid3x3 
 +:GetCreeperInRadius 
 + ->CR_RAD 
 + ->CR_Y 
 + ->CR_X 
 + 0 ->CR_C 
 + <-CR_RAD mul(2) add(1) ->CR_LENGTH 
 +  
 + <-CR_LENGTH 0 do 
 + <-CR_LENGTH 0 do 
 + <-CR_Y I add <-CR_RAD sub ->CR_FY 
 + <-CR_X J add <-CR_RAD sub ->CR_FX 
 + <-CR_FX <-CR_FY GetCreeper add(<-CR_C) ->CR_C 
 + loop 
 + loop 
 +  
 + <-CR_C 
 +  
 +# Function: :SetImageAlpha 
 +# Sets the alpha of the specified image for self. 
 +# Alpha ranges from 0 - 255 with 0 transparent and 255 opaque 
 +# Notation: s1 i1 - 
 +# eg. "main" 100 @SetImageAlpha 
 +:SetImageAlpha 
 +asint ->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 :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 
 + else 
 + 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 :OccupyArea 
 +# Safety net for @AddOccupy to prevent bad areas. 
 +# Notation: x y f1 - 
 +# eg. <-targetX <-targetY 1 @OccupyArea # this would occupy an area of land 
 +# #in a 3x3 grid around the central point, useful for flying units looking to land 
 +:OccupyArea 
 + -?OA_OCCUPIED not if 
 + # First occupation is legal. 
 + ->OA_RAD 
 + ->OA_Y 
 + ->OA_X 
 +  
 + <-OA_X <-OA_Y <-OA_RAD true @AddOccupy 
 + # Does occupy, is initialized. 
 + true ->OA_OCCUPIED 
 + else 
 + <-OA_OCCUPIED if 
 + # If occupying land already, disable occupation for re-assigning. 
 + <-OA_X <-OA_Y <-OA_RAD false @AddOccupy 
 + endif 
 + ->OA_RAD 
 + ->OA_Y 
 + ->OA_X 
 + <-OA_OCCUPY if 
 + <-OA_X <-OA_Y <-OA_RAD true @AddOccupy 
 + endif 
 + <-OA_OCCUPY ->OA_OCCUPIED 
 + endif 
 + 
 +:ReleaseOccupiedArea 
 + <-OA_OCCUPIED if 
 + # If occupying land already, disable occupation. 
 + <-OA_X <-OA_Y <-OA_RAD false @AddOccupy 
 + false ->OA_OCCUPIED 
 + 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 1 false @AddOccupy #this would allow another unit to land 
 +# #in a 3x3 grid around the central point. 
 +: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 
 + 
 +#====================================== 
 +#========= CELL RELATED CODE ========== 
 +#====================================== 
 + 
 +# 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 :SetUnitCoords 
 +# Simple convenience method. Sets current units pixel coordinates. 
 +# Notation: x y - 
 +# eg. x y u @SetPixelCoords 
 +:SetUnitCoords 
 + ->sp_unit 
 + asfloat ->sp_y 
 + asfloat ->sp_x 
 + SetUnitAttribute(<-sp_unit CONST_COORDX <-sp_x) 
 + SetUnitAttribute(<-sp_unit CONST_COORDY <-sp_y) 
 + 
 +# Function :MovePosition 
 +# Uses the given position, angle, and speed and returns a new position. 
 +# The target position is used for correctional purposes so that it doesn't overstep. 
 +# If you want to ignore the correctional functionality set the target coordinates to -5000 -5000. 
 +# Notation: x y x2 y2 f1 f2 - x y 
 +# eg. CurrentCoords <-targetX <-targetY <-angle 1.5 @MovePosition ->y ->x 
 +:MovePosition 
 + asfloat ->mp_ms 
 + asfloat ->mp_an 
 + asfloat ->mp_tY 
 + asfloat ->mp_tX 
 + asfloat ->mp_pY 
 + asfloat ->mp_pX 
 + 
 + <-mp_an <-mp_ms @GetVector ->mp_vY ->mp_vX 
 + 
 + <-mp_pX <-mp_tX sub <-mp_pY <-mp_tY sub @GetLength <-mp_ms lt if 
 + <-mp_tX 
 + <-mp_tY 
 + else 
 + <-mp_pX <-mp_vX add 
 + <-mp_pY <-mp_vY add 
 + endif 
 + 
 +# 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. 
 +# Negative distances will go beyond the target. 
 +# Notation: x y x2 y2 f1 - x y 
 +# eg. CurrentPosition @GetUnitCoords(<-targetUnit) 10 @GetIntermediatePosition 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_vy ->gip_vx 
 + <-gip_tx <-gip_vx add 
 + <-gip_ty <-gip_vy 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 - x y 
 +# eg. <-angle 1.5 @GetVector ->y ->x 
 +:GetVector 
 + asfloat ->gv_vrsm 
 + asfloat ->gv_vrAngle 
 + 
 + <-gv_vrAngle sin ->gv_vrY 
 + <-gv_vrAngle cos ->gv_vrX 
 + <-gv_vrX <-gv_vrY @NormalizeVector ->gv_vrY ->gv_vrX 
 + <-gv_vrY <-gv_vrsm mul ->gv_vrY 
 + <-gv_vrX <-gv_vrsm mul ->gv_vrX 
 + <-gv_vrX 
 + <-gv_vrY neg 
 + 
 +# 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 - x y 
 +# eg. <-vectorX <-vectorY @NormalizeVector ->vectorY ->vectorX 
 +: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_nx 
 + <-nv_ny 
 + 
 +# 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 
 + 
 +# 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 
 + 
 +# 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 
 + 
 +#====================================== 
 +#========= PIXEL RELATED CODE ========= 
 +#====================================== 
 + 
 +# Function :UnitPixelCoords 
 +# Simple convenience method. Takes a unit and returns the pixel coordinates. 
 +# 'CurrentPixelCoords' and 'self @UnitPixelCoords' are equivalent. 
 +# Notation: u - x y 
 +# eg. <-myUnitID @UnitCoords ->unitY ->unitX 
 +:UnitPixelCoords 
 + asint ->uc_u 
 + <-uc_u CONST_PIXELCOORDX GetUnitAttribute 
 + <-uc_u CONST_PIXELCOORDY GetUnitAttribute 
 +  
 +# Function :SetUnitPixelCoords 
 +# Simple convenience method. Sets current units pixel coordinates. 
 +# Notation: u x y - 
 +# eg. <-unit 10 10 @SetPixelCoords 
 +:SetUnitPixelCoords 
 + asfloat ->sp_y 
 + asfloat ->sp_x 
 + ->sp_unit 
 + SetUnitAttribute(<-sp_unit CONST_PIXELCOORDX <-sp_x) 
 + SetUnitAttribute(<-sp_unit CONST_PIXELCOORDY <-sp_y) 
 + 
 +# Function :SetPixelCoords 
 +# Simple convenience method. Sets current units pixel coordinates. 
 +# Notation: x y - 
 +# eg. x y @SetPixelCoords 
 +:SetPixelCoords 
 + asfloat ->sp_y 
 + asfloat ->sp_x 
 + SetUnitAttribute(self CONST_PIXELCOORDX <-sp_x) 
 + SetUnitAttribute(self CONST_PIXELCOORDY <-sp_y) 
 + 
 +# Function :MovePixelPosition 
 +# Uses the given position, angle, and speed and returns a new position. 
 +# The target position is used for correctional purposes so that it doesn't overstep. 
 +# Notation: x y x2 y2 f1 f2 - x y 
 +# eg. CurrentPixelCoords <-targetX <-targetY <-angle 1.5 @MovePixelPosition ->y ->x 
 +:MovePixelPosition 
 + asfloat ->mp_ms 
 + asfloat ->mp_an 
 + asfloat ->mp_tY 
 + asfloat ->mp_tX 
 + asfloat ->mp_pY 
 + asfloat ->mp_pX 
 + 
 + <-mp_an <-mp_ms @GetPixelVector ->mp_vY ->mp_vX 
 + 
 + <-mp_pX <-mp_tX sub <-mp_pY <-mp_tY sub @GetLength <-mp_ms lt if 
 + <-mp_tX 
 + <-mp_tY 
 + else 
 + <-mp_pX <-mp_vX add 
 + <-mp_pY <-mp_vY add 
 + endif 
 + 
 +# Function :GetIntermediatePixelPosition 
 +# 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 - x y 
 +# eg. CurrentPixelPosition @GetUnitPixelCoords(<-targetUnit) 10 @GetIntermediatePosition QueueMove 
 +:GetIntermediatePixelPosition 
 + asfloat ->gip_dist 
 + asfloat ->gip_ty 
 + asfloat ->gip_tx 
 + asfloat ->gip_y 
 + asfloat ->gip_x 
 + 
 + <-gip_tx <-gip_ty <-gip_x <-gip_y @GetPixelAngle ->gip_a 
 + <-gip_a <-gip_dist @GetPixelVector ->gip_vy ->gip_vx 
 + <-gip_ty <-gip_vy add 
 + <-gip_tx <-gip_vx add 
 + 
 +# Function :GetPixelVector 
 +# 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 - x y 
 +# eg. <-angle 1.5 @GetPixelVector ->y ->x 
 +:GetPixelVector 
 + asfloat ->gv_vrsm 
 + asfloat ->gv_vrAngle 
 + 
 + <-gv_vrAngle sin ->gv_vrY 
 + <-gv_vrAngle cos ->gv_vrX 
 + <-gv_vrX <-gv_vrY @NormalizeVector ->gv_vrY ->gv_vrX 
 + <-gv_vrY <-gv_vrsm mul ->gv_vrY 
 + <-gv_vrX <-gv_vrsm mul ->gv_vrX 
 + <-gv_vrX 
 + <-gv_vrY 
 +  
 +# Function :GetPixelAngle 
 +# 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. CurrentPixelCoords <-targetUnit @UnitPixelCoords @GetPixelAngle ->angle 
 +:GetPixelAngle 
 + asfloat ->ga_targetY 
 + asfloat ->ga_targetX 
 + asfloat ->ga_curY 
 + asfloat ->ga_curX 
 + 
 + <-ga_targetX <-ga_curX sub ->ga_deltaX 
 + <-ga_targetY <-ga_curY sub ->ga_deltaY 
 + <-ga_deltaY <-ga_deltaX atan2 ->ga_desiredAngle 
 + <-ga_desiredAngle 
 + 
 +# Function :RotateToPixelAngle 
 +# 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. CurrentPixelCoords <-targetUnit @UnitPixelCoords <-angle 0.03 @RotateToPixelAngle ->newAngle ->isOnTarget 
 +:RotateToPixelAngle 
 + 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 
 + <-rta_targetY <-rta_curY 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 
 +</code>
crpl/crpltutorial/easycrpl.1428933115.txt.gz · Last modified: 2015/04/13 09:51 by Karsten75