#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
# Pickpocket Ability
# Author: ForeverZer0
# Date: 5.4.2011
# Version: 1.5
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
# Version History:
# v.1.0 - Original Release
# v.1.1 - Added configuration for Input
# v.1.2 - More efficient and improved method of gathering pickpocket data
# - No longer requires comment codes to be in brackets []
# (Old configurations will still work, though)
# - Configurable search codes
# - No longer requires 'Pickpocket' comment for initialization
# - Consolidated various class methods/variables
# - Better looking pickpocket result window, and got rid of annoying bug
# that would 'talk' to event when exiting result window
# - Added config for font color of result item
# - Improved coding/compatability
# v.1.3 - Removed from Zer0 Add-On Collection
# - Optimized code
# - Added a TOTAL_ATTEMPTS_VARIABLE
# - Added ability to use a single comment instead of three in a row
# v.1.4 - Added switch to turn system ON/OFF
# - Made the item requirement optional (Thanks, GrieverSoft)
# - Improved the result window. Now draws icons.
# v.1.5 - Reconfigured to allow for weapons to also add pickpocket ability
# - Created configuration to allow for different equipment to give
# bonuses to the odds of a successful steal
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
#
# Explanation:
#
# - Anybody who played the PSX game Star Ocean will know exactly what this is.
# It is basically a system that will allow you to pickpocket NPCs to recieve
# various items, weapons, and armors if you have a certain accessory.
#
# Features:
#
# - Easy, quick configuration to setup each event
# - Variables log all successes and failures for easy merging into an
# Affection System, Good & Evil System, etc.
#
# Instructions:
#
# - Setup the few configurations below.
# - This script uses comments in the event's pages. Here's how to configure:
#
# ** In a single comment or consecutive single line comments *
#
# Chance = X - where X is equal to the percentage of
# a successful pickpocket. (0 - 100)
#
# Type = Y - where Y is the type of item that will be recieved (0-2)
# 0 = Item
# 1 = Weapon
# 2 = Armor
#
# ItemID = Z - where Z is equal to the database ID of the item, weapon,
# or armor (based off of the third comment).
#
# That's it for setting up events. There are a few more configurations below.
# For a player to use the ability, they have to have the "Bandit's Gloves"
# equipped, or whatever you want to call it (see below), and press the Z button
# (configurable) while touching an event and a pickpocket attempt will be made.
#
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
# BEGIN CONFIGURATION
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
module Pickpocket
#-----------------------------------------------------------------------------
# The following two methods define equipment that can offer the ability to
# pickpocket (if ITEM_REQUIRE), and the bonus that different equipment can
# give. In each respective method for armors and weapons, any ID that has
# a return value for it will be an item that unlocks the pickpocket ability
# if equipped. The returned value will define the bonus percentage that the
# item gives to the overall odds of success.
#
# EXAMPLE:
#
# when 34 then 10
#
# This does two things: Lets the weapon/armor with ID:34 provide the ability
# to steal if equipped, and adds a 10% bonus to the success rate.
#-----------------------------------------------------------------------------
def self.armors(armor_id)
return case armor_id
# when ARMOR_ID then PERCENT_ADDED
when 33 then 0 # Bandit's Glove
when 34 then 10 # Thief's Glove
when 35 then 25 # Magician's Hand
end
end
def self.weapons(weapon_id)
return case weapon_id
# when WEAPON_ID then PERCENT_ADDED
when 32 then 0
end
end
# Define any bonuses that are given for having a specific actor in the party.
def self.actor_bonus(actor_id)
return case actor_id
# when ACTOR_ID then PERCENT_ADDED
when 1 then 3
else
0 # Default case. Do not edit.
end
end
PICKPOCKET_SWITCH = 20
# ID of the switch that will turn the system ON/OFF.
SUCCESS_SE = ['055-Right01', 80, 100]
# SE played when attempt is successful [FILENAME, VOLUME, PITCH]
FAIL_SE = ['057-Wrong01', 80, 100]
# SE played when attempt fails [FILENAME, VOLUME, PITCH]
SUCCESS_VARIABLE = 1
# In-game variable that will be equal to total successful pickpockets
FAILURE_VARIABLE = 2
# In-game variable that will be equal to total unsuccessful pickpockets
TOTAL_ATTEMPTS_VARIABLE = 3
# Variable that will be equal to total attempts, successful or not.
ITEM_REQUIRE = true
# Set to true/false. Determines if an item is required to use the ability.
STEAL_BUTTON = Input::Z
# This will be the button that is used to pickpocket events, mind you this the
# the game button, not just the button on your keyboard.
CHANCE_STRING = 'Chance = '
TYPE_STRING = 'Type = '
ITEM_ID_STRING = 'ItemId = '
# These are the strings that the system searches for in event's comments. If
# you would like something different, change them. It will match the number
# that immediately follows them.
RESULT_FONT_COLOR = Color.new(128, 255, 128)
# This will be the font color that the item is written in when the result
# of a successful pickpocket is displayed on-screen. (Red, Green, Blue)
USE_MODIFIER = false
# If true, will apply a formula using the party's dexterity to get a
# small bonus to the chance of success. (below)
#-------------------------------------------------------------------------------
# * Modifier Formula
#
# (TOTAL_PARTY_DEX รท PARTY_SIZE) = X
#
# (Square Root of X) * 0.66 = MODIFIER
#
# The modifier is added to the chance. It's not much, but at higher levels,
# it can add a different dynamic to pickpocketing. In a quick test using the
# default curves, it's about a 5 point bonus at level 1, and with the same
# actors all at level 99, it is about a 16 point bonus. Even with the entire
# party all having 999 dexterity, the bonus will not exceed 21 points, which
# I feel is an appropriate curve. Check out the method and fiddle around
# with the '0.66' if you want to alter it. Just bust out a calculator and plug
# the formula in real quick to see what values your getting.
#
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
# END CONFIGURATION
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
end
#===============================================================================
# ** Game_Map
#===============================================================================
class Game_Map
attr_reader :steal_data # Array of pickpocket events, remade for each map
attr_accessor :attempted # Logs all attempted steals for each map
alias zer0_pickpocket_init initialize
def initialize
@steal_data, @attempted = [], {}
zer0_pickpocket_init
end
alias zer0_pickpocket_map setup
def setup(map_id)
unless @attempted.has_key?(map_id)
@attempted[map_id] = []
end
zer0_pickpocket_map(map_id)
refresh_pickpocket
end
def comment_code(string)
# Returns array of event IDs with matching number after 'string'
array = []
@map.events.each_key {|key|
event = @map.events[key]
event.pages.reverse.each {|page|
page.list.each_index {|i|
if [108, 408].include?(page.list[i].code) &&
page.list[i].parameters[0] =~ /#{string}([0-9]+)/
array.push([event.id, $1.to_i])
end
}}}
return array
end
def refresh_pickpocket
@steal_data.clear
chance = comment_code(Pickpocket::CHANCE_STRING)
type = comment_code(Pickpocket::TYPE_STRING)
item_id = comment_code(Pickpocket::ITEM_ID_STRING)
chance.each_index {|i|
id, ch, ty, it = chance[i][0], chance[i][1], type[i][1], item_id[i][1]
@steal_data.push([id, ch, ty, it])
}
end
end
#===============================================================================
# ** Game_Player
#===============================================================================
class Game_Player
alias zer0_pickpocket_map update
def update
zer0_pickpocket_map
if Input.trigger?(Pickpocket::STEAL_BUTTON) && $game_party.can_pickpocket?
# Get coordinates/direction in relation to event
dir_x = @x + (@direction == 6 ? 1 : @direction == 4 ? -1 : 0)
dir_y = @y + (@direction == 2 ? 1 : @direction == 8 ? -1 : 0)
$game_map.steal_data.each_index {|i|
id = $game_map.steal_data[i][0]
if $game_map.events[id].x == dir_x && $game_map.events[id].y == dir_y
return if $game_map.attempted[$game_map.map_id].include?(id)
pickpocket(i)
$game_map.attempted[$game_map.map_id].push(id)
end
}
end
end
def pickpocket(index)
# Get a random number between 0 - 100
r = rand(101)
# Initialize modifier (remains at 0 unless USE_MODIFIER is true)
modifier = $game_party.equipment_mod
if Pickpocket::USE_MODIFIER
$game_party.actors.each_index {|i|
modifier += $game_party.actors[i].base_dex
}
modifier = (modifier / $game_party.actors.size)
modifier = (Math.sqrt(modifier)) * 0.66
end
# Gather the event's pickpocket data from the steal_data list
chance = ($game_map.steal_data[index][1] + modifier.round)
item_type = $game_map.steal_data[index][2]
item_id = $game_map.steal_data[index][3]
# If the random number is less than the chance, SUCCESS!
if chance >= r
$game_system.se_play(RPG::AudioFile.new(*Pickpocket::SUCCESS_SE))
case item_type
when 0
$game_party.gain_item(item_id, 1)
item = $data_items[item_id]
when 1
$game_party.gain_weapon(item_id, 1)
item = $data_weapons[item_id]
when 2
$game_party.gain_armor(item_id, 1)
item = $data_armors[item_id]
end
$game_variables[Pickpocket::SUCCESS_VARIABLE] += 1
# Set the result of the pickpocket to the screen
$scene.pickpocket_result(item) if $scene.is_a?(Scene_Map)
else
$game_system.se_play(RPG::AudioFile.new(*Pickpocket::FAIL_SE))
$game_variables[Pickpocket::FAILURE_VARIABLE] += 1
end
$game_variables[Pickpocket::TOTAL_ATTEMPTS_VARIABLE] += 1
end
end
#===============================================================================
# ** Game_Party
#===============================================================================
class Game_Party
alias pickpocket_init initialize
def initialize
pickpocket_init
# Store pickpocket weapons and armors to prevent checking later
@pickpocket_weapons = (1..$data_weapons.size).find_all {|i|
Pickpocket.weapons(i) != nil }
@pickpocket_armors = (1..$data_armors.size).find_all {|i|
Pickpocket.armors(i) != nil }
@mods = []
end
def can_pickpocket?
# Check switch
return false unless $game_switches[Pickpocket::PICKPOCKET_SWITCH]
# Return false if message window is showing
return false if $game_temp.message_window_showing
# Check equipment if required
if Pickpocket::ITEM_REQUIRE
@mods = []
weapons = @pickpocket_weapons.find_all {|id| party_weapons.include?(id) }
armors = @pickpocket_armors.find_all {|id| party_armors.include?(id) }
# Add modifiers of found equipment.
@mods += weapons.collect {|weapon_id| Pickpocket.weapons(weapon_id) }
@mods += armors.collect {|armor_id| Pickpocket.armors(armor_id) }
return @mods != []
end
return true
end
def party_weapons
# Returns array of the party's weapon IDs
return @actors.collect {|actor| actor.weapon_id }
end
def party_armors
# Returns array of party's armor IDs
armors = []
$game_party.actors.each {|actor|
armors.push(actor.armor1_id)
armors.push(actor.armor2_id)
armors.push(actor.armor3_id)
armors.push(actor.armor4_id)
}
return armors
end
def equipment_mod
actor_bonus = @actors.collect {|actor| Pickpocket.actor_bonus(actor.id) }
bonus = 0
actor_bonus.each {|percent| bonus += percent }
# Returns the highest percentage-adding value of all current equipment.
return @mods != [] ? (@mods.sort[-1] + bonus) : bonus
end
end
#===============================================================================
# ** Window_Pickpocket
#===============================================================================
class Window_Pickpocket < Window_Base
def initialize(item)
# Initialize window through parent class.
super(176, 192, 224, 96)
self.contents = Bitmap.new(width - 32, height - 32)
self.contents.draw_text(0, 0, self.contents.width, 32, 'Received a', 1)
self.contents.font.color = Pickpocket::RESULT_FONT_COLOR
# Calculate coordinates to draw name and icon.
icon = RPG::Cache.icon(item.icon_name)
w = 32 + self.contents.text_size(item.name + '!').width
x = (self.contents.width - w) / 2
self.contents.blt(x + 4, 32, icon, Rect.new(0, 0, 24, 24))
self.contents.draw_text(x + 32, 32, w, 32, item.name + '!')
end
end
#===============================================================================
# ** Scene_Map
#===============================================================================
class Scene_Map
def pickpocket_result(item)
# Displays the result on screen in a message.
window = Window_Pickpocket.new(item)
loop {
[Graphics,Input, @spriteset].each {|obj| obj.update }
break if Input.trigger?(Input::C) || $scene != self
}
window.dispose
end
end