multiple cycle code help please

Freeform discussion about anything related to modding Transcendence.
Post Reply
relanat
Militia Captain
Militia Captain
Posts: 941
Joined: Tue Nov 05, 2013 9:56 am

It sounded so easy! There are only 6 of them!
With the addition of the 'P' criteria to 'unvFindObject' from 1.9a1 I was looking to automate the creation of Commander's Log entries at game start. This would create the data needed to show entries for the stations that are already known at game start, eg, Point Juno, Cathedral of Domina, etc, as show in the galactic map. Previously each station had their data entered manually in a separate helper function. Using code will handle any future (friendly) stations that are set known at game start.
The desired output is as shown in the attached composite image

The screen shows each system with station type names and a count of stations with that type name (even if they are different types). Split into ten different categories.

What is needed is to get this struct output:

Code: Select all

{
"A7":("" "" "Commonwealth settlement: 2" Nil Nil Nil "" "" Nil Nil)
BA:("" "" "Battle Arena Maximus: 1" Nil Nil Nil "" "" Nil Nil)
CD:("" "" "Cathedral of Domina: 1" Nil Nil Nil "" "" Nil Nil)
PJ:("" "" "Point Juno: 1" Nil Nil Nil "" "" Nil Nil)
SK:("" "" "Arcology of New Victoria: 1" Nil Nil Nil "" "" Nil Nil)
TauCeti:("" "" "corporate metropolis: 1" Nil Nil Nil "" "" Nil Nil)
}
from this:

Code: Select all

(unvFindObject 'TVAP-arcology)
->
((1921 1318913 BA "Battle Arena Maximus" 0)
(3584 1056799 SK "Arcology of New Victoria" 1)
(6604 1048628 CD "Cathedral of Domina" 1)
(11450 1712136 PJ ": Point Juno" 0)
(12279 1056770 "A7" "Commonwealth Settlement 5238" 64)
(12320 1056770 "A7" "Commonwealth Settlement 7440" 64)
(16783 8454225 TauCeti "Icarus Station" 64))
using code.

Each nodeID key has a list of 10 entries. These correspond to various objects like stargates, CSCs, friendly stations, etc as per the headings in the image. If no objects of that sort are known in the system the value is Nil or "" and the screen shows nothing. The third value in the list is for stations friendly to the player. The text inside the value is displayed using 'scrSetDisplayText'. Fortunately all the stations are friendly so all will be listed in the third value of the list. The other 9 entries will always be Nil or "" at game start.

I could probably work out how to do this if there was only ever one of any station. But I think the multiple Comm settlements require another cycle of code and I don't know how to do this.

The type and the nodeID are the two important values. The type name is used, not the object name, so the object name and flags aren't needed, neither is the ID. An additional complication is the use of the same type name by different types. So checking against the type name is required, not against the type. The code will run in <OnGlobalUniverseCreated>.

Possibly using a list of the nodeIDs and checking every entry by that will work? Save the type name and set the count at 1. Then checking the type name of the next entry of the same nodeID and if that type name already exists add 1 to the count value. Then check the next nodeID.

Or creating a new struct from these entries with only the nodeID and type saved. Then use that to check against.

Any help will be greatly appreciated. I have been battling against this for a while now with very limited success. TIA.
Attachments
LogScreen.jpg
LogScreen.jpg (85.33 KiB) Viewed 8903 times
Stupid code. Do what I want, not what I typed in!
NMS
Militia Captain
Militia Captain
Posts: 569
Joined: Tue Mar 05, 2013 8:26 am

What should your data struct look like when there are multiple station types in a category?
relanat
Militia Captain
Militia Captain
Posts: 941
Joined: Tue Nov 05, 2013 9:56 am

Here's the auto-generated output from during gameplay. C1 has been fully explored and then updated by the mod code.This is updated either on entering the Commander's Log screen or on system exit and uses a list of system objects. This is considerably easier than interrogating 'unvFindObject' lists.

Code: Select all

(logGetText)
{ "A7":(Nil Nil "Commonwealth Settlement 2" Nil Nil Nil Nil Nil Nil Nil)
BA:(Nil Nil "Battle Arena Maximus 1" Nil Nil Nil Nil Nil Nil Nil)
"C1":("Stargate: 2\n" "" "Commonwealth agricultural colony: 1\nCommonwealth colony: 1\ncorporate armor dealer: 1\ncorporate arms dealer: 2\nKorolov Shipping: 1\noccupied Commonwealth habitat: 2" Nil "Abbasid outpost: 1\nAnarchist habitat: 2\nCentauri warlord camp: 1\nCharon Pirates cache: 3\nCharon Pirates outpost: 1\nCharon Pirates stronghold: 1\nHimal refuge: 1\noutlaw camp: 2" Nil "abandoned cargo container: 4\n" "" Nil Nil)
"C9":(Nil Nil Nil Nil Nil Nil Nil Nil Nil Nil)
CD:(Nil Nil "Cathedral of Domina 1" Nil Nil Nil Nil Nil Nil Nil)
PJ:(Nil Nil "Point Juno 1" Nil Nil Nil Nil Nil Nil Nil)
SE:("" "" "Commonwealth agricultural colony: 1\nCommonwealth dry dock: 1\nCommonwealth habitat: 4\nCommonwealth residentials: 1\ncorporate enclave: 1\nSisters of Domina: 1\nStarton Eridani: 1" Nil Nil Nil "" "" Nil Nil) SK:(Nil Nil "St. Katharines Arcology 1" Nil Nil Nil Nil Nil Nil Nil) }
This is the Log screen that uses the C1 struct value above.
Thanks, Song. Used it already!
Thanks, Song. Used it already!
CLogOutput.jpg (59.64 KiB) Viewed 8876 times
Although there is only one Charon stronghold listed here the use of type name in the code means all of the three different stronghold types appear under the one name/count.

As a rough guide the 10 list entries in the struct values are:
stargates
CSCs
friendlies
abandoned friendlies
enemies
abandoned enemies
containers and crates
autons
mined ore, and
custom map markers.
The text for each category is displayed under the relevant heading on the screen.
The order is a bit muddled as some were added as the mod was developed.

In theory the code should also handle sorting into these categories but since there are only friendly stations set known at game start ATM that can definitely wait!
Stupid code. Do what I want, not what I typed in!
NMS
Militia Captain
Militia Captain
Posts: 569
Joined: Tue Mar 05, 2013 8:26 am

So the list for each system is always generated from scratch? You don't ever add stations to it one at a time, which would involve searching a string for the matching station name? But you want different types of stations that share a name to share an entry?
relanat
Militia Captain
Militia Captain
Posts: 941
Joined: Tue Nov 05, 2013 9:56 am

So the list for each system is always generated from scratch?
Yes, the list is always re-generated from lists of system objects of selected criteria, either on entering the first Log screen or on system exit. This checks for known stations in the system. (Although I use 'stations' here, this also includes CSCs and autons.) Two data stores are created. One is the text entries for the screen as shown above, the other (irrelevant here) is a list of the stations in a particular order which is shown in a customPicker screen to allow the player to highight the station or check its items.
You don't ever add stations to it one at a time, which would involve searching a string for the matching station name?
No, there is no adding of stations on an individual basis. The code uses 'sysFindObject' lists every time. It then runs additional code on these lists to generate the text entries. Unfortunately, because of the widely different critieria for different sub-sections, the same code doesn't run for every 'sysFindObject' list. As an example, the "friendly active" stations runs the helper code, 'rpgD789CondensedDisplayList', to check for various things like abandoned CSCs and "(Xenophobe worldship)" or parentheses in the type name and can adjust the displayed "type name" if a different name is clearer. Other lists just check the count and append it to a generic name, eg a count of all autons with the attribute 'combat' is shown as "combat autons: n".

But that all happens 'in-game' and, although messy, I have been able to get that code working.
What is needed is to check the types in the 'unvFindObject' lists. I am confident I can use the existing type name check code to check the type names and output a suitable different "type name' if it differs from the actual type name but cannot work out how to cycle through the 'unvFindObject' entries.
Somehow the nodeID and type need to be checked. First to create an entry for each nodeID, then to get a count of the stations which share a type name and then to output that info as the text "desired type name: n". This seems relatively easy as there are only 6 stations set known using 'unvSetObjectKnown' ATM and this could be expanded if more are known (I think TBR might do this already or will at some stage maybe EDIT: TBR identifies systems but not stations) but the stumbling block is how to check for more than one station, ie the Commonwealth settlements in Dantalion. I'm blocked when it comes to doing that.
This only needs to happen at game start to generate entries for stations in the other systems, eg Point Juno, etc which although known, have never been visited by the player. This code will never need to run again after a game is started, further updating is handled by code run in each system.
But you want different types of stations that share a name to share an entry?
Yes. Because of the limited number of stations set known at game start matching them to the type name is sufficient to place the stations under the appropriate type name. Later, in-game, more variation is encountered but, as mentioned above, this is a relatively easy expansion of the code that is only needed during gameplay, not at game start.

I hope that is clear, I suck at text communication!
Last edited by relanat on Wed Aug 28, 2019 2:41 am, edited 2 times in total.
Stupid code. Do what I want, not what I typed in!
NMS
Militia Captain
Militia Captain
Posts: 569
Joined: Tue Mar 05, 2013 8:26 am

OK, try this:

Code: Select all

(block (systemStruct outputStruct)
	;	Create a struct where the keys are nodes and each value is a struct.
	;	In the inner structs, the keys are station names and the values are the number of known stations with the name in the system.
	(enum inputList theEntry
		(block (
			(theType (@ theEntry 0))
			(theNode (@ theEntry 2))
			(theName (typGetProperty theType 'name)) ;	Apply a function that strips parenthesis here if you want.
			(theSystem (@ systemStruct theNode))
			(existingCount (@ theSystem theName))
			)
			(set@ systemStruct theNode
				(set@ theSystem theName (+ existingCount 1))
				)
			)
		)
	
	;	Convert to your desired format with the names and counts concatenated into strings with newlines between them,
	;	then inserted into a list.
	(enum (@ systemStruct) theNode
		(block (
			(theSystem (@ systemStruct theNode))
			friendliesList
			)
			(enum (@ theSystem) theName
				(lnkAppend friendliesList (cat theName ": " (@ theSystem theName)))
				)
			(set@ outputStruct theNode
				(list "" "" (join friendliesList "\n") Nil Nil Nil "" "")
				)
			)
		)
		
	outputStruct
	)
It's not tested, but it might work. And if it doesn't, hopefully you can see how it's supposed to. Set inputList to your list of entries from unvFindObject. It should produce the format you want even in cases where there's more than one station on the list in a system, whether they have the same type name or not.
relanat
Militia Captain
Militia Captain
Posts: 941
Joined: Tue Nov 05, 2013 9:56 am

Many thanks. Works perfectly with '(@ theEntry 1)' setting 'theType'.

Using the 'type name' as the key in the inner struct is very clever. That makes it really easy to increase the count. Nice one.
This is another topic that is getting copied into the helpful info folder!

Final code with '(unvFindObject 'TVAP-arcology)' as 'inputList'. The '-arcology' criteria excludes the 12 arcology segments which are automatically set known in the mod so the arcology is highlighted on entering the St Kats system. Also handles Icarus Station in CC if loaded.

Code: Select all

(setq rpgD789AutoCreateStartingTextEntries (lambda (inputList)
	(logSetText
		(block (systemStruct outputStruct)
				;Create a struct where the keys are nodes and each value is a struct.
				;In the inner structs, the keys are station type names and the values
				;	are the number of known stations with that type name in the
				;	system.
			(enum inputList theEntry
				(block (
					(theType (@ theEntry 1))
					(theNode (@ theEntry 2))
					(theName (typGetProperty theType 'name))
					(theSystem (@ systemStruct theNode))
					(existingCount (@ theSystem theName))
					)
					(set@ systemStruct
						theNode
						(set@ theSystem
							theName
							(+ existingCount 1)
						)
					)
		;			(printTo 'console systemStruct)
				)
			)

				;Convert to the desired format of the names then counts, then
				;	concatenate the strings with newlines between them as we
				;	insert them into the list.
			(enum (@ systemStruct) theNode
				(block (
					(theSystem (@ systemStruct theNode))
					friendliesList
					)
					(enum (@ theSystem) theName
						(lnkAppend friendliesList (cat theName ": " (@ theSystem theName)))
					)
					(set@ outputStruct
						theNode
						(list "" "" (join friendliesList "\n") Nil Nil Nil "" "" "" "")
					)
		;			(printTo 'console outputStruct)
				)
			)
			outputStruct
		)
	)
))
No EP stations are set known using 'unvSetObjectKnown' at this time.
However the Kibo shipyard is set known in its StationType <OnCreate> code and appears in the Log.

Although it worked fine running in <OnGlobalUniverseCreated> in SOTP, oddly, the code needs to be in <OnGlobalPlayerEnteredSystem> for the Director's Cut adventure for the data to be created. I overwrote EP to identify the arcology and the Cathedral of Domina and it worked fine in <OnGlobalUniverseCreated>. Code is weird!

EDIT: I have used this code to create another struct of structs in a mod, so double thanks.
Stupid code. Do what I want, not what I typed in!
Post Reply