ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/c_misc.C
Revision: 1.46
Committed: Thu Mar 1 13:18:37 2007 UTC (17 years, 2 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.45: +0 -21 lines
Log Message:
bug reports should be in perl, if ever

File Contents

# User Rev Content
1 elmex 1.1 /*
2 pippijn 1.36 * CrossFire, A Multiplayer game for X-windows
3     *
4     * Copyright (C) 2005, 2006, 2007 Marc Lehmann & Crossfire+ Development Team
5     * Copyright (C) 2002 Mark Wedel & Crossfire Development Team
6     * Copyright (C) 1992 Frank Tore Johansen
7     *
8     * This program is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License as published by
10     * the Free Software Foundation; either version 2 of the License, or
11     * (at your option) any later version.
12     *
13     * This program is distributed in the hope that it will be useful,
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     * GNU General Public License for more details.
17     *
18     * You should have received a copy of the GNU General Public License
19     * along with this program; if not, write to the Free Software
20     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21     *
22     * The authors can be reached via e-mail at <crossfire@schmorp.de>
23     */
24 elmex 1.1
25     #include <global.h>
26     #include <loader.h>
27 root 1.21 #include <sproto.h>
28    
29 elmex 1.1 /* Handles misc. input request - things like hash table, malloc, maps,
30     * who, etc.
31     */
32    
33     /* This command dumps the body information for object *op.
34     * it doesn't care what the params are.
35     * This is mostly meant as a debug command.
36     */
37 root 1.7 int
38     command_body (object *op, char *params)
39 elmex 1.1 {
40 root 1.7 int i;
41 elmex 1.1
42 root 1.7 /* Too hard to try and make a header that lines everything up, so just
43     * give a description.
44     */
45     new_draw_info (NDI_UNIQUE, 0, op, "The first column is the name of the body location.");
46     new_draw_info (NDI_UNIQUE, 0, op, "The second column is how many of those locations your body has.");
47     new_draw_info (NDI_UNIQUE, 0, op, "The third column is how many slots in that location are available.");
48     for (i = 0; i < NUM_BODY_LOCATIONS; i++)
49     {
50     /* really debugging - normally body_used should not be set to anything
51     * if body_info isn't also set.
52     */
53     if (op->body_info[i] || op->body_used[i])
54     {
55     new_draw_info_format (NDI_UNIQUE, 0, op, "%-30s %5d %5d", body_locations[i].use_name, op->body_info[i], op->body_used[i]);
56 root 1.3 }
57 elmex 1.1 }
58 root 1.7 if (!QUERY_FLAG (op, FLAG_USE_ARMOUR))
59     new_draw_info (NDI_UNIQUE, 0, op, "You are not allowed to wear armor");
60     if (!QUERY_FLAG (op, FLAG_USE_WEAPON))
61     new_draw_info (NDI_UNIQUE, 0, op, "You are not allowed to use weapons");
62 elmex 1.1
63 root 1.7 return 1;
64 elmex 1.1 }
65    
66    
67 root 1.7 int
68     command_motd (object *op, char *params)
69 elmex 1.1 {
70 root 1.7 display_motd (op);
71     return 1;
72 elmex 1.1 }
73    
74     /*
75     * Pretty much identical to current map_info, but on a bigger scale
76     * This function returns the name of the players current region, and
77     * a description of it. It is there merely for flavour text.
78     */
79 root 1.7 void
80     current_region_info (object *op)
81     {
82 root 1.38 if (region *reg = op->region ())
83 root 1.44 new_draw_info_format (NDI_UNIQUE, 0, op, "You are %s.\n%s", &reg->longname, &reg->msg);
84 elmex 1.1 }
85    
86 root 1.7 void
87     current_map_info (object *op)
88     {
89 root 1.9 maptile *m = op->map;
90 elmex 1.1
91 root 1.7 if (!m)
92     return;
93 elmex 1.1
94 root 1.44 new_draw_info_format (NDI_UNIQUE, 0, op, "%s (%s) %s", &m->name, &m->path, &op->region ()->longname);
95 elmex 1.1
96 root 1.7 if (QUERY_FLAG (op, FLAG_WIZ))
97 root 1.38 new_draw_info_format (NDI_UNIQUE, 0, op,
98     "players:%d difficulty:%d size:%dx%d start:%dx%d timeout %ld",
99     m->players, m->difficulty, m->width, m->height, m->enter_x, m->enter_y, m->timeout);
100 elmex 1.1
101 root 1.7 if (m->msg)
102     new_draw_info (NDI_UNIQUE, NDI_NAVY, op, m->msg);
103 elmex 1.1 }
104    
105     #ifdef DEBUG_MALLOC_LEVEL
106 root 1.7 int
107     command_malloc_verify (object *op, char *parms)
108 elmex 1.1 {
109 root 1.7 extern int malloc_verify (void);
110 elmex 1.1
111 root 1.7 if (!malloc_verify ())
112     new_draw_info (NDI_UNIQUE, 0, op, "Heap is corrupted.");
113     else
114     new_draw_info (NDI_UNIQUE, 0, op, "Heap checks out OK.");
115     return 1;
116     }
117 elmex 1.1 #endif
118    
119 root 1.7 int
120     command_whereabouts (object *op, char *params)
121     {
122 root 1.38 //TODO: should obviously not waste space in struct region for this.
123 root 1.7 /*
124     * reset the counter on the region, then use it to store the number of
125     * players there.
126     * I don't know how thread-safe this would be, I suspect not very....
127     */
128 root 1.41 for_all_regions (rgn)
129     rgn->counter = 0;
130 root 1.38
131 root 1.28 for_all_players (pl)
132 root 1.38 if (pl->ob->map)
133     ++pl->ob->region ()->counter;
134 root 1.7
135     /* we only want to print out by places with a 'longname' field... */
136 root 1.41 for_all_regions (rgn)
137 root 1.7 {
138 root 1.41 if (!rgn->longname && rgn->counter > 0)
139 root 1.7 {
140 root 1.41 if (rgn->parent)
141 root 1.7 {
142 root 1.41 rgn->parent->counter += rgn->counter;
143     rgn->counter = 0;
144 root 1.3 }
145 root 1.7 else /*uh oh, we shouldn't be here. */
146 root 1.41 LOG (llevError, "command_whereabouts() Region %s with no longname has no parent", &rgn->name);
147 root 1.3 }
148     }
149 root 1.38
150 root 1.7 new_draw_info_format (NDI_UNIQUE, 0, op, "In the world currently there are:");
151 root 1.38
152 root 1.41 for_all_regions (rgn)
153     if (rgn->counter)
154 root 1.44 new_draw_info_format (NDI_UNIQUE, 0, op, "%u players %s", rgn->counter, &rgn->longname);
155 root 1.38
156 root 1.7 return 1;
157 elmex 1.1 }
158    
159     typedef struct
160 root 1.7 {
161     char namebuf[MAX_BUF];
162     int login_order;
163     } chars_names;
164 elmex 1.1
165 root 1.7 int
166     command_afk (object *op, char *params)
167     {
168 root 1.28 if ((op->contr->ns->afk = !op->contr->ns->afk))
169     new_draw_info (NDI_UNIQUE, 0, op, "You are no longer AFK");
170 root 1.7 else
171 root 1.28 new_draw_info (NDI_UNIQUE, 0, op, "You are now AFK");
172 root 1.24
173 root 1.7 return 1;
174 elmex 1.1 }
175    
176 root 1.7 int
177     command_mapinfo (object *op, char *params)
178 elmex 1.1 {
179 root 1.7 current_map_info (op);
180     return 1;
181     }
182 elmex 1.1
183 root 1.7 int
184     command_whereami (object *op, char *params)
185 elmex 1.1 {
186 root 1.7 current_region_info (op);
187     return 1;
188 elmex 1.1 }
189    
190 root 1.7 int
191     command_time (object *op, char *params)
192 elmex 1.1 {
193 root 1.2 print_tod (op);
194     return 1;
195     }
196 elmex 1.1
197 root 1.7 int
198     command_weather (object *op, char *params)
199 elmex 1.1 {
200 root 1.33 #if 0
201 root 1.7 int wx, wy, temp, sky;
202     char buf[MAX_BUF];
203    
204     if (settings.dynamiclevel < 1)
205     return 1;
206    
207     if (op->map == NULL)
208     return 1;
209    
210     if (worldmap_to_weathermap (op->x, op->y, &wx, &wy, op->map) != 0)
211     return 1;
212    
213     if (QUERY_FLAG (op, FLAG_WIZ))
214     {
215     /* dump the weather, Dm style! Yo! */
216     new_draw_info_format (NDI_UNIQUE, 0, op, "Real temp: %d", real_world_temperature (op->x, op->y, op->map));
217     new_draw_info_format (NDI_UNIQUE, 0, op, "Base temp: %d", weathermap[wx][wy].temp);
218     new_draw_info_format (NDI_UNIQUE, 0, op, "Humid: %d", weathermap[wx][wy].humid);
219     new_draw_info_format (NDI_UNIQUE, 0, op, "Wind: dir=%d speed=%d", weathermap[wx][wy].winddir, weathermap[wx][wy].windspeed);
220     new_draw_info_format (NDI_UNIQUE, 0, op, "Pressure: %d", weathermap[wx][wy].pressure);
221     new_draw_info_format (NDI_UNIQUE, 0, op, "Avg Elevation: %d", weathermap[wx][wy].avgelev);
222     new_draw_info_format (NDI_UNIQUE, 0, op, "Rainfall: %d Water: %d", weathermap[wx][wy].rainfall, weathermap[wx][wy].water);
223     }
224    
225     temp = real_world_temperature (op->x, op->y, op->map);
226     new_draw_info_format (NDI_UNIQUE, 0, op, "It's currently %d degrees " "Centigrade out.", temp);
227    
228     /* humid */
229     if (weathermap[wx][wy].humid < 20)
230     new_draw_info (NDI_UNIQUE, 0, op, "It is very dry.");
231     else if (weathermap[wx][wy].humid < 40)
232     new_draw_info (NDI_UNIQUE, 0, op, "It is very comfortable today.");
233     else if (weathermap[wx][wy].humid < 60)
234     new_draw_info (NDI_UNIQUE, 0, op, "It is a bit muggy.");
235     else if (weathermap[wx][wy].humid < 80)
236     new_draw_info (NDI_UNIQUE, 0, op, "It is muggy.");
237     else
238     new_draw_info (NDI_UNIQUE, 0, op, "It is uncomfortably muggy.");
239 elmex 1.1
240 root 1.7 /* wind */
241     switch (weathermap[wx][wy].winddir)
242     {
243     case 1:
244     sprintf (buf, "north");
245     break;
246     case 2:
247     sprintf (buf, "northeast");
248     break;
249     case 3:
250     sprintf (buf, "east");
251     break;
252     case 4:
253     sprintf (buf, "southeast");
254     break;
255     case 5:
256     sprintf (buf, "south");
257     break;
258     case 6:
259     sprintf (buf, "southwest");
260     break;
261     case 7:
262     sprintf (buf, "west");
263     break;
264     case 8:
265     sprintf (buf, "northwest");
266     break;
267     }
268     if (weathermap[wx][wy].windspeed < 5)
269     new_draw_info_format (NDI_UNIQUE, 0, op, "There is a mild breeze " "coming from the %s.", buf);
270     else if (weathermap[wx][wy].windspeed < 10)
271     new_draw_info_format (NDI_UNIQUE, 0, op, "There is a strong breeze " "coming from the %s.", buf);
272     else if (weathermap[wx][wy].windspeed < 15)
273     new_draw_info_format (NDI_UNIQUE, 0, op, "There is a light wind " "coming from the %s.", buf);
274     else if (weathermap[wx][wy].windspeed < 25)
275     new_draw_info_format (NDI_UNIQUE, 0, op, "There is a strong wind " "coming from the %s.", buf);
276     else if (weathermap[wx][wy].windspeed < 35)
277     new_draw_info_format (NDI_UNIQUE, 0, op, "There is a heavy wind " "coming from the %s.", buf);
278     else
279     new_draw_info_format (NDI_UNIQUE, 0, op, "The wind from the %s is " "incredibly strong!", buf);
280 elmex 1.1
281 root 1.7 sky = weathermap[wx][wy].sky;
282     if (temp <= 0 && sky > SKY_OVERCAST && sky < SKY_FOG)
283     sky += 10; /*let it snow */
284     switch (sky)
285     {
286     case SKY_CLEAR:
287     new_draw_info (NDI_UNIQUE, 0, op, "There isn''t a cloud in the sky.");
288     break;
289     case SKY_LIGHTCLOUD:
290     new_draw_info (NDI_UNIQUE, 0, op, "There are a few light clouds in the sky.");
291     break;
292     case SKY_OVERCAST:
293     new_draw_info (NDI_UNIQUE, 0, op, "The sky is cloudy and dreary.");
294     break;
295     case SKY_LIGHT_RAIN:
296     new_draw_info (NDI_UNIQUE, 0, op, "It is raining softly.");
297     break;
298     case SKY_RAIN:
299     new_draw_info (NDI_UNIQUE, 0, op, "It is raining.");
300     break;
301     case SKY_HEAVY_RAIN:
302     new_draw_info (NDI_UNIQUE, 0, op, "It is raining heavily.");
303     break;
304     case SKY_HURRICANE:
305     new_draw_info (NDI_UNIQUE, 0, op, "There is a heavy storm! You should go inside!");
306     break;
307     case SKY_FOG:
308     new_draw_info (NDI_UNIQUE, 0, op, "It''s foggy and miserable.");
309     break;
310     case SKY_HAIL:
311     new_draw_info (NDI_UNIQUE, 0, op, "It''s hailing out! Take cover!");
312     break;
313     case SKY_LIGHT_SNOW:
314     new_draw_info (NDI_UNIQUE, 0, op, "Snow is gently falling from the sky.");
315     break;
316     case SKY_SNOW:
317     new_draw_info (NDI_UNIQUE, 0, op, "It''s snowing out.");
318     break;
319     case SKY_HEAVY_SNOW:
320     new_draw_info (NDI_UNIQUE, 0, op, "The snow is falling very heavily now.");
321     break;
322     case SKY_BLIZZARD:
323     new_draw_info (NDI_UNIQUE, 0, op, "A full blown blizzard is in effect. You might want to take cover!");
324     break;
325 elmex 1.1 }
326 root 1.33 #endif
327 root 1.7 return 1;
328 elmex 1.1 }
329    
330 root 1.7 int
331     command_hiscore (object *op, char *params)
332 elmex 1.1 {
333 root 1.7 display_high_score (op, op == NULL ? 9999 : 50, params);
334     return 1;
335     }
336 elmex 1.1
337 root 1.7 int
338     command_debug (object *op, char *params)
339 elmex 1.1 {
340 root 1.7 int i;
341     char buf[MAX_BUF];
342    
343     if (params == NULL || !sscanf (params, "%d", &i))
344     {
345     sprintf (buf, "Global debug level is %d.", settings.debug);
346     new_draw_info (NDI_UNIQUE, 0, op, buf);
347 elmex 1.1 return 1;
348     }
349 root 1.7 if (op != NULL && !QUERY_FLAG (op, FLAG_WIZ))
350     {
351     new_draw_info (NDI_UNIQUE, 0, op, "Privileged command.");
352 elmex 1.1 return 1;
353     }
354 root 1.7 settings.debug = (enum LogLevel) FABS (i);
355     sprintf (buf, "Set debug level to %d.", i);
356     new_draw_info (NDI_UNIQUE, 0, op, buf);
357     return 1;
358     }
359 elmex 1.1
360    
361     /*
362     * Those dumps should be just one dump with good parser
363     */
364    
365 root 1.7 int
366     command_dumpbelow (object *op, char *params)
367 elmex 1.1 {
368 root 1.7 if (op && op->below)
369     {
370 root 1.14 char *dump = dump_object (op->below);
371     new_draw_info (NDI_UNIQUE, 0, op, dump);
372     free (dump);
373 elmex 1.1 /* Let's push that item on the dm's stack */
374 root 1.7 dm_stack_push (op->contr, op->below->count);
375     }
376 elmex 1.1 return 0;
377     }
378    
379 root 1.7 int
380     command_dumpfriendlyobjects (object *op, char *params)
381 elmex 1.1 {
382 root 1.7 dump_friendly_objects ();
383 elmex 1.1 return 0;
384     }
385    
386 root 1.7 int
387     command_printlos (object *op, char *params)
388 elmex 1.1 {
389     if (op)
390 root 1.7 print_los (op);
391 elmex 1.1 return 0;
392     }
393    
394    
395 root 1.7 int
396     command_version (object *op, char *params)
397 elmex 1.1 {
398 root 1.7 version (op);
399     return 0;
400 elmex 1.1 }
401    
402     #ifndef BUG_LOG
403 root 1.7 # define BUG_LOG "bug_log"
404 elmex 1.1 #endif
405 root 1.7 void
406     bug_report (const char *reportstring)
407     {
408     FILE *fp;
409    
410     if ((fp = fopen (BUG_LOG, "a")) != NULL)
411     {
412     fprintf (fp, "%s\n", reportstring);
413     fclose (fp);
414     }
415     else
416     {
417     LOG (llevError, "Cannot write bugs file %s: %s\n", BUG_LOG, strerror (errno));
418 elmex 1.1 }
419 root 1.7 }
420    
421     int
422     command_output_sync (object *op, char *params)
423     {
424     int val;
425    
426     if (!params)
427     {
428     new_draw_info_format (NDI_UNIQUE, 0, op, "Output sync time is presently %d", op->contr->outputs_sync);
429     return 1;
430     }
431     val = atoi (params);
432     if (val > 0)
433     {
434     op->contr->outputs_sync = val;
435     new_draw_info_format (NDI_UNIQUE, 0, op, "Output sync time now set to %d", op->contr->outputs_sync);
436     }
437     else
438     new_draw_info (NDI_UNIQUE, 0, op, "Invalid value for output_sync.");
439 elmex 1.1
440 root 1.7 return 1;
441 elmex 1.1 }
442    
443 root 1.7 int
444     command_output_count (object *op, char *params)
445 elmex 1.1 {
446 root 1.7 int val;
447 elmex 1.1
448 root 1.7 if (!params)
449     {
450     new_draw_info_format (NDI_UNIQUE, 0, op, "Output count is presently %d", op->contr->outputs_count);
451     return 1;
452 elmex 1.1 }
453 root 1.7 val = atoi (params);
454     if (val > 0)
455     {
456     op->contr->outputs_count = val;
457     new_draw_info_format (NDI_UNIQUE, 0, op, "Output count now set to %d", op->contr->outputs_count);
458     }
459     else
460     new_draw_info (NDI_UNIQUE, 0, op, "Invalid value for output_count.");
461 elmex 1.1
462 root 1.7 return 1;
463 elmex 1.1 }
464    
465 root 1.7 int
466     command_listen (object *op, char *params)
467 elmex 1.1 {
468     int i;
469    
470 root 1.7 if (params == NULL || !sscanf (params, "%d", &i))
471     {
472     new_draw_info_format (NDI_UNIQUE, 0, op, "Set listen to what (presently %d)?", op->contr->listening);
473 elmex 1.1 return 1;
474     }
475 root 1.7 op->contr->listening = (char) i;
476     new_draw_info_format (NDI_UNIQUE, 0, op, "Your verbose level is now %d.", i);
477     return 1;
478 elmex 1.1 }
479    
480     /* Prints out some useful information for the character. Everything we print
481     * out can be determined by the docs, so we aren't revealing anything extra -
482     * rather, we are making it convenient to find the values. params have
483     * no meaning here.
484     */
485 root 1.7 int
486     command_statistics (object *pl, char *params)
487 elmex 1.1 {
488 root 1.7 if (!pl->contr)
489     return 1;
490 root 1.18 new_draw_info_format (NDI_UNIQUE, 0, pl, " Experience: %" PRId64, pl->stats.exp);
491     new_draw_info_format (NDI_UNIQUE, 0, pl, " Next Level: %" PRId64, level_exp (pl->level + 1, pl->expmul));
492 root 1.7 new_draw_info (NDI_UNIQUE, 0, pl, "\nStat Nat/Real/Max");
493 elmex 1.1
494 root 1.7 new_draw_info_format (NDI_UNIQUE, 0, pl, "Str %2d/ %3d/%3d",
495     pl->contr->orig_stats.Str, pl->stats.Str, 20 + pl->arch->clone.stats.Str);
496     new_draw_info_format (NDI_UNIQUE, 0, pl, "Dex %2d/ %3d/%3d",
497     pl->contr->orig_stats.Dex, pl->stats.Dex, 20 + pl->arch->clone.stats.Dex);
498     new_draw_info_format (NDI_UNIQUE, 0, pl, "Con %2d/ %3d/%3d",
499     pl->contr->orig_stats.Con, pl->stats.Con, 20 + pl->arch->clone.stats.Con);
500     new_draw_info_format (NDI_UNIQUE, 0, pl, "Int %2d/ %3d/%3d",
501     pl->contr->orig_stats.Int, pl->stats.Int, 20 + pl->arch->clone.stats.Int);
502     new_draw_info_format (NDI_UNIQUE, 0, pl, "Wis %2d/ %3d/%3d",
503     pl->contr->orig_stats.Wis, pl->stats.Wis, 20 + pl->arch->clone.stats.Wis);
504     new_draw_info_format (NDI_UNIQUE, 0, pl, "Pow %2d/ %3d/%3d",
505     pl->contr->orig_stats.Pow, pl->stats.Pow, 20 + pl->arch->clone.stats.Pow);
506     new_draw_info_format (NDI_UNIQUE, 0, pl, "Cha %2d/ %3d/%3d",
507     pl->contr->orig_stats.Cha, pl->stats.Cha, 20 + pl->arch->clone.stats.Cha);
508     new_draw_info_format (NDI_UNIQUE, 0, pl, "\nAttack Mode: %s", pl->contr->peaceful ? "Peaceful" : "Hostile");
509 elmex 1.1
510 root 1.7 /* Can't think of anything else to print right now */
511     return 0;
512 elmex 1.1 }
513    
514 root 1.7 int
515     command_fix_me (object *op, char *params)
516 elmex 1.1 {
517 root 1.7 sum_weight (op);
518 root 1.27 op->update_stats ();
519 root 1.7 return 1;
520 elmex 1.1 }
521    
522 root 1.7 int
523     command_logs (object *op, char *params)
524 elmex 1.1 {
525 root 1.10 new_draw_info (NDI_UNIQUE, 0, op, "Nobody is currently logging kills.");
526 elmex 1.1
527 root 1.7 return 1;
528 elmex 1.1 }
529    
530 root 1.7 int
531     command_applymode (object *op, char *params)
532 elmex 1.1 {
533 root 1.7 unapplymode unapply = op->contr->unapply;
534     static const char *const types[] = { "nochoice", "never", "always" };
535 elmex 1.1
536 root 1.7 if (!params)
537     {
538     new_draw_info_format (NDI_UNIQUE, 0, op, "applymode is set to %s", types[op->contr->unapply]);
539     return 1;
540     }
541    
542     if (!strcmp (params, "nochoice"))
543     op->contr->unapply = unapply_nochoice;
544     else if (!strcmp (params, "never"))
545     op->contr->unapply = unapply_never;
546     else if (!strcmp (params, "always"))
547     op->contr->unapply = unapply_always;
548     else
549     {
550     new_draw_info_format (NDI_UNIQUE, 0, op, "applymode: Unknown options %s, valid options are nochoice, never, always", params);
551     return 0;
552     }
553 root 1.38
554 root 1.7 new_draw_info_format (NDI_UNIQUE, 0, op, "Applymode %s set to %s",
555     (unapply == op->contr->unapply ? "" : " now"), types[op->contr->unapply]);
556     return 1;
557 elmex 1.1 }
558    
559 root 1.7 int
560     command_bowmode (object *op, char *params)
561 elmex 1.1 {
562 root 1.7 bowtype_t oldtype = op->contr->bowtype;
563     static const char *const types[] = { "normal", "threewide", "spreadshot", "firenorth",
564     "firene", "fireeast", "firese", "firesouth",
565     "firesw", "firewest", "firenw", "bestarrow"
566     };
567     char buf[MAX_BUF];
568     int i, found;
569    
570     if (!params)
571     {
572     new_draw_info_format (NDI_UNIQUE, 0, op, "bowmode is set to %s", types[op->contr->bowtype]);
573     return 1;
574     }
575    
576     for (i = 0, found = 0; i <= bow_bestarrow; i++)
577     {
578     if (!strcmp (params, types[i]))
579     {
580     found++;
581     op->contr->bowtype = (bowtype_t) i;
582     break;
583 root 1.3 }
584 elmex 1.1 }
585 root 1.38
586 root 1.7 if (!found)
587     {
588     sprintf (buf, "bowmode: Unknown options %s, valid options are:", params);
589     for (i = 0; i <= bow_bestarrow; i++)
590     {
591     strcat (buf, " ");
592     strcat (buf, types[i]);
593     if (i < bow_nw)
594     strcat (buf, ",");
595     else
596     strcat (buf, ".");
597 root 1.3 }
598 root 1.7 new_draw_info_format (NDI_UNIQUE, 0, op, buf);
599     return 0;
600 elmex 1.1 }
601 root 1.38
602 root 1.7 new_draw_info_format (NDI_UNIQUE, 0, op, "bowmode %s set to %s", (oldtype == op->contr->bowtype ? "" : "now"), types[op->contr->bowtype]);
603     return 1;
604 elmex 1.1 }
605    
606 root 1.7 int
607     command_petmode (object *op, char *params)
608 elmex 1.1 {
609 root 1.7 petmode_t oldtype = op->contr->petmode;
610     static const char *const types[] = { "normal", "sad", "defend", "arena" };
611 elmex 1.1
612 root 1.7 if (!params)
613     {
614     new_draw_info_format (NDI_UNIQUE, 0, op, "petmode is set to %s", types[op->contr->petmode]);
615     return 1;
616     }
617    
618     if (!strcmp (params, "normal"))
619     op->contr->petmode = pet_normal;
620     else if (!strcmp (params, "sad"))
621     op->contr->petmode = pet_sad;
622     else if (!strcmp (params, "defend"))
623     op->contr->petmode = pet_defend;
624     else if (!strcmp (params, "arena"))
625     op->contr->petmode = pet_arena;
626     else
627     {
628     new_draw_info_format (NDI_UNIQUE, 0, op,
629     "petmode: Unknown options %s, valid options are normal," "sad (seek and destroy), defend, arena", params);
630     return 0;
631     }
632     new_draw_info_format (NDI_UNIQUE, 0, op, "petmode %s set to %s", (oldtype == op->contr->petmode ? "" : "now"), types[op->contr->petmode]);
633     return 1;
634 elmex 1.1 }
635    
636 root 1.7 int
637     command_showpets (object *op, char *params)
638 elmex 1.1 {
639 root 1.7 objectlink *obl, *next;
640     int counter = 0, target = 0;
641     int have_shown_pet = 0;
642    
643     if (params != NULL)
644     target = atoi (params);
645     for (obl = first_friendly_object; obl != NULL; obl = next)
646     {
647     object *ob = obl->ob;
648    
649     next = obl->next;
650 root 1.22 if (ob->owner == op)
651 root 1.7 {
652     if (target == 0)
653     {
654     if (counter == 0)
655     new_draw_info (NDI_UNIQUE, 0, op, "Pets:");
656     new_draw_info_format (NDI_UNIQUE, 0, op, "%d %s - level %d", ++counter, &ob->name, ob->level);
657     }
658     else if (!have_shown_pet && ++counter == target)
659     {
660     new_draw_info_format (NDI_UNIQUE, 0, op, "level %d %s", ob->level, &ob->name);
661     new_draw_info_format (NDI_UNIQUE, 0, op, "%d/%d HP, %d/%d SP", ob->stats.hp, ob->stats.maxhp, ob->stats.sp, ob->stats.maxsp);
662     /* this is not a nice way to do this, it should be made to be more like the statistics command */
663     new_draw_info_format (NDI_UNIQUE, 0, op, "Str %d", ob->stats.Str);
664     new_draw_info_format (NDI_UNIQUE, 0, op, "Dex %d", ob->stats.Dex);
665     new_draw_info_format (NDI_UNIQUE, 0, op, "Con %d", ob->stats.Con);
666     new_draw_info_format (NDI_UNIQUE, 0, op, "Int %d", ob->stats.Int);
667     new_draw_info_format (NDI_UNIQUE, 0, op, "Wis %d", ob->stats.Wis);
668     new_draw_info_format (NDI_UNIQUE, 0, op, "Cha %d", ob->stats.Cha);
669     new_draw_info_format (NDI_UNIQUE, 0, op, "Pow %d", ob->stats.Pow);
670     new_draw_info_format (NDI_UNIQUE, 0, op, "wc %d damage %d ac %d ", ob->stats.wc, ob->stats.dam, ob->stats.ac);
671     have_shown_pet = 1;
672 root 1.3 }
673     }
674 elmex 1.1 }
675 root 1.7 if (counter == 0)
676     new_draw_info (NDI_UNIQUE, 0, op, "you have no pets.");
677     else if (target != 0 && have_shown_pet == 0)
678     new_draw_info (NDI_UNIQUE, 0, op, "no such pet.");
679     return 0;
680 elmex 1.1 }
681    
682 root 1.7 int
683     command_usekeys (object *op, char *params)
684 elmex 1.1 {
685 root 1.7 usekeytype oldtype = op->contr->usekeys;
686     static const char *const types[] = { "inventory", "keyrings", "containers" };
687 elmex 1.1
688 root 1.7 if (!params)
689     {
690     new_draw_info_format (NDI_UNIQUE, 0, op, "usekeys is set to %s", types[op->contr->usekeys]);
691     return 1;
692     }
693    
694     if (!strcmp (params, "inventory"))
695     op->contr->usekeys = key_inventory;
696     else if (!strcmp (params, "keyrings"))
697     op->contr->usekeys = keyrings;
698     else if (!strcmp (params, "containers"))
699     op->contr->usekeys = containers;
700     else
701     {
702     new_draw_info_format (NDI_UNIQUE, 0, op, "usekeys: Unknown options %s, valid options are inventory, keyrings, containers", params);
703     return 0;
704     }
705     new_draw_info_format (NDI_UNIQUE, 0, op, "usekeys %s set to %s", (oldtype == op->contr->usekeys ? "" : "now"), types[op->contr->usekeys]);
706     return 1;
707 elmex 1.1 }
708    
709 root 1.7 int
710     command_resistances (object *op, char *params)
711 elmex 1.1 {
712 root 1.7 int i;
713 elmex 1.1
714 root 1.7 if (!op)
715     return 0;
716    
717     for (i = 0; i < NROFATTACKS; i++)
718     {
719     if (i == ATNR_INTERNAL)
720     continue;
721 elmex 1.1
722 root 1.7 new_draw_info_format (NDI_UNIQUE, 0, op, "%-20s %+5d", attacktype_desc[i], op->resist[i]);
723 elmex 1.1 }
724    
725 root 1.7 /* If dragon player, let's display natural resistances */
726     if (is_dragon_pl (op))
727     {
728     int attack;
729     object *tmp;
730    
731     for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
732 elmex 1.1 {
733 root 1.7 if ((tmp->type == FORCE) && (strcmp (tmp->arch->name, "dragon_skin_force") == 0))
734 elmex 1.1 {
735 root 1.7 new_draw_info (NDI_UNIQUE, 0, op, "\nNatural skin resistances:");
736     for (attack = 0; attack < NROFATTACKS; attack++)
737 elmex 1.1 {
738 root 1.7 if (atnr_is_dragon_enabled (attack))
739 elmex 1.1 {
740 root 1.7 new_draw_info_format (NDI_UNIQUE, 0, op, "%s: %d", change_resist_msg[attack], tmp->resist[attack]);
741 elmex 1.1 }
742     }
743 root 1.7 break;
744 elmex 1.1 }
745     }
746 root 1.7 }
747 elmex 1.1
748 root 1.7 return 0;
749 elmex 1.1 }
750 root 1.7
751 elmex 1.1 /*
752     * Actual commands.
753     * Those should be in small separate files (c_object.c, c_wiz.c, cmove.c,...)
754     */
755    
756    
757 root 1.7 static void
758     help_topics (object *op, int what)
759 elmex 1.1 {
760 root 1.7 DIR *dirp;
761     struct dirent *de;
762     char filename[MAX_BUF], line[80];
763     int namelen, linelen = 0;
764    
765     switch (what)
766     {
767 root 1.21 case 1:
768     sprintf (filename, "%s/wizhelp", settings.datadir);
769     new_draw_info (NDI_UNIQUE, 0, op, " Wiz commands:");
770     break;
771     case 3:
772     sprintf (filename, "%s/mischelp", settings.datadir);
773     new_draw_info (NDI_UNIQUE, 0, op, " Misc help:");
774     break;
775     default:
776     sprintf (filename, "%s/help", settings.datadir);
777     new_draw_info (NDI_UNIQUE, 0, op, " Commands:");
778     break;
779 root 1.7 }
780 root 1.21
781 root 1.7 if (!(dirp = opendir (filename)))
782     return;
783    
784     line[0] = '\0';
785 pippijn 1.45 while ((de = readdir (dirp)))
786 root 1.7 {
787 root 1.21 namelen = strlen (de->d_name);
788 root 1.7 if (namelen <= 2 && *de->d_name == '.' && (namelen == 1 || de->d_name[1] == '.'))
789     continue;
790     linelen += namelen + 1;
791     if (linelen > 42)
792     {
793     new_draw_info (NDI_UNIQUE, 0, op, line);
794     sprintf (line, " %s", de->d_name);
795     linelen = namelen + 1;
796     continue;
797 root 1.3 }
798 root 1.7 strcat (line, " ");
799     strcat (line, de->d_name);
800 elmex 1.1 }
801 root 1.7 new_draw_info (NDI_UNIQUE, 0, op, line);
802     closedir (dirp);
803 elmex 1.1 }
804    
805 root 1.7 static void
806     show_commands (object *op, int what)
807 elmex 1.1 {
808     char line[80];
809 root 1.7 int i, size, namelen, linelen = 0;
810 elmex 1.1 CommArray_s *ap;
811     extern CommArray_s Commands[], WizCommands[];
812     extern const int CommandsSize, WizCommandsSize;
813 root 1.7
814     switch (what)
815     {
816     case 1:
817     ap = WizCommands;
818     size = WizCommandsSize;
819     new_draw_info (NDI_UNIQUE, 0, op, " Wiz commands:");
820     break;
821     case 2:
822     ap = CommunicationCommands;
823     size = CommunicationCommandSize;
824     new_draw_info (NDI_UNIQUE, 0, op, " Communication commands:");
825     break;
826     default:
827     ap = Commands;
828     size = CommandsSize;
829     new_draw_info (NDI_UNIQUE, 0, op, " Commands:");
830     break;
831     }
832    
833     line[0] = '\0';
834     for (i = 0; i < size; i++)
835     {
836     namelen = strlen (ap[i].name);
837     linelen += namelen + 1;
838     if (linelen > 42)
839     {
840     new_draw_info (NDI_UNIQUE, 0, op, line);
841     sprintf (line, " %s", ap[i].name);
842     linelen = namelen + 1;
843     continue;
844     }
845     strcat (line, " ");
846     strcat (line, ap[i].name);
847     }
848     new_draw_info (NDI_UNIQUE, 0, op, line);
849 elmex 1.1 }
850    
851    
852 root 1.7 int
853     command_help (object *op, char *params)
854 elmex 1.1 {
855     struct stat st;
856     FILE *fp;
857     char filename[MAX_BUF], line[MAX_BUF];
858     int len;
859    
860 root 1.7 if (op != NULL)
861     clear_win_info (op);
862 elmex 1.1
863     /*
864     * Main help page?
865     */
866 root 1.7 if (!params)
867     {
868     sprintf (filename, "%s/def_help", settings.datadir);
869     if ((fp = fopen (filename, "r")) == NULL)
870     {
871     LOG (llevError, "Cannot open help file %s: %s\n", filename, strerror (errno));
872     return 0;
873     }
874     while (fgets (line, MAX_BUF, fp))
875     {
876     line[MAX_BUF - 1] = '\0';
877     len = strlen (line) - 1;
878     if (line[len] == '\n')
879     line[len] = '\0';
880     new_draw_info (NDI_UNIQUE, 0, op, line);
881     }
882     fclose (fp);
883 elmex 1.1 return 0;
884     }
885    
886     /*
887     * Topics list
888     */
889 root 1.7 if (!strcmp (params, "topics"))
890     {
891     help_topics (op, 3);
892     help_topics (op, 0);
893     if (QUERY_FLAG (op, FLAG_WIZ))
894     help_topics (op, 1);
895     return 0;
896 elmex 1.1 }
897 root 1.7
898 elmex 1.1 /*
899     * Commands list
900     */
901 root 1.7 if (!strcmp (params, "commands"))
902     {
903     show_commands (op, 0);
904     show_commands (op, 2); /* show comm commands */
905     if (QUERY_FLAG (op, FLAG_WIZ))
906     show_commands (op, 1);
907     return 0;
908     }
909 elmex 1.1
910     /*
911     * User wants info about command
912     */
913 root 1.7 if (strchr (params, '.') || strchr (params, ' ') || strchr (params, '/'))
914     {
915     sprintf (line, "Illegal characters in '%s'", params);
916     new_draw_info (NDI_UNIQUE, 0, op, line);
917     return 0;
918     }
919 elmex 1.1
920 root 1.7 sprintf (filename, "%s/mischelp/%s", settings.datadir, params);
921     if (stat (filename, &st) || !S_ISREG (st.st_mode))
922     {
923     if (op)
924     {
925     sprintf (filename, "%s/help/%s", settings.datadir, params);
926     if (stat (filename, &st) || !S_ISREG (st.st_mode))
927     {
928     if (QUERY_FLAG (op, FLAG_WIZ))
929     {
930     sprintf (filename, "%s/wizhelp/%s", settings.datadir, params);
931     if (stat (filename, &st) || !S_ISREG (st.st_mode))
932     goto nohelp;
933     }
934     else
935     goto nohelp;
936     }
937     }
938     }
939 elmex 1.1
940     /*
941     * Found that. Just cat it to screen.
942     */
943 root 1.7 if ((fp = fopen (filename, "r")) == NULL)
944     {
945     LOG (llevError, "Cannot open help file %s: %s\n", filename, strerror (errno));
946     return 0;
947     }
948     sprintf (line, "Help about '%s'", params);
949     new_draw_info (NDI_UNIQUE, 0, op, line);
950     while (fgets (line, MAX_BUF, fp))
951     {
952     line[MAX_BUF - 1] = '\0';
953     len = strlen (line) - 1;
954     if (line[len] == '\n')
955     line[len] = '\0';
956     new_draw_info (NDI_UNIQUE, 0, op, line);
957 elmex 1.1 }
958 root 1.7 fclose (fp);
959 elmex 1.1 return 0;
960    
961     /*
962     * No_help -escape
963     */
964 root 1.7 nohelp:
965     sprintf (line, "No help available on '%s'", params);
966     new_draw_info (NDI_UNIQUE, 0, op, line);
967 elmex 1.1 return 0;
968     }
969    
970    
971 root 1.7 int
972     onoff_value (const char *line)
973 elmex 1.1 {
974     int i;
975    
976 root 1.7 if (sscanf (line, "%d", &i))
977 elmex 1.1 return (i != 0);
978 root 1.7 switch (line[0])
979     {
980     case 'o':
981     switch (line[1])
982     {
983     case 'n':
984     return 1; /* on */
985     default:
986     return 0; /* o[ff] */
987     }
988     case 'y': /* y[es] */
989     case 'k': /* k[ylla] */
990     case 's':
991     case 'd':
992     return 1;
993     case 'n': /* n[o] */
994     case 'e': /* e[i] */
995     case 'u':
996     default:
997     return 0;
998     }
999 elmex 1.1 }
1000    
1001 root 1.7 int
1002     command_sound (object *op, char *params)
1003 elmex 1.1 {
1004 root 1.26 if (op->contr->ns->sound)
1005 root 1.7 {
1006 root 1.26 op->contr->ns->sound = 0;
1007 root 1.7 new_draw_info (NDI_UNIQUE, 0, op, "Silence is golden...");
1008     }
1009     else
1010     {
1011 root 1.26 op->contr->ns->sound = 1;
1012 root 1.7 new_draw_info (NDI_UNIQUE, 0, op, "The sounds are enabled.");
1013 elmex 1.1 }
1014 root 1.23
1015 root 1.7 return 1;
1016 elmex 1.1 }
1017    
1018 root 1.7 int
1019     command_title (object *op, char *params)
1020 elmex 1.1 {
1021 root 1.7 char buf[MAX_BUF];
1022    
1023     if (settings.set_title == FALSE)
1024     {
1025     new_draw_info (NDI_UNIQUE, 0, op, "You cannot change your title.");
1026     return 1;
1027 elmex 1.1 }
1028 root 1.7
1029     /* dragon players cannot change titles */
1030     if (is_dragon_pl (op))
1031     {
1032     new_draw_info (NDI_UNIQUE, 0, op, "Dragons cannot change titles.");
1033     return 1;
1034     }
1035    
1036     if (params == NULL)
1037     {
1038     if (op->contr->own_title[0] == '\0')
1039     sprintf (buf, "Your title is '%s'.", op->contr->title);
1040     else
1041     sprintf (buf, "Your title is '%s'.", op->contr->own_title);
1042     new_draw_info (NDI_UNIQUE, 0, op, buf);
1043     return 1;
1044     }
1045     if (strcmp (params, "clear") == 0 || strcmp (params, "default") == 0)
1046     {
1047     if (op->contr->own_title[0] == '\0')
1048     new_draw_info (NDI_UNIQUE, 0, op, "Your title is the default title.");
1049     else
1050     new_draw_info (NDI_UNIQUE, 0, op, "Title set to default.");
1051     op->contr->own_title[0] = '\0';
1052     return 1;
1053     }
1054    
1055     if ((int) strlen (params) >= MAX_NAME)
1056     {
1057     new_draw_info (NDI_UNIQUE, 0, op, "Title too long.");
1058     return 1;
1059     }
1060     strcpy (op->contr->own_title, params);
1061     return 1;
1062 elmex 1.1 }
1063    
1064 root 1.7 int
1065     command_peaceful (object *op, char *params)
1066 elmex 1.1 {
1067 root 1.7 new_draw_info (NDI_UNIQUE, 0, op,
1068     "You cannot change your peaceful setting with this command."
1069     " Please speak to the priest in the temple of Gorokh"
1070     " if you want to become hostile or in temple of Valriel" " if you want to become peaceful again.");
1071 elmex 1.1
1072     /*
1073     if((op->contr->peaceful=!op->contr->peaceful))
1074     new_draw_info(NDI_UNIQUE, 0,op,"You will not attack other players.");
1075     else
1076     new_draw_info(NDI_UNIQUE, 0,op,"You will attack other players.");
1077     */
1078 root 1.7 return 1;
1079 elmex 1.1 }
1080    
1081 root 1.7 int
1082     command_wimpy (object *op, char *params)
1083 elmex 1.1 {
1084 root 1.7 int i;
1085     char buf[MAX_BUF];
1086 elmex 1.1
1087 root 1.7 if (params == NULL || !sscanf (params, "%d", &i))
1088     {
1089     sprintf (buf, "Your current wimpy level is %d.", op->run_away);
1090     new_draw_info (NDI_UNIQUE, 0, op, buf);
1091     return 1;
1092     }
1093     sprintf (buf, "Your new wimpy level is %d.", i);
1094     new_draw_info (NDI_UNIQUE, 0, op, buf);
1095     op->run_away = i;
1096     return 1;
1097 elmex 1.1 }
1098    
1099 root 1.7 int
1100     command_brace (object *op, char *params)
1101 elmex 1.1 {
1102     if (!params)
1103 root 1.7 op->contr->braced = !op->contr->braced;
1104 elmex 1.1 else
1105 root 1.7 op->contr->braced = onoff_value (params);
1106 elmex 1.1
1107 root 1.7 if (op->contr->braced)
1108     new_draw_info (NDI_UNIQUE, 0, op, "You are braced.");
1109 elmex 1.1 else
1110 root 1.7 new_draw_info (NDI_UNIQUE, 0, op, "Not braced.");
1111 elmex 1.1
1112 root 1.27 op->update_stats ();
1113 elmex 1.1 return 0;
1114     }
1115    
1116 root 1.7 int
1117     command_kill_pets (object *op, char *params)
1118 elmex 1.1 {
1119 root 1.7 objectlink *obl, *next;
1120     int counter = 0, removecount = 0;
1121    
1122     if (params == NULL)
1123     {
1124     terminate_all_pets (op);
1125     new_draw_info (NDI_UNIQUE, 0, op, "Your pets have been killed.");
1126     }
1127     else
1128     {
1129     int target = atoi (params);
1130    
1131     for (obl = first_friendly_object; obl != NULL; obl = next)
1132     {
1133     object *ob = obl->ob;
1134    
1135     next = obl->next;
1136 root 1.22 if (ob->owner == op)
1137 root 1.7 if (++counter == target || (target == 0 && !strcasecmp (ob->name, params)))
1138     {
1139 root 1.20 ob->destroy ();
1140 root 1.3 removecount++;
1141 root 1.7 }
1142 root 1.3 }
1143 root 1.7 if (removecount != 0)
1144     new_draw_info_format (NDI_UNIQUE, 0, op, "killed %d pets.\n", removecount);
1145     else
1146     new_draw_info (NDI_UNIQUE, 0, op, "Couldn't find any suitable pets to kill.\n");
1147 elmex 1.1 }
1148 root 1.7 return 0;
1149 elmex 1.1 }