Need some script help

Started by Asbestos, June 17, 2015, 10:55:06 PM

Previous topic - Next topic

Asbestos

I'm trying to make a Team Fortress 2-esque control point in CRPL, but it lags the game and shows a "exceeded max number of instructions per game loop" message in the trace log. Also, it doesn't work.
# control point.crpl
# Created on: 6/18/2015 10:03:25 AM
# ------------------------------------------
@countdown
30 Delay
<-count 1 sub ->count
:countdown

once
Self "main" "Custom1" SetImage
ClearTraceLog
300 ->count
endonce

<-count
if
CurrentCoords 3 GetUnitsInRange
if
ShowTraceLog
@countdown
<-count Trace
Self "Custom1" "Custom0" SetImage
endif
HideTraceLog
endif
0 DestroyAllEnemyUnits

Grayzzur

The main issue is the way you have @countdown calling itself recursively if an enemy unit is in range, which looks like an infinite loop, so you quickly hit that max instruction limit. What behavior are you looking for?
"Fate. It protects fools, little children, and ships named 'Enterprise.'" -William T. Riker

Asbestos

I would like the script to win the map if there is a player building within range of its core for 5 minutes, and display the countdown. I don't know if there is a built-in countdown like for spores, so I'm using the trace log. But why is @countdown slowing the game if it has a delay within it?

Grayzzur

#3
The delay is not being called.
You're calling the @countdown function...
If the count is not yet zero...
If there are units in range...
Show the trace log...
...and call the countdown function again, which
  If the count is not yet zero...
  If there are units in range...
  Show the trace log...
  ...and call the countdown function again, which
    If the count is not yet zero...
    If there are units in range...
    Show the trace log...
    ...and call the countdown function again, which
     If the count.................
"Fate. It protects fools, little children, and ships named 'Enterprise.'" -William T. Riker

Asbestos

Well, I got rid of the function and put its code in the main script, but now the countdown ticks down whether or not there's a unit in range, and the core creates a tiny image of Custom0 in its center, also independent of a unit in range.
# control point.crpl
# Created on: 6/18/2015 10:03:25 AM
# ------------------------------------------

once
Self "main" "Custom1" SetImage
ClearTraceLog
300 ->count
endonce

<-count
if
CurrentCoords 3 GetUnitsInRange
if
ShowTraceLog
30 Delay
<-count 1 sub ->count
<-count Trace
Self "Custom1" "Custom0" SetImage
endif
HideTraceLog
endif
0 DestroyAllEnemyUnits

Grayzzur

Are you looking for a unit to be next to your spot for 5 minutes continously (reset if it moves away or is destroyed and start over), or just 5 minutes total time of having something near there?
"Fate. It protects fools, little children, and ships named 'Enterprise.'" -William T. Riker

Asbestos

Quote from: Grayzzur on June 19, 2015, 10:01:29 AM
Are you looking for a unit to be next to your spot for 5 minutes continously (reset if it moves away or is destroyed and start over), or just 5 minutes total time of having something near there?
5 minutes total time.

Asbestos

This is the map. How do I make the core not show the image I want it to be set at as a tiny one in the middle of it?

Grayzzur

Ok, here we go.

First, you have a power zone hiding underneath that core, it it's being picked up by GetUnitsInRange and causing your countdown to run.

Second, I'd delete the core you have now and create a new one and re-attach the updated script to it. You've created multiple images on the core you have. (You've created a second image called "Custom1" in addition to the main image, and I think you just meant to swap out the main image.)

Third, instead of messing with delays and trying to avoid the script running to the end, I'd adjust it to run every tick. You want 5 minutes, that's 300 seconds * 30 = 9000 game ticks. So I would just count down from 9000, every tick that a unit is in range. Have the destroy code wrapped in a check for the count to hit zero.

Also, on your IF statements, I'd actually use comparison operators. It makes the code a little easier to read and tell what you're trying to do.

I assume you wanted the image to swap based on whether or not a unit is in range.


once
Self "main" "Custom1" SetImage
#ShowTraceLog
9000 ->count
endonce
#ClearTraceLog

<-count 0 gt
if
CurrentCoords 3 GetUnitsInRange 0 neq
if
<-count 1 sub ->count
Self "main" "Custom0" SetImage
else
Self "main" "Custom1" SetImage
endif
endif

#<-count Trace

<-count 0 eq
if
0 DestroyAllEnemyUnits
endif


Does that get you closer to what you're trying to accomplish?
"Fate. It protects fools, little children, and ships named 'Enterprise.'" -William T. Riker

Asbestos

#9
The script works completely.

Asbestos

#10
I added a slip center that appears a couple seconds after you take the control point and spawns some slip emitters. The center spawns, but it doesn't make slip emitters, and the countdown pauses while the center is running down a delay.
once
100 -10000 -10000 0 TRUE EnableTowerField
Self "main" "Custom1" SetImage
9000 ->count
"300 seconds left" SetText
15 SetTextY
0 ->creepcontrol
endonce

<-count 0 gt
if
CurrentCoords GetCreeper 0 gt
if
Self "main" "Custom2" SetImage
once
1 ->creepcontrol
ClearConversation
AddConversationMessage(1 "The creeper has taken the control point!")
ShowConversation
endonce
CurrentCoords 30 SetCreeperNoLower
60 Delay
else
0 ->creepcontrol
CurrentCoords 3 GetUnitsInRange 0 neq
if
once
"Misc18" PlaySound
endonce
<-count 1 sub ->count
<-count 30 div " seconds left" concat SetText
Self "main" "Custom0" SetImage
endif
endif
endif

<-count 0 eq
if
0 DestroyAllEnemyUnits
endif

<-creepcontrol 1 eq
if
300 Delay
166 44 RandUnitCoords 1 20 CreateSpore
120 Delay
166 44 RandUnitCoords 1 20 CreateSpore
166 44 RandUnitCoords 1 20 CreateSpore
30 Delay
166 44 RandUnitCoords 1 20 CreateSpore
300 Delay
<-creepcontrol 1 eq
if
once
"CRPLCORE" 166 44 CreateUnit ->flymitter1
<-flymitter1 "flymitter1.crpl" AddScriptToUnit
<-flymitter1 "main" "Custom5" SetImage
<-flymitter1 CONST_CREATEPZ 0 SetUnitAttribute
endonce
endif
endif

<-creepcontrol 0 eq
if
CurrentCoords 3 GetUnitsInRange 0 neq
if
once
300 Delay
ClearConversation
AddConversationMessage(1 "A slip center is warping in near the command node! Nullify it before it spawns slip emitters!")
ShowConversation
1 3 RandInt <-slipcenterposition
->slipcenterposition 1 eq if
"CRPLCORE" 47 26 CreateUnit ->slipcenter1
<-slipcenter1 "main" "Custom5" SetImage
<-slipcenter1 CONST_CREATEPZ 0 SetUnitAttribute
<-slipcenter1 CONST_DESTROYMODE 2 SetUnitAttribute
<-slipcenter1 CONST_COUNTSFORVICTORY 1 SetUnitAttribute
<-slipcenter1 "slipcenter.crpl" AddScriptToUnit
<-slipcenter1 "slipcenter.crpl" "sliplocation1x" 51 SetScriptVar
<-slipcenter1 "slipcenter.crpl" "sliplocation1y" 41 SetScriptVar
<-slipcenter1 "slipcenter.crpl" "sliplocation2x" 26 SetScriptVar
<-slipcenter1 "slipcenter.crpl" "sliplocation2y" 31 SetScriptVar
<-slipcenter1 "slipcenter.crpl" "sliplocation3x" 50 SetScriptVar
<-slipcenter1 "slipcenter.crpl" "sliplocation3y" 11 SetScriptVar
endif
->slipcenterposition 2 eq if
"CRPLCORE" 24 78 CreateUnit ->slipcenter1
<-slipcenter1 "main" "Custom5" SetImage
<-slipcenter1 CONST_CREATEPZ 0 SetUnitAttribute
<-slipcenter1 CONST_DESTROYMODE 2 SetUnitAttribute
<-slipcenter1 CONST_COUNTSFORVICTORY 1 SetUnitAttribute
<-slipcenter1 "slipcenter.crpl" AddScriptToUnit
<-slipcenter1 "slipcenter.crpl" "sliplocation1x" 11 SetScriptVar
<-slipcenter1 "slipcenter.crpl" "sliplocation2x" 51 SetScriptVar
<-slipcenter1 "slipcenter.crpl" "sliplocation3x" 29 SetScriptVar
<-slipcenter1 "slipcenter.crpl" "sliplocation1y" 75 SetScriptVar
<-slipcenter1 "slipcenter.crpl" "sliplocation2y" 80 SetScriptVar
<-slipcenter1 "slipcenter.crpl" "sliplocation3y" 66 SetScriptVar
endif
->slipcenterposition 3 eq if
"CRPLCORE" 50 53 CreateUnit ->slipcenter1
<-slipcenter1 "main" "Custom5" SetImage
<-slipcenter1 CONST_CREATEPZ 0 SetUnitAttribute
<-slipcenter1 CONST_DESTROYMODE 2 SetUnitAttribute
<-slipcenter1 CONST_COUNTSFORVICTORY 1 SetUnitAttribute
<-slipcenter1 "slipcenter.crpl" AddScriptToUnit
<-slipcenter1 "slipcenter.crpl" "sliplocation1x" 37 SetScriptVar
<-slipcenter1 "slipcenter.crpl" "sliplocation2x" 52 SetScriptVar
<-slipcenter1 "slipcenter.crpl" "sliplocation3x" 59 SetScriptVar
<-slipcenter1 "slipcenter.crpl" "sliplocation1y" 56 SetScriptVar
<-slipcenter1 "slipcenter.crpl" "sliplocation2y" 36 SetScriptVar
<-slipcenter1 "slipcenter.crpl" "sliplocation3y" 60 SetScriptVar
endif
endonce
endif
endif


$sliplocation1x:1
$sliplocation1y:1
$sliplocation2x:1
$sliplocation2y:1
$sliplocation3x:1
$sliplocation3y:1
$name:"main"
$red:150
$green:0
$blue:0
$rate:10
$active:1
once
0 255 do
<-active if
<-alpha 0 lt if
0 ->alpha
<-rate abs ->rate
else
<-alpha 255 gt if
255 ->alpha
<-rate abs -1 mul ->rate
endif
endif

<-alpha <-rate add ->alpha

self <-name <-red <-green <-blue <-alpha SetImageColor
else
self <-name 0 0 0 0 SetImageColor
endif
loop
self <-name 0 0 0 255 SetImageColor
120 Delay
"CRPLCORE" ->sliplocation1x ->sliplocation1y CreateUnit ->slip1
<-slip1 "main" "Custom6" SetImage
<-slip1 CONST_NULLIFIERDAMAGES 0 SetUnitAttribute
<-slip1 CONST_CREATEPZ 0 SetUnitAttribute
<-slip1 CONST_CELLHEIGHT 1 SetUnitAttribute
<-slip1 CONST_CELLWIDTH 1 SetUnitAttribute
<-slip1 "slip emitter.crpl" AddScriptToUnit
<-slip1 "slip emitter.crpl" "PARENT_EMITTER_X" CurrentX SetScriptVar
<-slip1 "slip emitter.crpl" "PARENT_EMITTER_Y" CurrentY SetScriptVar
100 Delay
"CRPLCORE" ->sliplocation2x ->sliplocation2y CreateUnit ->slip2
<-slip2 "main" "Custom6" SetImage
<-slip2 CONST_NULLIFIERDAMAGES 0 SetUnitAttribute
<-slip2 CONST_CREATEPZ 0 SetUnitAttribute
<-slip2 CONST_CELLHEIGHT 1 SetUnitAttribute
<-slip2 CONST_CELLWIDTH 1 SetUnitAttribute
<-slip2 "slip emitter.crpl" AddScriptToUnit
<-slip2 "slip emitter.crpl" "PARENT_EMITTER_X" CurrentX SetScriptVar
<-slip2 "slip emitter.crpl" "PARENT_EMITTER_Y" CurrentY SetScriptVar
60 Delay
"CRPLCORE" ->sliplocation3x ->sliplocation3y CreateUnit ->slip3
<-slip3 "main" "Custom6" SetImage
<-slip3 CONST_NULLIFIERDAMAGES 0 SetUnitAttribute
<-slip3 CONST_CREATEPZ 0 SetUnitAttribute
<-slip3 CONST_CELLHEIGHT 1 SetUnitAttribute
<-slip3 CONST_CELLWIDTH 1 SetUnitAttribute
<-slip3 "slip emitter.crpl" AddScriptToUnit
<-slip3 "slip emitter.crpl" "PARENT_EMITTER_X" CurrentX SetScriptVar
<-slip3 "slip emitter.crpl" "PARENT_EMITTER_Y" CurrentY SetScriptVar
endonce


$EMIT_AMT:10.0
$EMIT_INTERVAL:40
$PARENT_EMITTER_X:63
$PARENT_EMITTER_Y:59

once
GetUnitAt(<-PARENT_EMITTER_X <-PARENT_EMITTER_Y) ->emitterUID
endonce

if (GetTimer0 eq0)
SetCreeper(CurrentX CurrentY <-EMIT_AMT)
@FullAlphaImage
SetTimer0(<-EMIT_INTERVAL)
endif

@FadeImage

if (@CheckEmitterDead)
Destroy(Self 0)
endif

: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)

:CheckEmitterDead
if (<-emitterUID eq(-1))
return(TRUE)
endif

return(GetUnitAttribute(<-emitterUID CONST_ISDESTROYED))

The map in question is attached to this post:

warren

#11
That new script is impressive. I would use FALSE and TRUE or false and true instead of 0 and 1 for functions that only take 0 or 1 for readability (except for creating global variables as that causes an error). I put the slip emitter creation code in a function so I could more easily see if there was a problem.


$sliplocation1x:1
$sliplocation1y:1
$sliplocation2x:1
$sliplocation2y:1
$sliplocation3x:1
$sliplocation3y:1
$name:"main"
$red:150
$green:0
$blue:0
$rate:10
$active:1
once
0 255 do
<-active if
<-alpha 0 lt if
0 ->alpha
<-rate abs ->rate
else
<-alpha 255 gt if
255 ->alpha
<-rate abs -1 mul ->rate
endif
endif

<-alpha <-rate add ->alpha

self <-name <-red <-green <-blue <-alpha SetImageColor
else
self <-name 0 0 0 0 SetImageColor
endif
loop
self <-name 0 0 0 255 SetImageColor
120 Delay
<-sliplocation1x <-sliplocation1y @makeSlipEmitter
100 Delay
<-sliplocation2x <-sliplocation2y @makeSlipEmitter
60 Delay
<-sliplocation3x <-sliplocation3y @makeSlipEmitter
endonce

  :makeSlipEmitter
       ->tempy ->tempx
"CRPLCORE" <-tempx <-tempy CreateUnit ->slip
<-slip "main" "Custom6" SetImage
<-slip CONST_NULLIFIERDAMAGES 0 SetUnitAttribute
<-slip CONST_CREATEPZ 0 SetUnitAttribute
<-slip CONST_CELLHEIGHT 1 SetUnitAttribute
<-slip CONST_CELLWIDTH 1 SetUnitAttribute
<-slip "slip emitter.crpl" AddScriptToUnit
<-slip "slip emitter.crpl" "PARENT_EMITTER_X" CurrentX SetScriptVar
<-slip "slip emitter.crpl" "PARENT_EMITTER_Y" CurrentY SetScriptVar



In the process, I found that this line:

"CRPLCORE" ->sliplocation3x ->sliplocation3y CreateUnit ->slip3

should read

"CRPLCORE" <-sliplocation3x <-sliplocation3y CreateUnit ->slip3


I do see a latent problem as well. If there is more than one core at the $PARENT_EMITTER_X and $PARENT_EMITTER_Y, the wrong core may be selected and watched for destruction. A possible workaround, which I believe I put in one of my own maps, it to give the unit_uid of the parent directly. slip emitter.crpl would have to be modified like so:


$EMIT_AMT:10.0
$EMIT_INTERVAL:40
$PARENT_EMITTER:-1

if (GetTimer0 eq0)
SetCreeper(CurrentX CurrentY <-EMIT_AMT)
@FullAlphaImage
SetTimer0(<-EMIT_INTERVAL)
endif

@FadeImage

if (@CheckEmitterDead)
Destroy(Self 0)
endif

: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)

:CheckEmitterDead
if (<-PARENT_EMITTER eq(-1))
return(TRUE)
endif

return(GetUnitAttribute(<-PARENT_EMITTER CONST_ISDESTROYED))


Edit: in order to more closely match the behaviour of real emitters, I always change the command SetCreeper to SetCreeperNoLower in slip emitter.crpl.