Unit Morphing at selectable location

Unit Morphing at selectable location

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

Moderator: Moderators

Post Reply
UberWaffe
Posts: 10
Joined: 08 Mar 2012, 13:27

Unit Morphing at selectable location

Post by UberWaffe »

This issue relates to Conflict Terra, Issue 207

Concept:
Essentially the idea is that a unit can be given the order to morph into another unit, but to do so at a specific location. The location is also checked for being a valid location for the resulting unit to be created (i.e. if you morph into a ship, did you specify a location in water).

This could be used in instances beyond that envisioned for CT. For example, to ability to create a unit that acts like a construction kit, deploying into a structure.


Problem:
I am a bit lost as to what would be the best approach for tackling this. As per Sanada's suggestion in the link, I want to approach this as two separate items, namely a unsynced widget (for selecting the morph location) and a synced gadget (for (re-)checking the validity of the placement, and issuing the resulting move/morph order).

That way it is more modular and more in line with what I understand the coding approach to be.

I've taken a look at the current morph code, as well as some widgets from the widget library that display some form of ghosted image (Got "Show Build" and "Ghost Site" as examples).

I'm a bit overwhelmed at the moment by it all, so let's just start off with which (if any) of these options is better.


Approaches:
1. Widget uses current build system
1.1 Ties into build menu (Make the morph choices build-able unit/structure options, with the morphing unit essentially a constructor).
1.2 Intercepts such 'build' commands, removing them and calling the gadget with the "morph into ID" and the "morph at coordinates/orientation" data.
[Easier? Current build system will allow for image ghosting and placement testing.
Hacky?
Support for multiple morph possibilities with pictures, maybe?]

2. Widget defines new command
2.1 Ties into command menu [could this tie into the build menu? I.E. brings up a 'buildlist' of morph choices?]
2.2 Requires user to then specify location
2.3 Displays ghost image at location, with orientation changeable as with normal building.
2.4 [Does possible validation check of location?]
2.5 Passes data to gadget.
[More work?
Limited?]


3. Gadget as command queuer
3.1 Validates target location
3.2 Adds move command to morphing unit's queue.
3.3 Adds existing morph command to morphing unit's queue.
[Possible problem with unit that fails to reach destination?
Very Hacky?
Easy?]

4. Gadget as new single command
3.1 Validates target location
3.2 Adds single command to morphing unit's queue, namely: Morph at location
3.3 New command requests a move command to location (inserted before itself into queue)
3.4 When new command tries to execute (I.E. presumably because destination was reached) it first check location, and re-issues move command if not. [Possible limit on re-issues?]
3.5 If at location, issues morph command with orientation.
[More work?
Feasible?]


Disclaimer:
I've got minimal lua experience, so stupidity in above approaches is likely.

Other:
Suggestions of more examples I can look at would be welcome.

I'll probably start with the widget, and work on it until it can spit out a debug message that correctly gives [unitID, unitDefID, x, y, z, orientation, teamID], then I'll tackle the gadget side.
Google_Frog
Moderator
Posts: 2464
Joined: 12 Oct 2007, 09:24

Re: Unit Morphing at selectable location

Post by Google_Frog »

My main advice: Do not use a widget!

Widget command handling is extremely painful compared to gadgets and can be avoided almost all of the time. Gadgets can add things that appear as synced commands with many nice.

Also check out ZK's morph gadget because you can already queue morph as part of a build queue. As in you can say Move shift-morph and it will morph at a location.
User avatar
Niobium
Posts: 456
Joined: 07 Dec 2008, 02:35

Re: Unit Morphing at selectable location

Post by Niobium »

Google_Frog wrote:My main advice: Do not use a widget!
I'd personally use both a gadget and a widget. The gadget would handle just the command related business, and do no drawing or graphical anything. The widget would handle drawing the ghosts, highlighting invalid positions, possibly highlighting valid positions, etc.

I think the widget+gadget approach would also work better given that you are still learning, as it cleanly separates what you have to do into two parts which are each in their own file. Most of the gadgets that try to do everything in the gadget end up as giant inseparable messes (Which isn't good if you want someone to help you with it/work on it)
Google_Frog
Moderator
Posts: 2464
Joined: 12 Oct 2007, 09:24

Re: Unit Morphing at selectable location

Post by Google_Frog »

Ok it may be worthwhile using a widget for drawing. Just avoid widget command definition.
UberWaffe
Posts: 10
Joined: 08 Mar 2012, 13:27

Re: Unit Morphing at selectable location

Post by UberWaffe »

Thanks for the advice. Will proceed with a separate widget and gadget approach.
Also check out ZK's morph gadget because you can already queue morph as part of a build queue. As in you can say Move shift-morph and it will morph at a location.
I'll do that, thanks.

EDIT: 15 March 2012
I haven't been able to find more detail on gadgetHandler:RegisterCMDID(blabla).
How does one specify whether a newly defined command must require the user to select a location (like building or d-gun) after clicking the command button?

Also, with Spring.GetActiveCommand() can one grab the command parameters similar to widget:CommandNotify(cmdID, cmdParams, cmdOptions)?
Google_Frog
Moderator
Posts: 2464
Joined: 12 Oct 2007, 09:24

Re: Unit Morphing at selectable location

Post by Google_Frog »

http://springrts.com/wiki/Lua_CMDs CMDTYPE

Spring.GetActiveCommand() returns the thing attached to your cursor. That isn't a command with params, it is just a cmdID.
UberWaffe
Posts: 10
Joined: 08 Mar 2012, 13:27

Re: Unit Morphing at selectable location

Post by UberWaffe »

Google_Frog wrote:
Thanks, Google_Frog. This helped a lot. For some reason the first time I had read it it didn't sink in. I was confused by gadgetHandler:RegisterCMDID only taking an ID. But I got it now.



I've made some progress, but I'm getting stuck on a issue in the widget.

Widget.
Summary: Struggling to get hold of command parameters in DrawWorld().

Code: Select all

------------------------------------------------------------
-- Callins
------------------------------------------------------------
-- For now it seems to me I will have to catch the ID to morph to here with CommandNotify, and then use below in DrawWorld
function widget:CommandNotify(cmdID, cmdParams, cmdOptions)	
	if (cmdID >= CMD_MORPHLOC) then
        spEcho("<Morph Ghost> Command captured in CommandNotify.")
		spEcho(cmdParams)
		unitIDToMorphTo = 1 -- TODO: Need to somehow catch MorphToID
	end
end

function widget:DrawWorld()
	
	-- This widget must only activate for morph at location commands
	local _, cmdID = spGetActiveCommand()
	if not (cmdID) then return end --Check for invalid commands (For some reason I got nil return values)
	if not (cmdID >= CMD_MORPHLOC) then return end
	
	spEcho("<Morph Ghost> Command captured in DrawWorld.")
	spEcho(spGetActiveCommand())
	
	-- Attempt to get position of command
	local mx, my = spGetMouseState()
	local _, pos = spTraceScreenRay(mx, my, true)
	if not pos then return end
	
	-- Find build position and check if it is valid
	local morphIntoUnitID = 1 -- FIXME. Should equal unitIDToMorphTo
	local morphTeamID = 1 -- FIXME
	local bx, by, bz
	bx = pos[1]
	by = pos[2]
	bz = pos[3]
	--local bx, by, bz = Spring.Pos2BuildPos(morphIntoUnitID, pos[1], pos[2], pos[3]); --FIXME. Attempt to do deploy location sanity check.
	
	-- Get final facing for morphing
	local bface = Spring.GetBuildFacing()
	bface = HeadingToFacing(bface)
	
	-- Draw !
	glColor(0.3, 1.0, 0.3, 0.25)
	glDepthTest(true)
	
	glPushMatrix()
	glTranslate( bx, by, bz)
	glRotate(bface,0,by,0)
	
	glUnitShape(morphIntoUnitID, morphTeamID)
		  
	glPopMatrix()
	
	ResetGl()
end

--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
Currently I got the widget to the stage that it shows a ghosted version of a model while you select the deploy (morph) location. Problem is I don't know how to catch the unitDefID to morph to from the spGetActiveCommand as it does not pass the command parameters.
My original intent was to catch it via the CommandNotify, and pass via a local script variable. But CommandNotify triggers once the user selects the location (i.e. after this widget is to run). Can be seen in the infolog snippet:

Code: Select all

[f=0000248] <Morph Ghost> Command captured in DrawWorld.
[f=0000248] 19, 31215, 10, Deploy
[f=0000251] <Morph Ghost> Command captured in CommandNotify.
[f=0000251] <table>
[f=0000251] TABLE: 1107.4453125, 175.80334472656, 543.18701171875
Currently I can only think of defining some local table that will translate specific morph commands to unit models (i.e. this morph command ID is 31215 = Starting Cruiser Deploy). This solution is ugly for several reasons, so I'd rather find another way if possible.


Gadget:
Currently all I have done so far is change the command to require a position to be selected, and add code to check if the unit's current position is close enough to the target position. If not, the command aborts.

Still todo: Make the unit move to the target position if too far away before attempting the morph.
Post Reply

Return to “Lua Scripts”