--- deliantra/server/ext/NPC_Dialogue.pm 2008/07/14 23:57:45 1.10 +++ deliantra/server/ext/NPC_Dialogue.pm 2010/02/05 01:26:35 1.19 @@ -98,6 +98,8 @@ can be seen by all NPCs (so better name your flags uniquely). This is useful for storing e.g. quest information. See C<@setflag> and C<@ifflag>. +=item $find - see @find, below. + =back The environment is that standard "map scripting environment", which is @@ -140,7 +142,34 @@ =item @msg perl Like C<@cond>, but the return value will be stringified and prepended to -the message. +the reply message. + +=item @check match expression + +Executes a match expression (see +http://pod.tst.eu/http://cvs.schmorp.de/deliantra/server/lib/cf/match.pm) +to see if it matches. + +C is the npc object, C, C and C are the +player communicating with the NPC. + +If the check fails, the match is skipped. + +=item @find match expression + +Like C<@check> in that it executes a match expression, but instead of +failing, it gathers all objects into an array and provides a reference to +the array in the C<$find> variable. + +When you want to skip the match when no objects have been found, combine +C<@find> with C<@cond>: + + @match see my spellbook + @find type=SPELLBOOK in inv + @cond @$find + It looks dirty. + @match see my spellbook + I can't see any, where do you have it? =item @setstate state value @@ -173,13 +202,21 @@ markers and other information (e.g. reputation/alignment). Flags are persistent over the lifetime of a player, so be careful :) +Perversely enough, using C<@setfflag> without a C clears the flag +as if it was never set, so always provide a flag value (e.g. C<1>) when +you want to set the flag. + See C<@ifflag> for an example. =item @ifflag flag value Requires that the named C has the given C, otherwise this -topic is skipped. For more complex comparisons, see C<@cond> with -C<$flag>. Example: +topic is skipped. For more complex comparisons, see C<@cond> with +C<$flag>. + +If no C is given, then the ifflag succeeds when the flag is true. + +Example: @match I want to do the quest! @setflag kings_quest 1 @@ -203,9 +240,10 @@ state won't be changed when the connection is triggered by other triggers. So be careful when triggering the connection from other objects. -When a state argument is given it should be either 0 or 1. 1 will 'push' the connection -and 0 will 'release' the connection. This is useful for example when you want to -let a npc control a door. +When a state argument is given it should be a positive integer. Any value +C will 'push' the connection (in general, you should specify C<1> +for this) and C<0> will 'release' the connection. This is useful for +example when you want to let an NPC control a door. Trigger all objects with the given connected-id by 'releasing' the connection. @@ -247,6 +285,8 @@ my $state = $self->{npc}{$self->{ob}->name}{dialog_state} ||= {}; my $flag = $self->{ob}{dialog_flag} ||= {}; + my @find; + my %vars = ( who => $self->{ob}, npc => $self->{npc}, @@ -254,6 +294,7 @@ flag => $flag, msg => $msg, match => \@match, + find => \@find, ); local $self->{ob}{record_replies} = \@replies; @@ -284,22 +325,36 @@ cf::safe_eval $args, %vars; warn "\@eval evaluation error: $@\n" if $@; + } elsif ($cmd eq "check") { + eval { + cf::match::match $args, $self->{ob}, $self->{npc}, $self->{ob} + or next topic; + }; + warn "\@check evaluation error: $@\n" if $@; + + } elsif ($cmd eq "find") { + @find = eval { + cf::match::match $args, $self->{ob}, $self->{npc}, $self->{ob} + }; + warn "\@find evaluation error: $@\n" if $@; + } elsif ($cmd eq "msg") { push @replies, [$self->{npc}, (scalar cf::safe_eval $args, %vars)]; } elsif ($cmd eq "setflag") { my ($name, $value) = split /\s+/, $args, 2; - $value ? $flag->{$name} = $value - : delete $flag->{$name}; + defined $value ? $flag->{$name} = $value + : delete $flag->{$name}; } elsif ($cmd eq "setstate") { my ($name, $value) = split /\s+/, $args, 2; - $value ? $state->{$name} = $value - : delete $state->{$name}; + defined $value ? $state->{$name} = $value + : delete $state->{$name}; } elsif ($cmd eq "ifflag") { my ($name, $value) = split /\s+/, $args, 2; - $flag->{$name} eq $value + defined $value ? $flag->{$name} eq $value + : $flag->{$name} or next topic; } elsif ($cmd eq "ifstate") { @@ -309,13 +364,12 @@ } elsif ($cmd eq "trigger") { my ($con, $state) = split /\s+/, $args, 2; - $con = $con * 1; if (defined $state) { - $self->{npc}->map->trigger ($args, $state); + $self->{npc}->map->trigger ($con, $state, $self->{npc}, $self->{ob}); } else { - my $rvalue = \$self->{npc}{dialog_trigger}{$con}; - $self->{npc}->map->trigger ($con, $$rvalue = !$$rvalue); + my $rvalue = \$self->{npc}{dialog_trigger}{$con+0}; + $self->{npc}->map->trigger ($con, $$rvalue = !$$rvalue, $self->{npc}, $self->{ob}); } } elsif ($cmd eq "addtopic") { @@ -334,10 +388,6 @@ delete $self->{npc}{$self->{ob}->name}{dialog_state} unless %$state; delete $self->{ob}{dialog_flag} unless %$flag; - # combine lines into paragraphs - $reply =~ s/(?<=\S)\n(?=\w)/ /g; - $reply =~ s/\n\n/\n/g; - # ignores flags and npc from replies $reply = join "\n", (map $_->[1], @replies), $reply; @@ -351,6 +401,9 @@ } } + $self->{npc}->use_trigger ($self->{ob}) + if $self->{npc}->type == cf::MAGIC_EAR; + return wantarray ? ($reply, @kw) : $reply; } }