# # file:: room.rb # author:: Jon A. Lambert # version:: 2.10.0 # date:: 06/25/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 'network/protocol/mxpcodes' require 'core/gameobject' require 'core/spawn' require 'gettext' # The Room class is the mother of all rooms. # class Room < GameObject property :exits, :spawns logger 'DEBUG' include GetText include MXPCodes bindtextdomain("core") # Create a new Room object # [+name+] The displayed name of the room # [+owner+] The owner id of this room # [+return+] A handle to the new Room. def initialize(name, owner) super(name, owner) self.exits=[] # The list of exits for this room. self.spawns=[] # Objects to spawn here end # Resets a room # Removes stale entries that can come from shutting down the server def reset # Remove any stale user accounts contents.each do |oid| o = get_object(oid) if o.is_a? Character and not o.account and not o.kind_of? Mobile log.info "Purging stale contents #{oid} from Room #{id}." contents.delete oid end end end # Lists the characters in the room # [+notid+] Optional id of who not to return # [+return+] Array of character objects def characters(notid=nil) ppl = [] contents.each do |oid| o = get_object(oid) if o.kind_of? Character if notid ppl << o if not notid == oid else ppl << o end end end ppl end # Sends a message to all characters in a room # [+msg+] Message to broadcast # [+notid+] Optional person to leave out of the broadcast def say(msg, notid=nil) if not msg.is_a? Msg msg = Msg.new(msg) msg.broadcast = true end if notid characters(notid).each do |x| add_event(id,x.id,:show, msg) if x.account and x.cansee? end else characters.each do |x| add_event(id,x.id,:show, msg) if x.account and x.cansee? end end end # Sends a message to the "rest" of the players in the room except # for notid1 and notid2 # [+msg+] Message to display # [+notid1+] First person to skip # [+notid2+] Second person to skip def sayrest(msg, notid1, notid2) characters(notid1).each do |x| add_event(id,x.id,:show, msg) if x.account and x.cansee? and not x.id == notid2 end end # Get the MP cost to move through this room via the modifier # [+return+] cost in MP to move through this room def mpcost cost = 1 cost += get_modifier("mp").abs cost end # Searches current room for an object by name # [+obj+] object name to serach for. Supports 2.obj, etc. # [+return+] an array of objects that match that obj name def find_objects(what) objs = [] nth = 1 found = 0 if what=~/^(\d+)\.(.*)/ nth = $1.to_i what = $2 elsif what=~/^all\.(.*)/ nth = nil what = $1 end objects.each do |o| 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 # Returns if the room is dark # [+return+] true if room is dark def is_dark? return false if has_attribute? :bright return true if has_attribute? :dark return true if world.climate.night and not has_attribute? :inside false end # Event :describe # [+e+] The event # [+return+] Undefined def describe(e) msg = "[COLOR Green]" if world.can_build? e.from msg << "(#{id.to_s})" msg << "[#{mpcost}]" if mpcost > 1 msg << " " if spawns msg << "*" if spawns.size > 0 end end msg << mxptag("RName") + name + mxptag("/RName") if attributes msg << " #{attributes.inspect}" if world.can_build? e.from and attributes.size > 0 end msg << "[/COLOR]\n" if get_object(e.from).cansee? :dark msg << mxptag("RDesc") + desc + mxptag("/RDesc") + "\n" else msg << _("It is dark.\n") end add_event(id,e.from,:show,msg) end # Event :describe_exits # [+e+] The event # [+return+] Undefined def describe_exits(e) msg = "[COLOR Red]" + _("Exits:") +"\n" s = exits.size if s == 0 msg << _("None.")+"[/COLOR]" else i = 0 exits.each do |exid| ex = get_object(exid) key = ex.name.split(/;/).first msg << mxptag("Ex") + key + mxptag("/Ex") i += 1 case s - i when 1 then s > 2 ? msg << "," + _(" and ") : msg << _(" and ") when 0 then msg << "." else msg << ", " end end msg << "[/COLOR]" end add_event(id,e.from,:show,msg) end # Event :spawn # [+e+] Event to spawn all pending objects # [+return+] Undefined def spawn(e) spawns.each do |s| spawnobj = get_object(s) # Check to make sure you dont exceed the max_in_room value in_room = 0 contents.each do |oid| obj = get_object(oid) in_room += 1 if obj.id == spawnobj.targetid if obj.parentid in_room += 1 if obj.parentid == spawnobj.targetid end end if in_room < spawnobj.max_in_room o = spawnobj.load if o o.location = id case o when Mobile add_event(id, id, :arrive,o.id) else add_contents(o.id) end end end end end # Event :arrive # [+e+] The event # [+return+] Undefined def arrive(e) ch = get_object(e.msg) # add character add_contents(ch.id) if not contents.include? ch.id ch.location = id infectguard = nil # While we are parsing through players check for special players characters(e.msg).each do |x| msg = Msg.new _("^p1 has arrived.") msg.p1 = ch.name msg.is_invisible = true if ch.has_attribute? :invisible add_event(id,x.id,:show,msg) infectguard = x if x.has_attribute? :infect_guard end # Check if the person is infected and it is an infect_guard location if ch.has_attribute? :infected and infectguard ch.sendroom _("%{guard} scans %{name}'s eye then a siren sounds, \"INFECTED! INFECTED!\"" % {:guard => infectguard.name, :name => ch.name}) ch.sendto _("%{guard}, at point blank range, blows off your head!!" % {:guard => infectguard.name}) ch.sendrest( _("%{guard} unloads his weapon and blows off %{name}'s head!" % {:guard => infectguard.name, :name => ch.name}), ch.id) ch.make_corpse return end # If player is holding a light that requires power use it. light = ch.has_light? if light if light.has_val? :powered_from and light.respond_to? "use_power" left = light.use_power if left == 1 ch.sendto _("Your %{light} flickers." % {:light => light.name}) elsif left == 0 # Check to make sure there are not alternate fuels stored too if not light.has_power? # Nope, that was it...die ch.sendto _("Your %{light} flickers and dies." % {:light => light.name}) msg = Msg.new("^p1 %{light} flickers and dies." % {:light => light.name}) msg.p1 = ch.name add_event(ch.id, ch.id, :roomsay, msg) end end end end ch.parse('look') if ch.account end # Event :dig # [+e+] Event # [+return+] Undefined def dig(e) ch = get_object(e.from) dig_cost = 3 dig_cost = 0 if world.can_build? ch.id if ch.stats[:mp]-dig_cost > 0 ch.stats[:mp] -= dig_cost objects.each do |o| if o.has_attribute? :buried o.del_attribute(:buried) chmsg = Msg.new _("You dig up ^o1!") chmsg.o1 = o.shortname add_event(id,e.from,:show,chmsg) rmsg = Msg.new _("^p1 digs up ^o1!") rmsg.p1 = ch.name rmsg.o1 = o.shortname add_event(e.from,e.from,:roomsay,rmsg) end end else add_event(id,e.from,:show, _("You are too exhausted to dig right now.")) end end end