init -1 python:
import renpy.store as store
import renpy.exports as renpy # we need this so Ren'Py properly handles rollback with classes
from operator import attrgetter # we need this for sorting items
inv_page = 0 # initial page of the inventory screen
item = None
class Player(renpy.store.object):
def __init__(self, name, mc_max_hp=0, mc_max_mp=0, element=None):
self.name=name
self.mc_max_hp=mc_max_hp
self.mc_hp=mc_max_hp
self.mc_max_mp=mc_max_mp
self.mp=mc_max_mp
self.element=element
player = Player("[sylv]", 100, 50)
class Item(store.object):
def __init__(self, name, player=None, mc_hp=0, mc_mp=0, image="", element="", cost=0):
global cookbook
self.name = name
self.player=player # which character can use this item?
self.mc_hp = mc_hp # does this item restore hp?
self.mc_mp = mc_mp # does this item restore mp?
self.element=element # does this item change elemental damage?
self.image=image # image file to use for this item
self.cost=cost # how much does it cost in shops?
#self.desc = desc
#self.icon = icon
#self.act = act # screen action
#self.type = type # type of item
#self.recipe = recipe # nested list of [ingredient, qty]
#if recipe:
# cookbook.append(self)
# cookbook.sort(key=lambda i: i.name) #alpha order
#def change(self, name, desc=False, value=False, act=False, recipe=False):
#self.name = name
#if desc:
# self.desc = desc
#if value:
# self.value = value
#if act:
# self.act = act
#if recipe:
# self.recipe = recipe
# def output(self):
# return str(self.amt)
#
# def add_stack(self, amt):
# self. amt += 1
#
# class invitem(object):
# def __init__(self, item, amount):
# self.item = item
# self.amount = amount
def use(self): #here we define what should happen when we use the item
if self.mc_hp>0: #healing item
player.mc_hp = player.mc_hp+self.mc_hp
if player.mc_hp > player.mc_max_hp: # can't heal beyond max HP
player.mc_hp = player.mc_max_hp
inventory.drop(self) # consumable item - drop after use
elif self.mc_mp>0: #mp restore item
player.mc_mp = player.mc_mp+self.mc_mp
if player.mc_mp > player.mc_max_mp: # can't increase MP beyond max MP
player.mc_mp = player.mc_max_mp
inventory.drop(self) # consumable item - drop after use
else:
player.element=self.element #item to change elemental damage; we don't drop it, since it's not a consumable item
class Inventory(store.object):
def __init__(self, money=0):
self.currentItem = None
self.money = money
self.items = [] # items stored in nested list [item object, qty]
#self.barter = barter #percentage of value paid for items
#self.sort_by = self.sort_name
#self.sort_order = True #ascending, descending
#self.grid_view = True
def take(self, item, qty=1):
if self.qty(item):
item_location = self.check(item)
self.items[item_location][1] += qty
else:
self.items.append([item,qty])
#if len(inventory.items) > 54: #<---
# renpy.say(None, "Inventory is full.{w=0.5}{nw}") # or use any other way to show it to player
#else:
# self.items.append[(item,qty)]
def check(self, item):
if self.qty(item):
for i in self.items:
if i[0] == item:
return self.items.index(i) # returns item index (location)
def drop(self, item, qty=1):
if self.qty(item):
item_location = self.check(item)
if self.items[item_location][1] > qty:
self.items[item_location][1] -= qty
else:
del self.items[item_location]
#def drop(self, item):
# self.items.remove(item)
def buy(self, item):
if self.money >= item.cost:
if len(inventory.items) > 54:
renpy.say(None, "Inventory is full.{w=0.5}{nw}")
return False
else:
self.items.append[(item,qty)]
self.money -= item.cost #bonus code to next # line
return True
else:
renpy.say(None, "Not enough money.{w=0.5}{nw}")
return False
def earn(self, amount):
self.money += amount
def qty(self, item):
for i in self.items:
if i[0] == item:
return i[1] # returns quantity
def sort_qty(self):
self.items.sort(key=lambda i: i[1], reverse=self.sort_order)
#def take(self, item, qty=1):
# if self.qty(item):
# item_location = self.check(item)
# self.items[item_location][1] += qty
# else:
# self.items.append([item,qty])
def has_item(self, item):
if item in self.items:
return True
else:
return False #here ends bonus code
def updateSelected(self, item=None):
if item is not None:
self.currentItem = item.name
else:
self.currentItem = None
def sell(self, item, price):
self.withdraw(price)
self.drop(item[0])
def withdraw(self, amount):
self.money += amount
def deposit(self, amount):
self.money -= amount
def calculate_price(item, buyer):
if buyer:
price = item[0].cost * (buyer.barter * 0.01)
return int(price)
def item_use():
item.use()
def money_transfer(depositor, withdrawer, amount):
if depositor.money >= amount:
depositor.deposit(amount)
withdrawer.withdraw(amount)
else:
message = "Sorry, %s doesn't have %d!" % (buyer.name, amount)
renpy.show_screen("inventory_popup", message=message)
def transaction(seller, buyer, item):
price = calculate_price(item, buyer)
if buyer.money >= price:
seller.sell(item, price)
buyer.buy(item, price)
else:
message = "Sorry, %s doesn't have enough money!" % (buyer.name)
renpy.show_screen("inventory_popup", message=message)
transfer_amount = 0
#Tooltips:
style.tips_top = Style(style.default)
#style.title.font="gui/arial.ttf"
style.tips_top.size=14
style.tips_top.color="fff"
style.tips_top.outlines=[(3, "6b7eef", 0,0)]
style.tips_top.kerning = 5
style.tips_bottom = Style(style.tips_top)
style.tips_top.size=20
style.tips_bottom.outlines=[(0, "6b7eef", 1, 1), (0, "6b7eef", 2, 2)]
style.tips_bottom.kerning = 2
style.button.background=Frame("gui/frame.png",25,25)
style.button.yminimum=52
style.button.xminimum=52
style.button_text.color="000"
showitems = True #turn True to debug the inventory
# def display_items_overlay():
# if showitems:
# inventory_show = "Money:" + str(inventory.money) + " HP: " + str(player.hp) + " bullets: " + str(player.mp) + " element: " + str(player.element) + "\nInventory: "
# for i in range(0, len(inventory.items)):
# item_name = inventory.items[i].name
# if i > 0:
# inventory_show += ", "
# inventory_show += item_name
# ui.frame()
# ui.text(inventory_show, color="#000")
# config.overlay_functions.append(display_items_overlay)
screen inventory_button:
textbutton "Show Inventory" action [Hide("inventory_button"), Call("inv")] align (.95,.04)
screen inventory_screen:
add "gui/inventory.png"
modal True #prevent clicking on other stuff when inventory is shown
imagebutton auto "nav/exit_inv_%s.png" xpos 930 ypos 10 xalign 1.0 focus_mask True action [ Hide("inventory_screen")]
#use battle_frame(char=player, position=(.97,.20)) # we show characters stats (mp, hp) on the inv. screen
#use battle_frame(char=dog, position=(.97,.50))
window:
add "gui/inventory.png" # the background
xysize(1920, 1080)
align(0.0, 0.0)
imagebutton auto "gui/inv_bag_%s.png" xpos 156 ypos 397 focus_mask None action [Show("inventory_button"), Call("return_screen")]#, Show("gui_tooltip", my_picture=my_tooltip, my_tt_xpos=1715, my_tt_ypos=990) ] unhovered [Hide("gui_tooltip"), Function(set_cursor_default)] at main_eff1
hbox align (.95,.04) spacing 20:
textbutton "Close Inventory" action [Show("inventory_button"), Call("return_screen")]
for item in inventory.items:
$ cost = item[0].cost
$ qty = str(item[1])
$ x = 515 # coordinates of the top left item position
$ y = 25
$ i = 0
$ sorted_items = sorted(inventory.items, key=attrgetter('element'), reverse=True) # we sort the items, so non-consumable items that change elemental damage (guns) are listed first
$ next_inv_page = inv_page + 1
$ prev_inv_page = inv_page - 1 #my code
$ max_inv_page = 5 # count the max page number
if inv_page > max_inv_page: # if items in inventory were reduced and amount of pages were decreased too
$ inv_page = max_inv_page
if next_inv_page > int(len(inventory.items)/9):
$ next_inv_page = 0
if prev_inv_page < int(len(inventory.items)/54): #my code
$ prev_inv_page = 0
for item in sorted_items:
if i+1 <= (inv_page+1)*9 and i+1>inv_page*9:
$ x += 190
if i%3==0:
$ y += 170
$ x = 515
$ pic = item.image
$ my_tooltip = "tooltip_inventory_" + pic.replace("gui/inv_", "").replace(".png", "") # we use tooltips to describe what the item does.
imagebutton idle pic hover pic xpos x ypos y action [Hide("gui_tooltip"), SetVariable("item", item), Function(renpy.invoke_in_new_context, inventory.updateSelected, item), item_use, Function(renpy.restart_interaction)] hovered [ Play ("sound", "sfx/click.wav"), Show("gui_tooltip", my_picture=my_tooltip, my_tt_ypos=693) ] unhovered [Hide("gui_tooltip")] at inv_eff
if player.element and (player.element==item.element): #indicate the selected gun
add "gui/selected.png" xpos x ypos y anchor(.5,.5)
$ i += 1
if len(inventory.items)>9:
textbutton _("Next Page") action [ If(inv_page < max_inv_page, SetVariable('inv_page', inv_page + 1), SetVariable('inv_page', 0)), Show("inventory_screen") ] xpos .475 ypos .83 # if inv_page is less than max_inv_page increase the inv_page number, otherwise set the inv_page to 0
#textbutton _("Next Page") action [SetVariable('inv_page', next_inv_page), Show("inventory_screen")] xpos .475 ypos .83
textbutton _("Previous Page") action [SetVariable('inv_page', prev_inv_page), Show("inventory_screen")] xpos .575 ypos .83
screen inventory_popup(message):
zorder 100
frame:
style_group "invstyle"
hbox:
text message
timer 1.5 action Hide("inventory_popup")
screen gui_tooltip (my_picture="", my_tt_xpos=58, my_tt_ypos=687):
add my_picture xpos my_tt_xpos ypos my_tt_ypos
init -1:
transform inv_eff: # too lazy to make another version of each item, we just use ATL to make hovered items super bright
zoom 0.5 xanchor 0.5 yanchor 0.5
on idle:
linear 0.2 alpha 1.0
on hover:
linear 0.2 alpha 2.5
image information = Text("INFORMATION", style="tips_top")
#Tooltips-inventory:
image tooltip_inventory_chocolate=LiveComposite((665, 73), (3,0), ImageReference("information"), (3,30), Text("Generic chocolate to heal\n40 points of health.", style="tips_bottom"))
image tooltip_inventory_banana=LiveComposite((665, 73), (3,0), ImageReference("information"), (3,30), Text("A healthy banana full of potassium! You can also use it as ammo for your guns! O.O Recharges 20 bullets.", style="tips_bottom"))
image tooltip_inventory_gun=LiveComposite((665, 73), (3,0), ImageReference("information"), (3,30), Text("An gun that looks like something a cop would\ncarry around. Most effective on humans.", style="tips_bottom"))
image tooltip_inventory_laser=LiveComposite((665, 73), (3,0), ImageReference("information"), (3,30), Text("An energy gun that shoots photon beams.\nMost effective on aliens.", style="tips_bottom"))
image tooltip_inventory_bag_idle=LiveComposite((665, 73), (3,0), ImageReference("information"), (3,30), Text("Open bacpack.", style="tips_bottom"))
image sidewalk = "Gallery_bg.png"