ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/maps/perl/cfplus.ext
Revision: 1.3
Committed: Mon Jun 19 10:15:10 2006 UTC (17 years, 11 months ago) by root
Branch: MAIN
Changes since 1.2: +81 -48 lines
Log Message:
rewrite npc dialogue to be more generic, to be used in other modules soon

File Contents

# Content
1 #! perl
2
3 # additional support for cfplus client
4
5 cf::register_extcmd cfplus_support => sub {
6 my ($pl, $data) = @_;
7
8 my ($token, $client_version) = split / /, $data, 2;
9
10 $pl->send ("ext $token 1");
11 };
12
13 {
14 package NPC_Dialogue;
15
16 sub has_dialogue {
17 my ($ob) = @_;
18
19 $ob->get_message =~ /^\@match /;
20 }
21
22 sub parse_message($) {
23 map [split /\n/, $_, 2],
24 grep length,
25 split /^\@match /m,
26 $_[0]
27 }
28
29 sub new {
30 my ($class, %arg) = @_;
31
32 my $self = bless {
33 %arg,
34 }, $class;
35
36 $self->{match} ||= [parse_message $self->{npc}->get_message];
37
38 $self;
39 }
40
41 sub greet {
42 my ($self) = @_;
43
44 $self->tell ("hi")
45 }
46
47 sub tell {
48 my ($self, $msg) = @_;
49
50 for my $match (@{ $self->{match} }) {
51 for (split /\|/, $match->[0]) {
52 if ($_ eq "*" || 0 <= index $msg, $_) {
53 my $reply = $match->[1];
54
55 # combine lines into paragraphs
56 $reply =~ s/(?<=\S)\n(?=\w)/ /g;
57 $reply =~ s/\n\n/\n/g;
58
59 my @kw;
60 # now mark up all matching keywords
61 for my $match (@{ $self->{match} }) {
62 for (sort { (length $b) <=> (length $a) } split /\|/, $match->[0]) {
63 if ($reply =~ /\b\Q$_\E\b/i) {
64 push @kw, $_;
65 last;
66 }
67 }
68 }
69
70 return wantarray ? ($reply, @kw) : $reply;
71 }
72 }
73 }
74 }
75
76 ()
77 }
78
79 my %dialog; # currently active dialogs
80
81 sub dialog_tell {
82 my ($token, $dialog, $msg) = @_;
83
84 my $pl = $dialog->{ob}->contr;
85 my ($reply, @kw) = $dialog->tell ($msg);
86 $reply = "..." unless $reply;
87 $pl->send ("ext $token msg " . join "\x00", $reply, @kw);
88 }
89
90 # return "interesting" information about the given tile
91 # currently only returns the npc_dialog title when a dialog is possible
92 cf::register_extcmd lookat => sub {
93 my ($pl, $data) = @_;
94
95 my ($token, $dx, $dy) = split / /, $data;
96 my $near = (abs $dx) <= 2 && (abs $dy) <= 2;
97
98 my %res;
99
100 if ($pl->cell_visible ($dx, $dy)) {
101 for my $ob ($pl->ob->map->at ($pl->ob->x + $dx, $pl->ob->y + $dy)) {
102 $res{npc_dialog} = $ob->name
103 if $near && NPC_Dialogue::has_dialogue $ob;
104 }
105 }
106
107 $pl->send ("ext $token " . join "\x00", %res);
108 };
109
110 cf::register_extcmd npc_dialog_begin => sub {
111 my ($pl, $data) = @_;
112
113 my ($token, $dx, $dy) = split / /, $data;
114
115 return unless (abs $dx) <= 2 && (abs $dy) <= 2;
116 return unless $pl->cell_visible ($dx, $dy);
117
118 for my $npc ($pl->ob->map->at ($pl->ob->x + $dx, $pl->ob->y + $dy)) {
119 if (NPC_Dialogue::has_dialogue $npc) {
120 $dialog{$token} = new NPC_Dialogue ob => $pl->ob, npc => $npc;
121 dialog_tell $token, $dialog{$token}, "hi";
122 return;
123 }
124 }
125
126 $pl->send ("ext $token error");
127 };
128
129 cf::register_extcmd npc_dialog_tell => sub {
130 my ($pl, $data) = @_;
131
132 my ($token, $msg) = split / /, $data, 2;
133
134 dialog_tell $token, $dialog{$token}, $msg
135 if $dialog{$token};
136 };
137
138 cf::register_extcmd npc_dialog_end => sub {
139 my ($pl, $token) = @_;
140
141 delete $dialog{$token};
142 };
143
144 sub on_logout {
145 my ($pl, $host) = @_;
146
147 delete $dialog{$_} for grep $pl->ob == $dialog{$_}{ob}, keys %dialog;
148
149 0
150 }
151
152 sub on_clock {
153 return 0 unless %dialog;
154
155 while (my ($token, $dialog) = each %dialog) {
156 my (undef, $dx, $dy) = $dialog->{ob}->rangevector ($dialog->{npc});
157 next if (abs $dx) <= 2 && (abs $dy) <= 2;
158
159 $dialog->{ob}->contr->send ("ext $token out_of_range");
160 delete $dialog{$token};
161 }
162
163 0
164 }
165