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

Comparing deliantra/maps/perl/cfplus.ext (file contents):
Revision 1.3 by root, Mon Jun 19 10:15:10 2006 UTC vs.
Revision 1.9 by root, Fri Aug 25 15:07:43 2006 UTC

1#! perl 1#! perl
2 2
3# additional support for cfplus client 3# additional support for cfplus client
4 4
5use NPC_Dialogue;
6
5cf::register_extcmd cfplus_support => sub { 7cf::register_extcmd cfplus_support => sub {
6 my ($pl, $data) = @_; 8 my ($pl, $msg) = @_;
7 9
8 my ($token, $client_version) = split / /, $data, 2; 10 # $msg->{version}
9 11
10 $pl->send ("ext $token 1"); 12 (version => 1)
11}; 13};
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 14
79my %dialog; # currently active dialogs 15my %dialog; # currently active dialogs
80 16
17my $timer = Event->timer (interval => 0.2, parked => 1, cb => sub {
18 while (my ($id, $dialog) = each %dialog) {
19 my (undef, $dx, $dy) = $dialog->{ob}->rangevector ($dialog->{npc});
20 next if (abs $dx) <= 2 && (abs $dy) <= 2;
21
22 $dialog->{ob}->contr->ext_reply ($id => msgtype => "error", msg => "out of range");
23 delete $dialog{$id};
24 }
25
26 $_[0]->w->stop unless keys %dialog;
27});
28
81sub dialog_tell { 29sub dialog_tell {
82 my ($token, $dialog, $msg) = @_; 30 my ($id, $dialog, $msg) = @_;
83 31
84 my $pl = $dialog->{ob}->contr; 32 my $pl = $dialog->{ob}->contr;
85 my ($reply, @kw) = $dialog->tell ($msg); 33 my ($reply, @kw) = $dialog->tell ($msg);
86 $reply = "..." unless $reply; 34 $reply = "..." unless $reply;
87 $pl->send ("ext $token msg " . join "\x00", $reply, @kw); 35
36 $pl->ext_reply ($id => msgtype => "reply", msg => $reply, add_topics => \@kw);
88} 37}
89 38
90# return "interesting" information about the given tile 39# return "interesting" information about the given tile
91# currently only returns the npc_dialog title when a dialog is possible 40# currently only returns the npc_dialog title when a dialog is possible
92cf::register_extcmd lookat => sub { 41cf::register_extcmd lookat => sub {
93 my ($pl, $data) = @_; 42 my ($pl, $msg) = @_;
43 my ($dx, $dy) = @$msg{qw(dx dy)};
94 44
95 my ($token, $dx, $dy) = split / /, $data;
96 my $near = (abs $dx) <= 2 && (abs $dy) <= 2; 45 my $near = (abs $dx) <= 2 && (abs $dy) <= 2;
97 46
98 my %res; 47 my %res;
99 48
100 if ($pl->cell_visible ($dx, $dy)) { 49 if ($pl->cell_visible ($dx, $dy)) {
102 $res{npc_dialog} = $ob->name 51 $res{npc_dialog} = $ob->name
103 if $near && NPC_Dialogue::has_dialogue $ob; 52 if $near && NPC_Dialogue::has_dialogue $ob;
104 } 53 }
105 } 54 }
106 55
107 $pl->send ("ext $token " . join "\x00", %res); 56 %res
108}; 57};
109 58
110cf::register_extcmd npc_dialog_begin => sub { 59cf::register_extcmd npc_dialog_begin => sub {
111 my ($pl, $data) = @_; 60 my ($pl, $msg) = @_;
112 61 my ($id, $dx, $dy) = @$msg{qw(msgid dx dy)};
113 my ($token, $dx, $dy) = split / /, $data;
114 62
115 return unless (abs $dx) <= 2 && (abs $dy) <= 2; 63 return unless (abs $dx) <= 2 && (abs $dy) <= 2;
116 return unless $pl->cell_visible ($dx, $dy); 64 return unless $pl->cell_visible ($dx, $dy);
117 65
118 for my $npc ($pl->ob->map->at ($pl->ob->x + $dx, $pl->ob->y + $dy)) { 66 for my $npc ($pl->ob->map->at ($pl->ob->x + $dx, $pl->ob->y + $dy)) {
119 if (NPC_Dialogue::has_dialogue $npc) { 67 if (NPC_Dialogue::has_dialogue $npc) {
120 $dialog{$token} = new NPC_Dialogue ob => $pl->ob, npc => $npc; 68 $dialog{$id} = new NPC_Dialogue ob => $pl->ob, npc => $npc;
121 dialog_tell $token, $dialog{$token}, "hi"; 69 dialog_tell $id, $dialog{$id}, "hi";
70 $timer->start;
122 return; 71 return;
123 } 72 }
124 } 73 }
125 74
126 $pl->send ("ext $token error"); 75 (msgtype => "error", msg => "nothing to talk to found")
127}; 76};
128 77
129cf::register_extcmd npc_dialog_tell => sub { 78cf::register_extcmd npc_dialog_tell => sub {
130 my ($pl, $data) = @_; 79 my ($pl, $msg) = @_;
131 80
132 my ($token, $msg) = split / /, $data, 2; 81 dialog_tell $msg->{msgid}, $dialog{$msg->{msgid}}, $msg->{msg}
82 if $dialog{$msg->{msgid}};
133 83
134 dialog_tell $token, $dialog{$token}, $msg 84 ()
135 if $dialog{$token};
136}; 85};
137 86
138cf::register_extcmd npc_dialog_end => sub { 87cf::register_extcmd npc_dialog_end => sub {
139 my ($pl, $token) = @_; 88 my ($pl, $msg) = @_;
140 89
141 delete $dialog{$token}; 90 delete $dialog{$msg->{msgid}};
91
92 ()
142}; 93};
143 94
144sub on_logout { 95cf::attach_to_players
96 on_logout => sub {
145 my ($pl, $host) = @_; 97 my ($pl) = @_;
146 98
147 delete $dialog{$_} for grep $pl->ob == $dialog{$_}{ob}, keys %dialog; 99 delete $dialog{$_} for grep $pl->ob == $dialog{$_}{ob}, keys %dialog;
100 },
101;
148 102
103sub on_unload {
104 while (my ($id, $dialog) = each %dialog) {
105 $dialog->{ob}->contr->ext_reply ($id => msgtype => "error", msg => "npc dialogue module was reloaded");
149 0 106 }
107
108 %dialog = ();
150} 109}
151 110
152sub on_clock {
153 return 0 unless %dialog;
154 111
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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines