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

Comparing deliantra/server/ext/NPC_Dialogue.pm (file contents):
Revision 1.10 by root, Mon Jul 14 23:57:45 2008 UTC vs.
Revision 1.21 by root, Fri Mar 19 22:16:27 2010 UTC

82 82
83=item $who - The cf::object::player object that initiated the dialogue. 83=item $who - The cf::object::player object that initiated the dialogue.
84 84
85=item $npc - The NPC (or magic_ear etc.) object that is being talked to. 85=item $npc - The NPC (or magic_ear etc.) object that is being talked to.
86 86
87=item $map - The map the NPC (not the player) is on.
88
87=item $msg - The actual message as passed to this method. 89=item $msg - The actual message as passed to this method.
88 90
89=item $match - An arrayref with previous results from C<@parse>. 91=item $match - An arrayref with previous results from C<@parse>.
90 92
91=item $state - A hashref that stores state variables associated 93=item $state - A hashref that stores state variables associated
96 98
97=item $flag - A hashref that stores flags associated with the player and 99=item $flag - A hashref that stores flags associated with the player and
98can be seen by all NPCs (so better name your flags uniquely). This is 100can be seen by all NPCs (so better name your flags uniquely). This is
99useful for storing e.g. quest information. See C<@setflag> and C<@ifflag>. 101useful for storing e.g. quest information. See C<@setflag> and C<@ifflag>.
100 102
103=item $find - see @find, below.
104
101=back 105=back
102 106
103The environment is that standard "map scripting environment", which is 107The environment is that standard "map scripting environment", which is
104limited in the type of constructs allowed (no loops, for example). 108limited in the type of constructs allowed (no loops, for example).
105 109
138Like C<@cond>, but proceed regardless of the outcome. 142Like C<@cond>, but proceed regardless of the outcome.
139 143
140=item @msg perl 144=item @msg perl
141 145
142Like C<@cond>, but the return value will be stringified and prepended to 146Like C<@cond>, but the return value will be stringified and prepended to
143the message. 147the reply message.
148
149=item @check match expression
150
151Executes a match expression (see
152http://pod.tst.eu/http://cvs.schmorp.de/deliantra/server/lib/cf/match.pm)
153to see if it matches.
154
155C<self> is the npc object, C<object>, C<source> and C<originator> are the
156player communicating with the NPC.
157
158If the check fails, the match is skipped.
159
160=item @find match expression
161
162Like C<@check> in that it executes a match expression, but instead of
163failing, it gathers all objects into an array and provides a reference to
164the array in the C<$find> variable.
165
166When you want to skip the match when no objects have been found, combine
167C<@find> with C<@cond>:
168
169 @match see my spellbook
170 @find type=SPELLBOOK in inv
171 @cond @$find
172 It looks dirty.
173 @match see my spellbook
174 I can't see any, where do you have it?
144 175
145=item @setstate state value 176=item @setstate state value
146 177
147Sets the named state C<state> to the given C<value>. State values are 178Sets the named state C<state> to the given C<value>. State values are
148associated with a specific player-NPC pair, so each NPC has its own state 179associated with a specific player-NPC pair, so each NPC has its own state
153See C<@ifstate> for an example. 184See C<@ifstate> for an example.
154 185
155=item @ifstate state value 186=item @ifstate state value
156 187
157Requires that the named C<state> has the given C<value>, otherwise this 188Requires that the named C<state> has the given C<value>, otherwise this
158topic is skipped. For more complex comparisons, see C<@cond> with 189topic is skipped. For more complex comparisons, see C<@cond> with
159C<$state>. Example: 190C<$state>. Example:
160 191
161 @match quest 192 @match quest
162 @setstate question quest 193 @setstate question quest
163 Do you really want to help find the magic amulet of Beeblebrox? 194 Do you really want to help find the magic amulet of Beeblebrox?
171associated with a specific player and can be seen by all NPCs. with 202associated with a specific player and can be seen by all NPCs. with
172respect to a particular player, which makes them suitable to store quest 203respect to a particular player, which makes them suitable to store quest
173markers and other information (e.g. reputation/alignment). Flags are 204markers and other information (e.g. reputation/alignment). Flags are
174persistent over the lifetime of a player, so be careful :) 205persistent over the lifetime of a player, so be careful :)
175 206
207Perversely enough, using C<@setfflag> without a C<value> clears the flag
208as if it was never set, so always provide a flag value (e.g. C<1>) when
209you want to set the flag.
210
176See C<@ifflag> for an example. 211See C<@ifflag> for an example.
177 212
178=item @ifflag flag value 213=item @ifflag flag value
179 214
180Requires that the named C<flag> has the given C<value>, otherwise this 215Requires that the named C<flag> has the given C<value>, otherwise this
181topic is skipped. For more complex comparisons, see C<@cond> with 216topic is skipped. For more complex comparisons, see C<@cond> with
182C<$flag>. Example: 217C<$flag>.
218
219If no C<value> is given, then the ifflag succeeds when the flag is true.
220
221Example:
183 222
184 @match I want to do the quest! 223 @match I want to do the quest!
185 @setflag kings_quest 1 224 @setflag kings_quest 1
186 Then seek out Bumblebee in Navar, he will tell you... 225 Then seek out Bumblebee in Navar, he will tell you...
187 @match I did the quest 226 @match I did the quest
201When the state argument is omitted the trigger is stateful and retains an 240When the state argument is omitted the trigger is stateful and retains an
202internal state per connected-id. There is a limitation to the use of this: The 241internal state per connected-id. There is a limitation to the use of this: The
203state won't be changed when the connection is triggered by other triggers. So 242state won't be changed when the connection is triggered by other triggers. So
204be careful when triggering the connection from other objects. 243be careful when triggering the connection from other objects.
205 244
206When a state argument is given it should be either 0 or 1. 1 will 'push' the connection 245When a state argument is given it should be a positive integer. Any value
207and 0 will 'release' the connection. This is useful for example when you want to 246C<!= 0> will 'push' the connection (in general, you should specify C<1>
208let a npc control a door. 247for this) and C<0> will 'release' the connection. This is useful for
248example when you want to let an NPC control a door.
209 249
210Trigger all objects with the given connected-id by 'releasing' the connection. 250Trigger all objects with the given connected-id by 'releasing' the connection.
211 251
212=item @playersound face-name 252=item @playersound face-name
213 253
245 my @match; # @match/@parse command results 285 my @match; # @match/@parse command results
246 286
247 my $state = $self->{npc}{$self->{ob}->name}{dialog_state} ||= {}; 287 my $state = $self->{npc}{$self->{ob}->name}{dialog_state} ||= {};
248 my $flag = $self->{ob}{dialog_flag} ||= {}; 288 my $flag = $self->{ob}{dialog_flag} ||= {};
249 289
290 my @find;
291
250 my %vars = ( 292 my %vars = (
251 who => $self->{ob}, 293 who => $self->{ob},
252 npc => $self->{npc}, 294 npc => $self->{npc},
295 map => $self->{npc}->map,
253 state => $state, 296 state => $state,
254 flag => $flag, 297 flag => $flag,
255 msg => $msg, 298 msg => $msg,
256 match => \@match, 299 match => \@match,
300 find => \@find,
257 ); 301 );
258 302
259 local $self->{ob}{record_replies} = \@replies; 303 local $self->{ob}{record_replies} = \@replies;
260 304
261 # now execute @-commands (which can result in a no-match) 305 # now execute @-commands (which can result in a no-match)
282 326
283 } elsif ($cmd eq "eval") { 327 } elsif ($cmd eq "eval") {
284 cf::safe_eval $args, %vars; 328 cf::safe_eval $args, %vars;
285 warn "\@eval evaluation error: $@\n" if $@; 329 warn "\@eval evaluation error: $@\n" if $@;
286 330
331 } elsif ($cmd eq "check") {
332 eval {
333 cf::match::match $args, $self->{ob}, $self->{npc}, $self->{ob}
334 or next topic;
335 };
336 warn "\@check evaluation error: $@\n" if $@;
337
338 } elsif ($cmd eq "find") {
339 @find = eval {
340 cf::match::match $args, $self->{ob}, $self->{npc}, $self->{ob}
341 };
342 warn "\@find evaluation error: $@\n" if $@;
343
287 } elsif ($cmd eq "msg") { 344 } elsif ($cmd eq "msg") {
288 push @replies, [$self->{npc}, (scalar cf::safe_eval $args, %vars)]; 345 push @replies, [$self->{npc}, (scalar cf::safe_eval $args, %vars)];
289 346
290 } elsif ($cmd eq "setflag") { 347 } elsif ($cmd eq "setflag") {
291 my ($name, $value) = split /\s+/, $args, 2; 348 my ($name, $value) = split /\s+/, $args, 2;
292 $value ? $flag->{$name} = $value 349 defined $value ? $flag->{$name} = $value
293 : delete $flag->{$name}; 350 : delete $flag->{$name};
294 351
295 } elsif ($cmd eq "setstate") { 352 } elsif ($cmd eq "setstate") {
296 my ($name, $value) = split /\s+/, $args, 2; 353 my ($name, $value) = split /\s+/, $args, 2;
297 $value ? $state->{$name} = $value 354 defined $value ? $state->{$name} = $value
298 : delete $state->{$name}; 355 : delete $state->{$name};
299 356
300 } elsif ($cmd eq "ifflag") { 357 } elsif ($cmd eq "ifflag") {
301 my ($name, $value) = split /\s+/, $args, 2; 358 my ($name, $value) = split /\s+/, $args, 2;
302 $flag->{$name} eq $value 359 defined $value ? $flag->{$name} eq $value
360 : $flag->{$name}
303 or next topic; 361 or next topic;
304 362
305 } elsif ($cmd eq "ifstate") { 363 } elsif ($cmd eq "ifstate") {
306 my ($name, $value) = split /\s+/, $args, 2; 364 my ($name, $value) = split /\s+/, $args, 2;
307 $state->{$name} eq $value 365 defined $value ? $state->{$name} eq $value
366 : $state->{$name}
308 or next topic; 367 or next topic;
309 368
310 } elsif ($cmd eq "trigger") { 369 } elsif ($cmd eq "trigger") {
311 my ($con, $state) = split /\s+/, $args, 2; 370 my ($con, $state) = split /\s+/, $args, 2;
312 $con = $con * 1;
313 371
314 if (defined $state) { 372 if (defined $state) {
315 $self->{npc}->map->trigger ($args, $state); 373 $self->{npc}->map->trigger ($con, $state, $self->{npc}, $self->{ob});
316 } else { 374 } else {
317 my $rvalue = \$self->{npc}{dialog_trigger}{$con}; 375 my $rvalue = \$self->{npc}{dialog_trigger}{$con+0};
318 $self->{npc}->map->trigger ($con, $$rvalue = !$$rvalue); 376 $self->{npc}->map->trigger ($con, $$rvalue = !$$rvalue, $self->{npc}, $self->{ob});
319 } 377 }
320 378
321 } elsif ($cmd eq "addtopic") { 379 } elsif ($cmd eq "addtopic") {
322 push @kw, split /\|/, $args; 380 push @kw, split /\|/, $args;
323 $self->{add_topic}->(split /\s*\|\s*/, $args) if $self->{add_topic}; 381 $self->{add_topic}->(split /\s*\|\s*/, $args) if $self->{add_topic};
331 } 389 }
332 } 390 }
333 391
334 delete $self->{npc}{$self->{ob}->name}{dialog_state} unless %$state; 392 delete $self->{npc}{$self->{ob}->name}{dialog_state} unless %$state;
335 delete $self->{ob}{dialog_flag} unless %$flag; 393 delete $self->{ob}{dialog_flag} unless %$flag;
336
337 # combine lines into paragraphs
338 $reply =~ s/(?<=\S)\n(?=\w)/ /g;
339 $reply =~ s/\n\n/\n/g;
340 394
341 # ignores flags and npc from replies 395 # ignores flags and npc from replies
342 $reply = join "\n", (map $_->[1], @replies), $reply; 396 $reply = join "\n", (map $_->[1], @replies), $reply;
343 397
344 # now mark up all matching keywords 398 # now mark up all matching keywords
349 last; 403 last;
350 } 404 }
351 } 405 }
352 } 406 }
353 407
408 $self->{npc}->use_trigger ($self->{ob})
409 if $self->{npc}->type == cf::MAGIC_EAR;
410
354 return wantarray ? ($reply, @kw) : $reply; 411 return wantarray ? ($reply, @kw) : $reply;
355 } 412 }
356 } 413 }
357 } 414 }
358 415

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines