#! perl =head1 CF+ map maker library and utilities =over 4 =cut # This extension loads some nice functionality for map makers sub rec_inv_by_slaying { my ($ob, $slaying, $cb) = @_; $cb->($ob) if $ob->slaying eq $slaying; for my $iob ($ob->inv) { rec_inv_by_slaying ($iob, $slaying, $cb) } } =item object attachment: 'check_inventory_on_apply' This attachment checks on apply whether the applyer has a specific item. Currently you can only match the slaying field of the inventory item of the player. On match the apply isn't inhibited. Following configuration can be supplied to this attachment: =over 4 =item key_string This is the string that will be matched against the slaying field of the inventory item of the player. The first found item will be decreased by the amount that can be passed in the 'decrease_by_cnt' option. =item decrease_by_cnt This is the amount the matching object will be decreased by from the inventory. Default is 0 and means nothing will be removed. =item message_on_match This is the message that will printed to the player if a matching object was found. =item message_on_nomatch This is the message that will printed to the player if NO matching object was found. =back =cut cf::object::attachment check_inventory_on_apply => on_apply => sub { my ($self, $pl) = @_; my $cfg = $self->{check_inventory_on_apply}; my $match; rec_inv_by_slaying ($pl, $cfg->{key_string}, sub { my ($ob) = @_; $match = $ob; }); if ($match) { $match->decrease ($cfg->{decrease_by_cnt}) if $cfg->{decrease_by_cnt}; $pl->message ($cfg->{message_on_match}, cf::NDI_UNIQUE) if defined $cfg->{message_on_match}; } else { $pl->message ($cfg->{message_on_nomatch}, cf::NDI_RED | cf::NDI_UNIQUE) if defined $cfg->{message_on_nomatch}; cf::override; } }; =item object attachment: 'trigger_on_dialog_flag' This attachment checks whether the player has a specific dialog flag set (the ones you can set with @setflag, see also L, and triggers a connection depending on that. The attachment has following configuration: =over 4 =item flag This field should contain the name of the flag that you want to check for. =item connection The connection ID of the connection you want to trigger. =item state The state of the connection: 0 for release, 1 for push. =back =cut cf::object::attachment trigger_on_dialog_flag => on_move_trigger => sub { my ($self, $who, $orig) = @_; my $cfg = $self->{trigger_on_dialog_flag}; if (exists $who->{ob}{dialog_flag}{$cfg->{flag}}) { if ($who->{ob}{dialog_flag}{$cfg->{flag}}) { $self->map->trigger ($cfg->{connection}, $cfg->{state}); } cf::override; } }; =item object attachment: 'display_info_window' If you attach this attachment to a sign a window containing the message will open in the client when the player applies it. Use this feature with care, as popups usually are very noisy. This is mostly thought for tutorial or other instructions. =cut cf::object::attachment display_info_window => on_apply => sub { my ($self, $pl) = @_; return unless $pl->contr->ns->{can_widget}; my $cfg = $self->{display_info_window}; if ($pl->contr->ns->{info_wins}->{$self->uuid}) { $pl->contr->ns->{info_wins}->{$self->uuid}->destroy; } my $ws = $pl->contr->ns->new_widgetset; my $w = $ws->{my_main} = $ws->new (Toplevel => force_w => 600, force_h => 400, x => 'center', y => 'center', title => 'Information Sign', has_close_button => 1, on_delete => sub { $ws->destroy }, ); $w->add ($ws->{txt_area} = $ws->new ('TextScroller')); $ws->{txt_area}->add_paragraph ($self->msg); $w->show; $pl->contr->ns->{info_wins}->{$self->uuid} = $ws; cf::override 1; }; =back =cut