How to immobilize units until enemy approaches?

A forum to discuss custom scenarios, campaigns and modding in general.

Moderators: Slitherine Core, The Lordz

Kossatx
Sergeant - 7.5 cm FK 16 nA
Sergeant - 7.5 cm FK 16 nA
Posts: 241
Joined: Wed Nov 27, 2013 3:27 pm

How to immobilize units until enemy approaches?

Post by Kossatx »

Hi again! I would like to immobilize a few units until enemy approaches 3 hexes from them. Which lines I should include in this script (enemy is faction 1)? I know "pairs" command could be useful, but I don't know how to write it :?

Code: Select all

local koenigsberg = game:GetHex(112, 17)
if koenigsberg.unit ~= nil
and unit.hex ~= nil
and unit.hex.x == 112
and unit.hex.y == 17
and unit.prototype.name == "garrison" then
unit.mp = 0
end
Robotron
Brigadier-General - Elite Grenadier
Brigadier-General - Elite Grenadier
Posts: 2151
Joined: Tue Nov 23, 2010 3:35 pm

Re: How to immobilize units until enemy approaches?

Post by Robotron »

Okay, this will be a bit more complicated.
I will try to explain it by using function Taxis() from the vanilla game.
This function checks the approach of german units on Paris that come within a range of 3 hexes.
If a german unit is found, then the event will be triggered.
In your case no event will trigger but rather the unit's movement will be set to 0.

First we need to define the center from where the check will be taken. We'll take Paris for this example

Code: Select all

  local paris = game:GetHex(82, 30)
Then we need to define the range of hexes around the center
All hexes within the range of that value will be checked.
The range must be at least 1 or the check will not work (obviously)
All these hexes will be recorded into an array called "hexes".
An array is a table with values in it.
In our case these values are all pairs of X and Y coordinates of the hexes within the defined range of 3.

Code: Select all

local hexes = game.map:GetHexesInRange(paris, 3)
Now all the hexes in that array must be checked using a "for" loop command.
A "for" loop must be closed with "end" just like any other check or function.

Code: Select all

 
 for _, hex in pairs(hexes) do
 
 end
 
Into this loop you must enter the conditions that must be met.
If the conditions are met, then the loop will be terminated using the "break" command

In the "Taxis" function the loop will be terminated once a hex contains a unit

Code: Select all

if hex.unit ~= nil
and the unit belongs to germany, which has the faction.id of 2

Code: Select all

and hex.unit.faction.id == 2
then the event triggers and the loop is terminated with a break

Code: Select all

 
SetEvent("Taxis", game.turn)
break
 
The whole function reads:

Code: Select all

function Taxis()
  local paris = game:GetHex(82, 30)
  if GetEvent("Taxis") == 0 then
      local hexes = game.map:GetHexesInRange(paris, 3)
      for _, hex in pairs(hexes) do
        if hex.unit ~= nil 
          and hex.unit.faction.id == 2 then
          SetEvent("Taxis", game.turn)
          break
        end
      end
  end
end

In your case you don't want to trigger an event but rather want to immobilize the Koenigsberg unit once Russian units come into range of let's say 4 hexes so it would read:

Code: Select all

  
  local koenigsberg= game:GetHex(112, 17)
  local hexes = game.map:GetHexesInRange(koenigsberg, 4)
      for _, hex in pairs(hexes) do
        if hex.unit ~= nil 
          and hex.unit.faction.id == 4 then
          if koenigsberg.unit ~= nil 
            and koenigsberg.unit.alliance.id == 2 then	
            koenigsberg.unit.mp = 0
            break
          end
        end
      end
To avoid a crash if there is no unit on koenigsberg there is an additional check included that makes sure the conditions are only met if Koenigsberg has a unit and the unit has alliance.id == 2 because CP has alliance.id = 2. This makes sure no Entente unit will be immobilized once Koenigsberg was captured.

Code: Select all

          
   if koenigsberg.unit ~= nil 
        and koenigsberg.unit.alliance.id == 2 then	
        koenigsberg.unit.mp = 0
        break
     end
All this must be inserted into "game.supply" script, it will not work in normal event functions.
Image
Slitherine's Commander the Great War - Director's Cut: POTZBLITZ mod!
FIND IT HERE: http://www.slitherine.com/forum/viewtopic.php?f=218&t=77884&p=662610#p662610
Kossatx
Sergeant - 7.5 cm FK 16 nA
Sergeant - 7.5 cm FK 16 nA
Posts: 241
Joined: Wed Nov 27, 2013 3:27 pm

Re: How to immobilize units until enemy approaches?

Post by Kossatx »

This is the definitive script for a garrison detached in Birmingham:

Code: Select all

local birmingham= game:GetHex(76, 22)
local hexes = game.map:GetHexesInRange(birmingham, 4)
for _, hex in pairs(hexes) do
	if hex.unit ~= nil
	and hex.unit.alliance.id == 2
	and hex.unit.type == Unit.LAND	then
		if birmingham.unit ~= nil 
		and unit.prototype.name == "garrison"
		and birmingham.unit.alliance.id == 1 then	
		birmingham.unit.mp = 0
		break
		end
       end
   end
It seems to work, thanks Robotron!
Kossatx
Sergeant - 7.5 cm FK 16 nA
Sergeant - 7.5 cm FK 16 nA
Posts: 241
Joined: Wed Nov 27, 2013 3:27 pm

Re: How to immobilize units until enemy approaches?

Post by Kossatx »

Well, the previous script for Birmingham was wrong, I think this one will work correctly. The idea is to immobilize Birmingham garrison until any CP land unit approaches:

Code: Select all

local birmingham = game:GetHex(76, 22)
local hexes = game.map:GetHexesInRange(birmingham, 5)
for _, hex in pairs(hexes) do
	if hex.unit == nil
	or (hex.unit ~= nil
	and hex.unit.type == Unit.LAND
	and hex.unit.alliance.id == 1) then
		if birmingham.unit ~= nil 
		and unit.prototype.name == "garrison"
		and birmingham.unit.alliance.id == 1 then	
		birmingham.unit.mp = 0
		break
		end
	end
end
Robotron
Brigadier-General - Elite Grenadier
Brigadier-General - Elite Grenadier
Posts: 2151
Joined: Tue Nov 23, 2010 3:35 pm

Re: How to immobilize units until enemy approaches?

Post by Robotron »

Code: Select all

local birmingham = game:GetHex(76, 22)
local hexes = game.map:GetHexesInRange(birmingham, 5)
for _, hex in pairs(hexes) do
	if hex.unit == nil
	or (hex.unit ~= nil
	and hex.unit.type == Unit.LAND
	and hex.unit.alliance.id == 1) then ---- change the 1 to 2 or else the unit will freeze when Entente units are in range
		if birmingham.unit ~= nil 
		and unit.prototype.name == "garrison"
		and birmingham.unit.alliance.id == 1 then	
		birmingham.unit.mp = 0
		break
		end
	end
end
Image
Slitherine's Commander the Great War - Director's Cut: POTZBLITZ mod!
FIND IT HERE: http://www.slitherine.com/forum/viewtopic.php?f=218&t=77884&p=662610#p662610
Kossatx
Sergeant - 7.5 cm FK 16 nA
Sergeant - 7.5 cm FK 16 nA
Posts: 241
Joined: Wed Nov 27, 2013 3:27 pm

Re: How to immobilize units until enemy approaches?

Post by Kossatx »

I know how to write an script for "when an enemy unit in range, freeze the garrison unit", but not for "mantain freeze the garrison unit until an enemy unit is in range" :( No one scrips we have post work with this purpose. I guess the only way is to make an event (like taxis event in events.lua) for each freeze garrison (in game_supply.lua), wich would be linked as a condition not satisfied to mantain the unit freeze... I think there is no way to do it only in game_supply.lua file.
Robotron
Brigadier-General - Elite Grenadier
Brigadier-General - Elite Grenadier
Posts: 2151
Joined: Tue Nov 23, 2010 3:35 pm

Re: How to immobilize units until enemy approaches?

Post by Robotron »

Please explain to me the difference between
when an enemy unit in range, freeze the garrison unit
and
mantain freeze the garrison unit until an enemy unit is in range
because I can't see any.

I just noticed another problem with your script:

Code: Select all

local birmingham = game:GetHex(76, 22)
local hexes = game.map:GetHexesInRange(birmingham, 5)
for _, hex in pairs(hexes) do
	if hex.unit == nil  ----<<<<<<----- why is this included? this would mean that even if no enemy is in range the garrison would freeze in place
	or (hex.unit ~= nil
	and hex.unit.type == Unit.LAND
	and hex.unit.alliance.id == 1) then ----<<<<<<  change the 1 to 2 or else the unit will freeze when Entente units are in range
		if birmingham.unit ~= nil 
		and unit.prototype.name == "garrison"
		and birmingham.unit.alliance.id == 1 then	
		birmingham.unit.mp = 0
		break
		end
	end
end

Also you don't have to write a script for each city. You can just check every British unit on hex with a construction originally belonging to Britain by doing:

Code: Select all

local britain = game:GetFactionById(1)
for unit in britain.units do
	if unit.hex ~= nil then
		local center = unit.hex
		local hexes = game.map:GetHexesInRange(center, 5)
		for _, hex in pairs(hexes) do
			if hex.unit ~= nil
			and hex.unit.type == Unit.LAND
			and hex.unit.alliance.id == 2 then 
				if center.unit ~= nil 
					and center.unit.prototype.name == "garrison"
					and center.unit.alliance.id == 1 
					and center.construction ~= nil 
					and center.originalFaction.id == britain.id then	
						center.unit.mp = 0
						break
				end
			end
		end
	end
end
Image
Slitherine's Commander the Great War - Director's Cut: POTZBLITZ mod!
FIND IT HERE: http://www.slitherine.com/forum/viewtopic.php?f=218&t=77884&p=662610#p662610
Kossatx
Sergeant - 7.5 cm FK 16 nA
Sergeant - 7.5 cm FK 16 nA
Posts: 241
Joined: Wed Nov 27, 2013 3:27 pm

Re: How to immobilize units until enemy approaches?

Post by Kossatx »

Robotron wrote: Thu Aug 20, 2020 4:20 pm Please explain to me the difference between
when an enemy unit in range, freeze the garrison unit
and
mantain freeze the garrison unit until an enemy unit is in range
because I can't see any.
With the first one I mean an unit is free to move until enemy units are in range, when is freezed (useless). With the second one the unit is freeze from the first turn until enemy units are in range from the hex it occupies (what I want).
Robotron wrote: Thu Aug 20, 2020 4:20 pm I just noticed another problem with your script:

Code: Select all

local birmingham = game:GetHex(76, 22)
local hexes = game.map:GetHexesInRange(birmingham, 5)
for _, hex in pairs(hexes) do
	if hex.unit == nil  ----<<<<<<----- why is this included? this would mean that even if no enemy is in range the garrison would freeze in place
	or (hex.unit ~= nil
	and hex.unit.type == Unit.LAND
	and hex.unit.alliance.id == 1) then ----<<<<<<  change the 1 to 2 or else the unit will freeze when Entente units are in range
		if birmingham.unit ~= nil 
		and unit.prototype.name == "garrison"
		and birmingham.unit.alliance.id == 1 then	
		birmingham.unit.mp = 0
		break
		end
	end
end
It was a wrong try, it's difficult for me to explain the reason in english :|
Robotron wrote: Thu Aug 20, 2020 4:20 pm Also you don't have to write a script for each city. You can just check every British unit on hex with a construction originally belonging to Britain by doing:

Code: Select all

local britain = game:GetFactionById(1)
for unit in britain.units do
	if unit.hex ~= nil then
		local center = unit.hex
		local hexes = game.map:GetHexesInRange(center, 5)
		for _, hex in pairs(hexes) do
			if hex.unit ~= nil
			and hex.unit.type == Unit.LAND
			and hex.unit.alliance.id == 2 then 
				if center.unit ~= nil 
					and center.unit.prototype.name == "garrison"
					and center.unit.alliance.id == 1 
					and center.construction ~= nil 
					and center.originalFaction.id == britain.id then	
						center.unit.mp = 0
						break
				end
			end
		end
	end
end
It's an interesting script I'll use for other purposes, but not for "freezed garrisons" subject. I only want to freeze a few garrisons, not all of them in british cities.
Robotron
Brigadier-General - Elite Grenadier
Brigadier-General - Elite Grenadier
Posts: 2151
Joined: Tue Nov 23, 2010 3:35 pm

Re: How to immobilize units until enemy approaches?

Post by Robotron »

The last script will only freeze British garrisons on British cities if CP land units are in range of 5 hexes.

Is that not what you wanted?
Image
Slitherine's Commander the Great War - Director's Cut: POTZBLITZ mod!
FIND IT HERE: http://www.slitherine.com/forum/viewtopic.php?f=218&t=77884&p=662610#p662610
Kossatx
Sergeant - 7.5 cm FK 16 nA
Sergeant - 7.5 cm FK 16 nA
Posts: 241
Joined: Wed Nov 27, 2013 3:27 pm

Re: How to immobilize units until enemy approaches?

Post by Kossatx »

Is'nt what I want. I want, for example, the garrison in Birmingham begin the game freezed in it's hex, but if in any turn CP land units are in 5 hexes range from Birmingham the garrison becomes free to move.
Robotron
Brigadier-General - Elite Grenadier
Brigadier-General - Elite Grenadier
Posts: 2151
Joined: Tue Nov 23, 2010 3:35 pm

Re: How to immobilize units until enemy approaches?

Post by Robotron »

Code: Select all

local birmingham = game:GetHex(76, 22)
local check = 0
local hexes = game.map:GetHexesInRange(birmingham, 5)
		for _, hex in pairs(hexes) do
			if hex.unit ~= nil
			and hex.unit.type == Unit.LAND
			and hex.unit.alliance.id == 2 then 
				if birmingham.unit ~= nil 
					and birmingham.unit.prototype.name == "garrison"
					and birmingham.unit.faction.id == 1 then	
						check = 1
						break
				end
			end
		end
		if check == 0 then
			unit.mp = 0
		end
Image
Slitherine's Commander the Great War - Director's Cut: POTZBLITZ mod!
FIND IT HERE: http://www.slitherine.com/forum/viewtopic.php?f=218&t=77884&p=662610#p662610
Kossatx
Sergeant - 7.5 cm FK 16 nA
Sergeant - 7.5 cm FK 16 nA
Posts: 241
Joined: Wed Nov 27, 2013 3:27 pm

Re: How to immobilize units until enemy approaches?

Post by Kossatx »

Thanks for your help Robotron :idea: It looks pretty good, but for any reason it freezes all units, not only in Birmingham :shock:
Robotron
Brigadier-General - Elite Grenadier
Brigadier-General - Elite Grenadier
Posts: 2151
Joined: Tue Nov 23, 2010 3:35 pm

Re: How to immobilize units until enemy approaches?

Post by Robotron »

Code: Select all

local birmingham = game:GetHex(76, 22)
local check = 0
local hexes = game.map:GetHexesInRange(birmingham, 5)
		for _, hex in pairs(hexes) do
			if hex.unit ~= nil
			and hex.unit.type == Unit.LAND
			and hex.unit.alliance.id == 2 then
				check = 1
				break	
			end
		end
		
		if birmingham.unit ~= nil 
		and birmingham.unit.prototype.name == "garrison"
		and birmingham.unit.faction.id == 1 
		and check == 0	then
			birmingham.unit.mp = 0
		end	
Image
Slitherine's Commander the Great War - Director's Cut: POTZBLITZ mod!
FIND IT HERE: http://www.slitherine.com/forum/viewtopic.php?f=218&t=77884&p=662610#p662610
Kossatx
Sergeant - 7.5 cm FK 16 nA
Sergeant - 7.5 cm FK 16 nA
Posts: 241
Joined: Wed Nov 27, 2013 3:27 pm

Re: How to immobilize units until enemy approaches?

Post by Kossatx »

While tesing the script, in turn 3 and 4 the game crashes with this strange error I have no idea how to repair. I'm very grateful to you for your help Robotron, isn't necessary to continue struggling with this in your holidays :wink:

Code: Select all

[00:05:02][4208]game/game_events.lua:14(global SetEvent) game/game_events.lua:14: attempt to compare number with nil
Robotron
Brigadier-General - Elite Grenadier
Brigadier-General - Elite Grenadier
Posts: 2151
Joined: Tue Nov 23, 2010 3:35 pm

Re: How to immobilize units until enemy approaches?

Post by Robotron »

How should I be able to fix that crash if I don't know what's in line 14 in your game_events.lua?

Upload the whole script in a zip file so I can have a look at it.

*edit*

probably you forgot to include the game.turn when using SetEvent("XXX", game.turn)
Image
Slitherine's Commander the Great War - Director's Cut: POTZBLITZ mod!
FIND IT HERE: http://www.slitherine.com/forum/viewtopic.php?f=218&t=77884&p=662610#p662610
Kossatx
Sergeant - 7.5 cm FK 16 nA
Sergeant - 7.5 cm FK 16 nA
Posts: 241
Joined: Wed Nov 27, 2013 3:27 pm

Re: How to immobilize units until enemy approaches?

Post by Kossatx »

Here it is, crack!
Attachments
ctgw.rar
(4.05 KiB) Downloaded 70 times
Robotron
Brigadier-General - Elite Grenadier
Brigadier-General - Elite Grenadier
Posts: 2151
Joined: Tue Nov 23, 2010 3:35 pm

Re: How to immobilize units until enemy approaches?

Post by Robotron »

Okay, it was MY fault, not yours. :oops:

Open game_events.lua
go to function RussiaStorm()
which is at line 2700 or so

replace the whole function with

Code: Select all

function RussiaStorm()
local belgium = game:GetFactionById(6)
local russia = game:GetFactionById(4)

	if GetEvent("RussiaStorm") == 0
		and player.alliance.id == 2
		and game.type == Game.TYPE_SINGLE 
		and GetEvent("Rupprecht") <= 0
		and GetEvent("AllEast") <= 0
		and GetEvent("Redeploy") <= 0
		and GetEvent("BelgiumAttacked2") == 0
		and GetEvent("DOWgermany") >0
		and GetEvent("RussiaMob") <= 0
		and GetEvent("RussiaSurprise") == 0
		and GetEvent("DOWrussia") == 0 then
		
			SetFactionAlignment(4, 100)  
			SetEvent("RussiaSurprise", game.turn)
			SetEvent("RussiaStorm", -1)
		end
end
Image
Slitherine's Commander the Great War - Director's Cut: POTZBLITZ mod!
FIND IT HERE: http://www.slitherine.com/forum/viewtopic.php?f=218&t=77884&p=662610#p662610
Kossatx
Sergeant - 7.5 cm FK 16 nA
Sergeant - 7.5 cm FK 16 nA
Posts: 241
Joined: Wed Nov 27, 2013 3:27 pm

Re: How to immobilize units until enemy approaches?

Post by Kossatx »

It works Robotron! Great script, thank you very much :D
Kossatx
Sergeant - 7.5 cm FK 16 nA
Sergeant - 7.5 cm FK 16 nA
Posts: 241
Joined: Wed Nov 27, 2013 3:27 pm

Re: How to immobilize units until enemy approaches?

Post by Kossatx »

By the way, the sound for the russian surprise attack is fearing :shock:
Robotron
Brigadier-General - Elite Grenadier
Brigadier-General - Elite Grenadier
Posts: 2151
Joined: Tue Nov 23, 2010 3:35 pm

Re: How to immobilize units until enemy approaches?

Post by Robotron »

This goes into a section of game_supply.

Script for Birmingham garrison to freeze when CP units are NOT in range.

Code: Select all

local birmingham = game:GetHex(76, 22)
local check = 0
if unit.hex ~= nil 
  and unit.faction.id == 1 	
  and unit.hex == birmingham then

local ahexes = game.map:GetHexesInRange(birmingham, 5)
		for _, hex in pairs(ahexes) do
			if hex.unit ~= nil
			and hex.unit.type == Unit.LAND
			and hex.unit.alliance.id == 2 then
				check = 1
				break	
			end
		end
		if unit.prototype.name == "garrison"
		and check == 0	then
			unit.mp = 0
		end	
end
Considering the "Morale Freeze" thread: there seems to be no solution other than to delete the lines with the morale check.

In all honesty I find your methods to do functions with checks for units in over 200 different cities ("more than 200 variables") not at all desirable or even feasible .
In the long end you will just put the AI in chains and find yourself in an endless process of checking a single function with several hundreds of special cases.
This is a modder's nightmare!
To conserve my sanity I have decided not to help you with this specific problem anymore and to concentrate on getting on with my mod.

If you have other troubles in other areas you can of course ask me anything.

I hope you understand.

Cheers.
Image
Slitherine's Commander the Great War - Director's Cut: POTZBLITZ mod!
FIND IT HERE: http://www.slitherine.com/forum/viewtopic.php?f=218&t=77884&p=662610#p662610
Post Reply

Return to “Commander the Great War : Mods & Scenario Design”