######################################################################################## # 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 https://grandsphere.fandom.com/wiki/Champion_Challenge # Priority: Story.json option to call label instead (story.rpy - SQ_) # 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") 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 value # Rarity affects directly primary stat. We should distribute 140 points def readjust_status(rar, job, hp=True): newv=50 # Imbalanced class if (job == Job_Swordsman): if hp: newv+=30+rar else: newv+=10+(rar/2) elif (job == Job_Mage): if hp: newv+=10+(rar/2) else: newv+=30+rar # Balanced class elif (job == Job_Assassin): if hp: newv+=15+(rar/2) else: newv+=25+rar elif (job == Job_Archer): if hp: newv+=25+rar else: newv+=15+(rar/2) # All-rounder class, with no steady growth elif (job == Job_Gunner): if hp: newv+=20+(rar/2) else: newv+=20+(rar/2) return newv