summaryrefslogtreecommitdiff
path: root/misc
diff options
context:
space:
mode:
authorJesusaves <cpntb1@ymail.com>2020-05-15 04:55:56 -0300
committerJesusaves <cpntb1@ymail.com>2020-05-15 04:55:56 -0300
commitaa120b650afc2fa9ccabdbf32d79fcbea76d4996 (patch)
treeaa5c0c927b48a4d4e7d28ed8796825dac8f2eedd /misc
parent29a9f39efd9edad19cf44482a3dc2be7acd6046a (diff)
downloadtools-aa120b650afc2fa9ccabdbf32d79fcbea76d4996.tar.gz
tools-aa120b650afc2fa9ccabdbf32d79fcbea76d4996.tar.bz2
tools-aa120b650afc2fa9ccabdbf32d79fcbea76d4996.tar.xz
tools-aa120b650afc2fa9ccabdbf32d79fcbea76d4996.zip
Twine Mouboo Tool.
It converts simple twine stories into game code. Only plain text, one-line C comments and basic navigation are supported. (DO NOT use pipe navigation)
Diffstat (limited to 'misc')
-rwxr-xr-xmisc/twine.py167
1 files changed, 167 insertions, 0 deletions
diff --git a/misc/twine.py b/misc/twine.py
new file mode 100755
index 0000000..4949ec8
--- /dev/null
+++ b/misc/twine.py
@@ -0,0 +1,167 @@
+#!/usr/bin/python2
+
+import sys
+from HTMLParser import HTMLParser
+
+''' twine2rpy is for storyboarding/testing Ren'py scripts in Twine and converting
+the Twine source file to .rpy.
+
+This example was made for use with Twine 2, which exports directly to HTML.
+It only supports simple narrator speech and flow control: Variables, conditionals,
+images, and even markup are not supported.
+
+It should not be hard to extend this script (unless you're using HTML inside the
+dialog blocks). THIS FILE IS PROVIDED AS-IS, WITHOUT WARRANTIES OF ANY KIND,
+EXPRESS OR IMPLIED, EXCEPT WHERE OTHERWISE REQUIRED BY LAW.
+
+PS. This script version is not meant for production use.
+From the command line: twine2rpy_2.py source.txt '''
+
+
+#######################################################################
+# Open Twine source file
+
+# This function will (in an expensive manner) find the tuples we want
+# on HTML argument list.
+def dl_getkey(array, key):
+ for k in array:
+ if k[0] == key:
+ return k[1]
+
+# Receive arguments from commandline
+try:
+ file_name = sys.argv[1]
+except IndexError:
+ print("Usage: ./converter.py <twineproject.html>")
+ print("")
+ print("Made with Harlowe2 syntax. Use other syntaxes at your own risk!")
+ exit(0)
+
+# Receives a HTML file
+open_file = open(file_name)
+txt_file = open_file.read()
+txt_file = txt_file.replace("&quot;", "\"").replace("&#39;", "\'")
+
+# Prepare the Ren'Py file
+renpy_file = "t2_" + file_name[:file_name.find(".")].rstrip() + ".txt"
+rpy_file = open(renpy_file, "w")
+
+# Global dictionaries
+# TLT : Top Level Tag (what we're examining right now).
+TLT="html"
+LABELS={}
+INMENU=False
+PARSE=False
+BREAK=False
+
+# Parse data
+# The "data" is received as-is; As long that it doesn't uses HTML,
+# It should not break.
+def parse(basedata):
+ global TLT, LABELS, INMENU, BREAK
+ data=basedata.split("\n")
+
+ # Convert stuff
+ for d in data:
+ # regexes (or anything which would break this)
+ d=d.replace("\"", "\\\"")
+ d=d.strip()
+
+ # Exceptions: Do not add empty dialog boxes
+ if d == "":
+ if BREAK:
+ rpy_file.write(" next;\n")
+ #rpy_file.write(" mesn;\n")
+ BREAK=False
+ rpy_file.write("\n")
+ continue
+
+ # Handle comments
+ if (d.startswith("//")):
+ rpy_file.write(" %s\n" % d)
+ continue
+
+ # Here is an example of how simple menus could be handed:
+ if (d.startswith("[[") and not INMENU):
+ d=d.replace("[[", "").replace("]]", "")
+ INMENU=True
+ rpy_file.write(" menu\n")
+ target=LABELS[d]
+ rpy_file.write(" l(\"%s\"), L_%s" % (d, target))
+ elif (d.startswith("[[") and INMENU):
+ d=d.replace("[[", "").replace("]]", "")
+ target=LABELS[d]
+ rpy_file.write(",\n l(\"%s\"), L_%s" % (d, target))
+ elif INMENU:
+ INMENU=False
+ rpy_file.write(";\n")
+
+ else:
+ # Save it as a narrator speech block;
+ # It will ignore other markdown and comments, too, but thankfully,
+ # it is not very difficult to add regexes and replaces for them.
+ rpy_file.write(" mesq l(\"%s\");\n" % d)
+ BREAK=True
+
+
+# HTML Magic
+# create a subclass and override the default handler methods
+class MyHTMLParser(HTMLParser):
+ def handle_starttag(self, tag, attrs):
+ global TLT, LABELS, PARSE
+ # Set on TLT variable what tag we're in
+ # FIXME: You probably don't want to redefine TLT after
+ # it has been set to tw-passagedata; Instead, you'll want
+ # handle_endtag() to unset this. This is necessary if you plan
+ # in converting scripts with HTML code inside the passages.
+ TLT=tag
+
+ # A new passage! Lets get its name and pid.
+ if tag == "tw-passagedata":
+ labelname=dl_getkey(attrs, "name")
+ labelid=dl_getkey(attrs, "pid")
+ # Not writing file, lets register the label on the dict
+ if not PARSE:
+ LABELS[labelname]=labelid
+ print("Register label: %s" % labelname)
+ # If we're writing the file, then give it a safe label name
+ else:
+ rpy_file.write("L_%s:\n" % labelid)
+
+ def handle_endtag(self, tag):
+ global PARSE, INMENU
+ # Ops, seems like we finished the passage!
+ # To prevent implicit fallthroughs, lets call return
+ if tag == "tw-passagedata" and PARSE:
+ if not INMENU:
+ rpy_file.write(" close;\n\n")
+ else:
+ INMENU=False
+ rpy_file.write(";\n")
+ rpy_file.write(" close;\n\n")
+
+ def handle_data(self, data):
+ global TLT, PARSE
+ if (TLT in ["script", "style"] or not PARSE):
+ # Silently ignore Twine stuff
+ pass
+ else:
+ # We're writing and we're inside a passage, so call parse() on it
+ if (TLT == "tw-passagedata"):
+ parse(data)
+
+# Do a dry run.
+# This is needed to prepare LABELS dictionary
+parser = MyHTMLParser()
+parser.feed(txt_file)
+
+# Prepare the file
+PARSE=True
+parser.feed(txt_file)
+
+# Close files we opened
+open_file.close()
+rpy_file.close()
+
+# Report our success
+print("Success!")