Siedler 4 Scripting

Hier habe ich ein paar Scripts hinterlegt, die ich in meinen Maps öfter verwende. Ihr könnte diese gerne in eure Scripts mit einbinden.

Zudem könnt ihr euch auch die Scripts der Maps auf einem Github anschauen und etwas stöbern.

Wenn ihr Fragen dazu habt oder es Probleme mit den Script gibt, könnt ihr mich auch gerne auf Discord oder Insta kontaktieren. Viel Spaß dabei und happy Scripting 😀

Wollt ihr selbst mit der Entwicklung starten? Nutzt am besten für einen einfachen Einstieg mein Template, in diesem sind einige Funktionen schon richtig konfiguriert vorhanden.

https://github.com/sl4ng3r/theSettlers4Scripts/blob/master/Template.lua

Ich habe auch ein kurzes Tutorial für einen schnellen Start erstellt.

Anzahl an Gebäuden eines Spielers:

Hier könnt ihr euch für eine PlayerId die Anzahl seiner gebauten Gebäude geben lassen. Es werden nur fertige Gebäude gezählt. Dies könnt ihr aber auch simpel ändern indem ihr bei Buildings.READY einen anderen Wert setzt.

function getAmoutOfBuildings(playerId)
	local counter = 1
	local amountOfBuildings = 0
	
	--IDs der Gebaeude gehen von 1 - 83
	while counter <= 83 do
		amountOfBuildings = amountOfBuildings + Buildings.Amount(playerId, counter, Buildings.READY)
		counter = counter +  1
	end
	return amountOfBuildings
end 

Verschiedene Methoden, um die Anzahl von Einheiten zu bekommen

Wichtig ist, dass ihr das Array „militaryUnits“ im globalen Bereich definiert (außerhalb der Funktion). In diesem Array werden alle Einheiten Typen aufgelistet, die gezählt werden.

Anwendungsbeispiel:
Wenn ein Spieler mehr als … Einheiten hat, lasse die KI angreifen.

militaryUnits={Settlers.SWORDSMAN_01,Settlers.SWORDSMAN_02,Settlers.SWORDSMAN_03,Settlers.BOWMAN_01,Settlers.BOWMAN_02,Settlers.BOWMAN_03,Settlers.AXEWARRIOR_01,Settlers.AXEWARRIOR_02,Settlers.AXEWARRIOR_03,Settlers.BLOWGUNWARRIOR_01,Settlers.BLOWGUNWARRIOR_02,Settlers.BLOWGUNWARRIOR_03,Settlers.BACKPACKCATAPULIST_01,Settlers.BACKPACKCATAPULIST_02,Settlers.BACKPACKCATAPULIST_03,Settlers.MEDIC_01,Settlers.MEDIC_02,Settlers.MEDIC_03,Settlers.SQUADLEADER}
-- Anzahl der Soldaten eines Spielers
function getAmountOfPlayerUnits(playerId)
	local amoutOfMilitary = 0
	local counter = 1
	while counter <= getn(militaryUnits) do 
		amoutOfMilitary =  amoutOfMilitary + Settlers.Amount(playerId, militaryUnits[counter])
		counter = counter + 1
	end
	return amoutOfMilitary 
end 

-- Anzahl an Soldaten eines Spieler ohne die Soldaten innerhalb der Gebäude
function getAmountOfPlayerUnitsWithoutBuildings(playerId)
	local allUnitsWithoutBuilding = getAmountOfPlayerUnits(playerId)
	allUnitsWithoutBuilding = allUnitsWithoutBuilding - getUnitsInBuildings(playerId)
	return allUnitsWithoutBuilding
end 

-- Anzahl der Soldaten eines Spielers innerhalb seiner Gebäude
function getUnitsInBuildings(playerId)
	local allUnits = 0
	allUnits = allUnits + Buildings.Amount(playerId, Buildings.GUARDTOWERSMALL, Buildings.READY)
	allUnits = allUnits + Buildings.Amount(playerId, Buildings.GUARDTOWERBIG, Buildings.READY) * 6
	allUnits = allUnits + Buildings.Amount(playerId,Buildings.CASTLE, Buildings.READY) * 8
	return allUnits
end

Nachkomma Stellen abschneiden:

Mit dieser Funktion könnt ihr Nachkomma Stellen abschneiden, da leider im Siedler LUA Math nicht angebunden ist, muss man sich solche Funktionen selbst schreiben.

Anwendungsbeispiel:
Ihr braucht ganze Zahlen nach einer Division

-- Schneidet Nachkommastellen ab. 
function floorNumber(floatNumber)
	local stringmyValue =  tostring(floatNumber)
	if strfind (stringmyValue, "(%.+)") ~= nil then 
		local valuestring = strsub (stringmyValue, 1, strfind (stringmyValue, "(%.+)"))
		return tonumber(valuestring)
	else
		return floatNumber
	end

end

Siedler 4 Zufallszahl:

Das Problem mit der Siedler Random Funktion… Eigentlich gibt es in Siedler eine Random Funktion „Game.Random(number)“. Allerdings ist diese Funktion leider nicht so richtig zuverlässig. Game.Random(number) gibt immer eine Zufallszahl zurück entsprechend der Übergabe, allerdings gibt sie zu einem genau selben Zeitpunkt immer die selbe Zufallszahl zurück. Das bedeutet, wollt ihr z.B. in Minute 40 immer eine Random zahl ziehen, wird immer die selbe Random zahl zurück kommen.

Daraufhin hatten wir in der Scripter Community große Diskussionen, wie man dieses Problem lösen könnte. Entstanden ist dann die Funktion, die ihr unten findet. Danke an der Stelle an Hippo, der die getSeed Methode geschrieben hat. Diese berechnet anhand der aktuellen Gegebenheiten, (Häußer, Siedler… ) einen Seed der für die Zufallszahl benötigt wird.

Wie funktioniert die randomBeteween Funktion. Ihr gebt einfach mit, zwischen welchen Zahlen ihr gerne eine Zufallszahl haben möchtet. Die übergebenen Zahlen können auch zurück kommen (inklusive).

Anwendungsbeispiel:
local myRandomNumber = randomBetween(3,9) –> Liefert Zahlen zwischen 3 und 9.

function randomBetween(fromNumber, toNumber)
	if seed == 0 or Game.Time() >= (lastSeed + 5) then
		seed = getSeed()
		lastSeed = Game.Time()
	else
		seed = seed * Settlers.Amount(1, Settlers.CARRIER)
	end
	seed = seed - floorNumber(seed)
	local divNumber = toNumber - fromNumber
	local randomNumber = fromNumber + floorNumber(seed * (divNumber + 1))
	return randomNumber
end

function getSeed()
	local width = Map.Width() - 1;
	local height = Map.Height() - 1;
	local x
	local y
	local p = Game.NumberOfPlayers()
	local seed = 0

	while p > 0
	do
		x = width
		while x >= 0
		do
			y = height
			while y >= 0
			do
				seed = seed + (Settlers.AmountInArea(p, Settlers.ANY_SETTLER, x, y, 1) * p * x * y) / 1000000
				y = y - 10
			end
			x = x - 10
		end
		p = p - 1
	end
	return seed
end