1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

Keeping the boys home...?

Discussion in 'Civ5 - Creation & Customization' started by sman1975, Jan 8, 2019.

  1. sman1975

    sman1975 Chieftain

    Joined:
    Aug 27, 2016
    Messages:
    760
    Location:
    Dallas, TX
    Hello,

    I'm working on a WW2 Era mod that adds some militia units to the game. They are much weaker than normal units, with other restrictions as well.

    It also seems appropriate that these units should never really leave friendly territory.

    In test games, I've noticed the AI uses these militia like normal units, sending them straight to the front lines. Tends to add an ahistorical behavior that weakens the immersive qualities I'm trying hard to introduce.

    I've played around with a few solutions, but they aren't working well. TBH, they're downright ugly, processor-intensive, and not reliable. Three things you don't want in your code.

    Was hoping someone could point me in the direction of a way of ensuring these units remain in friendly (or at least not in enemy) territory?

    Thanks in advance!

    sman1975
     
  2. whoward69

    whoward69 DLL Minion

    Joined:
    May 30, 2011
    Messages:
    8,201
    Location:
    Near Portsmouth, UK
    Custom DLL or standard game? If the former, you can use the CanMoveInto (or whatever it's called) event. See my "Units - Railroad Artillery" mod
     
    sman1975 likes this.
  3. sman1975

    sman1975 Chieftain

    Joined:
    Aug 27, 2016
    Messages:
    760
    Location:
    Dallas, TX
    Thanks, @whoward69, but unfortunately, it's a standard game.
     
  4. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,766
    Location:
    Illinois, USA
    1. Basic code method I've used to keep rival combat-units close to their home territory so long as there are any goody huts still on the game-map.
    2. I've deleted (I think) anything related to goody huts.
    3. You'd have to adapt the code a bit to specifically look at whether the unit in question is one of the militia units, and determine your 'best' value for 'iMaxWanderingDistance'.
    4. Since it runs on PlayerDoTurn it isn't as apparently processing-heavy as it actually is. PlayerDoTurn methods usually don't "seem" to the human player like they are doing much in terms of creating lag or bog-down unless of course the code is really long and really heavy in logic and execution of all that logic. It's usually the solution I go to for these sorts of things where it isn't actually necessary to execute on a real-time trigger hook-event.
    Code:
    local iMaxWanderingDistance = 8
    local iDomainLand = GameInfoTypes.DOMAIN_LAND
    
    -----------------------------------------------------------------------------------------
    -- Get nearest city belonging to 'pPlayer' to plot 'pPlot'
    -- data is returned as NearestCityObject, NearestCityDistance
    -- so you would use as like: "local pCity, iDistance = GetNearestCityData(pPlot, pPlayer)"
    -----------------------------------------------------------------------------------------
    
    function GetNearestCityData(pPlot, pPlayer)
    	local pNearestCity, iNearestDistance = "NONE", 9999
    	for pCity in pPlayer:Cities() do
    		local iDistance = Map.PlotDistance(pPlot:GetX(), pPlot:GetY(), pCity:GetX(), pCity:GetY())
    		if (iDistance < iNearestDistance) then
    			iNearestDistance = iDistance
    			pNearestCity = pCity
    		end
    	end
    	return pNearestCity, iNearestDistance
    end
    function PlayerDoTurnRepositionRivalUnits(iPlayer)
    	local pPlayer = Players[iPlayer]
    	if pPlayer:IsBarbarian() then return end
    	if pPlayer:IsHuman() then return end
    	if pPlayer:IsMinorCiv() then return end
    	local sPlayerName = pPlayer:GetName()
    	--print("PlayerDoTurnRepositionRivalUnits: The event ran for " .. sPlayerName)
    	for pUnit in pPlayer:Units() do
    		if pUnit:IsCombatUnit() then
    			if pUnit:GetDomainType() == iDomainLand then
    				local pUnitPlot = pUnit:GetPlot()
    				local pNearestCity, iDistanceToNearestCity = GetNearestCityData(pUnitPlot, pPlayer)
    				if iDistanceToNearestCity >= iMaxWanderingDistance then
    					if pNearestCity ~= "NONE" then
    						local iStartingX, iStartingY = pUnit:GetX(), pUnit:GetY()
    						pUnit:SetXY(pNearestCity:GetX(), pNearestCity:GetY())
    						pUnit:JumpToNearestValidPlot()
    						print("A unit belonging to " .. sPlayerName .. " was re-positioned from " .. iStartingX .. "," .. iStartingY .. " to " .. pUnit:GetX() .. "," .. pUnit:GetY())
    					else
    						--print("A unit belonging to " .. sPlayerName .. " should have been re-positioned from " .. pUnit:GetX() .. "," .. pUnit:GetY() .. " but this failed because the pNearestCity data was invalid")
    					end
    				else
    					--print("A unit belonging to " .. sPlayerName .. " did not need to be re-positioned from " .. pUnit:GetX() .. "," .. pUnit:GetY())
    				end
    			end
    		end
    	end
    end
    GameEvents.PlayerDoTurn.Add(PlayerDoTurnRepositionRivalUnits)
     
    sman1975 likes this.
  5. sman1975

    sman1975 Chieftain

    Joined:
    Aug 27, 2016
    Messages:
    760
    Location:
    Dallas, TX
    @LeeS - I don't know if I'm lucky or finally starting to learn a thing or two... :think:

    I've been testing a strikingly similar function - the only real difference is where you use SetXY + JumpToNearestValidPlot, I was only conducting the test every 3 turns, then using a PushMission (MISSION_MOVE_TO) for any unit that is a militia or partisan unit.

    From just a few test games, it "looked" like it was working acceptably, but I haven't put it through it's paces. The militia, with a move of 1, don't wander too far before "most of the time" it looked like they were heading home. The partisans, with a move of 2, had more opportunity for mischief, looked to be behaving properly about half of the time.

    I think your code is (as always) much more determinative than mine, but I was wondering: if you don't have "quick moves" turned on, how does the forced move (teleport?) look on the map? Hinkey? Or "good enough?"

    Thanks again, Mon! Really appreciate the solid suggestions! :thumbsup:
     
  6. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,766
    Location:
    Illinois, USA
  7. sman1975

    sman1975 Chieftain

    Joined:
    Aug 27, 2016
    Messages:
    760
    Location:
    Dallas, TX
    The thing I like about your approach is you have 100% control over what unit is where. I feel that often when I use PushMission, it is me making a suggestion to the AI, and sometimes they follow, sometimes they don't.

    But in this case, my absolute #1 design criterion is that you cannot expect the Volkssturm to be invading other nations. Just breaks the realism/immersive qualities I'm trying to make sure are in the scenario.

    No brainer to me (familiar territory, one might say...) - thanks for the code, @LeeS - it's going in the mod, making a fine bookend to the UnitSpawnHandler that is making it into the 3 mods I'm currently developing.

    Appreciate it!
     
  8. LeeS

    LeeS Imperator

    Joined:
    Jul 23, 2013
    Messages:
    5,766
    Location:
    Illinois, USA
    Yeah, the AI can and usually does override a Push Mission, so in order to preserve the mission you want the unit to do you have to keep coming back every turn (or on some other trigger event) and re-send the Push Mission if the AI has overridden it. I think some (or most) of the over-ride on a MOVE_TO is caused by pathing 'interferences' because the game's pathing system does not consider that while the target plot (for example) is currently blocked the unit that is moving to that plot is still 20 turns away from getting there.
     
    sman1975 likes this.

Share This Page