You are awesome! It works now. But I'm with one problem: The bars don't update, I did set the default to 1 step per 1 point down. And the bars don't update, and if the bars should be empty, I'm still alive. (While i set the state that the player should get is Knockout.
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
# Hunger/Thirst
# Author: ForeverZer0
# Date: 5.14.2010
# Version: 1.0
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
#
# Features:
# - Easy to use
# - MUCH less complicated than many other similar scripts, yet it has more
# features and less code
# - Can have hunger and thirst decrease by time intervals or by steps walked
# by the player
# - Ability to have each character's 'Max Hunger' increase so that they can go
# longer in between food and drinks as they gain in power
# - Can use script calls to easily change hunger/thirst values, and to disable
# the system for long cutscenes, etc. so that nothing decreases while the
# player does not have control
# - Automatically added states if hunger/thirst is at specific rates.
#
# Compatibility:
# - If using Zero Add-On Collection, place this script below it. There is a
# minor issue with the Chemist Class script, but placing this script below
# it will solve the problem.
#
# Instructions:
# - Place script below debug, and above main (below Zer0 Add-Ons, if present)
# - All configuration is below and described fully in its respective section
# - The following script calls can be used in game:
#
# ► Zer0.hunger_system(true/false)
# - If false, hunger/thirst rates will not decrease. Good for long scenes
# where the player is not in control, etc. The system will remain ON/OFF
# until it is changed.
#
# ► Zer0.set_hunger(ACTOR_ID, AMOUNT)
# ► Zer0.set_thirst(ACTOR_ID, AMOUNT)
# - Sets the hunger/thirst of actor in your database with ACTOR_ID to the
# number specified by AMOUNT
#
# ► Zer0.set_max_hunger(ACTOR_ID, AMOUNT)
# ► Zer0.set_max_thirst(ACTOR_ID, AMOUNT)
# - Sets the MAX hunger/thirst of actor in your database with ACTOR_ID to
# the number specified by AMOUNT
#
# ► Zer0.recover_hunger(ACTOR_ID)
# - Will recover all hunger/thirst to actor with ACTOR_ID. If you omit the
# ( ) at the end of the script call, it will recover the entire party.
#
# ► Zer0.actor_hunger_id(ACTOR_ID)
# - Returns the current hunger of actor with ACTOR_ID
#
# ► Zer0.actor_thirst_id(ACTOR_ID)
# - Returns the current thirst of actor with ACTOR_ID
#
# ► Zer0.actor_hunger_pos(POSITION)
# - Return the current hunger of actor at party POSITION
# (0 is the leader, 1 is actor 2, etc)
#
# ► Zer0.actor_thirst_pos(POSITION)
# - Return the current thist of actor at party POSITION
# (0 is the leader, 1 is actor 2, etc)
#
# ► Zer0.hunger_debugger
# - Displays info on-screen of each characters hunger/thirst, current
# count for steps and time, and shows which features are currently ON.
#
# Special Thanks:
# - kukusu, whose request gave me the inspiration for the script
# - SBR*, for pointing out a stupid error I made with the stepcount
#
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
# BEGIN CONFIGURATION
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
module Zer0
DEFAULT_HUNGER = 50
DEFAULT_THIRST = 50
# Default max hunger/thirst players will begin with. This can be increased as
# the player becomes more powerful, through items, etc. if desired.
BY_TIME = false
BY_STEPS = true
# There are two ways hunger and thirst can be calculated; one by just how many
# seconds pass, and the other by how many steps have been taken. You can use
# both if you like, but I would suggest that if you do to try to keep it more
# skewed to one or the other as the main method of decreasing, and use the
# other as a minor added dynamic.
STEPS_HUNGER_DOWN = 1
STEPS_THIRST_DOWN = 1
# Only if using 'BY_STEPS', otherwise ignore these. These are the amount
# of steps before hunger/thirst decrease.
SECS_HUNGER_DOWN = 120
SECS_THIRST_DOWN = 120
# Only if using 'BY_TIME', otherwise ignore these. These are the amount
# of seconds before hunger/thirst decrease.
LVL_UP_INCREASE = true
# If true, will increase max hunger/thirst at each level up, the amount of
# increase is defined just below.
LVL_UP_AMOUNT = 2
# This will be added to the actor's max hunger/thirst at each level up, only
# if LVL_UP_INCREASE is true.
#-------------------------------------------------------------------------------
# Food/Drink Items:
#
# Set up your food/drink items recovery rates here. Food and drink are each in
# their own section. Use this syntax to set them up:
#
# when ITEM_ID the return RECOVERY_AMOUNT
#
# For example, in the first example below, it means that the item in your
# database with ID(1) will cure hunger by 15. If RECOVER_BY_PERCENT (below) is
# set to true, it will recover 15% of that actors MAX hunger/thirst.
#
# You can also create items that have negative effects by making the
# RECOVERY_AMOUNT a negative number. DO NOT have food/drink items do anything
# other than recover hunger/thirst and/or add/remove states. Anything else,
# such has HP/MP recovery, will have no effect.
#
#-------------------------------------------------------------------------------
RECOVER_BY_PERCENT = true
# Recovery can be by either absolute value, or by percent. Setting this to
# true will make it by percent.
def self.food(item_id)
case item_id
when 1 then return 15
when 2 then return 25
when 3 then return 35
when 4 then return 50
when 5 then return 75
when 6 then return 100
end
end
def self.drink(item_id)
case item_id
when 1 then return 15
when 2 then return 25
when 3 then return 35
when 4 then return 50
when 5 then return 75
when 6 then return 100
end
end
#-------------------------------------------------------------------------------
# Hunger/Thirst States
#
# Set up states that will be applied when an actors hunger/thirst fall within
# a defined range, such as 'Starvation', 'Dehydration', etc.
# Configure like this:
#
# when MIN..MAX then return STATE_ID
#
# If actor's hunger/thirst is equal to or between MIN and MAX, the state with
# STATE_ID will be applied. This method is refreshed everytime the system
# decreases hunger/thirst.
#
# Keep in mind that these states will NOT be automatically cured if the actor's
# hunger/thirst rise above. Create your food/drink items to cure these states.
#
#-------------------------------------------------------------------------------
def self.hunger_states(current_hunger)
case current_hunger
when 0 then return 1
when 1..5 then return 3
when 6..30 then return 2
end
end
def self.thirst_states(current_thirst)
case current_thirst
when 0 then return 1
when 1..9 then return 2
when 10..15 then return 3
end
end
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
# END CONFIGURATION
#:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:=:
def self.hunger_system(value)
$game_party.hunger = value
return true
end
def self.set_hunger(actor_id, amount)
$game_party.actors.each {|a| a.hunger = amount if a.id == actor_id}
end
def self.set_thirst(actor_id, amount)
$game_party.actors.each {|a| a.thirst = amount if a.id == actor_id}
end
def self.set_max_hunger(actor_id, amount)
$game_party.actors.each {|a| a.max_hunger = amount if a.id == actor_id}
end
def self.set_max_thirst(actor_id, amount)
$game_party.actors.each {|a| a.max_thirst = amount if a.id == actor_id}
end
def self.actor_hunger_id(actor_id)
$game_party.actors.each {|a| return a.hunger if a.id == actor_id}
end
def self.actor_thirst_id(actor_id)
$game_party.actors.each {|a| return a.thirst if a.id == actor_id}
end
def self.actor_hunger_pos(pos = 0)
return $game_party.actors[pos].hunger if $game_party.actors[pos] != nil
end
def self.actor_thist_pos(position = 0)
return $game_party.actors[pos].thirst if $game_party.actors[pos] != nil
end
def self.recover_hunger(actor_id = nil)
$game_party.actors.each {|actor|
if actor_id == nil
actor.hunger = actor.max_hunger
actor.thirst = actor.max_thirst
elsif actor.id == actor_id
actor.hunger = actor.max_hunger
actor.thirst = actor.max_thirst
end
}
end
def self.hunger_debugger
sys = "System ON: #{$game_party.hunger}\n\n" +
"By Time: #{BY_TIME}\n" +
"By Steps: #{BY_STEPS}\n\n"
actors = ''
$game_party.actors.each {|actor| actors +=
"#{actor.name}\nHunger: #{actor.hunger}\\#{actor.max_hunger}\n" +
"Thirst: #{actor.thirst}\\#{actor.max_thirst}\n\n"}
ht = "HungerTime: #{$game_party.time_hunger/40}\\#{SECS_HUNGER_DOWN}\n"
tt = "ThirstTime: #{$game_party.time_thirst/40}\\#{SECS_THIRST_DOWN}\n"
hs = "HungerStep: #{$game_party.steps}\\#{$game_party.step_hunger}\n"
ts = "ThirstStep: #{$game_party.steps}\\#{$game_party.step_thirst}\n"
print(sys + actors + ht + tt + hs + ts)
end
end
#-------------------------------------------------------------------------------
# ** Game_Actor
#-------------------------------------------------------------------------------
class Game_Actor < Game_Battler
attr_accessor :hunger
attr_accessor :max_hunger
attr_accessor :thirst
attr_accessor :max_thirst
alias zer0_hunger_setup setup
def setup(actor_id)
zer0_hunger_setup(actor_id)
@hunger = @max_hunger = Zer0::DEFAULT_HUNGER
@thirst = @max_thirst = Zer0::DEFAULT_THIRST
if Zer0::LVL_UP_INCREASE && @level > 1
increase = Zer0::LVL_UP_AMOUNT
@hunger = @max_hunger = (@level - 1) * increase + Zer0::DEFAULT_HUNGER
@thirst = @max_thirst = (@level - 1) * increase + Zer0::DEFAULT_THIRST
end
end
alias zer0_hunger_level_up exp=
def exp=(exp)
level = @level
zer0_hunger_level_up(exp)
if Zer0::LVL_UP_INCREASE && level != @level
lvls = @level - level
@max_hunger += (Zer0::LVL_UP_AMOUNT * lvls)
@max_thirst += (Zer0::LVL_UP_AMOUNT * lvls)
end
end
end
#-------------------------------------------------------------------------------
# ** Game_Battler
#-------------------------------------------------------------------------------
class Game_Battler
alias test item_effect
def item_effect(item)
food_item = false
hunger_plus = Zer0.food(item.id)
thirst_plus = Zer0.drink(item.id)
if hunger_plus != nil
if Zer0::RECOVER_BY_PERCENT
hunger_plus = (self.max_hunger * (hunger_plus * 0.01)).ceil
end
self.hunger += hunger_plus
self.hunger = [[self.hunger, self.max_hunger].min, 0].max
food_item = true
end
if thirst_plus != nil
if Zer0::RECOVER_BY_PERCENT
thirst_plus = (self.max_thirst * (thirst_plus * 0.01)).ceil
end
self.thirst += thirst_plus
self.thirst = [[self.thirst, self.max_thirst].min, 0].max
food_item = true
end
if food_item
states_plus(item.plus_state_set)
states_minus(item.minus_state_set)
return true
end
test(item)
end
end
#-------------------------------------------------------------------------------
# ** Game_Party
#-------------------------------------------------------------------------------
class Game_Party
attr_accessor :hunger
attr_accessor :time_hunger
attr_accessor :time_thirst
attr_accessor :step_hunger
attr_accessor :step_thirst
alias zer0_hunger_system_init initialize
def initialize
zer0_hunger_system_init
@hunger = true
@time_hunger = @time_thirst = 0
@step_hunger = Zer0::STEPS_HUNGER_DOWN
@step_thirst = Zer0::STEPS_THIRST_DOWN
end
def check_hunger_states
@actors.each {|actor|
state_id = Zer0.hunger_states(actor.hunger)
actor.add_state(state_id) if state_id != nil}
end
def check_thirst_states
@actors.each {|actor|
state_id = Zer0.thirst_states(actor.thirst)
actor.add_state(state_id) if state_id != nil}
end
end
#-------------------------------------------------------------------------------
# ** Scene_Map
#-------------------------------------------------------------------------------
class Scene_Map
alias zer0_hunger_map_upd update
def update
zer0_hunger_map_upd
if $game_party.hunger
update_hunger
end
end
def update_hunger
if Zer0::BY_TIME
$game_party.time_hunger += 1
$game_party.time_thirst += 1
if $game_party.time_hunger == (Zer0::SECS_HUNGER_DOWN * 40)
$game_party.actors.each {|actor|
actor.hunger -= 1 unless actor.dead? || actor.hunger == 0}
$game_party.check_hunger_states
$game_party.time_hunger = 0
end
if $game_party.time_thirst == (Zer0::SECS_THIRST_DOWN * 40)
$game_party.actors.each {|actor|
actor.thirst -= 1 unless actor.dead? || actor.thirst == 0}
$game_party.check_thirst_states
$game_party.time_thirst = 0
end
end
if Zer0::BY_STEPS
if $game_party.steps == $game_party.step_hunger
$game_party.actors.each {|actor|
actor.hunger -= 1 unless actor.dead? || actor.hunger == 0}
$game_party.check_hunger_states
$game_party.step_hunger = $game_party.steps + Zer0::STEPS_HUNGER_DOWN
end
if $game_party.steps == $game_party.step_thirst
$game_party.actors.each {|actor|
actor.thirst -= 1 unless actor.dead? || actor.thirst == 0}
$game_party.check_thirst_states
$game_party.step_thirst = $game_party.steps + Zer0::STEPS_THIRST_DOWN
end
end
end
end
#===============================================================================
# ** Hunger_HUD
#===============================================================================
class Hunger_HUD < Window_Base
#====================================================================#
# BEGIN CONFIGURATION #
#====================================================================#
# Define the colors used for each of the bars.
HUNGER_EMPTY = Color.new(255, 0, 0)
HUNGER_FULL = Color.new(0, 255, 0)
THIRST_EMPTY = Color.new(96, 96, 96)
THIRST_FULL = Color.new(128, 128, 255)
BACKGROUND_COLOR = Color.new(0, 0, 0)
# Define the type of bar used. (0 = Gradient, 1 = Transitional)
# It would take longer to explain the differences than to just try each out.
# There's only two as of the moment.
BAR_STYLE = 0
# Define the width and height, in pixels, of the bars.
BAR_WIDTH = 100
BAR_HEIGHT = 14
#====================================================================#
# END CONFIGURATION #
#====================================================================#
def initialize(y = -12)
super(0, y, 640, 96)
# Set the windowskin's opacity to 0.
self.windowskin = nil
@colors1 = [HUNGER_EMPTY, HUNGER_FULL, BACKGROUND_COLOR]
@colors2 = [THIRST_EMPTY, THIRST_FULL, BACKGROUND_COLOR]
@actors = $game_party.actors
@stats = stats
refresh
end
def refresh
# Dispose the contents of the HUD.
if self.contents != nil
self.contents.dispose
self.contents = nil
end
# Adjust width and location of window.
self.width = @actors.size * (BAR_WIDTH + 48)
self.x = (640 - self.width) / 2
self.contents = Bitmap.new(self.width, self.height)
# Iterate actors.
@actors.each_index {|i|
actor = @actors[i]
# Calculate locations for each actor's bars.
x = i * (BAR_WIDTH + 48)
# Draw actor's name.
self.contents.font.size = 16
self.contents.draw_text(x, 0, BAR_WIDTH, 16, actor.name)
# Draw hunger bars.
w, h, rate, max = BAR_WIDTH, BAR_HEIGHT, @stats[i][0], @stats[i][1]
self.contents.draw_bar(x, 16, w, h, rate, max, BAR_STYLE, @colors1)
# Draw thirst bars.
rate, max, height = @stats[i][2], @stats[i][3], 16+BAR_HEIGHT+4
self.contents.draw_bar(x, height, w, h, rate, max, BAR_STYLE, @colors2)
}
end
def stats
return @actors.collect {|a| [a.hunger, a.max_hunger, a.thirst, a.max_thirst]}
end
def update
if (@stats != stats) || (@actors != $game_party.actors)
@stats, @actors = stats, $game_party.actors
refresh
end
end
end
#===============================================================================
# ** Gradient_Bar
#===============================================================================
class Bitmap
def draw_bar(x, y, w, h, rate, max, style, colors = nil)
# Set required instance variables.
@bar_rect = Rect.new(x, y, w, h)
@rate, @max, @style, @colors = rate, max, style, colors
# Define default colors if not defined. (RED <--> GREEN)
if @colors == nil
@colors = [Color.new(255, 0, 0), Color.new(0, 255, 0), Color.new(0, 0, 0)]
end
# Draw the background color.
self.fill_rect(@bar_rect, @colors[2])
# Branch by what style is being used.
case @style
when 0 then gradient
when 1 then transition
end
end
#-------------------------------------------------------------------------------
def gradient
# Get the bar from the cache.
key = [@style, @bar_rect.width-2, @bar_rect.height-2, @colors[0], @colors[1]]
bar = RPG::Cache.gradient_bar(*key)
# Draw the gradient bar using rectangular transfer.
rect = Rect.new(0, 0, fill_width, @bar_rect.height)
self.blt(@bar_rect.x+1, @bar_rect.y+1, bar, rect)
end
#-------------------------------------------------------------------------------
def transition
# Returns the color for current rate.
c1 = [@colors[0].red, @colors[0].green, @colors[0].blue, @colors[0].alpha]
c2 = [@colors[1].red, @colors[1].green, @colors[1].blue, @colors[1].alpha]
rgba, rate = [], 1 - (@rate.to_f / @max)
c1.each_index {|i| rgba[i] = c2[i] - ((c2[i] - c1[i]) * rate) }
# Set the bars fill rate and color depending on value.
rect = Rect.new(@bar_rect.x+1, @bar_rect.y+1, fill_width, @bar_rect.height-2)
self.fill_rect(rect, Color.new(*rgba))
end
#-------------------------------------------------------------------------------
def fill_width
# Calculate the difference, in percentage, of the min and max rates.
return ((@rate / @max.to_f) * (@bar_rect.width - 2)).round
end
#-------------------------------------------------------------------------------
end
#===============================================================================
# ** Scene_Map
#===============================================================================
class Scene_Map
alias zer0_hunger_hud_main main
def main
# Add the bars to Scene_Map.
@hunger_hud = Hunger_HUD.new
@hunger_hud.x = 5
@hunger_hud.y = 400
zer0_hunger_hud_main
@hunger_hud.dispose unless @hunger_hud.disposed? || @hunger_hud == nil
end
alias zer0_hunger_hud_upd update
def update
# Update the bars as needed.
@hunger_hud.update
zer0_hunger_hud_upd
end
end
#===============================================================================
# ** RPG::Cache
#===============================================================================
module RPG::Cache
def self.gradient_bar(style, width, height, color1, color2)
# Create a unique key to call the bar back with.
path = [style, width, height, color1, color2]
# Check if cache already has bitmap defined, if not create it now.
if !@cache.include?(path) || @cache[path].disposed?
bitmap, rates = Bitmap.new(width, height), []
# Iterate through each pixel horizontally, setting a gradient color.
c1 = [color1.red, color1.green, color1.blue, color1.alpha]
c2 = [color2.red, color2.green, color2.blue, color2.alpha]
# Draw the bar, having in transition from the first color to the second.
c1.each_index {|i| rates[i] = (c1[i] - c2[i]).to_f / width }
(0...width).each {|i|
values = [0, 1, 2, 3].collect {|j| c1[j] - (i * rates[j]) }
# Set the color incrementally. This will be used later.
bitmap.fill_rect(i, 0, 1, height, Color.new(*values))
}
@cache[path] = bitmap
end
# Return the created bitmap.
return @cache[path]
end
end
class Hunger_HUD < Window_Base
def refresh
# Dispose the contents of the HUD.
if self.contents != nil
self.contents.dispose
self.contents = nil
end
# Adjust width and location of window.
self.width = @actors.size * (BAR_WIDTH + 48)
self.x = (640 - self.width) / 2
self.contents = Bitmap.new(self.width, self.height)
# Iterate actors.
@actors.each_index {|i|
actor = @actors[i]
# Calculate locations for each actor's bars.
x = i * (BAR_WIDTH + 48)
# self.contents.font.size = 16
# self.contents.font.color = Color.new(255,255,255,255)
# self.contents.font.bold = false
# self.contents.font.italic = false
# self.contents.draw_text(x, 0, BAR_WIDTH, 16, actor.name)
self.contents.font.size = 15
self.contents.font.color = Color.new(255,255,255,255)
self.contents.font.bold = true
self.contents.font.italic = false
# Draw hunger bars.
w, h, rate, max = BAR_WIDTH, BAR_HEIGHT, @stats[i][0], @stats[i][1]
self.contents.draw_bar(x, 16, w, h, rate, max, BAR_STYLE, @colors1)
self.contents.draw_text(x+4, 16 - 1 , BAR_WIDTH, 16, 'Hunger')
# Draw thirst bars.
rate, max, height = @stats[i][2], @stats[i][3], 16+BAR_HEIGHT+4
self.contents.draw_bar(x, height, w, h, rate, max, BAR_STYLE, @colors2)
self.contents.draw_text(x+4, height - 1, BAR_WIDTH, 16, 'Thirst')
}
end
end
Sorry that I'm so noobish at RGSS, but I try to do so much as I can. (I did change some settings, so the bars would look nicer. But they shouldn't have effects on the rest of the script, I think.)