Custom Factional Modding
-
Hello Everyone:
My name is Dragun, you might know me as the current maintainer and project head of the SCTA Mod(s). The original SCTA Mods were created by Raevn and later maintained by Axle. And because of some backend decisions in FAF Lua code (NOT FA base game lua to be clear here), it is difficult to add factions selectable in lobby. So you need some work arounds there is a few options available.
This guide/walkthrough will assume SCTA Mods or the Drop Pod Mod is installed.
- Editing the Initial Unit in Factions.lua
-For example changing uel0001 to (your commander unit equivalent), in case of SCTA, armcom.
This is easiest workaround and NOT one I'd recommend. The first issue is that AI will meme itself. As it has a unit that it doesn't know to build with. That said if you don't intend to PVE and don't mind replacing an OG Faction that is easy enough. BlackOps does something similar to what I am describing for there ACU replacement mod.
-
The second is getting yourself featured modded. This is what Nomads does, and there is a whole host of other things you need to do here. Including but not limited too setting up a specialized folder, and doing some specific backend stuff.
-
Is what I did for SCTA. I call it the Drop Pod. At game start, a for non-AI armies, their initial unit spawn is replaced with the drop pod.
Now notably base game ACU's even if added to buildable table in the unit section. Will not show up here, because they do not have a tech level. So you'll note in the SCTA Mod there is list of units MSS000x units. These are the units that are technically buildable by the Drop Pod MAS0001 for reference.
It isn't difficult to add more units or otherwise. To work with this code. Now the actual drop pod spawning. On game start depending on the mode, campaign or skirmish, one of two files get ran. ScenerioFramework or ScenerioUtils, now there are other things in these files but for now I'll focus on two specific functions.
In ScenerioFramework the function looking for is SpawnCommander. And you'd want to do a simple check basically if player then spawn the drop pod. The equivalent function here, SpawnInitialArmy Unit in ScenerioUtils here is slightly more complicated.
- Now why slightly more complicated, one is much more commonly hooked e.g. Uveso AllFaction Mod, Balth BrewLan and well SCTA. And several functions will sometimes be ran from here. Now I do destructively hook this function in SCTA, and as far as I know to achieve affect desired you'd have too. It just something to keep in mind with it.
function CreateInitialArmyGroup(strArmy, createCommander) if not ScenarioInfo.WindStatsTA then ScenarioInfo.WindStatsTA = {Thread = ForkThread(WindTAThread)} end ---[[for index, moddata in __active_mods do if moddata.name == 'All factions FAF BlackOps Nomads' then TACreateInitialArmyGroup(strArmy, createCommander) end end]] ---Need To Decide How I want compatibility to work local tblGroup = CreateArmyGroup(strArmy, 'INITIAL') local cdrUnit = false local initialUnitName if createCommander and ( tblGroup == nil or 0 == table.getn(tblGroup) ) then local ABrain = GetArmyBrain(strArmy); if(ABrain.BrainType == 'Human') then local initialUnitName = 'mas0001' cdrUnit = CreateInitialArmyUnit(strArmy, initialUnitName) cdrUnit:SetUnSelectable(false) cdrUnit:SetBusy(true) cdrUnit:SetBlockCommandQueue(true) ForkThread(ControlDelay, cdrUnit, 8.75) else local tblGroup = CreateArmyGroup( strArmy, 'INITIAL') local cdrUnit = false if createCommander and ( tblGroup == nil or 0 == table.getn(tblGroup) ) then local per = ScenarioInfo.ArmySetup[ABrain.Name].AIPersonality if per == 'sctaaiarm' then initialUnitName = 'armcom' ABrain.TA = 'ARM' elseif per == 'sctaaicore' then initialUnitName = 'corcom' ABrain.TA = 'CORE' elseif per == 'sctaairandom' then local coinFlip = math.random(2) if coinFlip == 1 then initialUnitName = 'armcom' ABrain.TA = 'ARM' else initialUnitName = 'corcom' ABrain.TA = 'CORE' end else local factionIndex = GetArmyBrain(strArmy):GetFactionIndex() initialUnitName = import('/lua/factions.lua').Factions[factionIndex].InitialUnit end cdrUnit = CreateInitialArmyUnit(strArmy, initialUnitName) if EntityCategoryContains(categories.COMMAND, cdrUnit) then if ScenarioInfo.Options['PrebuiltUnits'] == 'Off' then cdrUnit:HideBone(0, true) ForkThread(CommanderWarpDelay, cdrUnit, 3) end end end end end return tblGroup, cdrUnit end
So you'll see I check for HUMAN and then proceed to do some other functions if not. You'll also see a few references to other mods, if you want to check for compatibility or help alleviate some issues with destructive hooking you can do something like those tests shown above.
Beyond that, you'd have to make some minor edits to some unit scripts assuming you want the swirly and similar effects. For your ACU Units.
As a note if you see
---
Before something in Supreme Commander Lua code that means that part of the code is commented out with [[]] being used for when multiple lines are involved.UAL0001 = Class(taUAL0001) { OnStopBeingBuilt = function(self, builder, layer) taUAL0001.OnStopBeingBuilt(self, builder, layer) if __blueprints['eal0001'] then ForkThread(self.BlackOps, self, builder, layer) self:Destroy() end end, BlackOps = function (self, builder, layer) local position = self:GetPosition() local cdrUnit = CreateUnitHPR('eal0001', self:GetArmy(), (position.x), (position.y+1), (position.z), 0, 0, 0) cdrUnit:HideBone(0, true) cdrUnit:SetUnSelectable(false) cdrUnit:SetBlockCommandQueue(true) --WaitSeconds(2) coroutine.yield(21) cdrUnit:ForkThread(cdrUnit.PlayCommanderWarpInEffect, bones) end, } TypeClass = UAL0001
This is for for example what I did for Aeon Commander to ensure compatibility with BlackOps and then to make sure I didn't lose the swirly effect I added this to the relavent parent unit for the ACU's.
local oldtaACUUnit = ACUUnit ACUUnit = Class(oldtaACUUnit) { PlayCommanderWarpInEffect = function(self, bones) self:SetCustomName( ArmyBrains[self:GetArmy()].Nickname ) self:SetUnSelectable(false) self:SetBlockCommandQueue(true) --WaitSeconds(2) coroutine.yield(21) self:ForkThread(self.WarpInEffectThread, bones) end, WarpInEffectThread = function(self, bones) oldtaACUUnit.WarpInEffectThread(self, bones) local rotateOpt = ScenarioInfo.Options['RotateACU'] if not rotateOpt or rotateOpt == 'On' then self:RotateTowardsMid() elseif rotateOpt == 'Marker' then local marker = GetMarker(strArmy) or {} if marker['orientation'] then local o = EulerToQuaternion(unpack(marker['orientation'])) self:SetOrientation(o, true) end end end, }
Some of the code superflous for aethestics of the spawning but this will help you make factions easily selectable by your players. The Drop Pod mod on the vault, I uploaded a few weeks ago while not the full version of the drop pod code. It leaves out some things like the full warp effect here and renaming of ACU's. Would work as a baseline. The fuller version of is in the SCTAFix mod. On the vault.
With this your ACU Unit equivalent should be spawnable:
The ACU equivalent needs a few things but one of the most important is categories COMMAND. As certain game modes (i.e. assassination) work by looking for units with that categories.Example of unit buildable by the drop pod and drop pod unit itself
https://github.com/Dragun123/SCTA/tree/master/units/MAS0001 - Drop Pod
https://github.com/Dragun123/SCTA/tree/master/units/MSS0001 - Seraphim Build Unit that creates the Sera ACUI'll be adding more process as time goes on but this part is one of the more annoying parts of Custom Faction Modding for FAF
(as a note the original iteration of the drop pod code was written by Senteth_Loken. I have however revised the original code significantly sense then)
- Editing the Initial Unit in Factions.lua