Need some help on modding functions
-
It appears to be looking at the number of kills to determine veterancy. (I say "appears" because I have no idea if "UKills" represents the number of kills by that particular unit, or if it represents some other value, such as the mass value of units killed.)
A long, long time ago veterancy level was determined based on the number of kills. That's not how FAF does it now. So this might be some really old code, or it might be unused code, or it might be non-FAF code.
-
Please post code with code tags:
function RenameVet() for index, unit in allUnits do local Ukills = unit:GetStat('KILLS', 0).Value if Ukills >= unit:GetBlueprint().Veteran.Level1 and Ukills != 0 and ( unit:GetCustomName(unit) == nil or unit:IsInCategory('COMMAND') == true ) then local unitname = unit:GetBlueprint().General.UnitName local newName local temptable ; if unit:IsInCategory('COMMAND') == true then if Ukills >= unit:GetBlueprint().Veteran.Level5 then newName = "<[["..username.."]]>" elseif Ukills >= unit:GetBlueprint().Veteran.Level4 then newName = "[["..username.."]]" elseif Ukills >= unit:GetBlueprint().Veteran.Level3 then newName = "<["..username.."]>" elseif Ukills >= unit:GetBlueprint().Veteran.Level2 then newName = "["..username.."]" elseif Ukills >= unit:GetBlueprint().Veteran.Level1 then newName = "<"..username..">" else newName = username end end end end end
for index, unit in allUnits do end
This is a loop. It will loop over every entry inside the table
allUnits
and save it intounit
So you can access every unit inside the tableallUnits
Lets say you create an table with 3 words:
WORDS = { [1] = "Hallo", ['A'] = "12345", [2] = "ABCDE", }
now you are looping over the table:
for index, word in WORDS do LOG('index: '..index) LOG('word: '..word) end
you will get this output:
index: 1
word: Hallo
index: A
word: 12345
index: 2
word: ABCDElocal Ukills = unit:GetStat('KILLS', 0).Value
This will get the number of kills of this unit.
You can set this value with unit:SetStat('KILLS', unitKills)
In base game this function is only used for killstatistics.
There is nothing else saved in thereunit:GetBlueprint()
This will get you the blueprint of an unit.
Here an example for an unit blueprint:
https://github.com/FAForever/fa/blob/deploy/fafdevelop/units/UAL0401/UAL0401_unit.bpunit:GetBlueprint().Veteran.Level4
This will get the value inside
Level4
, that is part of the tableVeteran
inside the unit blueprint here:
https://github.com/FAForever/fa/blob/deploy/fafdevelop/units/UAL0401/UAL0401_unit.bp#L287So
unit:GetBlueprint().Veteran.Level4
will get the number360
unit:IsInCategory('COMMAND')
This will check the blueprint category table and search for a match.
Here is a ACU blueprint, with a matching category entry:
https://github.com/FAForever/fa/blob/deploy/fafdevelop/units/UAL0001/UAL0001_unit.bp#L131unitname = unit:GetBlueprint().General.UnitName
This will get the unitname saved inside the unitblueprint from here:
https://github.com/FAForever/fa/blob/deploy/fafdevelop/units/UAL0401/UAL0401_unit.bp#L226
Have in mind you need to remove the Translation TAG (with LOC() )before you can use this name:unitname = LOC( unit:GetBlueprint().General.UnitName )
Finally this will rename a unit
Unit:SetCustomName(newName)
-
@Sprouto
I have some BASIC and AUTOLISP programming knowledge. I have in fact many years ago programmed a Tetris game using BASIC language and Pac-man game using AUTOLISP language.
But the codes for SCFA game looked very different from what I have learned.
(1) Is there anywhere I could get some lectures or lessons from anywhere online to learn more about these functions.
(2) What coding language do they use for SCFA game ?
Thanks. -
@arma473
It started when I found that there is no way of sharing template between 2 profile name becos I wanted to use a newer profile name but found out that the template created by previous profile cannot be shared by newer profile name.
So I went online to find something that can rename my profile but instead found this.
https://forums.faforever.com/viewtopic.php?f=41&t=11382A mod that rename the unit, coded by Cobrand.
-
@Uveso
Wow, thanks for the in-depth explanation. You must be the moderator for this website site.After reading your explanation now I have some idea how these codes work.
Is there anywhere I could learn all functions of this language. LOL, I don't even know what language this is called. It looked so foreign to me compare to other programming languages.
Many thanks for the in-depth explanation. -
The complete code of autorename.lua
local NameTable = import("/mods/Veterename/tables.lua").GetTable() local allUnits = {} ; local username = nil ; function UpdateAllUnits() -- Add unit being built by others for _, unit in allUnits do if not unit:IsDead() and unit:GetFocus() and not unit:GetFocus():IsDead() then allUnits[unit:GetFocus():GetEntityId()] = unit:GetFocus() end end -- Remove dead for entityid, unit in allUnits do if unit:IsDead() then allUnits[entityid] = nil end end end function RenameVet() for index, unit in allUnits do local Ukills = unit:GetStat('KILLS', 0).Value if Ukills >= unit:GetBlueprint().Veteran.Level1 and Ukills != 0 and ( unit:GetCustomName(unit) == nil or unit:IsInCategory('COMMAND') == true ) then local unitname = unit:GetBlueprint().General.UnitName local newName local temptable ; if unit:IsInCategory('COMMAND') == true then if Ukills >= unit:GetBlueprint().Veteran.Level5 then newName = "<[["..username.."]]>" elseif Ukills >= unit:GetBlueprint().Veteran.Level4 then newName = "[["..username.."]]" elseif Ukills >= unit:GetBlueprint().Veteran.Level3 then newName = "<["..username.."]>" elseif Ukills >= unit:GetBlueprint().Veteran.Level2 then newName = "["..username.."]" elseif Ukills >= unit:GetBlueprint().Veteran.Level1 then newName = "<"..username..">" else newName = username end else if unit:IsInCategory('EXPERIMENTAL') then if unit:IsInCategory('UEF') then temptable = NameTable.UEFT4table elseif unit:IsInCategory('CYBRAN') then temptable = NameTable.CybranT4table elseif unit:IsInCategory('AEON') then temptable = NameTable.AeonT4table elseif unit:IsInCategory('SERAPHIM') then temptable = NameTable.SeraphimT4table end elseif unit:IsInCategory('DEFENSE') then temptable = NameTable.Defense elseif unit:IsInCategory('STRUCTURE') then temptable = NameTable.Structures elseif unit:IsInCategory('BATTLESHIP') == true or unit:IsInCategory('BATTLECRUISER') then temptable = NameTable.BNaval elseif unit:IsInCategory('NAVAL') then temptable = NameTable.Naval elseif unit:IsInCategory('AIR') and unit:IsInCategory('GROUNDATTACK') then temptable = NameTable.Gunships elseif unit:IsInCategory('AIR') then temptable = NameTable.AirTable else temptable = NameTable.Default end if temptable != nil then newName = temptable[math.random(table.getsize (temptable) )] end end if newName != nil then unit:SetCustomName(newName) else unit:SetCustomName("test") end end end end -- ForkThread function Repeat() -- this piece of code will actually select units at the beginning of the game -- every other unit is eventually created by other units at some point, hence we are adding them via that way local selection = GetSelectedUnits() UISelectionByCategory("ALLUNITS", false, false, false, false) for _, unit in (GetSelectedUnits() or {}) do username = unit:GetCustomName(unit); allUnits[unit:GetEntityId()] = unit end SelectUnits(selection); -- select back what was previously selected -- while true do -- while there are units alive out there WaitSeconds(1) UpdateAllUnits() RenameVet() end end -- Init function VetInit() -- if SessionIsReplay() == true then LOG("Veterename: Disabled ; Watching replay") else LOG("Veterename: Enabled") local newSelectionsMap = { ['shift-Backspace'] = {action = 'UI_Lua import("/mods/Veterename/autorename.lua").RenameVet()'}, } -- shortcut IN_AddKeyMapTable(newSelectionsMap) ForkThread(Repeat) end end
-
Wow, I think I say too early when I say "now I have some idea how these codes work".
I am still having trouble to grasp it fully how it work.
for index, unit in allUnits do end
As shown above, the words in brown color is the function, are the words in white color a variable ?
for index, word in WORDS do LOG('index: '..index) LOG('word: '..word) end
As shown above, the wording LOG, is it a function or variable ?
am I right to say that ?
'index:
this print the text "index:" out ?
'..index
will print out a variable value ?
Thanks again.
-
@Uveso
Can you explain how this code "tables.lua" filelocal NameTable = { Default = { -- land units "Destiny", "Infinity", "Void", "Overcharge", "Neo", }, UEFT4table = { "George Washington", "John Adams", "Thomas Jefferson", "James Madison", "James Monroe", "John Q. Adams", "Andrew Jackson", "Martin Van Buren", "William H. Harrison", "John Tyler", "James K. Polk", "Zachary Taylor", "Millard Fillmore", "Franklin Pierce", "James Buchanan", "Abraham Lincoln", "Andrew Johnson", "Ulysses S. Grant", "Rutherford B. Hayes", "James A. Gardield", "Chester A. Arthur", "S. Grover Cleveland", "Benjamin Harrison", "William McKinley", "Theodore Roosevelt", "William H. Taft", "T.Woodrow Wilson", "Warren G. Harding", "J. Calvin Coolidge", "Herbet C. Hoover", "Franlin D. Roosevelt", "Harry S. Truman", "Dwight D. Eisenhower", "John F. Kennedy", "Lyndon B. Johnson", "Richard M. Nixon", "Gerald R. Ford", "James E. Carter", "Ronald W. Reagan", "George H. W. Bush", "William J. 'Bill' Clinton", "George W. Bush", "Barack Obama", "Bernie Sanders", }, AeonT4table = { "UFO", }, SeraphimT4table = { "Obvious alien is obvious", }, CybranT4table = { "Obvious Troll is obvious", "This is a mantis", "Captain sneak", }, AirTable = { "Eagle", "Owl", "Falcon", "Griffin", }, Naval = { "Nessie", "Jormungandr", "The Kraken", }, BNaval = { "Leviathan", "Carcinos", }, Gunships = { "Snake", "Starvation", "Nidhogg", "Phoenix", }, Defense = { "I am expansive", "Killer", "AWW YEAA", "THIS IS SPARTA", "mega turret", "Thousand flames", "You are an idiot", }, Structures = { "Nuker", "Alpha", "Foxtrot", "Beta", "Charlie", "Echo", "Golf", "Juliett", "November", } } function GetTable() return NameTable; end
work together with this part of main codes ?
function RenameVet() for index, unit in allUnits do local Ukills = unit:GetStat('KILLS', 0).Value if Ukills >= unit:GetBlueprint().Veteran.Level1 and Ukills != 0 and ( unit:GetCustomName(unit) == nil or unit:IsInCategory('COMMAND') == true ) then local unitname = unit:GetBlueprint().General.UnitName local newName local temptable ; if unit:IsInCategory('COMMAND') == true then if Ukills >= unit:GetBlueprint().Veteran.Level5 then newName = "<[["..username.."]]>" elseif Ukills >= unit:GetBlueprint().Veteran.Level4 then newName = "[["..username.."]]" elseif Ukills >= unit:GetBlueprint().Veteran.Level3 then newName = "<["..username.."]>" elseif Ukills >= unit:GetBlueprint().Veteran.Level2 then newName = "["..username.."]" elseif Ukills >= unit:GetBlueprint().Veteran.Level1 then newName = "<"..username..">" else newName = username end else if unit:IsInCategory('EXPERIMENTAL') then if unit:IsInCategory('UEF') then temptable = NameTable.UEFT4table elseif unit:IsInCategory('CYBRAN') then temptable = NameTable.CybranT4table elseif unit:IsInCategory('AEON') then temptable = NameTable.AeonT4table elseif unit:IsInCategory('SERAPHIM') then temptable = NameTable.SeraphimT4table end elseif unit:IsInCategory('DEFENSE') then temptable = NameTable.Defense elseif unit:IsInCategory('STRUCTURE') then temptable = NameTable.Structures elseif unit:IsInCategory('BATTLESHIP') == true or unit:IsInCategory('BATTLECRUISER') then temptable = NameTable.BNaval elseif unit:IsInCategory('NAVAL') then temptable = NameTable.Naval elseif unit:IsInCategory('AIR') and unit:IsInCategory('GROUNDATTACK') then temptable = NameTable.Gunships elseif unit:IsInCategory('AIR') then temptable = NameTable.AirTable else temptable = NameTable.Default end if temptable != nil then newName = temptable[math.random(table.getsize (temptable) )] end end if newName != nil then unit:SetCustomName(newName) else unit:SetCustomName("test") end end end end
Especially this part here ...
if unit:IsInCategory('EXPERIMENTAL') then if unit:IsInCategory('UEF') then temptable = NameTable.UEFT4table elseif unit:IsInCategory('CYBRAN') then temptable = NameTable.CybranT4table elseif unit:IsInCategory('AEON') then temptable = NameTable.AeonT4table elseif unit:IsInCategory('SERAPHIM') then temptable = NameTable.SeraphimT4table end
The NameTable for UEF has a much longer name list than others ? How do this work out ?
I hope I am not giving you too much trouble getting you to explain all these. I really appreciate the explanation. -
The scripting language the game uses is called Lua. You can learn it here https://www.lua.org/pil/contents.html
Going through that will answer 90% of your questions. -
@speed2 said in Need some help on modding functions:
The scripting language the game uses is called Lua. You can learn it here https://www.lua.org/pil/contents.html
Going through that will answer 90% of your questions.Thanks, this is what I am looking for but to understand it is another question LOL.
One more question - are the blue and white color texts a function ?
Thanks again. -
This post is deleted! -
if unit:IsInCategory('MOBILE') then
(1) How do you use IsInCategory to select only units that moves around and is an attacking type of units.
I tried the above but it also consider Factory and Engineer as Mobile ?(2) Any blueprint for Tech 3 Transport unit ?
Thanks.
-
Here's a list of categories https://wiki.faforever.com/index.php?title=Mission_Scripting#Categories
-
hello SupCom_16-12-20 ,
i guess you already figured out how to use table in tables ?
If not, let me know.You will maybe find custom LUA commands inside the game.
Here is a list of all commands you can use in SIM-STATE of the game:
https://github.com/FAForever/fa/blob/deploy/fafdevelop/engine/Sim.luaAnd here a List of all commands you can use in the UI-STATE of the game:
https://github.com/FAForever/fa/blob/deploy/fafdevelop/engine/User.luaYou can't use SIM-STATE commands in UI-STATE of the game and vise versa.
SIM-STATE commands are for the gamesimulation like moving units etc.
UI-STATE commands are for the user Interface -
@speed2 said in Need some help on modding functions:
Here's a list of categories https://wiki.faforever.com/index.php?title=Mission_Scripting#Categories
Thanks. I will use this if I am doing a mission scripting. Now I am trying to work on skirmish game play.
Actually I am looking for these 2 things.
(1) category list for unit that is moving around (mobile type) and an attacking unit.(2) Blueprint for Tech 3 Transport unit.
Thanks.
-
To your question - Table in tables. After spending some time reading "Cobrand" code ... I think I roughly know how tables work. I know saying it, is easier than doing it ie. to actually write codes out that actually works without a bug.
I think I will know that when I reach that point.But right now actually I am stuck in this code here.
local NameTable = import("/mods/Veterename/tables.lua").GetTable() local allUnits = {} ; local username = nil ; function UpdateAllUnits() -- Add unit being built by others for _, unit in allUnits do if not unit:IsDead() and unit:GetFocus() and not unit:GetFocus():IsDead() then allUnits[unit:GetFocus():GetEntityId()] = unit:GetFocus() end end -- Remove dead for entityid, unit in allUnits do if unit:IsDead() then allUnits[entityid] = nil end end end function RenameVet() for index, unit in allUnits do local Ukills = unit:GetStat('KILLS', 0).Value if Ukills >= unit:GetBlueprint().Veteran.Level1 and Ukills != 0 and unit:GetCustomName(unit) == nil then local unitname = unit:GetBlueprint().General.UnitName local newName ; -- commander upgraded name if unit:IsInCategory('COMMAND') == true then if Ukills >= unit:GetBlueprint().Veteran.Level5 then newName = "[~[Top Rank: Chief Commander]~]" elseif Ukills >= unit:GetBlueprint().Veteran.Level4 then newName = "[=[2nd Rank: General]=]" elseif Ukills >= unit:GetBlueprint().Veteran.Level3 then newName = "<+>3rd Rank: Colonel<+>" elseif Ukills >= unit:GetBlueprint().Veteran.Level2 then newName = "<<4th Rank: Major>>" elseif Ukills >= unit:GetBlueprint().Veteran.Level1 then newName = "<5th Rank: First Lieutenant>" else newName = username end end else -- ONLY Tech 3 Transport Air units upgraded name if unit:IsInCategory('TRANSPORT') and unit:IsInCategory('TECH3') then if Ukills >= unit:GetBlueprint().Veteran.Level5 then newName = "[~[Top Rank: Whitehorse]~]" elseif Ukills >= unit:GetBlueprint().Veteran.Level4 then newName = "[=[2nd Rank: Hawk]=]" elseif Ukills >= unit:GetBlueprint().Veteran.Level3 then newName = "<+>3rd Rank: Pegasus<+>" elseif Ukills >= unit:GetBlueprint().Veteran.Level2 then newName = "<<4th Rank: Wolfhound>>" elseif Ukills >= unit:GetBlueprint().Veteran.Level1 then newName = "<5th Rank: Puma>" -- else -- newName = username end else -- others mobile units that moves around such as land, air and naval units upgraded name if unit:IsInCategory('DIRECTFIRE') and ( unit:IsInCategory('NAVAL') or unit:IsInCategory('LAND') or unit:IsInCategory('AIR') ) then if Ukills >= unit:GetBlueprint().Veteran.Level5 then newName = "[~[Top Rank: Chief General]~]" elseif Ukills >= unit:GetBlueprint().Veteran.Level4 then newName = "[=[2nd Rank: General]=]" elseif Ukills >= unit:GetBlueprint().Veteran.Level3 then newName = "<+>3rd Rank: Captain<+>" elseif Ukills >= unit:GetBlueprint().Veteran.Level2 then newName = "<<4th Rank: Lieutenant>>" elseif Ukills >= unit:GetBlueprint().Veteran.Level1 then newName = "<5th Rank: Sergeant>" end end end -- if newName != nil then unit:SetCustomName(newName) else unit:SetCustomName("test") end end end end -- ForkThread function Repeat() -- this piece of code will actually select units at the beginning of the game -- every other unit is eventually created by other units at some point, hence we are adding them via that way local selection = GetSelectedUnits() UISelectionByCategory("ALLUNITS", false, false, false, false) for _, unit in (GetSelectedUnits() or {}) do username = unit:GetCustomName(unit); allUnits[unit:GetEntityId()] = unit end SelectUnits(selection); -- select back what was previously selected -- while true do -- while there are units alive out there WaitSeconds(1) UpdateAllUnits() RenameVet() end end -- Init function VetInit() -- if SessionIsReplay() == true then LOG("Veterename: Disabled ; Watching replay") else LOG("Veterename: Enabled") local newSelectionsMap = { ['shift-Backspace'] = {action = 'UI_Lua import("/mods/Veterename/autorename.lua").RenameVet()'}, } -- shortcut IN_AddKeyMapTable(newSelectionsMap) ForkThread(Repeat) end end
The complete code above. Last night I ran the code using this and game still runs okay but I still cannot find out if this thing works or not as I cannot get a unit to stay on battle field long enough to see it's effect.
The last 2 blocks of code, I know for sure it won't work because I have no info as how to trap a unit that is a mobile type ie. moving type of unit and also an attacking type. And also how to trap a Transport Tech 3 unit.
-- others mobile units that moves around such as land, air and naval units upgraded name if unit:IsInCategory('DIRECTFIRE') and ( unit:IsInCategory('NAVAL') or unit:IsInCategory('LAND') or unit:IsInCategory('AIR') ) then if Ukills >= unit:GetBlueprint().Veteran.Level5 then
I don't know how to check if a unit is a mobile type and an attacking type of unit.
-- ONLY Tech 3 Transport Air units upgraded name if unit:IsInCategory('TRANSPORT') and unit:IsInCategory('TECH3') then if Ukills >= unit:GetBlueprint().Veteran.Level5 then
And also don't know how to check if a unit is a Tech 3 Transport unit.
Thanks.
-
This post is deleted! -
Use LOG commands to print debug text to the game.log.
Like:if unit:IsInCategory('TRANSPORT') and unit:IsInCategory('TECH3') then LOG('Found Unit with category TRANSPORT*TECH3') if Ukills >= unit:GetBlueprint().Veteran.Level5 then
To Check For mobil units, you can use
unit:IsInCategory('MOBILE')
units have layer category, so you can ask for land air or naval units:
unit:IsInCategory('LAND')
unit:IsInCategory('AIR')
unit:IsInCategory('NAVAL')
random Examples:
MOBILE * LAND * INDIRECTFIRE * DIRECTFIRE
for land units that can attack other land units
MOBILE * LAND * ANTIAIR
for mobile Anti Air
MOBILE * AIR * HIGHALTAIR
for ASF
MOBILE * AIR * TRANSPORTFOCUS
for Air Transporter
(if unit:IsInCategory('MOBILE') and unit:IsInCategory('AIR') and unit:IsInCategory('TRANSPORTFOCUS') then
) -
@Uveso said in Need some help on modding functions:
Use LOG commands to print debug text to the game.log.
Like:if unit:IsInCategory('TRANSPORT') and unit:IsInCategory('TECH3') then LOG('Found Unit with category TRANSPORT*TECH3') if Ukills >= unit:GetBlueprint().Veteran.Level5 then
Is there any way we could use LOG to extract the blueprint of a specific unit ?
-
@Uveso said in Need some help on modding functions:
To Check For mobil units, you can use
unit:IsInCategory('MOBILE')
units have layer category, so you can ask for land air or naval units:
unit:IsInCategory('LAND')
unit:IsInCategory('AIR')
unit:IsInCategory('NAVAL')
random Examples:
MOBILE * LAND * INDIRECTFIRE * DIRECTFIRE
for land units that can attack other land units
MOBILE * LAND * ANTIAIR
for mobile Anti Air
MOBILE * AIR * HIGHALTAIR
for ASF
MOBILE * AIR * TRANSPORTFOCUS
for Air Transporter
(if unit:IsInCategory('MOBILE') and unit:IsInCategory('AIR') and unit:IsInCategory('TRANSPORTFOCUS') then
)This might help me complete the coding. I will get back to you. Thanks a lot for these.