Moving units

Pazyryk

Deity
Joined
Jun 13, 2008
Messages
3,584
There's a thread on this already, but its >1 yr old and perhaps out of date.

First, the function seems to have 9 args, but then the wiki gives an example usage that is much simpler:

unit:PushMission(GameInfoTypes.MISSION_MOVE_TO, plotX, plotY)​

Does anyone know if the above will drive an AI unit?

Here it is with 9 args (I'm not sure where I copied this from now):

unit:PushMission(missionType, x, y, 0, 0, 1, missionAItype, plot, unit)​

If I have to use this longer form, where can I find missionAItypes? Would GameInfoTypes.MISSION_MOVE_TO work for both missionType and missionAItype?

The old thread above calls this function using SerialEventUnitInfoDirty. But I think this may have been before PlayerDoTurn even existed. Is there any reason why I can't do the PushMission from PlayerDoTurn instead? Has the AI already moved its units at PlayerDoTurn or do they move right after this?

Is there any way to Get a unit's mission?
 
Yes, PlayerDoTurn will do (if you don't need to move AI unit at first turn...), I'm using it a lot in the WW2 mod.

About the code, I'm using
Code:
	unit:PopMission()
	unit:PushMission(MissionTypes.MISSION_MOVE_TO, x, y, 0, 0, 1, MissionTypes.MISSION_MOVE_TO, unit:GetPlot(), unit)
where x,y the destination plot, don't know if all parameters are needed.

I'm also using whoward69's Route Finding mod, or see Redox' post in this thread
 
Is there any way to Get a unit's mission?
Other than the destination plot (pUnit:LastMissionPlot() which btw returns the plot the unit is on and not nil if the unit has no mission), not that I've ever found. It would have been nice if PopMission() returned the array of values that had been pushed, but it doesn't
 
Thanks!

I actually need to move a unit to a foreign city. Really, they just need to get to an adjacent (or even 2 tile away) tile and then my own Lua function kicks in. I'm assuming that MISSION_MOVE_TO fails if you give it an invalid tile like a foreign city. Is there such a thing as MISSION_MOVE_TO_CITY? If so, has anyone used it? Otherwise I'll have to write some complicated code to find a valid adjacent tile and move to it. (I guess I should just iterate over MissionTypes to see what they are, but I don't have access now. And the wiki doesn't have them.)

Another basic question: How are folks actually using the route finding algorithms like whoward69's? If I use PushMission MISSION_MOVE_TO then the engine is just going to use its own path-finding anyway, isn't it? Or are you driving the unit 2 tiles at a time? Or do you use the route finding simply to figure out the travel distance (to evaluate possible destinations), and then allowing the engine pathfinding to actually drive the unit to the destination?
 
The route finding code was written to answer questions such as "is there a railway between city X and city Y" and "is there a coastal waterway from port Z to the capital" and not really as a "how do I move from X to Y" as it takes no account of terrain movement costs.
 
Thanks!

I actually need to move a unit to a foreign city. Really, they just need to get to an adjacent (or even 2 tile away) tile and then my own Lua function kicks in. I'm assuming that MISSION_MOVE_TO fails if you give it an invalid tile like a foreign city. Is there such a thing as MISSION_MOVE_TO_CITY? If so, has anyone used it? Otherwise I'll have to write some complicated code to find a valid adjacent tile and move to it. (I guess I should just iterate over MissionTypes to see what they are, but I don't have access now. And the wiki doesn't have them.)

Another basic question: How are folks actually using the route finding algorithms like whoward69's? If I use PushMission MISSION_MOVE_TO then the engine is just going to use its own path-finding anyway, isn't it? Or are you driving the unit 2 tiles at a time? Or do you use the route finding simply to figure out the travel distance (to evaluate possible destinations), and then allowing the engine pathfinding to actually drive the unit to the destination?
The unit will use the game path finding, and just won't move if the destination is not reachable.

I use whoward69's code to check if a land/sea route to the destination plot actually exist for the unit I'm trying to move, leaving the core engine deciding the best path then. As I'm not concerned by combined land/sea routes in my mod, it does the job.

Here's what I use, from my WWII mod, see RedAI.lua file for details, I've not the time to remove/comment the reference to variable/functions (like GetAdjacentPlots) from another parts of the code right now:

Spoiler :
Code:
function MoveUnitTo (unit, plot)
	local unitPlot = unit:GetPlot()
	local movesBefore = unit:MovesLeft()

	if movesBefore == 0 then
		Dprint ("Trying to move unit without move left, returning true as the destination may be in fact reachable... ", g_bAIDebug)
		return true
	end

	local x = plot:GetX()
	local y = plot:GetY()
	Dprint ("Trying to move unit to " .. x .."," ..y, g_bAIDebug)


	local player = Players[unit:GetOwner()]
	if player:GetID() == Game:GetActivePlayer() and SHOW_FORCED_MOVE then
		UI.LookAt(unit:GetPlot(), 0)
	end

	unit:PopMission()
	unit:PushMission(MissionTypes.MISSION_MOVE_TO, x, y, 0, 0, 1, MissionTypes.MISSION_MOVE_TO, unitPlot, unit)
	
	local movesAfter = unit:MovesLeft()

	if movesAfter < movesBefore then
		Dprint ("  - returning move done !")
		return true
	else
		Dprint ("  - returning move failed, try close plots !")
		local plotList = GetCloseDestinationList(unit, plot)
		for i, destination in ipairs(plotList) do
			local x = destination.Plot:GetX()
			local y = destination.Plot:GetY()
			Dprint ("    - Trying to move unit to " .. x .."," ..y, g_bAIDebug)
			unit:PopMission()
			unit:PushMission(MissionTypes.MISSION_MOVE_TO, x, y, 0, 0, 1, MissionTypes.MISSION_MOVE_TO, unitPlot, unit)
			movesAfter = unit:MovesLeft()
			if movesAfter < movesBefore then
				Dprint ("    - returning move done !")
				return true
			end
		end
	end
	Dprint ("  - returning move failed !")
	return false
end

function GetCloseDestinationList(unit, plot) -- return routeList = {Plot = destinationPlot, Distance = distance}

	local bDebug = true

	Dprint ("   - Get close destination list...", bDebug)

	local plotList = GetAdjacentPlots(plot)
	local routeList = {}

	local routeType = "Land" -- default...

	local unitType = unit:GetUnitType()
	local player = Players[unit:GetOwner()]

	if GameInfo.Units[unitType].Domain == "DOMAIN_SEA" or unit:IsEmbarked() then
		routeType = "Ocean"
	end

	Dprint ("   - Route type = " .. routeType, bDebug)

	for i, destinationPlot in pairs(plotList) do			
		local bRoute = isPlotConnected(player, unit:GetPlot(), destinationPlot, routeType, false, true , nil)
		if bRoute then
			local distance = getRouteLength()
			Dprint ("   - Adding route, distance = " .. distance, bDebug)
			table.insert (routeList, {Plot = destinationPlot, Distance = distance})
		end
	end

	table.sort(routeList, function(a,b) return a.Distance > b.Distance end) -- shorter distance first...

	return routeList
end

I haven't tested how this affect game turns, in my mod there's not a lot of units controlled this way.
 
Back
Top Bottom