# _CTemplate.crpl # Created on: 4/7/2015 10:00:27 PM # ------------------------------------------ # THIS IS THE DEFAULT CREEP DOCUMENT, COPY AND PASTE TO A FRESH .crpl # VERSION 1.1 # == CUSTOM VARS == # == 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:1.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:"Custom19" $BUILD_SOUND:"Misc7" $CREEPER_FOR_BUILD:20.0 $CREEP_TYPE:"UNSPECIFIED" # 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:150 # 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 # Beams deal a lot less damage so having a health modifier allows # player beams to deal a fairer amount of damage. Natural maximum # health is restored after landing. $FLIGHT_HEALTH_MODIFIER:0.25 # 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("This is a sample template! #Feel free to experiment and create something great.") #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 #custom code here :ConsistentAI #custom code here, runs every tick regardless of circumstance :SleepAI #custom code here :FlightAI #custom code here :built #custom code here :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 CurrentCoords @SetForcefieldCoords @CreateForcefield #<-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_Y ->C_FLIGHT_X <-C_FLIGHT_X <-C_FLIGHT_Y GetUnitAttribute(self CONST_CELLWIDTH) sub(1) div(2) @OccupyArea -?C_FLIGHT and(<-C_FLYING) if AbortMove <-C_FLIGHT_X <-C_FLIGHT_Y <-FLIGHT_SPEED QueueMove endif # 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 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 @WipeForcefield # Beams deal significantly less damage, therefore, lower health to # within acceptable parameters. self CONST_HEALTH dup2 GetUnitAttribute mul(<-FLIGHT_HEALTH_MODIFIER) SetUnitAttribute self CONST_MAXHEALTH dup2 GetUnitAttribute mul(<-FLIGHT_HEALTH_MODIFIER) 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 div(<-FLIGHT_HEALTH_MODIFIER) SetUnitAttribute self CONST_HEALTH dup2 GetUnitAttribute div(<-FLIGHT_HEALTH_MODIFIER) 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 @OverrideWipeForcefieldProperties @SetForcefieldProperties(<-CREEP_FORCEFIELD_RANGE <-CREEP_FORCEFIELD_CPUSH <-CREEP_FORCEFIELD_ACPUSH) CurrentCoords @SetForcefieldCoords @CreateForcefield #<-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 <-PLAYER_UNITS @GetClosestUnit ->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) @ReleaseOccupiedArea endif <-C_DIGITALIS_PRESENT not if CurrentCoords 0 SetDigitalis CurrentCoords false SetDigitalisGrowth endif @WipeForcefield @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 @SetForcefieldProperties @CreateForcefield else 0 ->CREEPER_FOR_BUILD endif @BeginList "ALL:BUILT,LANDED" "COMMANDNODE" "COLLECTOR" "RELAY" "REACTOR:rank=2" "OREMINE:rank=1.5" "SIPHON:rank=1.5" "TERP" "GUPPY" "PULSECANNON" "MORTAR" "STRAFER" "BOMBER" "SPRAYER" "NULLIFIER:rank=5" "BEAM" "SNIPER:rank=3" "SHIELD" "FORGE" "BERTHA" "THOR" @BuildList ->PLAYER_UNITS false ->IS_SLEEPING 0 ->C_SLEEP 300 ->C_SLEEPCHECK 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 PrependToList loop <-BL_L #====================================== #======== 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 #====================================== #==== VARIOUS CONVENIENCE METHODS ===== #====================================== # 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 :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'T -?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 :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 :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 # == END REQUIRED CREEP CODE == #