User Tools

Site Tools


cw4:4rpl_tools

Editors

Note: to get a default editor associated with the .4rpl filetype, please read about file association.

NotePad++

Syntax Highlighting

Some community members created syntax highlighters for Notepad++. More detailed descriptions can be found on the respective pages for each highlighter.

Please check out the Notepad++ Guide on how to install highlighters if you don't know how.

  • Highlighter by Sanian. Comes with basic spellcheck by underlining offending text in red. A Standard and Dark version are available.
  • Highlighter by Alophox. Does not include spellcheck. This highlighter can be used with multiple themes.

Utilities

Console Scripts

These scripts can be run from the Console in the Mods section of the Mission Editor


Copy/Paste Utility

This script can be used to copy and paste terrain in a map.

New: now can copy arbitrary rectangle, use terrain overlay to show marked and copied areas. Also copy special terrain (breeder, mesh, etc.)

Click here for the source code.

Click here for the source code.

CopyPaste.4rpl
# Copy/Paste 2021-02-20
 
# ---------------------
# With grateful thanks to knucracker for his patient assistance 
# ---------------------
 
# Also copies special terrain
 
$lmb:0				# left click button
$rmb:1				# right click button
$themeSlot:1		# theme overlay slot to use
$copy:1				# true for copy
$markActive:0       # false until area selection start
 
GetPointerTerrainCoords ->mouseZ ->mouseX
@BlitImage
 
if (GetMouseButtonDown(<-lmb false)) 		# start copy area selection
	true ->markActive
	--area									# delete copy buffer
	if 	(@IsMouseValid)
			<-mouseZ ->areaStartZ 
			<-mouseX ->areaStartX 
	endIf
endIf
 
if (NOT(<-markActive) 
	AND (NOT(-?area)))
	Return 
endIf		# don't run rest if not selecting terrain
 
if (GetMouseButton(<-lmb false))			# track copy area size amd mark terrain 
	if 	(@IsMouseValid)
		<-mouseZ ->areaEndZ 
		<-mouseX ->areaEndX 
		MIN(<-areaStartZ <-areaEndZ) ->minZ
		MAX(<-areaStartZ <-areaEndZ) ->maxZ
		MIN(<-areaStartX <-areaEndX) ->minX
		MAX(<-areaStartX <-areaEndX) ->maxX
		FromCell(<-minX <-minZ) ->minV
		FroMCell(<-maxX <-MaxZ) ->maxV
 
		@MarkArea (V4(0 0 0 0) <-minVOld <-maxVOld) 	# Clear marker before painting new marker
		@MarkArea (V4(.4 .4 .4 .4) <-minV <-maxV)		# mark terrain
 
		<-minV ->minVOld
		<-maxV ->maxVOld
	endIf
endif
 
if (GetMouseButtonUp(<-lmb false))				# copy terrain, create blit image
	@MakeCopy
endIf
 
if (GetMouseButtonDown(<-rmb true))				# let's paste	
	If (-?area)
		@Paste
	else
		TraceAllSp ("Copy buffer is empty!")
	endIf
endIf
 
 
## mainline end - functiosn/routines follow
 
:MakeCopy
	CreateList ->area
	CreateList ->pasteImage
	toCell(<-maxV) ->_maxCellZ ->_maxCellX
	toCell(<-minV) ->_minCellZ ->_minCellX
	<-_maxCellX <-_minCellX  - ->blitWidth
	<-_maxCellZ <-_minCellZ  - ->blitHeight
#	Iterate over marked area, copying both cell height and setting texture overlay
	Do (<-_maxCellZ <-_minCellZ)
		Do (<-_maxCellX <-_minCellX)
			GetTerrain (I J ) ->_ter
			GetTerrainSpecial(I J) ->_terS
			V2(<-_ter <-_terS) ->_terData
			<-_ter 20.0 / ->c
			v4(<-c <-c <-c .6) ->_color
			AppendToList(<-area <-_terData)
			AppendToList(<-pasteImage <-_color)
		loop
	Loop
	TraceAllSp ("Copied " GetListCount(<-area) "cells. From min/max" <-minV <-maxV)
	If (GetListCount(<-area) eq0) --area endif 					# can't paste 0 zells
 
:BlitImage
	If(-?PasteImage)
		ClearThemeOverlay(<-themeSlot Vector0) 						# remove old mark
		SetThemeOverlayPixels(<-themeSlot, <-mouseX,  <-mouseZ,		# set paste overlay 	
			<-blitWidth <-blitHeight <-pasteImage)
	EndIf
 
:MarkArea
	toCell ->_maxCellZ ->_maxCellX
	toCell ->_minCellZ ->_minCellX
	->_tex
	<-_maxCellX <-_minCellX - ->_width
	<-_maxCellZ <-_minCellZ - ->_height 
	SetThemeOverlayRectPixels(<-themeSlot <-_minCellX  <-_minCellZ  <-_width <-_height <-_tex)
 
:Paste	
	if 	(@isMouseValid)
			<-mouseZ ->areaStartZ 
			<-mouseX ->areaStartX 
	else
		PlaySoundAtPosition("ADAMessage" 8 FromCell(<-mouseX <-mouseZ))
		Return
	endIf
	if (not(-?area)) 
		Trace ("Copy buffer empty!")
		PlaySoundAtPosition("ADAMessage" 8 FromCell(<-mouseX <-mouseZ))
		Return
	endif
	EditAddUndo(0)
	->listItem (0)
	toCell(<-maxV) ->_maxCellZ ->_maxCellX
	toCell(<-minV) ->_minCellZ ->_minCellX
 
	<-_maxCellZ <-_minCellZ - ->sizeZ
	<-_maxCellX <-_minCellX - ->sizeX
	Do (<-mouseZ <-sizeZ +, <-mouseZ)
		Do (<-mouseX  <-sizeX +,  <-mouseX)
			<-area[<-listItem] ->_terData
			EV2(<-_terdata) ->_terS ->_ter
			SetTerrain(I  J   <-_ter)
			SetTerrainSpecial(I  J   <-_terS)
			<-listItem 1 add ->listItem
		loop
	loop
	Trace3 ("pasted " <-listitem   "cells.")
 
:IsMouseValid
	if 	(<-mouseX gte0 
		and(<-mouseZ gte0) 
		and(<-mouseX lt(<-mapSizeX)) 
		and(<-mouseZ lt(<-mapSizeZ)))
		true 
	else
		false
	endIf
 
:once
	@Instructions
 
# null mouse positions
	-1 ->mouseOldZ 
	-1 ->mouseOldX
 
	GetMapSize ->mapSizeZ ->mapSizeX
	CreateThemeOverlay(<-themeSlot <-mapSizeX <-mapSizeZ Vector0)
	SetThemeOverlayEnabled(<-themeSlot true)
#	SetThemeOverlayPointFilter(<-themeSlot true)
 
	GetCameraTopDown ->initCamera  	# remember camera position
	SetCameraTopDown(true)
 
# end Once 
 
:Instructions
	TraceAllSp ("Left Mouse to mark terrain,") 
	TraceAllSp ("right mouse to paste")
	TraceAllSp ("Drag mouse to select area")
 
:Destroyed
	SetCameraTopDown(<-initCamera)
	SetThemeOverlayEnabled(<-themeSlot false)  	# delete
	DestroyThemeOverlay(<-themeSlot) 			# stomp on it



Terrain Export/Map Copy

Sometimes one might want to copy a terrain feature from one map to another.

That's not simple. This code will endeavor to assist, but it is a multi-step process.

  • Download the Map Export.4RPL* file and run it in the Console of the map that has the desired terrain feature. Note that every time you click the right mouse button, an export operation will be performed.
  • The Export operation creates code in the file
%HOMEPATH%\Documents\My Games\creeperworld4\rpl.txt

If you close and open a new map in the game, the file will be erased, so make sure to save the contents before opening the next map.

  • There will be one or more (depending on how many exports you created) 4RPL programs in the file. All lines in the file will start with CONSOLE: that you need to remove in a text editor. A global change should suffice.
  • Import these scripts into the Console and run them in the map where you desire to create the exported terrain feature.

Click here for the source code.

Click here for the source code.

Map Export.4rpl
# BigExport 2121-05-17
 
# exports a set of 4RPL instructions that can be used to replicate
# part of a map in another map.
# Exports Terrain and special terrain settings.
# 
# A 4RPL script will be created in the rpl.txt file in the Creeper World 4 folder
# every time  you copy terrai, another script will be appended to the file (in the same map editing session).
# You should save these scripts because next mission you open will overwrite the file. 
# Edit the output file to remove the "Console:" prefix to every line.
# run the clean 4RPL script in the map where you want the terrain to be imported.
#
# With grateful thanks to knucracker who helped resolve my dumb blunders 
#  and provided the necessary APIs
 
$exports:0          # increment counter every export operation. 
$lmb:0				# left click button
$rmb:1				# right click button
$themeSlot:1		# theme overlay slot to use
$markActive:0		# false until area selection start
 
GetPointerTerrainCoords ->mouseZ ->mouseX
 
if (GetKeyDown("A" false))
	Trace("A Pressed")
	GetMapSize ->maxCellZ ->maxCellX
	0 ->minCellX
	0 ->minCellZ
	@export
endif
 
if (GetMouseButtonDown(<-lmb false)) 		# start copy area selection
	if 	(@IsMouseValid)
			<-mouseZ ->areaStartZ
			<-mouseX ->areaStartX
			true ->markActive
			--area							# delete old copy buffer
	endIf
endIf
 
if (NOT(<-markActive)) 		# don't run rest if not selecting terrain
	Return
endIf
 
if (GetMouseButton(<-lmb false))			# track copy area size and mark terrain
	if 	(@IsMouseValid)
		<-mouseZ ->areaEndZ
		<-mouseX ->areaEndX
		MIN(<-areaStartZ <-areaEndZ) ->minZ
		MAX(<-areaStartZ <-areaEndZ) ->maxZ
		MIN(<-areaStartX <-areaEndX) ->minX
		MAX(<-areaStartX <-areaEndX) ->maxX
		FromCell(<-minX <-minZ) ->minV
		FroMCell(<-maxX <-MaxZ) ->maxV
 
		@MarkArea (V4(0 0 0 0) <-minVOld <-maxVOld) 	# Clear marker before painting new marker
		@MarkArea (V4(.4 .4 .4 .4) <-minV <-maxV)		# mark terrain
 
		<-minV ->minVOld
		<-maxV ->maxVOld
	endIf
endif
 
if (GetMouseButtonUp(<-lmb false))				# copy terrain, create blit image
	@MarkArea (V4(0 0 0 0) <-minVOld <-maxVOld) # Clear marker 
	toCell(<-maxV) ->maxCellZ ->maxCellX
	toCell(<-minV) ->minCellZ ->minCellX
	<-maxCellX <-minCellX  - ->blitWidth
	<-maxCellZ <-minCellZ  - ->blitHeight
	@Export
endIf
 
# --- end mainline ---
 
:Export
	<-exports 1 + ->exports
	@PrintPreamble
	@CopyTerrain
	@PrintPostamble
	TraceAll ("Exported " <-cells " terrain cells
				in " <-rows " rows and " <-columns " columns.")
 
:CopyTerrain
	0 ->cells
	0 ->rows
 
	PrintAll (":BuildListTerrain ")
#	Iterate over marked area, copying cell height 
# 	Copy Terrain
	"" ->terData
	Do (<-maxCellZ <-minCellZ)
		<-rows 1 + ->rows
		0 ->columns
		Do (<-maxCellX <-minCellX)
			<-columns 1 + ->columns
			<-cells 1 + ->cells
			GetTerrain (I J ) ->ter
			 if (<-ter 10 <) <-terData " " concat ->tmp endif
			 <-terData <-ter concat ->terData
             <-terData " " concat ->terData
		loop
		PrintAll (<-terData)
		"" ->terData
	loop
		PrintAll ("	List ->pasteTerrain ")
 
#copy special terrain
	PrintAll (":BuildListSpecial ")
	"" ->terSData
	Do (<-maxCellZ <-minCellZ)
		Do (<-maxCellX <-minCellX)
			GetTerrainSpecial(I J) ->terS
			 if (<-terS 10 <) <-terSData " " concat ->tmp endif
			 <-terSData <-terS concat ->terSData
             <-terSData " " concat ->terSData
		loop
		PrintAll (<-terSData)
		"" ->terSData
	loop
 
	PrintAll ("	List ->pasteSpecial  ")
 
	TraceAllSp ("Copied " <-cells "cells. From min/max" <-minV <-maxV)
	If (GetListCount(<-area) eq0) --area endif 					# can't paste 0 zells
 
 
:MarkArea
	toCell ->maxCellZ ->maxCellX
	toCell ->minCellZ ->minCellX
	->_tex
	<-maxCellX <-minCellX - ->_width
	<-maxCellZ <-minCellZ - ->_height
	SetThemeOverlayRectPixels(<-themeSlot <-minCellX  <-minCellZ
		<-_width <-_height <-_tex)
 
:IsMouseValid
	if 	(<-mouseX gte0
		and(<-mouseZ gte0)
		and(<-mouseX lt(<-mapSizeX))
		and(<-mouseZ lt(<-mapSizeZ)))
		true
	else
		TraceAllSp ("Mouse not over terrain.")
		PlaySoundAtPosition("ADAMessage" 8 FromCell(<-mouseX <-mouseZ))
 
		false
	endIf
 
:once
	@Instructions
 
# null mouse positions
	-1 ->mouseOldZ
	-1 ->mouseOldX
 
	GetMapSize ->mapSizeZ ->mapSizeX
	CreateThemeOverlay(<-themeSlot <-mapSizeX <-mapSizeZ Vector0)
	SetThemeOverlayEnabled(<-themeSlot true)
#	SetThemeOverlayPointFilter(<-themeSlot true)
 
	GetCameraTopDown ->initCamera  	# remember camera position
	SetCameraTopDown(true)
 
	GetPrintPrefixEnabled ->enabled
	SetPrintPrefixEnabled(false)
 
# end Once
 
:Instructions
	TraceAll   ("Press " DQ "A" DQ " to export the entire map.")
	TraceAllSp (" OR ")
	TraceAllSp ("Left Mouse to mark terrain,")
	TraceAllSp ("Drag mouse to select area")
	TraceAllSp ("Mouse up to export selected area")
	TraceAllSp
	TraceAllSP ("Beeping sound means mouse is not over valid area.")
 
:Destroyed
	TraceAllSP ("")
	If(<-exports eq0)
		TraceAllSp ("No map copy operations were performed.")
	else
		TraceAllSP ("Remember to save rpl.txt now!")
		If (<-exports eq (1))
			TraceAllSp ("One map export operation performed.")
		else
			TraceAllSp (<-exports "Map copy operations performed.")
		endIf
	endIf
	TraceAllSP ("")
	SetCameraTopDown(<-initCamera)
	SetPrintPrefixEnabled(<-enabled)
	SetThemeOverlayEnabled(<-themeSlot false)  	# delete
	DestroyThemeOverlay(<-themeSlot) 			# stomp on it
 
:PrintPreamble
	PrintAll ("# Terrain Import V 2.0. Copy Tick Timer: " GetGameTickCount )
	PrintAll (" ")
 
	PrintAll ("$lmb:0			# left click button  ")
	PrintAll ("$rmb:1			# right click button ")
	PrintAll ("$themeSlot:1		# theme overlay slot to use ")
	Printall (" ")
 
	PrintAll ("Once  ")
	PrintAll ("TraceAllSp ( " DQ "Use right mouse button to paste." DQ ")"  )
	PrintAll (<-blitWidth " ->blitWidth   ")
	PrintAll (<-blitHeight " ->blitHeight  ")
	PrintAll ("	GetMapSize ->mapSizeZ ->mapSizeX  ")
	PrintAll ("	GetCameraTopDown ->initCamera  	# remember camera position  ")
	PrintAll ("	SetCameraTopDown(true)  ")
	PrintAll ("	@BuildListTerrain  ")
	PrintAll ("	@BuildListSpecial  ")
	PrintAll ("	@MakeBlitImage  ")
	PrintAll ("endOnce  ")
	PrintAll (" ")
 
	PrintAll ("GetPointerTerrainCoords ->mouseZ ->mouseX ")
	PrintAll ("@BlitImage ")
	PrintAll (" ")
 
	PrintAll ("if (GetMouseButtonDown(<-rmb true )) ")
	PrintAll ("    if (@isMouseValid) ")
	printall ("        @Import ")
	PrintAll ("    endIf  ")
	printall ("endif ")
	PrintAll (" ")
 
	PrintAll (":Import ")
	PrintAll ("    EditAddUndo (0) ")
	PrintAll ("    0 ->rows ")
	Printall ("    0 ->cell ")
	Printall ("    Do (<-mouseZ <-blitHeight + , <-mouseZ ) ")
	Printall ("        <-rows 1 + ->rows ")
	PrintAll ("        0 ->columns ")
	Printall ("        Do (<-mouseX <-blitWidth +, <-mouseX  ) ")
	Printall ("            SetTerrain (I J  <-pasteTerrain[<-cell]) ")
	Printall ("            SetTerrainSpecial (I J <-pasteSpecial[<-cell]) ")
	Printall ("            <-cell 1 + ->cell ")
	Printall ("            <-columns 1 + ->columns ")
	Printall ("        loop ")
	Printall ("     loop ")
	PrintAll ("     TraceAll (" DQ "Imported " DQ " <-cell " DQ " terrain cells  in " DQ " <-rows " DQ " rows and " DQ " <-columns " DQ " columns." DQ ") ")
	PrintAll (" ")
 
	PrintAll (":BlitImage ")
	PrintAll ("		ClearThemeOverlay(<-themeSlot Vector0) 	 ")					# remove old mark ")
	PrintAll ("		SetThemeOverlayPixels(<-themeSlot, <-mouseX,  <-mouseZ,		# set paste overlay 	 ")
	PrintAll ("		<-blitWidth <-blitHeight <-blitMap) ")
	Printall ("	")
 
	PrintAll (":MakeBlitImage ")
	pRINTaLL ("	CreateList ->blitMap	")
	pRINTaLL ("	0 ->i 	")
	pRINTaLL ("	Do (<-blitHeight  0) 	")
	pRINTaLL ("		Do (<-blitWidth 0 ) 	")
	pRINTaLL ("			<-pasteTerrain[<-i] ->c 	")
	pRINTaLL ("			<-c 20.0 / ->c 	")
	pRINTaLL ("			v4(<-c <-c <-c .6) ->color 	")
	pRINTaLL ("			AppendToList(<-blitMap <-color) 	")
	pRINTaLL ("			<-i 1 + ->i 	")
	pRINTaLL ("		loop 	")
	pRINTaLL ("	Loop 	")
	pRINTaLL ("	GetMapSize ->mapSizeZ ->mapSizeX	")
	pRINTaLL ("	CreateThemeOverlay(<-themeSlot <-mapSizeX <-mapSizeZ Vector0)	")
	pRINTaLL ("	SetThemeOverlayEnabled(<-themeSlot true)	")
	pRINTaLL ("	TraceAllSp (<-i " DQ " cells in blit map " DQ " ) ")
	Printall ("	")
 
	PrintAll (" ")
	PrintAll (":IsMouseValid ")
	PrintAll ("		if 	(<-mouseX gte0  ")
	PrintAll ("			and(<-mouseZ gte0)  ")
	PrintAll ("			and(<-mouseX lt(<-mapSizeX))  ")
	PrintAll ("			and(<-mouseZ lt(<-mapSizeZ))) ")
	PrintAll ("			true  ")
	PrintAll ("		else ")
	PrintAll ("			false ")
	PrintAll ("		endIf ")
	PrintAll (" ")
 
	PrintAll (":Destroyed")
	PrintAll ("	SetCameraTopDown(<-initCamera) ")
	PrintAll ("	SetThemeOverlayEnabled(<-themeSlot false)  	# delete ")
	PrintAll ("	DestroyThemeOverlay(<-themeSlot) 			# stomp on it ")
	PrintAll (" ")
	PrintAll (" ")
:PrintPostamble
	PrintAll ("### End ### ")





Change notes:

  • V3
    • now can export whole map with one key. Press “a”
    • message indicating how many operations were performed. For each uperation, there will be one program in RPL.txt.
  • V2 Change notes:
    • New version. Uses Terrain texture to show image
  • V2.1 Change notes
    • The` CONSOLE:` prefix is now suppressed, making it a bit easier to run.

Sound Player

Looking for just that right sound for your next unit?

Here is a player that lets you evaluate all the available in-game sounds. You know the drill. Download, and run from the Console.

Click here for the source code

Click here for the source code

Sound Player.4rpl
# Sounds
 
$rmb:1			# right click button
$index:0
 
Once
	@MakeSoundList
endOnce
 
if (GetMappedKeyDown("Custom1" false))
	Mod(<-Index 1 +, <-soundCount) ->index
	<-soundList[<-index] ->soundName
	TraceAll ("This is sound #" <-index ", " DQ <-soundName DQ)
endIf
 
if (GetMappedKeyDown("Custom2" false))
	Mod2(<-Index 1 -, <-soundCount) ->index
	<-soundList[<-index] ->soundName
	TraceAll ("This is sound #" <-index ", " DQ <-soundName DQ)
endIf
 
if (GetMouseButtonDown(<-rmb true ))
	PlaySound(<-soundName 8)	
endif
 
:MakeSoundList
 
		"ADAMessage"  
		"ADAMessagesClose"  
		"ADAMessagesOpen"  
		"Achievement"
		"Aircraft"  
		"Aircraft2"  
		"BaseLand"  
		"BerthaExplosion"  
		"BerthaFire"  
		"BombDrop"  
		"BombDropSlide"  
		"BombExplosion"  
		"BraveWarning"  
		"ButtonClick"  
		"Click 1"  
		"Click"  
		"Click2"  
		"CloseClick"  
		"Damper"  
		"DamperDone"  
		"Dematerialize"  
		"EggBrave"  
		"EggBurst"  
		"EggReleased"  
		"ErrorBuild"  
		"Explosion"  
		"Explosion_1"  
		"Explosion_10"  
		"Explosion_11"  
		"Explosion_12"  
		"Explosion_2"  
		"Explosion_3"  
		"Explosion_4"  
		"Explosion_5"  
		"Explosion_7"  
		"Explosion_8"  
		"Explosion_9"  
		"HoverOpen"  
		"InfoCacheCollected"  
		"Materialize"  
		"MinimapAlert"  
		"MissileExplosion"  
		"MissileLaunch"  
		"MissionFail"  
		"MissionObjective"  
		"MissionObjectiveFail"  
		"MissionObjectiveRequiredComplete"  
		"MissionScan"    "InhibitorFiring"   
		"MissionSpaceInitiateJump"  
		"MissionSpacePanelClose"  
		"MissionSpacePanelOpen"  
		"MissionSpaceRegionNavSelect"  
		"MissionWin"  
		"MortarFire"  
		"MortarShellExplosion"  
		"NeutronBurst"  
		"Notify"  
		"PlanetView"  
		"PlanetView2"  
		"RainDrop"  
		"Rematerialize"  
		"RiftLabDepart"  
		"Sci Fi Explosion 01"  
		"Sci Fi Explosion 02"  
		"Sci Fi Explosion 03"  
		"Sci Fi Explosion 04"  
		"Sci Fi Explosion 05"  
		"Sci Fi Explosion 06"  
		"Sci Fi Explosion 07"  
		"Sci Fi Explosion 08"  
		"Sci Fi Explosion 09"  
		"Sci Fi Explosion 10"  
		"Sci Fi Explosion 11"  
		"Sci Fi Explosion 12"  
		"Sci Fi Explosion 13"  
		"Sci Fi Explosion 14"  
		"Sci Fi Explosion 15"  
		"Sci Fi Explosion 16"  
		"Sci Fi Explosion 17"  
		"Sci Fi Explosion 18"  
		"Sci Fi Explosion 19"  
		"Sci Fi Explosion 20"  
		"Sci Fi Explosion 21"  
		"Sci Fi Explosion 22"  
		"Sci Fi Explosion 23"  
		"Sci Fi Explosion 24"  
		"Shutdown"  
		"Singularity"  
		"SingularityDone"  
		"SingularityLaunch"  
		"SniperFire"  
		"SporeHit"  
		"SporeLaunch"  
		"SporePrelaunch"  
		"SprayerFire"  
		"Stun"    "CannonFire"  
		"SurviveBaseOffline"  
		"SurviveBaseWarn"  
		"ThorGun"  
		"TotemExplosion"   "UnitHoverLand"  
		"UnitBuild"  
		"UnitExplosion"  
		"UnitHoverTakeoff"  
		"UnitLand"  
		"UnitPlace"  
		"UnitTakeoff"  
		"Warning"  
		"Warning2"  
	List ->soundList
 
		"AlarmClock" 
		"GreenarRefinery"  
		"InhibitorArming"
		"Overloading" 
		"Pulsing Ambience"  
		"Rocket" 
		"SoundLoop_alarm0"  
		"SoundLoop_alarm1"  
		"SoundLoop_alarm10"  
		"SoundLoop_alarm11"  
		"SoundLoop_alarm12"  
		"SoundLoop_alarm13"  
		"SoundLoop_alarm14"  
		"SoundLoop_alarm15"  
		"SoundLoop_alarm2"  
		"SoundLoop_alarm3"  
		"SoundLoop_alarm4"  
		"SoundLoop_alarm5"  
		"SoundLoop_alarm6"  
		"SoundLoop_alarm7"  
		"SoundLoop_alarm8"  
		"SoundLoop_alarm9"  
		"SoundLoop_ambience0"  
		"SoundLoop_ambience1"  
		"SoundLoop_ambience10"  
		"SoundLoop_ambience2"  
		"SoundLoop_ambience3"  
		"SoundLoop_ambience4"  
		"SoundLoop_ambience5"  
		"SoundLoop_ambience6"  
		"SoundLoop_ambience7"  
		"SoundLoop_ambience8"  
		"SoundLoop_ambience9"  
		"SoundLoop_gun0"  
		"SoundLoop_gun1"  
		"SoundLoop_gun2"  
		"SoundLoop_gun3"  
		"SoundLoop_hum0"  
		"SoundLoop_hum1"  
		"SoundLoop_hum10"  
		"SoundLoop_hum11"  
		"SoundLoop_hum12"  
		"SoundLoop_hum13"  
		"SoundLoop_hum14"  
		"SoundLoop_hum15"  
		"SoundLoop_hum16"  
		"SoundLoop_hum17" 
		"SoundLoop_hum18"  
		"SoundLoop_hum2"  
		"SoundLoop_hum3"  
		"SoundLoop_hum4"  
		"SoundLoop_hum5"  
		"SoundLoop_hum6"  
		"SoundLoop_hum7"  
		"SoundLoop_hum8"  
		"SoundLoop_hum9"  
		"SoundLoop_machine0"  
		"SoundLoop_machine1"  
		"SoundLoop_machine10"  
		"SoundLoop_machine11"  
		"SoundLoop_machine12"  
		"SoundLoop_machine2"  
		"SoundLoop_machine3"  
		"SoundLoop_machine4"  
		"SoundLoop_machine5"  
		"SoundLoop_machine6"  
		"SoundLoop_machine7"  
		"SoundLoop_machine8" 
		"SoundLoop_machine9"  
		"SoundLoop_misc0"  
		"SoundLoop_misc1"  
		"SoundLoop_misc2"  
		"SoundLoop_misc3"  
		"SoundLoop_misc4"  
		"SoundLoop_misc5"  
		"SoundLoop_misc6"  
		"SoundLoop_misc7"  
		"SoundLoop_misc8"
		"TotemFire" 
		"ambient" 
	List ->loopSoundList
 
	GetListCount(<-soundList) ->soundCount
	TraceAllSp ("List of " <-soundCount "sounds available")
	TraceAllSp ("There are also " GetListCOunt(<-loopSoundList) "looping sounds that cannot be played in this module")
	TraceAllSP ("Press and hold user key 1/2 to scroll through the sound list." )
	TraceAllSp ("Left-click mouse to listen to it.")

Map Information

Looking for some general map information on a specific map, including how much of various resources can be produced? This script is primarily income related information, but there's a little bit of general information in there, too.

All values should be correct, but errors are possible. Below is a sample output of a chronum map, and the source itself that you can put in as a console script. There's some notes about the output in the top of the source code.

Sample Output

Sample Output

 Ground Tiles: 12340 
 Resource Tiles: 620 
 Void Tiles: 904 
 Eco: 347 / 347 
 
 Potential Soylent Energy: 34.06 
 Eco Energy Value: 3.83 
 
 Resource Terrain could be 
 Energy Gen: 41 or 
 Bluite: 516.67 /min 
 
 Map resources per minute 
 Bluite: 0 
 Redon: 90 
 Greenar Crystals: 9.68 
 Liftic Produced:  116.2 

click here for source code

click here for source code

file MapInfo.4rpl
#"Notes: You have to advance a frame for eco counts to be updated."
#"Values assume no ERNs"
#"Soylent value assumes flat terrain, and 100% efficiency."
 
GetMapSize ->sizeZ ->sizeX
 
0 ->tiles
0 ->void
0 ->resource
0 ->crystalsMin
0 ->blueMin
0 ->redMin
 
Createtable ->table
0 ->table{1}
 
<-sizeZ 0 do
	<-sizeX 0 do
		GetTerrain(i j) ->terrainHeight
		if (<-terrainHeight gt0)
			<-tiles 1 add ->tiles
			GetTerrainSpecial(i j) ->specialTerrainSlot
			<-table{<-specialTerrainSlot} 1 add ->table{<-specialTerrainSlot}
		else
			<-void 1 add ->void
		endif
	loop
loop
 
GetUnitsByType("resourcered" 1) ->units
<-units GetListCount 0 do	
	GetUnitSettings(<-units[i]) ->unitSettings
	<-redMin 1800 <-unitSettings{"Interval"} div add ->redMin
loop
 
GetUnitsByType("resourceblue" 1) ->units
<-units GetListCount 0 do	
	GetUnitSettings(<-units[i]) ->unitSettings
	<-blueMin 1800 <-unitSettings{"Interval"} div add ->blueMin
loop
 
 
GetUnitsByType("greenarmother" 1) ->units
 
<-units GetListCount 0 do	
	0 ->validTiles
	GetUnitCell(<-units[i]) ->posZ ->posX
	<-posZ 11 add <-posZ 10 sub do
		<-posX 11 add <-posX 10 sub do
			DistanceCell((<-posX) (<-posZ) i j) ->dist
			if (<-dist 10.5 lte)					
				i ->x
				j ->z
				@TileOkay
				if (<-okay gt0)
					<-validTiles 1 add ->validTiles
				endif
			endif	
		loop
	loop
	<-validTiles 339.0 div ->pct
	GetUnitSettings(<-units[i]) ->unitSettings
	<-crystalsMin 1800 <-unitSettings{"Interval"} div <-pct mul add ->crystalsMin	
loop
 
GetEcoCounts ->liveCount ->stumpCount
<-stumpCount <-liveCount add ->totalEco
 
" Ground Tiles:" <-tiles LF
"Resource Tiles:" <-table{1} LF
"Void Tiles:" <-void LF
"Eco:" <-liveCount "/" <-totalEco LF
LF
"Potential Soylent Energy:" <-tiles 0.00276 mul 2 round lf
"Eco Energy Value:" <-totalEco 0.01104 mul 2 round lf
lf
"Resource Terrain could be" lf
"Energy Gen:" <-table{1} 15 div "or" lf
"Bluite:" <-table{1} 1.2 div 2 round "/min" lf
LF
"Map resources per minute" LF
"Bluite:" <-blueMin 2 round lf
"Redon:" <-redMin 2 round lf
"Greenar Crystals:" <-crystalsMin 2 round lf
"Liftic Produced: " <-crystalsMin 12 mul 1 round lf
 
 
traceallsp
 
:TileOkay
1 ->okay
GetTerrain(<-x <-z) ->terrainHeight
if (<-terrainHeight lte0 GetCellOccupiedCount(<-x <-z) gt0 or)
	0 ->okay
	return
endif
<-z 2 add <-z 1 sub do
	<-x 2 add <-x 1 sub do
		if (GetTerrain(i j) <-terrainHeight neq )
			0 ->okay
			break
		endif
	loop
loop

Measure Execution Time

Optimizing code is important. This helps you quickly test how well different options run and choose the best one. Also can check for loose items on the stack if you want.

click here for source code

click here for source code

Execution Time.4rpl
$avgNum:10 #The average, min, and max will be over this many invocations.
$showMin:1
$showAvg:1
$showMax:1
$checkStack:1
$iterations:1000 #How many times to execute the code every invocation.
 
ElapsedTime ->start
<-iterations 0 do
	#CODE TO MEASURE GOES HERE
loop
@EndMeasure
 
#===============
 
:Once
	<-avgNum CreateListStartingSize ->timeList
 
:EndMeasure
	ElapsedTime <-start sub ->timeTaken
	if(StackSize <-checkStack &&)
		Trace(StackSize <-iterations div " items left on the stack!" concat)
	endif
	ClearStack
 
	<-timeTaken ->timeList[InvocationCount <-avgNum mod]
 
	9999999 ->min
	0 ->max
	0
	InvocationCount 1 add <-avgNum min 0 do #Find the average
		<-timeList[i] 
		dup <-min min ->min
		dup <-max max ->max
		add
	loop
	<-avgNum InvocationCount min div ->avg
 
	<-timeTaken @Pad
	if(<-showMin)
		"min: " <-min @Pad
	endif
	if(<-showAvg)
		"avg: " <-avg 1 round @Pad
	endif
	if(<-showMax)
		"max: " <-max @Pad
	endif
	TraceAll 
 
#Gets close, but non-monospace fonts (like the tracelog) aren't exact.
#Doesn't use a tab because sometimes that makes the issue worse.
:Pad
	dup StringLength 8 swap sub 0 do
		"  "
	loop 

Map Symmetry/Transform Tool

Run this script in console to provide several functions that can copy half/quarter of the map and reflect/rotate and paste it (special terrain types are also copied, but units and creeper are not). Any operation may be undone with Ctrl-Z or redone with Ctrl-Y. Key binds are shown at the top of the script, and are also shown/described here for ease of use.

Be aware that some functions will not execute on non-square maps since symmetry cannot be maintained.

Click here for source code

Click here for source code

Symmetrifier.4rpl
# Symmetrifier
 
#		How to use: Paste script into console script file, run (not just once), then press one of the keys shown in the list below to perform the the described symmetry/map transform operation
 
#		NOTE: Units are not affected by any of the below functions
#		NOTE: On maps with odd-numbered side lengths, a 1-wide strip of terrain in the middle is unaffected
#		NOTE: Script uses above-keyboard number keys and left-hand modifier keys (left alt, left shift and left control)
#		=================================
#		|1| = Left to Right Reflectional
#		|2| = Right to Left Reflectional
#		|3| = Bottom to Top Reflectional
#		|4| = Top to Bottom Reflectional
#		|5| = Bottom Left to Top Right Diagonal Reflectional (Requires Square Map)
#		|6| = Top Right to Bottom Left Diagonal Reflectional (Requires Square Map)
#		|7| = Bottom Right to Top Left Diagonal Reflectional (Requires Square Map)
#		|8| = Top left to Bottom Right Diagonal Reflectional (Requires Square Map)
#		|9| = Bottom Left Quadrilateral Reflectional
#		|0| = Bottom Right Quadrilateral Reflectional
#		|Shift+1| = Top Left Quadrilateral Reflectional
#		|Shift+2| = Top Right Quadrilateral Reflectional
#		=============================================
#		|Shift+3| = Left Half Rotational
#		|Shift+4| = Right Half Rotational
#		|Shift+5| = Top Half Rotational
#		|Shift+6| = Bottom Half Rotational
#		|Shift+7| = Bottom Left Half Diagonal Rotational
#		|Shift+8| = Bottom Right Half Diagonal Rotational
#		|Shift+9| = Top Left Half Diagonal Rotational
#		|Shift+0| = Top Right Half Diagonal Rotational
#		|Alt+1| = Bottom Left Quarter Rotational (Requires Square Map)
#		|Alt+2| = Bottom Right Quarter Rotational (Requires Square Map)
#		|Alt+3| = Top Left Quarter Rotational (Requires Square Map)
#		|Alt+4| = Top Right Quarter Rotational (Requires Square Map)
#		|Alt+5| = Left Quarter Rotational (Requires Square Map)
#		|Alt+6| = Right Quarter Rotational (Requires Square Map)
#		|Alt+7| = Top Quarter Rotational (Requires Square Map)
#		|Alt+8| = Bottom Quarter Rotational (Requires Square Map)
#		====================================
#		|Ctrl+1| = Rotate Map 90 Clockwise  (Requires Square Map)
#		|Ctrl+2| = Rotate Map 90 Counterclockwise (Requires Square Map)
#		|Ctrl+3| = Rotate Map 180
#		|Ctrl+4| = Flip Map Left to Right
#		|Ctrl+5| = Flip Map Top to Bottom
#		|Ctrl+6| = Flip Map Bottom Left to Top Right Diagonal (Requires Square Map)
#		|Ctrl+7| = Flip Map Bottom Right to Top Left Diagonal (Requires Square Map)
#		=============================================
#		|Ctrl+Arrow Key| = Scroll Map 1 tile in direction
#		|Shift+Arrow Key| = Scroll Map 10 tiles in direction
 
once
 
GetMapSize ->mapHeight ->mapWidth
if(<-mapWidth 2 mod neq0)
	<-mapWidth 1 sub 2 div ->halfWidth
else
	<-mapWidth 2 div ->halfWidth
endif
if(<-mapHeight 2 mod neq0)
	<-mapHeight 1 sub 2 div ->halfHeight
else
	<-mapHeight 2 div ->halfHeight
endif
if(<-mapHeight <-mapWidth eq)
	true ->squareMap
else
	false ->squareMap
endif
CreateListStartingSize(<-mapHeight <-mapWidth mul) ->terrainBuffer #Only used in flipping/rotating/scrolling map
CreateListStartingSize(<-mapHeight <-mapWidth mul) ->specialBuffer #Ditto
 
endonce
 
if(GetKey("LeftShift" true))
	if(GetKeyDown("Alpha1" true)) EditAddUndo(0) @TopLeftQuadrilateral endif
	if(GetKeyDown("Alpha2" true)) EditAddUndo(0) @TopRightQuadrilateral endif
	if(GetKeyDown("Alpha3" true)) EditAddUndo(0) @LeftHalfRotational endif
	if(GetKeyDown("Alpha4" true)) EditAddUndo(0) @RightHalfRotational endif
	if(GetKeyDown("Alpha5" true)) EditAddUndo(0) @TopHalfRotational endif
	if(GetKeyDown("Alpha6" true)) EditAddUndo(0) @BottomHalfRotational endif
	if(GetKeyDown("Alpha7" true)) EditAddUndo(0) @BottomLeftHalfRotational endif
	if(GetKeyDown("Alpha8" true)) EditAddUndo(0) @BottomRightHalfRotational endif
	if(GetKeyDown("Alpha9" true)) EditAddUndo(0) @TopLeftHalfRotational endif
	if(GetKeyDown("Alpha0" true)) EditAddUndo(0) @TopRightHalfRotational endif
	if(GetKeyDown("LeftArrow" true)) EditAddUndo(0) 10 ->scr @ScrollMapLeft endif
	if(GetKeyDown("RightArrow" true)) EditAddUndo(0) 10 ->scr @ScrollMapRight endif
	if(GetKeyDown("UpArrow" true)) EditAddUndo(0) 10 ->scr @ScrollMapUp endif
	if(GetKeyDown("DownArrow" true)) EditAddUndo(0) 10 ->scr @ScrollMapDown endif
else
if(GetKey("LeftAlt" true))
	if(GetKeyDown("Alpha1" true) true eq <-squareMap true eq and) EditAddUndo(0) @BottomLeftQuarterRotational endif
	if(GetKeyDown("Alpha2" true) true eq <-squareMap true eq and) EditAddUndo(0) @BottomRightQuarterRotational endif
	if(GetKeyDown("Alpha3" true) true eq <-squareMap true eq and) EditAddUndo(0) @TopLeftQuarterRotational endif
	if(GetKeyDown("Alpha4" true) true eq <-squareMap true eq and) EditAddUndo(0) @TopRightQuarterRotational endif
	if(GetKeyDown("Alpha5" true) true eq <-squareMap true eq and) EditAddUndo(0) @LeftQuarterRotational endif
	if(GetKeyDown("Alpha6" true) true eq <-squareMap true eq and) EditAddUndo(0) @RightQuarterRotational endif
	if(GetKeyDown("Alpha7" true) true eq <-squareMap true eq and) EditAddUndo(0) @TopQuarterRotational endif
	if(GetKeyDown("Alpha8" true) true eq <-squareMap true eq and) EditAddUndo(0) @BottomQuarterRotational endif
else
if(GetKey("LeftControl" true))
	if(GetKeyDown("Alpha1" true) true eq <-squareMap true eq and) EditAddUndo(0) @Rotate90Clockwise endif
	if(GetKeyDown("Alpha2" true) true eq <-squareMap true eq and) EditAddUndo(0) @Rotate90Counterclockwise endif
	if(GetKeyDown("Alpha3" true)) EditAddUndo(0) @Rotate180 endif
	if(GetKeyDown("Alpha4" true)) EditAddUndo(0) @FlipLeftToRight endif
	if(GetKeyDown("Alpha5" true)) EditAddUndo(0) @FlipTopToBottom endif
	if(GetKeyDown("Alpha6" true) true eq <-squareMap true eq and) EditAddUndo(0) @FlipBottomLeftToTopRight endif
	if(GetKeyDown("Alpha7" true) true eq <-squareMap true eq and) EditAddUndo(0) @FlipBottomRightToTopLeft endif
	if(GetKeyDown("LeftArrow" true)) EditAddUndo(0) 1 ->scr @ScrollMapLeft endif
	if(GetKeyDown("RightArrow" true)) EditAddUndo(0) 1 ->scr  @ScrollMapRight endif
	if(GetKeyDown("UpArrow" true)) EditAddUndo(0) 1 ->scr @ScrollMapUp endif
	if(GetKeyDown("DownArrow" true)) EditAddUndo(0) 1 ->scr @ScrollMapDown endif
else
	if(GetKeyDown("Alpha1" true)) EditAddUndo(0) @LeftToRight endif
	if(GetKeyDown("Alpha2" true)) EditAddUndo(0) @RightToLeft endif
	if(GetKeyDown("Alpha3" true)) EditAddUndo(0) @BottomToTop endif
	if(GetKeyDown("Alpha4" true)) EditAddUndo(0) @TopToBottom endif
	if(GetKeyDown("Alpha5" true) true eq <-squareMap true eq and) EditAddUndo(0) @BottomLeftToTopRight endif
	if(GetKeyDown("Alpha6" true) true eq <-squareMap true eq and) EditAddUndo(0) @TopRightToBottomLeft endif
	if(GetKeyDown("Alpha7" true) true eq <-squareMap true eq and) EditAddUndo(0) @BottomRightToTopLeft endif
	if(GetKeyDown("Alpha8" true) true eq <-squareMap true eq and) EditAddUndo(0) @TopLeftToBottomRight endif
	if(GetKeyDown("Alpha9" true)) EditAddUndo(0) @BottomLeftQuadrilateral endif
	if(GetKeyDown("Alpha0" true)) EditAddUndo(0) @BottomRightQuadrilateral endif
endif
endif
endif
 
 
 
:LeftToRight #########################################################################################
do(<-mapHeight 0)
	do(<-halfWidth 0)
		SetTerrain(<-mapWidth 1 sub I sub J GetTerrain(I J))
		SetTerrainSpecial(<-mapWidth 1 sub I sub J GetTerrainSpecial(I J))
	loop
loop
:RightToLeft #########################################################################################
do(<-mapHeight 0)
	do(<-halfWidth 0)
		SetTerrain(I J GetTerrain(<-mapWidth 1 sub I sub J))
		SetTerrainSpecial(I J GetTerrainSpecial(<-mapWidth 1 sub I sub J))
	loop
loop
:BottomToTop #########################################################################################
do(<-halfHeight 0)
	do(<-mapWidth 0)
		SetTerrain(I <-mapHeight 1 sub J sub GetTerrain(I J))
		SetTerrainSpecial(I <-mapheight 1 sub J sub GetTerrainSpecial(I J))
	loop
loop
:TopToBottom #########################################################################################
do(<-halfHeight 0)
	do(<-mapWidth 0)
		SetTerrain(I J GetTerrain(I <-mapHeight 1 sub J sub))
		SetTerrainSpecial(I J GetTerrainSpecial(I <-mapheight 1 sub J sub))
	loop
loop
:BottomLeftToTopRight ################################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		if(I J add <-mapWidth lte)
			SetTerrain(<-mapWidth 1 sub J sub <-mapHeight 1 sub I sub GetTerrain(I J))
			SetTerrainSpecial(<-mapWidth 1 sub J sub <-mapHeight 1 sub I sub GetTerrainSpecial(I J))
		endif
	loop
loop
:TopRightToBottomLeft ################################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		if(I J add <-mapWidth lte)
			SetTerrain(I J GetTerrain(<-mapWidth 1 sub J sub <-mapHeight 1 sub I sub))
			SetTerrainSpecial(I J GetTerrainSpecial(<-mapWidth 1 sub J sub <-mapHeight 1 sub I sub))
		endif
	loop
loop
:BottomRightToTopLeft ################################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		if(<-mapWidth 1 sub I sub J add <-mapWidth lte)
			SetTerrain(J I GetTerrain(I J))
			SetTerrainSpecial(J I GetTerrainSpecial(I J))
		endif
	loop
loop
:TopLeftToBottomRight ################################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		if(<-mapWidth 1 sub I sub J add <-mapWidth lte)
			SetTerrain(I J GetTerrain(J I))
			SetTerrainSpecial(I J GetTerrainSpecial(J I))
		endif
	loop
loop
:BottomLeftQuadrilateral #############################################################################
@LeftToRight
@BottomToTop
:BottomRightQuadrilateral ############################################################################
@RightToLeft
@BottomToTop
:TopLeftQuadrilateral ################################################################################
@LeftToRight
@TopToBottom
:TopRightQuadrilateral ###############################################################################
@RightToLeft
@TopToBottom
:LeftHalfRotational ##################################################################################
do(<-mapHeight 0)
	do(<-halfWidth 0)
		SetTerrain(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub GetTerrain(I J))
		SetTerrainSpecial(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub GetTerrainSpecial(I J))
	loop
loop
:RightHalfRotational #################################################################################
do(<-mapHeight 0)
	do(<-halfWidth 0)
		SetTerrain(I J GetTerrain(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub))
		SetTerrainSpecial(I J GetTerrainSpecial(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub))
	loop
loop
:TopHalfRotational ###################################################################################
do(<-halfHeight 0)
	do(<-mapWidth 0)
		SetTerrain(I J GetTerrain(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub))
		SetTerrainSpecial(I J GetTerrainSpecial(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub))
	loop
loop
:BottomHalfRotational ################################################################################
do(<-halfHeight 0)
	do(<-mapWidth 0)
		SetTerrain(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub GetTerrain(I J))
		SetTerrainSpecial(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub GetTerrainSpecial(I J))
	loop
loop
:BottomLeftHalfRotational ############################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		if(asfloat(I) asfloat(<-mapWidth) div asfloat(J) asfloat(<-mapHeight) div add 1 lt)
			SetTerrain(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub GetTerrain(I J))
			SetTerrainSpecial(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub GetTerrainSpecial(I J))
		endif
	loop
loop
:TopRightHalfRotational ##############################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		if(asfloat(I) asfloat(<-mapWidth) div asfloat(J) asfloat(<-mapHeight) div add 1 lt)
			SetTerrain(I J GetTerrain(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub))
			SetTerrainSpecial(I J GetTerrainSpecial(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub))
		endif
	loop
loop
:BottomRightHalfRotational ###########################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		if(asfloat(<-mapWidth 1 sub I sub) asfloat(<-mapWidth) div asfloat(J) asfloat(<-mapHeight) div add 1 lt)
			SetTerrain(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub GetTerrain(I J))
			SetTerrainSpecial(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub GetTerrainSpecial(I J))
		endif
	loop
loop
:TopLeftHalfRotational ###############################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		if(asfloat(<-mapWidth 1 sub I sub) asfloat(<-mapWidth) div asfloat(J) asfloat(<-mapHeight) div add 1 lt)
			SetTerrain(I J GetTerrain(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub ))
			SetTerrainSpecial(I J GetTerrainSpecial(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub ))
		endif
	loop
loop
:BottomLeftQuarterRotational #########################################################################
do(<-halfHeight 0)
	do(<-halfWidth 0)
		SetTerrain(J <-mapHeight 1 sub I sub GetTerrain(I J))
		SetTerrainSpecial(J <-mapHeight 1 sub I sub GetTerrainSpecial(I J))
	loop
loop
@LeftHalfRotational
:TopLeftQuarterRotational ############################################################################
do(<-halfHeight 0)
	do(<-halfWidth 0)
		SetTerrain(I J GetTerrain(J <-mapHeight 1 sub I sub))
		SetTerrainSpecial(I J GetTerrainSpecial(J <-mapHeight 1 sub I sub))
	loop
loop
@LeftHalfRotational
:BottomRightQuarterRotational ########################################################################
do(<-halfHeight 0)
	do(<-halfWidth 0)
		SetTerrain(I J GetTerrain(<-mapWidth 1 sub J sub I))
		SetTerrainSpecial(I J GetTerrainSpecial(<-mapWidth 1 sub J sub I))
	loop
loop
@BottomHalfRotational
:TopRightQuarterRotational ###########################################################################
do(<-halfHeight 0)
	do(<-halfWidth 0)
		SetTerrain(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub GetTerrain(<-mapWidth 1 sub J sub I))
		SetTerrainSpecial(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub GetTerrainSpecial(<-mapWidth 1 sub J sub I))
	loop
loop
@RightHalfRotational
:LeftQuarterRotational ###############################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		if(asfloat(I) asfloat(<-mapWidth) div asfloat(J) asfloat(<-mapHeight) div add 1 lt asfloat(I) asfloat(<-mapWidth) div asfloat(<-mapHeight 1 sub J sub) asfloat(<-mapHeight) div add 1 lt and)
			SetTerrain(J <-mapHeight 1 sub I sub GetTerrain(I J))
			SetTerrainSpecial(J <-mapHeight 1 sub I sub GetTerrainSpecial(I J))
		endif
	loop
loop
@TopLeftHalfRotational
:RightQuarterRotational ##############################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		if(asfloat(I) asfloat(<-mapWidth) div asfloat(J) asfloat(<-mapHeight) div add 1 lt asfloat(I) asfloat(<-mapWidth) div asfloat(<-mapHeight 1 sub J sub) asfloat(<-mapHeight) div add 1 lt and)
			SetTerrain(J <-mapHeight 1 sub I sub GetTerrain(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub))
			SetTerrainSpecial(J <-mapHeight 1 sub I sub GetTerrainSpecial(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub))
		endif
	loop
loop
@TopRightHalfRotational
:TopQuarterRotational ################################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		if(asfloat(I) asfloat(<-mapWidth) div asfloat(J) asfloat(<-mapHeight) div add 1 lt asfloat(I) asfloat(<-mapWidth) div asfloat(<-mapHeight 1 sub J sub) asfloat(<-mapHeight) div add 1 lt and)
			SetTerrain(I J GetTerrain(J <-mapHeight 1 sub I sub))
			SetTerrainSpecial(I J GetTerrainSpecial(J <-mapHeight 1 sub I sub))
		endif
	loop
loop
@TopLeftHalfRotational
:BottomQuarterRotational #############################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		if(asfloat(I) asfloat(<-mapWidth) div asfloat(J) asfloat(<-mapHeight) div add 1 lt asfloat(I) asfloat(<-mapWidth) div asfloat(<-mapHeight 1 sub J sub) asfloat(<-mapHeight) div add 1 lt and)
			SetTerrain(I J GetTerrain(<-mapWidth 1 sub J sub I))
			SetTerrainSpecial(I J GetTerrainSpecial(<-mapWidth 1 sub J sub I))
		endif
	loop
loop
@BottomLeftHalfRotational
:Rotate90Clockwise ###################################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		I ->x J ->z GetTerrain(<-mapWidth 1 sub J sub I) ->h GetTerrainSpecial(<-mapWidth 1 sub J sub I) ->sp
		@SetBuffersAt
	loop
loop
@PrintBuffers
:Rotate90Counterclockwise ############################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		I ->x J ->z GetTerrain(J <-mapHeight 1 sub I sub) ->h GetTerrainSpecial(J <-mapheight 1 sub I sub) ->sp
		@SetBuffersAt
	loop
loop
@PrintBuffers
:Rotate180 ###########################################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		I ->x J ->z GetTerrain(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub) ->h GetTerrainSpecial(<-mapWidth 1 sub I sub <-mapHeight 1 sub J sub) ->sp
		@SetBuffersAt
	loop
loop
@PrintBuffers
:FlipLeftToRight #####################################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		I ->x J ->z GetTerrain(<-mapWidth 1 sub I sub J) ->h GetTerrainSpecial(<-mapWidth 1 sub I sub J) ->sp
		@SetBuffersAt
	loop
loop
@PrintBuffers
:FlipTopToBottom #####################################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		I ->x J ->z GetTerrain(I <-mapHeight 1 sub J sub) ->h GetTerrainSpecial(I <-mapHeight 1 sub J sub) ->sp
		@SetBuffersAt
	loop
loop
@PrintBuffers
:FlipBottomLeftToTopRight ############################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		I ->x J ->z GetTerrain(<-mapHeight 1 sub J sub <-mapWidth 1 sub I sub) ->h GetTerrainSpecial(<-mapHeight 1 sub J sub <-mapWidth 1 sub I sub) ->sp
		@SetBuffersAt
	loop
loop
@PrintBuffers
:FlipBottomRightToTopLeft ############################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		I ->x J ->z GetTerrain(J I) ->h GetTerrainSpecial(J I) ->sp
		@SetBuffersAt
	loop
loop
@PrintBuffers
:ScrollMapLeft #######################################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		I <-scr add ->x2
		if(<-x2 <-mapWidth gte) <-x2 <-mapWidth sub ->x2 endif
		I ->x J ->z GetTerrain(<-x2 J) ->h GetTerrainSpecial(<-x2 J) ->sp
		@SetBuffersAt
	loop
loop
@PrintBuffers
:ScrollMapRight ######################################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		I <-scr sub ->x2
		if(<-x2 lt0) <-x2 <-mapWidth add ->x2 endif
		I ->x J ->z GetTerrain(<-x2 J) ->h GetTerrainSpecial(<-x2 J) ->sp
		@SetBuffersAt
	loop
loop
@PrintBuffers
:ScrollMapUp #########################################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		J <-scr sub ->z2
		if(<-z2 lt0) <-z2 <-mapHeight add ->z2 endif
		I ->x J ->z GetTerrain(I <-z2) ->h GetTerrainSpecial(I <-z2) ->sp
		@SetBuffersAt
	loop
loop
@PrintBuffers
:ScrollMapDown #######################################################################################
do(<-mapHeight 0)
	do(<-mapWidth 0)
		J <-scr add ->z2
		if(<-z2 <-mapHeight gte) <-z2 <-mapHeight sub ->z2 endif
		I ->x J ->z GetTerrain(I <-z2) ->h GetTerrainSpecial(I <-z2) ->sp
		@SetBuffersAt
	loop
loop
@PrintBuffers
:SetBuffersAt ########################################################################################
	SetListElement(<-terrainBuffer <-z <-mapWidth mul <-x add <-h)
	SetListElement(<-specialBuffer <-z <-mapWidth mul <-x add <-sp)
:PrintBuffers ########################################################################################
do(GetListCount(<-terrainBuffer) 0)
	SetTerrain(I asint(<-mapWidth) mod I asint(<-mapWidth) div GetListElement(<-terrainBuffer I))
	SetTerrainSpecial(I asint(<-mapWidth) mod I asint(<-mapWidth) div GetListElement(<-specialBuffer I))
loop
 
# Made with luv by Argonwolf

Click here for controls list

Click here for controls list

Note: All reflections/rotations leave the original half/quarter intact when pasting a copy

1 - Reflect left half of map to right

2 - Reflect right half of map to left

3 - Reflect bottom half of map to top

4 - Reflect top half of map to bottom

5 - Reflect bottom-left half of map to top-right diagonally (Requires square map)

6 - Reflect top-right half of map to bottom-left diagonally (Requires square map)

7 - Reflect bottom-right half of map to top-left diagonally (Requires square map)

8 - Reflect top-left half of map to bottom-right diagonally (Requires square map)

9 - Reflect bottom-left quarter of map to all four corners

0 - Reflect bottom-right quarter of map to all four corners

Shift+1 - Reflect top-left quarter of map to all four corners

Shift+2 - Reflect top-right quarter of map to all four corners

Shift+3 - Rotate left half of map to right

Shift+4 - Rotate right half of map to left

Shift+5 - Rotate top half of map to bottom

Shift+6 - Rotate bottom half of map to top

Shift+7 - Rotate bottom-left half of map to top-right diagonally

Shift+8 - Rotate bottom-right half of map to top-left diagonally

Shift+9 - Rotate top-left half of map to bottom-right diagonally

Shift+0 - Rotate top-right half of map to bottom-left diagonally

Alt+1 - Rotate bottom-left quarter of map to all four corners (Requires square map)

Alt+2 - Rotate bottom-right quarter of map to all four corners (Requires square map)

Alt+3 - Rotate top-left quarter of map to all four corners (Requires square map)

Alt+4 - Rotate top-right quarter of map to all four corners (Requires square map)

Alt+5 - Rotate left triangular quarter of map to all four sides (Requires square map)

Alt+6 - Rotate right triangular quarter of map to all four sides (Requires square map)

Alt+7 - Rotate top triangular quarter of map to all four sides (Requires square map)

Alt+8 - Rotate bottom triangular quarter of map to all four sides (Requires square map)

Ctrl+1 - Rotate map 90 degrees clockwise (Requires square map)

Ctrl+2 - Rotate map 90 degrees counterclockwise (Requires square map)

Ctrl+3 - Rotate map 180 degrees

Ctrl+4 - Flip map left to right

Ctrl+5 - Flip map top to bottom

Ctrl+6 - Flip map bottom-left to top-right (Requires square map)

Ctrl+7 - Flip map bottom-right to top-left (Requires square map)

Ctrl+Arrow - Scroll map 1 tile in direction of arrow (off-map tiles wrap to other side)

Shift+Arrow - Scroll map 10 tiles in direction of arrow (off-map tiles wrap to other side)


Reset Mesh

click here for source code

click here for source code

ResetMesh.4rpl
# ResetMesh
# For mesh values, see:  https://knucklecracker.com/wiki/doku.php?id=4rpl:commands:getmeshhealth
 
GetMapSize ->sizeZ ->sizeX
do(<-sizeZ 0)
	do(<-sizeX 0)
		if(GetMeshHealth(I J) neq0)
			SetMeshHealth(I J -1000000)
		endif
	loop
loop

Locate all cells in a range

4RPL code that will locate cells in range of a midpoint and within a certain radius.

click here for source code

click here for source code

CellRange.4rpl
# CellinRange  2021/06/26
 
# Return a list of cells given a midpoint and a radius. 
115 ->x
54 ->z
20 ->radius 
 
CreateList  ->cells  # will contain list of cells in range of call
Do (<-x <-radius 1 + +, <-x <-radius -)   	#x #J
	Do (<-z <-radius 1 + +, <-z <-radius -)	#z #I
		If (DistanceCell(<-x <-z J I) LTE (<-radius 0.66 +))
			If (IsV2InMap (V2(J I)))
				FC(J I)   #push to stack
			EndIf
		EndIf
	Loop
Loop
 
AppendStackToList (<-cells)  # populate list
 
@CellOut   #replace this with a routine to do what you desire.  
 
#---------
 
:CellOut
	# set up theme overlay
	V4(1 1 0 1) List ->yellow
	V4(0 1 0 1) list ->green
	CreateThemeOverlay(0 GetMapSize Vector0)
	SetThemeOverlayEnabled(0 true)
	SetThemeOverlayPointFilter(0 true)
 
	# do the real work
	Do (GetListCount(<-cells) 0)
		SetThemeOverlayPixels(0, UFC(<-cells[i]),, 1, 1, <-green) 
	Loop

Next Utility goes here

click here for source code

click here for source code


Useful Functions

GetUnitsInPolygon() and IsPointInPoly()

Need to find units in a polygon or determine if a specific point is inside a convex/concave polygon (without holes)? These slightly inefficient and imperfect functions are for you - at least until something equivalent is available natively in 4RPL. Just put the functions at the bottom of your 4RPL script.

Click here for the source code

Click here for the source code

polygon_functions.4rpl
# IsPointInPoly(point polyList)
:IsPointInPoly
	->ipip_polyList
	->ipip_point
 
	false ->ipip_retval
	GetListCount(<-ipip_polyList) 1 - ->ipip_prev
	<-ipip_polyList 0 do
		<-ipip_polyList[I] ->ipip_linept1
		<-ipip_polyList[<-ipip_prev] ->ipip_linept2
 
		if (<-ipip_linept1.y <-ipip_point.y gt <-ipip_linept2.y <-ipip_point.y gt neq)
			<-ipip_linept2.x <-ipip_linept1.x - <-ipip_point.y <-ipip_linept1.y - * ->ipip_tempval
			<-ipip_tempval <-ipip_linept2.y <-ipip_linept1.y - / ->ipip_tempval
			<-ipip_tempval <-ipip_linept1.x + ->ipip_tempval
 
			if (<-ipip_point.x <-ipip_tempval lt)
				<-ipip_retval ! ->ipip_retval
			endif
		endif
 
		I ->ipip_prev
	loop
 
	<-ipip_retval
 
 
# GetUnitsInPolygon(unitType polyList enemyState builtState imperviousState)
:GetUnitsInPolygon
	->guip_imperviousState
	->guip_builtState
	->guip_enemyState
	->guip_polyList
	->guip_unitType
 
	# Get all units on the map that match the non-position requirements.
	GetUnits(<-guip_unitType V3(128 128 128) 512 false false false <-guip_enemyState <-guip_builtState <-guip_imperviousState) ->guip_units
 
	CreateList ->guip_retval
 
	<-guip_units 0 do
		<-guip_units[I] ->guip_tempunit
 
		if (@IsPointInPoly(V2(GetUnitCell(<-guip_tempunit)) <-guip_polyList))
			AppendToList(<-guip_retval <-guip_tempunit)
		endif
	loop
 
	<-guip_retval

Example usage:

Click to show example usage

Click to show example usage

polygon_functions_example.4rpl
	# Creates a sparks effect on each friendly unit inside a triangle.
	List(
		V2(18 148)
		V2(138 102)
		V2(44 29)
	) ->testPoly
 
	@GetUnitsInPolygon("" <-testPoly 2 0 1) ->units
 
	TraceAllSp("Num units " GetListCount(<-units))
 
	<-units 0 do
		<-units[I] ->tempunit
 
		CreateEffect("sparks" GetUnitPosition(<-tempunit) V3(1 1 1))
	loop

cw4/4rpl_tools.txt · Last modified: 2021/06/28 20:15 by Karsten75