Custom Factional Modding

1

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.

  1. 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.

  1. 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.

  2. 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.

SCTA 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.

  1. 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 ACU

I'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)