Prototype Terp CRPL code

Started by kwinse, March 07, 2014, 11:10:51 PM

Previous topic - Next topic

kwinse

Hey, thought I'd share our work with the corrupted prototype terp as seen in pyramis. Posting it in the crpl examples wiki seems weird to me but I can if people want.

# Written by Crimson King, kwinse
# ------------------------------------------

#works like a terp, except its targets are random
#and can change multiple cells per firing cycle

$limitFireRangeBool:1 #boolean
#don't just use a fire range larger than the whole map because
#there's a more efficient coordinate picker for whole map
$setFireRange:20
$playerUnitCheckRange:10
$terpToLevel:0 #0 for random up/down
$chargeTimeFrames:90
$fireTimeFrames:15
$downTimeFrames:29 #delay adds 1 frame

#initializing variables and the beam image
once
Self CONST_MAXAMMO 1.0 SetUnitAttribute
"Beam" ->beamName
255 ->beamR
102 ->beamG
0 ->beamB
255 ->beamA
Self <-beamName "Custom1" SetImage
Self <-beamName 2 SetImageScaleY
Self <-beamName <-beamR <-beamG <-beamB 0 SetImageColor

1.0 <-chargeTimeFrames div ->chargeStep
1.0 <-fireTimeFrames div ->fireStep
0 ->state
#X by X effect box, where X is 1 + terrRange, >2 lags!
#apparently runs fine on 0, but is inefficient for changing only 1 cell
1 ->terrRange
MapWidth <-terrRange sub ->maxWidth
MapHeight <-terrRange sub ->maxHeight
#6 for terrRange 2
4 ->terpEffScale

<-terpToLevel 1 lt <-terpToLevel 10 gt or if
0 ->terpToLevel
endif
endonce

#target picking
<-state eq0 if
0 ->ammo
Self CONST_AMMO 0 SetUnitAttribute
1 ->count
1 ->invalid
0 ->chargeDelay
0 ->fireDelay

#try up to 5 times to find a valid random target
#where valid is no would-be affected cells in void or AC,
#no player units within playerUnitCheckRange,
#not within zone(s) defined by @inExlusionZone,
#no cells are occupied,
#and at least one cell would be raised/lowered
while <-count 5 lte <-invalid and repeat
0 ->invalid
@GetRandCoords
<-count 1 add ->count
@PlayerUnitInRange <-terrX <-terrY GetVoid or
@InExclusionZone or ->invalid
<-invalid not if
<-terrX <-terrY GetTerrain ->terrLevel

<-terpToLevel if
#raises/lowers towards terpToLevel
<-terrLevel <-terpToLevel lt if
<-terrLevel 1 add ->terrLevel
endif
<-terrLevel <-terpToLevel gt if
<-terrLevel 1 sub ->terrLevel
endif
else
#randomly raises/lowers terrain by 1
0 2 RandInt ->updown
<-updown eq0 if -1 ->updown endif
<-terrLevel <-updown add 1 max 10 min ->terrLevel
endif

<-invalid @CheckCells or ->invalid
endif
endwhile
1 ->state
endif

#charging
<-state 1 eq if
<-invalid eq0 if
<-ammo 1 lt if
<-ammo <-chargeStep add ->ammo
Self CONST_AMMO <-ammo SetUnitAttribute
endif
endif

<-chargeDelay 1 add ->chargeDelay
<-chargeDelay <-chargeTimeFrames eq if
2 ->state
endif
endif

#firing
<-state 2 eq if
#fizzle or start firing
<-invalid eq0 <-fireDelay eq0 and if
#checks if target is still valid
@PlayerUnitInRange @CheckCells or ->invalid

#dumps ammo and plays an animation if not
<-invalid if
14 CurrentPixelCoords -0.02 1 1 1 <-fireTimeFrames CreateEffectClipped
0 ->ammo
Self CONST_AMMO 0 SetUnitAttribute
else

#rotates and scales beam and draws terp effect
#thanks to Virgil for the code shamelessly grabbed from the Credits map
<-terrX <-terrY CellToPixel ->targetY ->targetX
CurrentPixelCoords ->selfY ->selfX
<-targetX <-selfX sub ->deltaX
<-targetY <-selfY sub ->deltaY
<-deltaY <-deltaX atan2 ->angle

<-selfX <-selfY <-targetX <-targetY Distance ->distance
<-distance 24 div ->beamScaleX
<-deltaX 2 div ->beamX
<-deltaY 2 div ->beamY

Self <-beamName <-beamX <-beamY -0.02 SetImagePosition
Self <-beamName <-beamScaleX SetImageScaleX
Self <-beamName <-angle SetImageRotation
Self <-beamName <-beamR <-beamG <-beamB <-beamA SetImageColor
15 <-targetX <-targetY -0.03 <-terpEffScale dup 1 <-fireTimeFrames CreateEffectClipped
endif
endif

<-fireDelay 1 add ->fireDelay
<-ammo 0 gt if
<-ammo <-fireStep sub ->ammo
Self CONST_AMMO <-ammo SetUnitAttribute
endif

<-fireDelay <-fireTimeFrames eq if
#sets cells in terrRange to terrLevel
<-invalid eq0 if
<-terrRange 1 add <-terrY add <-terrY <-terrRange sub do
<-terrRange 1 add <-terrX add <-terrX <-terrRange sub do
I J <-getTerrain <-terrLevel neq if
I J <-terrLevel SetTerrain
endif
loop
loop
endif

3 ->state
Self <-beamName <-beamR <-beamG <-beamB 0 SetImageColor
Self CONST_AMMO 0 SetUnitAttribute
endif
endif

#delay between firing and picking a new target
<-state 3 eq if
<-downTimeFrames Delay
0 ->state
endif

#gets random coords terrRange units away from map edge or
#picks within setFireRange of core if limitFireRangeBool is set
:GetRandCoords
<-limitFireRangeBool if
while
CurrentCoords <-setFireRange RandCoordsInRange ->terrY ->terrX
<-terrX <-terrRange lt <-terrX <-maxWidth gte or
<-terrY <-terrRange lt <-terrY <-maxHeight gte or or repeat
endwhile
else
<-terrRange <-maxWidth RandInt ->terrX
<-terrRange <-maxHeight RandInt ->terrY
endif
return

#defines an excluded zone where the prototype will never fire
:InExclusionZone
<-terrX 30 lte <-terrY 30 lte and
return

#checks if a landed player unit is within playerUnitCheckRange
:PlayerUnitInRange
<-terrX <-terrY <-playerUnitCheckRange GetUnitCountInRange
return

#check each cell in terrRange for AC on it,
#whether it's occupied or void,
#and if at least one would be raised/lowered
:CheckCells
0 ->invalidCheck
1 ->nochange
<-terrRange 1 add <-terrY add <-terrY <-terrRange sub do
<-terrRange 1 add <-terrX add <-terrX <-terrRange sub do
I J GetTerrain ->cell
<-cell -1 eq I J GetCreeper 0 lt or
I J GetCellOccupiedCount or ->invalidCheck
<-invalidCheck if break endif
<-cell <-terrLevel neq if
0 ->nochange
endif
Loop
<-invalidCheck if break endif
Loop
<-invalidCheck <-nochange or return

#randomly raises/lowers terrain under it if destroyed with at least 75% ammo
#honestly was just messing around when making this part
:destroyed
Self CONST_AMMO GetUnitAttribute 0.75 gte if
CurrentCoords ->Y ->X
<-X <-Y GetTerrain ->terrLevel
0 2 RandInt ->updown
<-updown eq0 if -1 ->updown endif
<-terrLevel 1 eq 1 ->updown
<-terrLevel 10 eq -1 ->updown
<-terrLevel <-updown add ->terrLevel
<-Y 2 add <-Y 1 sub do
<-X 2 add <-X 1 sub do
I J <-terrLevel SetTerrain
loop
loop
endif


Or a version that should be able to handle larger firing areas without SetTerrain lagging the game:
$limitFireRangeBool:1 #boolean
#don't just use a fire range larger than the whole map because
#there's a more efficient coordinate picker for whole map
$setFireRange:20
$playerUnitCheckRange:10
#0 for random up/down
$terpToLevel:0
#X by X effect box, where X is 1 + terrRange
#appears to work on 0 but is inefficient for changing only 1 cell
#beware of large terrRanges, especially with small fireTimeFrames!
$terrRange:1
$chargeTimeFrames:90
$fireTimeFrames:15
$downTimeFrames:29 #delay adds 1 frame

#initializing variables and the beam image
once
Self CONST_MAXAMMO 1.0 SetUnitAttribute
"Beam" ->beamName
255 ->beamR
102 ->beamG
0 ->beamB
255 ->beamA
Self <-beamName "Custom1" SetImage
Self <-beamName 2 SetImageScaleY
Self <-beamName <-beamR <-beamG <-beamB 0 SetImageColor

1.0 <-chargeTimeFrames div ->chargeStep
1.0 <-fireTimeFrames div ->fireStep
0 ->state
MapWidth <-terrRange sub ->maxWidth
MapHeight <-terrRange sub ->maxHeight
#TODO: find better effectscales for larger terrRanges?
2 <-terrRange mul 2 add ->terpEffScale

<-terpToLevel 1 lt <-terpToLevel 10 gt or if
0 ->terpToLevel
endif
endonce

#target picking
<-state eq0 if
0 ->ammo
Self CONST_AMMO 0 SetUnitAttribute
1 ->count
1 ->invalid
0 ->chargeDelay
0 ->fireDelay
CreateList ->cellList
CreateList ->fireList

#try up to 5 times to find a valid random target
#where valid is no would-be affected cells in void or AC,
#no player units within playerUnitCheckRange,
#not within zone(s) defined by @inExlusionZone,
#no cells are occupied,
#and at least one cell would be raised/lowered
while <-count 5 lte <-invalid and repeat
0 ->invalid
@GetRandCoords
<-count 1 add ->count
@PlayerUnitInRange <-terrX <-terrY GetVoid or
@InExclusionZone or ->invalid
<-invalid not if
<-terrX <-terrY GetTerrain ->terrLevel

<-terpToLevel if
#raises/lowers towards terpToLevel
<-terrLevel <-terpToLevel lt if
<-terrLevel 1 add ->terrLevel
endif
<-terrLevel <-terpToLevel gt if
<-terrLevel 1 sub ->terrLevel
endif
else
#randomly raises/lowers terrain by 1
0 2 RandInt ->updown
<-updown eq0 if -1 ->updown endif
<-terrLevel <-updown add 1 max 10 min ->terrLevel
endif

<-invalid @CheckCells or ->invalid
endif
endwhile
1 ->state
endif

#charging
<-state 1 eq if
<-invalid eq0 if
<-ammo 1 lt if
<-ammo <-chargeStep add ->ammo
Self CONST_AMMO <-ammo SetUnitAttribute
endif
endif

<-chargeDelay 1 add ->chargeDelay
<-chargeDelay <-chargeTimeFrames eq if
2 ->state
endif
endif

#firing
<-state 2 eq if
#fizzle or start firing
<-invalid eq0 <-fireDelay eq0 and if
#checks if target is still valid
@PlayerUnitInRange @CheckCells or ->invalid

#dumps ammo and plays an animation if not
<-invalid if
14 CurrentPixelCoords -0.02 1 1 1 <-fireTimeFrames CreateEffectClipped
0 ->ammo
Self CONST_AMMO 0 SetUnitAttribute
else

#get cells to change per frame
#divides work over multiple frames because SetTerrain lags
#when changing many cells per frame
<-cellList GetListCount 2 div ->count
<-count asfloat <-fireTimeFrames div ceil ->cellsPerFrame
<-fireTimeFrames 0 do
<-count <-cellsPerFrame min ->cells
<-count <-cells sub ->count
<-cells if
I 1 add <-fireTimeFrames eq if
<-cells <-count add ->cells
endif
<-fireList <-cells AppendToList
else
<-fireList 0 PrependToList
endif
loop

#rotates and scales beam and draws terp effect
#thanks to Virgil for the code shamelessly grabbed from the Credits map
<-terrX <-terrY CellToPixel ->targetY ->targetX
CurrentPixelCoords ->selfY ->selfX
<-targetX <-selfX sub ->deltaX
<-targetY <-selfY sub ->deltaY
<-deltaY <-deltaX atan2 ->angle

<-selfX <-selfY <-targetX <-targetY Distance ->distance
<-distance 24 div ->beamScaleX
<-deltaX 2 div ->beamX
<-deltaY 2 div ->beamY

Self <-beamName <-beamX <-beamY -0.02 SetImagePosition
Self <-beamName <-beamScaleX SetImageScaleX
Self <-beamName <-angle SetImageRotation
Self <-beamName <-beamR <-beamG <-beamB <-beamA SetImageColor
15 <-targetX <-targetY -0.03 <-terpEffScale dup 1 <-fireTimeFrames CreateEffectClipped
endif
endif

#set however many cells in fireList this frame to terrLevel
<-invalid eq0 if
<-fireList <-fireDelay GetListElement 0 do
<-cellList 0 GetListElement
<-cellList 1 GetListElement <-terrLevel SetTerrain
<-cellList 0 RemoveListElement
<-cellList 0 RemoveListElement
loop
endif

<-fireDelay 1 add ->fireDelay
<-ammo 0 gt if
<-ammo <-fireStep sub ->ammo
Self CONST_AMMO <-ammo SetUnitAttribute
endif

<-fireDelay <-fireTimeFrames eq if
3 ->state
Self <-beamName <-beamR <-beamG <-beamB 0 SetImageColor
Self CONST_AMMO 0 SetUnitAttribute
endif
endif

#delay between firing and picking a new target
<-state 3 eq if
<-downTimeFrames Delay
0 ->state
endif

#gets random coords terrRange units away from map edge or
#picks within setFireRange of core if limitFireRangeBool is set
:GetRandCoords
<-limitFireRangeBool if
while
CurrentCoords <-setFireRange RandCoordsInRange ->terrY ->terrX
<-terrX <-terrRange lt <-terrX <-maxWidth gte or
<-terrY <-terrRange lt <-terrY <-maxHeight gte or or repeat
endwhile
else
<-terrRange <-maxWidth RandInt ->terrX
<-terrRange <-maxHeight RandInt ->terrY
endif
return

#defines an excluded zone where the prototype will never fire
:InExclusionZone
<-terrX 30 lte <-terrY 30 lte and
return

#checks if a landed player unit is within playerUnitCheckRange
:PlayerUnitInRange
<-terrX <-terrY <-playerUnitCheckRange GetUnitCountInRange
return

#check each cell in terrRange for AC on it,
#whether it's occupied or void,
#and if at least one would be raised/lowered
#adds coordinates that would change to cellList if charged
:CheckCells
0 ->invalidCheck
1 ->nochange
<-terrRange 1 add <-terrY add <-terrY <-terrRange sub do
<-terrRange 1 add <-terrX add <-terrX <-terrRange sub do
I J GetTerrain ->cell
<-cell -1 eq I J GetCreeper 0 lt or
I J GetCellOccupiedCount or ->invalidCheck
<-invalidCheck if break endif
<-cell <-terrLevel neq if
0 ->nochange
<-chargeDelay if
<-cellList I AppendToList
<-cellList J AppendToList
endif
endif
Loop
<-invalidCheck if break endif
Loop
<-invalidCheck <-nochange or return

#randomly raises/lowers terrain under it if destroyed with at least 75% ammo
#honestly was just messing around when making this part
:destroyed
Self CONST_AMMO GetUnitAttribute 0.75 gte if
CurrentCoords ->Y ->X
<-X <-Y GetTerrain ->terrLevel
0 2 RandInt ->updown
<-updown eq0 if -1 ->updown endif
<-terrLevel 1 eq 1 ->updown
<-terrLevel 10 eq -1 ->updown
<-terrLevel <-updown add ->terrLevel
<-Y 2 add <-Y 1 sub do
<-X 2 add <-X 1 sub do
I J <-terrLevel SetTerrain
loop
loop
endif


Attached is the terp sprite I edited.

Clean0nion

#1
Well, this sure trumps my Corrupted Terp. I'll add this to the Corrupted Units thread.