#============================================================================== # Storage Boxes Addon: Item Thefts # by IMP1 #------------------------------------------------------------------------------ # THIS SCRIPT REQUIRES THE 'STORAGE BOXES' SCRIPT BY IMP1 # # You can set a box's last accessed time to the current time by having the # following in an event's script command: # # $game_boxes.touch(3) # This will reset the last accessed time of box 3 to the current time. # # To stop an item from being stolen, add into its notebox. #------------------------------------------------------------------------------ # Compatability: # # Aliased Methods: # IMP1_Game_Boxes.initialize # Scene_ItemStorage.start # Scene_ItemStorage.terminate # # New Methods/Fields: # Game_BaseItem.maximum_price # IMP1_Game_Boxes.touch # Scene_ItemStorage.process_past_thefts # Scene_ItemStorage.calculate_item_theft # Scene_ItemStorage.calculate_box_theft # Scene_ItemStorage.calculate_theft_probability # # Overwritten Methods: # none. # #------------------------------------------------------------------------------ # Version History: # v1.2 [2015/07/01] : Updated to use refactored base code. # v1.1 [2014/11/18] : Added option of having boxes only stealable after the # first time they're accessed. # v1.0 [2014/11/16] : Initial release. #============================================================================== module IMP1_Storage_Boxes #------------------------------------------------------------------------------ # CONFIGURATION BEGIN: #------------------------------------------------------------------------------ # This is the minimum amount of time (in seconds) that have to have passed # for there to be any chance of an item being stolen. MINIMUM_THEFT_TIME = 10 # This is the default probability that items will be stolen from this box. # Setting it to 0 will mean items cannot be stolen, and 1 will mean the box # offers no protection against theft. DEFAULT_BOX_PROBABILITY = 0.5 # You can set a box to have a probability other than the default. BOX_THEFT_PROBABILITIES = { # Do not remove. # The first box will have a probability of 0.8 0 => 0.8, # The third will be very safe because of its low value. 2 => 0.1 } # Do not remove. DEFAULT_ITEM_THEFT = lambda { |gold_value, max_gold_value, key_item| # This is the default probability that an item will be stolen. # You can use the following variables: # gold_value : the price of the item (in the database). # max_gold_value : the maximum price of all items. # key_item : this is 1 if the item is a key item and 0 if not. return (gold_value / max_gold_value) ** 0.5 } # Do not remove. # If this is true then key items cannot be stolen. KEY_ITEMS_UNSTEALABLE = true # This is true, then boxes can only have items stolen from them after they # have been accessed for the first time (this will include the .touch # function). ONLY_STEALABLE_AFTER_FIRST_VISIT = false #------------------------------------------------------------------------------ # CONFIGURATION END. #------------------------------------------------------------------------------ end #============================================================================== # Game_BaseItem #============================================================================== class Game_BaseItem # A new variable to hold the maximum price of any item. @@imp_max_price = nil #-------------------------------------------------------------------------- # Set the time last accessed for all the boxes to the time now. #-------------------------------------------------------------------------- def self.maximum_price if @@imp_max_price.nil? max = 0 $data_items.each { |i| max = i.price if i && i.price && i.price > max } $data_weapons.each { |i| max = i.price if i && i.price && i.price > max } $data_armors.each { |i| max = i.price if i && i.price && i.price > max } @@imp_max_price = max end return @@imp_max_price end end # Game_BaseItem #============================================================================== # Game_Boxes #============================================================================== class IMP1_Game_Boxes # The array of last accessed times of the boxes. attr_accessor :last_accessed #-------------------------------------------------------------------------- # Set the time last accessed for all the boxes to the time now. #-------------------------------------------------------------------------- alias :sans_steal_initialize :initialize unless $@ def initialize sans_steal_initialize time = nil if ONLY_STEALABLE_AFTER_FIRST_VISIT time = Graphics.frame_count.to_f / Graphics.frame_rate end @last_accessed = Array.new(BOXES.size, time) end #-------------------------------------------------------------------------- # Set the time last accessed for a box to the time now. #-------------------------------------------------------------------------- def touch(box_id) @last_accessed[box_id] = Graphics.frame_count.to_f / Graphics.frame_rate end end # IMP1_Game_Boxes #============================================================================== # Scene_ItemStorage #============================================================================== class Scene_ItemStorage #-------------------------------------------------------------------------- # Before starting, it performs any thefts. #-------------------------------------------------------------------------- alias :sans_steal_start :start unless $@ def start process_past_thefts sans_steal_start end #-------------------------------------------------------------------------- # Calculates thefts to be performed and executes them. #-------------------------------------------------------------------------- def process_past_thefts last_access = $game_boxes.last_accessed[@box_id] return if last_access == nil time_now = Graphics.frame_count.to_f / Graphics.frame_rate t = time_now - last_access b = calculate_box_theft(@box_id) $game_boxes.box(@box_id).each do |item, num| k = calculate_item_theft(item) thefts = 0 num.times do stolen = rand() < calculate_theft_probability(t, k, b) thefts += 1 if stolen end $game_boxes.remove_item(item, thefts, @box_id) end end #-------------------------------------------------------------------------- # Creates the necessary parameters, and calls the function to calculate # the item's theft probability. #-------------------------------------------------------------------------- def evaluate_item_formula(item) value = item.price.to_f max_value = Game_BaseItem.maximum_price key_item = item.is_a?(RPG::Item) && item.key_item? ? 1 : 0 args = [value, max_value, key_item] result = IMP1_Storage_Boxes::DEFAULT_ITEM_THEFT.call(*args) return [[0, result].max, 1].min end #-------------------------------------------------------------------------- # Returns the liklihood that this item will be stolen. #-------------------------------------------------------------------------- def calculate_item_theft(item) if item.note.include?("") || (item.is_a?(RPG::Item) && item.key_item? && IMP1_Storage_Boxes::KEY_ITEMS_UNSTEALABLE) return 0 elsif item.note.include?("/).flatten[0].to_f else return evaluate_item_formula(item) end end #-------------------------------------------------------------------------- # Returns the liklihood that an item will be stolen from this box. #-------------------------------------------------------------------------- def calculate_box_theft(box) if IMP1_Storage_Boxes::BOX_THEFT_PROBABILITIES.keys.include?(box) return IMP1_Storage_Boxes::BOX_THEFT_PROBABILITIES[box] else return IMP1_Storage_Boxes::DEFAULT_BOX_PROBABILITY end end #-------------------------------------------------------------------------- # Returns the liklihood that this item will be stolen from this box, given # that this amount of time has passed. #-------------------------------------------------------------------------- def calculate_theft_probability(time, item, box) return 0 if time < IMP1_Storage_Boxes::MINIMUM_THEFT_TIME time -= IMP1_Storage_Boxes::MINIMUM_THEFT_TIME return box * item * (time) / (time + 1) end #-------------------------------------------------------------------------- # Sets the last accessed time to when the box is closed. #-------------------------------------------------------------------------- alias :sans_steal_terminate :terminate unless $@ def terminate time_now = Graphics.frame_count.to_f / Graphics.frame_rate $game_boxes.last_accessed[@box_id] = time_now sans_steal_terminate end end # Scene_ItemStorage