#
# file:: gameobject.rb
# author:: Jon A. Lambert
# version:: 2.8.0
# date:: 01/19/2006
#
# Additional Contributor: Craig Smith
#
# This source code copyright (C) 2005, 2006 by Jon A. Lambert
# All rights reserved.
#
# Released under the terms of the TeensyMUD Public License
# See LICENSE file for additional information.
#
$:.unshift "lib" if !$:.include? "lib"
$:.unshift "vendor" if !$:.include? "vendor"
require 'gettext'
require 'network/protocol/mxpcodes'
require 'utility/log'
require 'core/root'
# The GameObject class is no longer the mother of all objects.
#
class GameObject < Root
property :location, :contents, :triggers, :msgfail, :msgsucc, :attributes, :val, :cost, :weight, :aliases, :modifier
include MXPCodes
include GetText
bindtextdomain("core")
logger 'DEBUG'
# Create a new Object
# [+name+] Every object needs a name
# [+owner+] The owner id of this object
# [+location+] The object id containing this object or nil.
# [+return+] A handle to the new Object
def initialize(name, owner, location=nil)
super(name, owner)
self.location = location # The location of this object or nil if none
self.contents = []
self.triggers = {}
self.msgfail = ''
self.msgsucc = ''
self.attributes = []
self.val = {} # VALues specific to this type of object
self.cost = 0
self.weight = 0
self.aliases = []
self.modifier = {}
end
# add an attribute value
# [+key+] Key for the value
# [+value+] the actual value of that key
def add_val(key, value)
key = key.to_s if key.is_a? Symbol
val[key] = value
end
# deletes an attribute value
# [+key+] Key to delete
def del_val(key)
key = key.to_s if key.is_a? Symbol
val.delete(key) if val.has_key? key
end
# has key. If so returns the value
# [+key+] Key to check for
# [+return+] returns the value if exists else nil
def has_val? key
key = key.to_s if key.is_a? Symbol
return nil if val == nil
return nil if not val.has_key? key
val[key]
end
# Add an attribute
# [+strattr+] String attribute to add
def add_attribute(strattr)
strattr = strattr.to_s if strattr.is_a? Symbol
attributes << strattr if !attributes.include? strattr
end
# Delete an attribute
# [+strattr+] String attribute to delete
def del_attribute(strattr)
strattr = strattr.to_s if strattr.is_a? Symbol
attributes.delete(strattr)
end
# Checks if object has a set attribute
# [+strattr+] String attribute to check for
# [+return+] true or false
def has_attribute? strattr
return false if attributes == nil
strattr = strattr.to_s if strattr.is_a? Symbol
attributes.include? strattr
end
# Toggles attributes on and off
# [+strattr+] String attribute to toggle
# [+return+] Undefined
def toggle_attribute(strattr)
if has_attribute? strattr
del_attribute(strattr)
else
add_attribute(strattr)
end
end
# Adds a new modifier
# [+key+] Key for modifier, Eg: MP, HP, etc.
# [+value+] number of what to add/subtract
# [+return+] Undefined
def add_modifier(key,val)
key = key.to_s if key.is_a? Symbol
val = val.to_i if val.is_a? String
self.modifier[key] = val
end
# Deletes a modifier
# [+key+] key to delete, Eg: MP, HP, etc.
# [+return+] Undefiened
def del_modifier(key)
key = key.to_s if key.is_a? Symbol
self.modifier.delete(key) if has_modifier?(key)
end
# [+key+] Key to check for in modifier
# [+return+] True of object has key in modifier
def has_modifier?(key)
return false if not self.modifier
key = key.to_s if key.is_a? Symbol
modifier.has_key? key
end
# Returns the given modifier
# [+key+] To to retrieve, Eg: MP, HP, etc
# [+return+] Numeric modifier or 0 if none
def get_modifier(key)
key = key.to_s if key.is_a? Symbol
return modifier[key] if has_modifier? key
0
end
# Add an object to the contents of this object
# [+oid+] The object id to add
def add_contents(oid)
if contents.include? oid
log.error "Object #{oid} already in contents of #{id}"
else
contents << oid
end
end
# Deletes an object from the contents of this object
# [+oid+] The object id to delete
def delete_contents(oid)
d = contents.delete(oid)
if d.nil?
log.error "Object #{oid} not in contents of #{id}"
end
d
end
# Returns the contents of the object
# [+return+] An array of object ids
def get_contents
contents || []
end
# Add a trigger script to this object
# [+s+] The script to add
def add_trigger(event, sid)
event = event.intern if event.respond_to?(:to_str)
triggers[event] = sid
end
# Deletes a trigger script from this object
# [+event+] The trigger event type to delete
def delete_trigger(event)
event = event.intern if event.respond_to?(:to_str)
triggers.delete(event)
end
# Returns a specific trigger script from the object
# [+event+] The trigger event type to retrieve
# [+return+] A trigger or nil
def get_trigger(event)
event = event.intern if event.respond_to?(:to_str)
triggers[event]
end
# Returns the trigger scripts on the object
# [+return+] An array of trigger scripts
def get_triggers
triggers.values
end
# Finds all objects contained in this object
# [+return+] Handle to a array of the objects.
def objects
objs = []
contents.each do |oid|
o = get_object(oid)
case o
when Spawn, Character, Account, Liquid
nil
when GameObject
objs << o
when nil, ""
log.error "nil object found with oid of #{oid}. You might need to add the object to engine.rb"
else
nil
end
end
objs
end
# Finds all the characters contained in this object except the passed character.
# [+exempt+] The character id exempted from the list.
# [+return+] Handle to a list of the Character objects.
def characters(exempt=nil)
ary = contents.collect do |oid|
o = get_object(oid)
(o.class == Character && oid != exempt && o.account) ? o : nil
end
ary.compact
end
# Find all mobiles contained in this object
# [+return+] Handle to a list of mobile objects
def mobiles
ary = contents.collect do |oid|
o = get_object(oid)
(o.class == Mobile) ? o : nil
end
ary.compact
end
# Find players and NPCs mobiles alike
# [+exempt+] The character id exempted from the list
# [+return+] Handle to a list of the character objects
def people(exempt=nil)
chars = []
contents.each do |oid|
o = get_object(oid)
case o
when Mobile
chars << o if not o.id == exempt
when Character
chars << o if o.account and not o.id == exempt
end
end
chars
end
# Generic object reset. Resets flags and attribute values if object is a clone
def reset
if isclone and parentid
parent = get_object(parentid)
attributes = parent.attributes.dup
val = parent.val.dup
modifier = parent.modifier.dup
end
end
# All command input routed through here and parsed.
# [+m+] The input message to be parsed
# [+return+] false or true depending on whether command succeeded.
def parse(m)
# match legal command
m=~/([A-Za-z0-9_@?"'#!]+)(.*)/
cmd=$1
arg=$2
arg.strip! if arg
# look for a command from our table for objects
c = world.ocmds.find(cmd)
# there are three possibilities here
case c.size
when 0 # no commands found
false
when 1 # command found
return self.send(c[0].cmd, arg)
else # ambiguous command - tell luser about them.
false
end
end
# Returns a short name of an object
# [+return+] a shortname of an object. (ex. ball == a ball)
def shortname
return name if self.is_a? Character
# NOTE: This is very specific to english...maybe this should be redone
return name if name=~/^a[n]*\s/i or name=~/^the\s/i
return "an #{name}" if name=~ /^[aeiou]/i
"a #{name}"
end
# Event :describe
# [+e+] The event
# [+return+] Undefined
def describe(e)
ch = get_object(e.from)
msg = ""
msg << "[COLOR Yellow]"
msg << "(#{id}) " if ch.get_stat(:debugmode) == true
if has_attribute? :buried
if world.can_build? e.from
msg << "*#{shortname.capitalize} "
msg << _("is buried here.")
msg << "[/COLOR]"
else
msg = _("A mound of dirt.")
end
else
if has_val? :fountain
msg << mxptag("Fountain '#{name}' '#{shortname}'")
msg << _("%{item} is here." % {:item => shortname.ucfirst})
msg << mxptag("/Fountain") + "[/COLOR]"
else
msg << mxptag("GroundObj '#{name}' '#{shortname}'")
msg << _("%{item} is here." % {:item => shortname.ucfirst})
msg << mxptag("/GroundObj") + "[/COLOR]"
end
end
add_event(id,e.from,:show,msg) if msg
end
# Event :get
# [+e+] The event
# [+return+] Undefined
def get(e)
place = get_object(location)
if has_attribute? :fixed and not world.is_admin? e.from
if not place.owner == e.from or not world.can_build? e.from
add_event(id,e.from,:show, _("You can not pick up the %{obj}" % {:obj => name}))
return
end
end
if has_attribute? :buried
add_event(id,e.from,:show, _("You do not see that here."))
return
end
plyr = get_object(e.from)
if not plyr.can_carry?(weight)
add_event(id,e.from,:show, _("You are too encumbered to pick that up."))
return
end
from_cont = false
from_cont = true if place.kind_of? Container
if not place.kind_of? Room and not place.kind_of? Container
place = get_object(plyr.location)
end
# remove it
place.delete_contents(id)
# add it
plyr.add_contents(id)
self.location = plyr.id
if from_cont
add_event(id,e.from,:show, _("You get the %{obj} from %{place}." % {:obj => name, :place => place.shortname}))
add_event(e.from,e.from,:roomsay, _("%{person} gets %{obj} from %{place}" % {:person => plyr.name, :obj => shortname, :place => place.shortname}))
else
add_event(id,e.from,:show, _("You get the %{obj}" % {:obj => name}))
add_event(e.from,e.from,:roomsay, _("%{person} picks up %{obj}" % {:person => plyr.name, :obj => shortname}))
end
end
# Event :drop
# [+e+] The event
# [+return+] Undefined
def drop(e)
plyr = get_object(e.from)
place = get_object(plyr.location)
# remove it
plyr.delete_contents(id)
# add it
place.add_contents(id)
self.location = place.id
add_event(id,e.from,:show, _("You drop the %{obj}." % {:obj => name}))
add_event(e.from,e.from,:roomsay, _("%{person} drops %{obj}." % {:person => plyr.name, :obj => shortname}))
end
# Event :junk
# [+e+] The event
# [+return+] Undefined
def junk(e)
plyr = get_object(e.from)
plyr.delete_contents(id)
self.location = nil
self.unused = true
add_event(id,e.from,:show, _("You junk the %{obj}." % {:obj => name}))
add_event(e.from,e.from,:roomsay, _("%{person} junks %{obj}." % {:person => plyr.name, :obj => shortname}))
end
# Event :timer
# [+e+] The event
# [+return+] Undefined
def timer(e)
end
# Event :weathermsg (Called from world misc timer thread)
# [+e+] The event
# [+return+] Undefined
def weathermsg(e)
world.all_characters.each do |pid|
char = get_object(pid)
if char.account and char.cansee?
if not get_object(char.location).has_attribute? :inside
char.sendto("#{e.msg}")
end
end
end
end
# Event :delete
# [+e+] The event
# [+return+] Undefined
def delete(e)
plyr = get_object(e.from)
place = get_object(plyr.location)
# remove it
place.delete_contents(id)
delete_object(id)
self.location = nil
add_event(id,e.from,:show, _("You delete the %{obj}." % {:obj => name}))
end
# Event :bury
# [+e+] The event
# [+return+] Undefined
def bury(e)
ch = get_object(e.from)
bury_cost = 2
bury_cost = 0 if world.can_build? ch.id
if ch.stats[:mp]-bury_cost > 0
ch.delete_contents(id)
ch.stats[:mp] -= bury_cost
add_event(id,e.from,:show, _("You bury the %{obj}." % {:obj => name}))
add_event(e.from,e.from,:roomsay, _("%{person} buries %{obj}." % {:person => ch.name, :obj => shortname}))
self.add_attribute(:buried)
self.location = ch.location
get_object(ch.location).add_contents(id)
else
add_event(id,e.from,:show, _("You are too exhausted to dig right now."))
end
end
end