Module:Scenario

From Granblue Fantasy Wiki
Jump to navigation Jump to search

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

local p = {}
local getArgs = require('Module:Arguments').getArgs
local util = require('Module:Util')
local mCharacter = require('Module:Character')

function p.formatScenario(frame)
	local args = getArgs(frame, {
		trim = true,
		removeBlanks = true,
	})
	return p._formatScenario(args)
end

function p._formatScenario(args)
	local frame = mw.getCurrentFrame()
	
	-- Step flag will color each variant of required characters and outfits differently
	local var_prev_step_flag = 'prev_step_flag'
	local step_flag_output = ''
	local step_flag = args['step_flag']
	local step_flag_color = ''
	if step_flag ~= nil then
		local var_step_flag_text = 'scenario_'..step_flag..'_text'
		local var_step_flag_color = 'scenario_'..step_flag..'_color'
		local var_step_flag_color_index = 'scenario_step_flag_color_index'
		
		local step_flag_text = frame:callParserFunction{ name = '#var', args = { var_step_flag_text, ''}}
		if string.len(step_flag_text) == 0 then
			-- This is a new step flag, set it up
			local step_flag_color_index = frame:callParserFunction{ name = '#var', args = { var_step_flag_color_index, '0'}}
			step_flag_color_index = tonumber(step_flag_color_index) + 1
			step_flag_color = '#FBEEE6'
			if step_flag_color_index <= 10 then
				local color_table = {'#EAFAF1','#EBF5FB','#F4ECF7','#FBEEE6','#EBEDEF','#FDEDEC','#FAFAE9','#E5FFF9','#FFEBBA','#FFDDEF'}
				step_flag_color = color_table[step_flag_color_index]
			end
			step_flag_color = 'background-color:'..step_flag_color..';'
			
			local flags = util.string.split(step_flag, ';')
			local reqs = {}
			for _, flag in pairs(flags) do
				local req = util.string.split(flag, ',')
				local req_type = req[1]
				local req_id  = req[2]
					
				if req_type == 'mc' then
					if (req_id == 'f') or (req_id == 'female') then
						table.insert(reqs, 'Djeeta is the [[Main Character]]')
					elseif (req_id == 'm') or (req_id == 'male') then
						table.insert(reqs, 'Gran is the [[Main Character]]')
					else
						table.insert(reqs, string.format('%s is the [[Main Character]]', req_id))
					end
				elseif req_type == 'custom' then
					table.insert(reqs, req_id)
				else
					local link = mCharacter._getCharacterLinkById({ id = req_id })
					if link ~= '' then
						if req_type == 'lack' then
							table.insert(reqs, string.format('[[%s]] not in crew', link))
						elseif req_type == 'lackany' then
							table.insert(reqs, string.format('No version of [[%s]] in crew', link))
						elseif (req_type == 'have') or (req_type == 'possess') then
							table.insert(reqs, string.format('[[%s]] is a crew member', link))
						elseif req_type == 'haveany' then
							table.insert(reqs, string.format('Any version of [[%s]] is a crew member', link))
						end
					else
						link = mCharacter._getOutfitLinkById({ id = req_id, full = 'yes' })
						if (link ~= '') and (link ~= nil) then
							if req_type == 'lack' then
								table.insert(reqs, string.format('%s outfit not obtained', link))
							elseif (req_type == 'have') or (req_type == 'possess') then
								table.insert(reqs, string.format('%s outfit obtained', link))
							end
						else 
							table.insert(reqs, string.format('<span style="color: red;">Unable to find "%s"!</span>', req_id))
						end
					end
				end
			end
			
			step_flag_text = table.concat(reqs, ', ') .. ' '

			frame:callParserFunction{ name = '#vardefine', args = { var_step_flag_color_index, step_flag_color_index }}
			frame:callParserFunction{ name = '#vardefine', args = { var_step_flag_color, step_flag_color }}
			frame:callParserFunction{ name = '#vardefine', args = { var_step_flag_text, step_flag_text }}
		else
			step_flag_color = frame:callParserFunction{ name = '#var', args = { var_step_flag_color, ''}}
		end
		
		local prev_step_flag = frame:callParserFunction{ name = '#var', args = { var_prev_step_flag, ''}}
		if prev_step_flag ~= step_flag then
			step_flag_output = string.format('<div style="font-size: 0.85em; line-height: 1.3;">%s</div><hr />', step_flag_text)
		end
	end

	local result = {}
	local scenario_id = frame:callParserFunction{ name = '#var', args = { 'scenario_id', 'undefined' }}
	local id = args['id'] or ''
	-- Output a label for ahrefs
	table.insert(result, string.format('<div id="%s_%s"></div>', scenario_id, id))
	
	-- Return id for user select branches
	local var_scenario_return_id = scenario_id .. '_return_' .. id
	local scenario_return_id_text = frame:callParserFunction{ name = '#var', args = { var_scenario_return_id, '' }}
	table.insert(result, scenario_return_id_text)

	-- Do we have a "next" pointing at this id?
	local var_scenario_merge = 'scenario_merge_1'
	local scenario_merge = frame:callParserFunction{ name = '#var', args = { var_scenario_merge, '' }}
	local scenario_merges = util.string.split(scenario_merge, ',')
	if string.find(scenario_merge, ','..id..',', 1, true) ~= nil then
		if string.len(scenario_return_id_text) > 0 then
			table.insert(result, '<br />')
		end
		local i = p._findIndex(scenario_merges, id) - 1
		table.insert(result, string.format('<span style="padding-left:3em;font-weight:bold;">Continue %s</span>', i))
	end
	
	-- Flag differences based on MC gender, since those aren't called out in the journal
	local sex = args['sex']
	if sex ~= nil then
		-- Are we in the Scenario namespace? If so we want the gender check category.
		local title = mw.title.getCurrentTitle()
		if title.namespace == 5000 then -- Scenario namespace
			table.insert(result, '[[Category:Fate Gender Check]]')
		end
	end
	
	-- Output actual node text!
	local character_name1 = args['character1_name'] or 'null'
	if character_name1 ~= 'null' then
		table.insert(result, string.format(
			'<div style="width: 408px; padding: 10px 4px 10px 4px;%s">%s<strong>%s:</strong> %s</div>',
			step_flag_color,
			step_flag_output,
			character_name1,
			args['detail'] or ''
		))

		-- Are we in the Scenario namespace? If so we want character categories.
		local title = mw.title.getCurrentTitle()
		if title.namespace == 5000 then -- Scenario namespace
			table.insert(result, string.format('[[Category:Scenario Character: %s]]', character_name1))
		end
	elseif args['detail'] ~= nil then
		table.insert(result, string.format(
			'<div style="width: 408px; padding: 10px 4px 10px 4px;%s">%s<em>%s</em></div>',
			step_flag_color,
			step_flag_output,
			args['detail'] or ''
		))
	end

	local next = tonumber(args['next'] or -1)
	if (next >= 0) and (((tonumber(id) or -3) + 1) ~= next) then
		--mw.logObject(scenario_merges)
		local i = p._findIndex(scenario_merges, tostring(next)) or 0
		if i > 0 then
			-- already seen before
		else
			-- new merge point
			i = #scenario_merges
			if string.len(scenario_merge) == 0 then
				scenario_merge = ','
				i = 2
			end
			scenario_merge = scenario_merge .. next .. ','
			frame:callParserFunction{ name = '#vardefine', args = { var_scenario_merge, scenario_merge }}
		end
		
		table.insert(result, string.format(
			'<div style="width:408px; padding: 10px 4px 10px 4px;%s">%s<span style="padding-left:3em;">[[#%s_%d|Go to "Continue %d"]]</span></div><br />',
			step_flag_color,
			step_flag_output,
			scenario_id,
			next,
			i - 1
		))
	end

	if args['sel1_txt'] ~= nil then
		table.insert(result, '<ol>')
		for i=1, 10 do
			local sel_next = args['sel_next'..i]
			local sel_text = args['sel'..i..'_txt'] or ''
			if sel_next ~= nil then
				table.insert(result, string.format(
					'<li><b>[[#%s_%s|%s]]</b></li>',
					scenario_id,
					sel_next,
					args['sel'..i..'_txt'] or ''
				))
				-- define return point
				local sel_return = string.format(
					'<span style="padding-left:3em;">[[#%s_%s|<em><strong>Choose:</strong> %s</em>]]</span>',
					scenario_id,
					id,
					sel_text
				)
				local var_sel_return_next = scenario_id .. '_return_' .. sel_next
				local prev_sel_return = frame:callParserFunction{ name = '#var', args = { var_sel_return_next, '' }}
				if string.len(prev_sel_return) > 0 then
					prev_sel_return = prev_sel_return .. '<br />'
				end
				sel_return = prev_sel_return .. sel_return
				frame:callParserFunction{ name = '#vardefine', args = { var_sel_return_next, sel_return }}
			else
				break
			end
		end
		table.insert(result, '</ol><br />')
	end

	frame:callParserFunction{ name = '#vardefine', args = { var_prev_step_flag, step_flag or '' }}

	return table.concat(result, '')
end

function p._findIndex(tbl, val)
	local i = 1
	while tbl[i] do
		if tbl[i] == val then
			return i
		end
		i = i + 1
	end
	return nil
end

function p.testFormatScenario1()
	mw.logObject(p._formatScenario({ id = '1', step_flag = 'lack,3710082000;mc,f;have,3030135000', character1_name = 'Vira' }))
	mw.logObject(p._formatScenario({ id = '2', step_flag = 'mc,f', detail = 'heffaklump', next = '4'  }))
	mw.logObject(p._formatScenario({ id = '3', step_flag = 'mc,f', detail = 'heffaklump', sel1_txt = 'option 1', sel2_txt = 'option 2', sel_next1 = '5', sel_next2 = '6' }))
	mw.logObject(p._formatScenario({ id = '4', character1_name = 'Vira', detail = 'blork', next = '9' }))
	mw.logObject(p._formatScenario({ id = '5', character1_name = 'Vira', detail = 'heffaklump1', next = '11' }))
	mw.logObject(p._formatScenario({ id = '6', character1_name = 'Vira', detail = 'heffaklump2', next = '9'  }))
	mw.logObject(p._formatScenario({ id = '7', character1_name = 'Vira', detail = 'heffaklump3', next = '11'  }))
	mw.logObject(p._formatScenario({ id = '8', character1_name = 'Vira', detail = 'heffaklump4', next = '12'  }))
	mw.logObject(p._formatScenario({ id = '9', character1_name = 'Vira', detail = 'heffaklump5' }))
	mw.logObject(p._formatScenario({ id = '10', character1_name = 'Vira', detail = 'heffaklump6' }))
	mw.logObject(p._formatScenario({ id = '11', character1_name = 'Vira', detail = 'heffaklump7' }))
	mw.logObject(p._formatScenario({ id = '12', character1_name = 'Vira', detail = 'heffaklump8' }))
	mw.logObject(p._formatScenario({ id = '13', step_flag = 'lack,37100820000', character1_name = 'Vira', detail = 'heffaklump9'  }))
end

return p