# Merchant class # 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 'core/body' require 'storage/properties' class Merchant < Mobile include GetText bindtextdomain("core") logger 'DEBUG' MAX_MERCHANT_INV = 10 property :forsale, :buytype, :buyattribute, :buydtype, :markup def initialize(name, owner, location=nil) super(name, owner, location) self.forsale = [] # Oids that merchant will have an unlimited supply of self.buytype = [] # Object types that merchant will only buy self.buyattribute = [] # Only buy objects with specified attributes self.buydtype = [] # Buy only weapons of these damage types self.markup = 0.20 # Markup percentage end # Event :list # List the items for sale # e.from = person requesting list def list(e) return if has_attribute? :zombie items = {} msg = _("----[ %{name}'s Items for Sale ]-------------------\n" % {:name => name}) msg += sprintf("%-10s %-25s %s\n", _("Amount"),_("Item"), _("Cost")) msg << mxptag("StoreList") forsale.each do |oid| obj = get_object(oid) price = obj.cost + (obj.cost * markup).to_i imsg = sprintf("%-10s %-25s $%d\n", _("unlimited"),obj.shortname, price) msg += mxptag("Buy '#{obj.name}' '#{name}'") + imsg + mxptag("/Buy") end # Group items together contents.each do |oid| obj = get_object(oid) if obj.parentid haveid = obj.parentid else haveid = obj.id end if not forsale.include? haveid if items.has_key? haveid items[haveid] += 1 else items[haveid] = 1 end end end items.each do |oid, count| obj = get_object(oid) price = obj.cost + (obj.cost * markup).to_i imsg = sprintf("%-10s %-25s $%d\n", "[#{count}]",obj.shortname, price) msg += mxptag("Buy '#{obj.name}' '#{name}'") + imsg + mxptag("/Buy") end msg << mxptag("/StoreList") msg << "--------------------------------[End of List]----\n" add_event(id, e.from, :show, msg) end # Check if merchant would by that item # [+oid+] Oid to check to see if merchant will buy # [+return+] True if they will buy that item def willbuy(oid) return false if has_attribute? :no_buy obj = get_object(oid) # At least one of these must match if buytype.size > 0 typematch = false buytype.each do |btype| typematch = true if obj.class.to_s == btype end else typematch = true end if buyattribute.size > 0 attrmatch = false buyattribute.each do |battr| attrmatch = true if obj.has_attribute? battr attrmatch = true if obj.has_val? battr end else attrmatch = true end if buydtype.size > 0 dtypematch = false buydtype.each do |dtype| # If the dtype is specified as bludgeon then allow any dtypematch = true if obj.has_attribute? dtype or dtype == "bludgeon" end else dtypematch = true end typematch and attrmatch and dtypematch end # [+objid+] Object to see how many we are carrying # [+return+] number of items fo that type def totalobjs(objid) o = get_object(objid) objid = o.parentid if o.parentid cnt = 0 contents.each do |oid| cobj = get_object(oid) cnt += 1 if cobj.id == objid if cobj.parentid cnt += 1 if cobj.parentid == objid end end cnt end # Event :offer # Ask merchant to make an offer on an item # [+e+] e.from = requester, e.msg = oid to make offer on def offer(e) return if has_attribute? :zombie obj = get_object(e.msg) return if not obj if not willbuy(obj.id) msg = _("Sorry, but I won't buy that.") add_event(id, e.from, :show, msg) return end if totalobjs(obj.id) > MAX_MERCHANT_INV msg = _("Sorry but I have too many of those.") add_event(id, e.from, :show, msg) return end price = obj.cost - (obj.cost * markup).to_i if price > 0 msg = _("I will give you $%{price} for that." % {:price => price}) add_event(id, e.from, :show, msg) else msg = _("That's is not worth anything to me.") add_event(id, e.from, :show, msg) end end # Event :buy # Seems backwards but this is when a merchant SELLS something and a player buys # [+e+] e.from = buyer, e.msg = object name def buy(e) return if has_attribute? :zombie ch = get_object(e.from) oname = e.msg if oname.size < 1 ch.sendto _("Buy what?") return end # First we check out contents tobuy = nil have = false contents.each do |oid| obj = get_object(oid) if obj.name =~/#{oname}/i tobuy = obj have = true end end # Didn't find anything in contents see if it is something we always sell if not have forsale.each do |oid| obj = get_object(oid) if obj.name =~/#{oname}/i tobuy = obj end end end if not tobuy msg = _("I do not have that item for sale.") add_event(id, ch.id, :show, msg) else price = tobuy.cost + (tobuy.cost * markup) if ch.get_stat(:cash) < price msg = _("You do not have enough money.") add_event(id, ch.id, :show, msg) else ch.adjust_stat(:cash, -price.to_i) msg = _("That will be $%{cost}." % {:cost => price.to_i}) add_event(id, ch.id, :show, msg) if not have # We need to load a new object tobuy = world.load_object(tobuy.id) tobuy.location = id tobuy.reset if tobuy.respond_to? "reset" add_contents(tobuy.id) end add_event(id, ch.id, :give, tobuy.id) end end end # Event :sell # Seems backwards but this is when a merchant BUYS something and the player sells it # [+e+] e.from = seller, e.msg = oid of object to sell def sell(e) return if has_attribute? :zombie ch = get_object(e.from) obj = get_object(e.msg) if willbuy(obj.id) if totalobjs(obj.id) <= MAX_MERCHANT_INV price = obj.cost - (obj.cost * markup) ch.adjust_stat(:cash, price.to_i) msg = _("%{name} gives you $%{cost}." % {:name => name, :cost => price.to_i}) add_event(id, ch.id, :show, msg) add_event(ch.id, id, :give, obj.id) else msg = _("I have too many of those.") add_event(id, ch.id, :show, msg) end else msg = _("I do not want that.") add_event(id, ch.id, :show, msg) end end end