ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/c_misc.C
Revision: 1.39
Committed: Mon Jan 29 14:46:01 2007 UTC (17 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.38: +3 -3 lines
Log Message:
partial region cleanup

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.7 strcpy (buf, op->name);
85     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     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.38 for (region *reg = first_region; reg; reg = reg->next)
150     reg->counter = 0;
151    
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.38 for (region *reg = first_region; reg; reg = reg->next)
158 root 1.7 {
159     if (reg->longname == NULL && reg->counter > 0)
160     {
161 root 1.38 if (reg->parent)
162 root 1.7 {
163     reg->parent->counter += reg->counter;
164     reg->counter = 0;
165 root 1.3 }
166 root 1.7 else /*uh oh, we shouldn't be here. */
167 root 1.39 LOG (llevError, "command_whereabouts() Region %s with no longname has no parent", &reg->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     for (region *reg = first_region; reg; reg = reg->next)
174     if (reg->counter)
175 root 1.39 new_draw_info_format (NDI_UNIQUE, 0, op, "%u players in %s", reg->counter, reg->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_archs (object *op, char *params)
353 elmex 1.1 {
354 root 1.7 arch_info (op);
355     return 1;
356     }
357 elmex 1.1
358 root 1.7 int
359     command_hiscore (object *op, char *params)
360 elmex 1.1 {
361 root 1.7 display_high_score (op, op == NULL ? 9999 : 50, params);
362     return 1;
363     }
364 elmex 1.1
365 root 1.7 int
366     command_debug (object *op, char *params)
367 elmex 1.1 {
368 root 1.7 int i;
369     char buf[MAX_BUF];
370    
371     if (params == NULL || !sscanf (params, "%d", &i))
372     {
373     sprintf (buf, "Global debug level is %d.", settings.debug);
374     new_draw_info (NDI_UNIQUE, 0, op, buf);
375 elmex 1.1 return 1;
376     }
377 root 1.7 if (op != NULL && !QUERY_FLAG (op, FLAG_WIZ))
378     {
379     new_draw_info (NDI_UNIQUE, 0, op, "Privileged command.");
380 elmex 1.1 return 1;
381     }
382 root 1.7 settings.debug = (enum LogLevel) FABS (i);
383     sprintf (buf, "Set debug level to %d.", i);
384     new_draw_info (NDI_UNIQUE, 0, op, buf);
385     return 1;
386     }
387 elmex 1.1
388    
389     /*
390     * Those dumps should be just one dump with good parser
391     */
392    
393 root 1.7 int
394     command_dumpbelow (object *op, char *params)
395 elmex 1.1 {
396 root 1.7 if (op && op->below)
397     {
398 root 1.14 char *dump = dump_object (op->below);
399     new_draw_info (NDI_UNIQUE, 0, op, dump);
400     free (dump);
401 elmex 1.1 /* Let's push that item on the dm's stack */
402 root 1.7 dm_stack_push (op->contr, op->below->count);
403     }
404 elmex 1.1 return 0;
405     }
406    
407 root 1.7 int
408     command_dumpfriendlyobjects (object *op, char *params)
409 elmex 1.1 {
410 root 1.7 dump_friendly_objects ();
411 elmex 1.1 return 0;
412     }
413    
414 root 1.7 int
415     command_printlos (object *op, char *params)
416 elmex 1.1 {
417     if (op)
418 root 1.7 print_los (op);
419 elmex 1.1 return 0;
420     }
421    
422    
423 root 1.7 int
424     command_version (object *op, char *params)
425 elmex 1.1 {
426 root 1.7 version (op);
427     return 0;
428 elmex 1.1 }
429    
430     #ifndef BUG_LOG
431 root 1.7 # define BUG_LOG "bug_log"
432 elmex 1.1 #endif
433 root 1.7 void
434     bug_report (const char *reportstring)
435     {
436     FILE *fp;
437    
438     if ((fp = fopen (BUG_LOG, "a")) != NULL)
439     {
440     fprintf (fp, "%s\n", reportstring);
441     fclose (fp);
442     }
443     else
444     {
445     LOG (llevError, "Cannot write bugs file %s: %s\n", BUG_LOG, strerror (errno));
446 elmex 1.1 }
447 root 1.7 }
448    
449     int
450     command_output_sync (object *op, char *params)
451     {
452     int val;
453    
454     if (!params)
455     {
456     new_draw_info_format (NDI_UNIQUE, 0, op, "Output sync time is presently %d", op->contr->outputs_sync);
457     return 1;
458     }
459     val = atoi (params);
460     if (val > 0)
461     {
462     op->contr->outputs_sync = val;
463     new_draw_info_format (NDI_UNIQUE, 0, op, "Output sync time now set to %d", op->contr->outputs_sync);
464     }
465     else
466     new_draw_info (NDI_UNIQUE, 0, op, "Invalid value for output_sync.");
467 elmex 1.1
468 root 1.7 return 1;
469 elmex 1.1 }
470    
471 root 1.7 int
472     command_output_count (object *op, char *params)
473 elmex 1.1 {
474 root 1.7 int val;
475 elmex 1.1
476 root 1.7 if (!params)
477     {
478     new_draw_info_format (NDI_UNIQUE, 0, op, "Output count is presently %d", op->contr->outputs_count);
479     return 1;
480 elmex 1.1 }
481 root 1.7 val = atoi (params);
482     if (val > 0)
483     {
484     op->contr->outputs_count = val;
485     new_draw_info_format (NDI_UNIQUE, 0, op, "Output count now set to %d", op->contr->outputs_count);
486     }
487     else
488     new_draw_info (NDI_UNIQUE, 0, op, "Invalid value for output_count.");
489 elmex 1.1
490 root 1.7 return 1;
491 elmex 1.1 }
492    
493 root 1.7 int
494     command_listen (object *op, char *params)
495 elmex 1.1 {
496     int i;
497    
498 root 1.7 if (params == NULL || !sscanf (params, "%d", &i))
499     {
500     new_draw_info_format (NDI_UNIQUE, 0, op, "Set listen to what (presently %d)?", op->contr->listening);
501 elmex 1.1 return 1;
502     }
503 root 1.7 op->contr->listening = (char) i;
504     new_draw_info_format (NDI_UNIQUE, 0, op, "Your verbose level is now %d.", i);
505     return 1;
506 elmex 1.1 }
507    
508     /* Prints out some useful information for the character. Everything we print
509     * out can be determined by the docs, so we aren't revealing anything extra -
510     * rather, we are making it convenient to find the values. params have
511     * no meaning here.
512     */
513 root 1.7 int
514     command_statistics (object *pl, char *params)
515 elmex 1.1 {
516 root 1.7 if (!pl->contr)
517     return 1;
518 root 1.18 new_draw_info_format (NDI_UNIQUE, 0, pl, " Experience: %" PRId64, pl->stats.exp);
519     new_draw_info_format (NDI_UNIQUE, 0, pl, " Next Level: %" PRId64, level_exp (pl->level + 1, pl->expmul));
520 root 1.7 new_draw_info (NDI_UNIQUE, 0, pl, "\nStat Nat/Real/Max");
521 elmex 1.1
522 root 1.7 new_draw_info_format (NDI_UNIQUE, 0, pl, "Str %2d/ %3d/%3d",
523     pl->contr->orig_stats.Str, pl->stats.Str, 20 + pl->arch->clone.stats.Str);
524     new_draw_info_format (NDI_UNIQUE, 0, pl, "Dex %2d/ %3d/%3d",
525     pl->contr->orig_stats.Dex, pl->stats.Dex, 20 + pl->arch->clone.stats.Dex);
526     new_draw_info_format (NDI_UNIQUE, 0, pl, "Con %2d/ %3d/%3d",
527     pl->contr->orig_stats.Con, pl->stats.Con, 20 + pl->arch->clone.stats.Con);
528     new_draw_info_format (NDI_UNIQUE, 0, pl, "Int %2d/ %3d/%3d",
529     pl->contr->orig_stats.Int, pl->stats.Int, 20 + pl->arch->clone.stats.Int);
530     new_draw_info_format (NDI_UNIQUE, 0, pl, "Wis %2d/ %3d/%3d",
531     pl->contr->orig_stats.Wis, pl->stats.Wis, 20 + pl->arch->clone.stats.Wis);
532     new_draw_info_format (NDI_UNIQUE, 0, pl, "Pow %2d/ %3d/%3d",
533     pl->contr->orig_stats.Pow, pl->stats.Pow, 20 + pl->arch->clone.stats.Pow);
534     new_draw_info_format (NDI_UNIQUE, 0, pl, "Cha %2d/ %3d/%3d",
535     pl->contr->orig_stats.Cha, pl->stats.Cha, 20 + pl->arch->clone.stats.Cha);
536     new_draw_info_format (NDI_UNIQUE, 0, pl, "\nAttack Mode: %s", pl->contr->peaceful ? "Peaceful" : "Hostile");
537 elmex 1.1
538 root 1.7 /* Can't think of anything else to print right now */
539     return 0;
540 elmex 1.1 }
541    
542 root 1.7 int
543     command_fix_me (object *op, char *params)
544 elmex 1.1 {
545 root 1.7 sum_weight (op);
546 root 1.27 op->update_stats ();
547 root 1.7 return 1;
548 elmex 1.1 }
549    
550 root 1.7 int
551     command_logs (object *op, char *params)
552 elmex 1.1 {
553 root 1.10 new_draw_info (NDI_UNIQUE, 0, op, "Nobody is currently logging kills.");
554 elmex 1.1
555 root 1.7 return 1;
556 elmex 1.1 }
557    
558 root 1.7 int
559     command_applymode (object *op, char *params)
560 elmex 1.1 {
561 root 1.7 unapplymode unapply = op->contr->unapply;
562     static const char *const types[] = { "nochoice", "never", "always" };
563 elmex 1.1
564 root 1.7 if (!params)
565     {
566     new_draw_info_format (NDI_UNIQUE, 0, op, "applymode is set to %s", types[op->contr->unapply]);
567     return 1;
568     }
569    
570     if (!strcmp (params, "nochoice"))
571     op->contr->unapply = unapply_nochoice;
572     else if (!strcmp (params, "never"))
573     op->contr->unapply = unapply_never;
574     else if (!strcmp (params, "always"))
575     op->contr->unapply = unapply_always;
576     else
577     {
578     new_draw_info_format (NDI_UNIQUE, 0, op, "applymode: Unknown options %s, valid options are nochoice, never, always", params);
579     return 0;
580     }
581 root 1.38
582 root 1.7 new_draw_info_format (NDI_UNIQUE, 0, op, "Applymode %s set to %s",
583     (unapply == op->contr->unapply ? "" : " now"), types[op->contr->unapply]);
584     return 1;
585 elmex 1.1 }
586    
587 root 1.7 int
588     command_bowmode (object *op, char *params)
589 elmex 1.1 {
590 root 1.7 bowtype_t oldtype = op->contr->bowtype;
591     static const char *const types[] = { "normal", "threewide", "spreadshot", "firenorth",
592     "firene", "fireeast", "firese", "firesouth",
593     "firesw", "firewest", "firenw", "bestarrow"
594     };
595     char buf[MAX_BUF];
596     int i, found;
597    
598     if (!params)
599     {
600     new_draw_info_format (NDI_UNIQUE, 0, op, "bowmode is set to %s", types[op->contr->bowtype]);
601     return 1;
602     }
603    
604     for (i = 0, found = 0; i <= bow_bestarrow; i++)
605     {
606     if (!strcmp (params, types[i]))
607     {
608     found++;
609     op->contr->bowtype = (bowtype_t) i;
610     break;
611 root 1.3 }
612 elmex 1.1 }
613 root 1.38
614 root 1.7 if (!found)
615     {
616     sprintf (buf, "bowmode: Unknown options %s, valid options are:", params);
617     for (i = 0; i <= bow_bestarrow; i++)
618     {
619     strcat (buf, " ");
620     strcat (buf, types[i]);
621     if (i < bow_nw)
622     strcat (buf, ",");
623     else
624     strcat (buf, ".");
625 root 1.3 }
626 root 1.7 new_draw_info_format (NDI_UNIQUE, 0, op, buf);
627     return 0;
628 elmex 1.1 }
629 root 1.38
630 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]);
631     return 1;
632 elmex 1.1 }
633    
634 root 1.7 int
635     command_petmode (object *op, char *params)
636 elmex 1.1 {
637 root 1.7 petmode_t oldtype = op->contr->petmode;
638     static const char *const types[] = { "normal", "sad", "defend", "arena" };
639 elmex 1.1
640 root 1.7 if (!params)
641     {
642     new_draw_info_format (NDI_UNIQUE, 0, op, "petmode is set to %s", types[op->contr->petmode]);
643     return 1;
644     }
645    
646     if (!strcmp (params, "normal"))
647     op->contr->petmode = pet_normal;
648     else if (!strcmp (params, "sad"))
649     op->contr->petmode = pet_sad;
650     else if (!strcmp (params, "defend"))
651     op->contr->petmode = pet_defend;
652     else if (!strcmp (params, "arena"))
653     op->contr->petmode = pet_arena;
654     else
655     {
656     new_draw_info_format (NDI_UNIQUE, 0, op,
657     "petmode: Unknown options %s, valid options are normal," "sad (seek and destroy), defend, arena", params);
658     return 0;
659     }
660     new_draw_info_format (NDI_UNIQUE, 0, op, "petmode %s set to %s", (oldtype == op->contr->petmode ? "" : "now"), types[op->contr->petmode]);
661     return 1;
662 elmex 1.1 }
663    
664 root 1.7 int
665     command_showpets (object *op, char *params)
666 elmex 1.1 {
667 root 1.7 objectlink *obl, *next;
668     int counter = 0, target = 0;
669     int have_shown_pet = 0;
670    
671     if (params != NULL)
672     target = atoi (params);
673     for (obl = first_friendly_object; obl != NULL; obl = next)
674     {
675     object *ob = obl->ob;
676    
677     next = obl->next;
678 root 1.22 if (ob->owner == op)
679 root 1.7 {
680     if (target == 0)
681     {
682     if (counter == 0)
683     new_draw_info (NDI_UNIQUE, 0, op, "Pets:");
684     new_draw_info_format (NDI_UNIQUE, 0, op, "%d %s - level %d", ++counter, &ob->name, ob->level);
685     }
686     else if (!have_shown_pet && ++counter == target)
687     {
688     new_draw_info_format (NDI_UNIQUE, 0, op, "level %d %s", ob->level, &ob->name);
689     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);
690     /* this is not a nice way to do this, it should be made to be more like the statistics command */
691     new_draw_info_format (NDI_UNIQUE, 0, op, "Str %d", ob->stats.Str);
692     new_draw_info_format (NDI_UNIQUE, 0, op, "Dex %d", ob->stats.Dex);
693     new_draw_info_format (NDI_UNIQUE, 0, op, "Con %d", ob->stats.Con);
694     new_draw_info_format (NDI_UNIQUE, 0, op, "Int %d", ob->stats.Int);
695     new_draw_info_format (NDI_UNIQUE, 0, op, "Wis %d", ob->stats.Wis);
696     new_draw_info_format (NDI_UNIQUE, 0, op, "Cha %d", ob->stats.Cha);
697     new_draw_info_format (NDI_UNIQUE, 0, op, "Pow %d", ob->stats.Pow);
698     new_draw_info_format (NDI_UNIQUE, 0, op, "wc %d damage %d ac %d ", ob->stats.wc, ob->stats.dam, ob->stats.ac);
699     have_shown_pet = 1;
700 root 1.3 }
701     }
702 elmex 1.1 }
703 root 1.7 if (counter == 0)
704     new_draw_info (NDI_UNIQUE, 0, op, "you have no pets.");
705     else if (target != 0 && have_shown_pet == 0)
706     new_draw_info (NDI_UNIQUE, 0, op, "no such pet.");
707     return 0;
708 elmex 1.1 }
709    
710 root 1.7 int
711     command_usekeys (object *op, char *params)
712 elmex 1.1 {
713 root 1.7 usekeytype oldtype = op->contr->usekeys;
714     static const char *const types[] = { "inventory", "keyrings", "containers" };
715 elmex 1.1
716 root 1.7 if (!params)
717     {
718     new_draw_info_format (NDI_UNIQUE, 0, op, "usekeys is set to %s", types[op->contr->usekeys]);
719     return 1;
720     }
721    
722     if (!strcmp (params, "inventory"))
723     op->contr->usekeys = key_inventory;
724     else if (!strcmp (params, "keyrings"))
725     op->contr->usekeys = keyrings;
726     else if (!strcmp (params, "containers"))
727     op->contr->usekeys = containers;
728     else
729     {
730     new_draw_info_format (NDI_UNIQUE, 0, op, "usekeys: Unknown options %s, valid options are inventory, keyrings, containers", params);
731     return 0;
732     }
733     new_draw_info_format (NDI_UNIQUE, 0, op, "usekeys %s set to %s", (oldtype == op->contr->usekeys ? "" : "now"), types[op->contr->usekeys]);
734     return 1;
735 elmex 1.1 }
736    
737 root 1.7 int
738     command_resistances (object *op, char *params)
739 elmex 1.1 {
740 root 1.7 int i;
741 elmex 1.1
742 root 1.7 if (!op)
743     return 0;
744    
745     for (i = 0; i < NROFATTACKS; i++)
746     {
747     if (i == ATNR_INTERNAL)
748     continue;
749 elmex 1.1
750 root 1.7 new_draw_info_format (NDI_UNIQUE, 0, op, "%-20s %+5d", attacktype_desc[i], op->resist[i]);
751 elmex 1.1 }
752    
753 root 1.7 /* If dragon player, let's display natural resistances */
754     if (is_dragon_pl (op))
755     {
756     int attack;
757     object *tmp;
758    
759     for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
760 elmex 1.1 {
761 root 1.7 if ((tmp->type == FORCE) && (strcmp (tmp->arch->name, "dragon_skin_force") == 0))
762 elmex 1.1 {
763 root 1.7 new_draw_info (NDI_UNIQUE, 0, op, "\nNatural skin resistances:");
764     for (attack = 0; attack < NROFATTACKS; attack++)
765 elmex 1.1 {
766 root 1.7 if (atnr_is_dragon_enabled (attack))
767 elmex 1.1 {
768 root 1.7 new_draw_info_format (NDI_UNIQUE, 0, op, "%s: %d", change_resist_msg[attack], tmp->resist[attack]);
769 elmex 1.1 }
770     }
771 root 1.7 break;
772 elmex 1.1 }
773     }
774 root 1.7 }
775 elmex 1.1
776 root 1.7 return 0;
777 elmex 1.1 }
778 root 1.7
779 elmex 1.1 /*
780     * Actual commands.
781     * Those should be in small separate files (c_object.c, c_wiz.c, cmove.c,...)
782     */
783    
784    
785 root 1.7 static void
786     help_topics (object *op, int what)
787 elmex 1.1 {
788 root 1.7 DIR *dirp;
789     struct dirent *de;
790     char filename[MAX_BUF], line[80];
791     int namelen, linelen = 0;
792    
793     switch (what)
794     {
795 root 1.21 case 1:
796     sprintf (filename, "%s/wizhelp", settings.datadir);
797     new_draw_info (NDI_UNIQUE, 0, op, " Wiz commands:");
798     break;
799     case 3:
800     sprintf (filename, "%s/mischelp", settings.datadir);
801     new_draw_info (NDI_UNIQUE, 0, op, " Misc help:");
802     break;
803     default:
804     sprintf (filename, "%s/help", settings.datadir);
805     new_draw_info (NDI_UNIQUE, 0, op, " Commands:");
806     break;
807 root 1.7 }
808 root 1.21
809 root 1.7 if (!(dirp = opendir (filename)))
810     return;
811    
812     line[0] = '\0';
813 root 1.21 while (de = readdir (dirp))
814 root 1.7 {
815 root 1.21 namelen = strlen (de->d_name);
816 root 1.7 if (namelen <= 2 && *de->d_name == '.' && (namelen == 1 || de->d_name[1] == '.'))
817     continue;
818     linelen += namelen + 1;
819     if (linelen > 42)
820     {
821     new_draw_info (NDI_UNIQUE, 0, op, line);
822     sprintf (line, " %s", de->d_name);
823     linelen = namelen + 1;
824     continue;
825 root 1.3 }
826 root 1.7 strcat (line, " ");
827     strcat (line, de->d_name);
828 elmex 1.1 }
829 root 1.7 new_draw_info (NDI_UNIQUE, 0, op, line);
830     closedir (dirp);
831 elmex 1.1 }
832    
833 root 1.7 static void
834     show_commands (object *op, int what)
835 elmex 1.1 {
836     char line[80];
837 root 1.7 int i, size, namelen, linelen = 0;
838 elmex 1.1 CommArray_s *ap;
839     extern CommArray_s Commands[], WizCommands[];
840     extern const int CommandsSize, WizCommandsSize;
841 root 1.7
842     switch (what)
843     {
844     case 1:
845     ap = WizCommands;
846     size = WizCommandsSize;
847     new_draw_info (NDI_UNIQUE, 0, op, " Wiz commands:");
848     break;
849     case 2:
850     ap = CommunicationCommands;
851     size = CommunicationCommandSize;
852     new_draw_info (NDI_UNIQUE, 0, op, " Communication commands:");
853     break;
854     default:
855     ap = Commands;
856     size = CommandsSize;
857     new_draw_info (NDI_UNIQUE, 0, op, " Commands:");
858     break;
859     }
860    
861     line[0] = '\0';
862     for (i = 0; i < size; i++)
863     {
864     namelen = strlen (ap[i].name);
865     linelen += namelen + 1;
866     if (linelen > 42)
867     {
868     new_draw_info (NDI_UNIQUE, 0, op, line);
869     sprintf (line, " %s", ap[i].name);
870     linelen = namelen + 1;
871     continue;
872     }
873     strcat (line, " ");
874     strcat (line, ap[i].name);
875     }
876     new_draw_info (NDI_UNIQUE, 0, op, line);
877 elmex 1.1 }
878    
879    
880 root 1.7 int
881     command_help (object *op, char *params)
882 elmex 1.1 {
883     struct stat st;
884     FILE *fp;
885     char filename[MAX_BUF], line[MAX_BUF];
886     int len;
887    
888 root 1.7 if (op != NULL)
889     clear_win_info (op);
890 elmex 1.1
891     /*
892     * Main help page?
893     */
894 root 1.7 if (!params)
895     {
896     sprintf (filename, "%s/def_help", settings.datadir);
897     if ((fp = fopen (filename, "r")) == NULL)
898     {
899     LOG (llevError, "Cannot open help file %s: %s\n", filename, strerror (errno));
900     return 0;
901     }
902     while (fgets (line, MAX_BUF, fp))
903     {
904     line[MAX_BUF - 1] = '\0';
905     len = strlen (line) - 1;
906     if (line[len] == '\n')
907     line[len] = '\0';
908     new_draw_info (NDI_UNIQUE, 0, op, line);
909     }
910     fclose (fp);
911 elmex 1.1 return 0;
912     }
913    
914     /*
915     * Topics list
916     */
917 root 1.7 if (!strcmp (params, "topics"))
918     {
919     help_topics (op, 3);
920     help_topics (op, 0);
921     if (QUERY_FLAG (op, FLAG_WIZ))
922     help_topics (op, 1);
923     return 0;
924 elmex 1.1 }
925 root 1.7
926 elmex 1.1 /*
927     * Commands list
928     */
929 root 1.7 if (!strcmp (params, "commands"))
930     {
931     show_commands (op, 0);
932     show_commands (op, 2); /* show comm commands */
933     if (QUERY_FLAG (op, FLAG_WIZ))
934     show_commands (op, 1);
935     return 0;
936     }
937 elmex 1.1
938     /*
939     * User wants info about command
940     */
941 root 1.7 if (strchr (params, '.') || strchr (params, ' ') || strchr (params, '/'))
942     {
943     sprintf (line, "Illegal characters in '%s'", params);
944     new_draw_info (NDI_UNIQUE, 0, op, line);
945     return 0;
946     }
947 elmex 1.1
948 root 1.7 sprintf (filename, "%s/mischelp/%s", settings.datadir, params);
949     if (stat (filename, &st) || !S_ISREG (st.st_mode))
950     {
951     if (op)
952     {
953     sprintf (filename, "%s/help/%s", settings.datadir, params);
954     if (stat (filename, &st) || !S_ISREG (st.st_mode))
955     {
956     if (QUERY_FLAG (op, FLAG_WIZ))
957     {
958     sprintf (filename, "%s/wizhelp/%s", settings.datadir, params);
959     if (stat (filename, &st) || !S_ISREG (st.st_mode))
960     goto nohelp;
961     }
962     else
963     goto nohelp;
964     }
965     }
966     }
967 elmex 1.1
968     /*
969     * Found that. Just cat it to screen.
970     */
971 root 1.7 if ((fp = fopen (filename, "r")) == NULL)
972     {
973     LOG (llevError, "Cannot open help file %s: %s\n", filename, strerror (errno));
974     return 0;
975     }
976     sprintf (line, "Help about '%s'", params);
977     new_draw_info (NDI_UNIQUE, 0, op, line);
978     while (fgets (line, MAX_BUF, fp))
979     {
980     line[MAX_BUF - 1] = '\0';
981     len = strlen (line) - 1;
982     if (line[len] == '\n')
983     line[len] = '\0';
984     new_draw_info (NDI_UNIQUE, 0, op, line);
985 elmex 1.1 }
986 root 1.7 fclose (fp);
987 elmex 1.1 return 0;
988    
989     /*
990     * No_help -escape
991     */
992 root 1.7 nohelp:
993     sprintf (line, "No help available on '%s'", params);
994     new_draw_info (NDI_UNIQUE, 0, op, line);
995 elmex 1.1 return 0;
996     }
997    
998    
999 root 1.7 int
1000     onoff_value (const char *line)
1001 elmex 1.1 {
1002     int i;
1003    
1004 root 1.7 if (sscanf (line, "%d", &i))
1005 elmex 1.1 return (i != 0);
1006 root 1.7 switch (line[0])
1007     {
1008     case 'o':
1009     switch (line[1])
1010     {
1011     case 'n':
1012     return 1; /* on */
1013     default:
1014     return 0; /* o[ff] */
1015     }
1016     case 'y': /* y[es] */
1017     case 'k': /* k[ylla] */
1018     case 's':
1019     case 'd':
1020     return 1;
1021     case 'n': /* n[o] */
1022     case 'e': /* e[i] */
1023     case 'u':
1024     default:
1025     return 0;
1026     }
1027 elmex 1.1 }
1028    
1029 root 1.7 int
1030     command_sound (object *op, char *params)
1031 elmex 1.1 {
1032 root 1.26 if (op->contr->ns->sound)
1033 root 1.7 {
1034 root 1.26 op->contr->ns->sound = 0;
1035 root 1.7 new_draw_info (NDI_UNIQUE, 0, op, "Silence is golden...");
1036     }
1037     else
1038     {
1039 root 1.26 op->contr->ns->sound = 1;
1040 root 1.7 new_draw_info (NDI_UNIQUE, 0, op, "The sounds are enabled.");
1041 elmex 1.1 }
1042 root 1.23
1043 root 1.7 return 1;
1044 elmex 1.1 }
1045    
1046 root 1.7 int
1047     command_title (object *op, char *params)
1048 elmex 1.1 {
1049 root 1.7 char buf[MAX_BUF];
1050    
1051     if (settings.set_title == FALSE)
1052     {
1053     new_draw_info (NDI_UNIQUE, 0, op, "You cannot change your title.");
1054     return 1;
1055 elmex 1.1 }
1056 root 1.7
1057     /* dragon players cannot change titles */
1058     if (is_dragon_pl (op))
1059     {
1060     new_draw_info (NDI_UNIQUE, 0, op, "Dragons cannot change titles.");
1061     return 1;
1062     }
1063    
1064     if (params == NULL)
1065     {
1066     if (op->contr->own_title[0] == '\0')
1067     sprintf (buf, "Your title is '%s'.", op->contr->title);
1068     else
1069     sprintf (buf, "Your title is '%s'.", op->contr->own_title);
1070     new_draw_info (NDI_UNIQUE, 0, op, buf);
1071     return 1;
1072     }
1073     if (strcmp (params, "clear") == 0 || strcmp (params, "default") == 0)
1074     {
1075     if (op->contr->own_title[0] == '\0')
1076     new_draw_info (NDI_UNIQUE, 0, op, "Your title is the default title.");
1077     else
1078     new_draw_info (NDI_UNIQUE, 0, op, "Title set to default.");
1079     op->contr->own_title[0] = '\0';
1080     return 1;
1081     }
1082    
1083     if ((int) strlen (params) >= MAX_NAME)
1084     {
1085     new_draw_info (NDI_UNIQUE, 0, op, "Title too long.");
1086     return 1;
1087     }
1088     strcpy (op->contr->own_title, params);
1089     return 1;
1090 elmex 1.1 }
1091    
1092 root 1.7 int
1093     command_peaceful (object *op, char *params)
1094 elmex 1.1 {
1095 root 1.7 new_draw_info (NDI_UNIQUE, 0, op,
1096     "You cannot change your peaceful setting with this command."
1097     " Please speak to the priest in the temple of Gorokh"
1098     " if you want to become hostile or in temple of Valriel" " if you want to become peaceful again.");
1099 elmex 1.1
1100     /*
1101     if((op->contr->peaceful=!op->contr->peaceful))
1102     new_draw_info(NDI_UNIQUE, 0,op,"You will not attack other players.");
1103     else
1104     new_draw_info(NDI_UNIQUE, 0,op,"You will attack other players.");
1105     */
1106 root 1.7 return 1;
1107 elmex 1.1 }
1108    
1109 root 1.7 int
1110     command_wimpy (object *op, char *params)
1111 elmex 1.1 {
1112 root 1.7 int i;
1113     char buf[MAX_BUF];
1114 elmex 1.1
1115 root 1.7 if (params == NULL || !sscanf (params, "%d", &i))
1116     {
1117     sprintf (buf, "Your current wimpy level is %d.", op->run_away);
1118     new_draw_info (NDI_UNIQUE, 0, op, buf);
1119     return 1;
1120     }
1121     sprintf (buf, "Your new wimpy level is %d.", i);
1122     new_draw_info (NDI_UNIQUE, 0, op, buf);
1123     op->run_away = i;
1124     return 1;
1125 elmex 1.1 }
1126    
1127 root 1.7 int
1128     command_brace (object *op, char *params)
1129 elmex 1.1 {
1130     if (!params)
1131 root 1.7 op->contr->braced = !op->contr->braced;
1132 elmex 1.1 else
1133 root 1.7 op->contr->braced = onoff_value (params);
1134 elmex 1.1
1135 root 1.7 if (op->contr->braced)
1136     new_draw_info (NDI_UNIQUE, 0, op, "You are braced.");
1137 elmex 1.1 else
1138 root 1.7 new_draw_info (NDI_UNIQUE, 0, op, "Not braced.");
1139 elmex 1.1
1140 root 1.27 op->update_stats ();
1141 elmex 1.1 return 0;
1142     }
1143    
1144 root 1.7 int
1145     command_kill_pets (object *op, char *params)
1146 elmex 1.1 {
1147 root 1.7 objectlink *obl, *next;
1148     int counter = 0, removecount = 0;
1149    
1150     if (params == NULL)
1151     {
1152     terminate_all_pets (op);
1153     new_draw_info (NDI_UNIQUE, 0, op, "Your pets have been killed.");
1154     }
1155     else
1156     {
1157     int target = atoi (params);
1158    
1159     for (obl = first_friendly_object; obl != NULL; obl = next)
1160     {
1161     object *ob = obl->ob;
1162    
1163     next = obl->next;
1164 root 1.22 if (ob->owner == op)
1165 root 1.7 if (++counter == target || (target == 0 && !strcasecmp (ob->name, params)))
1166     {
1167 root 1.20 ob->destroy ();
1168 root 1.3 removecount++;
1169 root 1.7 }
1170 root 1.3 }
1171 root 1.7 if (removecount != 0)
1172     new_draw_info_format (NDI_UNIQUE, 0, op, "killed %d pets.\n", removecount);
1173     else
1174     new_draw_info (NDI_UNIQUE, 0, op, "Couldn't find any suitable pets to kill.\n");
1175 elmex 1.1 }
1176 root 1.7 return 0;
1177 elmex 1.1 }