Edit: Since I don't want to flood the forum with new threads for every question about CRPL that I can't answer myself I renamed this thread. Feel free to add your own questions to mine.
As soon as I try anything higher than a value of 1.3 for SetCreeperFlowRate (http://knucklecracker.com/wiki/doku.php?id=crpl:docs:setcreeperflowrate) the creeper is all over the map and randomly turning into anti-creeper. The same happens with SetCreeperFlowRateOnDigitalis. Is that a bug or am I doing something wrong?
This is the script I was using:
once
2 SetCreeperFlowRate
endonce
Use values from 0 to 1, if it is 1 the creeper will be divided equally over the cell with creeper and the 4 cells next to it. If it is higher than 1.3, it will move more creeper than present and thus, it will create AC. You might be able to prevent this by emitting creeper in a 2x2 region.
Thank you, that clears things up.
In the meantime I managed to hit another problem, so I am going to repurpose this thread to ask any questions I come up with.
Here goes:
Trace(div(4 2)) #displays '2' in trace log
Trace(div(2 4)) #displays '0'
Trace(div(2.0 4.0) #displays '0.5'
My layman's guess is that the output of div matches the input. When I put integers in, I get an integer as output. Is there a way around having to add .0 everywhere? And is there a way to force variables to be floating point?
You can force a value to be floating-point via the "asfloat" command. So if you have an internal variable you can force it to be floating point by including that command before stroing the value in the variable.
For a $variable exposed to the editor, simply make sure the default value is a float, and it should take care of the rest.
Whenever I try to make a CRPL tower create more CRPL towers, brokenness happens.
For example, this:
Lots of code
Attached to tower
# GolehmLoop.crpl
# Created on: 10/9/2013 5:38:32 PM
# ------------------------------------------
$Range:40
$Wait:1800
$HP:12
$MaxDrones:12
$Radius:12
$RotateTime:180 #HAS TO BE A MULTIPLE OF Wait FOR THE ANGLES TO WORK PROPERLY!
once
while CurrentCoords <-Range GetUnitCountInRange eq0
repeat
30 Delay
endwhile
<-MaxDrones 0 do
0 "Drone" I concat ->!
loop
endonce
<-MaxDrones 0 do
"Drone" I concat <-! ->cdrone
<-cdrone "CONST_ISDESTROYED" GetUnitAttribute 1 eq <-cdrone eq0 or if
CurrentCoords "crplcore" CreateUnit ->NewUnit
<-NewUnit "Drone" I concat ->!
<-NewUnit "GolehmDrone" AddScriptToUnit
<-NewUnit "GolehmDrone" "Master" Self SetScriptVar
<-NewUnit "GolehmDrone" "Angle" 360 <-MaxDrones div @degtorad SetScriptVar
<-NewUnit "GolehmDrone" "Radius" <-Radius SetScriptVar
<-NewUnit "GolehmDrone" "RotateTime" <-RotateTime SetScriptVar
<-NewUnit "GolehmDrone" "HP" <-HP SetScriptVar
<-NewUnit "CONST_COUNTSFORVICTORY" 0 SetUnitAttribute
<-NewUnit "CONST_NULLIFIERDAMAGES" 0 SetUnitAttribute
<-NewUnit "CONST_CREATEPZ" 0 SetUnitAttribute
<-NewUnit "CONST_DESTROYMODE" 1 SetUnitAttribute
<-NewUnit "CONST_DESTROYONDAMAGE" 1 SetUnitAttribute
<-NewUnit "CONST_SNIPERTARGET" 1 SetUnitAttribute
<-NewUnit "CONST_SUPPORTSDIGITALIS" 0 SetUnitAttribute
<-NewUnit "CONST_TAKEMAPSPACE" 0 SetUnitAttribute
endif
loop
<-Wait Delay
:degtorad
PI mul 180 div
:destroy
<-MaxDrones 0 do
"Drone" I concat <-! 1 Destroy
loop
# GolehmLoop2.crpl
# Created on: 10/9/2013 5:38:41 PM
# ------------------------------------------
$Range:540
$Speed:2
$Delay1:30
$Delay2:60
$Amount:500
$Amount2:200
$Amount3:100
$Event1D:6
$Event1A:10
$Event2D2:150
$Event2R:5
once
while CurrentCoords <-Range GetUnitCountInRange eq0
repeat
30 Delay
endwhile
CurrentX ->StartX
CurrentY ->StartY
endonce
<-StartX <-Range neg <-Range RandInt add <-StartY <-Range neg <-Range RandInt add <-Speed QueueMove
while GetQueuedMoveCount neq0
repeat
1 Delay
endwhile
50 @Chance if
#Default
<-Delay1 Delay
CurrentCoords <-Amount SetCreeperNoLower
<-Delay2 Delay
else
50 @Chance if
#Event 1
<-Delay1 Delay
<-Event1A 0 do
CurrentCoords <-StartX <-StartY <-Range RandCoordsInRange 2 <-Amount2 CreateSpore
<-Event1D Delay
loop
<-Delay2 Delay
else
#Event 2
<-Delay1 Delay
CurrentX <-Event2R add CurrentX <-Event2R sub do
CurrentY <-Event2R add CurrentY <-Event2R sub do
J I <-Amount3 SetCreeperNoLower
J I 1 SetDigitalisGrowth
J I 1 SetDigitalis
loop
loop
<-Event2D2 Delay
endif
endif
:Chance
0 100 RandInt gte
Not attached to the tower:
# GolehmDrone.crpl
# Created on: 10/9/2013 5:38:47 PM
# ------------------------------------------
$Master:0
$Angle:0
$Radius:12
$RotateTime:180
$HP:12
once
<-Angle asfloat @degtorad ->ca
360 <-RotateTime div @degtorad ->step
Self "CONST_MAXHEALTH" <-HP SetUnitAttribute
Self "CONST_HEALTH" <-HP SetUnitAttribute
Self "main" "Custom4" SetImage
Self "second" "Custom1" SetImage
Self "beam" "Custom0" SetImage
Self "main" 2 2 SetImageScale
Self "second" 2 2 SetImageScale
Self "beam" <-Radius 2 SetImageScale
Self "main" -0.2 SetImagePositionZ
Self "beam" -0.15 SetImagePositionZ
Self "second" -0.1 SetImagePositionZ
endonce
<-ca <-step add ->ca
<-ca cos <-Radius asfloat mul <-Master "CONST_XCOORD" GetUnitAttribute add SetCurrentX
<-ca sin <-Radius asfloat mul <-Master "CONST_YCOORD" GetUnitAttribute add SetCurrentY
Self "main" <-ca SetImageRotation
Self "second" <-ca SetImageRotation
Self "beam" <-ca SetImageRotation
Self "beam" <-Master "CONST_XCOORD" GetUnitAttribute CurrentX @avg SetImagePositionX
Self "beam" <-Master "CONST_YCOORD" GetUnitAttribute CurrentY @avg SetImagePositionY
:degtorad
PI mul 180 div
:avg
add 2 div
is supposed to make the tower move around, emitting creeper and spores, which it does fine, although it occasionally teleports randomly.
However, it is supposed to be surrounded by a bunch of drones to block attacks, which don't even appear.
So, what is the problem with it?
Lost in Nowhere...wow, you are doing alot there. In the map I am working on I have a CRPL tower that makes another CRPL tower and gives it a script to act like a Runner's nest. It works perfectly, but it is nowhere near as complex as what you are trying to accomplish.
I have no idea what '!' does in your drone loop in 'GolehmLoop.crpl'.
I have attached a copy of my two scripts, they might help, but I am not sure. Sounds like an awesome concept though! Look forward to playing your map.
Spoiler
# Primary custom tower code
# If there are no player units within outer digitalis, blue conditions
# If there are player units within outer digitalis, green conditions
# If there are player units within inner digitalis, red conditions
# Changing conditions should change color of creeper on the map
# Outer digitalis bounds: TL(66,66); TR(190,66); BL(66,190); BR(190,190)
# Inner digitalis bounds: T1L(117,98); T1R(139,98)
# T2L(98,117); T2R(158,117)
# T3L(98,139); T3R(158,139)
# T4L(117,158);T4R(139,158)
#-----------------------------------------------------------------------
$range:200
$sleepy:30
@GetClosestUnit ->closestUnit
<-closestUnit neq0 if
<-closestUnit CONST_COORDX GetUnitAttribute ->targetX
<-closestUnit CONST_COORDY GetUnitAttribute ->targetY
else
0 ->targetX
0 ->targetY
endif
#first check to see if there any units in range
<-targetX neq0 <-targetY neq0 and if
#second check to see if X & Y are both between 36 and 220
<-targetX 36 gte <-targetX 220 lte and <-targetY 36 gte and <-targetY 220 lte and if
#third condition to check is if X & Y are both between 66 and 190
<-targetX 66 gte <-targetX 190 lte and <-targetY 66 gte and <-targetY 190 lte and if
#fourth condition to check if X & Y are both between 100 and 156
<-targetX 100 gte <-targetX 156 lte and <-targetY 100 gte and <-targetY 156 lte and if
#Red conditions here, execute if within inner digitalis (kinda)
once
@SetColorRed
#Place a CRPL core to act as a runners nest
"CRPLCORE" CurrentCoords CreateUnit ->unit2
<-unit2 "Mimic Runner.crpl" AddScriptToUnit
<-unit2 "main" "CustomRunnerNest" SetImage
#Seed active digitalis into entire center grid
158 98 do
158 98 do
I J true SetDigitalisGrowth
I J 1 SetDigitalis
loop
loop
endonce
128 128 75 RandCoordsInRange ->randsinRange
<-randsinRange 5 QueueMove
60 Delay
AbortMove
CurrentCoords 250 SetCreeper
#end Red conditions
endif
#Green conditions here, execute if within outer digitalis
once
@SetColorGreen
endonce
#Plant 25 creeper 5 times in random locations
5 1 do
RandCoords 25 AddCreeper
loop
#Launch 1 spore with 1 health, 100 payload at random coordinates
CurrentCoords RandCoords 1 100 CreateSpore <-numb 1 add ->numb
#end Green conditions
endif
#Blue conditions here, execute on outer perimeter of where player units are
#This is more of just a warning with little consequences
once
@SetColorBlue
endonce
CurrentCoords 50 SetCreeper
#end Blue conditions
endif
endif
<-sleepy Delay
#Function to find UID of closest unit
:GetClosestUnit
99999999 ->closestDistance
0 ->closestUnit
CurrentCoords <-range GetUnitsInRange ->unitCount
<-unitCount neq0 if
<-unitCount 0 do
->unit
CurrentCoords <-unit CONST_COORDX GetUnitAttribute <-unit CONST_COORDY GetUnitAttribute Distance ->d
<-d <-closestDistance lt if
<-d ->closestDistance
<-unit ->closestUnit
endif
loop
endif
<-closestUnit
#End of GetClosestUnit function
#Function to change color to dark blue
:SetColorBlue
GetCreeperColors ->acB ->acG ->acR ->creeperB ->creeperG ->creeperR
0 ->creeperR
0 ->creeperG
60 ->creeperB
SetCreeperColors(<-creeperR <-creeperG <-creeperB <-acR <-acG <-acB)
#End of SetColorBlue function
#Function to change color to green
:SetColorGreen
GetCreeperColors ->acB ->acG ->acR ->creeperB ->creeperG ->creeperR
0 ->creeperR
160 ->creeperG
0 ->creeperB
SetCreeperColors(<-creeperR <-creeperG <-creeperB <-acR <-acG <-acB)
#End of SetColorGreen function
#Function to change color to red
:SetColorRed
GetCreeperColors ->acB ->acG ->acR ->creeperB ->creeperG ->creeperR
160 ->creeperR
0 ->creeperG
0 ->creeperB
SetCreeperColors(<-creeperR <-creeperG <-creeperB <-acR <-acG <-acB)
#End of SetColorRed function
#Simple script to mimic a runner's nest
#--------------------------------------
30 ->sleep
GetRunnerCount 15 lte if
CurrentCoords 2 25 100 CreateRunner
<-sleep Delay
endif
Quote from: Lost in Nowhere on October 13, 2013, 10:23:00 PM
CurrentCoords "crplcore" CreateUnit ->NewUnit
However, it is supposed to be surrounded by a bunch of drones to block attacks, which don't even appear.
You have to switch the coordinates and the unit type:
"crplcore" CurrentCoords CreateUnit ->NewUnit
No idea what's up with the random teleporting. To me your movement code seems fine.
Quote from: Lost in Nowhere on October 13, 2013, 10:23:00 PM
However, it is supposed to be surrounded by a bunch of drones to block attacks, which don't even appear.
So, what is the problem with it?
Add this line:
<-NewUnit "main" "Default" SetImage
You must set an image for a crpl core to appear.
J, the image is set in the drone script... which doesn't seem to be working anyways.
The drones appear to be being created, but just sit there and have no image. I forgot to mention that whenever the activation code finishes, the boss teleports to the left side of the screen and waits some more for it to start actually doing stuff.
Wiki articles for the <-! (http://knucklecracker.com/wiki/doku.php?id=crpl:docs:refread) and ->! (http://knucklecracker.com/wiki/doku.php?id=crpl:docs:refwrite) operators.
I'm going to mess around with it a bit to see if I can get it to work...
edit - Managed to get rid of the random teleportation to the left side of the screen.
edit 2 - Just found the issue with the drones - the script name was "GolehmDrone" instead of "GolehmDrone.crpl".
Aaaaaaaaaaaand, now the drones are acting weird...
Two quick questions:
1) Is it possible to pause/unpause the game with CRPL?
2) Is it possible to track player input (mouse clicks/key presses) while the game is paused?
Is it possible to directly set a unit's position to something that is not an integer?
Quote from: eduran on October 15, 2013, 08:12:22 AM
Two quick questions:
1) Is it possible to pause/unpause the game with CRPL?
2) Is it possible to track player input (mouse clicks/key presses) while the game is paused?
yes and no. in that order. The command is PauseGame I know virgil used it in the credits scripts. (It's at the last line)
# CRPLChest.crpl
# Created on: 9/14/2013 2:57:04 PM
# ------------------------------------------
$score:200
once
GetCoresWithVar("name" "Player") pop ->player
endonce
if (Distance(CurrentCoords GetUnitAttribute(<-player CONST_COORDX) GetUnitAttribute(<-player CONST_COORDY)) lte(2))
@ApplyPoints
PlaySound("Retro20")
Destroy(Self 1)
endif
:ApplyPoints
AddAdditionalScore(<-score)
CreateUnit("CRPLCORE" CurrentCoords) ->fadingPoints
AddScriptToUnit(<-fadingPoints "FadingPoints.crpl")
SetScriptVar(<-fadingPoints "FadingPoints.crpl" "pointAmt" <-score)
ClearConversation
AddConversationMessage(7 "You may have noticed that this mission is substantially different from most of the other missions in the game....")
AddConversationMessage(7 "How? CRPL... Creeper Reverse Polish Language. That's the scripting language available in CW3.")
AddConversationMessage(7 "Everything from the Gold Man, to his bullets, to the chests... even the walls that Creeper can't overflow.... all implemented using CRPL.")
AddConversationMessage(7 "What's even better is that you can use CRPL to make maps like this or almost anything else you can think up!")
AddConversationMessage(7 "Visit KnuckleCracker.com to learn more about CRPL, and making your own custom maps.")
ShowConversation
PauseGame
How do you use the "CreateEffect"? I read the wiki about it, and the example works; but i would like to know how to change the effect.
From wiki:
CreateEffect(14 CellToPixel(CurrentCoords) -1 1.5 1.5 0.05)
I have a feeling it's using effect "0", but I can't figure out how to add in the variable for 1-16 effects.
Question:
Is there a way to make it so that packets cannot traverse creeper or digitalis, similar to how packets got destroyed when they came into contact with creeper in CW2?
I want to build a maze map, but don't want to have to make 10 wide walls to prevent bridging.
Quote from: Cotters on October 17, 2013, 06:39:43 PM
How do you use the "CreateEffect"? I read the wiki about it, and the example works; but i would like to know how to change the effect.
From wiki:
CreateEffect(14 CellToPixel(CurrentCoords) -1 1.5 1.5 0.05)
I have a feeling it's using effect "0", but I can't figure out how to add in the variable for 1-16 effects.
If you take a look at the CreateEffect wiki page, you missed the vital part.
Arguments | Notation |
Effect_Num,X,Y,Z,ScaleX,ScaleY,Speed | n1 x1 y1 z1 f1 f2 f3 - |
Those 'Arguments' - they list what you pass into the method. the very first arg - 'Effect_Num' - is what you need to change. In the examples case, it is the number '14'.
Quote from: Michionlion on October 17, 2013, 09:49:23 PM
Arguments | Notation |
Effect_Num,X,Y,Z,ScaleX,ScaleY,Speed | n1 x1 y1 z1 f1 f2 f3 - |
Those 'Arguments' - they list what you pass into the method. the very first arg - 'Effect_Num' - is what you need to change. In the examples case, it is the number '14'.
Aha! thanks so much! :)
I mistook the 14 as the pixel ratio.
Why isn't this working?
# CreeperCannon.crpl
# Created on: 10/9/2013 8:02:23 AM
# ------------------------------------------
$RADIUS:7
$POWER:1.2 #Larger=weaker
$EXTRACREEPER:1
$CHARGETIME:7200
$RELOADTIME:1800
once
1 SetPopupTextAlwaysVisible
<-CHARGETIME 0 do
1 Delay
I asfloat <-CHARGETIME asfloat div 100 asfloat mul floor "%" Concat SetPopupText
loop
endonce
GetTimer0 0 lte if
<-RELOADTIME SetTimer0
#create bullet here
@GetClosestUnit ->closestUnit
"crplcore" CurrentCoords CreateUnit ->NewUnit
<-NewUnit "MegaBullet.crpl" AddScriptToUnit
<-NewUnit "MegaBullet.crpl" "TARGETX" <-closestUnit CONST_COORDX GetUnitAttribute SetScriptVar
<-NewUnit "MegaBullet.crpl" "TARGETY" <-closestUnit CONST_COORDY GetUnitAttribute SetScriptVar
<-NewUnit "MegaBullet.crpl" "RADIUS" <-RADIUS SetScriptVar
<-NewUnit "MegaBullet.crpl" "POWER" <-POWER SetScriptVar
<-NewUnit "MegaBullet.crpl" "EXTRACREEPER" <-EXTRACREEPER SetScriptVar
<-NewUnit "CONST_COUNTSFORVICTORY" 0 SetUnitAttribute
<-NewUnit "CONST_NULLIFIERDAMAGES" 0 SetUnitAttribute
<-NewUnit "CONST_CREATEPZ" 0 SetUnitAttribute
<-NewUnit "CONST_DESTROYMODE" 1 SetUnitAttribute
<-NewUnit "CONST_SUPPORTSDIGITALIS" 0 SetUnitAttribute
<-NewUnit "CONST_TAKEMAPSPACE" 0 SetUnitAttribute
<-NewUnit "main" "Custom1" SetImage
endif
<-RELOADTIME GetTimer0 sub <-RELOADTIME div 100 mul floor "%" Concat SetPopupText
:GetClosestUnit
99999999 ->closestDistance
0 ->closestUnit
CurrentCoords 1000 GetUnitsInRange ->unitCount
<-unitCount neq0 if
<-unitCount 0 do
->unit
CurrentCoords <-unit CONST_COORDX GetUnitAttribute <-unit CONST_COORDY GetUnitAttribute Distance ->d
<-d <-closestDistance lt if
<-d ->closestDistance
<-unit ->closestUnit
endif
loop
endif
<-closestUnit
:destroyed
CurrentCoords 1000 AddCreeper
The tower just sits there, displaying "0%."
It's supposed to wait for CHARGETIME and then wait for RELOADTIME between firing bullets, with the text displaying how close it is to building/firing.
Quote from: Lost in Nowhere on October 17, 2013, 11:06:39 PM
It's supposed to wait for CHARGETIME and then wait for RELOADTIME between firing bullets, with the text displaying how close it is to building/firing.
I think you need an asfloat in your second SetPopupText.
Another question:
I am trying to make a custom emitter that looks exactly like a normal emitter. How do I get SetPopupText to display two lines?
Quote from: eduran on October 19, 2013, 11:44:01 AMHow do I get SetPopupText to display two lines?
As far as I know there are no escape codes; you have to type the return directly into your script. e.g.:
SetPopupTextAlwaysVisible(True)
SetPopupText("Line 1
Line 2")
This isn't working:
# LifeEngine.crpl
# Created on: 10/30/2013 7:23:43 PM
# ------------------------------------------
$Width:37
$Height:36
$CellAmt:2
$Period:15
once
1 ->state
@awake
endonce
<-state if
#Gets creeper state
CurrentCoords ->y ->x
<-Height <-y add <-y do
<-Width <-x add <-x do
I J GetCreeper 0 gt "x" I concat "y" J concat concat ->!
loop
loop
1 Delay
endif
<-state not if
#Recalculates creeper
CurrentCoords ->y ->x
<-Height <-y add <-y do
<-Width <-x add <-x do
I J @GetSurroundingNum ->n
"x" I concat "y" J concat concat <-! if #if the cell is "alive"
<-n 2 eq <-n 3 eq or if #if it has 2 or 3 neighbors
I J <-CellAmt SetCreeper
else #otherwise
I J 0 SetCreeper
endif
else #if the cell is "dead"
<-n 3 eq if #if it has 3 neighbors
I J <-CellAmt SetCreeper
endif
endif
loop
loop
<-Period 1 sub Delay
endif
<-state not ->state
:awake
CurrentCoords ->y ->x
<-Height 0 do
<-Width 0 do
<-x I add <-y J add TRUE FALSE SetPinFieldCell
loop
loop
:GetSurroundingNum
->y2 ->x2
0 ->t
<-y2 1 add <-y2 1 sub do
<-x2 1 add <-x2 1 sub do
<-t "x" I concat "y" J concat concat <-! add ->t
loop
loop
<-t "x" <-x2 concat "y" <-y2 concat concat <-! sub ->t
It is supposed to simulate Conway's Game of Life using creeper in the area specified, but it just erases all creeper.
(In the case that you don't know what that is: http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life (http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life))
Quote from: Lost in Nowhere on October 30, 2013, 10:43:23 PMThis isn't working:
I find your reverse polish syntax really hard to read, but I think the "->t" at the end of :GetSurroundingNum was maybe meant to be a "return".
Another thing to consider is your do loops.
3 0 do
# runs for 0, 1 and 2. Does not run for 3
loop
I think you may be trying to work on a 3x3 grid around a starting point. If that's the case, you may want to try:
<-y2 2 add <-y2 1 sub do
<-x2 2 add <-x2 1 sub do
ThirdParty: No, that last line is meant to just make it not count the cell in question. I completely forgot the return.
Grayzzur: I just thought about that while I was laying in bed, half-asleep.
And yay, it works now!
Note that you can set walls (and unset them) with great efficiency as well. So if you are using Creeper because it is fast to set (in your game of life sim), also consider walls since they are equally fast. You could also create a 'GUI' the player could click on or for display purposes at the top or bottom of the map that would allow you to clear the grid, create well known structures (gliders, etc.), or allow you to click to paint or erase. See the Credits mission for some code on how to create GUI.
I'm mostly using it because it is very easy to kill, though using walls could also work.
I made a script that creates a glider, which worked. I also tried a glider gun, but it dies shortly after emitting a glider... which it destroys.
Also, somewhere else you mentioned that there is a limit of 500,000 or so operations per tower per frame. What exactly constitutes a operation in this context?
Quote from: Lost in Nowhere on October 31, 2013, 05:28:43 PM
Also, somewhere else you mentioned that there is a limit of 500,000 or so operations per tower per frame. What exactly constitutes a operation in this context?
Every opcode is counted. so
1 2 add
counts as 3 operations/opcodes
Quote from: J on October 31, 2013, 05:35:00 PM
Quote from: Lost in Nowhere on October 31, 2013, 05:28:43 PM
Also, somewhere else you mentioned that there is a limit of 500,000 or so operations per tower per frame. What exactly constitutes a operation in this context?
Every opcode is counted. so1 2 add
counts as 3 operations/opcodes
J: Actually I believe that is one opcode with two operands. :)
No, those are three opcodes, there is no such thing as operands in the syntax of a simple stack-based language. The first opcode pushes a 1 to the stack, the second opcode pushes a 2 to the stack, and the third opcode pops two values and pushes their sum. This leads to something that looks like reverse polish notation, but is actually caused by something else. /tmyk
My bad, I conflated CRPL with assembler. You are right.
Why does CRPL seem to not like me?
Anyways:
This is supposed to fire exploding globs of creeper that function similar to the Mass orbital weapons, but create more creeper.
# GremlinTower.crpl
# Created on: 11/7/2013 3:39:55 PM
# ------------------------------------------
$Build:1800
$Wait:1800
$Amt:50.0 #Amount of creeper is divided by this
$Height:0.5
once
FALSE ->Built
CurrentX ->x
CurrentY ->y
Self "CONST_MAXAMMO" <-Build SetUnitAttribute
Self "CONST_SHOWAMMOBAR" TRUE SetUnitAttribute
endonce
<-Built if
Self "CONST_AMMO" GetUnitAttribute ->a
<-a Self "CONST_MAXAMMO" GetUnitAttribute gte if
#fire a bullet
"CRPLCORE" CurrentCoords CreateUnit ->u
@GetClosestUnit ->v
<-u "CRBullet.crpl" AddScriptToUnit
<-u "GremlinBullet.crpl" "TX" <-v "CONST_XCOORD" GetUnitAttribute SetScriptVar
<-u "GremlinBullet.crpl" "TY" <-v "CONST_YCOORD" GetUnitAttribute SetScriptVar
0 ->p
CurrentY 2 add CurrentY 1 sub do
CurrentX 2 add CurrentX 1 sub do
I J GetCreeper <-p add ->p
I J 0 SetCreeper
loop
loop
<-u "GremlinBullet.crpl" "Power" <-p SetScriptVar
<-u "GremlinBullet.crpl" "Height" <-Height SetScriptVar
Self "CONST_AMMO" 0 SetUnitAttribute
else
Self "CONST_AMMO" <-a 1 add SetUnitAttribute
endif
else
Self "CONST_AMMO" GetUnitAttribute ->a
<-a Self "CONST_MAXAMMO" GetUnitAttribute gte if
Self "CONST_MAXAMMO" <-Wait SetUnitAttribute
Self "CONST_AMMO" 0 SetUnitAttribute
TRUE ->Built
else
Self "CONST_AMMO" <-a 1 add SetUnitAttribute
endif
endif
<-x <-y SetCurrentCoords
:GetClosestUnit
99999999 ->closestDistance
0 ->closestUnit
CurrentCoords 9999 GetUnitsInRange ->unitCount
<-unitCount neq0 if
<-unitCount 0 do
->unit
CurrentCoords <-unit CONST_COORDX GetUnitAttribute <-unit CONST_COORDY GetUnitAttribute Distance ->d
<-d <-closestDistance lt if
<-d ->closestDistance
<-unit ->closestUnit
endif
loop
endif
<-closestUnit
# GremlinBullet.crpl
# Created on: 11/7/2013 3:42:35 PM
# ------------------------------------------
$Power:100
$TX:0
$TY:0
$Height:0.5
once
<-TX <-TY 8 QueueMove
Self "main" "Custom0" SetImage
Self "CONST_NULLIFIERDAMAGES" FALSE SetUnitAttribute
Self "CONST_SUPPORTSDIGITALIS" FALSE SetUnitAttribute
Self "CONST_COUNTSFORVITORY" FALSE SetUnitAttribute
Self "CONST_SUPPORTSDIGIALIS" FALSE SetUnitAttribute
Self "CONST_TAKESMAPSPACE" FALSE SetUnitAttribute
endonce
GetQueuedMoveCount eq0 if
.75 <-Power mul PI div 1 3 div pow ->Radius
CurrentCoords GetTerrain ->t
<-Radius 1 add <-Radius neg do
<-Radius 1 add <-Radius neg do
I 2 pow J 2 pow add ->a
<-a <-Radius lte if
<-a sqrt <-Height mul ->b
I J <-b 2 mul AddCreeper
I J GetTerrain ->n <-t <-b sub min 1 max ->c
I J <-c SetTerrain
endif
loop
loop
CurrentCoords <-Radius GetUnitsInRange ->unitCount
<-unitCount neq0 if
<-unitCount 0 do
2 Destroy
loop
endif
Self 2 Destroy
endif
Quote from: Lost in Nowhere on November 07, 2013, 07:58:57 PM
Self "CONST_SUPPORTSDIGITALIS" FALSE SetUnitAttribute
Self "CONST_COUNTSFORVITORY" FALSE SetUnitAttribute
Self "CONST_SUPPORTSDIGIALIS" FALSE SetUnitAttribute
Haven't really picked through it but I noticed two typoed lines, one of them being a repeated command. Should be "CONST_COUNTSFORVI
CTORY".
Quote from: Lost in Nowhere on November 07, 2013, 07:58:57 PM
Why does CRPL seem to not like me?
Anyways:
This is supposed to fire exploding globs of creeper that function similar to the Mass orbital weapons, but create more creeper.
In GremlinTower:
* You added the script "CRBullet.crpl" to your new bullet unit, instead of "GremlinBullet.crpl" like I think you intended.
* The next two lines, I think you need to fix the GetUnitAttribute parameters. Take the quotes off the consts
... <-v CONST_COORDX GetUnitAttributes ...
... <-v CONST_COORDY GetUnitAttributes ...
In GremlinBullet:
* What the previous poster mentioned. You misspelled some of the unit attribute constants. Also, they shouldn't have quotes around the constant names.
Self CONST_SUPPORTDIGITALIS FALSE SetUnitAttribute
- etc.
I recommend Notepad++ with the CRPL add-ons you can download from the Wiki. It really helps get the spelling of all the commands and constants correctly.
I have Notepad++, but not the syntax highlighter thing... I guess I'll get that...
Aaaand, I can't find it.
Quote from: Lost in Nowhere on November 08, 2013, 06:50:38 PM
I have Notepad++, but not the syntax highlighter thing... I guess I'll get that...
Aaaand, I can't find it.
http://knucklecracker.com/wiki/doku.php?id=crpl:overview
Bottom of the page, section called "Creating CRPL Scripts" -- has links to download config files for Notepad++, and tells you what to do with them.
Quote from: Grayzzur on November 08, 2013, 11:01:20 PM
Quote from: Lost in Nowhere on November 08, 2013, 06:50:38 PM
I have Notepad++, but not the syntax highlighter thing... I guess I'll get that...
Aaaand, I can't find it.
http://knucklecracker.com/wiki/doku.php?id=crpl:overview
Bottom of the page, section called "Creating CRPL Scripts" -- has links to download config files for Notepad++, and tells you what to do with them.
Okay, now I just can't figure out how to get it to use it...
I have used all of the given instructions.
Edit - Never mind, it just doesn't apply to the files that are already open.
Is it possible to access the player's key bindings? I'd like to do something when the pause key is pressed. In principle, GetKeyDown does what I need, except that i don't know what key pause/unpause is bound to.
There's no way to read those bindings right now...
Thinking about this, though, I wonder if an intrinsic function callback might meet the need. For instance, if whenever the game was paused an "OnGamePaused" function would be called on any script. The complication I can see is with the 'step' functionality (pressing 'n'). That basically allows a game to advance by one frame while in the paused state. So even while paused, a game can advance. Of course if you only want to do something at the moment of a pause, the callback would work fine (assuming it doesn't re-fire every time 'n' is pressed).
I am trying to use a couple of custom UI elements, which stop working during pause mode. What I need is a way to make sure they are left in a 'save' state when the game is paused. A OnGamePause function would work for that.
How would one make a "sandstorm" effect that covers the whole map, especially while paused?
Quote from: Lost in Nowhere on November 11, 2013, 08:57:55 PM
especially while paused?
CRPL scripts never run while the game is paused. The best one could do in that regard is set up a (still) image that shows during pause without any additional effect.
How does GetEnemyUnitsInRange work????? Because for some reason it counts my strafer and bombers as enemies?????????? also the code posted on the wiki as example doesn't work.....
Specifically I need a code to count all enemies on map on map. But the GetEnemyUnitsInRange counts also totems, ore deposits (but that's on I can simply subtract them). But out of random it also started including strafes and bombers ??? and that I can't take into account at first? bdw. still sitting on 1.04 build.
Ut-oh. Virgil made a recent change in how Strafers and Bombers are treated, to correct their ISLANDED attribute. I'll alert him to this and he may have to loo at a further fix. :)
I use the old build so it can't be that.
Maybe the bomber itself counts, not the bomber pad. The bomber and the bomber pad are actually two different 'units' to the game. They are related internally, but are two distinct things nonetheless. So maybe the pad doesn't count, but the bomber does. The part of your description the confuses me is this:
"But out of random it also started including strafes and bombers".
What do you mean by random? Do you have a test map where they weren't being counted at some point, then they started being counted?
Sorry I had a test map where the emitter output was scaled (max - number of enemies on map)*20 and it worked fine but when while testing i build a bomber and a strafer they started emitting AC(meaning nr. enemies on map has gone up) when i destroyed the bomber and strafer the emmiters behaved normally again. I used something like
0 ->count
0 0 99999 GetEnemiesInRange do
<-count add(1) ->count
enddo
<-count
this count included the ore deposits and totems on map as well.
Alright I see some issues with this I will fix and put in the next beta build. Looks like I left out the strafer and bomber in a routine for some reason.
As a note on your CRPL, you can do this for improved efficiency:
GetEnemyUnitsInRange(0 0 99999) ->count ClearStack
Note that you have to be running with an empty stack prior to this line since it clears the stack. But this will give you the count and then throw away all of the unit UIDs that were pushed to the stack without requiring that you pop each one off.
If I use GetUnitAt on a coord with multiple units on it, in which order are the UIDs returned?
Edit: answered by V and eduran. eduran says only returns one UID. V says returns all UIDs in order of age.
It should only return one, that's for sure. If you want all, then you could probably use a GetAllUnitsInRange call with a short range (like 1).
I just checked and when you ask for one, the one you get back (if units are stacked) is not defined. Translation, it's hash order and won't make any sense and can change across loads or as units get created and destroyed.
I was messing around with that the other day and noticed the problem with GetUnitAt and stacked units (in my case, a cannon and a flying strafer). A 0 range on your choice of unit in range function should work.
Ok, I am trying to make a player-controlled spaceship, similar to the credits mission.
Currently, it immediately explodes and teleports while doing so, despite it having no reason to do so.
# PlayerShip.crpl
# Created on: 11/23/2013 8:06:21 PM
# ------------------------------------------
$Name:"Player"
$MaxHealth:100
$HealRate:0.1
$CreeperDamage:0.6
$SelectedWeapon:0
$LaserCooldown:10
$LaserCreeperDamage:100
$LaserStructureDamage:100
$MaxMissiles:0
$Missiles:0
$MissileCooldown:30
$MissileCreeperDamage:10000
$MissileStructureDamage:200
$MaxSuperLasers:0
$SuperLasers:0
$SuperLaserCooldown:30
$SuperLaserStructureDamage:500
$MaxSpeed:4.0
$Acceleration:0.05
$TurnSpeedDeg:4
once
# initialize more variables and set some unit attributes
SetUnitAttribute(Self CONST_MAXHEALTH <-MaxHealth)
SetUnitAttribute(Self CONST_HEALTH <-MaxHealth)
SetUnitAttribute(Self CONST_DESTROYONDAMAGE TRUE)
SetUnitAttribute(Self CONST_HEALRATE <-HealRate)
0.0 ->dir
0.0 ->speed
endonce
@UpdateHealth
@UpdatePosition
@UpdateImage
:awake
TRUE EnableAlternateControlMode
:UpdateHealth
if (@OverCreeper)
GetUnitAttribute(Self CONST_HEALTH) ->health
<-health sub(<-CreeperDamage) ->health
if (<-health lte(0))
0 ->health
endif
SetUnitAttribute(Self CONST_HEALTH <-health)
endif
#if (@OverWall)
# 0 ->health
#endif
#Stick stuff for other enemies here
if (<-health lte(0))
Self 2 Destroy
endif
:OverCreeper
do(2 -1)
do (2 -1)
if (GetCreeper(CurrentX add(I) CurrentY add(J)) gt(0))
return (TRUE)
endif
loop
loop
FALSE
:OverWall
do(2 -1)
do (2 -1)
if (GetTerrainOverride(CurrentX add(I) CurrentY add(J)) gt(500))
return (TRUE)
endif
loop
loop
FALSE
:UpdateImage
Self "main" <-dir SetImageRotation
:UpdatePosition
"LeftArrow" GetKey or("A" GetKey) if
<-TurnSpeedDeg @DegToRad <-dir add ->dir
endif
"RightArrow" GetKey or("D" GetKey) if
<-TurnSpeedDeg @DegToRad <-dir sub ->dir
endif
"UpArrow" GetKey or("W" GetKey) if
<-speed <-Acceleration add <-MaxSpeed min ->speed
endif
"DownArrow" GetKey or("S" GetKey) if
<-speed <-Acceleration sub 0.0 max ->speed
endif
CurrentPixelCoords ->px ->py
<-dir cos mul (<-speed 8 mul) add (<-px) ->px
<-dir sin mul (<-speed 8 mul) add (<-py) ->py
Self CONST_PIXELCOORDX <-px SetUnitAttribute
Self CONST_PIXELCOORDY <-py SetUnitAttribute
:FireProjectile
"Alpha1" GetKey if
1 ->SelectedWeapon
endif
"Alpha2" GetKey if
2 ->SelectedWeapon
endif
"Alpha3" GetKey if
3 ->SelectedWeapon
endif
<-SelectedWeapon 1 eq if
#Stuff
endif
<-SelectedWeapon 2 eq and (<-Missiles 0 gt) if
#Stuff
endif
<-SelectedWeapon 3 eq and (<-SuperLasers 0 gt) if
#Stuff
endif
:DegToRad
asfloat PI mul 180.0 div
:destroyed
#FailMission
Its teleportation also seems to be across the line y=MapHeight-x, running diagonally across the map...
Edit - fixed the teleporting
Quote from: Lost in Nowhere on November 24, 2013, 10:27:13 AM
Ok, I am trying to make a player-controlled spaceship, similar to the credits mission.
Currently, it immediately explodes and teleports while doing so, despite it having no reason to do so.
# PlayerShip.crpl
# Created on: 11/23/2013 8:06:21 PM
# ------------------------------------------
$Name:"Player"
$MaxHealth:100
$HealRate:0.1
$CreeperDamage:0.6
$SelectedWeapon:0
$LaserCooldown:10
$LaserCreeperDamage:100
$LaserStructureDamage:100
$MaxMissiles:0
$Missiles:0
$MissileCooldown:30
$MissileCreeperDamage:10000
$MissileStructureDamage:200
$MaxSuperLasers:0
$SuperLasers:0
$SuperLaserCooldown:30
$SuperLaserStructureDamage:500
$MaxSpeed:4.0
$Acceleration:0.05
$TurnSpeedDeg:4
once
# initialize more variables and set some unit attributes
SetUnitAttribute(Self CONST_MAXHEALTH <-MaxHealth)
SetUnitAttribute(Self CONST_HEALTH <-MaxHealth)
SetUnitAttribute(Self CONST_DESTROYONDAMAGE TRUE)
SetUnitAttribute(Self CONST_HEALRATE <-HealRate)
0.0 ->dir
0.0 ->speed
endonce
@UpdateHealth
@UpdatePosition
@UpdateImage
:awake
TRUE EnableAlternateControlMode
:UpdateHealth
if (@OverCreeper)
GetUnitAttribute(Self CONST_HEALTH) ->health
<-health sub(<-CreeperDamage) ->health
if (<-health lte(0))
0 ->health
endif
SetUnitAttribute(Self CONST_HEALTH <-health)
endif
#if (@OverWall)
# 0 ->health
#endif
#Stick stuff for other enemies here
if (<-health lte(0))
Self 2 Destroy
endif
:OverCreeper
do(2 -1)
do (2 -1)
if (GetCreeper(CurrentX add(I) CurrentY add(J)) gt(0))
return (TRUE)
endif
loop
loop
FALSE
:OverWall
do(2 -1)
do (2 -1)
if (GetTerrainOverride(CurrentX add(I) CurrentY add(J)) gt(500))
return (TRUE)
endif
loop
loop
FALSE
:UpdateImage
Self "main" <-dir SetImageRotation
:UpdatePosition
"LeftArrow" GetKey or("A" GetKey) if
<-TurnSpeedDeg @DegToRad <-dir add ->dir
endif
"RightArrow" GetKey or("D" GetKey) if
<-TurnSpeedDeg @DegToRad <-dir sub ->dir
endif
"UpArrow" GetKey or("W" GetKey) if
<-speed <-Acceleration add <-MaxSpeed min ->speed
endif
"DownArrow" GetKey or("S" GetKey) if
<-speed <-Acceleration sub 0.0 max ->speed
endif
CurrentPixelCoords ->px ->py
<-dir cos mul (<-speed 8 mul) add (<-px) ->px
<-dir sin mul (<-speed 8 mul) add (<-py) ->py
Self CONST_PIXELCOORDX <-px SetUnitAttribute
Self CONST_PIXELCOORDY <-py SetUnitAttribute
:FireProjectile
"Alpha1" GetKey if
1 ->SelectedWeapon
endif
"Alpha2" GetKey if
2 ->SelectedWeapon
endif
"Alpha3" GetKey if
3 ->SelectedWeapon
endif
<-SelectedWeapon 1 eq if
#Stuff
endif
<-SelectedWeapon 2 eq and (<-Missiles 0 gt) if
#Stuff
endif
<-SelectedWeapon 3 eq and (<-SuperLasers 0 gt) if
#Stuff
endif
:DegToRad
asfloat PI mul 180.0 div
:destroyed
#FailMission
Its teleportation also seems to be across the line y=MapHeight-x, running diagonally across the map...
Edit - fixed the teleporting
Have you checked to see if the health is resetting to zero somewhere in the code?
No, it's not. It also started working, so, it definitely isn't.
Why does RandCoords run 25 times in succession always give the same set of 25 coords(?)
For repeatability? :P
"health" only gets initialized if the ship is over Creeper. But there is a check that if health is <= 0, then destroy. Either this has to be done every frame:
GetUnitAttribute(Self CONST_HEALTH) ->health
or GetUnitAttribute(Self CONST_HEALTH) has to be called for determining whether to call Destroy.
Command request!
WinMission: the opposite of FailMission
Alternatively, you can blow up all enemy units to trigger normal victory, as in the connect totems to win (http://knucklecracker.com/wiki/doku.php?id=crpl:crpltutorial:code_examples#connect_totems_to_win) code example.
He tried (he used destroyallenemyunits) but for some reason it doesn't win the map!
Quote from: Annonymus on December 08, 2013, 12:21:49 PM
He tried (he used destroyallenemyunits) but for some reason it doesn't win the map!
...or destroy the units.
Collectors is a list with some UID's of CPRL cores. Since the player can destroy them, every game loop I check if any have been destroyed and remove them form this list using such a code:
<-Collectors GetListCount 0 do
<-Collectors I GetListElement CONST_ISDESTROYED GetUnitAttribute if
<-Collectors I RemoveListElement
endif
loop
Can someone tell me why it doesn't work? I'm getting that RemoveListElement it taking item from an empty stack?
You are modifying the list as you loop over it, so the indexes change (the list gets shorter). Imagine you have a list 5 elements long. 0, 1, 2, 3, 4 are the indexes of the elements. You are looping from 0 through 4 inclusive. Say that when you are on index 2 you remove the element. That shrinks the list to 4 elements in length but you will still loop over 5 elements.
This is a common problem that shows up in many situations in many languages and scenarios; modifying a list while iterating over it. Some languages have iterators that help you deal with it. CRPL is old school, though, so you have to use an old school solution. You could use a while/repeat/endwhile loop to go over the list and keep up with an index variable yourself. Another solution would be to not modify the list but to build a new list each time (leaving out the items you want to discard).
If I had the time I'd work up an couple examples for you. But, I'm rushing to get Colonial Space done this week...
Try adding one to a variable each time you remove an element. Substruct this value from I.
0 ->numb
<-Collectors GetListCount 0 do
<-Collectors I <-numb sub GetListElement CONST_ISDESTROYED GetUnitAttribute if
<-Collectors I <-numb sub RemoveListElement
<-numb 1 add ->numb
endif
loop
For whatever reason, this isn't functioning properly:
# CircleDecay.crpl
# Created on: 11/23/2013 12:50:12 PM
# ------------------------------------------
$rad:30
$Increase:1
$Decrease:1
$Range:3
once
PlaySound("Retro25")
1 ->row
endonce
if (<-row lt (<-rad))
@GetRow
@DoRow
<-row add(1) ->row
endif
:GetRow
<-row 12 mul asfloat PI mul ->circ
<-circ 0 gt if
<-circ 0 do
I @GetCoords ->x ->y
<-x <-y GetTerrain ->t
<-t "x" <-x concat "y" <-y concat concat ->!
loop
endif
:DoRow
<-row 2 mul asfloat PI mul ->circ
<-circ 0 gt if
<-Range 2 mul 1 add ->tr
<-circ 0 do
I @GetCoords ->x ->y
"x" <-x concat "y" <-y concat concat <-! ->t
I ->n
0 ->total
<-n <-Range add <-n <-Range sub do
I @GetCoords swap GetTerrain <-total add ->total
loop
<-total <-tr asfloat div ceil ->nt
<-t <-nt @Check ->ft
<-x <-y <-ft SetTerrain
loop
endif
:GetCoords
->b
<-b <-circ div cos <-row mul CurrentX add ->xgc
<-b <-circ div sin <-row mul CurrentY add ->ygc
<-ygc <-xgc
:Check # oldT newT -> finalT
->newT ->oldT
<-Increase not if
<-newT <-oldT gt if
<-oldT ->newT
endif
endif
<-Decrease not if
<-newT <-oldT lt if
<-oldT ->newT
endif
endif
<-newT
It's supposed to decay higher areas in a circular manner, which it does for about 1/8 of the area; elsewhere, it does nothing.
It's not exactly CRPL, but recently I tried to set the middle 3 upgrades at the forge to "-1", meaning you can infinitely upgrade your energy production and ore production, as long as you can afford the increasing price. However, it acted as if I had put in 0. There's a pretty obvious formula for producing the prices for the first 10, but no matter what I try, I can't make it go over 10.
Not that that's a pressing issue, but maybe in a future patch an ability to go over those current bounds would be nice.
Meanwhile, I was wondering, does anyone have a script that changes a core between two states depending on whether it's sitting on creeper or anticreeper? Such as an emitter, that releases 50 AC every 2 seconds if the last thing that was under it was AC, or 100 creeper every 2 seconds if the last thing that was under it was creeper. I'm having trouble with the figuring out whether it's on creeper or not bit.
CurrentCoords GetCreeper should work (though you may have to be more creative if you want anti/creeper under any part of it to affect its output). Positive number should be creeper, negative ac. Having it change output like that shouldn't be hard.
Quote from: Flabort on December 30, 2013, 01:58:35 AM
It's not exactly CRPL, but recently I tried to set the middle 3 upgrades at the forge to "-1", meaning you can infinitely upgrade your energy production and ore production, as long as you can afford the increasing price. However, it acted as if I had put in 0. There's a pretty obvious formula for producing the prices for the first 10, but no matter what I try, I can't make it go over 10.
Not that that's a pressing issue, but maybe in a future patch an ability to go over those current bounds would be nice.
Those are hard limits.
Quote
Meanwhile, I was wondering, does anyone have a script that changes a core between two states depending on whether it's sitting on creeper or anticreeper? Such as an emitter, that releases 50 AC every 2 seconds if the last thing that was under it was AC, or 100 creeper every 2 seconds if the last thing that was under it was creeper. I'm having trouble with the figuring out whether it's on creeper or not bit.
Obtain the unit coordinates, the do "getcreeper" at those coordinates and examine the return value.
Well, with the first one, I was trying to make a map with two totems, a single ore patch, a free forge, and not enough room to build an energy economy that would support >1 blaster. With only 3 energy upgrades available, but infinite ore upgrades. However, if it's a hard limit, and that's not going to be changing any time soon, I'll just have to go without. 8)
And, oh, OK, so I was obviously getting my notation backwards, the coordinates go before the getcreeper. And I would use an if statement, but... what about staying in it's last state when neither AC or C is present?
Quote from: Flabort on December 30, 2013, 03:15:33 PM
Well, with the first one, I was trying to make a map with two totems, a single ore patch, a free forge, and not enough room to build an energy economy that would support >1 blaster. With only 3 energy upgrades available, but infinite ore upgrades. However, if it's a hard limit, and that's not going to be changing any time soon, I'll just have to go without. 8)
And, oh, OK, so I was obviously getting my notation backwards, the coordinates go before the getcreeper. And I would use an if statement, but... what about staying in it's last state when neither AC or C is present?
Set a variable, that way, as long as you don't change the var except to change to the opposite type, you can emit based on the variables value.
Right, so let me know if I did anything wrong here:
$amtCreeper:50
$amtAnti:-25
$interval:60
CurrentCoords GetCreeper 0 gt if
1 ->state
endif
CurrentCoords GetCreeper 0 lt if
0 ->state
endif
<-state if
CurrentCoords <-amtCreeper SetCreeper
else
CurrentCoords <-amtAnti SetCreeper
endif
<-interval Delay
As I imagine it, it starts as an AC emitter, but a much stronger emitter quickly overtakes it, converting it to a regular creeper emitter, but stronger. You can change it back if you can spray enough AC at it... Is there flaws in my logic/script?
edit: Yes, I missed several "<-"s. Except for that. Edited those in.
Edit2: I can confirm it works as intended, and am playing a map I threw together with it. It's very fun, somewhat difficult (not too much), and I am attaching a picture of the map in progress.
The only thing I would do is add this after your initial variables before the rest of the code:
once
0 ->state
endonce
This little script works without it, because you're relying on uninitialized variables to have a value of zero at the start. That's a bad practice and might get you into unintended behavior in future script projects. Always initialize your variables.
I posted a slight update to your script in your map discussion thread:
http://knucklecracker.com/forums/index.php?topic=15081.msg110691#msg110691
This update makes it so that friendly flip emitters don't have to be nullified to win the map.
OK, after having played Nano in Neon, which is just
evil genius in it's use of colors, I went and tried to make a script that continually messes with the color of creeper. After some trial and error, finding out that the Get and Set commands use two different number formats, and discovering I had used lte when I wanted gte, I got it to work. I was going to ask how to fix it here, but I'll just share it instead.
Spoiler
# psychedelicCreeper.crpl
# Created on: 1/4/2014 4:00:31 PM
# ------------------------------------------
once #Initializing my variables. Actually, this may as well be ripped off the official examples page for changing creeper color to red. Except I use blue. And the whol Mul thing, that's due to the floating point vs whole number.
GetCreeperColors 255 mul ->acB 255 mul ->acG 255 mul ->acR 255 mul ->creeperB 255 mul ->creeperG 255 mul ->creeperR
20 ->creeperR 20 ->creeperG 220 ->creeperB
SetCreeperColors(<-creeperR <-creeperG <-creeperB <-acR <-acG <-acB)
endonce
#Start the loop by getting the current colors. Pop off the AC colors to make sure I don't mess with them by accident. Same as initialization.
GetCreeperColors 255 mul ->acB 255 mul ->acG 255 mul ->acR 255 mul ->creeperB 255 mul ->creeperG 255 mul ->creeperR
#manipulate two colors, making sure not to touch the third if it's at it's lowest point.
<-creeperR 20 lte <-creeperB <-creeperR gte Or <-creeperG <-creeperR gt and if
<-creeperG 20 sub ->creeperG
<-creeperB 20 add ->creeperB
endif
#Same thing. Note that when one of the two I manipulated reaches it's lowest point, it triggers TRUE in the next one.
<-creeperG 20 lte <-creeperR <-creeperG gte Or <-creeperB <-creeperG gt and if
<-creeperB 20 sub ->creeperB
<-creeperR 20 add ->creeperR
endif
#And the third pair of colors. Pattern should be Blue to Purple to Red to Orange/Yellow to Green to Cyan to Blue.
<-creeperB 20 lte <-creeperG <-creeperB gte Or <-creeperR <-creeperB gt and if
<-creeperR 20 sub ->creeperR
<-creeperG 20 add ->creeperG
endif
#Update the color set, and wait a little bit so as not to lag the game too much.
SetCreeperColors(<-creeperR <-creeperG <-creeperB <-acR <-acG <-acB)
10 Delay
Actually working on a non-theoretical script, and I'm stuck. VirgilW himself told me to try marrying the Flip Emitter concept with the Slip Emitter concept.
So I concieved two new scripts. Everything works except the X coordinate of the Slip Emitter. Much of the code was stolen from the Phantom Emitter script on... I forget which world.
The Converterv2.crpl script goes on a core with the SlipEmitSet.crpl code. You set the variables for where you want the slip emitter to go, and do not actually make a core for the child emitter, the script does that.
The scripts:
Converterv2.crpl
# Converterv2.crpl
# Created on: 1/3/2014 1:53:35 PM
# ------------------------------------------
$amtCreeper:50
$amtAnti:-25
$interval:60
$startState:0
#Initializes state, thanks to Grayzzur for the idea.
Once
<-startState ->state
"
" ->lineBreak
endonce
#Checks if there is creeper, if there is, sets the converter to make creeper.
CurrentCoords GetCreeper 0 gt if
1 ->state
SetPopUpText("amt: " <-amtCreeper <-lineBreak "delay: " <-interval 30 div concat concat concat concat)
SetUnitAttribute(Self CONST_COUNTSFORVICTORY TRUE)
endif
#Checks if there is anticreeper, if there is, sets the converter to make AC
CurrentCoords GetCreeper 0 lt if
0 ->state
#the linebreak is on purpose, and concat because the amt isn't always the same.
SetPopUpText("amt: " <-amtAnti <-lineBreak "delay: " <-interval 30 div concat concat concat concat)
SetUnitAttribute(Self CONST_COUNTSFORVICTORY FALSE)
endif
#Checks the state, remember if there was nothing under it, it will use it's last state!
<-state if
CurrentCoords <-amtCreeper SetCreeper
else
CurrentCoords <-amtAnti SetCreeper
endif
<-interval Delay
SlipEmitSet.crpl
# SlipEmitSet.crpl
# Created on: 1/12/2014 5:48:16 PM
# ------------------------------------------
$childX:10
$childY:10
$percentEmit:20
$interval:15
once
"CRPLCore" <-childX <-childY CreateUnit ->child
<-child "SlipEmitasChild.crpl" AddScriptToUnit
<-child "SlipEmitasChild.crpl" "interval" <-interval setScriptVar
endonce
Self "Converterv2.crpl" "state" GetScriptVar if
<-child "SlipEmitasChild.crpl" "amtCreeper" Self "Converterv2.crpl" "amtCreeper" getScriptVar <-percentEmit mul 100 div setScriptVar
else
<-child "SlipEmitasChild.crpl" "amtCreeper" Self "Converterv2.crpl" "amtAnti" getScriptVar <-percentEmit mul 100 div setScriptVar
endif
:destroyed
<-child 0 Destroy
SlipEmitasChild.crpl
# SlipEmitasChild.crpl
# Created on: 1/12/2014 5:48:07 PM
# ------------------------------------------
$interval:15
$amtCreeper:5
once
Self "CONST_CANREQUESTAMMO" setUnitAttribute
Self "CONST_CELLHEIGHT" 3 setUnitAttribute
Self "CONST_CELLWIDTH" 3 setUnitAttribute
Self "CONST_COUNTSFORVICTORY" false setUnitAttribute
Self "CONST_CREATEPZ" false setUnitAttribute
Self "CONST_DESTROYONDAMAGE" false setUnitAttribute
Self "CONST_NULLIFIERDAMAGES" false setUnitAttribute
Self "CONST_TAKEMAPSPACE" true setUnitAttribute
Self "Main" "Custom2" SetImage
endonce
if (GetTimer0 eq0)
SetCreeper(CurrentX CurrentY <-amtCreeper)
@FullAlphaImage
SetTimer0(<-interval)
endif
@FadeImage
:FadeImage
GetImageColor(Self "main") ->alpha ->blue ->green ->red
if (<-alpha gt(0))
<-alpha sub(15) ->alpha
SetImageColor(Self "main" <-red <-green <-blue <-alpha)
endif
:FullAlphaImage
GetImageColor(Self "main") ->alpha ->blue ->green ->red
SetImageColor(Self "main" <-red <-green <-blue 255)
Basically my problem is when I start up the map, the slip emitters all appear on the left edge of the map. They have their proper Y coordinate, but not the X coordinate.
spoilers don't work well with code tags...
Nothing appears wrong with the BBcode on my end. I can open the spoilers and find the code block within, and from there scroll through my code.
As to the CRPL... what did I do wrong?
Quote from: Flabort on January 12, 2014, 09:59:05 PM
As to the CRPL... what did I do wrong?
Nothing, actually. I copied the code to a new project without any changes and the slip emitter shows up at 10/10. Check if you manually set childX on the core to a different value. If that's not it, make sure you are really using the code you pasted here and that you compiled it (that one never gets old for me: fix a bug, forget to compile, bug still exists, go off on a wild-goose chase to find cause of the no-longer-existing bug ;D)
???
Well, I copied the one I pasted to the forum into a new project too, laid out terrain, and just compiled and attached the scripts to a core. No dice. It showed up at 1/10. Also tried to set one to 85/62 afterwards... it showed up at 1/62.
So it's not that I didn't compile this time. Still, thank you for checking, that would have made my week.
Found the reason why it worked for me: I got the name of the child script wrong, so it was never attached to the slip emitter. That script is causing the problem. Remove the quotation marks from all CONST_SOMETHING and you should be good.
...quotes around the CONSTs. ::) I should have known, thank you so much. It works perfectly now. ;D
is there a way to make a button on the screen i don't see a draw pixel like functions only camera and image functions but i don't want to use an image function->
Quote from: jakeflee on January 20, 2014, 12:47:06 AM
is there a way to make a button on the screen i don't see a draw pixel like functions only camera and image functions but i don't want to use an image function->
You can't put a custom image on the screen without using an image function.
dam ok
Say you have two scripts, parent and child. Parent is attached to a CRPL core, creates a new core and attaches child to that new core. Obviously parent will execute before child on the first frame, because child only exists if parent was executed at least once. But what happens now? Will parent always execute first or can the order switch around?
Quote from: eduran on January 21, 2014, 05:41:42 AM
Say you have two scripts, parent and child. Parent is attached to a CRPL core, creates a new core and attaches child to that new core. Obviously parent will execute before child on the first frame, because child only exists if parent was executed at least once. But what happens now? Will parent always execute first or can the order switch around?
I suppose it depends entirely on the length of the script.
Quote from: eduran on January 21, 2014, 05:41:42 AM
Say you have two scripts, parent and child. Parent is attached to a CRPL core, creates a new core and attaches child to that new core. Obviously parent will execute before child on the first frame, because child only exists if parent was executed at least once. But what happens now? Will parent always execute first or can the order switch around?
I would have to assume that they happen simultaneously. If they in some way rely on each other frame-by-frame, like one changing the details of the other, then I couldn't say for certain when the change would take effect. Though you might be able to set up a trace log thing that would show you for certain.
To add some context to why I am even asking:
I created a custom unit, the Creeper Tunnel. For the player it looks like two cores (with custom images) connected by a line. This line is an image added to one of the cores, stretched and rotated to connect the two. The core that has the line attached checks the position of both cores and does the strechtching and rotating. Works like a charm.
Then I allowed the cores to move around. At that point I noticed that the line was slightly trailing one of the cores (the one that didn't draw the line). Instead of connecting to the center it connected to where its center was the last frame. Using GetUnitAttribute(<-otherCoreUID CONST_PIXELCOORDX/Y)
actually returns x/y values corresponding to otherCore's position during the previous frame. If I run that command on both cores and trace the result, they are different.
At least they were until I deleted both cores, placed them again and added the scripts in a different order (core without line first, core with line second). Doing that, the script works as intended. Adding the scripts in reverse order causes the 'bug' I described. Looks like a text-book race condition.
I guess what I need to know is: is it 'save' to make a map like this, finalize and upload it? Will it run on everyone's machines if I've got the order right on mine? Or can the same bug pop up randomly on other computers/times of day/phases of the moon?
One of the reasons I'm against these Omnibus threads is that Virgil doesn't always look at later posts in a thread. People here have a tendency to drag topics off-line and then continue them ad-infinitum. If you want to ask a question that Virgil is best positioned to answer, then start your own thread with a topic title that pertains to the question.
My take is that it may depend on a number of factors and I just don't know, apart from that the order of execution has never been explicitly defined.
The execution order of units is the order of this Unity API:
FindGameObjectsWithTag
And that is basically undefined. This means you can't rely on the order of execution with a given frame. Save/Load could also perturb the order along with unit creation and destruction.
Now I could probably make the execution order be defined. The order would always be latter units execute later than earlier units (creation order). This would introduce a small performance loss, though, and of course would only show up in future builds.
Actually... let's try this for the next build. Unit updating per frame will be done from oldest to youngest. This is based off of the unit UID. Basically the unit UID is an int and this int only ever goes up as units are created. Updating happens on a sorted list of these units per frame.
There should be a very slight performance degradation that should be worse the more units that are on a map. But I doubt it will ever be noticed as it will be a tee-tiny fraction of what is going on in the game.
So try the upcoming 165 build and see if everything seems ok with this...
Wow, that was fast. I did some quick tests and everything seems to work as you described. With 1.64 I am sometimes able to change the execution order by saving/reloading and by just having stuff happen (not sure what exactly caused it). In 1.65 it is unperturbed by anything I tried to mess it up. Now I just hope that doesn't ruin the frame rate on lower end machines.
Quote from: Grauniad on January 21, 2014, 02:44:31 PM
One of the reasons I'm against these Omnibus threads is that Virgil doesn't always look at later posts in a thread. People here have a tendency to drag topics off-line and then continue them ad-infinitum. If you want to ask a question that Virgil is best positioned to answer, then start your own thread with a topic title that pertains to the question.
Yes, sorry about that. I didn't have much time when I first posted the question and just threw it in here. Making a separate thread would have been better.
I'm now locking this topic. Please ask each question in a separate thread. It makes finding things a lot easier.