########################################################################################
# This file is part of Castle.
# Copyright (C) 2015 Jesusalva
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library 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
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
########################################################################################
# Miscellaneous functions from another game, also under LGPL
init python:
# Core processing to be on a while loop
def hit_verbose(someone, damage, counting, dmgfactor, fixfactor):
someone["hp"] -= dmgfactor
counting += dmgfactor
if counting+fixfactor == damage:
someone["hp"]-=(fixfactor)
counting+=fixfactor
# TODO: What if something went wrong?
renpy.pause(0.001)
return someone, damage, counting, dmgfactor, fixfactor
# Main hit verbose function
def hit_someone_verbose(someone, damage, fast=False):
counting = 0
# We can use dmgfactor
if ((damage > 10) or (damage < 10)) and (not persistent.SkipHPAnimation) and (not fast):
fixfactor=damage%10
dmgfactor=int(damage/10)
dbg_interactions=0
dbg_srchp=0+someone["hp"]
# Which loop to use?
if damage > 0:
while counting < damage:
someone, damage, counting, dmgfactor, fixfactor=hit_verbose(someone, damage, counting, dmgfactor, fixfactor)
someone["hp"]=int(someone["hp"])
dbg_interactions+=1
# Something went wrong
if dbg_interactions > 15:
raise Exception("WARNING 15 interactions or more happened without hit_verbose concluding.\n\nBy all means report this bug\nBUG ID: HSV FAILED on hpbar_handler with params unit_id, damage, counting, dmgfactor, fixfactor being %s,%d,%d,%d.\n\nClick \"Ignore\" to continue." % (someone["unit_id"], damage, counting, dmgfactor, fixfactor))
counting=damage
someone["hp"]=dbg_srchp-damage
# So, healing it is
else:
while counting > damage:
someone, damage, counting, dmgfactor, fixfactor=hit_verbose(someone, damage, counting, dmgfactor, fixfactor)
someone["hp"]=int(someone["hp"])
dbg_interactions+=1
# Something went wrong
if dbg_interactions > 15:
raise Exception("WARNING 15 interactions or more happened without hit_verbose concluding.\n\nBy all means report this bug\nBUG ID: HSV FAILED on hpbar_handler with params unit_id, damage, counting, dmgfactor, fixfactor being %s,%d,%d,%d.\n\nClick \"Ignore\" to continue." % (someone["unit_id"], damage, counting, dmgfactor, fixfactor))
counting=damage
someone["hp"]=dbg_srchp-damage
# We cannot use dmgfactor
else:
someone["hp"] -= damage
if (someone["hp"] > someone["max_hp"]):
someone["hp"]=int(someone["max_hp"]) # Apply some corrections. TODO possible alias?
renpy.block_rollback() # No rollback from there.
"""
https://github.com/websocket-client/websocket-client/issues/532
Due to #532 we had to disable SSL... again
threading.enumerate() → Find one which name is "MainThread"
Create a threading.Event in an overlay .set()
To send the RenpyQuit exception??
https://grandsphere.fandom.com/wiki/Champion_Challenge
# Priority: Story.json option to call label instead (story.rpy - SQ<id>_)
# Priority: Summon Button
# Priority: Move "system header" to overlay, and hide during fights
# Priority: Tavern Persiana
# And also: Calculate chance for units (adding czoom_25) on draws
# Don't forget to quote price etc.
# Priority: Tavern: We could determine if a tavern is on/off in tavern.py
# Specially if we make "high ranking knight taverns", we could even use
# them during events, returning "107: Selected tavern is not yet open"
# But how can the client know about this and when to display?
# Eval() is not really safe. We could use persiana for this, though.
# Priority: charge GP for upgrade
# Priority: Unit Selling
# Priority: Daily Quest (Fairies and Mana Eggs)
# Priority: Daily Login reward screen
# Priority: Token rewrite
# Priority: Skill system
# Priority: Card swapping (Move cards sideways)
# Priority: AP potions
# Notes
# renpy.invoke_in_thread(?)
# raise KeyboardException → renpy.reload_script() or renpy.quit(relaunch=True)
# if (renpy.android) use androidID, but we could get MAC at server?
# or (renpy.mobile)
# TODO
# Login with already valid token: Currently, it returns the data associated
# to the token, instead of executing login sequence.
# Tokens are still a safety concern, specially with multi-device.
# salted MD5 is not exactly safe. It does the trick, but isn't safe.
# Maybe we should salt this further with account ID?
# Future Improvement:
# Server Protocol Version (compatibility for legacy clients/servers ?)
# Or just check in the client packet?
#
# Result[token] and Battle[token]
# Result[token] contains operation history, loot, gp
# Send two packages: update_battle at final
# battle retrieves Result[token]
# Result loot in icons
# Weekly event switcher (Raids, etc. → events.py)
"""
label msgbox_label(msgcode):
call screen msgbox(msgcode)
return
label clear_all:
python:
rl=False
# Your version is no longer valid
if (HOST != persistent.host):
print("Host changed from %s to %s" % (str(HOST), persistent.host))
persistent.version=1
rl=True
# TODO: Clear cache
# Update host and delete password
HOST=persistent.host
PORT=persistent.port
renpy.notify("Deleting password: %s" % persistent.password)
persistent.password=None
if debug or config.developer:
"Spheres" "Techinical info:\n\nServer: [HOST]:[PORT]"
if rl:
"Spheres" "Server data purged, we will now relaunch the game."
$renpy.quit(relaunch=True)
else:
"Spheres" "You have logged out successfully."
$ renpy.full_restart()
# ???
jump start
label clear_cache:
python:
import os
# Your version is no longer valid
if persistent.host != "localhost":
persistent.version=1
# Find path to cached files
#if renpy.android:
root=get_path("")
#else:
# root=get_path("extra/")
# Remove cached files
for file in os.listdir(root):
if file.endswith('.png') or file.endswith('.mp3') or file.endswith('.jpg') or file.endswith('.webp') or file.endswith('.ogg'):
try:
os.remove(get_path(root+file))
stdout("[CC] Removing %s" % get_path(root+file))
except:
stdout("[CC] Removing %s... FAILED" % get_path(root+file))
os.remove(root+file)
stdout("[CC] Removing %s" % (root+file))
continue
# Erase file memory
persistent.allfiles=[]
allfiles=[]
"Spheres" "Cache deleted. Space was freed!"
$renpy.full_restart()
jump start
image spinner:
"gfx/spinner.png"
rotate 30.0
pause 0.05
"gfx/spinner.png"
rotate 60.0
pause 0.05
"gfx/spinner.png"
rotate 90.0
pause 0.05
"gfx/spinner.png"
rotate 120.0
pause 0.05
"gfx/spinner.png"
rotate 150.0
pause 0.05
"gfx/spinner.png"
rotate 180.0
pause 0.05
"gfx/spinner.png"
rotate 210.0
pause 0.05
"gfx/spinner.png"
rotate 240.0
pause 0.05
"gfx/spinner.png"
rotate 270.0
pause 0.05
"gfx/spinner.png"
rotate 300.0
pause 0.05
"gfx/spinner.png"
rotate 330.0
pause 0.05
"gfx/spinner.png"
#rotate 360.0
pause 0.05
repeat
########################################################################################
# This file is part of Spheres.
# Copyright (C) 2019 Jesusalva
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
# This library 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
# Lesser General Public License for more details.
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
########################################################################################
# Player data internals
init python:
def ap_restore():
# Request AP Data from websocket
raw=send_packet("apdata", fg=False)
apdata=json_decode(raw)
try:
Player["ap"]=apdata["ap"]
Player["max_ap"]=apdata["max_ap"]
Player["aptime"]=apdata["aptime"]
except:
stdout("Failed to restore AP!")
traceback.print_exc()
pass
return
def update_ap():
# TODO: This aptime update might be wrong =/ But it will be overriden soon
Player["aptime"] = now()
renpy.invoke_in_thread(ap_restore)
return
# Techinically a battle function, readjusts a status value
# Must be exactly the same as server side function!!
def readjust_status(lvl, val):
return val+int(val*(max(lvl-1, 0)/100.0))