searching multiple levels of items help please

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

Fri Apr 26, 2019 4:37 pm

One of the big drawbacks of GODMod was you could jump to Heretic but still only had the starting ship armor installed. This usually quickly led to destruction. It was possible but tedious to upgrade the ship.

Thanks to George for making the Wand of Wishing available. It has given me the idea to add a ship auto-upgrade feature to the Taipan GodShip mod. This will only apply when the player uses a non-god ship but will allow them to select a level and have items of that level auto-installed on the ship. A considerable time saving.

But I'm having a bit of trouble with the code.
This code creates a struct with level 10 item types for all the necessary items:

Code: Select all

(block Nil
	(setq theStruct Nil)
	(setq theLevel 10)
	(setq theTypes (typFind (cat "'i=" theLevel)))
	(setq categoryList (list 'weapon 'launcher 'reactor 'shields 'armor))
	(enum categoryList theCategory
		(setq theStruct
			(structAppend theStruct
				theCategory
				(random (filter theTypes type (eq (typGetProperty type 'category) theCategory)))
			)
		)
	)
)
But there isn't always an item of the desired level resulting in a Nil value.
What is needed is to check other levels until an item is found.
So check level 9 for reactors, if no reactors of level 9, check level 8, etc.
I've messed about with 'for' and 'loop' but can't quite work out a way of stopping the code when a reactor is found. Possibly it needs 'enumWhile' instead (or as well) but I've never used that function.
While I could do the extremely time-consuming trial and error thing, it would be better if someone would be kind enough to post some basic code, perhaps with a couple of comments, which could do this.

The requirement is for a reactor type of the desired level to be added to the struct, but if no reactors of that level exist then a reactor of the next level down. If there still isn't a reactor, continue through all levels down to level 1.

The other alternative is to get all the reactors and sort them by level, then select a reactor of the desired level or lower. I don't know which way would be better. Or if there is a better way?
Anyone got any ideas? Thanks.
Stupid code. Do what I want, not what I typed in!

User avatar
Xephyr
Militia Captain
Militia Captain
Posts: 855
Joined: Fri Dec 14, 2007 1:52 am
Location: Orion Arm, Milky Way
Contact:

Fri Apr 26, 2019 6:03 pm

I'm a little rusty with tlisp, but enum should return a list, and there is a prime function that returns the first item in that list.
Project Renegade (Beta) : "The Poor Man's Corporate Command!"
Real programmers count from 0. And sometimes I do, too.

NMS
Militia Captain
Militia Captain
Posts: 551
Joined: Tue Mar 05, 2013 8:26 am

Sat Apr 27, 2019 2:03 am

I'd do it like this:

Code: Select all

(block (resultList resultStruct)
	(enum '(p l r s a) theCategory
		(block (foundItem level)
			(setq level 10)
			(loop (and (not foundItem) (gr level 0))
				(setq foundItem (random (itmGetTypes (cat theCategory " =" level ";"))))
				(setq level (- level 1))
				)
			; Pick one:
			(lnkAppend resultList foundItem)
			(setq resultStruct (struct resultStruct (typGetProperty foundItem 'category) foundItem))
			)
		)
	)
Xephyr wrote:
Fri Apr 26, 2019 6:03 pm
I'm a little rusty with tlisp, but enum should return a list, and there is a prime function that returns the first item in that list.
enum returns the result of the last iteration. map returns a list of the results of each iteration. So you could do something like:

(setq resultList (map '(p l r s a) ...

(@ theList 0) returns the first item.

relanat
Militia Captain
Militia Captain
Posts: 817
Joined: Tue Nov 05, 2013 9:56 am

Sat Apr 27, 2019 2:51 pm

Excellent. I didn't think of using two qualifiers in the condition section of the 'loop' code. That was the bit that was eluding me.

All the above code needed was a 'block' around the 'loop' expression to do the job.

Mod code which runs from a dockscreen action with 'scrGetCounter' setting the desired level:

Code: Select all

(setq rpgD789ShipLevelReset (lambda (level)
	(block (resultStruct)
		(block (searchLevel)
			(enum '(p l r s a) theCategory
				(block (foundItem)
					(setq searchLevel level)
					(loop (and (not foundItem) (gr searchLevel 0))
						(block Nil
							(setq foundItem (random (itmGetTypes (cat theCategory " =" searchLevel ";"))))
							(setq searchLevel (- searchLevel 1))
						)
					)
					(setq resultStruct (struct resultStruct (typGetProperty foundItem 'category) foundItem))
				)
			)
			(printTo 'console resultStruct)
		)
		(if (@ resultStruct 'reactor)
			(block Nil
				(objAddItem gPlayerShip (itmCreate (@ resultStruct 'reactor) 1))
				(shpInstallDevice gPlayerShip (itmCreate (@ resultStruct 'reactor) 1))
				(shpRefuelFromItem gPlayerShip (itmCreate &itHelium3FuelRod; (shpGetFuelNeeded gPlayerShip (itmCreate &itHelium3FuelRod; 1))))
		...
Thanks.
Stupid code. Do what I want, not what I typed in!

Post Reply