Page 1 of 1

Need Help to shorten and Improve LUA Script

Posted: Wed Aug 14, 2019 7:58 am
by Zeruel87
Greetings,

i had a similiar post in the past.
Meanwhile i have a working LUA script that tells AI players to sent Money Delivering Trucks to allied players to share their money.

Now, the LUA looks like this (this is a shortened version because the original LUA is thousands of lines long and thats the issue)

Code: Select all

WorldLoaded = function()
	p1cash()

p1cash = function()
	if p1 and p1.IsBot then
		citybottruck = p1.GetActorsByType("citybottruck")
		for _,trucks in pairs(citybottruck) do
			if p2 and p1.IsAlliedWith(p2) then
				fact = p2.GetActorsByType("fact")
				pyle = p2.GetActorsByType("pyle")
				hand = p2.GetActorsByType("hand")
				afld = p2.GetActorsByType("afld")
				weap = p2.GetActorsByType("weap")
				hpad = p2.GetActorsByType("hpad")
				for _,fact in pairs(fact) do trucks.DeliverCash(fact) end
				for _,pyle in pairs(pyle) do trucks.DeliverCash(pyle) end
				for _,hand in pairs(hand) do trucks.DeliverCash(hand) end
				for _,afld in pairs(afld) do trucks.DeliverCash(afld) end
				for _,weap in pairs(weap) do trucks.DeliverCash(weap) end
				for _,hpad in pairs(hpad) do trucks.DeliverCash(hpad) end
			end
			if p3 and p1.IsAlliedWith(p3) then
				fact = p3.GetActorsByType("fact")
				pyle = p3.GetActorsByType("pyle")
				hand = p3.GetActorsByType("hand")
				afld = p3.GetActorsByType("afld")
				weap = p3.GetActorsByType("weap")
				hpad = p3.GetActorsByType("hpad")
				for _,fact in pairs(fact) do trucks.DeliverCash(fact) end
				for _,pyle in pairs(pyle) do trucks.DeliverCash(pyle) end
				for _,hand in pairs(hand) do trucks.DeliverCash(hand) end
				for _,afld in pairs(afld) do trucks.DeliverCash(afld) end
				for _,weap in pairs(weap) do trucks.DeliverCash(weap) end
				for _,hpad in pairs(hpad) do trucks.DeliverCash(hpad) end
			end
		end
	end
	Trigger.AfterDelay(DateTime.Seconds(5), function()
		p1cash()
	end)
end
my knowledge of LUA is very small, can someone tell me how to improve / shorten the LUA?
iam sure there is a way, at the moment iam doing this script for many more buildings and not just 1 but 16 players that all have their own function and check each of the other not 3 but 15 players. if they exist and are allied with them and if so send them their trucks in the respective buildings.

maybe it is possible to do this part only once and implement it somehow else in each function

Code: Select all

				for _,fact in pairs(fact) do trucks.DeliverCash(fact) end
				for _,pyle in pairs(pyle) do trucks.DeliverCash(pyle) end
				for _,hand in pairs(hand) do trucks.DeliverCash(hand) end
				for _,afld in pairs(afld) do trucks.DeliverCash(afld) end
				for _,weap in pairs(weap) do trucks.DeliverCash(weap) end
				for _,hpad in pairs(hpad) do trucks.DeliverCash(hpad) end
or maybe it is eben pssobible to check each individual other of the 15 players but do one part that tells the AI to check Play 1,2,3... and so on.

any idea would be very much appreciated.


if you are curious, this is the real script as it looks at the moment:
https://github.com/Zeruel87/AImoneytruc ... 4fc0426c8f



the third and last thing i can think of that can possible be improved is that the whole script does not have to run every 5 seconds but checks if a Truck enters the game/map and then orders it to deliver its money to the allied building.

Re: Need Help to shorten and Improve LUA Script

Posted: Wed Nov 27, 2019 9:53 pm
by Zeruel87
Okay let me be more specific, maybe someone can answer this LUA question:
for i=0,15 do
local Spieler = Player.GetPlayer("Multi" .. tostring(i))
with this i can shorten everything, so it checks every player form 1 to 16 in that order.

BUT who knows how to either shuffle the numbers OR how to start counting from another number?
for example 5,6,7,8,9,10,11,12,13,14,15,0,1,2,3,4 isntead of 0 to 15

i tried
i=math.random(0,15)
but that does not seem to work, i guess it is because every mention if "i" is seperatly random and therefore cannot get to one result.

Long Story Short, i want to know if you can somehow start counting from a different number, i tried google but did not find anything, except the random.math thing.

Re: Need Help to shorten and Improve LUA Script

Posted: Thu Nov 28, 2019 11:16 pm
by abcdefg30
I suppose the simplest way would be

Code: Select all

local indices = { 5,6,7,8,9,10,11,12,13,14,15,0,1,2,3,4 }
for i=0,15 do
local Spieler = Player.GetPlayer("Multi" .. tostring(indices[i]))

Re: Need Help to shorten and Improve LUA Script

Posted: Tue Dec 03, 2019 2:38 pm
by Zeruel87
another Rroblem i encounter when i try to shorten my Script is:
when i try to shorten

Code: Select all

				fact = p2.GetActorsByType("fact")
				pyle = p2.GetActorsByType("pyle")
				hand = p2.GetActorsByType("hand")
				afld = p2.GetActorsByType("afld")
				weap = p2.GetActorsByType("weap")
				hpad = p2.GetActorsByType("hpad")
to

Code: Select all

				buildings = p2.GetActorsByType("fact","pyle","hand","afld","weap","hpad")
it seems that only the first actor, in that case "fact" seems to be affected and nothing behind the line.

do i have to use "GetActorsByTypes" for that?

Re: Need Help to shorten and Improve LUA Script

Posted: Tue Dec 03, 2019 3:53 pm
by Materianer
Zeruel87 wrote:
Tue Dec 03, 2019 2:38 pm
another Rroblem i encounter when i try to shorten my Script is:
when i try to shorten

Code: Select all

				fact = p2.GetActorsByType("fact")
				pyle = p2.GetActorsByType("pyle")
				hand = p2.GetActorsByType("hand")
				afld = p2.GetActorsByType("afld")
				weap = p2.GetActorsByType("weap")
				hpad = p2.GetActorsByType("hpad")
to

Code: Select all

				buildings = p2.GetActorsByType("fact","pyle","hand","afld","weap","hpad")
it seems that only the first actor, in that case "fact" seems to be affected and nothing behind the line.

do i have to use "GetActorsByTypes" for that?
I can show you how i solved this problem.

This just gives all trees a codition wich changes its colors. ( of course no needle trees :D )

Code: Select all

AllTrees = {"t03", "t10", "t11", "t12", "t13", "t14", "t15", "t17", "tc02", "tc05"}

AprilTrees = function()
	for i=1,#AllTrees do
		if i ~= nil then
			local Trees = Neutral.GetActorsByType(AllTrees[i])
			for p,tree in pairs(Trees) do
				Trigger.AfterDelay(DateTime.Seconds(Utils.RandomInteger(1, 210)), function()
					if not tree.IsDead and tree.IsInWorld and tree.HasProperty("GrantCondition") and tree.AcceptsCondition("spring2") then
						tree.GrantCondition("spring2", 0)
					end
				end)
			end
		end
	end
end
Now a bit more comlex i get the wintertrees ( i added wintertrees in yaml ) change them (Destroy and rebuild) to normal trees and put a condition on them at the same time.

Code: Select all

AllWinterStufft = {"t01winter", "t02winter", "t03winter", "t05winter", "t06winter", "t07winter", "t08winter", "t10winter", "t11winter", "t12winter", "t13winter", "t14winter", "t15winter", "t16winter", "t17winter"}
AllWinterStufftc = {"tc01winter", "tc02winter", "tc03winter", "tc04winter", "tc05winter"}
AllTNumbers = {"01", "02", "03", "04", "05", "06", "07", "08", "10", "11", "12", "13", "14", "15", "16", "17", "18"}
AllTCNumbers = {"01", "02", "03", "04", "05"}

ChangeSpringTrees = function()
	for u=1,#AllWinterStufft do
		if u ~= nil then
			local Trees = Neutral.GetActorsByType(AllWinterStufft[u])
			for p,tree in pairs(Trees) do
				for i=1,#AllTNumbers do
					if tree.Type == "t0" .. i .. "winter" then        -- This is important if you want to do different things with the actors
						Trigger.AfterDelay(DateTime.Seconds(Utils.RandomInteger(1, 25)), function()
							if not tree.IsDead and tree.IsInWorld then
								Newtree = Actor.Create("t0" .. i .. "" , true, { Location = tree.Location, Owner = Neutral })
								if Newtree.HasProperty("GrantCondition") and Newtree.AcceptsCondition("spring") then
									Newtree.GrantCondition("spring", 0)
								end
								tree.Destroy()
							end
						end)
					elseif tree.Type == "t" .. i .. "winter" then
						Trigger.AfterDelay(DateTime.Seconds(Utils.RandomInteger(1, 25)), function()
							if not tree.IsDead and tree.IsInWorld then
								Newtree = Actor.Create("t" .. i .. "" , true, { Location = tree.Location, Owner = Neutral })
								if Newtree.HasProperty("GrantCondition") and Newtree.AcceptsCondition("spring") then
									Newtree.GrantCondition("spring", 0)
								end
								tree.Destroy()
							end
						end)
					end
				end
			end
		end
	end
	for u=1,#AllWinterStufftc do
		if u ~= nil then
			local Trees = Neutral.GetActorsByType(AllWinterStufftc[u])
			for p,tree in pairs(Trees) do
				for i=1,#AllTCNumbers do
					if tree.Type == "tc0" .. i .. "winter" then
						Trigger.AfterDelay(DateTime.Seconds(Utils.RandomInteger(1, 25)), function()
							if not tree.IsDead and tree.IsInWorld then
								Newtree = Actor.Create("tc0" .. i .. "" , true, { Location = tree.Location, Owner = Neutral })
								if Newtree.HasProperty("GrantCondition") and Newtree.AcceptsCondition("spring") then
									Newtree.GrantCondition("spring", 0)
								end
								tree.Destroy()
							end
						end)
					end
				end
			end
		end
	end
Maybe you can also use this for Players in the same step i didnt need that by now.

Another example how you can setup players is here.

Code: Select all

SetupPlayers = function()
	Neutral = Player.GetPlayer("Neutral")
	Creeps = Player.GetPlayer("Creeps")
	Multi0 = Player.GetPlayer("Multi0")
	Multi1 = Player.GetPlayer("Multi1")
	Multi2 = Player.GetPlayer("Multi2")
	Multi3 = Player.GetPlayer("Multi3")
	Multi4 = Player.GetPlayer("Multi4")
	Multi5 = Player.GetPlayer("Multi5")
	Multi6 = Player.GetPlayer("Multi6")
	Multi7 = Player.GetPlayer("Multi7")
	Multi8 = Player.GetPlayer("Multi8")
	Multi9 = Player.GetPlayer("Multi9")
	Humans = { Multi0, Multi1, Multi2, Multi3, Multi4, Multi5, Multi6, Multi7, Multi8, Multi9 }
end
FuseFlag1Cell = function()
	Utils.Do(Humans, function(player)
		local flagactors = player.GetActorsByType("ctflag")
		for p,flag in pairs(flagactors) do
			if not flag.HasTag("isfused1") then
				flag.AddTag("isfused1")   	   -- This tag is to dont fuse already checked flags
				Trigger.OnEnteredProximityTrigger(flag.CenterPosition, WDist.FromCells(1), function(a, id)
					local mine = flag.Owner
					local yours = a.Owner
					if a.HasTag("flagholdingunit") and mine == yours then
						a.Stop()
						a.Kill()
					elseif mine ~= yours and a.Type == "tflag" and mine.IsAlliedWith(yours) == true then
						NewPositionFlag = Actor.Create("ctflag", true, { Location = a.Location + CVec.New(Utils.RandomInteger(-1, 2), 1), Owner = yours })
						a.Destroy()
					elseif mine ~= yours and a.Type ~= "mcv" and a.Type ~= "truk" and a.Type ~= "ctfmcv" and a.Type ~= "dpctflag" and a.HasProperty("GrantCondition") and a.AcceptsCondition("flagholder") and not a.HasTag("flagholdingunit") then
						if Mode ~= "temprasphere" and mine.IsAlliedWith(yours) == true then
							return
						else
							Trigger.RemoveProximityTrigger(id)
							if mine.IsLocalPlayer then
								SetCamera(mine)
							end
							Beacon.New(mine, a.CenterPosition, 100, true)
							a.AddTag("flagholdingunit")
							a.GrantCondition("flagholder", 0)
							a.GrantCondition("hold" .. mine.InternalName .. "flag", 0)
							if Mode ~= "hawkie" then
								if DateTime.GameTime < DateTime.Minutes(5) then
									a.GrantCondition("snailspeed", 0)
								elseif DateTime.GameTime < DateTime.Minutes(7) then
									a.GrantCondition("turtlespeed", 0)
								else
									a.GrantCondition("frogspeed", 0)
								end
							end
							flag.Destroy()
							Trigger.OnKilled(a, function()
								Flag = Actor.Create("tflag", true, { Location = a.Location, Owner = mine })
							end)
						end
					end
				end)
			end
		end
	end)
end
Here is the map i used this code for, weather effects or a capture the flag mode (and other things) are optional in the gamelobby.
https://resource.openra.net/maps/32840/
The update just failed for the newest release, but i will add an updated version soon.

Re: Need Help to shorten and Improve LUA Script

Posted: Tue Dec 10, 2019 10:44 pm
by Zeruel87
finally i got time to test this out.
i just tested this:

Code: Select all

	Gebilde = {"citybotnuke", "cityc", "citybotcoal", "citybotr", "citybotr2"}

p1building = function()
	if p1 and p1.IsBot then
		for i=1,#Gebilde do
		citybotelitearchitect = p1.GetActorsByType("citybotelitearchitect")
		for _,expert in pairs(citybotelitearchitect) do
				-- Player own Buildings
				Tester = p1.GetActorsByType(Gebilde[i])
				for _,Tester in pairs(Tester) do expert.DeliverExperience(Tester) end
				-- Other Players Buildings
		end
		end
	end
	Trigger.AfterDelay(DateTime.Seconds(6), function()
		p1building()
	end)
end
and it seems to work :? :lol: i have no idea how or why, i have to look into it to understand but it seems to work :D

Re: Need Help to shorten and Improve LUA Script

Posted: Wed Dec 11, 2019 10:06 am
by Zeruel87
i had time to do some research, i now understand how and why the # works
it is exactly this thingy that solves my problem, it utilizes all elements that are in the table {}

thanks a bunch, that shortens and improves my scripts by many lines and i learned soemthing new :)

Re: Need Help to shorten and Improve LUA Script

Posted: Wed Dec 11, 2019 9:31 pm
by Zeruel87
okay iam experimenting, my latest script for units that upgrade the rank of powerplants to increase their power looks like this:

Code: Select all

p1building = function()
	for c=0,15 do
		local Creator = Player.GetPlayer("Multi" .. tostring(c))
		if Creator and Creator.IsBot then
			for p=1,#powerall do
				citybotelitearchitect = Creator.GetActorsByType("citybotelitearchitect")
				for _,expert in pairs(citybotelitearchitect) do
					for i=0,15 do
						local Spieler = Player.GetPlayer("Multi" .. tostring(i))
						if Spieler and Creator.IsAlliedWith(Spieler) then
							poweraction = Spieler.GetActorsByType(powerall[p])
							for _,poweraction in pairs(poweraction) do expert.DeliverExperience(poweraction) end
						end
					end
				end
			end
		end
	end
	Trigger.AfterDelay(DateTime.Seconds(5), function()
		p1building()
	end)
end
the script checksif a player is in the game and if this player is a bot, it checks this for multi0 to multi 15 (16 players) and then gets all the actors/units that are called "citybotelitearchitect" and sends them to allies as well to them self within the 16 players.

but i think the first part is a disaster

Code: Select all

	for c=0,15 do
		local Creator = Player.GetPlayer("Multi" .. tostring(c))
		if Creator and Creator.IsBot then
the game seems to lag with asa little as 4 bots, prorably because it checks every 5 seconds all available bots and runs this script?

maybe i can do it differently that the script only kicks in when the unit "citybotelitearchitect" enters the map / is finished producing ?

any ideas?

Re: Need Help to shorten and Improve LUA Script

Posted: Fri Dec 13, 2019 10:55 pm
by Materianer
Zeruel87 wrote:
Wed Dec 11, 2019 10:06 am
i had time to do some research, i now understand how and why the # works
I dont fully understand how it works but thats okay for me the important thing is that it works ;)
Zeruel87 wrote:
Wed Dec 11, 2019 9:31 pm
the game seems to lag with asa little as 4 bots, prorably because it checks every 5 seconds all available bots and runs this script?
Maybe you can get the Trigger.OnAnyProduction somehow running https://github.com/OpenRA/OpenRA/wiki/Lua-API
then it would only call the check if any unit is produced.