# # 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