--- deliantra/server/ext/map_lib.ext 2008/04/21 06:35:26 1.6 +++ deliantra/server/ext/map_lib.ext 2010/03/22 18:16:38 1.9 @@ -13,6 +13,19 @@ for my $iob ($ob->inv) { rec_inv_by_slaying ($iob, $slaying, $cb) } } +=item count_linked ($map, $connected) + +Counts the number of objects with the connected value C<$connected> on +the map C<$map>. + +=cut + +sub count_linked { + my ($map, $connected) = @_; + my (@a) = $map->find_link ($connected); + scalar @a +} + =item object attachment: 'check_inventory_on_apply' This attachment checks on apply whether the applyer @@ -109,6 +122,103 @@ } }; + +=item object attachment: 'ratelimit_converter' + +This is an attachment that allows a converter to be ratelimited in terms of +items per hour. + +The attachment has following configuration: + +=over 4 + +=item match + +This field should contain a L match string, that should match the +input object. + +=item generate_arch + +This field should contain the archetype name of the output. + +=item items_per_hour + +This field should contain the number of items to generate at maximum per hour. +Default is: 20 + +=item converter_tag + +This is the tag of the converter, it should be unique per converter. You can +also use this to make the limit hit for multiple converters. + +=item msg + +This is the message when the player successfully converted. + +=item failmsg + +This is the failure message, which will be presented to the player when he hits +the rate limit. + +=back + +=cut + +cf::object::attachment ratelimit_converter => + on_drop_on => sub { + my ($self, $obj, $who) = @_; + + my $cfg = $self->{ratelimit_converter}; + + my $output_arch = $cfg->{generate_arch}; + my $match = $cfg->{match}; + my $mitems = $cfg->{items_per_hour} || 20; + my $tag = 'ratelimit_converter_' . $cfg->{converter_tag}; + + return unless cf::match::match $match, $obj; + + my $items = $mitems; + + if (!$who->flag (cf::FLAG_WIZ) && defined $who->{$tag . '_ts'}) { + my $itemtime = time - $who->{$tag . '_ts'}; + if ($itemtime < 3600) { + $items = int ($items * ($itemtime / 3600)); + } + } + + my $nr = $obj->nrof ? $obj->nrof : 1; + $nr = $items if $nr > $items; + + if ($nr > 0) { + $obj->decrease ($nr); + + my $out = cf::object::generate ($output_arch, $self); + $out->nrof ($nr); + $out->insert_at ($self, $self); + + if ($nr >= $mitems) { + $who->{$tag . '_ts'} = time; + } else { + # give player credit for the unused refills. + $who->{$tag . '_ts'} = + time - int ((($items - $nr) * 3600) / $mitems); + } + + $who->message ($cfg->{msg}) + if $cfg->{msg} ne ''; + } else { + if ($who->contr) { + $who->contr->failmsg ($cfg->{failmsg}) + if $cfg->{failmsg} ne ''; + } + } + + if ($who->flag (cf::FLAG_WIZ)) { + delete $who->{$tag . '_ts'}; + } + }; + + =item object attachment: 'display_info_window' If you attach this attachment to a sign a window containing the