352 lines
7.4 KiB
Python
352 lines
7.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
#!/usr/bin/env python
|
|
#
|
|
# Automatically converts VNDS to Ren'Py.
|
|
|
|
import os
|
|
import zipfile
|
|
from io import open
|
|
|
|
# Sets of variables found in the game.
|
|
global_variables = set()
|
|
game_variables = set()
|
|
|
|
def unjp(s):
|
|
print(s)
|
|
white = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890"
|
|
for a in s:
|
|
if a not in white:
|
|
s = s.replace(a, str(ord(a)))
|
|
if s[0].isdigit():
|
|
s = "var" + s
|
|
print(s)
|
|
return s
|
|
|
|
def scan_gsetvar(l):
|
|
l = l.split()[0]
|
|
l = unjp(l)
|
|
global_variables.add(l)
|
|
|
|
def scan_setvar(l):
|
|
if l[0] == "~":
|
|
return
|
|
|
|
l = l.split()[0]
|
|
l = unjp(l)
|
|
game_variables.add(l)
|
|
|
|
with zipfile.ZipFile("script.zip", 'r') as zip_ref:
|
|
zip_ref.extractall()
|
|
|
|
def scan_script(infn):
|
|
inf = open("script/" + infn, encoding="utf-8")
|
|
|
|
for l in inf:
|
|
l = l.replace("\xef\xbb\xbf", "")
|
|
l = l.strip()
|
|
|
|
if not l:
|
|
continue
|
|
|
|
if " " in l:
|
|
command, l = l.split(' ', 1)
|
|
else:
|
|
command = l
|
|
l = ""
|
|
|
|
if "scan_" + command in globals():
|
|
globals()["scan_" + command](l)
|
|
|
|
inf.close()
|
|
|
|
|
|
class ConvertState(object):
|
|
|
|
def __init__(self, outf, shortfn=""):
|
|
self.outf = outf
|
|
self.depth = 0
|
|
self.shortfn = shortfn
|
|
self.textbuffer = ""
|
|
self.empty_block = False
|
|
self.imindex = 0
|
|
|
|
def write(self, s, *args):
|
|
|
|
|
|
self.outf.write(" " * self.depth + "\n")
|
|
|
|
line = " " * self.depth + s % args + "\n"
|
|
|
|
if isinstance(line, str):
|
|
line = line.encode("utf-8")
|
|
|
|
self.outf.write(line.decode("utf-8"))
|
|
|
|
self.empty_block = False
|
|
|
|
def indent(self):
|
|
self.depth += 1
|
|
|
|
def outdent(self):
|
|
self.depth -= 1
|
|
|
|
def convert_endscript(cs, l):
|
|
cs.write("return")
|
|
|
|
def convert_label(cs, l):
|
|
l = l.replace("*", "_star_")
|
|
l = l.replace("-", "_")
|
|
l = cs.shortfn + "_" + l
|
|
|
|
cs.outdent()
|
|
cs.write("label %s:", l)
|
|
cs.indent()
|
|
|
|
def convert_goto(cs, l):
|
|
l = l.replace("*", "_star_")
|
|
l = cs.shortfn + "_" + l
|
|
l = l.replace("-", "_")
|
|
|
|
cs.write("jump %s", l)
|
|
|
|
def convert_choice(cs, l):
|
|
choices = l.split("|")
|
|
|
|
cs.write("menu:")
|
|
cs.indent()
|
|
|
|
for i, c in enumerate(choices):
|
|
cs.write("%r:", c)
|
|
cs.indent()
|
|
cs.write("$ selected = %d", i + 1)
|
|
cs.outdent()
|
|
|
|
cs.outdent()
|
|
|
|
def convert_setvar(cs, l):
|
|
if l[0] == "~":
|
|
return
|
|
|
|
print(f"l = {l}")
|
|
if l == 'chain = "main.scr start"':
|
|
var, op, val = "chain", "=", "main.scr start"
|
|
else:
|
|
var, op, val = l.split()
|
|
var = unjp(var)
|
|
|
|
if op == "=":
|
|
cs.write("$ %s = %s", var, val)
|
|
elif op == "+":
|
|
cs.write("$ %s += %s", var, val)
|
|
elif op == "-":
|
|
cs.write("$ %s -= %s", var, val)
|
|
else:
|
|
raise Exception("Unknown operation " + op)
|
|
|
|
def convert_gsetvar(cs, l):
|
|
if l[0] == "~":
|
|
return
|
|
|
|
var, op, val = l.split()
|
|
var = unjp(var)
|
|
|
|
if op == "=":
|
|
cs.write("$ persistent.%s = %s", var, val)
|
|
elif op == "+":
|
|
cs.write("$ persistent.%s += %s", var, val)
|
|
elif op == "-":
|
|
cs.write("$ persistent.%s -= %s", var, val)
|
|
else:
|
|
raise Exception("Unknown operation " + op)
|
|
|
|
def convert_if(cs, l):
|
|
var, rest = l.strip().split(' ', 1)
|
|
var = unjp(var)
|
|
|
|
if var in global_variables:
|
|
var = "persistent." + var
|
|
|
|
cs.write("if %s %s:", var, rest)
|
|
cs.indent()
|
|
|
|
cs.empty_block = True
|
|
|
|
def convert_fi(cs, l):
|
|
if cs.empty_block:
|
|
cs.write("pass")
|
|
|
|
cs.outdent()
|
|
|
|
def convert_sound(cs, l):
|
|
if l == "~":
|
|
cs.write("stop sound")
|
|
else:
|
|
l = "sound/" + l
|
|
cs.write("play sound \"%s\"", l)
|
|
|
|
def convert_setimg(cs, l):
|
|
fn, x, y = l.split()
|
|
x = int(x)
|
|
y = int(y)
|
|
fn = "foreground/" + fn
|
|
|
|
cs.write("show expression %r as i%d at fgpos(%d, %d)", fn, cs.imindex, x, y)
|
|
cs.imindex += 1
|
|
|
|
def convert_delay(cs, l):
|
|
try:
|
|
t = int(l) / 60.0
|
|
cs.write("pause %f", t)
|
|
except:
|
|
pass
|
|
|
|
|
|
|
|
def convert_bgload(cs, fn):
|
|
|
|
if " " in fn:
|
|
fn, delay = fn.split(" ", 1)
|
|
delay = int(delay) / 60.0
|
|
else:
|
|
delay = 0.5
|
|
|
|
assert " " not in fn
|
|
|
|
cs.write("nvl clear")
|
|
fn = "background/" + fn
|
|
cs.write("scene expression %r", fn)
|
|
cs.imindex = 0
|
|
|
|
if delay:
|
|
cs.write("with Dissolve(%f)", delay)
|
|
|
|
def convert_jump(cs, fn):
|
|
if " " in fn:
|
|
fn, l = fn.split(" ", 1)
|
|
l = l.replace("*", "_star_")
|
|
l = l.replace("-", "_")
|
|
fn = fn.replace(".scr", "").replace("-", "_")
|
|
cs.write("jump %s_%s", fn, l)
|
|
return
|
|
|
|
fn = fn.replace(".scr", "").replace("-", "_")
|
|
cs.write("jump %s", fn)
|
|
|
|
def convert_music(cs, fn):
|
|
if " " in fn:
|
|
fn, loops = fn.split(" ", 1)
|
|
else:
|
|
loops = 0
|
|
|
|
if int(loops) > 0:
|
|
noloop = " noloop"
|
|
else:
|
|
noloop = ""
|
|
|
|
if fn == "~":
|
|
cs.write("stop music")
|
|
else:
|
|
fn = "sound/" + fn
|
|
cs.write("play music %r%s", fn, noloop)
|
|
|
|
def convert_text(cs, text):
|
|
|
|
while text and (text[0] == "~" or text[0] == "!"):
|
|
text = text[1:]
|
|
|
|
if not text:
|
|
return
|
|
|
|
if text[0] == "@":
|
|
cs.textbuffer += text[1:] + "\n"
|
|
return
|
|
|
|
text = cs.textbuffer + text
|
|
text = text.replace("\\", "\\\\")
|
|
text = text.replace("\"", "\\\"")
|
|
text = text.replace("\n", "\\n")
|
|
|
|
cs.write('"%s"', text)
|
|
cs.textbuffer = ""
|
|
|
|
def convert_script(infn):
|
|
dir_rp = "rpy/"
|
|
if not os.path.exists(dir_rp):
|
|
os.mkdir(dir_rp)
|
|
|
|
if os.path.exists(dir_rp):
|
|
shortfn = infn.replace(".scr", "")
|
|
shortfn = shortfn.replace("-", "_")
|
|
inf = open("script/" + infn, encoding="utf-8")
|
|
outf = open (dir_rp + shortfn + ".rpy", "w", encoding = "utf-8")
|
|
cs = ConvertState(outf, shortfn)
|
|
cs.write("label %s:", shortfn)
|
|
cs.indent()
|
|
|
|
for l in inf:
|
|
l = l.replace("\xef\xbb\xbf", "")
|
|
l = l.strip()
|
|
|
|
if not l:
|
|
continue
|
|
|
|
if l[0] == "#":
|
|
continue
|
|
|
|
if " " in l:
|
|
command, l = l.split(' ', 1)
|
|
else:
|
|
command = l
|
|
l = ""
|
|
|
|
if "convert_" + command in globals():
|
|
globals()["convert_" + command](cs, l)
|
|
else:
|
|
print("Unknown command", repr(command), repr(l), repr(infn))
|
|
|
|
outf.close()
|
|
|
|
def main():
|
|
for i in os.listdir("script"):
|
|
if not i.endswith(".scr"):
|
|
continue
|
|
|
|
scan_script(i)
|
|
|
|
for i in os.listdir("script"):
|
|
if not i.endswith(".scr"):
|
|
continue
|
|
|
|
convert_script(i)
|
|
|
|
outf = open("rpy/_start.rpy", "w", encoding="utf-8")
|
|
cs = ConvertState(outf)
|
|
cs.write("init python:")
|
|
cs.indent()
|
|
|
|
for i in global_variables:
|
|
i = unjp(i)
|
|
cs.write("if persistent.%s is None:", i)
|
|
cs.indent()
|
|
cs.write("persistent.%s = 0", i)
|
|
cs.outdent()
|
|
|
|
# prevent non-empty block.
|
|
cs.write("pass")
|
|
|
|
cs.outdent()
|
|
cs.write("label start:")
|
|
cs.indent()
|
|
|
|
for i in game_variables:
|
|
i = unjp(i)
|
|
cs.write("$ %s = 0", i)
|
|
|
|
cs.write("window show")
|
|
cs.write("jump main")
|
|
|
|
cs.outdent()
|
|
outf.close()
|
|
|
|
if __name__ == "__main__":
|
|
main()
|