… | |
… | |
23 | cf::register_extcmd cfplus_support => sub { |
23 | cf::register_extcmd cfplus_support => sub { |
24 | my ($pl, $msg) = @_; |
24 | my ($pl, $msg) = @_; |
25 | |
25 | |
26 | # $msg->{version} |
26 | # $msg->{version} |
27 | |
27 | |
|
|
28 | ( |
28 | (version => 2) |
29 | version => 2, |
29 | }; |
|
|
30 | |
|
|
31 | my %dialog; # currently active dialogs |
|
|
32 | |
|
|
33 | my $timer = Event->timer (interval => 0.2, parked => 1, data => cf::WF_AUTOCANCEL, cb => sub { |
|
|
34 | while (my ($id, $dialog) = each %dialog) { |
|
|
35 | my (undef, $dx, $dy) = $dialog->{ob}->rangevector ($dialog->{npc}); |
|
|
36 | next if (abs $dx) <= 2 && (abs $dy) <= 2; |
|
|
37 | |
|
|
38 | $dialog->{ob}->contr->ext_reply ($id => msgtype => "error", msg => "out of range"); |
|
|
39 | delete $dialog{$id}; |
|
|
40 | } |
30 | ) |
41 | |
|
|
42 | $_[0]->w->stop unless keys %dialog; |
|
|
43 | }); |
31 | }; |
44 | |
32 | |
45 | sub dialog_tell { |
33 | sub dialog_tell { |
46 | my ($id, $dialog, $msg) = @_; |
34 | my ($id, $dialog, $msg) = @_; |
47 | |
35 | |
48 | my $pl = $dialog->{ob}->contr; |
36 | my $pl = $dialog->{pl}; |
49 | my ($reply, @kw) = $dialog->tell ($msg); |
37 | my ($reply, @kw) = $dialog->tell ($msg); |
|
|
38 | |
50 | $reply = "..." unless $reply; |
39 | $reply = "..." unless defined $reply; |
|
|
40 | return if $reply eq ""; # NPC doesn't want to say, or wants to say something later |
51 | |
41 | |
52 | $pl->ext_reply ($id => msgtype => "reply", msg => $reply, add_topics => \@kw); |
42 | $pl->ext_reply ($id => msgtype => "reply", msg => $reply, add_topics => \@kw); |
53 | } |
43 | } |
54 | |
44 | |
55 | =item ... = extcmd lookat { dx => $dx, dy => $dy } |
45 | =item ... = extcmd lookat { dx => $dx, dy => $dy } |
… | |
… | |
75 | my %res; |
65 | my %res; |
76 | |
66 | |
77 | if ($pl->cell_visible ($dx, $dy)) { |
67 | if ($pl->cell_visible ($dx, $dy)) { |
78 | for my $ob ($pl->ob->map->at ($pl->ob->x + $dx, $pl->ob->y + $dy)) { |
68 | for my $ob ($pl->ob->map->at ($pl->ob->x + $dx, $pl->ob->y + $dy)) { |
79 | $res{npc_dialog} = $ob->name |
69 | $res{npc_dialog} = $ob->name |
80 | if $near && NPC_Dialogue::has_dialogue $ob; |
70 | if $near && NPC_Dialogue::has_dialogue $ob && !$pl->{npc_dialog}; |
81 | } |
71 | } |
82 | } |
72 | } |
83 | |
73 | |
84 | %res |
74 | %res |
85 | }; |
75 | }; |
… | |
… | |
89 | Tries to start a dialogue with the mapspace specified by $dx and $dy (see |
79 | Tries to start a dialogue with the mapspace specified by $dx and $dy (see |
90 | C<extcmd lookat>). The $msgid will be used as a handle for all future |
80 | C<extcmd lookat>). The $msgid will be used as a handle for all future |
91 | messages related to this dialog interaction. |
81 | messages related to this dialog interaction. |
92 | |
82 | |
93 | It either replies with an error reply or starts a dialog by telling |
83 | It either replies with an error reply or starts a dialog by telling |
94 | the npc "hi" and returning a reply strcuture as with C<extcmd |
84 | the npc "hi" and returning a reply structure as with C<extcmd |
95 | npc_dialog_tell>. |
85 | npc_dialog_tell>. |
96 | |
86 | |
97 | =cut |
87 | =cut |
98 | |
88 | |
99 | cf::register_extcmd npc_dialog_begin => sub { |
89 | cf::register_extcmd npc_dialog_begin => sub { |
… | |
… | |
101 | my ($id, $dx, $dy) = @$msg{qw(msgid dx dy)}; |
91 | my ($id, $dx, $dy) = @$msg{qw(msgid dx dy)}; |
102 | |
92 | |
103 | return unless $pl->ob && $pl->ob->map; |
93 | return unless $pl->ob && $pl->ob->map; |
104 | return unless (abs $dx) <= 2 && (abs $dy) <= 2; |
94 | return unless (abs $dx) <= 2 && (abs $dy) <= 2; |
105 | return unless $pl->cell_visible ($dx, $dy); |
95 | return unless $pl->cell_visible ($dx, $dy); |
|
|
96 | return if $pl->{npc_dialog}; # only one dialog at a time |
106 | |
97 | |
107 | for my $npc ($pl->ob->map->at ($pl->ob->x + $dx, $pl->ob->y + $dy)) { |
98 | for my $npc ($pl->ob->map->at ($pl->ob->x + $dx, $pl->ob->y + $dy)) { |
108 | if (NPC_Dialogue::has_dialogue $npc) { |
99 | if (NPC_Dialogue::has_dialogue $npc) { |
|
|
100 | $pl->attach ("npc_dialog_active"); |
109 | $dialog{$id} = new NPC_Dialogue ob => $pl->ob, npc => $npc; |
101 | $pl->{npc_dialog} = new NPC_Dialogue pl => $pl, npc => $npc, id => $id; |
110 | dialog_tell $id, $dialog{$id}, "hi"; |
102 | dialog_tell $id, $pl->{npc_dialog}, "hi"; |
111 | $timer->start; |
|
|
112 | return; |
103 | return; |
113 | } |
104 | } |
114 | } |
105 | } |
115 | |
106 | |
116 | (msgtype => "error", msg => "nothing to talk to found") |
107 | (msgtype => "error", msg => "nothing to talk to found") |
… | |
… | |
129 | =cut |
120 | =cut |
130 | |
121 | |
131 | cf::register_extcmd npc_dialog_tell => sub { |
122 | cf::register_extcmd npc_dialog_tell => sub { |
132 | my ($pl, $msg) = @_; |
123 | my ($pl, $msg) = @_; |
133 | |
124 | |
|
|
125 | if (my $dialog = $pl->{npc_dialog}) { |
134 | dialog_tell $msg->{msgid}, $dialog{$msg->{msgid}}, $msg->{msg} |
126 | dialog_tell $msg->{msgid}, $dialog, $msg->{msg}; |
135 | if $dialog{$msg->{msgid}}; |
127 | } |
136 | |
128 | |
137 | () |
129 | () |
138 | }; |
130 | }; |
139 | |
131 | |
140 | =item extcmd npc_dialog_end { msgid => $id } |
132 | =item extcmd npc_dialog_end { msgid => $id } |
… | |
… | |
144 | =cut |
136 | =cut |
145 | |
137 | |
146 | cf::register_extcmd npc_dialog_end => sub { |
138 | cf::register_extcmd npc_dialog_end => sub { |
147 | my ($pl, $msg) = @_; |
139 | my ($pl, $msg) = @_; |
148 | |
140 | |
149 | delete $dialog{$msg->{msgid}}; |
141 | if (my $dialog = delete $pl->{npc_dialog}) { |
|
|
142 | $pl->detach ("ncpa_dialog_active"); |
|
|
143 | } |
150 | |
144 | |
151 | () |
145 | () |
152 | }; |
146 | }; |
153 | |
|
|
154 | cf::attach_to_players |
|
|
155 | on_logout => sub { |
|
|
156 | my ($pl) = @_; |
|
|
157 | |
|
|
158 | delete $dialog{$_} for grep $pl->ob == $dialog{$_}{ob}, keys %dialog; |
|
|
159 | }, |
|
|
160 | ; |
|
|
161 | |
147 | |
162 | =item ... = extcmd editor_support |
148 | =item ... = extcmd editor_support |
163 | |
149 | |
164 | Returns the value required by clients that have an editor to download and |
150 | Returns the value required by clients that have an editor to download and |
165 | upload maps from/to the server. |
151 | upload maps from/to the server. |
… | |
… | |
192 | |
178 | |
193 | map +($_ => $cf::CFG{"editor_$_"}), qw(servertype gameserver testserver cvs_root lib_root builder_ui) |
179 | map +($_ => $cf::CFG{"editor_$_"}), qw(servertype gameserver testserver cvs_root lib_root builder_ui) |
194 | }; |
180 | }; |
195 | |
181 | |
196 | sub unload { |
182 | sub unload { |
197 | while (my ($id, $dialog) = each %dialog) { |
183 | for my $pl (cf::player::list) { |
|
|
184 | if (my $dialog = delete $pl->{npc_dialog}) { |
|
|
185 | $pl->detach ("npc_dialog_active"); |
198 | $dialog->{ob}->contr->ext_reply ($id => msgtype => "error", msg => "npc dialogue module was reloaded"); |
186 | $pl->ext_reply ($dialog->{id} => msgtype => "error", msg => "npc dialogue module was reloaded"); |
|
|
187 | } |
199 | } |
188 | } |
200 | |
|
|
201 | %dialog = (); |
|
|
202 | } |
189 | } |
203 | |
190 | |
|
|
191 | cf::player::attachment npc_dialog_active => |
|
|
192 | on_logout => sub { |
|
|
193 | my ($pl) = @_; |
|
|
194 | |
|
|
195 | delete $pl->{npc_dialog}; |
|
|
196 | $pl->detach ("npc_dialog_active"); |
|
|
197 | }, |
|
|
198 | on_move => sub { |
|
|
199 | my ($pl, $dir) = @_; |
|
|
200 | |
|
|
201 | if (my $dialog = $pl->{npc_dialog}) { |
|
|
202 | warn "on_move<@_>\n";#d# |
|
|
203 | warn $pl->ob; |
|
|
204 | warn $dialog; |
|
|
205 | warn $dialog->{npc}; |
|
|
206 | warn $dialog->{npc}->is_valid; |
|
|
207 | |
|
|
208 | my (undef, $dx, $dy) = $pl->ob->rangevector ($dialog->{npc}); |
|
|
209 | |
|
|
210 | return if (abs $dx) <= 2 && (abs $dy) <= 2; |
|
|
211 | |
|
|
212 | $pl->ext_reply ($dialog->{id} => msgtype => "error", msg => "out of range"); |
|
|
213 | } |
|
|
214 | |
|
|
215 | delete $pl->{npc_dialog}; |
|
|
216 | $pl->detach ("npc_dialog_active"); |
|
|
217 | }, |
|
|
218 | ; |
|
|
219 | |
|
|
220 | cf::player->attach ( |
|
|
221 | on_login => sub { |
|
|
222 | my ($pl) = @_; |
|
|
223 | |
|
|
224 | delete $pl->{npc_dialog}; |
|
|
225 | }, |
|
|
226 | ); |
|
|
227 | |
204 | =back |
228 | =back |
205 | |
229 | |
206 | =cut |
230 | =cut |
207 | |
231 | |