# Mobile class # Author: Craig Smith # This class is the base class of NPCs. # 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 'core/body' require 'storage/properties' class Mobile < Character include GetText bindtextdomain("core") property :gender logger 'DEBUG' def initialize(name, owner, location=nil) super(name, owner, location) self.gender = nil # Non descript end # Parse wrapper. Currently does nothing but useful for debugging def parse(args) #log.info "Mobile command: #{name} - #{args}" super(args) end # Call parent reset() def reset super(true) @body.wearing.each do |oid| @body.wearing.delete oid o = get_object(oid) o.unused = true o.location = nil end @body.wielding?.each do |oid| @body.unwield(oid) o = get_object(oid) o.unused = true o.location = nil end contents.clear if parentid self.stats.clear self.attributes.clear self.val.clear self.modifier.clear parent = get_object(parentid) parent.stats.each { |key, val| set_stat(key, val) } parent.attributes.each { |at| add_attribute(at) } parent.val.each { |key, val| add_val(key, val) } parent.modifier.each { |key, val| add_modifier(key, val) } end end # Very simple kill recorder def add_kill(id) self.stats[:kills] += 1 end # :idle event # This is called by the world timer def idle(e) return if not location return if location == 0 room = get_object(location) recoverHP recoverMP recoverStunned if has_attribute? :zombie add_attribute :aggressive if not has_attribute? :aggressive target = find_zombie_victim else target = attack_nearby manage_infections end # What to do when fighting if @position == :fighting if has_attribute? :wimpy and not has_attribute? :zombie min = (get_stat(:maxhp) * 0.1).to_i min = 10 if min < 10 flee if health <= min end # No idle commands, focus on fighting return end # Looking for a fight? if target kill_id(target) else # Scavengers - junk stuff too if has_attribute? :scavenger and rand(3) == 0 and contents.size > 0 items = [] contents.each { |oid| items << oid if get_object(oid).cost == 0 } if items.size > 0 itemid = items[rand(items.size)] item = get_object(itemid).name parse(_("junk %{obj}" % {:obj => item})) end end # Scavenge more if has_attribute? :scavenger and rand(3) == 0 items = [] room.contents.each { |oid| items << oid if not get_object(oid).has_attribute? :fixed } if items.size > 0 itemid = items[rand(items.size)] item = get_object(itemid).name parse(_("get %{obj}" % {:obj => item})) return end end # 1 in 10 chance of trying to leave the room move if not has_attribute? :fixed and rand(10) > 8 end end # Move in a random direction def move if dirhint ex = get_object(dirhint) self.dirhint = nil if ex parse(ex.name) return end end room = get_object(location) if room.exits.size > 0 dir = room.exits[rand(room.exits.size)] parse(get_object(dir).name) end end # If mobile is aggressive it will attack somebody nearby that is not # of the same type # [+return+] id of person to attack if one is found def attack_nearby # Must have an aggressive attribute of some type return nil if not has_attribute? :aggressive and not has_attribute? :guard and not has_attribute? :infect_guard return nil if @position == :fighting victim_needs_light = false victim_needs_light = true if not cansee? :dark get_object(location).characters(id).each do |ch| if not world.can_build? ch.id # Never attack builders/admins if has_attribute? :aggressive if not ch.is_a? Mobile if not cansee? :dark return ch.id if ch.has_light? end if ch.has_attribute? :invisible return ch.id if cansee? :invisible end return ch.id end elsif has_attribute? :infect_guard return ch.id if ch.has_attribute? :infected elsif has_attribute? :guard return ch.id if ch.has_attribute? :PK or ch.position == :fighting end end # End never attack gods end nil end # Attack target id # [+tid+] Character id to attack def kill_id(tid) target = get_object(tid) # Infect guards vs. infected == instant kill if has_attribute?(:infect_guard) and target.has_attribute?(:infected) sendroom _("%{guard} scans %{name}'s eye then a siren sounds, \"INFECTED! INFECTED!\"" % {:guard => name, :name => target.name}) target.sendto _("%{guard}, at point blank range, blows off your head!!" % {:guard => name}) sendrest( _("%{guard} unloads his weapon and blows off %{name}'s head!" % {:guard => name, :name => target.name}), target.id) target.make_corpse else sendroom _("%{attacker} shouts, \"%{name} is a player killer!!\"" % {:attacker => name, :name => target.name}) if has_attribute?(:guard) and target.has_attribute? :PK sendroom _("%{attacker} shouts, \"Hey! No fighting!!\"" % {:attacker => name}) if has_attribute?(:guard) and target.position == :fighting parse(_("kill %{name}" % {:name => target.name})) end end # Flee from a fight def flee parse(_("flee")) end end