ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/maps/perl/NPC_Dialogue.pm
(Generate patch)

Comparing deliantra/maps/perl/NPC_Dialogue.pm (file contents):
Revision 1.5 by root, Wed Jul 19 22:20:07 2006 UTC vs.
Revision 1.8 by root, Thu Jul 20 04:28:26 2006 UTC

41 my ($self) = @_; 41 my ($self) = @_;
42 42
43 $self->tell ("hi") 43 $self->tell ("hi")
44} 44}
45 45
46=item ($reply, @topics) = $dialog->tell ($msg)
47
48Tells the dialog object something and returns its response and optionally
49a number of topics that are refered to by this topic.
50
51It supports a number of command constructs. They have to follow the
52C<@match> directive, and there can be multiple commands that will be
53executed in order.
54
55=over 4
56
57=item @parse regex
58
59Parses the message using a perl regular expression (by default
60case-insensitive). Any matches will be available as C<< $match->[$index]
61>>.
62
63If the regular expression does not match, the topic is skipped.
64
65Example:
66
67 @match deposit
68 @parse deposit (\d+) (\S+)
69 @eval bank::deposit $match->[0], $match->[1]
70
71=item @cond perl
72
73Evaluates the given perl code. If it returns false (or causes an
74exception), the topic will be skipped, otherwise topic interpretation is
75resumed.
76
77The following local variables are defined within the expression:
78
79=over 4
80
81=item $who - The cf::object::player object that initiated the dialogue.
82
83=item $npc - The NPC (or magic_ear etc.) object that is being talked to.
84
85=item $msg - The actual message as passed to this method.
86
87=item $match - An arrayref with previous results from C<@parse>.
88
89=back
90
91The environment is that standard "map scripting environment", which is
92limited in the type of constructs allowed (no loops, for example).
93
94=item @eval perl
95
96Like C<@cond>, but proceed regardless of the outcome.
97
98=item @trigger connected-id
99
100Trigger all objects with the given connected-id. The trigger is stateful
101and retains state per connected-id.
102
103=item @addtopic topic
104
105Adds the given topic names (separated by C<|>) to the list of topics
106returned.
107
108=back
109
110=cut
111
46sub tell { 112sub tell {
47 my ($self, $msg) = @_; 113 my ($self, $msg) = @_;
48 114
49 my $lcmsg = lc $msg; 115 my $lcmsg = lc $msg;
50 116
51 match: 117 match:
52 for my $match (@{ $self->{match} }) { 118 for my $match (@{ $self->{match} }) {
53 for (split /\|/, $match->[0]) { 119 for (split /\|/, $match->[0]) {
54 if ($_ eq "*" || $lcmsg eq lc) { 120 if ($_ eq "*" || $lcmsg eq lc) {
55 my $reply = $match->[1]; 121 my $reply = $match->[1];
122 my @kw;
56 123
124 my @replies;
57 my @match; # @match/@parse command results 125 my @match; # @match/@parse command results
126 local $self->{ob}{record_replies} = \@replies;
58 127
59 # now execute @-commands (which can result in a no-match) 128 # now execute @-commands (which can result in a no-match)
60 while ($reply =~ s/^\@(\w+)\s*([^\n]*)\n?//) { 129 while ($reply =~ s/^\@(\w+)\s*([^\n]*)\n?//) {
61 my ($cmd, $args) = ($1, $2); 130 my ($cmd, $args) = ($1, $2);
62 131
64 no re 'eval'; # default, but make sure 133 no re 'eval'; # default, but make sure
65 @match = $msg =~ /$args/i 134 @match = $msg =~ /$args/i
66 or next match; 135 or next match;
67 136
68 } elsif ($cmd eq "cond") { 137 } elsif ($cmd eq "cond") {
69 cf::safe_eval $args, who => $self->{ob}, npc => $self->{npc}, msg => $msg 138 cf::safe_eval $args, who => $self->{ob}, npc => $self->{npc}, msg => $msg, match => \@match
70 or next match; 139 or next match;
71 140
72 } elsif ($cmd eq "eval") { 141 } elsif ($cmd eq "eval") {
73 cf::safe_eval $args, who => $self->{ob}, npc => $self->{npc}, msg => $msg; 142 cf::safe_eval $args, who => $self->{ob}, npc => $self->{npc}, msg => $msg, match => \@match;
74 warn "\@eval evaluation error: $@\n" if $@; 143 warn "\@eval evaluation error: $@\n" if $@;
144
145 } elsif ($cmd eq "trigger") {
146 my $rvalue = \$self->{npc}{dialog_trigger}{$args*1};
147
148 my $trigger = cf::object::new "magic_ear";
149 $trigger->set_value ($$rvalue);
150
151 # needs to be on the map for remove_button_link to work
152 # the same *should* be true for add_button_link....
153 $self->{npc}->map->insert_object ($trigger, 0, 0);
154
155 $trigger->add_button_link ($self->{npc}->map, $args);
156
157 $trigger->use_trigger;
158
159 $trigger->remove_button_link;
160 $trigger->remove;
161 $trigger->free;
162
163 $$rvalue = !$$rvalue;
164
165 } elsif ($cmd eq "addtopic") {
166 push @kw, split /\|/, $args;
75 167
76 } else { 168 } else {
77 warn "unknown dialogue command <$cmd,$args> used (from " . $self->{npc}->get_message . ")"; 169 warn "unknown dialogue command <$cmd,$args> used (from " . $self->{npc}->get_message . ")";
78 } 170 }
79 } 171 }
80 172
81 # combine lines into paragraphs 173 # combine lines into paragraphs
82 $reply =~ s/(?<=\S)\n(?=\w)/ /g; 174 $reply =~ s/(?<=\S)\n(?=\w)/ /g;
83 $reply =~ s/\n\n/\n/g; 175 $reply =~ s/\n\n/\n/g;
84 176
85 my @kw; 177 # ignores flags and npc from replies
178 $reply = join "\n", (map $_->[1], @replies), $reply;
179
86 # now mark up all matching keywords 180 # now mark up all matching keywords
87 for my $match (@{ $self->{match} }) { 181 for my $match (@{ $self->{match} }) {
88 for (sort { (length $b) <=> (length $a) } split /\|/, $match->[0]) { 182 for (sort { (length $b) <=> (length $a) } split /\|/, $match->[0]) {
89 if ($reply =~ /\b\Q$_\E\b/i) { 183 if ($reply =~ /\b\Q$_\E\b/i) {
90 push @kw, $_; 184 push @kw, $_;

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines