1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
|
--[[
Copyright (c) 2014 Scott Furry
This file is part of Freedroid
Freedroid is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Freedroid is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Freedroid; see the file COPYING. If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
MA 02111-1307 USA
]]--
-- Lua module to parse FDRPG Character information into wiki page
local modWP_Quests = {}
-- modWPCommon reference
modWP_Quests.modcommon = {}
-- Variable will contained all parsed information after completion of ProcessNPCData()
modWP_Quests.AllQuestsData = {}
-- ReturnOfTux.droid file parsed line-by-line into table
modWP_Quests.QuestsFileData = {}
-- module references
modWP_Quests.modules = {}
-- names of required modules - "modWP_NPC" <-- also required for wiki
modWP_Quests.requiredModules = { moduleNames[6].id, }
-- table of FDRPG filepaths used for parsing ReturnOfTux.Droids information
modWP_Quests.files = {
quests=""
}
-- "struct" of quest information
modWP_Quests.questItem = {
name = "",
desc = "",
targetlevel = -1,
targetmarker = -1,
isDebug = false,
isTutorial = false,
code = {},
questAssign = {},
questActor = {},
content = {}, -- nulled after parsing
}
-- markers deliniating code in file data
modWP_Quests.codemarkstart = "Completion LuaCode={"
modWP_Quests.codemarkend = "}"
-- text for Event presentation/parsing - break up file data into sections
-- id) key, srchPatn) text/pattern to use to find data extrctPatn) how to extract found data
modWP_Quests.QuestSection = {
{ id = "missionStart", srchPatn = "Start of this mission target subsection", extrctPatn="[TEXT]" },
{ id = "missionEnd", srchPatn = "End of this mission target subsection", extrctPatn="[TEXT]" },
}
-- text for Event presentation/parsing - parsing each event section
-- id) key, srchPatn) text/pattern to use to find data extrctPatn) how to extract found data
modWP_Quests.Triggers = {
{ id = "name", srchPatn = "Mission Name=_(%b\"\")", extrctPatn="[MATCH]" },
{ id = "desc", srchPatn = "+++", extrctPatn="[EOL]" },
{ id = "targetlevel", srchPatn = "Mission target is to kill all hostile droids on this level%s*:%s*[%d]+", extrctPatn="[%d]+" },
{ id = "targetmarker", srchPatn = "Mission target is to kill droids with marker%s*:%s*[%d]+", extrctPatn="[%d]+" },
{ id = "codeStart", srchPatn = modWP_Quests.codemarkstart, extrctPatn="[TEXT]" },
{ id = "codeEnd", srchPatn = modWP_Quests.codemarkend, extrctPatn="[TEXT]" },
}
modWP_Quests.NPCQuestTables = { "quest_given", "quest_update", "quest_end" }
-- special sorting for "all data table"
-- [in] a|b elements in all data table
function modWP_Quests.SpecialAllDataSort(a,b)
if (((a.isDebug) and (not b.isDebug ))
or ((a.isDebug) and (b.isTutorial ))
or ((a.isTutorial) and (not b.isTutorial ) and (not a.isDebug) and (not b.isDebug))
) then
return false
elseif (((not a.isDebug) and (b.isDebug ))
or ((a.isTutorial) and (b.isDebug ))
or ((not a.isTutorial) and (b.isTutorial ) and (not a.isDebug) and (not b.isDebug))
) then
return true
else
return (a.name < b.name)
end
end
-- retrieve the anchortext associated with this id value
function modWP_Quests.GetItemUrlText( idvalue )
local retText = ""
if ( not idvalue ) then
return retText
end
local quest = select(1,modWP_Quests.modcommon.Extract.GetTableItem(modWP_Quests.AllQuestsData,"name", idvalue))
if ( quest ~= nil ) then
retText = modWP_Quests.modcommon.outputfilenames.quests .. quest.urlAnchor
end
return retText
end
-- Parse quests.dat - Find all Start/End Events copying information to ["contents"] table
function modWP_Quests.ParseFile()
local inQuest = false
local processed = false
local section = {}
-- pass # 1 - parse file
for key, line in pairs(modWP_Quests.QuestsFileData) do
for subkey, trigItem in pairs(modWP_Quests.QuestSection) do
local data = modWP_Quests.modcommon.Extract.SearchText( line, trigItem.srchPatn, trigItem.extrctPatn )
if ( data ) then
if ( trigItem.id == "missionEnd" ) then
inQuest = false
processed = true
modWP_Quests.AllQuestsData[#modWP_Quests.AllQuestsData + 1] = section
break
elseif ( trigItem.id == "missionStart" ) then
inQuest = true
processed = true
section = modWP_Quests.modcommon.Extract.TblDeepCopy(modWP_Quests.questItem)
break
end
end
end -- loop through Quest Section
if ( not processed and inQuest ) then
section.content[#section.content + 1] = line
end
processed = false
end -- loop through quest file data
end
-- Process each found quest event's contents for more details about the event
function modWP_Quests.ParseContents()
local modNPC = assert(require(modWP_Quests.requiredModules[1]))
local in_code = false
local key, section = next(modWP_Quests.AllQuestsData, nil)
repeat
for subkey, line in pairs(section.content) do
local dataItem = {}
if ( in_code ) then
dataItem = modWP_Quests.modcommon.Extract.SearchText( line, modWP_Quests.codemarkend, "[TEXT]" )
if ( dataItem == nil ) then
section.code[#section.code + 1] = line
else
in_code = false
break
end
else
for sub, trigItem in pairs(modWP_Quests.Triggers) do
dataItem = modWP_Quests.modcommon.Extract.SearchText( line, trigItem.srchPatn, trigItem.extrctPatn )
if ( dataItem == nil ) then goto PARSE_EVENT_NEXT_PATTERN end
-- search text found
if (( trigItem.id == "name" )
or ( trigItem.id == "targetlevel" )
or ( trigItem.id == "targetmarker" )) then
section[trigItem.id] = dataItem
break
elseif ( trigItem.id == "desc" ) then
section[trigItem.id] = section[trigItem.id] .. dataItem
break
elseif ( trigItem.id == "codeStart" ) then
local data = modWP_Quests.modcommon.Extract.SearchText( line, modWP_Quests.codemarkend, "[TEXT]" )
if ( data ~= nil ) then
in_code = false
section.code[#section.code + 1] = line:sub((modWP_Quests.codemarkstart:len() + 1), (#line - modWP_Quests.codemarkend:len()))
else
in_code = true
end
break
elseif ( trigItem.id == "codeEnd" ) then
in_code = false
break
end
::PARSE_EVENT_NEXT_PATTERN::
end -- determine event type
end -- copy code contents
end -- loop through each line of text in section
key, section = next(modWP_Quests.AllQuestsData, key)
until ( key == nil )
for key, quest in pairs(modWP_Quests.AllQuestsData, nil) do
local questnamelower = quest.name:lower()
quest.isDebug = ( ( questnamelower:find("debug") ~= nil )
or ( questnamelower:find("24_") ~= nil ))
quest.isTutorial = ( questnamelower:find("tutorial") ~= nil )
for subkey, npc in pairs(modNPC.AllNPCData) do
for index, questItem in pairs(modWP_Quests.NPCQuestTables) do
if (npc[questItem] == nil) then goto NPC_NEXT_QUEST_ITEM end
local foundquest = select(1,modWP_Quests.modcommon.Extract.GetTableItem(npc[questItem], nil, quest.name))
if ( foundquest == nil ) then goto NPC_NEXT_QUEST_ITEM
else
-- quest.name not found in table npc[questItem]
if ( questItem == modWP_Quests.NPCQuestTables[1]) then
modWP_Quests.modcommon.Process.InsertToNoKeyTable( quest.questAssign, npc.name )
elseif (( questItem == modWP_Quests.NPCQuestTables[2])
or ( questItem == modWP_Quests.NPCQuestTables[3])) then
local foundAssign = select(1,modWP_Quests.modcommon.Extract.GetTableItem(quest.questAssign, nil, npc.name))
if ( foundAssign ~= nil ) then goto NPC_NEXT_QUEST_ITEM end
modWP_Quests.modcommon.Process.InsertToNoKeyTable( quest.questActor, npc.name )
end
end
::NPC_NEXT_QUEST_ITEM::
end
end -- loop through each NPC to see if it acts in quest
-- and clean up tables
quest["content"] = nil
local elements = { "code", "questAssign", "questActor" }
for key, elem in pairs(elements) do
if ( #quest[elem] == 0 ) then
quest[elem] = nil
end
end
end -- post-process each quest
end
-- Read in FDRPG ReturnOfTux.droid data file
-- All droid information is saved into lua table.
function modWP_Quests.ProcessData()
modWP_Quests.modcommon = require("modWPCommon")
local modWIKI = modWP_Quests.modcommon.Wiki
-- test for presence of source data files
modWP_Quests.files.quests = tostring(modWP_Quests.modcommon.paths.srcData .. modWP_Quests.modcommon.datafiles["quests"])
modWP_Quests.modcommon.Test.Files(modWP_Quests.files)
-- read file and process into table objects
modWP_Quests.QuestsFileData = modWP_Quests.modcommon.Process.FileToLines(modWP_Quests.files["quests"])
modWP_Quests.ParseFile()
modWP_Quests.ParseContents()
if (#modWP_Quests.AllQuestsData > 0) then
table.sort(modWP_Quests.AllQuestsData,modWP_Quests.SpecialAllDataSort)
end -- sort AllQuestsData table
for key, quest in pairs(modWP_Quests.AllQuestsData) do
quest["urlAnchor"] = modWIKI.HLink .. modWIKI.WikifyLink("q" .. quest.name)
end -- loop through each npc
end
-- Write FDRPG npc information to file in a wiki format
-- Format is currently pmwiki-specific. Output file is ready
-- to be loaded directly into FDRPG site.
function modWP_Quests.WikiWrite()
local modWIKI = modWP_Quests.modcommon.Wiki
local modNPC = assert(require(modWP_Quests.requiredModules[1]))
local filename = modWP_Quests.modcommon.outputfilenames.quests .. ".html.md.eco"
local filepath = tostring(modWP_Quests.modcommon.paths.destRootFile .. filename)
local wikitext = {}
wikitext[#wikitext + 1] = "---"
wikitext[#wikitext + 1] = "layout: 'page'"
wikitext[#wikitext + 1] = "title: 'Quest Guide'"
wikitext[#wikitext + 1] = "comment: 'Description of the quests to fulfill to advance in the game.'"
wikitext[#wikitext + 1] = ""
wikitext[#wikitext + 1] = "quests:"
-- loop to produce individual entries
for key, quest in pairs(modWP_Quests.AllQuestsData) do
-- preprocess quest tables
if ( quest.questAssign ) then
local questdata = {}
for key, questperson in pairs(quest.questAssign) do
local namelink = modNPC.GetItemUrlText(questperson)
if ( namelink ) then
questdata[#questdata + 1] = modWIKI.LinkText(namelink, questperson)
end
end
quest.questAssign = questdata
end
if ( quest.questActor ) then
local questdata = {}
for key, questperson in pairs(quest.questActor) do
local namelink = modNPC.GetItemUrlText(questperson)
if ( namelink ) then
questdata[#questdata + 1] = modWIKI.LinkText(namelink,questperson)
end
end
quest.questActor = questdata
end
-- process presentation
modWIKI.StartMapping()
wikitext[#wikitext + 1] = modWIKI.AddAttr('id', modWIKI.WikifyLink("q" .. quest.name))
wikitext[#wikitext + 1] = modWIKI.AddAttr('name', quest.name)
wikitext[#wikitext + 1] = modWIKI.AddAttr('description', quest.desc)
if quest.questAssign then
wikitext[#wikitext + 1] = modWIKI.AddAttr('assigns_quest', quest.questAssign)
end
if quest.questActor then
wikitext[#wikitext + 1] = modWIKI.AddAttr('other_actors', quest.questActor)
end
modWIKI.EndMapping()
end
wikitext[#wikitext + 1] = "---"
wikitext[#wikitext + 1] = ""
wikitext[#wikitext + 1] = [[
# Quests Guide
<div class="row">
<div class="toc col-md-3 pull-right">
<span><b>Quests Name</b></span>
<ul>
<% for quest in @document.quests: %>
<li><a href="#<%- quest.id %>"><%- quest.name %></a></li>
<% end %>
</ul>
</div>
<div class="col-md-9">
<% for quest in @document.quests: %>
<h3 id='<%- quest.id %>'><%- quest.name %></h3>
<p> <strong>Description</strong>: <%- quest.description %></p>
<% if quest.assigns_quest: %>
<p> <strong>Assigns Quest</strong>:<br />
<% for value in quest.assigns_quest: %>
<%- value %><% if value != quest.assigns_quest[quest.assigns_quest.length- 1]: %>, <% end %>
<% end %>
</p>
<% end %>
<% if quest.other_actors: %>
<p> <strong>Other Quest Actors</strong>:<br />
<% for value in quest.other_actors: %>
<%- value %><% if value != quest.other_actors[quest.other_actors.length- 1]: %>, <% end %>
<% end %>
</p>
<% end %>
<% end %>
</div>
</div>
]]
-- write string to file
modWP_Quests.modcommon.Process.DataToFile(filepath, table.concat(wikitext, "\n"))
end
-- Print out NPC information based on selected verbosity.
function modWP_Quests.Verbosity()
if (( not modWP_Quests.modcommon.verbose) and ( not modWP_Quests.modcommon.doubleverbose)) then
return
end
io.stdout:write(modWP_Quests.modcommon.VerboseHeader)
io.stdout:write("modWP_Quests\n")
io.stdout:write("number of Quests: " .. #modWP_Quests.AllQuestsData .. "\n")
io.stdout:write(modWP_Quests.modcommon.VerboseHeader)
if (modWP_Quests.modcommon.doubleverbose) then
modWP_Quests.modcommon.Process.TblPrint(modWP_Quests.AllQuestsData, nil, nil, "All Quests Data")
end
end
return modWP_Quests
|