FAForever Forums
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Login

    Custom Factional Modding

    Scheduled Pinned Locked Moved Modding & Tools
    1 Posts 1 Posters 215 Views
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Dragun101D Offline
      Dragun101
      last edited by Dragun101

      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)

      I’m a shitty 1k Global. Any balance or gameplay suggestions should be understood or taken as such.

      Project Head and current Owner/Manager of SCTA Project

      1 Reply Last reply Reply Quote 1
      • First post
        Last post