1 | #! perl |
1 | #! perl |
2 | |
2 | |
3 | my $price_fact = 50; |
3 | my $price_fact = 50; |
4 | |
4 | |
5 | sub set_package { |
5 | sub set_package { |
6 | my ($pkg, $to, $from, $bagname, $weight) = @_; |
6 | my ($pkg, $from, $to, $bagname, $weight) = @_; |
7 | $pkg->set_name ("$bagname T: $to F: $from"); |
7 | $pkg->set_name ("$bagname T: $to F: $from"); |
8 | $pkg->set_weight_limit ($weight); |
8 | $pkg->set_weight_limit ($weight); |
9 | $pkg->set_str (0); |
9 | $pkg->set_str (0); |
10 | } |
10 | } |
11 | |
11 | |
12 | # prices in plat. |
12 | # prices in plat. |
13 | my %prices = ( |
13 | my %prices = ( |
14 | pen => [ |
14 | pen => [ |
15 | 40, 'stylus', |
15 | 40, 'stylus', |
16 | sub { $_[0]->set_name ('IPO Writing Pen'); $_[0]->set_value (40 * $price_fact); }, 'plarg' |
16 | sub { $_[0]->set_name ('IPO Writing Pen'); $_[0]->set_value (40 * $price_fact); } |
17 | ], |
17 | ], |
18 | literacy => [ |
18 | literacy => [ |
19 | 1000, 'scroll_literacy', |
19 | 1000, 'scroll_literacy', |
20 | sub { $_[0]->set_value (1000 * $price_fact) } |
20 | sub { $_[0]->set_value (1000 * $price_fact) } |
21 | ], |
21 | ], |
… | |
… | |
40 | }, |
40 | }, |
41 | 'plarg' |
41 | 'plarg' |
42 | ], |
42 | ], |
43 | ); |
43 | ); |
44 | |
44 | |
|
|
45 | my %mailtypes = ( |
|
|
46 | 1 => ['scroll', 'mailscroll'], |
|
|
47 | 2 => ['note', 'newspaper'], |
|
|
48 | 3 => ['diploma', 'mailwarning'], |
|
|
49 | ); |
|
|
50 | |
45 | sub create_object { |
51 | sub create_object { |
46 | my ($name, $map, $x, $y, $cb, @a) = @_; |
52 | my ($name, $map, $x, $y, $cb, @a) = @_; |
47 | my $o = cf::object::new $name; |
53 | my $o = cf::object::new $name; |
48 | my $r = $cb->($o, @a); |
54 | my $r = $cb->($o, @a); |
49 | $map->insert_object ($o, $x, $y); |
55 | $map->insert_object ($o, $x, $y); |
50 | $r |
56 | $r |
51 | } |
57 | } |
52 | |
58 | |
|
|
59 | # this handler handles to notice the player that he has got mail |
|
|
60 | sub on_login { |
|
|
61 | my ($pl, $host) = @_; |
|
|
62 | |
|
|
63 | my $mails = CFMail::get_mail ($pl->ob->name); |
|
|
64 | |
|
|
65 | my $cnt = @{$mails || []}; |
|
|
66 | |
|
|
67 | if ($cnt == 1) { |
|
|
68 | $pl->ob->message ("You got one mail."); |
|
|
69 | } elsif ($cnt > 1) { |
|
|
70 | $pl->ob->message ("You got $cnt mails."); |
|
|
71 | } else { |
|
|
72 | $pl->ob->message ("You haven't got any mail."); |
|
|
73 | } |
|
|
74 | |
|
|
75 | 0 |
|
|
76 | } |
|
|
77 | |
|
|
78 | # this event handler handles receiving of mails |
|
|
79 | sub on_apply { |
|
|
80 | my ($ev, $box, $pl) = @_; |
|
|
81 | |
|
|
82 | my $cnt; |
|
|
83 | my $mails = CFMail::get_mail ($pl->name) || []; |
|
|
84 | |
|
|
85 | # count the mails that are in the container |
|
|
86 | # FIXME: the problem with on_apply is that it is called even when |
|
|
87 | # the player closes the container. so we get a 'You have X mails.' message |
|
|
88 | # twice. - This bug existed also with the old python plugin |
|
|
89 | |
|
|
90 | my $plname = $pl->name; |
|
|
91 | for ($box->inv) { |
|
|
92 | $_->name =~ /\S+ F: \S+ T: \Q$plname\E/ |
|
|
93 | and $cnt++; |
|
|
94 | } |
|
|
95 | |
|
|
96 | for (@$mails) { |
|
|
97 | my ($type, $from, $msg) = @$_; |
|
|
98 | $type = $mailtypes{$type || 1} || ['scroll', 'mailscroll']; |
|
|
99 | my $mail = cf::object::new $type->[0]; |
|
|
100 | $mail->set_name ("$type->[1] F: $from T: " .$pl->name); |
|
|
101 | $mail->set_name_plural ("$type->[1]s F: $from T: " .$pl->name); |
|
|
102 | $mail->set_message ($msg); |
|
|
103 | $mail->set_value (0); |
|
|
104 | $mail->insert_in_ob ($box); |
|
|
105 | } |
|
|
106 | |
|
|
107 | $cnt += @$mails; |
|
|
108 | |
|
|
109 | if ($cnt == 1) { |
|
|
110 | $pl->message ("You got one mail."); |
|
|
111 | } elsif ($cnt > 1) { |
|
|
112 | $pl->message ("You got $cnt mails."); |
|
|
113 | } else { |
|
|
114 | $pl->message ("You haven't got any mail."); |
|
|
115 | } |
|
|
116 | |
|
|
117 | CFMail::clear_mail ($pl->name); |
|
|
118 | |
|
|
119 | 0; |
|
|
120 | } |
|
|
121 | |
|
|
122 | # this event handler handles the sending of mails |
|
|
123 | sub on_close { |
|
|
124 | my ($ev, $box, $pl) = @_; |
|
|
125 | |
|
|
126 | my @mails; |
|
|
127 | |
|
|
128 | my %sent_targets; |
|
|
129 | |
|
|
130 | for ($box->inv) { |
|
|
131 | if ($_->name =~ m/^mail(scroll|warning) T: (\S+) F: (\S+)/) { |
|
|
132 | CFMail::send_mail ($1 eq 'scroll' ? 1 : 3, $2, $3, $_->message); |
|
|
133 | $pl->message ("Sent mail$1 to $2 (from $3)."); |
|
|
134 | $sent_targets{$2}++; |
|
|
135 | push @mails, $_; |
|
|
136 | |
|
|
137 | } elsif ($_->name =~ m/^mail(scroll|warning) F: (\S+) T: (\S+)/) { |
|
|
138 | # this is for mails that remain in the queue for the player |
|
|
139 | CFMail::store_mail ($1 eq 'scroll' ? 1 : 3, $3, $2, $_->message); |
|
|
140 | push @mails, $_; |
|
|
141 | } |
|
|
142 | } |
|
|
143 | |
|
|
144 | $_->remove for @mails; |
|
|
145 | |
|
|
146 | # lets message player ingame: this is a NEW feature from the perl IPO :-) |
|
|
147 | for (keys %sent_targets) { |
|
|
148 | if (my $player = cf::player::find $_) { |
|
|
149 | my $cnt = $sent_targets{$_}; |
|
|
150 | |
|
|
151 | if ($cnt == 1) { |
|
|
152 | $player->ob->message ("You've got new mail."); |
|
|
153 | } else { |
|
|
154 | $player->ob->message ("You've got $cnt new mails."); |
|
|
155 | } |
|
|
156 | } |
|
|
157 | } |
|
|
158 | |
|
|
159 | 0; |
|
|
160 | } |
|
|
161 | |
|
|
162 | # this is the main command interface for the IPO NPC |
53 | cf::register_script_function "ipo::command" => sub { |
163 | cf::register_script_function "ipo::command" => sub { |
54 | my ($who, $msg, $npc) = @_; |
164 | my ($who, $msg, $npc) = @_; |
55 | my ($cmd, $arguments) = split /\s+/, $msg, 2; |
165 | my ($cmd, $arguments) = split /\s+/, $msg, 2; |
56 | $cmd = lc $cmd; |
166 | $cmd = lc $cmd; |
57 | |
167 | |
… | |
… | |
105 | return 1; |
215 | return 1; |
106 | } |
216 | } |
107 | |
217 | |
108 | my $cnt; |
218 | my $cnt; |
109 | for ($who->inv) { |
219 | for ($who->inv) { |
110 | if ($_->name () =~ /^\S+ T: \Q$arguments\E F: (\S+)$/) { |
220 | if ($_->name () =~ /^(bag|package|carton) T: \Q$arguments\E F: (\S+)$/) { |
111 | $_->set_name ("$1 F: $2 T: $arguments"); |
221 | $_->set_name ("$1 F: $2 T: $arguments"); |
112 | $_->teleport ($storage, 2, 2); |
222 | $_->teleport ($storage, 2, 2); |
113 | $cnt++; |
223 | $cnt++; |
114 | } |
224 | } |
115 | } |
225 | } |
… | |
… | |
120 | $who->reply ($npc, "Sorry, found no package to send to $arguments."); |
230 | $who->reply ($npc, "Sorry, found no package to send to $arguments."); |
121 | } |
231 | } |
122 | |
232 | |
123 | } else { |
233 | } else { |
124 | $who->reply ($npc, |
234 | $who->reply ($npc, |
125 | "How can I help you?\n" |
235 | sprintf "How can I help you?\n" |
126 | ."Here is a quick list of commands I understand:\n\n" |
236 | ."Here is a quick list of commands I understand:\n\n" |
127 | ."- pen (%s platinum)\n" |
237 | ."- pen (%s platinum)\n" |
128 | ."- literacy (%s platinum)\n" |
238 | ."- literacy (%s platinum)\n" |
129 | ."- mailscroll <friend> (%s platinum)\n" |
239 | ."- mailscroll <friend> (%s platinum)\n" |
130 | ."- bag <friend> (%s platinum)\n" |
240 | ."- bag <friend> (%s platinum)\n" |
131 | ."- package <friend> (%s platinum)\n" |
241 | ."- package <friend> (%s platinum)\n" |
|
|
242 | ."- carton <friend> (%s platinum)\n" |
132 | .($who->flag (cf::FLAG_WIZ) ? "- mailwarning <player>" : "") |
243 | .($who->flag (cf::FLAG_WIZ) ? "- mailwarning <player>" : ""), |
|
|
244 | 40, 1000, 1, 1, 5, 10 |
133 | ); |
245 | ); |
134 | } |
246 | } |
135 | 1 |
247 | 1 |
|
|
248 | }; |
|
|
249 | |
|
|
250 | package CFMail; |
|
|
251 | use YAML qw/LoadFile DumpFile Dump/; |
|
|
252 | use POSIX qw/strftime/; |
|
|
253 | |
|
|
254 | my $maildb_file = cf::localdir . "/crossfiremail.perl"; |
|
|
255 | my $last_check = (-M $maildb_file) + 1; |
|
|
256 | my $MAILDB; |
|
|
257 | |
|
|
258 | sub check_maildb { |
|
|
259 | if ($last_check > (-M $maildb_file)) { |
|
|
260 | $last_check = -M $maildb_file; |
|
|
261 | |
|
|
262 | my $maildb = eval { my $m = LoadFile ($maildb_file); return $m }; |
|
|
263 | if ($@) { |
|
|
264 | warn "ERROR when reading mail database $maildb_file: $@\n"; |
|
|
265 | $maildb_file = cf::localdir . "/crossfiremail.perl.after_load_failure"; |
|
|
266 | } else { |
|
|
267 | $MAILDB = $maildb; |
|
|
268 | } |
|
|
269 | } |
136 | } |
270 | } |
|
|
271 | |
|
|
272 | # This is not thread or multiprocess safe! |
|
|
273 | # XXX: A second process will (of course) terribly damage the maildatabase |
|
|
274 | # but i assume there wont be any second process. |
|
|
275 | sub sync_maildb { |
|
|
276 | eval { |
|
|
277 | DumpFile ("$maildb_file.tmp", $MAILDB); |
|
|
278 | }; |
|
|
279 | if ($@) { |
|
|
280 | warn "ERROR when writing mail database $maildb_file.tmp: $@\n"; |
|
|
281 | } else { |
|
|
282 | rename "$maildb_file.tmp", $maildb_file; |
|
|
283 | $last_check = -M $maildb_file; |
|
|
284 | } |
|
|
285 | } |
|
|
286 | |
|
|
287 | sub get_mail { |
|
|
288 | my ($toname) = @_; |
|
|
289 | check_maildb; |
|
|
290 | $MAILDB->{$toname}; |
|
|
291 | } |
|
|
292 | |
|
|
293 | sub clear_mail { |
|
|
294 | my ($toname) = @_; |
|
|
295 | check_maildb; |
|
|
296 | $MAILDB->{$toname} = []; |
|
|
297 | sync_maildb; |
|
|
298 | } |
|
|
299 | |
|
|
300 | sub store_mail { |
|
|
301 | my ($type, $toname, $fromname, $message) = @_; |
|
|
302 | check_maildb; |
|
|
303 | push @{$MAILDB->{$toname}}, [$type, $fromname, $message]; |
|
|
304 | sync_maildb; |
|
|
305 | } |
|
|
306 | |
|
|
307 | sub send_mail { |
|
|
308 | my ($type, $toname, $fromname, $message) = @_; |
|
|
309 | my $time = strftime ("%a, %d %b %Y %H:%M:%S CEST", localtime (time)); |
|
|
310 | my $msg = "From: $fromname\nTo: $toname\nDate: $time\n\n$message\n"; |
|
|
311 | check_maildb; |
|
|
312 | push @{$MAILDB->{$toname}}, [$type, $fromname, $msg]; |
|
|
313 | sync_maildb; |
|
|
314 | } |
|
|
315 | |
|
|
316 | check_maildb (); |
|
|
317 | |
|
|
318 | 1; |