Module:NarrativeEventLister

From Terra Invicta Official Wiki

Documentation for this module may be created at Module:NarrativeEventLister/doc

---
---Reads the NarrativeEvent data files and presents them in readable formats, with additional calculated statistics.
---
---@module NarrativeEventLister
local NarrativeEventLister = {}

--region Dependencies
local RestrictionChecker = require('Module:RestrictionChecker')
local IconModule = require('Module:Icon')
local TVModule = require('Module:TV')
local StringReplaceModule = require('Module:StringReplace')
local sreplace = StringReplaceModule.replace

local NarrativeEventData = mw.loadData('Module:CSVReader/NarrativeEvent')

local MapRegionToRegion = mw.loadData('Module:RegionLister/MapRegions')

local HabModuleNames = mw.loadData('Module:ENReader/HabModule')
local NarrativeEventNames = mw.loadData('Module:ENReader/NarrativeEvent')
local NationNames = mw.loadData('Module:ENReader/Nation')
local ObjectiveNames = mw.loadData('Module:ENReader/Objective')
local OrgNames = mw.loadData('Module:ENReader/Org')
local RegionNames = mw.loadData('Module:ENReader/Region')
local SpaceBodyNames = mw.loadData('Module:ENReader/SpaceBody')
local TechNames = mw.loadData('Module:ENReader/Tech')
local TraitNames = mw.loadData('Module:ENReader/Trait')
local UtilityModuleNames = mw.loadData('Module:ENReader/UtilityModule')

local EffectDescriptionBuilder = require('Module:EffectLister/DescriptionBuilder')
local ProjectNameBuilder = require('Module:ProjectLister/NameBuilder')
--endregion

--region Private constants
local tinsert = table.insert
local tconcat = table.concat
local sfind = string.find
local ssub = string.sub
local ScienceCategories = {
	Energy = 'energy',
	InformationScience='information',
	LifeScience='life',
	Materials='material',
	MilitaryScience='military',
	SocialScience='social',
	SpaceScience='space',
	Xenology='xenology'
}
local costMultiplierStrings = {
	region_popMillions = "[[Regions|Region's]] " .. TVModule.TV({args={'pop'}}) .. " in Millions",
	nation_numControlPoints = "[[Nations|Nation's]] number of [[Control Points]]",
	nation_numRegions = "[[Nations|Nation's]] number of [[Regions]]",
	nation_spaceProgramSize = "[[Nations|Nation's]] (Annual [[Boost]] / 5 + [[MC]] / 2 + [[Space Defenses]])",
	nation_democracy = "[[Nations|Nation's]] " .. TVModule.TV({args={'democracy'}}),
	nation_autocracy = "(10 - [[Nations|Nation's]] " .. TVModule.TV({args={'democracy'}}) .. ")",
	nation_miltech = "[[Nations|Nation's]] " .. TVModule.TV({args={'miltech'}}),
	nation_education = "[[Nations|Nation's]] " .. TVModule.TV({args={'education'}}),
	global_campaignDuration = "(Current Campaign Duration / 2.5 Years)",
	global_GDP = "(Global [[GDP]] ^ 0.33 / 30000)",
	global_fissionTechLevel_discount, -- Gone
	global_fusionTechLevel_discount, -- Gone
	hab_tier = "[[Habs|Hab's]] Tier",
	hab_sectors = "[[Habs|Hab's]] number of Sectors",
	hab_modules = "[[Habs|Hab's]] number of Modules",
	faction_numControlPointsWeighted = "[[Factions|Faction's]] Annual " .. TVModule.TV({args={'influence'}}) .. " cost from being over their " .. TVModule.TV({args={'cp'}}),
	army_miltech = "[[Army]]'s " .. TVModule.TV({args={'miltech'}}),
	globalTemperatureAnomaly_C = "[[Climate_Change|Global Temperature Anomaly (C)]]",
	globalSeaLevelAnomaly_cm = "[[Climate_Change#Global_Sea_Level_Anomaly|Sea Level Anomaly (cm)]]",
}

local ideoToFaction = {
	Destroy = IconModule.Icon({args={'destroy'}}) .. '[[Humanity First]]',
	Resist = IconModule.Icon({args={'resist'}}) .. '[[The Resistance]]',
	Escape = IconModule.Icon({args={'escape'}}) .. '[[Project Exodus]]',
	Exploit = IconModule.Icon({args={'exploit'}}) .. '[[The Initiative]]',
	Cooperate = IconModule.Icon({args={'cooperate'}}) .. '[[The Academy]]',
	Appease = IconModule.Icon({args={'appease'}}) .. '[[The Protectorate]]',
	Submit = IconModule.Icon({args={'submit'}}) .. '[[The Servants]]',
	Alien = IconModule.Icon({args={'alien'}}) .. '[[Aliens|The Aliens]]',
	DestroyCouncil = IconModule.Icon({args={'destroy'}}) .. '[[Humanity First]]',
	ResistCouncil = IconModule.Icon({args={'resist'}}) .. '[[The Resistance]]',
	EscapeCouncil = IconModule.Icon({args={'escape'}}) .. '[[Project Exodus]]',
	ExploitCouncil = IconModule.Icon({args={'exploit'}}) .. '[[The Initiative]]',
	CooperateCouncil = IconModule.Icon({args={'cooperate'}}) .. '[[The Academy]]',
	AppeaseCouncil = IconModule.Icon({args={'appease'}}) .. '[[The Protectorate]]',
	SubmitCouncil = IconModule.Icon({args={'submit'}}) .. '[[The Servants]]',
	AlienCouncil = IconModule.Icon({args={'alien'}}) .. '[[Aliens|The Aliens]]',
}

local conditionSignTable = {
	LessThanOrEqualTo = '≤',
	GreaterThanOrEqualTo = '≥',
	LessThan = '<',
	GreaterThan = '>',
	NotEqualTo = '≠',
	EqualTo = '=',
	Has = 'Has',
	DoesNotHave = 'Does Not Have',
}

local conditionTypeTable = {
	TIGlobalCondition_tbCompletedTech = '[[Technology|Techs]] researched {sign} {techValue}',
	TIGlobalCondition_fSeaLevelAnomaly = '[[Climate_Change#Global_Sea_Level_Anomaly|Sea Level Anomaly]] {sign} {value}cm',
	TIGlobalCondition_fAtmosphericCO2_ppm =  '[[Climate_Change|Atmospheric CO2]] {sign} {value}ppm',
	TIGlobalCondition_fTemperatureAnomaly_C = '[[Climate_Change|Temperate Anomaly]] {sign} {value}°C',
	TIGlobalCondition_fTemperatureAnomaly_C_Abs = 'Absolute value of [[Climate_Change|Temperate Anomaly]] {sign} {value}°C',
	TIGlobalCondition_fStartTime_temperature = '([[Climate_Change|Temperate Anomaly]] at Campaign Start) {sign} {value}°C',
	TIGlobalCondition_fCampaignDuration_years = "Years since Campaign Start {sign} {value}",
	TIGlobalCondition_bWaveOfFearEligible = '(There are [[Aliens]] on, around, or approaching [[Earth]]) {sign} {value}',
	TIGlobalCondition_iLooseNukes = "Number of Loose Nukes in the World {sign} {value}",
	TIGlobalCondition_iSpacePopulation = "Total Space Population {sign} {value}",
	
	TIRegionCondition_bCoastal = '(Target [[Regions|Region]] has [[Regions#World_Ocean_Access|Ocean Access]] at least sometimes?) {sign} {value}',
	TIRegionCondition_bSeasonalCoast = '(Target [[Regions|Region]] has [[Regions#World_Ocean_Access|Ocean Access]] only sometimes?) {sign} {value}',
	TIRegionCondition_bOnTheWater = '(Target [[Regions|Region]] has [[Regions#World_Ocean_Access|Ocean Access]] right now?) {sign} {value}',
	TIRegionCondition_bIslandRegion = '(Target [[Regions|Region]] has no Adjacent [[Regions]] and Target [[Regions|Region]] has [[Regions#World_Ocean_Access|Ocean Access]] at least sometimes?) {sign} {value}',
	
	TIRegionCondition_bAlienNearby = '(Target [[Regions|Region]] or Adjacent contains [[Aliens#Alien_Agents|Alien Councilor(s)]]?) {sign} {value}',
	TIRegionCondition_bUndetectedAlienActivity = '(Target [[Regions|Region]] or Adjacent contains undetected [[Aliens#Alien_Activity_Investigation|Alien Activity]]?) {sign} {value}',
	TIRegionCondition_bBorderRegionWithEnemy = "(Target [[Regions|Region]] is Adjacent to [[Foreign_Relations#Wars|War Enemy's]] [[Regions|Region]]?) {sign} {value}",
	TIRegionCondition_bXenoformingVisibleToOwningFaction = "(Target [[Regions|Region's]] [[Aliens#Alien_Xenoforming|Xenoflora]] is visible to owning [[Factions|Faction]]?) {sign} {value}",

	TIRegionCondition_bCoreEconomic = "(Target [[Regions|Region]] is " .. IconModule.Icon({args={'core economic region'}}) .. "Core Economic?) {sign} {value}",
	TIRegionCondition_bCoreResource = "(Target [[Regions|Region]] is " .. IconModule.Icon({args={'mining region'}}) .. "Mining?) {sign} {value}",
	TIRegionCondition_bCapital = "(Target [[Regions|Region]] is " .. IconModule.Icon({args={'capital region'}}) .. "Capital?) {sign} {value}",
	TIRegionCondition_bColony = "(Target [[Regions|Region]] is " .. IconModule.Icon({args={'colony region'}}) .. "Colony?) {sign} {value}",
	TIRegionCondition_eRugged = "(Target [[Regions|Region]] is " .. IconModule.Icon({args={'rugged'}}) .. "Rugged?) {sign} {value}",
	TIRegionCondition_fLatitude = "Target [[Regions|Region's]] Latitude {sign} {value}",
	TIRegionCondition_fAbsLatitude = "Target [[Regions|Region's]] Latitude's Absolute Value {sign} {value}",
	TIRegionCondition_fLongitude = "Target [[Regions|Region's]] Longtitude {sign} {value}",
	TIRegionCondition_fXenoforming = "Target [[Regions|Region's]] [[Aliens#Alien_Xenoforming|Xenoflora Growth Levels]] {sign} {value}",
	TIRegionCondition_iAbductions = "Target [[Regions|Region's]] [[Aliens#Alien_Abductions|Abductions]] {sign} {value}",
	TIRegionCondition_iArmiesPresent = "Number of [[Terrestrial_Warfare#Armies|Armies]] in Target [[Regions|Region]] {sign} {value}",
	TIRegionCondition_iArmiesPresent_Enemy = "Number of [[Foreign_Relations#Wars|War Enemy's]] [[Terrestrial_Warfare#Armies|Armies]] in Target [[Regions|Region]] {sign} {value}",
	TIRegionCondition_iArmiesPresent_Friendly =  "Number of Non-[[Foreign_Relations#Wars|War Enemy's]] [[Terrestrial_Warfare#Armies|Armies]] in Target [[Regions|Region]] {sign} {value}",
	TIRegionCondition_iOccupations = "Number of Occupations in Target [[Regions|Region]] {sign} {value}",
	TIRegionCondition_bIsBeingOccupied = "(Target [[Regions|Region]] is being Occupied?) {sign} {value}",
	TIRegionCondition_eEnvironment = "Target [[Regions|Region's]] Environmental Status {sign} {value}",
	TIRegionCondition_fMonthlyBoost = "Target [[Regions|Region's]] Monthly " .. IconModule.Icon({args={'boost'}}) .. "[[Boost]] Production {sign} {value}",
	TIRegionCondition_fPerCapitaGDP = "Target [[Regions|Region's]] " .. IconModule.Icon({args={'gdppc', bgcolor="DarkSlateGray"}}) .. "[[GDPPC]] {sign} {value}",

	TIFactionCondition_bCouncilorHasTraitGrouping = "(Target [[Factions|Faction]] has a [[Councilor]] with a Group {idx} Trait?) {sign} {value}",
	TIFactionCondition_bCouncilorHasTraitOrPredecessor = "(Target [[Factions|Faction]] has a [[Councilor]] with {idx} Trait (or predecessor)?) {sign} {value}",
	TIFactionCondition_fSpaceCombatValueLEO = "Total " .. TVModule.TV({args={'combat value'}}) .. " of the Target [[Factions|Faction's]] [[Fleets]] in LEO {sign} {value}",
	TIFactionCondition_tfEffectCounter = "Target [[Factions|Faction]] has {idx} effects {sign} {value}",
	TIFactionCondition_tbHasEffect = "(Target [[Factions|Faction]] has {idx} effect?) {sign} {value}",
	TIFactionCondition_fTechBonusFromFleets = "Target [[Factions|Faction's]] {catIdx} bonus from [[Fleets]] {sign} {value%}",
	TIFactionCondition_iHabSupportFailureLevel = "(Number of [[Resources]] that Target [[Factions|Faction]] is bankrupt in, out of " .. TVModule.TV({args={'boost'}}) .. ", " .. TVModule.TV({args={'money'}}) .. ", and " .. TVModule.TV({args={'mc'}}) .. ") {sign} {value}",
	TIFactionCondition_efResourceValue = "Target [[Factions|Faction's]] {idx} {sign} {value}",
	TIFactionCondition_efResourceIncomeDaily = "Target [[Factions|Faction's]] daily {idx} income {sign} {value}",
	TIFactionCondition_bHasSpareMissionControl = "(Target [[Factions|Faction]] has unused " .. TVModule.TV({args={'mc'}}) .. " capacity?) {sign} {value}",
	TIFactionCondition_fAvailableMissionControl = "Target [[Factions|Faction's]] unused " .. TVModule.TV({args={'mc'}}) .. " capacity {sign} {value}",
	TIFactionCondition_fMissionControlBalance = "Target [[Factions|Faction's]] unused " .. TVModule.TV({args={'mc'}}) .. " capacity {sign} {value}",
	TIFactionCondition_bInfluenceCostFromNextControlPoint = "(Target [[Factions|Faction]] will exceed their " .. TVModule.TV({args={'cp'}}) .. " if they take a control point in Target Nation?) {sign} {value}",
	TIFactionCondition_tbCompletedCampaignObjective = "Target [[Factions|Faction's]] Complete Objectives {sign} {objectiveValue}",
	TIFactionCondition_tbCompletedMilestone = "Target [[Factions|Faction's]] Complete Milestones {sign} [[{value}]]",
	TIFactionCondition_tbCompletedProject = "Target [[Factions|Faction's]] Complete [[Technology|Projects]] {sign} {projectValue}",
	TIFactionCondition_bHumanFaction = "(Target [[Factions|Faction]] is Human?) {sign} {value}",
	TIFactionCondition_bAlienFaction = "(Target [[Factions|Faction]] is Alien?) {sign} {value}",
	TIFactionCondition_bAntiAlien = "(Target [[Factions|Faction]] is Anti-Alien?) {sign} {value}",
	TIFactionCondition_bProAlien = "(Target [[Factions|Faction]] is Pro-Alien?) {sign} {value}",
	TIFactionCondition_bExtremist = "(Target [[Factions|Faction]] is " .. ideoToFaction['Destroy'] .. ", " .. ideoToFaction['Submit'] .. ", or " .. ideoToFaction['Alien'] .. "?) {sign} {value}",
	TIFactionCondition_bBelievers =  "(Target [[Factions|Faction]] is " .. ideoToFaction['Escape'] .. ", " .. ideoToFaction['Cooperate'] .. ", or " .. ideoToFaction['Submit'] .. "?) {sign} {value}",
	TIFactionCondition_bCouncilorHasTrait = "(Target [[Factions|Faction]] has a councilor with {traitIdx} trait?) {sign} {value}",
	TIFactionCondition_eIdeology = "Target [[Factions|Faction]] {sign} {ideoValue}",
	TIFactionCondition_iAlienInvestigations = "Target [[Factions|Faction's]] number of [[Aliens#Alien_Activity_Investigation|Alien Activity Investigations]] {sign} {value}",
	TIFactionCondition_iAtrocities = "Target [[Factions|Faction's]] number of [[Factions#Atrocity|Atrocities]] {sign} {value}",
	TIFactionCondition_iHabs = "Target [[Factions|Faction's]] number of [[Habs]] {sign} {value}",
	TIFactionCondition_iMines = "Target [[Factions|Faction's]] number of [[Habs|Mines]] {sign} {value}",
	TIFactionCondition_iTotalStat = "Excluding " .. IconModule.MissionIcon({args={'Detain'}}) .. "[[Detain|Detained]] [[Councilors]], Target [[Factions|Faction's]] total [[{idx}]] [[Councilors#Attributes|Attribute]] {sign} {value}",
	TIFactionCondition_iAggregateStat = "(Excluding " .. IconModule.MissionIcon({args={'Detain'}}) .. "[[Detain|Detained]] [[Councilors]], Target [[Factions|Faction's]] total [[{idx}]] [[Councilors#Attributes|Attribute]] / 6) {sign} {value}",
	TIFactionCondition_iControlPointsByNationSize = "(Target [[Factions|Faction's]] number of [[Nations]] with at least {idx} [[Control Points]]) {sign} {value}",
	TIFactionCondition_HasControlPointofTypeForMapRegion = "Target [[Factions|Faction]] owns a [[Control Points]] of type {sign} {value} in the [[Nations|Nation]] that owns {mapIdx}.",
	TIFactionCondition_iSpaceDefenseFacilities = "(Target [[Factions|Faction]] has at least one [[Space Defenses]] in a [[Nations|Nation]] where it owns the executive and more than 50% of the [[Control Points]]?) {sign} {value}",
	TIFactionCondition_iAssassinatedHumans = "Number of Human [[Councilors]] " .. IconModule.MissionIcon({args={'assassinate'}}) .. "[[Assassinate|Assassinated]] by Target [[Factions|Faction]] {sign} {value}",
	TICouncilorCondition_iAssassinatedAliens= "Number of Alien [[Councilors]] " .. IconModule.MissionIcon({args={'assassinate'}}) .. "[[Assassinate|Assassinated]] by Target [[Factions|Faction]] {sign} {value}",
	
	
	TINationCondition_bExecFactionOwnsCPType = "(Target [[Nations|Nation]] has a [[Control Point]] of type {idx} that is owned by the same [[Factions|Faction]] as the executive?) {sign} {value}",
	TINationCondition_eHasControlPointOfType = "(Target [[Nations|Nation]] has a [[Control Point]] of type {idx}?) {sign} {value}",
	TINationCondition_efPriority = "Target [[Nations|Nation's]] {idx} priority % {sign} {value%}",
	TINationCondition_efMonthlyIPsToPriority = "(Target [[Nations|Nation's]] {idx} priority IP invested per month, including priority bonuses) {sign} {value}",
	TINationCondition_iControlPoints = "Target [[Nations|Nation's]] number of [[Control Points]] {sign} {value}",
	TINationCondition_iExecFactionUndefendedCPs = "(Target [[Nations|Nation's]] number of [[Control Points]] that are owned by the same [[Factions|Faction]] as the executive but are not " .. IconModule.MissionIcon({args={'Defend Interests'}}) .. "[[Defend Interests|defended]]) {sign} {value}",
	TINationCondition_iAllies = "Target [[Nations|Nation's]] number of [[Foreign_Relations#Allies|Allies]] {sign} {value}",
	TINationCondition_iRivals = "Target [[Nations|Nation's]] number of [[Foreign_Relations#Rivals|Rivals]] {sign} {value}",
	TINationCondition_iWars = "(Target [[Nations|Nation's]] number of [[Foreign_Relations#Wars|Wars]]) {sign} {value}",
	TINationCondition_iOffensiveWars = "(Target [[Nations|Nation's]] number of [[Foreign_Relations#Wars|Wars]] where they are the attacking side's war leader) {sign} {value}",
	TINationCondition_iArmies = "Target [[Nations|Nation's]] number of " .. TVModule.TV({args={'armies'}}) .. " {sign} {value}",
	TINationCondition_iNavies = "Target [[Nations|Nation's]] number of " .. TVModule.TV({args={'navies'}}) .. " {sign} {value}",
	TINationCondition_iNuclearWeapons = "Target [[Nations|Nation's]] number of " .. TVModule.TV({args={'nuke'}}) .. " {sign} {value}",
	TINationCondition_iNuclearWeaponsProtectingMe = "(Target [[Nations|Nation's]] and [[Foreign_Relations#Allies|Allies]] total number of " .. TVModule.TV({args={'nuke'}}) .. ", but allies don't contribute their last nuke and don't contribute if they have no " .. TVModule.TV({args={'armies'}}) .. ") {sign} {value}",
	
	TINationCondition_fCorruption = "Target [[Nations|Nation's]] [[Corruption]] {sign} {value%}",
	TINationCondition_fEducation = "Target [[Nations|Nation's]] " .. TVModule.TV({args={'education', '{sign} {value}'}}),
	TINationCondition_fMiltech = "Target [[Nations|Nation's]] " .. TVModule.TV({args={'miltech', '{sign} {value}'}}),
	TINationCondition_fMiltechMaxDifferential = "(Max " .. TVModule.TV({args={'miltech'}}) .. " - Target [[Nations|Nation's]] " .. TVModule.TV({args={'miltech'}}) .. ") {sign} {value}",
	TINationCondition_fCohesion = "Target [[Nations|Nation's]] " .. TVModule.TV({args={'cohesion', '{sign} {value}'}}),
	TINationCondition_fUnrest = "Target [[Nations|Nation's]] " .. TVModule.TV({args={'unrest', '{sign} {value}'}}),
	TINationCondition_fDemocracy = "Target [[Nations|Nation's]] " .. TVModule.TV({args={'democracy', '{sign} {value}'}}),
	TINationCondition_fInequality = "Target [[Nations|Nation's]] " .. TVModule.TV({args={'inequality', '{sign} {value}'}}),
	TINationCondition_fPerCapitaGDP = "Target [[Nations|Nation's]] " .. TVModule.TV({args={'gdppc', '{sign} {value}'}}),
	TINationCondition_fChangePerCapitaGDP = "(Target [[Nations|Nation's]] [[GDP]] change within the last 31 days) {sign} {value}",
	TINationCondition_fPerCapitaGDPFractionOfHighest = "(Target [[Nations|Nation's]] [[GDP]] / highest the GDP has ever been in the last {idx} quarters) {sign} {value%}",
	TINationCondition_fPercentChangePerCapitaGDP = "(Target [[Nations|Nation's]] [[GDP]] percent change within the last 31 days) {sign} {value%}",
	
	TINationCondition_bFactionControlled = "(Target [[Nations|Nation's]] executive is not empty?) {sign} {value}",
	TINationCondition_bFactionHasControl = "(Target [[Nations|Nation's]] executive is owned by {ideoIdx}?) {sign} {value}",
	TINationCondition_bRegionsCountChange =  "(Target [[Nations|Nation's]] number of [[Regions]] has changed in the last 31 days?) {sign} {value}",
	TINationCondition_bExtant = "(Target [[Nations|Nation]] has at least one [[Regions|Region]]?) {sign} {value}",
	TINationCondition_bHasMilitary = "(Target [[Nations|Nation]] has founded a military?) {sign} {value}",
	TINationCondition_bSpaceflightProgram = "(Target [[Nations|Nation]] has completed a spaceflight program?) {sign} {value}",
	TINationCondition_bAnySpaceAssets = "(Target [[Nations|Nation]] has at least one space facility?) {sign} {value}",
	TINationCondition_bHasAntiSpaceDefenses = "(Target [[Nations|Nation]] has at least one [[Space Defenses]]?) {sign} {value}",
	TINationCondition_bIsAlienNation = "(Target [[Nations|Nation]] is the [[Aliens#Alien_Administration|Alien Nation]]?) {sign} {value}",
	TINationCondition_bAggregateNation = "(Target [[Nations|Nation]] is an Aggregate Nation?) {sign} {value}",
	TINationCondition_bPolicyClosedBorders = "(Target [[Nations|Nation]] has closed borders?) {sign} {value} (Note: Closed borders not implemented, yet!)",
	TINationCondition_efPublicOpinion = "Target [[Nations|Nation's]] {ideoIdx} public support % {sign} {value%}",
	
	TIArmyCondition_fNationMiltechDifferential = "(Difference between Target " .. IconModule.Icon({args={'army'}}) .. "[[Terrestrial_Warfare#Armies|Army's]] Home [[Nations|Nation's]] " .. TVModule.TV({args={'miltech'}}) .. " and that of the [[Nations|Nation]] it is currently within) {sign} {value}",
	TIArmyCondition_fMiltech = "Target " .. IconModule.Icon({args={'army'}}) .. "[[Terrestrial_Warfare#Armies|Army's]] Home [[Nations|Nation's]] " .. TVModule.TV({args={'miltech', '{sign} {value}'}}),
	TIArmyCondition_bIsFighting = "(Target " .. IconModule.Icon({args={'army'}}) .. "[[Terrestrial_Warfare#Armies|Army]] is Fighting?) {sign} {value}",
	TIArmyCondition_bFactionControlled = "(Target " .. IconModule.Icon({args={'army'}}) .. "[[Terrestrial_Warfare#Armies|Army]] is controlled by a [[Factions|Faction]]?) {sign} {value}",
	TIArmyCondition_bIsAttacking = "(Target " .. IconModule.Icon({args={'army'}}) .. "[[Terrestrial_Warfare#Armies|Army]] is on the attack?) {sign} {value}",
	TIArmyCondition_ebArmyType = "(Target " .. IconModule.Icon({args={'army'}}) .. "[[Terrestrial_Warfare#Armies|Army]] is {idx}?) {sign} {value}",
	
	TIHabSiteCondition_bIcequakes = "(Target Hab Site can have Ice Quakes?) {sign} {value}", --TODO
	TIHabCondition_GenericTransferTimeFromEarth_d = "Target [[Habs|Hab]]'s transfer duration from Earth " .. TVModule.TV({args={'days', '{sign} {value}'}}),
	
	TIHabCondition_bHasSpecialRule = "(Target [[Habs|Hab]] has an active module with {idx} special rule?) {sign} {value}",
	TIHabCondition_bIsAlien = "(Target [[Habs|Hab]] is owned by " .. ideoToFaction['Alien'] .. "?) {sign} {value}",
	TIHabCondition_bUnderConstruction = "(Target [[Habs|Hab]] has no completed modules?) {sign} {value}",
	TIHabCondition_bIsMarsOREuropaOREnceladusBase = "(Target [[Habs|Hab]] is a ground " .. IconModule.Icon({args={'base'}}) .. "base on [[Mars]], [[Europa]], or [[Enceladus]]?) {sign} {value}",
	TIHabCondition_bIsBase = "(Target [[Habs|Hab]] is a ground " .. IconModule.Icon({args={'base'}}) .. "base?) {sign} {value}",
	TIHabCondition_bIsStation = "(Target [[Habs|Hab]] is a space " .. IconModule.Icon({args={'station'}}) .. "station?) {sign} {value}",
	TIHabCondition_bAllowsShipConstruction = "(Target [[Habs|Hab]] has a completed space dock or higher tier version?) {sign} {value}",
	TIHabCondition_bHasConstructionModule = "(Target [[Habs|Hab]] has a completed construction module or higher tier version?) {sign} {value}",
	TIHabCondition_bHasMine = "(Target [[Habs|Hab]] has a completed mine?) {sign} {value}",
	TIHabCondition_bFactionOnlyMine = "(Target [[Habs|Hab]] is the Target [[Factions|Faction's]] only [[Habs|Hab]] that has a completed mine?) {sign} {value}",
	TIHabCondition_tbHasModuleOrUpgradePrereqFunctioning = "(Target [[Habs|Hab]] has a completed {habIdx} module or lower tier version?) {sign} {value}",
	TIHabCondition_iCrewSize = "Target [[Habs|Hab]] has " .. TVModule.TV({args={'crew', "{sign} {value}"}}),
	TIHabCondition_iHabTier = "Tier of Target [[Habs|Hab]] {sign} {value}",
	TIHabCondition_iMineTier = "Tier of Target [[Habs|Hab's]] Mine {sign} {value}",
	TIHabCondition_iOkayModules = "(Number of modules on Target [[Habs|Hab]] that are not empty, destroyed, or decommissioning) {sign} {value}",
	TIHabCondition_iCompletedModules = "Number of completed modules on Target [[Habs|Hab]] {sign} {value}",
	TIHabCondition_fConstructionTimeModifier = "Target [[Habs|Hab's]] construction time modifier {sign} {value}",
	TIHabCondition_fAssaultCombatValue = TVModule.TV({args={'marine'}}) .. " of the Target [[Habs|Hab]] {sign} {value}",
	TIHabCondition_fAssaultCombatValueCombined = TVModule.TV({args={'marine'}}) .. " of the Target [[Habs|Hab]] plus any defending [[Fleets]] {sign} {value}",
	TIHabCondition_fSpaceCombatValue = TVModule.TV({args={'combat value'}}) .. " of the Target [[Habs|Hab]] {sign} {value}",
	TIHabCondition_fSpaceCombatValueFromDockedFleets = TVModule.TV({args={'combat value'}}) .. " of defending [[Fleets]] docked to the Target [[Habs|Hab]] {sign} {value}",
	TIHabCondition_fAggregateDefensiveScore = "Using the " .. TVModule.TV({args={'combat value'}}) .. " of the Target [[Habs|Hab]] and the " .. TVModule.TV({args={'combat value'}}) .. " of any docked defending [[Fleets]], is Max × (Sum / Max) ^ 0.25 {sign} {value}?", 
	TIHabCondition_fTechBonus = "Target [[Habs|Hab's]] {catIdx} bonus {sign} {value%}",
	TIHabCondition_bWarDogContainment = "(Target [[Habs|Hab's]] total " .. IconModule.Icon({args={'life'}}) .. IconModule.Icon({args={'materials'}}) .. IconModule.Icon({args={'military'}}) .. IconModule.Icon({args={'xenology'}}) .. " bonus > 10%?) {sign} {value}",
	TIHabCondition_efResourceIncomeAnnual = "Target [[Habs|Hab's]] annual {idx} income {sign} {value}",
	TIHabCondition_fPowerToSectorRatio = "(Target [[Habs|Hab's]] power generation / sectors) {sign} {value}",
	
	TIFleetCondition_bIsDocked = "(Target [[Fleets|Fleet]] is docked?) {sign} {value}",
	TIFleetCondition_bIsInTransfer = "(Target [[Fleets|Fleet]] is transfer?) {sign} {value}",
	
	TISpaceShipCondition_bNuclearArmed = "(Target [[Spaceships|Spaceship]] has [[Spaceships#Missiles|Nukes]]?) {sign} {value}",
	TISpaceShipCondition_tbHasUtilityModuleType = "(Target [[Spaceships|Spaceship]] has {utilIdx} module?) {sign} {value}",
	TISpaceShipCondition_tiNumberOfUtilityModulesType = "Number of {utilIdx} utility modules on Target [[Spaceships|Spaceship]] {sign} {value}",
	TISpaceShipCondition_bLaserBonusPower = "(Target [[Spaceships|Spaceship]] has bonus [[Spaceships#Lasers|Laser]] damage from [[Spaceships#Utility_Modules|utility modules]]?) {sign} {value}",
	TISpaceShipCondition_bIsAlien = "(Target [[Spaceships|Spaceship]] is owned by " .. IconModule.Icon({args={'alien'}}) .. "[[Aliens]]?) {sign} {value})",
	TISpaceShipCondition_iHullMaxOfficers = "Maximum number of [[Spaceships#Officer|Officers]] on Target [[Spaceships|Spaceship]] {sign} {value}",
	TISpaceShipCondition_bEligibleOfficerTemplates = "(Target [[Spaceships|Spaceship]] has room for a new [[Spaceships#Officer|Officer]]?) {sign} {value})",
	TISpaceShipCondition_fAssaultCombatValue = TVModule.TV({args={'marine'}}) .. " of Target [[Spaceships|Spaceship]] {sign} {value}",
	
	TIOfficerCondition_bAtMaxOfficerLevel = "(Target [[Spaceships#Officer|Officer]] is at max rank?) {sign} {value})",
	TIOfficerCondition_iRank = "Target [[Spaceships#Officer|Officer's]] rank {sign} {value})",
	TIOfficerCondition_bOnAShip = "(Target [[Spaceships#Officer|Officer]] is on a [[Spaceships|Spaceship]]?) {sign} {value})",
	TIOfficerCondition_ebShipLocation = "(Target [[Spaceships#Officer|Officer's]] [[Spaceships|Spaceship]] location is {idx}?) {sign} {value})",
	
	TISpaceBodyCondition_ebIsObjectType = "(Target [[Celestial_Bodies|Space Body]] is {idx}?) {sign} {value}",
	TINaturalSpaceObjectCondition_bTargetDataName = "(Target [[Celestial_Bodies|Space Body]] is {idx}?) {sign} {value}",
	TINaturalSpaceObjectCondition_fSemiMajorAxis_AU = "Target [[Celestial_Bodies|Space Body]] semi-major axis {sign} {value}AU",
	TIOrbitCondition_iDestroyedAssetsInOrbit = "Target Orbit's [[Celestial_Bodies#Orbital_Debris|Debris]] {sign} {value}",
	TIGlobalCondition_iDestroyedAssetsInLEO = "Total Low Earth Orbit's [[Celestial_Bodies#Orbital_Debris|Debris]] {sign} {value}",
	
	TICouncilorCondition_bIsAlien = "(Target [[Councilors|Councilor]] is " .. IconModule.Icon({args={'alien'}}) .. "[[Aliens|Alien]]?) {sign} {value})",
	TICouncilorCondition_bHomeNationIsAlienNation = "(Target [[Councilors|Councilor's]] Home [[Nations|Nation]] is the [[Aliens#Alien_Administration|Alien Nation]]?) {sign} {value})",
	TICouncilorCondition_bHasTraitGrouping = "(Target [[Councilors|Councilor]] has Group {idx} Trait?) {sign} {value})",
	TICouncilorCondition_bHasTraitWithTag = "(Target [[Councilors|Councilor]] has {idx} Trait?) {sign} {value})",
	TICouncilorCondition_bInAHab = "(Target [[Councilors|Councilor]] is in a [[Habs|Hab]]?) {sign} {value})",
	TICouncilorCondition_bDetained = "(Target [[Councilors|Councilor]] is " .. IconModule.MissionIcon({args={'Detain'}}) .. "[[Detain|Detained]]?) {sign} {value})",
	TICouncilorCondition_tbHasTrait = "Target [[Councilors|Councilor's]] Traits {sign} {traitIdx}",
	TICouncilorCondition_tbHasTraitOrPredecessor = "Target [[Councilors|Councilor's]] Traits {sign} {traitIdx} or lower tier version",
	TICouncilorCondition_efResourceIncomeMonthly = "Target [[Councilors|Councilor's]] monthly {idx} income {sign} {value}",
	TICouncilorCondition_fMonthsSinceRecruitDate = "(Target [[Councilors|Councilor's]] months since recruited) {sign} {value}",
	TICouncilorCondition_iStat = "Target [[Councilors|Councilor's]] [[{idx}]] [[Councilors#Attributes|Attribute]] {sign} {value}",
	TICouncilorCondition_iStatWithoutOrgs = "Target [[Councilors|Councilor's]] [[{idx}]] [[Councilors#Attributes|Attribute]] without [[Orgs]] {sign} {value}",
	TICouncilorCondition_iNumLoseableOrgs = "(Number of [[Orgs]] on Target [[Councilors|Councilor]] that can be sold to market) {sign} {value}",
	TICouncilorCondition_iSpareOrgCapacity =  "Target [[Councilors|Councilor's]] unused capacity for [[Orgs]] {sign} {value}",
	TICouncilorCondition_bInFactionOwnedNation = "(Target [[Councilors|Councilor]] is in a [[Nations|Nation]] whose executive is owned by the Target [[Factions|Faction]]?) {sign} {value})",
	
	
	TIGlobalCondition_bDummyCondition = "Dummy Condition, only on disabled events.",
}

local primaryTypeTable = {
	mapRegion = "Must be a [[Regions|Region]].",
	region = "Must be a [[Regions|Region]].",
	faction = "Must be a [[Factions|Faction]].",
	nation = "Must be a [[Nations|Nation]].",
	global = "Target is Global Game State.",
	priorActor = "Must be the Actor of the Prior Event.",
	priorTarget = "Must be the Primary Target of the Prior Event.",
	priorSecondary = "Must be the Secondary Target of the Prior Event.",
	army = "Must be an [[Terrestrial_Warfare#Armies|Army]].",
	hab = "Must be a [[Habs|Hab]].",
	habSite = "Must be a [[Habs|Hab]].",
	councilor = "Must be a [[Councilors|Councilor]].",
	ship = "Must be a [[Spaceships|Spaceship]].",
	officer = "Must be an [[Spaceships#Officers|Officer]].",
}

local secondaryTypeTable = {
	InputState = "Must be {InputState}.",
	
	PriorEvent_Actor = "Must be the Actor of the Prior Event.",
	PriorEvent_Target = "Must be the Primary Target of the Prior Event.",
	PriorEvent_SecondaryTarget = "Must be the Secondary Target of the Prior Event.",
	
	Faction_AlienAppeaser =  'Must be ' .. ideoToFaction['Appease'] .. '.',
	Faction_AlienProxy = 'Must be ' .. ideoToFaction['Submit'] .. '.',
	Faction_AlienFaction = 'Must be ' .. ideoToFaction['Alien'] .. '.',
	Faction_NonExecFaction = "Must be a Human [[Factions|Faction]] that does not own the executive of the Primary Target.",
	Faction_AnyHuman = "Must be a Human [[Factions|Faction]].",
	Faction_NMF_CloseIdeology = "Must be a Human [[Factions|Faction]] that is not the same as the Primary Target but whose ideological distance is less than 2 away.",
	Faction_MostPopularInNation = "Must be the [[Factions|Faction]] that is most [[Public Opinion|popular]] in the Primary Target.",
	
	Nation_AlienNation = "Must be the [[Aliens#Alien_Administration|Alien Nation]].",
	Nation_FederationMember = "Must be a [[Nations|Nation]] from the same [[Foreign_Relations#Federations|Federation]] as the Primary Target.",
	Nation_FederationLeader = "Must be the [[Nations|Nation]] that leads the [[Foreign_Relations#Federations|Federation]] that the Primary Target is in.",
	Nation_MyFaction = "Must be a [[Nations|Nation]] that is owned by the same [[Factions|Faction]] as the Primary Target.",
	Nation_Neighbor = "Must be a [[Nations|Nation]] that is a neighbor of the Primary Target.",
	
	Nation_NonAlly = "Must be a [[Nations|Nation]] that is not one of the Primary Target's [[Foreign_Relations#Allies|Allies]].",
	Nation_NormalRelations = "Must be a [[Nations|Nation]] that is not:"
		.. "\n** one of the Primary Target's [[Foreign_Relations#Allies|Allies]]."
		.. "\n** one of the Primary Target's [[Foreign_Relations#Rivals|Rivals]]."
		.. "\n** one of the Primary Target's [[Foreign_Relations#Wars|War Enemies]].",
	Nation_AllyOrRival = "Must be a [[Nations|Nation]] that is one of the following:"
		.. "\n** one of the Primary Target's [[Foreign_Relations#Allies|Allies]]."
		.. "\n** one of the Primary Target's [[Foreign_Relations#Rivals|Rivals]].",
	Nation_NonRival = "Must be a [[Nations|Nation]] that is not:"
		.. "\n** one of the Primary Target's [[Foreign_Relations#Rivals|Rivals]]."
		.. "\n** one of the Primary Target's [[Foreign_Relations#Wars|War Enemies]].",
	
	Nation_AllyOfCouncilorHomeNation = "Must be one of the Primary Target [[Councilors|Councilor's]] Home [[Nations|Nation's]] [[Foreign_Relations#Allies|Allies]].",
	Nation_Ally = "Must be one of the Primary Target's [[Foreign_Relations#Allies|Allies]].",
	Nation_LargerAlly = "Must be one of the Primary Target's [[Foreign_Relations#Allies|Allies]] that has:"
		.. "\n** More [[Control Points]].",
	Nation_Ally_HigherMiltech = "Must be one of the Primary Target's [[Foreign_Relations#Allies|Allies]] that has:"
		.. "\n** Higher " .. TVModule.TV({args={'miltech'}}) .. ".",
	
	Nation_Rival = "Must be one of the Primary Target's [[Foreign_Relations#Rivals|Rivals]].",
	Nation_Rival_Accessible = "Must be one of the Primary Target's [[Foreign_Relations#Rivals|Rivals]] that the Primary Target's " .. IconModule.Icon({args={'army'}}) .. "Armies could Access (for war purposes).",
	Nation_RivalOfCouncilorHomeNation = "Must be one of the Primary Target's Home [[Nations|Nation's]] [[Foreign_Relations#Rivals|Rivals]].",
	Nation_Rival_Neighbor = "Must be one of the Primary Target's [[Foreign_Relations#Rivals|Rivals]] that has:"
		.. "\n** A [[Regions|Region]] that is adjacent to the Primary Target.",
	Nation_Rival_Neighbor_NMF = "Must be one of the Primary Target's [[Foreign_Relations#Rivals|Rivals]] that has:"
		.. "\n** An executive that is not owned by the same [[Factions|Faction]]."
		.. "\n** A [[Regions|Region]] that is adjacent to the Primary Target.",
	Nation_Rival_NMF = "Must be one of the Primary Target's [[Foreign_Relations#Rivals|Rivals]] that has:"
		.. "\n** An executive that is not owned by the same [[Factions|Faction]].",
	Nation_SmallerRival_NMF = "Must be one of the Primary Target's [[Foreign_Relations#Rivals|Rivals]] that has:"
		.. "\n** Fewer [[Control Points]]."
		.. "\n** An executive that is not owned by the same [[Factions|Faction]].",
	Nation_EqualRival_NMF = "Must be one of the Primary Target's [[Foreign_Relations#Rivals|Rivals]] that has:"
		.. "\n** The same number of [[Control Points]]."
		.. "\n** An executive that is not owned by the same [[Factions|Faction]].",
	Nation_LargerRival_NMF = "Must be one of the Primary Target's [[Foreign_Relations#Rivals|Rivals]] that has:"
		.. "\n** More [[Control Points]]."
		.. "\n** An executive that is not owned by the same [[Factions|Faction]].",
		
	Nation_WarEnemy = "Must be one of the Primary Target's [[Foreign_Relations#Wars|War Enemies]].",
		
	Nation_OffensiveWarEnemy_AtrocityVictim = "Must be a [[Nations|Nation]] that the Primary Target is currently occupying or fighting in, where the Primary Target Nation is on the attacking side of the [[Foreign_Relations#Wars|War]]",
	
	Nation_OpenControlPoint = "Must be a [[Nations|Nation]] with an empty [[Control Point]].",
	
	Region_ArmyHome = "Must be the home [[Regions|Region]] of the Primary Target.",
	Region_CouncilorHomeRegion = "Must be the home [[Regions|Region]] of the Primary Target.",
	Region_Neighbor = "Must be a [[Regions|Region]] that is adjacent to the Primary Target.",
	Region_Neighbor_Rival = "Must be a [[Regions|Region]] that is adjacent to the Primary Target such that:"
		.. "\n** The [[Nations]] that own the two [[Regions]] are [[Foreign_Relations#Rivals|Rivals]] .",
	Region_Neighbor_WarEnemy = "Must be a [[Regions|Region]] that is adjacent to the Primary Target such that:"
		.. "\n** The [[Nations]] that own the two [[Regions]] are [[Foreign_Relations#Wars|War Enemies]].",
		
	Hab_AnyHuman = "Must be a Human [[Habs|Hab]].",
	Hab_NMF_CloseIdeology = "Must be a Human [[Habs|Hab]] such that the ideological distance between the Hab Owner and the Primary Target's [[Factions|Faction]] is less than 2.",
	Hab_CouncilorOnBoard = "Must be the [[Habs|Hab]] that the Primary Target is on.",
	
	Ship_MyFaction_AnotherFleet = "Must be a [[Spaceships|ship]] that is owned by the same [[Factions|Faction]] as the Primary Target but in a different [[Fleets|Fleet]].",
	
	SpaceBody_FleetInOrbit = "Must be the [[Celestial_Bodies|Space Body]] that the Primary Target is orbiting.",
	SpaceBody_HabSiteParent = "Must be the [[Celestial_Bodies|Space Body]] that the Primary Target is on.",
	
	Councilor_MyFaction = "Must be another [[Councilors|Councilor]] of the same faction as the Primary Target.",
	Councilor_MyFaction_OpposedWealth = "Must be another [[Councilors|Councilor]] of the same faction as the Primary Target such that:"
		.. "\n** The two [[Councilors]] have different Group 1 Traits.",
	Councilor_MyFaction_OpposedScience = "Must be another [[Councilors|Councilor]] of the same faction as the Primary Target such that:"
		.. "\n** The two [[Councilors]] have different Group 2 Traits.",
	Councilor_MyFaction_OpposedGovStatus = "Must be another [[Councilors|Councilor]] of the same faction as the Primary Target such that:"
		.. "\n** The two [[Councilors]] have different Group 4 Traits.",
	Councilor_MyFaction_OpposedPersonality = "Must be another [[Councilors|Councilor]] of the same faction as the Primary Target such that:"
		.. "\n** The two [[Councilors]] have different Group 5 Traits.",
	Councilor_MyFaction_OpposedLearner = "Must be another [[Councilors|Councilor]] of the same faction as the Primary Target such that:"
		.. "\n** The two [[Councilors]] have different Group 10 Traits.",
	Councilor_MyFaction_RivalHomeNation = "Must be another [[Councilors|Councilor]] of the same faction as the Primary Target such that:"
		.. "\n** The two [[Councilors]] have [[Foreign_Relations#Rivals|Rival]] home [[Nations]].",
	
	Councilor_SharedHomeRegion = "Must be a Human [[Councilors|Councilor]] with the same Home [[Regions|Region]] as the Primary Target.",
}
--endregion



--region Private member variables
--none
--endregion

--region Private methods

local function buildConditionString(condType, condIdx, condSign, condVal)
	condSign = conditionSignTable[condSign] or ('Error: Unknown condition sign: ' .. condSign)
	condType = conditionTypeTable[condType] or conditionTypeTable[mw.text.trim(condType)] or ('Error: Unknown condition type: ' .. condType)
	condType = sreplace(condType, '{sign}', condSign)
	condType = sreplace(condType, '{value}', condVal)
	condType = sreplace(condType, '{idx}', condIdx)
	condType = sreplace(condType, '{ideoValue}', ideoToFaction[condVal] or condVal)
	condType = sreplace(condType, '{ideoIdx}', ideoToFaction[condIdx] or condIdx)
	condType = sreplace(condType, '{traitValue}', TraitNames['TITraitTemplate.displayName.' .. condVal] or condVal)
	condType = sreplace(condType, '{utilIdx}', UtilityModuleNames['TIUtilityModuleTemplate.displayName.' .. condIdx] or condIdx)
	condType = sreplace(condType, '{traitIdx}', TraitNames['TITraitTemplate.displayName.' .. condIdx] or condIdx)
	condType = sreplace(condType, '{catIdx}', IconModule.Icon({args={ScienceCategories[condIdx] or condIdx}}) or condIdx)
	condType = sreplace(condType, '{habIdx}', HabModuleNames['TIHabModuleTemplate.displayName.' .. condIdx] or condIdx)
	condType = sreplace(condType, '{mapIdx}', (RegionNames['TIRegionTemplate.displayName.' .. (MapRegionToRegion[condIdx] or condIdx)] or 'Error: Region Not Found "' .. condIdx))
	condType = sreplace(condType, '{techValue}', '[[' .. condVal .. '|' .. (TechNames['TITechTemplate.displayName.' .. condVal] or condVal) .. ']]')
	condType = sreplace(condType, '{projectValue}', ProjectNameBuilder.buildName({args={condVal}}) or condVal)
	condType = sreplace(condType, '{objectiveValue}', '[[' .. condVal .. '|' .. (ObjectiveNames['TIObjectiveTemplate.displayName.' .. condVal] or condVal) .. ']]')
	condType = sreplace(condType, '{value%}', ((tonumber(condVal) or 0) * 100) .. '%')
	return condType
end

--endregion

--region Public methods

---@param frame a set of arguments that includes:
----frame.args a list of restrictions, only show events that satisfy all restrictions.
---@return wiki table of NarrativeEvents
function NarrativeEventLister.ListNarrativeEvents(frame)
	restrictionsTable = frame.args
	
	local returnString = '{| class="wikitable sortable mw-collapsible" style="text-align: center;"'
	returnString = returnString .. '\n|-'
	returnString = returnString .. '\n! Narrative Event'
	returnString = returnString .. '\n! Base Weight'
	returnString = returnString .. '\n! Requirements'
	returnString = returnString .. '\n! Potential Effects'
	returnString = returnString .. '\n|-'
	
	for rowID, row in pairs(NarrativeEventData) do
		if (not row['disable'] or row['disable'] ~= 'true') and RestrictionChecker.AllPass(restrictionsTable, row) then
			returnString = returnString .. '\n| ' .. (NarrativeEventNames['TINarrativeEventTemplate.displayName.' .. rowID] or 'Error: Missing Name for ' .. rowID)
			if row['forceEvent'] == 'true' then
				returnString = returnString .. '\n| Forced'
			else
				returnString = returnString .. '\n| ' .. row['baseWeight']
				if row['altBaseWeight/value'] and row['altBaseWeight/value'] ~= '' then
					returnString = returnString .. '<br>Alt: ' .. row['altBaseWeight/value']
				end
			end
			
			-- Requirements
			returnString = returnString .. '\n| '
			returnString = returnString .. '\n{| class="wikitable" style="text-align: left;"'
			returnString = returnString .. '\n|-'
			returnString = returnString .. "\n| '''General Requirements:'''"
			if row['repeatable'] == 'OncePerFaction' then
				returnString = returnString .. '\n* Triggers at most once for each [[Factions|Faction]].'
			elseif row['repeatable'] == 'OncePerCampaign' then
				returnString = returnString .. '\n* Triggers at most once.'
			end
			if row['global_cooldown_months'] and row['global_cooldown_months'] ~= '' and row['global_cooldown_months'] ~= '0' then
				returnString = returnString .. '\n* Triggers at most once every ' .. row['global_cooldown_months'] .. ' months.'
			end
			if row['target_cooldown_months'] and row['target_cooldown_months'] ~= '' and row['target_cooldown_months'] ~= '0' then
				returnString = returnString .. '\n* Triggers at most once every ' .. row['target_cooldown_months'] .. ' months for each target.'
			end
			if row['reqTechDataName'] and row['reqTechDataName'] ~= '' then
				returnString = returnString .. '\n* Needs [[' .. row['reqTechDataName'] .. '|' .. (TechNames['TITechTemplate.displayName.' .. row['reqTechDataName']] or row['reqTechDataName']) .. ']]'
			end
			if row['year'] and row['year'] ~= '' then
				returnString = returnString .. '\n* Cannot trigger before Year: ' .. row['year']
			end
			if row['endYear'] and row['endYear'] ~= '' then
				returnString = returnString .. '\n* Cannot trigger after Year: ' .. row['endYear']
			end
			if row['earliestMonth'] and row['earliestMonth'] ~= '' then
				returnString = returnString .. '\n* Cannot trigger before Month: ' .. row['earliestMonth']
			end
			if row['latestMonth'] and row['latestMonth'] ~= '' then
				returnString = returnString .. '\n* Cannot trigger after Month: ' .. row['latestMonth']
			end
			returnString = returnString .. '\n|-'
			
			if row['altBaseWeight/value'] and row['altBaseWeight/value'] ~= '' then
				returnString = returnString .. "\n| '''Alt Weight Requirements:'''"
				returnString = returnString .. '\n* ' .. buildConditionString(row['altBaseWeight/condition/$type'], row['altBaseWeight/condition/strIdx'], row['altBaseWeight/condition/sign'], row['altBaseWeight/condition/strValue'])
			end
			
			returnString = returnString .. '\n|-'
			local conditionString = '\n* ' .. (primaryTypeTable[row['targetType']] or ('Error: Unknown primary State Type: ' .. row['targetType']))
			for i = 0, 10 do
				local ncondition = row['targetConditions/'  .. i .. '/$type']
				if ncondition and ncondition ~= '' then
					conditionString = conditionString .. '\n* ' .. buildConditionString(ncondition, row['targetConditions/'  .. i .. '/strIdx'], row['targetConditions/'  .. i .. '/sign'], row['targetConditions/'  .. i .. '/strValue'])
				end
			end
			
			local possiblePrimaryTargets = {}
			for i = 0, 100 do
				local possibleTarget = row['possibleTargetDataNames/' .. i]
				if possibleTarget and possibleTarget ~= '' then
					if RegionNames['TIRegionTemplate.displayName.' .. (MapRegionToRegion[possibleTarget] or possibleTarget)] then
						-- If this is a region.
						possibleTarget = RegionNames['TIRegionTemplate.displayName.' .. (MapRegionToRegion[possibleTarget] or possibleTarget)]
					elseif NationNames['TINationTemplate.displayName.' .. possibleTarget] then
						-- If this is a nation.
						possibleTarget = '[[' .. possibleTarget .. '|' .. NationNames['TINationTemplate.displayName.' .. possibleTarget] .. ']]'
					elseif SpaceBodyNames['TISpaceBodyTemplate.displayName.' .. possibleTarget] then
						-- If this is a space body.
						possibleTarget = SpaceBodyNames['TISpaceBodyTemplate.displayName.' .. possibleTarget]
					else
						possibleTarget = 'ERROR: Unrecognized Target: ' .. possibleTarget
					end
					tinsert(possiblePrimaryTargets, possibleTarget)
				else
					break
				end
			end
			if possiblePrimaryTargets[1] then
				if row['targetType'] == 'hab' or row['targetType'] == 'habSite' then
					conditionString = conditionString .. '\n* Must be on or around one of the following [[Celestial_Bodies|Space Bodies]]: ' .. tconcat(possiblePrimaryTargets, " ● ") 
				else
					conditionString = conditionString .. '\n* Must be one of the following: ' .. tconcat(possiblePrimaryTargets, " ● ")
				end
			end
			
			returnString = returnString .. "\n| '''Primary Target Requirements:'''" .. conditionString
			returnString = returnString .. '\n|-'
			
			if row['secondaryStateType'] and row['secondaryStateType'] ~= '' then
				conditionString = '\n* ' .. (secondaryTypeTable[row['secondaryStateType']] or ('Error: Unknown secondary State Type: ' .. row['secondaryStateType']))
				-- TODO: At some point this should properly read and convert all entries. But right now this is barely used by the game anyway.
				local inputState = row['possibleSecondaryStateDataNames/0'] 
				inputState = ideoToFaction[inputState] or inputState
				conditionString = sreplace(conditionString, '{InputState}', inputState)
				
				for i = 0, 10 do
					local ncondition = row['secondaryStateConditions/'  .. i .. '/$type']
					if ncondition and ncondition ~= '' then
						conditionString = conditionString .. '\n* ' .. buildConditionString(ncondition, row['secondaryStateConditions/'  .. i .. '/strIdx'], row['secondaryStateConditions/'  .. i .. '/sign'], row['secondaryStateConditions/'  .. i .. '/strValue'])
					end
				end
				if conditionString ~= '' then
					returnString = returnString .. "\n| '''Secondary Target Requirements:'''" .. conditionString
					returnString = returnString .. '\n|-'
				end
			end
			returnString = returnString .. '\n|-'
			
			for i = 0, 4 do
				local ncondition = row['eventOptions/'  .. i .. '/actingFactionCondition/$type']
				local ncondition2 = row['eventOptions/'  .. i .. '/targetCondition/$type']
				if (ncondition and ncondition ~= '') or (ncondition2 and ncondition2 ~= '') then
					returnString = returnString .. "\n| '''Option " .. (i+1) .. " Requirements:'''"
				end
				if ncondition and ncondition ~= '' then
					returnString = returnString .. '\n* ' .. buildConditionString(ncondition, row['eventOptions/'  .. i .. '/actingFactionCondition/strIdx'], row['eventOptions/'  .. i .. '/actingFactionCondition/sign'], row['eventOptions/'  .. i .. '/actingFactionCondition/strValue'])
				end
				if ncondition2 and ncondition2 ~= '' then
					returnString = returnString .. '\n* ' .. buildConditionString(ncondition2, row['eventOptions/'  .. i .. '/targetCondition/strIdx'], row['eventOptions/'  .. i .. '/targetCondition/sign'], row['eventOptions/'  .. i .. '/targetCondition/strValue'])
				end
				returnString = returnString .. '\n|-'
			end
			
			returnString = returnString .. '\n|}' 
			
			
			-- Effects
			returnString = returnString .. '\n| '
			returnString = returnString .. '\n{| class="wikitable" style="text-align: left;"'
			returnString = returnString .. '\n|-'
			for option = 0, 3 do
				for outcome = 0, 4 do
					local effectString = ''
					for i = 0, 10 do
						local neffect = row['eventOptions/' .. option .. '/outcomes/' .. outcome .. '/effectTemplateNames/' .. i]
						if neffect and neffect ~= '' and neffect ~= 0 then
							local effectDescription = EffectDescriptionBuilder.buildDescription({args={neffect}})
							if effectDescription and effectDescription ~= '' and effectDescription ~= 'ERROR: No Description' then
								effectString = effectString .. '\n* ' .. effectDescription
							else
								effectString = effectString .. '\n* ' .. neffect
							end
						end
						-- I'm not sure what the difference is really...
						neffect = row['eventOptions/' .. option .. '/outcomes/' .. outcome .. '/delayedEffectTemplateNames/' .. i]
						if neffect and neffect ~= '' and neffect ~= 0 then
							local effectDescription = EffectDescriptionBuilder.buildDescription({args={neffect}})
							if effectDescription and effectDescription ~= '' and effectDescription ~= 'ERROR: No Description' then
								effectString = effectString .. '\n* ' .. effectDescription
							else
								effectString = effectString .. '\n* ' .. neffect
							end
						end
						-- Abusing the loop to also do event stuff
						neffect = row['eventOptions/' .. option .. '/outcomes/' .. outcome .. '/addNarrativeEvents/' .. i]
						if neffect and neffect ~= '' then
							effectString = effectString .. '\n* Adds Event: ' .. (NarrativeEventNames['TINarrativeEventTemplate.displayName.' .. neffect] or 'Error: Missing Name for ' .. neffect)
						end
						
						neffect = row['eventOptions/' .. option .. '/outcomes/' .. outcome .. '/removeNarrativeEvents/' .. i]
						if neffect and neffect ~= '' then
							effectString = effectString .. '\n* Removes Event: ' .. (NarrativeEventNames['TINarrativeEventTemplate.displayName.' .. neffect] or 'Error: Missing Name for ' .. neffect)
						end
					end
					
					local orgGranted = row['eventOptions/' .. option .. '/outcomes/' .. outcome .. '/orgGrantedTemplateName']
					if orgGranted and orgGranted ~= '' then
						orgGranted = (OrgNames['TIOrgTemplate.displayName.' .. orgGranted] or orgGranted)
						if ssub(orgGranted,1,6) == 'Random' then
							orgGranted = 'Random ' .. ssub(orgGranted,7)	
						end
						effectString = effectString .. '\n* Grants [[Orgs|org]]: ' .. orgGranted 
					end
					
					local resourceCost = ''
					resourceCost = row['eventOptions/' .. option .. '/outcomes/' .. outcome .. '/costBuilder/money']
					if resourceCost and resourceCost ~= '' and tonumber(resourceCost) then
						if tonumber(resourceCost) > 0 then
							effectString = effectString .. '\n* Costs ' .. TVModule.TV({args={'money', resourceCost, 'true'}})
						elseif tonumber(resourceCost) < 0 then
							effectString = effectString .. '\n* Gain ' .. TVModule.TV({args={'money', (-resourceCost), 'true'}})
						end
					end
					resourceCost = row['eventOptions/' .. option .. '/outcomes/' .. outcome .. '/costBuilder/influence']
					if resourceCost and resourceCost ~= '' and tonumber(resourceCost) then
						if tonumber(resourceCost) > 0 then
							effectString = effectString .. '\n* Costs ' .. TVModule.TV({args={'influence', resourceCost, 'true'}})
						elseif tonumber(resourceCost) < 0 then
							effectString = effectString .. '\n* Gain ' .. TVModule.TV({args={'influence', (-resourceCost), 'true'}})
						end
					end
					resourceCost = row['eventOptions/' .. option .. '/outcomes/' .. outcome .. '/costBuilder/operations']
					if resourceCost and resourceCost ~= '' and tonumber(resourceCost) then
						if tonumber(resourceCost) > 0 then
							effectString = effectString .. '\n* Costs ' .. TVModule.TV({args={'ops', resourceCost, 'true'}})
						elseif tonumber(resourceCost) < 0 then
							effectString = effectString .. '\n* Gain ' .. TVModule.TV({args={'ops', (-resourceCost), 'true'}})
						end
					end
					resourceCost = row['eventOptions/' .. option .. '/outcomes/' .. outcome .. '/costBuilder/boost']
					if resourceCost and resourceCost ~= '' and tonumber(resourceCost) then
						if tonumber(resourceCost) > 0 then
							effectString = effectString .. '\n* Costs ' .. TVModule.TV({args={'boost', resourceCost, 'true'}})
						elseif tonumber(resourceCost) < 0 then
							effectString = effectString .. '\n* Gain ' .. TVModule.TV({args={'boost', -resourceCost, 'true'}})
						end
					end
					resourceCost = row['eventOptions/' .. option .. '/outcomes/' .. outcome .. '/costBuilder/research']
					if resourceCost and resourceCost ~= '' and tonumber(resourceCost) then
						if tonumber(resourceCost) > 0 then
							effectString = effectString .. '\n* Costs ' .. TVModule.TV({args={'research', resourceCost, 'true'}})
						elseif tonumber(resourceCost) < 0 then
							effectString = effectString .. '\n* Gain ' .. TVModule.TV({args={'research', -resourceCost, 'true'}})
						end
					end
					resourceCost = row['eventOptions/' .. option .. '/outcomes/' .. outcome .. '/costBuilder/water']
					if resourceCost and resourceCost ~= '' and tonumber(resourceCost) then
						if tonumber(resourceCost) > 0 then
							effectString = effectString .. '\n* Costs ' .. TVModule.TV({args={'water', resourceCost, 'true'}})
						elseif tonumber(resourceCost) < 0 then
							effectString = effectString .. '\n* Gain ' .. TVModule.TV({args={'water', -resourceCost, 'true'}})
						end
					end
					resourceCost = row['eventOptions/' .. option .. '/outcomes/' .. outcome .. '/costBuilder/volatiles']
					if resourceCost and resourceCost ~= '' and tonumber(resourceCost) then
						if tonumber(resourceCost) > 0 then
							effectString = effectString .. '\n* Costs ' .. TVModule.TV({args={'volatiles', resourceCost, 'true'}})
						elseif tonumber(resourceCost) < 0 then
							effectString = effectString .. '\n* Gain ' .. TVModule.TV({args={'volatiles', -resourceCost, 'true'}})
						end
					end
					resourceCost = row['eventOptions/' .. option .. '/outcomes/' .. outcome .. '/costBuilder/metals']
					if resourceCost and resourceCost ~= '' and tonumber(resourceCost) then
						if tonumber(resourceCost) > 0 then
							effectString = effectString .. '\n* Costs ' .. TVModule.TV({args={'metals', resourceCost, 'true'}})
						elseif tonumber(resourceCost) < 0 then
							effectString = effectString .. '\n* Gain ' .. TVModule.TV({args={'metals', -resourceCost, 'true'}})
						end
					end
					resourceCost = row['eventOptions/' .. option .. '/outcomes/' .. outcome .. '/costBuilder/nobleMetals']
					if resourceCost and resourceCost ~= '' and tonumber(resourceCost) then
						if tonumber(resourceCost) > 0 then
							effectString = effectString .. '\n* Costs ' .. TVModule.TV({args={'nobles', resourceCost, 'true'}})
						elseif tonumber(resourceCost) < 0 then
							effectString = effectString .. '\n* Gain ' .. TVModule.TV({args={'nobles', -resourceCost, 'true'}})
						end
					end
					resourceCost = row['eventOptions/' .. option .. '/outcomes/' .. outcome .. '/costBuilder/fissiles']
					if resourceCost and resourceCost ~= '' and tonumber(resourceCost) then
						if tonumber(resourceCost) > 0 then
							effectString = effectString .. '\n* Costs ' .. TVModule.TV({args={'fissiles', resourceCost, 'true'}})
						elseif tonumber(resourceCost) < 0 then
							effectString = effectString .. '\n* Gain ' .. TVModule.TV({args={'fissiles', -resourceCost, 'true'}})
						end
					end
					resourceCost = row['eventOptions/' .. option .. '/outcomes/' .. outcome .. '/costBuilder/exotics']
					if resourceCost and resourceCost ~= '' and tonumber(resourceCost) then
						if tonumber(resourceCost) > 0 then
							effectString = effectString .. '\n* Costs ' .. TVModule.TV({args={'exotics', resourceCost, 'true'}})
						elseif tonumber(resourceCost) < 0 then
							effectString = effectString .. '\n* Gain ' .. TVModule.TV({args={'exotics', -resourceCost, 'true'}})
						end
					end
					resourceCost = row['eventOptions/' .. option .. '/outcomes/' .. outcome .. '/costBuilder/antimatter']
					if resourceCost and resourceCost ~= '' and tonumber(resourceCost) then
						if tonumber(resourceCost) > 0 then
							effectString = effectString .. '\n* Costs ' .. TVModule.TV({args={'antimatter', resourceCost, 'true'}})
						elseif tonumber(resourceCost) < 0 then
							effectString = effectString .. '\n* Gain ' .. TVModule.TV({args={'antimatter', -resourceCost, 'true'}})
						end
					end
					
					
					local costMultiplier = row['eventOptions/' .. option .. '/outcomes/' .. outcome .. '/costMultiplier']
					if costMultiplier and costMultiplier ~= '' then
						effectString = effectString .. '\n* All [[Resources|Resource]] costs and gains are multiplied by ' .. (costMultiplierStrings[costMultiplier] or costMultiplier)
					end
					
					
					
					if effectString ~= '' then
						returnString = returnString .. "\n| '''Option " .. (option+1) .. ", Outcome " .. (outcome+1) .. ":'''" .. effectString
						returnString = returnString .. '\n|-'
					end
				end
			end
			returnString = returnString .. '\n|-'
			returnString = returnString .. '\n|}' 
					
	    	returnString = returnString .. '\n|-'
    	end
	end
	returnString = returnString .. '\n|}'
	
	return returnString
end

--endregion

return NarrativeEventLister