Need Help to shorten and Improve LUA Script

I have a working LUA script that iam sure can be improved quite a bit

Information and discussion for custom maps and mods.
Post Reply
User avatar
Zeruel87
Posts: 55
Joined: Mon Oct 15, 2018 8:18 pm
Location: Austria
Contact:

Need Help to shorten and Improve LUA Script

Post by Zeruel87 » Wed Aug 14, 2019 7:58 am

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.
Check out my CnC mod at:
https://www.moddb.com/mods/cameo

User avatar
Zeruel87
Posts: 55
Joined: Mon Oct 15, 2018 8:18 pm
Location: Austria
Contact:

Re: Need Help to shorten and Improve LUA Script

Post by Zeruel87 » Wed Nov 27, 2019 9:53 pm

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.
Check out my CnC mod at:
https://www.moddb.com/mods/cameo

abcdefg30
Posts: 358
Joined: Mon Aug 18, 2014 6:00 pm

Re: Need Help to shorten and Improve LUA Script

Post by abcdefg30 » Thu Nov 28, 2019 11:16 pm

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]))

User avatar
Zeruel87
Posts: 55
Joined: Mon Oct 15, 2018 8:18 pm
Location: Austria
Contact:

Re: Need Help to shorten and Improve LUA Script

Post by Zeruel87 » 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?
Check out my CnC mod at:
https://www.moddb.com/mods/cameo

User avatar
Materianer
Posts: 191
Joined: Mon Jul 04, 2016 8:27 am

Re: Need Help to shorten and Improve LUA Script

Post by Materianer » Tue Dec 03, 2019 3:53 pm

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.

User avatar
Zeruel87
Posts: 55
Joined: Mon Oct 15, 2018 8:18 pm
Location: Austria
Contact:

Re: Need Help to shorten and Improve LUA Script

Post by Zeruel87 » Tue Dec 10, 2019 10:44 pm

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
Check out my CnC mod at:
https://www.moddb.com/mods/cameo

User avatar
Zeruel87
Posts: 55
Joined: Mon Oct 15, 2018 8:18 pm
Location: Austria
Contact:

Re: Need Help to shorten and Improve LUA Script

Post by Zeruel87 » Wed Dec 11, 2019 10:06 am

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 :)
Check out my CnC mod at:
https://www.moddb.com/mods/cameo

User avatar
Zeruel87
Posts: 55
Joined: Mon Oct 15, 2018 8:18 pm
Location: Austria
Contact:

Re: Need Help to shorten and Improve LUA Script

Post by Zeruel87 » Wed Dec 11, 2019 9:31 pm

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?
Check out my CnC mod at:
https://www.moddb.com/mods/cameo

Post Reply