exclusion distance when adding stations 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

Is there a way of making sure that a station added with <OnGlobalSystemCreated> doesn't overlap a station placed by the system code?

The attached mod adds two small stargates to binary systems. They are placed between 40 and 70 ls from the centre of the each star. Using 'objSetPos' the player can instantly travel between the two gates.

But there is a possibility that the gates will be placed where a station already exists.

I've tried

Code: Select all

exclusionRadius="40"
in the StationType UNID XML and

Code: Select all

<Encounter
	exclusionRadius=	"100"
	>
</Encounter>
in the station code (also 'enemyExclusionRadius') but have found both enemy and friendly stations within 30 ls of the gate

I don't mind if the gates are close to other stations but having them overlap or be completely hidden isn't desirable.

Is there another way to stop station overlap? Or am I doing it wrong? Any help greatly appreciated.

This is the code for adding the gates:

Code: Select all

<OnGlobalSystemCreated>
	(block (listOfStars firstGate secondGate)
		(setq listOfStars (filter (sysFindObject Nil '*) theObj (eq (objGetProperty theObj 'scale) 'star)))
		(if (eq (count listOfStars) 2)
			(block Nil
				(setq firstGate (sysCreateStation &stD789SmallStargate; (sysVectorPolarOffset (@ listOfStars 0) (random 0 360) (random 40 70))))
				(objSetName firstGate (cat (sysGetName) " Gate 1"))
				(setq secondGate (sysCreateStation &stD789SmallStargate; (sysVectorPolarOffset (@ listOfStars 1) (random 0 360) (random 40 70))))
				(objSetName secondGate (cat (sysGetName) " Gate 2"))
			)
		)
	)
</OnGlobalSystemCreated>
and the mod is attached (without any exclusion code).
Attachments
BinaryStargates.zip
(624.73 KiB) Downloaded 287 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

Exclusion distance isn't checked when creating a station with sysCreateStation. (What would it do? Not create the station? Put it somewhere other than the specified position?)

If you use sysGetRandomLocation and pass the type of the station, I think it will respect that station's exclusionRadius and locationCriteria (which could be "+++innerSystem" to ensure it's reasonably close to a star). But you can't control which star it's near, so you'd have to repeatedly try and check which star it's near.

I think what you want is (sysVectorRandom center radius minSeparation [filter]) to ensure it's a specified distance from the star and at least some minimum distance from objects matching some criteria if possible.
relanat
Militia Captain
Militia Captain
Posts: 941
Joined: Tue Nov 05, 2013 9:56 am

Got it working but not with sysVectorRandom. Stations were still within the specified distance. Game code examples use it with ships (a lot) and stargates, but not stations (but I didn't search very thoroughly). And a lot of the game examples use sysVectorRandom to create the 'pos' first, then create the object at that pos but I couldn't get this working either.

In the end I used 'loop' to create the gate and then check for distance to the nearest object, destroy the gate if it was too close and create another, etc. I think there might be the chance of creating an endless loop error doing this but in every binary system I saw during testing there is more than enough room to fit the mini-stargate so this shouldn't happen. The gate was always placed as desired within three 'loop's.
There is some 'bestTries' code in SOTP which appears to handle this so I'll mess around with that to fix it and create the gate further or closer if there isn't room in the desired area.

Thanks for the help. I used your 'for' example code from another topic again to create the two gates.

Code: Select all

(for i 0 1
	(block (
		(theDistance Nil)
		)
		(loop (not (geq theDistance 40))
			(block (theStargate theNearestObj)
				(setq theStargate (sysCreateStation &stD789SmallStargate; (sysVectorPolarOffset (@ starList i) (random 0 359) (random 40 70))))
				(setq theNearestObj (sysFindObject theStargate "TN -shipwreck"))
				(setq theDistance (objGetDistance theStargate theNearestObj))
				(if (geq theDistance 40)
					(objSetName theStargate (cat (sysGetName) " Gate " (+ i 1))
					(objDestroy theStargate)
				)
			)
		);loop
	);block
);for
EDIT: Corrected the function name, sysVectorRandom.
Last edited by relanat on Thu Aug 16, 2018 3:54 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

You could just do something like:

Code: Select all

(enum starList theStar
	(objSetName (sysCreateStation
					&stD789SmallStargate;
					(sysVectorRandom theStar (random 40 70) 40 "T -shipwreck")
					)
				(cat (objGetName theStar) " Gate")
		)
	)
There's a chance it'll end up too close to something even if there are possible positions that would be OK, because it picks the radius at random first. But it's easier and has no risk of infinite loops. If that's not good enough, you could use something like your code, but keep track of the best position and distance so far and the number of attempts. End the loop if the distance is OK or the number of attempts is too large, and use the best position.
relanat
Militia Captain
Militia Captain
Posts: 941
Joined: Tue Nov 05, 2013 9:56 am

There's a chance it'll end up too close to something ... because it picks the radius at random first
That was, I think, the info I was missing. Thanks. So using a single value for radius will stop the erratic placement. So easy when you know how!
I do however want to keep the randomness of the radius and also maintain enough distance from existing stations to completely prevent overlap. One attempt with early code resulted in the stargate appearing in the middle of a multiple Dwarg colony!
End the loop if the distance is OK or the number of attempts is too large, and use the best position.
Aah, yes. Brilliant. I never even thought of that. So then the gate would be placed more than 40 ls from a station or if such a position wasn't found within, say, 10 loops the largest distance could be used. Not guaranteed to be infallible but most likely the distance (greatest distance from 10 attempts) would be more than enough to stop overlap with an existing station which is the ultimate requirement of the code, and it eliminates endless loops. I shalll do that. Many thanks.
Stupid code. Do what I want, not what I typed in!
relanat
Militia Captain
Militia Captain
Posts: 941
Joined: Tue Nov 05, 2013 9:56 am

Finally got this mod working.

The exclusion feature for 'sysVectorRandom' doesn't work in <OnGlobalSystemCreated>. Running similar code in a formed system does. So I'll guess that mod stations get created first so there aren't any other stations for them to be excluded from. Or something!

Once that was abandoned it was just a matter of running code until a sufficiently large distance was found or using the largest distance found so far.

This code runs for each star using 'for':

Code: Select all

(loop (gr triesLeft 0)
	(block (
		(theMarker (sysCreateMarker "Marker" (sysVectorRandom (@ starList i) (random 40 70) 100) &svIndependent;))
		(thePos (objGetPos theMarker))
		(theDistance (sysVectorDistance theMarker (sysFindObject theMarker "TN -shipwreck")))
		)
		(objDestroy theMarker)
		(if (gr theDistance savedDistance)
			(block Nil
				(setq savedDistance theDistance)
				(setq savedPos thePos)
			)
		)
		(setq triesLeft (subtract triesLeft 1))
		(switch
			(gr savedDistance 100)
				(block Nil
					(setq theStargate (sysCreateStation &stD789SmallStargate; savedPos))
					(objSetName theStargate (cat (sysGetName) " Gate " (+ i 1)))
					(setq triesLeft 0)
				)

			(eq triesLeft 0)
				(block Nil
					(setq theStargate (sysCreateStation &stD789SmallStargate; savedPos))
					(objSetName theStargate (cat (sysGetName) " Gate " (+ i 1)))
				)
		);switch
	)
);loop
'triesLeft' is set at 15.
The desired separation distance was increased to 100. It could have stayed at 40 but it doesn't matter now as it isn't a set minimum value anymore (see below).
The creation of the marker was neccessary because I couldn't find a way to measure a distance from a 'pos' value.
In practice if the exclusion distance doesn't reach 100 after 15 tries it is usually around 80 or 90, although I have seen a couple of 40 values and a 60. This is enough to prevent overlap.

Thanks for the help, NMS.
Stupid code. Do what I want, not what I typed in!
Post Reply