If you have having issues with manual install make sure you delete any previous versions (including jmm889901.titanframework) before updating
This is an experimental mod and any crash logs will be appreciated, i will aim to keep backwards compatability as much as possible to make updating optional
Confused with how to use the mod, have suggestions or found a bug, please DM me the_peepeepoopoo_man.
on discord
framework for adding custom titans
To use the mod, install a compatible titan mod such as Archon or Chimera, Go to the titan loadout selection menu and select "Custom loadouts", Create a new loadout, within this loadout click the "Select Titan" button to bring up the titan selection.
global function ChimeraSetup
void function ChimeraSetup()
{
ModdedTitanData Chimera
Chimera.Name = "#DEFAULT_TITAN_CHIMERA"
Chimera.Tag = "Atlas" //The tag is displayed in the selection menu if groupsettings.showtagasprefix /suffix is enabled
//can be used to give an alternate name to a titan in selection vs actual use
Chimera.Description = "This is the description for Chimera"
Chimera.BaseSetFile = "titan_atlas_tracker"
Chimera.BaseName = "tone" //we will use monarchs model
Chimera.altChassisType = frameworkAltChassisMethod.ALT_TITAN
Chimera.titanHints = [
"#DEATH_HINT_CHIMERA_001",
"#DEATH_HINT_CHIMERA_002",
"#DEATH_HINT_CHIMERA_003",
"#DEATH_HINT_CHIMERA_004",
"#DEATH_HINT_CHIMERA_005",
"#DEATH_HINT_CHIMERA_006"
]
#if UI
Chimera.loadoutsMenuControllerFunc = ChimeraPreviewController
#endif
Chimera.groupSettings.Name = "#CHIMERACATEGORY"
Chimera.groupSettings.showTagAsSuffix = true
Chimera.groupSettings.showName = false //Only show the chassis type in selection menu
ModdedTitanWeaponAbilityData GenericWeaponMount
GenericWeaponMount.weaponName = "mp_titanweapon_xo16_vanguard" //Custom weapons can actually use default weapons as the item
Chimera.Primary = GenericWeaponMount
ModdedTitanWeaponAbilityData GenericDefensiveMount
GenericDefensiveMount.weaponName = "mp_titanability_particle_wall"
Chimera.Left = GenericDefensiveMount
ModdedTitanWeaponAbilityData DefaultCore
DefaultCore.weaponName = "mp_titancore_salvo_core" //We only have 6 passive slots, 2 are universal and 4 are titan unique
//So we can only really use 4 Generic slots meaning we cant make all items (gun, core, abilities) generic
Chimera.Core = DefaultCore
ModdedTitanWeaponAbilityData GenericOffensiveMount
GenericOffensiveMount.weaponName = "mp_titanweapon_salvo_rockets"
Chimera.Right = GenericOffensiveMount
ModdedTitanWeaponAbilityData GenricUtilityMount
GenricUtilityMount.weaponName = "mp_titanability_phase_dash"
Chimera.Mid = GenricUtilityMount
CustomPersistentVar Primary
Primary.property = "primary"
Primary.defaultValue = "mp_titanweapon_xo16_vanguard" //<- this value is actually not err, used. i need to setup "true" custom values first
Primary.passiveItemsMethod = eItemsMethod.FIND_ALL_TYPE //FIND_ALL_TYPE will setup all items matching itemTypeOverride as accepted items
Primary.itemTypeOverride = eItemTypes.TITAN_PRIMARY
Chimera.ValidationOverrides["primary"] <- Primary
/*
========Defining Passive4, or Defensive=======
*/
CustomPersistentVar Defensive
Defensive.property = "special"
Defensive.defaultValue = "mp_titanability_particle_wall"
Defensive.passiveItemsMethod = eItemsMethod.FIND_FORCE//Forces the game to use the exact list of refs we provide
//In this case FIND Seems like it would work initially, however mp_titanweapon_stun_laser is also of type TITAN_ORDNANCE, but is unique in that it fits a different slot
//therefor it must be in the utility slot
//however FIND For this slot would still discover it, and add it to the list of accepted items
Defensive.itemTypeOverride = eItemTypes.TITAN_SPECIAL
Defensive.validationFunc = IsValidChimeraSpecial
Chimera.ValidationOverrides["special"] <- Defensive
ModdedPassiveData ParticleWall
ParticleWall.Name = "mp_titanability_particle_wall"//Basegame localised names/descriptions can be used
//This may cause issues with other mods that do this as these names are both display names
//and internal names, This may change in the future
ParticleWall.description = "#WPN_TITAN_SHIELD_WALL_DESC"
ParticleWall.image = $"rui/titan_loadout/defensive/titan_defensive_particle_wall_menu"
Chimera.ValidationOverrides["special"].acceptedItems.append(ParticleWall)
ModdedPassiveData HeatShield
HeatShield.Name = "mp_titanweapon_heat_shield"
HeatShield.description = "#WPN_TITAN_HEAT_SHIELD_DESC"
HeatShield.image = $"rui/titan_loadout/defensive/titan_defensive_heat_shield_menu"
Chimera.ValidationOverrides["special"].acceptedItems.append(HeatShield)
ModdedPassiveData VortexShield
VortexShield.Name = "mp_titanweapon_vortex_shield_ion"
VortexShield.description = "WPN_TITAN_VORTEX_SHIELD_DESC"
VortexShield.image = $"rui/titan_loadout/defensive/titan_defensive_vortex_menu"
Chimera.ValidationOverrides["special"].acceptedItems.append(VortexShield)
/*
=======Defining Passive5, or utility==========
*/
CustomPersistentVar Utility
Utility.property = "antirodeo"
Utility.defaultValue = "mp_titanability_phase_dash"
Utility.passiveItemsMethod = eItemsMethod.FIND_FORCE //Not all abilities we have in this slot share a type, so we use FIND_FORCE to specify an exact list of refs
Utility.itemTypeOverride = eItemTypes.TITAN_ANTIRODEO
Utility.validationFunc = IsValidChimeraAntirodeo
Chimera.ValidationOverrides["antirodeo"] <- Utility
ModdedPassiveData Siphon
Siphon.Name = "mp_titanweapon_stun_laser"
Siphon.description = "WPN_TITAN_STUN_LASER_DESC"
Siphon.image = $"rui/titan_loadout/defensive/titan_defensive_energy_siphon_menu"
Chimera.ValidationOverrides["antirodeo"].acceptedItems.append(Siphon)
ModdedPassiveData PhaseDash
PhaseDash.Name = "mp_titanability_phase_dash"
PhaseDash.description = "WPN_TITAN_PHASE_DASH_DESC"
PhaseDash.image = $"rui/titan_loadout/tactical/titan_tactical_phase_dash_menu"
Chimera.ValidationOverrides["antirodeo"].acceptedItems.append(PhaseDash)
ModdedPassiveData hover
hover.Name = "mp_titanability_hover"
hover.description = "WPN_TITAN_HOVER_DESC"
hover.image = $"rui/titan_loadout/tactical/titan_tactical_hover_menu"
Chimera.ValidationOverrides["antirodeo"].acceptedItems.append(hover)
ModdedPassiveData tripwire
tripwire.Name = "mp_titanability_laser_trip"
tripwire.description = "WPN_TITAN_TRIPWIRE_DESC"
tripwire.image = $"rui/titan_loadout/tactical/titan_tactical_laser_tripwire_menu"
Chimera.ValidationOverrides["antirodeo"].acceptedItems.append(tripwire)
/*
=======Defining Passive6, or Offensive========
*/
CustomPersistentVar ordnanceSlot
ordnanceSlot.property = "ordnance"
ordnanceSlot.defaultValue = "mp_titanweapon_laser_lite"
ordnanceSlot.passiveItemsMethod = eItemsMethod.FIND
ordnanceSlot.itemTypeOverride = eItemTypes.TITAN_ORDNANCE
ordnanceSlot.validationFunc = IsValidChimeraOrdnance
Chimera.ValidationOverrides["ordnance"] <- ordnanceSlot
ModdedPassiveData RocketPod
RocketPod.Name = "mp_titanweapon_salvo_rockets"
RocketPod.description = "WPN_TITAN_SALVO_ROCKETS_DESC"
RocketPod.image = $"rui/titan_loadout/ordnance/tracking_rockets_menu"
Chimera.ValidationOverrides["ordnance"].acceptedItems.append(RocketPod)
ModdedPassiveData FlameWall
FlameWall.Name = "mp_titanweapon_flame_wall"
FlameWall.description = "WPN_TITAN_FIREWALL_DESC"
FlameWall.image = $"rui/titan_loadout/ordnance/flame_wall_menu"
Chimera.ValidationOverrides["ordnance"].acceptedItems.append(FlameWall)
ModdedPassiveData Laser
Laser.Name = "mp_titanweapon_laser_lite"
Laser.description = "WPN_TITAN_LASER_LITE_DESC"
Laser.image = $"rui/titan_loadout/ordnance/laser_shot_menu"
Chimera.ValidationOverrides["ordnance"].acceptedItems.append(Laser)
ModdedPassiveData DumbfireRockets
DumbfireRockets.Name = "mp_titanweapon_dumbfire_rockets"
DumbfireRockets.description = "WPN_TITAN_DUMB_SHOULDER_ROCKETS_DESC"
DumbfireRockets.image = $"rui/titan_loadout/ordnance/cluster_missile_menu"
Chimera.ValidationOverrides["ordnance"].acceptedItems.append(DumbfireRockets)
ModdedPassiveData arcWave
arcWave.Name = "mp_titanweapon_arc_wave"
arcWave.description = "WPN_TITAN_ARC_WAVE_DESC"
arcWave.image = $"rui/titan_loadout/ordnance/arc_wave_menu"
Chimera.ValidationOverrides["ordnance"].acceptedItems.append(arcWave)
CustomPersistentVar coreAbility
coreAbility.property = "coreAbility"
coreAbility.defaultValue = "mp_titancore_salvo_core"
coreAbility.passiveItemsMethod = eItemsMethod.FIND //These all match the same type, but we dont want ALL titan cores
coreAbility.itemTypeOverride = eItemTypes.TITAN_CORE_ABILITY
coreAbility.validationFunc = IsValidChimeraCore
Chimera.ValidationOverrides["coreAbility"] <- coreAbility
ModdedPassiveData SalvoCore
SalvoCore.Name = "mp_titancore_salvo_core"
SalvoCore.customIcon = true //Icons arent actually custom, but hardcoded ui atlas' arent meant to display these icons on passive icons
Chimera.ValidationOverrides["coreAbility"].acceptedItems.append(SalvoCore)
ModdedPassiveData LaserCore
LaserCore.Name = "mp_titancore_laser_cannon"
LaserCore.customIcon = true
Chimera.ValidationOverrides["coreAbility"].acceptedItems.append(LaserCore)
ModdedPassiveData FlameCore
FlameCore.Name = "mp_titancore_flame_wave"
FlameCore.customIcon = true
Chimera.ValidationOverrides["coreAbility"].acceptedItems.append(FlameCore)
ModdedPassiveData DashCore
DashCore.Name = "mp_titancore_dash_core"
DashCore.customIcon = true
Chimera.ValidationOverrides["coreAbility"].acceptedItems.append(DashCore)
ModdedPassiveData ampCore
ampCore.Name = "mp_titancore_amp_core"
ampCore.customIcon = true
Chimera.ValidationOverrides["coreAbility"].acceptedItems.append(ampCore)
FrameworkChassisStruct Ogre
Ogre.name = "Ogre"
Ogre.setFile = "titan_ogre_minigun"
Ogre.executionAnimationType = 57
#if CLIENT || SERVER
PrecacheModel($"models/titans/heavy/titan_heavy_ogre_base.mdl")
#endif
Ogre.modelOverride = $"models/titans/heavy/titan_heavy_ogre_base.mdl"
Chimera.altChassisArray.append(Ogre)
FrameworkChassisStruct Atlas
Atlas.name = "Atlas"
Atlas.setFile = "titan_atlas_tracker"
Atlas.executionAnimationType = 55
//#if CLIENT || SERVER //Removed temporarily because animations crash server
//PrecacheModel($"models/titans/medium/titan_medium_atlas_base.mdl")
//#endif
//Atlas.modelOverride = $"models/titans/medium/titan_medium_atlas_base.mdl"
Chimera.altChassisArray.append(Atlas)
FrameworkChassisStruct Stryder
Stryder.name = "Stryder"
Stryder.setFile = "titan_stryder_leadwall"
Stryder.executionAnimationType = 52
#if CLIENT || SERVER
PrecacheModel($"models/titans/light/titan_light_stryder_base.mdl")
#endif
Stryder.modelOverride = $"models/titans/light/titan_light_stryder_base.mdl"
Chimera.altChassisArray.append(Stryder)
CreateModdedTitanSimple(Chimera)//Ah yes """"""""""""Simple""""""""""""
#if CLIENT
RegisterTitanAudioFunctionByTitan("#DEFAULT_TITAN_CHIMERA", chimeraHandleVoice)
#endif
}
A base titan is just the titan from which to get the persistent passives, animations, xp and various other things from.
It should not, framework uses its own standalone persistence system built using safe IO
If persistence breaks for any reason simply go to Titanfall2\local_mod_data
and remove every file, this will reset titanframework back to its base state, while preserving your vanilla loadouts
To help debugging broken persistence data it can be helpful to run the command
titanFrameworkDevPrintsEnabled 1
Now uses a fully custom persistence system for storing loadouts using local JSON instead of trying to use basegame persistence
This means:
. Unlimited titan loadouts
. Titans no longer have restrictions on how many passives they can load
. Titans can have arbitrary persistent vars allowing more or different changable values than would otherwise be allowed
This also leads onto the main new feature
Titanframework now supports custom custom grenades, tacticals and guns, this is done using overrides rathere than creating further loadouts just for modded content
Other notable features
Remade titan UI to facilitate all the new additions, Titans can now be accessed from the "Custom loadouts" footer button on the bottom of the titan menu