… | |
… | |
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 | |
|
|
48 | Tells the dialog object something and returns its response and optionally |
|
|
49 | a number of topics that are refered to by this topic. |
|
|
50 | |
|
|
51 | It supports a number of command constructs. They have to follow the |
|
|
52 | C<@match> directive, and there can be multiple commands that will be |
|
|
53 | executed in order. |
|
|
54 | |
|
|
55 | =over 4 |
|
|
56 | |
|
|
57 | =item @parse regex |
|
|
58 | |
|
|
59 | Parses the message using a perl regular expression (by default |
|
|
60 | case-insensitive). Any matches will be available as C<< $match->[$index] |
|
|
61 | >>. |
|
|
62 | |
|
|
63 | If the regular expression does not match, the topic is skipped. |
|
|
64 | |
|
|
65 | Example: |
|
|
66 | |
|
|
67 | @match deposit |
|
|
68 | @parse deposit (\d+) (\S+) |
|
|
69 | @eval bank::deposit $match->[0], $match->[1] |
|
|
70 | |
|
|
71 | =item @cond perl |
|
|
72 | |
|
|
73 | Evaluates the given perl code. If it returns false (or causes an |
|
|
74 | exception), the topic will be skipped, otherwise topic interpretation is |
|
|
75 | resumed. |
|
|
76 | |
|
|
77 | The 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 | |
|
|
91 | The environment is that standard "map scripting environment", which is |
|
|
92 | limited in the type of constructs allowed (no loops, for example). |
|
|
93 | |
|
|
94 | =item @eval perl |
|
|
95 | |
|
|
96 | Like C<@cond>, but proceed regardless of the outcome. |
|
|
97 | |
|
|
98 | =item @trigger connected-id |
|
|
99 | |
|
|
100 | Trigger all objects with the given connected-id. The trigger is stateful |
|
|
101 | and retains state per connected-id. |
|
|
102 | |
|
|
103 | =item @addtopic topic |
|
|
104 | |
|
|
105 | Adds the given topic names (separated by C<|>) to the list of topics |
|
|
106 | returned. |
|
|
107 | |
|
|
108 | =back |
|
|
109 | |
|
|
110 | =cut |
|
|
111 | |
46 | sub tell { |
112 | sub 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, $_; |