Force Landing for lus or gadget

Force Landing for lus or gadget

Discuss Lua based Spring scripts (LuaUI widgets, mission scripts, gaia scripts, mod-rules scripts, scripted keybindings, etc...)

Moderator: Moderators

User avatar
bobthedinosaur
Blood & Steel Developer
Posts: 2702
Joined: 25 Aug 2004, 13:31

Force Landing for lus or gadget

Post by bobthedinosaur »

Just running this by the lua experts
does this look okay, for a forced landing script for aircraft?

any suggestions for improvements?

Code: Select all

local function forceland()
	local x,y,z = Spring.GetUnitPosition(unitID)
	local landy = Spring.GetGroundHeight(x,z)
	if (y > landy) then
	landed = 2  ---landing
	Spring.MoveCtrl.Enable(unitID)
	local xsize = 32  --use hitbox
	local zsize = 54  --use hitbox
	local _,gny1,_ = Spring.GetGroundNormal ((x+(xsize*0.5)),(z+(zsize*0.5)))
	local _,gny2,_ = Spring.GetGroundNormal ((x+(xsize*0.5)),(z-(zsize*0.5)))
	local _,gny3,_ = Spring.GetGroundNormal ((x-(xsize*0.5)),(z+(zsize*0.5)))
	local _,gny4,_ = Spring.GetGroundNormal ((x-(xsize*0.5)),(z-(zsize*0.5)))
		if (gny1 < 0.98)or(gny2 < 0.98)or(gny3 < 0.98)or(gny4 < 0.98)  then  ---checks for flat landing 0.98 is ~ 11 degrees   
			landed = 3 --abort signal
			return false
		else
		  while y > (landy+10) do
					Spring.MoveCtrl.SetVelocity(unitID,0,-2.5,0)
					local x,y,z = Spring.GetUnitPosition(unitID)
					Sleep (50)
					end
		  while y > (landy) do
					Spring.MoveCtrl.SetVelocity(unitID,0,-1,0)
					local x,y,z = Spring.GetUnitPosition(unitID)
					Sleep (50)
					end
	   Spring.MoveCtrl.SetVelocity(unitID,0,0,0) 
	   x,y,z = Spring.GetUnitPosition(unitID)
	   landy = Spring.GetGroundHeight(x,z)
	   Spring.MoveCtrl.SetPosition(unitID,x,landy,z)   
	   landed = 1
	   end
	else
    Spring.MoveCtrl.SetPosition(unitID,x,landy,z)   
	landed = 1   	
	end
end
edit: with knorke's corrections
Last edited by bobthedinosaur on 04 Jan 2011, 22:51, edited 5 times in total.
User avatar
knorke
Posts: 7971
Joined: 22 Feb 2006, 01:02

Re: Force Landing for lus or gadget

Post by knorke »

Spring.MoveCtrl.SetVelocity(unitID,0,-2.5,0)

Spring.MoveCtrl.SetVelocity(unitID,0,-1,0)

these loops will loop forever

Code: Select all

      while y > (landy) do
      Spring.MoveCtrl.SetVelocity(unitID,0,-1,0,
      end
you need to re-read y every time you move the unit.

like

Code: Select all

            
--only need to set velocity once
Spring.MoveCtrl.SetVelocity(unitID,0,-1,0)
while y > (landy) do
--check every 50 ms if the unit has landed yet
local x,y,z = Spring.GetUnitPosition(unitID)
Sleep (50)
      end
User avatar
bobthedinosaur
Blood & Steel Developer
Posts: 2702
Joined: 25 Aug 2004, 13:31

Re: Force Landing for lus or gadget

Post by bobthedinosaur »

right now the unit dives underground, and wont stop! oh noes...
User avatar
FLOZi
MC: Legacy & Spring 1944 Developer
Posts: 6242
Joined: 29 Apr 2005, 01:14

Re: Force Landing for lus or gadget

Post by FLOZi »

You can use Spring.MoveCtrl.SetCollideStop and the MoveCtrlNotify callin to detect when it has hit the ground rather than doing it 'manually'
User avatar
knorke
Posts: 7971
Joined: 22 Feb 2006, 01:02

Re: Force Landing for lus or gadget

Post by knorke »

interessting, cant find anything about those.
Image
pretty please?
User avatar
bobthedinosaur
Blood & Steel Developer
Posts: 2702
Joined: 25 Aug 2004, 13:31

Re: Force Landing for lus or gadget

Post by bobthedinosaur »

FLOZi wrote:You can use Spring.MoveCtrl.SetCollideStop and the MoveCtrlNotify callin to detect when it has hit the ground rather than doing it 'manually'
examples? that sounds much easier.

also i need to add unit detection in the landing zone to avoid unit clipping.



Edit: &(%&(%$%#^!!

edit: I was frustrated... but I do appreciate the engine developers hard work.
Last edited by bobthedinosaur on 05 Jan 2011, 20:10, edited 1 time in total.
User avatar
FLOZi
MC: Legacy & Spring 1944 Developer
Posts: 6242
Joined: 29 Apr 2005, 01:14

Re: Force Landing for lus or gadget

Post by FLOZi »

knorke wrote:interessting, cant find anything about those.
Image
pretty please?
http://springrts.com/wiki/Lua_MoveCtrl

Examples from S44 SVN:

cmd_lcgm.lua - Used to make the LCG(M) ship lower itself to the sea bed (actually it mostly does it only to a limited depth because of the scale of the model vs the depth of water on most spring maps, but it does stop itself if in shallow enough water so the code is there.)

game_cruiseMissile.lua - Used for V1 missiles (explode on collide) and Gliders (die on collide and spawn units around the corpse)

game_paratroopers.lua - Used for paratroopers (switches out the paratrooper unit for the actual landed paratrooper infantry dude)

I'm not going to say these are clear examples or even easy to follow at all, good luck, have fun. :wink:
User avatar
knorke
Posts: 7971
Joined: 22 Feb 2006, 01:02

Re: Force Landing for lus or gadget

Post by knorke »

thanks.
MoveCtrlNotify(unitID, unitDefID, unitTeam, data)
when is this called, every time the unit was moved a step by the simulation?
and what is "data"?
User avatar
FLOZi
MC: Legacy & Spring 1944 Developer
Posts: 6242
Joined: 29 Apr 2005, 01:14

Re: Force Landing for lus or gadget

Post by FLOZi »

To my understanding, *snip* see kloot!

jk or kloot or Tobi or zerg or Trepan will know better. :wink:
Last edited by FLOZi on 05 Jan 2011, 21:54, edited 1 time in total.
Kloot
Spring Developer
Posts: 1867
Joined: 08 Oct 2006, 16:58

Re: Force Landing for lus or gadget

Post by Kloot »

MoveCtrlNotify is just a simple hook that only (ScriptMoveType is incomplete) fires whenever a unit under MoveCtrl drops below terrain. A gadget has to call both SetTrackGround and SetCollideStop to receive the notifications.

The data parameter was supposed to indicate the type of notification but currently never has a value other than 1 (where 1 means "unit hit the ground").
Last edited by Kloot on 05 Jan 2011, 20:29, edited 1 time in total.
User avatar
bobthedinosaur
Blood & Steel Developer
Posts: 2702
Joined: 25 Aug 2004, 13:31

Re: Force Landing for lus or gadget

Post by bobthedinosaur »

This kind of works:

It forces the initial load to be on the ground and stops the unload from flying off when done.

Code: Select all

local function forceland()
	local x,y,z = Spring.GetUnitPosition(unitID)
	local landy = Spring.GetGroundHeight(x,z)
	local xsize = 32  --use hitbox
	local zsize = 54  --use hitbox
	local mcenter = 14	--model's center
	Spring.MoveCtrl.Enable(unitID)
		Spring.Echo ("start pos",y,landy)
	if (math.floor(y) - math.floor(landy + mcenter) < 2) and (math.floor(y) - math.floor(landy + mcenter) >= 0) then
		Spring.Echo ("already on ground")
		landed = 1
		return false
	end
	if (y > (landy + mcenter)) then
		landed = 2  ---landing
		local _,gny1,_ = Spring.GetGroundNormal ((x+(xsize*0.5)),(z+(zsize*0.5)))
		local _,gny2,_ = Spring.GetGroundNormal ((x+(xsize*0.5)),(z-(zsize*0.5)))
		local _,gny3,_ = Spring.GetGroundNormal ((x-(xsize*0.5)),(z+(zsize*0.5)))
		local _,gny4,_ = Spring.GetGroundNormal ((x-(xsize*0.5)),(z-(zsize*0.5)))
			if (gny1 < 0.98)or(gny2 < 0.98)or(gny3 < 0.98)or(gny4 < 0.98)  then  ---checks for flat landing 0.98 is ~ 11 degrees   
				Spring.Echo ("landing aborted")
				landed = 3 --abort signal
				return false
			else
			  while (y > (20 + (landy + mcenter))) do
			 -- Spring.Echo ("drop at 2.5")
						Spring.MoveCtrl.SetVelocity(unitID,0,-2.5,0)
						x,y,z = Spring.GetUnitPosition(unitID)
						landy = Spring.GetGroundHeight(x,z)
						Sleep(100)
						end
			  while (y > (landy + mcenter)) do
			--- Spring.Echo ("drop at 1")	
						Spring.MoveCtrl.SetVelocity(unitID,0,-1,0)
						x,y,z = Spring.GetUnitPosition(unitID)
						landy = Spring.GetGroundHeight(x,z)
						Sleep(100)
						end
		   Spring.MoveCtrl.SetVelocity(unitID,0,0,0) 
		   x,y,z = Spring.GetUnitPosition(unitID)
		   landy = Spring.GetGroundHeight(x,z)
		   Spring.MoveCtrl.SetPosition(unitID,x,(landy+mcenter),z)   
		   landed = 1
		   end
	else
		Spring.MoveCtrl.SetPosition(unitID,x,landy,z)   
		landed = 1   	
	end
end


function script.QueryTransport(passengerID)
	return -1
end

function script.TransportPickup(passengerID)
	Spring.Echo ("hey passenger Pickup",passengerID)
	StartThread(forceland)
	while landed ~= 1 do
	sleep (500)
		if landed ==3 then --aborted
			Spring.MoveCtrl.Disable(unitID)
			landed = 0
			return false
		end
	end
	if (landed == 1) then
		Spring.UnitScript.AttachUnit (-1, passengerID)
		Turn( canopy , x_axis, math.rad(0), math.rad(30) )
		WaitForTurn(canopy, x_axis)		
		Sleep(500)
		pilot = 1
		Spring.Echo ("pilot",pilot,passengerID,"reporting")
	end
end

function script.BeginTransport(passengerID)
	Spring.Echo ("hey passenger Begin trans",passengerID)
	StartThread(forceland)
	while landed ~= 1 do
	sleep (500)
		if landed ==3 then --aborted
			Spring.MoveCtrl.Disable(unitID)
			landed = 0
			return false
		end
	end
	if (landed == 1) then
		Spring.UnitScript.AttachUnit (-1, passengerID)
		Turn( canopy , x_axis, math.rad(0), math.rad(30) )
		WaitForTurn(canopy, x_axis)		
		Sleep(500)
		pilot = 1
		Spring.Echo ("pilot",pilot,passengerID,"reporting")
	end
end

function script.StartUnload()
	Spring.Echo ("bye passenger")
	StartThread(forceland)
	while landed ~= 1 do
	sleep (500)
		if landed ==3 then --aborted
			Spring.Echo ("unload aborted")
			Spring.MoveCtrl.Disable(unitID)
			landed = 0
			return false
		end
	end
end

function script.TransportDrop()
	if (landed == 1) then
		Turn( canopy , x_axis, math.rad(-60), math.rad(30) )
		WaitForTurn(canopy, x_axis)		
		Sleep(500)
		Spring.MoveCtrl.Enable(unitID)	
		Spring.MoveCtrl.SetVelocity(unitID,0,0,0)
		local lx,ly,lz = Spring.GetUnitPosition(unitID)
		Spring.MoveCtrl.SetPosition(unitID,lx,ly+14,lz) 
		UnitScript.DropUnit( passengerID, (lx + 30), ly, (lz + 30)) --offset as not to drop inside unit 
		pilot = 0
	else 
		Spring.Echo ("unload aborted")
		return false	
	end
end	


After changing some things around, this however, lets the flight control be ignored after an unload and the aircraft takes off again to land near by... why?

Code: Select all

local function forceland()
	local x,y,z = Spring.GetUnitPosition(unitID)
	local landy = Spring.GetGroundHeight(x,z)
	local xsize = 32  --use hitbox
	local zsize = 54  --use hitbox
	local mcenter = 14	--model's center
	Spring.MoveCtrl.Enable(unitID)
		Spring.Echo ("start pos",y,landy)
	if (math.floor(y) - math.floor(landy + mcenter) < 2) and (math.floor(y) - math.floor(landy + mcenter) >= 0) then
		Spring.Echo ("already on ground")
		landed = 1
		return true
	end
	if (y > (landy + mcenter)) then
		landed = 2  ---landing
		local _,gny1,_ = Spring.GetGroundNormal ((x+(xsize*0.5)),(z+(zsize*0.5)))
		local _,gny2,_ = Spring.GetGroundNormal ((x+(xsize*0.5)),(z-(zsize*0.5)))
		local _,gny3,_ = Spring.GetGroundNormal ((x-(xsize*0.5)),(z+(zsize*0.5)))
		local _,gny4,_ = Spring.GetGroundNormal ((x-(xsize*0.5)),(z-(zsize*0.5)))
			if (gny1 < 0.98)or(gny2 < 0.98)or(gny3 < 0.98)or(gny4 < 0.98)  then  ---checks for flat landing 0.98 is ~ 11 degrees   
				Spring.Echo ("landing aborted")
				landed = 3 --abort signal
				return false
			else
			  while (y > (20 + (landy + mcenter))) do
			 -- Spring.Echo ("drop at 2.5")
						Spring.MoveCtrl.SetVelocity(unitID,0,-2.5,0)
						x,y,z = Spring.GetUnitPosition(unitID)
						landy = Spring.GetGroundHeight(x,z)
						Sleep(100)
						end
			  while (y > (landy + mcenter)) do
			--- Spring.Echo ("drop at 1")	
						Spring.MoveCtrl.SetVelocity(unitID,0,-1,0)
						x,y,z = Spring.GetUnitPosition(unitID)
						landy = Spring.GetGroundHeight(x,z)
						Sleep(100)
						end
		   Spring.MoveCtrl.SetVelocity(unitID,0,0,0) 
		   x,y,z = Spring.GetUnitPosition(unitID)
		   landy = Spring.GetGroundHeight(x,z)
		   Spring.MoveCtrl.SetPosition(unitID,x,(landy+mcenter),z)   
		   landed = 1
		   return true
		   end
	else
		Spring.MoveCtrl.SetPosition(unitID,x,(landy + mcenter),z)   
		landed = 1   
		return true
	end
end

function script.QueryTransport(passengerID)
	if landed == 1 then
	return -1
	else
	return false
	end	
end

function script.TransportPickup(passengerID)
	Spring.Echo ("hey passenger Pickup",passengerID)
	StartThread(forceland)
	while landed ~= 1 do
	sleep (500)
		if landed ==3 then --aborted
			Spring.MoveCtrl.Disable(unitID)
			landed = 0
			return false
		end
	end
	if (landed == 1) then
		Spring.UnitScript.AttachUnit (-1, passengerID)
		Turn( canopy , x_axis, math.rad(0), math.rad(30) )
		WaitForTurn(canopy, x_axis)		
		Sleep(500)
		pilot = 1
		Spring.Echo ("pilot",pilot,passengerID,"reporting")
	end
end

function script.BeginTransport(passengerID)
	Spring.Echo ("hey passenger Begin trans",passengerID)
	StartThread(forceland)
	while landed ~= 1 do
	sleep (500)
		if landed ==3 then --aborted
			Spring.MoveCtrl.Disable(unitID)
			landed = 0
			return false
		end
	end
	if (landed == 1) then
		Spring.UnitScript.AttachUnit (-1, passengerID)
		Turn( canopy , x_axis, math.rad(0), math.rad(30) )
		WaitForTurn(canopy, x_axis)		
		Sleep(500)
		pilot = 1
		Spring.Echo ("pilot",pilot,passengerID,"reporting")
	end
end

function script.StartUnload()
	Spring.Echo ("bye passenger")
	StartThread(forceland)
	while landed ~= 1 do
	sleep (500)
		if landed ==3 then --aborted
			Spring.Echo ("unload aborted")
			Spring.MoveCtrl.Disable(unitID)
			return false
		end	
	end
	if landed == 1 then
			return true
	else
		return false
	end	
end

function script.TransportDrop()
	if landed ~= 1 then --aborted
			Spring.Echo ("i said, unload aborted!")
			Spring.MoveCtrl.Disable(unitID)
			landed = 0
			return false
		end
	if (landed == 1) then
		Turn( canopy , x_axis, math.rad(-60), math.rad(30) )
		WaitForTurn(canopy, x_axis)		
		Sleep(500)
		Spring.MoveCtrl.Enable(unitID)	
		Spring.MoveCtrl.SetVelocity(unitID,0,0,0)
		local lx,ly,lz = Spring.GetUnitPosition(unitID)
		Spring.MoveCtrl.SetPosition(unitID,lx,ly+mcenter,lz) 
		UnitScript.DropUnit( passengerID, (lx + 30), ly, (lz - 30)) --offset as not to drop inside unit 
		pilot = 0
	end
end	
User avatar
FLOZi
MC: Legacy & Spring 1944 Developer
Posts: 6242
Joined: 29 Apr 2005, 01:14

Re: Force Landing for lus or gadget

Post by FLOZi »

Kloot wrote:MoveCtrlNotify is just a simple hook that only (ScriptMoveType is incomplete) fires whenever a unit under MoveCtrl drops below terrain. A gadget has to call both SetTrackGround and SetCollideStop to receive the notifications.

The data parameter was supposed to indicate the type of notification but currently never has a value other than 1 (where 1 means "unit hit the ground").
Thanks for the clarification kloot! Does that mean the other call outs do nothing at all currently?

Hmm, should probably make an example question on Q&A.
Kloot
Spring Developer
Posts: 1867
Joined: 08 Oct 2006, 16:58

Re: Force Landing for lus or gadget

Post by Kloot »

Some of the callouts are indeed no-ops (SetShotStop and SetSlopeStop), but the others work.
User avatar
FLOZi
MC: Legacy & Spring 1944 Developer
Posts: 6242
Joined: 29 Apr 2005, 01:14

Re: Force Landing for lus or gadget

Post by FLOZi »

Cool, I updated the wiki page a bit with the info from this thread:
http://springrts.com/wiki/Lua_MoveCtrl#Options
User avatar
bobthedinosaur
Blood & Steel Developer
Posts: 2702
Joined: 25 Aug 2004, 13:31

Re: Force Landing for lus or gadget

Post by bobthedinosaur »

I can get a ground detection to work with just the position and ground level comparison. maybe using the ground detection call would be easier but would it eat more or less resources?

any ways the main issue right now is figuring out how to prevent the aircraft from taking off from the engine control. it sometimes works, sometimes doesn't. is this effort even worth it? I mean is it possible to completely block the engine's movement and force it to stay down with lua or do we need to wait for a more flexible airtransport system to be engine coded?
User avatar
FLOZi
MC: Legacy & Spring 1944 Developer
Posts: 6242
Joined: 29 Apr 2005, 01:14

Re: Force Landing for lus or gadget

Post by FLOZi »

If you have the initial height difference and a constant speed, you don't need a loop to know when it will hit the deck. ;)
User avatar
bobthedinosaur
Blood & Steel Developer
Posts: 2702
Joined: 25 Aug 2004, 13:31

Re: Force Landing for lus or gadget

Post by bobthedinosaur »

I've come to the conclusion that you can attempt to block a unit's movement everywhere you can think of in the script with movectrl but it doesn't matter because the engine will override it. There is no sure way to do this with out an engine change.
User avatar
knorke
Posts: 7971
Joined: 22 Feb 2006, 01:02

Re: Force Landing for lus or gadget

Post by knorke »

override what?
the unit movement or the transport behaviour?
because i never noticed movement being overwritten by engine, you can even spin nanoframes in all directions when they are build. (what engine does not allow when spinning the piece they are build from)
User avatar
bobthedinosaur
Blood & Steel Developer
Posts: 2702
Joined: 25 Aug 2004, 13:31

Re: Force Landing for lus or gadget

Post by bobthedinosaur »

Well its kind of quirky.
You can block an air unit form the start from taking off with move, attack, or load commands. Once it has flown getting it to land and stay down is impossible. You can lock it to the ground but simple things like an attack order or unload order may make it take off and in some cases move away (horizontally) when it is still under movectrl.
User avatar
bobthedinosaur
Blood & Steel Developer
Posts: 2702
Joined: 25 Aug 2004, 13:31

Re: Force Landing for lus or gadget

Post by bobthedinosaur »

to revive an older issue, since the wiki is a little more clear and i know a little more lua...

this works: http://pastebin.com/gexWgmQE
but with a few issues:
1) it uses a fail hack for detecting the ground in landing, I wish I understood this ground collision method flozi mentioned earlier in the discussion, but I do not.
2) when unloading, air transports seem to ignore dropunit from inside script.TransportDrop, and will drop the unit directly underneath the transport at the end of the TransportDrop. so if it is on the ground it drops it inside the transport. maybe a recording of the dropped unitID's into a table and then later a movectrl them outside the transport's area would do the trick?
Post Reply

Return to “Lua Scripts”