Setting orders and OnCreate event

Freeform discussion about anything related to modding Transcendence.
Post Reply
User avatar
Mutos
Militia Lieutenant
Militia Lieutenant
Posts: 218
Joined: Thu Aug 14, 2008 3:31 am
Location: Near Paris, France
Contact:

Hi all,


I try to set a ship's orders on creation for a freighter. For now my code reads :

Code: Select all

<onCreate>
	(block (nextWaypoint waypointsList)
		; Send message to debug
		(dbgLog "New freighter created : " (objGetName gSource))

		; List all dockable planets
		(setq waypointList (sysFindObject gSource "t:parkingOrbit"))
		(dbgLog "Dockable planets scanned")

		; Randomly choose a waypoint
		(setq nextWayPoint (random waypointList))
		(dbgLog "Waypoint chosen : " (objGetName nextWaypoint))

		; Clear previous orders
		;(shpCancelOrders gSource)
		;(dbgLog "Previous orders cancelled")

		; Set new order
		;(shpOrderDock gSource nextWaypoint)
		;(dbgLog "New orders : go to " (objGetName nextWaypoint))
	)
</onCreate>
This code works fine as long as it does nothing but setting variables. But if I uncomment either line shpCancelOrders or shpOrderDock, it crashes the game as soon as I create a freighter.

Could you give me some hints as to what is missing ? Is it impossible to call the shpOrders* functions from an OnCreate ? Or maybe there is something missing in my ship definition ? I copied it from the Antares I and only changed the graphics.

Thanks in advance ^-^
@+

Benoît 'Mutos' ROBIN
Hoshikaze 2250 Project
Apemant
Commonwealth Pilot
Commonwealth Pilot
Posts: 94
Joined: Mon Dec 03, 2007 12:51 pm

Not sure about this... you are trying to give orders to the newly created ship? Maybe it's not fully initialized at the time of the OnCreate event?

In any case, personally I would solve problems of this type by calling sysAddObjTimerEvent with a delay of a few ticks, perhaps even just 1 tick if it needs to happen immediatelly upon creation.

I had perhaps a similar problem like this, namely, I couldn't use objDestroy in a OnDestroy event (I wanted to remove a station when it's destroyed, so that no wreck remained). It also crashed the game. So I did it like this:

Code: Select all

<OnDestroy>
	(sysAddObjTimerEvent 1 gSource "Cleanup")
</OnDestroy>
<Cleanup>
	(objDestroy gSource)
</Cleanup>

Try it out and say if it worked.
User avatar
Mutos
Militia Lieutenant
Militia Lieutenant
Posts: 218
Joined: Thu Aug 14, 2008 3:31 am
Location: Near Paris, France
Contact:

Hi Apemant,


Thanks a lot, I'll try this asap...
@+

Benoît 'Mutos' ROBIN
Hoshikaze 2250 Project
User avatar
Mutos
Militia Lieutenant
Militia Lieutenant
Posts: 218
Joined: Thu Aug 14, 2008 3:31 am
Location: Near Paris, France
Contact:

Hi all,


Here is my final code for that :

Code: Select all

<Events>
	<OnOrdersCompleted>
		(block (timeWait nextWaypoint waypointsList message)
			; Log beginning of event
			(setq message (cat "Ship " (objGetName gSource) " : Entering OnOrdersCompleted event"))
			(dbgLog message)

			; Test if ship is docked
			(if (objGetData gSource "notFirstTime")
				(block Nil
					; Ship is docked : we wait quite a long time
					(setq timeWait 200)

					; Send message to player
					(setq message (cat "Ship " (objGetName gSource) " :   not the first time OnOrdersCompleted is played"))
					(dbgLog message)
				)

				(block Nil
					; Ship is not docked : we wait for just a few ticks
					(setq timeWait 5)

					; Send message to player
					(setq message (cat "Ship " (objGetName gSource) " :   first time OnOrdersCompleted is played"))
					(dbgLog message)
				)
			)


			; Set first time flag
			(objSetData gSource "notFirstTime" True)

			; Activate timer for next orders
			(sysAddObjTimerEvent timeWait gSource "OnTimerSetNextWaypoint")

			; Log another message with timeWait value
			(setq message (cat "Ship " (objGetName gSource) " :   setting timer to " timeWait " ticks"))
			(dbgLog message)

			; Log end of event
			(setq message (cat "Ship " (objGetName gSource) " : Exiting OnOrdersCompleted event"))
			(dbgLog message)
		)
	</OnOrdersCompleted>

	<OnTimerSetNextWaypoint>
		(block (nextWaypoint waypointsList message)
			; Log beginning of event
			(setq message (cat "Ship " (objGetName gSource) " : Entering OnTimerSetNextWaypoint event"))
			(dbgLog message)

			; Find next waypoint
			(setq waypointList (sysFindObject gSource "t:parkingOrbit"))
			(setq nextWayPoint (random waypointList))

			; Send message to player
			(setq message (cat "Ship " (objGetName gSource) " :   going to " (objGetName nextWaypoint)))
			(objSendMessage gPlayerShip gSource message)
			(dbgLog message)

			; Set new orders
			(shpCancelOrders gSource)
			(shpOrderDock gSource nextWaypoint)

			; Log end of event
			(setq message (cat "Ship " (objGetName gSource) " : Exiting OnTimerSetNextWaypoint event"))
			(dbgLog message)
		)
	</OnTimerSetNextWaypoint>
</Events>
My problem was that the OnOrdersCompleted event is also fired just after OnCreate.

So I settled on not using OnCreate and instead creating a test :
- If it is the first time OnOrdersCompleted is fired, then we wait only 5 ticks to set a destination before default behavior (go to nearest gate and gate out) takes over,
- Else we wait 200 ticks to stay docked a little while before selecting another destination.

This way I'll be able to build some traffic in my systems ! See you for next episode ^-^
@+

Benoît 'Mutos' ROBIN
Hoshikaze 2250 Project
User avatar
Mutos
Militia Lieutenant
Militia Lieutenant
Posts: 218
Joined: Thu Aug 14, 2008 3:31 am
Location: Near Paris, France
Contact:

Hi all,


Ended up with a much more streamlined code. If you look over the logging lines, you will find it simple and quite extendable, opposite to the code I posted before, that was quite unclear and specific :

Code: Select all

<Events>
	<onCreate>
		(block (message oldStatus newStatus)
			; Log beginning of event
			(setq message (cat "Ship " (objGetName gSource) " : Entering OnCreate event"))
			(dbgLog message)

			; Set variables
			(setq oldStatus (objGetData gSource "status"))
			(setq newStatus "statusCreated")

			; Log status change
			(setq message (cat "Ship " (objGetName gSource) " :   changing status from [" oldStatus "] to [" newStatus "]"))
			(dbgLog message)

			; Set status data
			(objSetData gSource "status" newStatus)

			; Log end of event
			(setq message (cat "Ship " (objGetName gSource) " : Exiting OnCreate event"))
			(dbgLog message)
		)
	</onCreate>

	<OnOrdersCompleted>
		(block (message oldStatus newStatus timeWait)
			; Log beginning of event
			(setq message (cat "Ship " (objGetName gSource) " : Entering OnOrdersCompleted event"))
			(dbgLog message)

			; Set variables
			(setq oldStatus (objGetData gSource "status"))

			; Test if first time execution
			(if (eq oldStatus "statusCreated")
				(block Nil
					; First time : we wait for just a few ticks
					(setq timeWait 1)

					; Log condition
					(setq message (cat "Ship " (objGetName gSource) " :   first time executed"))
					(dbgLog message)

					; Set the new status variable
					(setq newStatus oldStatus)
				)

				(block Nil
					; Not first time : we wait quite a long time
					(setq timeWait (random 1000 5000))

					; Log condition
					(setq message (cat "Ship " (objGetName gSource) " :   not first time executed"))
					(dbgLog message)

					; Set the new status variable
					(setq newStatus "statusDocked")
				)
			)

			; Activate timer for next orders
			(sysAddObjTimerEvent timeWait gSource "OnTimerSetNextWaypoint")

			; Log status change
			(setq message (cat "Ship " (objGetName gSource) " :   changing status from [" oldStatus "] to [" newStatus "]"))
			(dbgLog message)

			; Log timeWait value and send it to player
			(setq message (cat "Ship " (objGetName gSource) " :   setting timer to " timeWait " ticks"))
			(objSendMessage gPlayerShip gSource message)
			(dbgLog message)

			; Actually set ship status
			(objSetData gSource "status" newStatus)

			; Log end of event
			(setq message (cat "Ship " (objGetName gSource) " : Exiting OnOrdersCompleted event"))
			(dbgLog message)
		)
	</OnOrdersCompleted>

	<OnTimerSetNextWaypoint>
		(block (message oldStatus newStatus nextWaypoint waypointsList)
			; Log beginning of event
			(setq message (cat "Ship " (objGetName gSource) " : Entering OnTimerSetNextWaypoint event"))
			(dbgLog message)

			; Set variables
			(setq oldStatus (objGetData gSource "status"))
			(setq newStatus "statusInFlight")

			; Find next waypoint
			(setq waypointList (sysFindObject gSource "t:parkingOrbit"))
			(setq nextWayPoint (random waypointList))

			; Log status change
			(setq message (cat "Ship " (objGetName gSource) " :   changing status from [" oldStatus "] to [" newStatus "]"))
			(dbgLog message)

			; Tell the player next destination
			(setq message (cat "Ship " (objGetName gSource) " #" gSource " :   going to " (objGetName nextWaypoint)))
			(objSendMessage gPlayerShip gSource message)
			(dbgLog message)

			; Set new orders
			(shpCancelOrders gSource)
			(shpOrderDock gSource nextWaypoint)

			; Actually change status
			(objSetData gSource "status" newStatus)

			; Log end of event
			(setq message (cat "Ship " (objGetName gSource) " : Exiting OnTimerSetNextWaypoint event"))
			(dbgLog message)
		)
	</OnTimerSetNextWaypoint>
</Events>
This code will keep a status updated, depending on what the ship is doing. It will also log in details every status change, wait time set and destination choosen. The core code, without all the logging, follows :

Code: Select all

<Events>
	<onCreate>
		(block (message oldStatus newStatus)
			; Set variables
			(setq oldStatus (objGetData gSource "status"))
			(setq newStatus "statusCreated")

			; Set status data
			(objSetData gSource "status" newStatus)
		)
	</onCreate>

	<OnOrdersCompleted>
		(block (message oldStatus newStatus timeWait)
			; Set variables
			(setq oldStatus (objGetData gSource "status"))

			; Test if first time execution
			(if (eq oldStatus "statusCreated")
				(block Nil
					; First time : we wait for just a few ticks
					(setq timeWait 1)

					; Set the new status variable
					(setq newStatus oldStatus)
				)

				(block Nil
					; Not first time : we wait quite a long time
					(setq timeWait (random 1000 5000))

					; Set the new status variable
					(setq newStatus "statusDocked")
				)
			)

			; Activate timer for next orders
			(sysAddObjTimerEvent timeWait gSource "OnTimerSetNextWaypoint")

			; Actually set ship status
			(objSetData gSource "status" newStatus)
		)
	</OnOrdersCompleted>

	<OnTimerSetNextWaypoint>
		(block (message oldStatus newStatus nextWaypoint waypointsList)
			; Set variables
			(setq oldStatus (objGetData gSource "status"))
			(setq newStatus "statusInFlight")

			; Find next waypoint
			(setq waypointList (sysFindObject gSource "t:parkingOrbit"))
			(setq nextWayPoint (random waypointList))

			; Set new orders
			(shpCancelOrders gSource)
			(shpOrderDock gSource nextWaypoint)

			; Actually change status
			(objSetData gSource "status" newStatus)
		)
	</OnTimerSetNextWaypoint>
</Events>
@+

Benoît 'Mutos' ROBIN
Hoshikaze 2250 Project
Post Reply