######################################################################################## # 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 displays init -10 python: import copy init python: import json from threading import Timer def inventoryplace(): global Player # Return next free slot index try: return Player["inv"].index(None) except: return len(Player["inv"]) def get_inventory(): raw=send_packet("get_inv", "") pt=json_decode(raw) if (pt == ERR_JSONDECODER): return ERR_JSONDECODER if (pt == FAILUREMSG): # TODO: msgbox you're offline, quit return ERR_LOGIN_DEFAULT print "get_inv(): "+str(pt) return pt # Function which list all unit id on party def party_dupcheck(pid): ar=[] for unt in Player["party_%s" % pid]: ar.append(unt["unit_id"]) return ar def get_party(pid, internal=False): raw=send_packet("get_party", str(pid)) pt=json_decode(raw) if (pt == ERR_JSONDECODER): return ERR_JSONDECODER Player["party_%d" % pid]=pt if (internal): return False allmem="" for member in pt: # Skip'invalid members if member["unit_id"] <= 0: continue # TODO: show image rfc=Player["inv"][member["inv_id"]] allmem+="%d★ %s (Lv %d, %d exp)\n" % (allunits[member["unit_id"]]["rare"], allunits[member["unit_id"]]["name"], rfc["level"], rfc["exp"]) #Player["party_1"].append(member) renpy.call_screen("msgbox", "Party %d\n %s" % (pid, allmem)) return True def ap_restore(): global ApTimer, Player Player["ap"]+=1 if (Player["ap"] < Player["max_ap"]): try: ApTimer.cancel() except: pass ApTimer=Timer(360.0, ap_restore) ApTimer.daemon=True ApTimer.start() return def update_ap(newval): global ApTimer, Player running=False if (Player["ap"] < Player["max_ap"]): running=True # Update AP # TODO: Do we allow over-the-cap AP? Player["ap"]+=newval # Handle the timer if (not running and Player["ap"] < Player["max_ap"]): ApTimer=Timer(360.0, ap_restore) ApTimer.daemon=True ApTimer.start() if (running and Player["ap"] >= Player["max_ap"]): ApTimer.cancel() return def set_party(pid, members): raw=send_packet("set_party", """{"party_id": %d, "formation": %s}""" % (pid, str(members))) pt=json_decode(raw) if (pt == ERR_JSONDECODER): return ERR_JSONDECODER return True # Ping function, it keeps the connection alive. def ping_routine(): global Pinger, OFFLINEMSG pinged=send_packet_now("ping", legacy=True) # Something went wrong if pinged != "pong": stdout("ERROR, Unexpected reply: %s (expected: pong)" % pinged) # Connection is already dead; Why bothering if pinged == OFFLINEMSG: return # TODO: Terminate connection on our end? timetowait=60.0 else: timetowait=300.0 Pinger=Timer(float(timetowait), ping_routine) Pinger.daemon=True Pinger.start() 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 def party_update(pid, pix): newindex=renpy.call_screen("inventory", True) # We only need inventory id's # So make a Party variable with this Party=dlist() for une in Player["party_%d" % pid]: Party.append(une["inv_id"]) if debug: print str(Party) # Add unit, but only if no duplicates are found # Exception: If it is -1, then we can add if newindex != -1: dupcheck=party_dupcheck(pid) dupid=Player["inv"][newindex]["unit_id"] if dupid in dupcheck: renpy.notify(_("You cannot add duplicate party members!")) else: Party[pix]=newindex else: Party[pix]=newindex if debug: print str(Party) # Set party set_party(pid, Party) return True def evocheck(level, unit): # Does an evolved form exist? print "evocheck lv %d" % level try: nu=unit["unit_id"]+1 #print "nu is: %d" % int(nu) next_name=allunits[nu]["name"] #print "next name: %s" % next_name except: return False # Level requeriment return level == unit["max_level"] screen inventory(blank=False, filters="True"): # window # hbox vpgrid: cols 4 spacing 5 draggable True mousewheel True scrollbars "vertical" side_xalign 0.5 xoffset 15 #yoffset 45 #xfill True yfill True # The close button returns -1 and comes first imagebutton: if not blank: idle At("gfx/square/back_idle.png", czoom_70) hover At("gfx/square/back_hover.png", czoom_70) else: idle At("gfx/square/bg.png", czoom_70) action Return(-1) for i, item in enumerate(Player["inv"]): # We don't care for None items if item is not None: # Needed because eval :rolling_eyes: #$ ir=copy.copy(item["rare"]) #$ print str(locals()) python: evl=False #print "---- repr" try: alu=allunits[item["unit_id"]] except: alu={} stdout("ERROR, alu: not defined, index %d" % i) evl=eval(filters, globals(), locals()) #print str(evl) #print str(filters) #print str(item) #print str(alu) if evl: imagebutton: idle At(Composite( (340, 340), (0, 0), "gfx/square/bg.png", (0, 0), "gfx/square/units/%d.png" % item["unit_id"], (0, 0), "gfx/square/%d.png" % allunits[item["unit_id"]]["rare"], ), czoom_70) action Return(i) #alternate "Show the char data chart" screen party_main(): default party = 1 vbox: xalign 0.5 yalign 0.3 label _("{size=32}{color=#fff}Party %d{/color}{/size}" % (party)) null height 20 hbox: for i, item in enumerate(Player["party_%d" % party]): imagebutton: if item["unit_id"] > 0: idle At(Composite( (340, 340), (0, 0), "gfx/square/bg.png", (0, 0), "gfx/square/units/%d.png" % item["unit_id"], (0, 0), "gfx/square/%d.png" % allunits[item["unit_id"]]["rare"], ), czoom_70) else: idle At("gfx/square/bg.png", czoom_70) action Return([party, i]) null height 80 # The close button returns -1 and comes last (TODO) imagebutton: idle At("gfx/square/back_idle.png", czoom_75) hover At("gfx/square/back_hover.png", czoom_75) action Return(-1) screen upgrade_char(): vbox: xalign 0.5 yalign 0.3 # The unit hbox: add At(Composite( (340, 340), (0, 0), "gfx/square/bg.png", (0, 0), "gfx/square/units/%d.png" % unit["unit_id"], (0, 0), "gfx/square/%d.png" % unit["rare"], ), czoom_70) null width 10 label _("{size=32}{color=#fff}%s{/color}{/size}" % (unit["name"])) null height 20 $i=0 hbox: for ignored in enumerate(material): if i < 4: imagebutton: if material[i] >= 0: idle At(Composite( (340, 340), (0, 0), "gfx/square/bg.png", (0, 0), "gfx/square/units/%d.png" % Player["inv"][material[i]]["unit_id"], (0, 0), "gfx/square/%d.png" % allunits[Player["inv"][material[i]]["unit_id"]]["rare"], ), czoom_70) else: idle At("gfx/square/bg.png", czoom_70) action Return(i) $i+=1 null height 20 hbox: for ignored in enumerate(material): if i < 8: imagebutton: if material[i] >= 0: idle At(Composite( (340, 340), (0, 0), "gfx/square/bg.png", (0, 0), "gfx/square/units/%d.png" % Player["inv"][material[i]]["unit_id"], (0, 0), "gfx/square/%d.png" % allunits[Player["inv"][material[i]]["unit_id"]]["rare"], ), czoom_70) else: idle At("gfx/square/bg.png", czoom_70) action Return(i) $i+=1 null height 80 # The close button returns -1 and comes last (TODO) hbox: textbutton _("Merge") action Return(-2) null width 80 textbutton _("Leave") action Return(-1) screen evolve_char(): vbox: xalign 0.5 yalign 0.3 # The unit hbox: add At(Composite( (340, 340), (0, 0), "gfx/square/bg.png", (0, 0), "gfx/square/units/%d.png" % unit["unit_id"], (0, 0), "gfx/square/%d.png" % unit["rare"], ), czoom_70) null width 10 add At("gfx/evol.png", czoom_70) null width 10 add At(Composite( (340, 340), (0, 0), "gfx/square/bg.png", (0, 0), "gfx/square/units/%d.png" % next["unit_id"], (0, 0), "gfx/square/%d.png" % next["rare"], ), czoom_70) #label _("{size=32}{color=#fff}%s\n↓\n%s{/color}{/size}" % (unit["name"], next["name"])) null height 120 $i=0 hbox: xalign 0.5 spacing 150 for ignored in enumerate(material): if i < 2: imagebutton: if material[i] >= 0: idle At(Composite( (340, 340), (0, 0), "gfx/square/bg.png", (0, 0), "gfx/square/units/%d.png" % Player["inv"][material[i]]["unit_id"], (0, 0), "gfx/square/%d.png" % allunits[Player["inv"][material[i]]["unit_id"]]["rare"], ), czoom_70) else: idle At("gfx/square/bg.png", czoom_70) action Return(i) $i+=1 null height 80 # The close button returns -1 and comes last (TODO) hbox: xalign 0.5 spacing 80 textbutton _("Evolve") action [SensitiveIf(material[0]>=0 and material[1]>=0), Return(-2)] textbutton _("Cancel") action Return(-1) screen char_details(un, hpval, akval, idx): style_prefix "confirm" frame: at msgbox_emp vbox: xalign 0.5 yalign 0.5 spacing 30 label _("{b}%s{/b}\n%s\n\nHP: %d\nATK: %d\nLv %d/%d\nEXP: %d") % ( star_write(un["rare"]), un["name"], hpval, akval, Player["inv"][idx]["level"], un["max_level"], Player["inv"][idx]["exp"]): style "confirm_prompt" xalign 0.5 hbox: xalign 0.5 spacing 100 textbutton _("Merge") action [SensitiveIf(Player["inv"][idx]["level"] < un["max_level"]), Return(-1)] textbutton _("Evolve") action [SensitiveIf(evocheck(Player["inv"][idx]["level"], un)), Return(-2)] hbox: xalign 0.5 spacing 100 textbutton _("Ok") action Return(0) ## Right-click and escape answer "no". key "game_menu" action Return(0) # Show inventory button label inventory: play music MUSIC_PARTY.id() fadein 0.5 $ hud_clear() # Try to update inventory $ inv=get_inventory() python: try: renpy.call_screen("msgbox", "Error: %d" % int(inv)) except: Player["inv"]=dlist() for a in inv: Player["inv"].append(a) label show_inv: call screen inventory if (_return >= 0): $stdout("Selected unit index %d" % _return) $un=allunits[Player["inv"][_return]["unit_id"]] $show_img("unit_"+str(un["unit_id"]), at_list=[truecenter]) $hpval=readjust_status(un["rare"], un["job"], True)*Player["inv"][_return]["level"]+un["hp"] $akval=readjust_status(un["rare"], un["job"], False)*Player["inv"][_return]["level"]+un["strength"] $ret=renpy.call_screen("char_details", un, hpval, akval, _return) # Proccess input if ret == -1: $who=_return call upgrade_pre elif ret == -2: $who=_return call evolve_pre $renpy.hide("unit_"+str(un["unit_id"])) else: jump restore jump show_inv label party_lobby_enter: play music MUSIC_PARTY.id() fadein 0.5 $ hud_clear() # Try to update inventory $ inv=get_inventory() python: try: renpy.call_screen("msgbox", "Error: %d" % int(inv)) except: Player["inv"]=dlist() for a in inv: Player["inv"].append(a) # FIXME $ get_party(1, True) jump party_lobby label party_lobby: call screen party_main # Return to town if _return == -1: jump restore # Update party index $party_update(_return[0], _return[1]) $ get_party(_return[0], True) jump party_lobby label upgrade_pre: # who -> index. Set beforehand if who < 0: call screen msgbox("Error: Invalid upgrade parameters passed") return $ unit = allunits[Player["inv"][who]["unit_id"]] $ material = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1] # Try to update inventory $ inv=get_inventory() python: try: renpy.call_screen("msgbox", "Error: %d" % int(inv)) except: Player["inv"]=dlist() for a in inv: Player["inv"].append(a) jump upgrade label upgrade: call screen upgrade_char() $message=_return if (message == -1): $who=-1 return #jump restore if (message == -2): # TODO python: mats=list(set(material)) mats.insert(0, who) if -1 in mats: mats.remove(-1) stdout(str(mats)) ret=None ret=renpy.call_screen("confirm", "Are you sure you want to merge these units?", Return(True), Return(False)) if ret: # TODO: DISPLAY ANIMATION message=send_packet("upgrade", str(mats)) message=json_decode(message) try: lv=Player["inv"][who]["level"] narrator("Level up! %d -> %d" % (lv, int(message)+lv)) except: narrator("An error occured.\n\nError code: %s" % str(message)) renpy.jump("upgrade_pre") else: $ cand=renpy.call_screen("inventory", True) if cand in material and cand >= 0: "This unit is already to be merged!" elif cand == who: "Cannot merge unit with itself!" else: # TODO: Check for party #"Trying to fuse [cand], must check if in party, duplicate, etc." $ material[message]=cand $ del cand # WIP jump upgrade label evolve_pre: # who -> index. Set beforehand if who < 0: call screen msgbox("Error: Invalid upgrade parameters passed") return $ unit = allunits[Player["inv"][who]["unit_id"]] $ next = allunits[Player["inv"][who]["unit_id"]+1] $ material = [-1, -1] # Try to update inventory $ inv=get_inventory() python: try: renpy.call_screen("msgbox", "Error: %d" % int(inv)) except: Player["inv"]=dlist() for a in inv: Player["inv"].append(a) #$renpy.call_screen("msgbox", "Feature not yet available\n%s" % next["name"]) $renpy.hide("unit_"+str(unit["unit_id"])) jump evolve label evolve: call screen evolve_char() $message=_return if (message == -1): $who=-1 return #jump restore if (message == -2): # TODO python: mats=list(set(material)) mats.insert(0, who) stdout(str(mats)) ret=None ret=renpy.call_screen("confirm", "Are you sure you want to evolve this units?\nReagents will be lost forever!", Return(True), Return(False)) if ret: message=send_packet("evolve", str(mats)) message=json_decode(message) if message in ["200", 200]: # TODO: DISPLAY ANIMATION narrator("Evolution SUCCESS!") else: narrator("Error code: 101!\n\n%s" % str(message)) renpy.jump("inventory") else: $ cand=renpy.call_screen("inventory", True, 'alu["rare"] == %d and\ (\ (alu["unit_id"] == %s) or\ (alu["flags"] & UF_EVOMAT and alu["attribute"] == %d) or\ (alu["flags"] & UF_SUPEREVO) )' % (unit["rare"], unit["unit_id"], unit["attribute"])) if cand in material and cand >= 0: "This unit is already to be used as material!" elif cand == who: "That's the unit being evolved!" else: # TODO: Check for party #"Trying to fuse [cand], must check if in party, duplicate, etc." $ material[message]=cand $ del cand # WIP jump evolve