#
# file:: container.rb
# Author: Craig Smith
# This source code copyright (C) 2009 Craig Smith
# All rights reserved.
#
# Released under the terms of the TeensyMUD Public License
# See LICENSE file for additional information.
#
$:.unshift "lib" if !$:.include? "lib"
require 'gettext'
require 'core/gameobject'
require 'storage/properties'
# This is the base container class
#
class Container < GameObject
include GetText
bindtextdomain("core")
logger 'DEBUG'
CONT_DEFAULT_MAX_AMT=50
CONT_DEFAULT_MAX_WEIGHT=200
property :types, :liq_amt, :initial_weight
# Create a new Container object
# [+name+] The displayed name of the Container.
# [+return+] A handle to the new Container.
def initialize(name, owner, location=nil)
super(name, owner, location)
self.liq_amt = 0 # Amount of liquid stored
self.types = [] # types of other Containers or objects
# this Container can hold (e.g
self.initial_weight = 1
end
# Reset runs when object first loads
def reset
self.liq_amt = 0
contents.each { |oid| get_object(oid).unused = true }
self.contents.clear
# Some items come pre-filled with liquid (Like drinks)
if has_val? :filled_with
liq = get_object(has_val?(:filled_with))
if liq.is_a? Liquid
if has_val? :max_amt
self.liq_amt = has_val? :max_amt
else
self.liq_amt = CONT_DEFAULT_MAX_AMT
end
add_contents(liq.id)
end
end
end
# Adds an item type
# [+type+] The string of the Class allowed
def add_type(type)
self.types << type if not types.include? type
end
# Deletes an item type
# [+type+] The string of the class to delete
def del_type(type)
self.types.delete(type) if types.include? type
end
# Checks if container can hold this type
# [+type+] Class as string. If types is empty always returns true
def has_type?(type)
types.include? type
end
# No container can weigh 0..this prevent infinite recursion
# [+return+] total weight of contents
def weight
# If an initial weight is specified add that
if initial_weight
amt = initial_weight
else
amt = 1
end
contents.each do |oid|
amt += get_object(oid).weight
end
amt
end
# If container has value of powered_from checks if cont has power src
# [+amt+] Amount of power requested
# [+return+] Returns true if object has power to operate
def has_power?(amt=1)
return true if not has_val? :powered_from
power = get_object(has_val?(:powered_from))
if power
if power.is_a? Liquid
has_proper_liquid = false
contents.each do |oid|
has_proper_liquid = true if oid == power.id
end
return false if not has_proper_liquid
return true if liq_amt - amt >= 0
return false
elsif power.is_a? Battery
battery = nil
# Any battery will do
contents.each do |oid|
obj = get_object(oid)
battery = obj if obj.is_a? Battery
end
return false if not battery
return true if battery.has_val?(:current_charge) - amt >= 0
return false
else
log.info "Unknown power source for #{power.name}"
return false
end
end
false
end
# Simple emthod to return the value of :powered_from
# [+return+] Nil if no power requirement, else oid of power req.
def power_requirement
has_val? :powered_from
end
# Drains power
# [+amt+] Amount to drain
# [+return+] amount left
def use_power(amt=1)
return false if not has_power? amt
req = get_object(power_requirement)
return false if not req
remaining = 0
if req.is_a? Liquid
self.liq_amt -= amt
if liq_amt <= 0
self.liq_amt = 0
self.contents.clear
end
remaining = liq_amt
elsif req.is_a? Battery
battery = nil
contents.each do |oid|
obj = get_object(oid)
# Any Battery will do
battery = obj if obj.is_a? Battery
end
return 0 if not battery
charge = battery.has_val? :current_charge
charge -= amt
if charge <= 0
battery.add_val(:current_charge, 0)
battery.unused = true
self.contents.delete(battery.id)
else
battery.add_val(:current_charge, charge)
end
remaining = battery.has_val? :current_charge
else
log.info "use_power() called with unknown power requirment"
end
remaining
end
# Check the Container to see if it can contain
# a specific type of item or anything at all
# [+oid+] Object id to check if container can hold it
# [+return+] Boolean
def can_hold? oid
o = get_object(oid)
supported_type = false
if types.size == 0
supported_type = true
else
supported_type = has_type? o.class.to_s
end
if supported_type
# This object can hold that type.
maxamt = CONT_DEFAULT_MAX_AMT
maxweight = CONT_DEFAULT_MAX_WEIGHT
maxamt = val["max_amt"] if has_val? :max_amt
maxweight = val["max_weight"] if has_val? :max_weight
if has_type? "Liquid"
container_size = liq_amt
else
container_size = contents.size
end
if container_size < maxamt and weight+o.weight < maxweight
# Object is within amount and weight limits
return true
end
end
false
end
# Case insensitive search of inventory. Supports 2.obj and all.obj syntax
# [+what+] name of obj in inventory
# [+return+] Array of matching objects
def find(what)
objs = []
nth = 1
found = 0
if what=~/^(\d+)\.(.*)/
nth = $1.to_i
what = $2
elsif what=~/^all\.(.*)/
nth = nil
what = $1
end
contents.each do |oid|
o = get_object(oid)
gotname = false
if o.name =~/^#{what}$/i
gotname = true
elsif o.aliases.size > 0
o.aliases.each do |a|
gotname = true if a=~/^#{what}$/
end
end
if gotname
found += 1
if not nth
objs << o
elsif found == nth
objs << o
end
end
end
objs
end
# Event :describe_contents
# [+e+] Event data
# [+return+] Undefined
def describe_contents(e)
ch = get_object(e.from)
if contents.size < 1
add_event(id, ch.id, :show, "It is empty.")
else
if liq_amt > 0
maxamt = CONT_DEFAULT_MAX_AMT
maxamt = val["max_amt"] if has_val? :max_amt
half = maxamt * 0.5
liq = get_object(contents[0])
if liq_amt == maxamt
add_event(id, ch.id, :show, _("It is full of %{liq}" % {:liq => liq.name}))
elsif liq_amt >= half
add_event(id, ch.id, :show, _("It is over half full of %{liq}" % {:liq => liq.name}))
else
add_event(id, ch.id, :show, _("It has some %{liq} in it." % {:liq => liq.name}))
end
else
contents.each do |oid|
obj = get_object(oid)
if obj
add_event(oid, ch.id, :show, "#{obj.shortname}")
else
log.error "Contents of #{id} contained oid of #{oid} that was not an object"
end
end
end
end
end
# Event :put
# [+e+] Event data. e.from == ch, e.msg == item to place
# [+return+] undefined
def put(e)
ch = get_object(e.from)
what = get_object(e.msg)
if can_hold? what.id
ch.delete_contents(what.id)
self.add_contents(what.id)
what.location = id
add_event(id, ch.id, :show, "You put #{what.shortname} in the #{name}")
add_event(id, ch.id, :roomsay, "#{ch.name} puts #{what.shortname} in #{shortname}")
else
add_event(id, ch.id, :show, "You can not fit that in there.")
end
end
end