# The script of the game goes in this file.
# Declare images
#image bg room = Frame("gfx/bg/port.png", 0, 0)
image dialog rebel = "gfx/dialog/rebel.png"
# Declare characters used by this game. The color argument colorizes the
# name of the character.
define e = Character("Player")
label splashscreen:
centered "{b}{color=#f00}Disclaimer{/color}\n\nBy running this software, you affirm that you have the right to do so.\nNo license is provided for using this demo software.\n\n\
\
\
{color=#f00}This client may contain assets which {u}does not{/u} belongs to it.\n\
If you are the legal owner of an asset, or their legal representant,\n\
And find an asset of yours illegally used, please, fill a DMCA complaint\n\
by sending an email to {a=mailto:dmca@tmw2.org}dmca@tmw2.org{/a}.{/color}\n\
\n\
\n\
No warranties.{/b}{fast}"
return
init python:
# FIXME: Drop dead if session_id mismatches (new "token")
# Same as ondata?
def onmsg(self, message):
global tr_load, tr_val, tr_busy
stdout("Server : " + message)
# Inform whatever is waiting for us that a reply was obtained
tr_load=True
tr_val=str(received)
# We do not clean tr_busy here
return
def ondata(self, msg, dtype, cont):
#print("data received")
"""
on_data: callback object which is called when a message received.
This is called before on_message or on_cont_message,
and then on_message or on_cont_message is called.
on_data has 4 argument.
The 1st argument is this class object.
The 2nd argument is utf-8 string which we get from the server.
The 3rd argument is data type. ABNF.OPCODE_TEXT or ABNF.OPCODE_BINARY will be came.
The 4th argument is continue flag. if 0, the data continue
"""
#renpy.notify(msg)
return
def onopen(self):
global tr_busy, tr_load, tr_val, HOST
print("Opening connection to %s" % HOST)
tr_load=True
tr_val=""
tr_busy=False
self.send("Ping")
def onerror(self, err):
stdout("ERROR RECEIVED")
stdout("More details: %s" % repr(err))
stdout("An error happened: %s" % str(err))
renpy.full_restart()
raise err
# Inform you are now ingame
label start:
# Begin the initial displays
# TODO: a fairy :(
scene black
show spinner at truecenter
# Initial configuration
python:
tr_busy=True
tr_val=""
tr_load=False
session_id=uuid.uuid4().hex
"We shall now begin testing a websocket"
python:
ws=persistent.ws
if (ws is not None):
stdout("Socket exists, trying to reuse connection...")
try:
boom = send_packet_now("ping")
if not boom:
del boom
raise
del boom
except:
ws = None
if ws is None:
stdout("Opening new socket...")
# server, sock, address
# on_open=None, on_message=None, on_error=None,
# on_close=None, on_ping=None, on_pong=None,
# on_data=None):
ws = wsock.WebSocketApp("wss://"+HOST+":61000",
on_data=ondata, on_error=onerror, on_open=onopen,
on_message=onmsg)
print repr(ws)
ws.on_open = onopen
renpy.invoke_in_thread(ws.run_forever, sslopt={"cert_reqs": ssl.CERT_NONE})
#ws.connect("wss://localhost:61000")
while not tr_load:
renpy.pause(0.02)
hide spinner
"Connection established!"
$ send_packet("Hello world")
"Message sent!"
return
# Run updater
python:
tr_load=False
renpy.invoke_in_thread(GAME_UPDATER)
while not tr_load:
renpy.pause(0.1)
tr_load=False
renpy.invoke_in_thread(GAME_LOADER)
while not tr_load:
renpy.pause(0.1)
# Open game
scene bg town with Dissolve(0.3)
pause 0.1
#show dialog rebel
$ password=persistent.password
$ email=""
# Check if we need to register
if persistent.password is None:
call screen welcome
return
# Otherwise just login
jump login
# Registration procedures
# You don't have an account yet
label register_email:
python:
import re
regex = '^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
email = ""
# Ask player for their email
while email == "":
email=renpy.call_screen("input_box", "Welcome to %s!\nPlease insert your email to register an account: \n{size=12}Your account password will be emailed to you. This is the only way to recover a lost account. You can use an {a=https://www.tempmailaddress.com/}Temporary email{/a} if you wish.{/size}" % (config.name))
if not re.search(regex, email):
email=""
renpy.call_screen("msgbox",
"The email you've entered is not valid.")
# You've inserted a valid email
raw=send_packet("register", """{"email": "%s"}""" % email)
bt=json_decode(raw)
try:
password=bt["password"]
valid=True
except:
# Either a SQL error, or a server error, or a connection error...
# But either way, we can't proceed!
renpy.call_screen("msgbox", "An error happened, maybe this email is already registered.\nPlease try again later.")
valid=False
# An error happened, return to login screen
if not valid:
jump start
# Save data
$ persistent.password=password
jump login
# Registration procedures
# You already have an account and want to recover it
label register_password:
python:
password=""
while password == "":
password=renpy.call_screen("input_box",
"Welcome to %s!\nPlease insert your password: " % (config.name))
if not password.isalnum():
renpy.call_screen("msgbox",
"The password you've entered is not valid.")
password=""
jump login
# Login procedures
label login:
$message=login()
# TODO=load message
$ stdout(message)
python:
try:
message=int(message)
import copy
dlcode=copy.copy(message)
except:
print "AN ERROR HAPPENED AT LOGIN TIME"
stdout("Invalid: "+str(message))
message=-1
if (message < 5000):
if (message == ERR_LOGIN_DEFAULT):
e "Error Code: [message]{fast}\n\nCould not estabilish connection to server."
jump login
else:
e "Error Code: [message]{fast}\n\nCannot login to server. Terminating."
return
# Successful login? Update client data and begin routines
$ persistent.password=password
$ dlcode-=5000
#$ ping_routine()
$ renpy.invoke_in_thread(irc_loop)
# We're now logged in, load misc data (TODO: What if ERR_ is returned?)
$ who = -1
$ inv=get_inventory()
python:
for a in inv:
Player["inv"].append(a)
# Run AP Timer if needed
if (Player["ap"] < Player["max_ap"]):
ApTimer=Timer(360.0, ap_restore)
ApTimer.start()
# Remove some temporary variables
$ del password
if (email):
$ del email
jump prologue
# Begin loop
play music MUSIC_TOWN fadein 0.5
# Show news (if they exist and you haven't logged in past day)
if dlcode:
if (len(allnews) >= 1):
call screen show_news
else:
$stdout("This server doesn't have a MOTD")
# TODO: Daily login rewards screen
label loop:
# Delete predictions, if possible
$ renpy.free_memory()
# Maybe we're in combat? If we are, you cannot go to town
if (Player["status"] >= ST_QUEST):
window hide None
$ renpy.call_screen("msgbox", "{b}Battle{/b}\n\nYou are in battle. You'll be brought back to combat.")
#window show None
$ Battle=reload_battle()
# TODO: Handle errors
if (Battle in [ERR_JSONDECODER]):
e "Unknown Error: [ERR_JSONDECODER]"
jump loop
play music MUSIC_BATTLE.id() fadein 0.5
jump combat
$ hud_show()
menu:
"Development Options" if config.developer:
$message="Development login OK"
menu:
"Send ping packet":
$message=send_packet("ping")
pass
"Redeclare Image":
$m=renpy.call_screen("input_box", "Image Name: ")
$renpy.image("redeclared", m)
"We'll now display Redeclared"
show redeclared at truecenter with dissolve
pause
"So?"
hide redeclared with None
pass
"Quest Editor":
jump quest_editors
"List party members":
$message=get_party(1)
"Update client":
jump updater_editors
"Do nothing":
pass
"World Map":
jump quest_select
"Manage Party":
jump party_lobby_enter
"Show inventory":
jump inventory
"Visit tavern":
jump tavern
"PUB":
# TODO this needs its own label
if persistent.nickname is not None:
python:
while True:
_return=renpy.call_screen("pub")
if _return != "":
res=irc_send(persistent.nickname, _return)
else:
break
else:
"ERROR" "You are not authorized to complete this operation.\n\nERR_NICK"
"Logout":
#$message=send_packet("logout")
jump quit
#"Server replies:" "[message]"
#return
if (message == OFFLINEMSG):
"Server replies:" "[message]\n\nYou are offline?"
return
if (message not in [ERR_OK, OKMSG, True]):
"Server replies:" "[message]"
jump loop
# This ends the game.
return
label restore:
# Restore town view
scene bg town
#show dialog rebel
play music MUSIC_TOWN fadein 0.5
$ hud_show()
jump loop
label prologue:
$ hud_story()
call SQ00001_prologue
# Automatically begin quest
$ Battle=loadquest(1)
$ update_ap(-1)
play music MUSIC_BATTLE.id() fadein 0.5
$ renpy.free_memory()
window hide
jump combat
#"Go to Capital, where you'll be formally appointed and receive a mission"
#"Graduating: You (tactician / whatever) - Auto-Presentation"
#"You decide it is better to travel to the Capital not alone."
#"Giulio, graduate as knight."
#"If you complete the mission at Capital, you'll get a job."
# --> Mission is derailed if favor of more epic adventure
#"Reaching Capital is a test on itself, to see if you have what it takes."
#"You can use Crystals to recruit mercenaries and colleagues."
# We may want to automatically begin fight 01, and keep important info
# on story.json (in case you close the app)
jump restore
label quit:
$ stdout("Received quit signal!")
python:
# Delete pinger
try:
Pinger.stop()
del Pinger
except:
pass
# Delete ApTimer
try:
ApTimer.cancel()
del ApTimer
except:
pass
# If needed, logout
try:
token=Player["token"]
send_packet("logout")
del Player
except:
pass
# If needed, close the socket
try:
ws.close()
except:
pass
# Delete variables
try:
del allunitsbase
del allunits
del header
del allnews
del allstory
del allworld
del alltaverns
except:
pass
# Terminate IRC connection
irc_kill()
# Data cleaned up
# Destroy the socket
$ persistent.ws = None
$ print("Sockets closed and data flushed!")
return