couple of Ship Pointing mod event queries

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

Mon Sep 02, 2019 4:05 am

I have updated the Rotating Ship Pointing mod ready for release on the Multiverse.
This mod rotates the ship automatically to the nearest cardinal point to help with lining up long range weapons fire. It is initiated by an added action in the Ship's Interior screen.
Pretty much everything I know about events is due to marsrocks' help with this mod, so thanks again, marsrocks.

1. The mod uses 'sysAddTypeTimerEvent' to fire a "ShipDirection" event. There is code which cancels this event after 200 ticks but I have a feeling this isn't needed.
Do type timer events need to be canceled or only recurring type timer events?

The event canceling code:

Code: Select all

<StartCode>
	(block Nil
			;We start a timer event, "ShipDirection", which determine which way
			;	the ship has to turn.
		(sysAddTypeTimerEvent 2 gType "ShipDirection")
			;After 100 ticks we cancel the event as by then the ship is pointing
			;	in the desired direction.
		(sysAddTypeTimerEvent 200 gType "EndCode")
		(printTo 'console "StartCode")
	)
</StartCode>

<EndCode>
	(sysCancelTypeTimerEvent gType "ShipDirection")
</EndCode>
2. Although the mod runs fine in 1.8.3 it only functions partially in 1.9a1. I'm not sure if this is a bug or intentional. Possibly an event can't be fired from inside itself anymore?
The mod sets the playership's rotation angle continually 5 degrees closer to the closest cardinal point angle. If the playership is facing more than 10 degrees away from the desired angle it refires the 'angle resetting' event "ShipCounterMove". Over and over until the ship faces in the desired direction.
In 1.9a1 there is only one resetting of the playership angle. After that the event does not fire again for some reason. I originally tried using 'sysAddTypeTimerEvent' in the resetting event and now use 'typAddTimerEvent'. Neither will fire again if additional resetting is required although an initial reset always occurs.

Anyone got any clues about why the event won't fire again?

The counter-clockwise resetting event:

Code: Select all

<ShipCounterMove>
	;This event is the same as "ShipClockMove" except that 5 degrees is added
	;	(instead of subtracted) to the "nowAngle" value. This turns the ship in
	;	the opposite direction.
	(block (nowAngle wantAngle closeAngle interimAngle)
		(setq nowAngle (objGetProperty gPlayerShip 'rotation))
		(switch
			(and (geq nowAngle 45) (leq nowAngle 135))
				(setq wantAngle 90)

			(and (geq nowAngle 136) (leq nowAngle 225))
				(setq wantAngle 180)

			(and (geq nowAngle 226) (leq nowAngle 315))
				(setq wantAngle 270)

				;If none of the above default to 0.
			(setq wantAngle 0)
		);switch
			;Remember the desired angle for the "ShipFinalMove" event.
		(typSetData gType 'wantAngle wantAngle)

		(setq closeAngle (abs (subtract nowAngle wantAngle)))

		(if (gr closeAngle 10)
			(block (interimAngle)
				(setq interimAngle (add nowAngle 5))
				(objSetProperty gPlayerShip 'rotation interimAngle)
				(typAddTimerEvent gType 1 "ShipCounterMove")
			)
			(typAddTimerEvent gType 1 "ShipFinalMove")
		);if
	);block
</ShipCounterMove>
Mod attached.
Attachments
04 ShipPointing for ul forum.xml
(7.6 KiB) Downloaded 26 times
Stupid code. Do what I want, not what I typed in!

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

Mon Sep 02, 2019 8:45 pm

I think there was a recent change to prevent more than one of a particular timer from existing on a type/object/etc. So try cancelling the timer before creating a new one. Or use a recurring timer.

AdmiralZo
Militia Lieutenant
Militia Lieutenant
Posts: 209
Joined: Wed Feb 11, 2015 10:32 am
Location: Scouring Dantalion System for CSC Antarctica...

Tue Sep 03, 2019 4:16 am

1. The mod uses 'sysAddTypeTimerEvent' to fire a "ShipDirection" event. There is code which cancels this event after 200 ticks but I have a feeling this isn't needed.
Do type timer events need to be canceled or only recurring type timer events?
No, I don't think it needs to be cancelled because it is only fired once, unlike a recurring timer event which continues to fire indefinitely unless it is cancelled.


Try changing the typAddTimerEvent in "ShipDirection" to typAddRecurringTimerEvent. This essentially does the same thing as calling "ShipClockMove" / "ShipCounterMove" from inside itself.

Code: Select all

		<ShipDirection>
				(block (nowAngle)
						;Here marsrocks has sorted the direction the ship has to rotate into
						;	clockwise or anticlockwise.
						;Cleverly, marsrocks has selected all the values of ship direction
						;	which require a clockwise move using the event "ShipClockMove"
						;	and left any other values to default to the anticlockwise or
						;	counterclockwise event "ShipCounterMove".
					(setq nowAngle (objGetProperty gPlayerShip 'rotation))
					(switch
						(or (and (geq nowAngle 1) (leq nowAngle 45))
							(and (geq nowAngle 91) (leq nowAngle 135))
							(and (geq nowAngle 181) (leq nowAngle 225))
							(and (geq nowAngle 271) (leq nowAngle 315))
						)
							(block Nil
								(typAddRecurringTimerEvent gType 2 "ShipClockMove")
								(printTo 'console "Firing ClockMove")
							)

						(block Nil
							(typAddRecurringTimerEvent gType 2 "ShipCounterMove")
							(printTo 'console "Firing CounterMove")
						)
					);switch
					(printTo 'console "ShipDirection run")
				);block
			</ShipDirection>
This time, we need to cancel the "ShipClockMove" and "ShipCounterMove" events, otherwise we'll keep trying to point to the nearest cardinal point forever. We can do this just before "ShipFinalMove" is called.

Code: Select all

		<ShipClockMove>
				(block Nil
						;We get the angle the ship is currently facing and save it as
						;	'nowAngle'.
					(setq nowAngle (objGetProperty gPlayerShip 'rotation))
						;The value of 'wantAngle' is set to the desired finishing angle. This
						;	depends on which cardinal direction is nearest.
					(switch
						(and (geq nowAngle 45) (leq nowAngle 135))
							(setq wantAngle 90)

						(and (geq nowAngle 136) (leq nowAngle 225))
							(setq wantAngle 180)

						(and (geq nowAngle 226) (leq nowAngle 315))
							(setq wantAngle 270)

							;If none of the above we set 'wantAngle' to 0 (same as 360).
						(setq wantAngle 0)
					);switch
						;Remember the desired angle for the "ShipFinalMove" event.
					(typSetData gType 'wantAngle wantAngle)

						;We subtract 'wantAngle' from 'nowAngle' to give a value of how many
						;	degrees are left to move until the desired direction is required.
						;	We call this 'closeAngle'. The 'abs' function converts this number
						;	to a positive number if it is negative.
					(setq closeAngle (abs (subtract nowAngle wantAngle)))

						;This is the best bit, nice work, marsrocks.
						;If 'closeAngle' (how many degrees left to move) is greater than 10
						;	then the "interimAngle" code is run.
						;This reduces the number of degrees by 5, rotates the playership and
						;	adds a delay of 1 tick.
						;The code then starts again at the beginning of "ShipClockMove" to
						;	give a repeating function until 'closeAngle' is less than 10.
						;Once this happens the code fires a timer event, "ShipFinalMove".
					(if	(gr closeAngle 10)
						(block (interimAngle)
							(setq interimAngle (subtract nowAngle 5))
							(objSetProperty gPlayerShip 'rotation interimAngle)
							(printTo 'console "ClockMove run")
						)
						(block Nil
							(typAddTimerEvent gType 1 "ShipFinalMove")
							(typCancelTimerEvent gType "ShipClockMove")
							)
					);if
				);block
			</ShipClockMove>

Code: Select all

		<ShipCounterMove>
				;This event is the same as "ShipClockMove" except that 5 degrees is added,
				;	instead of subtracted, to the "nowAngle" value. This turns the ship in
				;	the opposite direction.
				(block (nowAngle wantAngle closeAngle interimAngle)
					(setq nowAngle (objGetProperty gPlayerShip 'rotation))
					(switch
						(and (geq nowAngle 45) (leq nowAngle 135))
							(setq wantAngle 90)

						(and (geq nowAngle 136) (leq nowAngle 225))
							(setq wantAngle 180)

						(and (geq nowAngle 226) (leq nowAngle 315))
							(setq wantAngle 270)

							;If none of the above, default to 0.
						(setq wantAngle 0)
					);switch
						;Remember the desired angle for the "ShipFinalMove" event.
					(typSetData gType 'wantAngle wantAngle)

					(setq closeAngle (abs (subtract nowAngle wantAngle)))

					(if (gr closeAngle 10)
						(block (interimAngle)
							(setq interimAngle (add nowAngle 5))
							(objSetProperty gPlayerShip 'rotation interimAngle)
						)
						(block Nil
							(typAddTimerEvent gType 1 "ShipFinalMove")
							(typCancelTimerEvent gType "ShipCounterMove")
							)
					);if
				);block
			</ShipCounterMove>

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

Wed Sep 04, 2019 2:03 am

Thanks. I got it working in 1.9a1 with the provided code but then discovered a bug when you move the mouse when the code is running. I haven't tried cancelling the event first then re-firing it. That might help with the bug. Not sure.
Stupid code. Do what I want, not what I typed in!

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

Thu Sep 05, 2019 3:27 am

Very clever, NMS, cancelling the event within itself will allow it to be fired again from inside. Adding the cancel code to this code from the API 29 version cancels the event inside of itself and then fires it again. This works in 1.9a1.

Code: Select all

(if (gr close 10)
	(block (desire)
		(setq desire (subtract now 5))
		(objSetProperty gplayership 'rotation desire)
			;Add this line  of code to make it work in 1.9a1/API 45.
		(sysCancelTimerEvent gSource 'CarClockMove)
		(sysAddObjTimerEvent 1 gSource 'CarClockMove)
	)
	(sysAddObjTimerEvent 1 gSource 'CarTargetNow)
);if
It doesn't help with the mouse/keyboard glitch though.
Stupid code. Do what I want, not what I typed in!

Post Reply