ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/c_misc.C
Revision: 1.43
Committed: Mon Feb 5 01:24:45 2007 UTC (17 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.42: +1 -1 lines
Log Message:
replace amny strcpy by checked assign's

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