ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/c_misc.C
Revision: 1.53
Committed: Fri Mar 2 11:13:51 2007 UTC (17 years, 3 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.52: +0 -19 lines
Log Message:
whereami in perl

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 void
75     current_map_info (object *op)
76     {
77 root 1.9 maptile *m = op->map;
78 elmex 1.1
79 root 1.7 if (!m)
80     return;
81 elmex 1.1
82 root 1.44 new_draw_info_format (NDI_UNIQUE, 0, op, "%s (%s) %s", &m->name, &m->path, &op->region ()->longname);
83 elmex 1.1
84 root 1.7 if (QUERY_FLAG (op, FLAG_WIZ))
85 root 1.38 new_draw_info_format (NDI_UNIQUE, 0, op,
86     "players:%d difficulty:%d size:%dx%d start:%dx%d timeout %ld",
87     m->players, m->difficulty, m->width, m->height, m->enter_x, m->enter_y, m->timeout);
88 elmex 1.1
89 root 1.7 if (m->msg)
90     new_draw_info (NDI_UNIQUE, NDI_NAVY, op, m->msg);
91 elmex 1.1 }
92    
93     #ifdef DEBUG_MALLOC_LEVEL
94 root 1.7 int
95     command_malloc_verify (object *op, char *parms)
96 elmex 1.1 {
97 root 1.7 extern int malloc_verify (void);
98 elmex 1.1
99 root 1.7 if (!malloc_verify ())
100     new_draw_info (NDI_UNIQUE, 0, op, "Heap is corrupted.");
101     else
102     new_draw_info (NDI_UNIQUE, 0, op, "Heap checks out OK.");
103     return 1;
104     }
105 elmex 1.1 #endif
106    
107 root 1.7 int
108     command_whereabouts (object *op, char *params)
109     {
110 root 1.38 //TODO: should obviously not waste space in struct region for this.
111 root 1.7 /*
112     * reset the counter on the region, then use it to store the number of
113     * players there.
114     * I don't know how thread-safe this would be, I suspect not very....
115     */
116 root 1.41 for_all_regions (rgn)
117     rgn->counter = 0;
118 root 1.38
119 root 1.28 for_all_players (pl)
120 root 1.38 if (pl->ob->map)
121     ++pl->ob->region ()->counter;
122 root 1.7
123     /* we only want to print out by places with a 'longname' field... */
124 root 1.41 for_all_regions (rgn)
125 root 1.7 {
126 root 1.41 if (!rgn->longname && rgn->counter > 0)
127 root 1.7 {
128 root 1.41 if (rgn->parent)
129 root 1.7 {
130 root 1.41 rgn->parent->counter += rgn->counter;
131     rgn->counter = 0;
132 root 1.3 }
133 root 1.7 else /*uh oh, we shouldn't be here. */
134 root 1.41 LOG (llevError, "command_whereabouts() Region %s with no longname has no parent", &rgn->name);
135 root 1.3 }
136     }
137 root 1.38
138 root 1.7 new_draw_info_format (NDI_UNIQUE, 0, op, "In the world currently there are:");
139 root 1.38
140 root 1.41 for_all_regions (rgn)
141     if (rgn->counter)
142 root 1.44 new_draw_info_format (NDI_UNIQUE, 0, op, "%u players %s", rgn->counter, &rgn->longname);
143 root 1.38
144 root 1.7 return 1;
145 elmex 1.1 }
146    
147     typedef struct
148 root 1.7 {
149     char namebuf[MAX_BUF];
150     int login_order;
151     } chars_names;
152 elmex 1.1
153 root 1.7 int
154     command_mapinfo (object *op, char *params)
155 elmex 1.1 {
156 root 1.7 current_map_info (op);
157     return 1;
158     }
159 elmex 1.1
160 root 1.7 int
161     command_time (object *op, char *params)
162 elmex 1.1 {
163 root 1.2 print_tod (op);
164     return 1;
165     }
166 elmex 1.1
167 root 1.7 int
168     command_weather (object *op, char *params)
169 elmex 1.1 {
170 root 1.33 #if 0
171 root 1.7 int wx, wy, temp, sky;
172     char buf[MAX_BUF];
173    
174     if (settings.dynamiclevel < 1)
175     return 1;
176    
177     if (op->map == NULL)
178     return 1;
179    
180     if (worldmap_to_weathermap (op->x, op->y, &wx, &wy, op->map) != 0)
181     return 1;
182    
183     if (QUERY_FLAG (op, FLAG_WIZ))
184     {
185     /* dump the weather, Dm style! Yo! */
186     new_draw_info_format (NDI_UNIQUE, 0, op, "Real temp: %d", real_world_temperature (op->x, op->y, op->map));
187     new_draw_info_format (NDI_UNIQUE, 0, op, "Base temp: %d", weathermap[wx][wy].temp);
188     new_draw_info_format (NDI_UNIQUE, 0, op, "Humid: %d", weathermap[wx][wy].humid);
189     new_draw_info_format (NDI_UNIQUE, 0, op, "Wind: dir=%d speed=%d", weathermap[wx][wy].winddir, weathermap[wx][wy].windspeed);
190     new_draw_info_format (NDI_UNIQUE, 0, op, "Pressure: %d", weathermap[wx][wy].pressure);
191     new_draw_info_format (NDI_UNIQUE, 0, op, "Avg Elevation: %d", weathermap[wx][wy].avgelev);
192     new_draw_info_format (NDI_UNIQUE, 0, op, "Rainfall: %d Water: %d", weathermap[wx][wy].rainfall, weathermap[wx][wy].water);
193     }
194    
195     temp = real_world_temperature (op->x, op->y, op->map);
196     new_draw_info_format (NDI_UNIQUE, 0, op, "It's currently %d degrees " "Centigrade out.", temp);
197    
198     /* humid */
199     if (weathermap[wx][wy].humid < 20)
200     new_draw_info (NDI_UNIQUE, 0, op, "It is very dry.");
201     else if (weathermap[wx][wy].humid < 40)
202     new_draw_info (NDI_UNIQUE, 0, op, "It is very comfortable today.");
203     else if (weathermap[wx][wy].humid < 60)
204     new_draw_info (NDI_UNIQUE, 0, op, "It is a bit muggy.");
205     else if (weathermap[wx][wy].humid < 80)
206     new_draw_info (NDI_UNIQUE, 0, op, "It is muggy.");
207     else
208     new_draw_info (NDI_UNIQUE, 0, op, "It is uncomfortably muggy.");
209 elmex 1.1
210 root 1.7 /* wind */
211     switch (weathermap[wx][wy].winddir)
212     {
213     case 1:
214     sprintf (buf, "north");
215     break;
216     case 2:
217     sprintf (buf, "northeast");
218     break;
219     case 3:
220     sprintf (buf, "east");
221     break;
222     case 4:
223     sprintf (buf, "southeast");
224     break;
225     case 5:
226     sprintf (buf, "south");
227     break;
228     case 6:
229     sprintf (buf, "southwest");
230     break;
231     case 7:
232     sprintf (buf, "west");
233     break;
234     case 8:
235     sprintf (buf, "northwest");
236     break;
237     }
238     if (weathermap[wx][wy].windspeed < 5)
239     new_draw_info_format (NDI_UNIQUE, 0, op, "There is a mild breeze " "coming from the %s.", buf);
240     else if (weathermap[wx][wy].windspeed < 10)
241     new_draw_info_format (NDI_UNIQUE, 0, op, "There is a strong breeze " "coming from the %s.", buf);
242     else if (weathermap[wx][wy].windspeed < 15)
243     new_draw_info_format (NDI_UNIQUE, 0, op, "There is a light wind " "coming from the %s.", buf);
244     else if (weathermap[wx][wy].windspeed < 25)
245     new_draw_info_format (NDI_UNIQUE, 0, op, "There is a strong wind " "coming from the %s.", buf);
246     else if (weathermap[wx][wy].windspeed < 35)
247     new_draw_info_format (NDI_UNIQUE, 0, op, "There is a heavy wind " "coming from the %s.", buf);
248     else
249     new_draw_info_format (NDI_UNIQUE, 0, op, "The wind from the %s is " "incredibly strong!", buf);
250 elmex 1.1
251 root 1.7 sky = weathermap[wx][wy].sky;
252     if (temp <= 0 && sky > SKY_OVERCAST && sky < SKY_FOG)
253     sky += 10; /*let it snow */
254     switch (sky)
255     {
256     case SKY_CLEAR:
257     new_draw_info (NDI_UNIQUE, 0, op, "There isn''t a cloud in the sky.");
258     break;
259     case SKY_LIGHTCLOUD:
260     new_draw_info (NDI_UNIQUE, 0, op, "There are a few light clouds in the sky.");
261     break;
262     case SKY_OVERCAST:
263     new_draw_info (NDI_UNIQUE, 0, op, "The sky is cloudy and dreary.");
264     break;
265     case SKY_LIGHT_RAIN:
266     new_draw_info (NDI_UNIQUE, 0, op, "It is raining softly.");
267     break;
268     case SKY_RAIN:
269     new_draw_info (NDI_UNIQUE, 0, op, "It is raining.");
270     break;
271     case SKY_HEAVY_RAIN:
272     new_draw_info (NDI_UNIQUE, 0, op, "It is raining heavily.");
273     break;
274     case SKY_HURRICANE:
275     new_draw_info (NDI_UNIQUE, 0, op, "There is a heavy storm! You should go inside!");
276     break;
277     case SKY_FOG:
278     new_draw_info (NDI_UNIQUE, 0, op, "It''s foggy and miserable.");
279     break;
280     case SKY_HAIL:
281     new_draw_info (NDI_UNIQUE, 0, op, "It''s hailing out! Take cover!");
282     break;
283     case SKY_LIGHT_SNOW:
284     new_draw_info (NDI_UNIQUE, 0, op, "Snow is gently falling from the sky.");
285     break;
286     case SKY_SNOW:
287     new_draw_info (NDI_UNIQUE, 0, op, "It''s snowing out.");
288     break;
289     case SKY_HEAVY_SNOW:
290     new_draw_info (NDI_UNIQUE, 0, op, "The snow is falling very heavily now.");
291     break;
292     case SKY_BLIZZARD:
293     new_draw_info (NDI_UNIQUE, 0, op, "A full blown blizzard is in effect. You might want to take cover!");
294     break;
295 elmex 1.1 }
296 root 1.33 #endif
297 root 1.7 return 1;
298 elmex 1.1 }
299    
300 root 1.7 int
301     command_hiscore (object *op, char *params)
302 elmex 1.1 {
303 root 1.7 display_high_score (op, op == NULL ? 9999 : 50, params);
304     return 1;
305     }
306 elmex 1.1
307 root 1.7 int
308     command_debug (object *op, char *params)
309 elmex 1.1 {
310 root 1.7 int i;
311     char buf[MAX_BUF];
312    
313     if (params == NULL || !sscanf (params, "%d", &i))
314     {
315     sprintf (buf, "Global debug level is %d.", settings.debug);
316     new_draw_info (NDI_UNIQUE, 0, op, buf);
317 elmex 1.1 return 1;
318     }
319 root 1.7 settings.debug = (enum LogLevel) FABS (i);
320     sprintf (buf, "Set debug level to %d.", i);
321     new_draw_info (NDI_UNIQUE, 0, op, buf);
322     return 1;
323     }
324 elmex 1.1
325    
326     /*
327     * Those dumps should be just one dump with good parser
328     */
329    
330 root 1.7 int
331     command_dumpbelow (object *op, char *params)
332 elmex 1.1 {
333 root 1.7 if (op && op->below)
334     {
335 root 1.14 char *dump = dump_object (op->below);
336     new_draw_info (NDI_UNIQUE, 0, op, dump);
337     free (dump);
338 elmex 1.1 /* Let's push that item on the dm's stack */
339 root 1.7 dm_stack_push (op->contr, op->below->count);
340     }
341 elmex 1.1 return 0;
342     }
343    
344 root 1.7 int
345     command_dumpfriendlyobjects (object *op, char *params)
346 elmex 1.1 {
347 root 1.7 dump_friendly_objects ();
348 elmex 1.1 return 0;
349     }
350    
351 root 1.7 int
352     command_printlos (object *op, char *params)
353 elmex 1.1 {
354     if (op)
355 root 1.7 print_los (op);
356 elmex 1.1 return 0;
357     }
358    
359    
360 root 1.7 int
361     command_version (object *op, char *params)
362 elmex 1.1 {
363 root 1.7 version (op);
364     return 0;
365 elmex 1.1 }
366    
367     #ifndef BUG_LOG
368 root 1.7 # define BUG_LOG "bug_log"
369 elmex 1.1 #endif
370 root 1.7 void
371     bug_report (const char *reportstring)
372     {
373     FILE *fp;
374    
375     if ((fp = fopen (BUG_LOG, "a")) != NULL)
376     {
377     fprintf (fp, "%s\n", reportstring);
378     fclose (fp);
379     }
380     else
381     {
382     LOG (llevError, "Cannot write bugs file %s: %s\n", BUG_LOG, strerror (errno));
383 elmex 1.1 }
384 root 1.7 }
385    
386 elmex 1.1 /* Prints out some useful information for the character. Everything we print
387     * out can be determined by the docs, so we aren't revealing anything extra -
388     * rather, we are making it convenient to find the values. params have
389     * no meaning here.
390     */
391 root 1.7 int
392     command_statistics (object *pl, char *params)
393 elmex 1.1 {
394 root 1.7 if (!pl->contr)
395     return 1;
396 root 1.18 new_draw_info_format (NDI_UNIQUE, 0, pl, " Experience: %" PRId64, pl->stats.exp);
397     new_draw_info_format (NDI_UNIQUE, 0, pl, " Next Level: %" PRId64, level_exp (pl->level + 1, pl->expmul));
398 root 1.7 new_draw_info (NDI_UNIQUE, 0, pl, "\nStat Nat/Real/Max");
399 elmex 1.1
400 root 1.7 new_draw_info_format (NDI_UNIQUE, 0, pl, "Str %2d/ %3d/%3d",
401     pl->contr->orig_stats.Str, pl->stats.Str, 20 + pl->arch->clone.stats.Str);
402     new_draw_info_format (NDI_UNIQUE, 0, pl, "Dex %2d/ %3d/%3d",
403     pl->contr->orig_stats.Dex, pl->stats.Dex, 20 + pl->arch->clone.stats.Dex);
404     new_draw_info_format (NDI_UNIQUE, 0, pl, "Con %2d/ %3d/%3d",
405     pl->contr->orig_stats.Con, pl->stats.Con, 20 + pl->arch->clone.stats.Con);
406     new_draw_info_format (NDI_UNIQUE, 0, pl, "Int %2d/ %3d/%3d",
407     pl->contr->orig_stats.Int, pl->stats.Int, 20 + pl->arch->clone.stats.Int);
408     new_draw_info_format (NDI_UNIQUE, 0, pl, "Wis %2d/ %3d/%3d",
409     pl->contr->orig_stats.Wis, pl->stats.Wis, 20 + pl->arch->clone.stats.Wis);
410     new_draw_info_format (NDI_UNIQUE, 0, pl, "Pow %2d/ %3d/%3d",
411     pl->contr->orig_stats.Pow, pl->stats.Pow, 20 + pl->arch->clone.stats.Pow);
412     new_draw_info_format (NDI_UNIQUE, 0, pl, "Cha %2d/ %3d/%3d",
413     pl->contr->orig_stats.Cha, pl->stats.Cha, 20 + pl->arch->clone.stats.Cha);
414     new_draw_info_format (NDI_UNIQUE, 0, pl, "\nAttack Mode: %s", pl->contr->peaceful ? "Peaceful" : "Hostile");
415 elmex 1.1
416 root 1.7 /* Can't think of anything else to print right now */
417     return 0;
418 elmex 1.1 }
419    
420 root 1.7 int
421     command_fix_me (object *op, char *params)
422 elmex 1.1 {
423 root 1.7 sum_weight (op);
424 root 1.27 op->update_stats ();
425 pippijn 1.51 new_draw_info (NDI_UNIQUE, 0, op, "Your character was fixed.");
426    
427 root 1.7 return 1;
428 elmex 1.1 }
429    
430 root 1.7 int
431     command_logs (object *op, char *params)
432 elmex 1.1 {
433 root 1.10 new_draw_info (NDI_UNIQUE, 0, op, "Nobody is currently logging kills.");
434 elmex 1.1
435 root 1.7 return 1;
436 elmex 1.1 }
437    
438 root 1.7 int
439     command_bowmode (object *op, char *params)
440 elmex 1.1 {
441 root 1.7 bowtype_t oldtype = op->contr->bowtype;
442     static const char *const types[] = { "normal", "threewide", "spreadshot", "firenorth",
443     "firene", "fireeast", "firese", "firesouth",
444     "firesw", "firewest", "firenw", "bestarrow"
445     };
446     char buf[MAX_BUF];
447     int i, found;
448    
449     if (!params)
450     {
451     new_draw_info_format (NDI_UNIQUE, 0, op, "bowmode is set to %s", types[op->contr->bowtype]);
452     return 1;
453     }
454    
455     for (i = 0, found = 0; i <= bow_bestarrow; i++)
456     {
457     if (!strcmp (params, types[i]))
458     {
459     found++;
460     op->contr->bowtype = (bowtype_t) i;
461     break;
462 root 1.3 }
463 elmex 1.1 }
464 root 1.38
465 root 1.7 if (!found)
466     {
467     sprintf (buf, "bowmode: Unknown options %s, valid options are:", params);
468     for (i = 0; i <= bow_bestarrow; i++)
469     {
470     strcat (buf, " ");
471     strcat (buf, types[i]);
472     if (i < bow_nw)
473     strcat (buf, ",");
474     else
475     strcat (buf, ".");
476 root 1.3 }
477 root 1.7 new_draw_info_format (NDI_UNIQUE, 0, op, buf);
478     return 0;
479 elmex 1.1 }
480 root 1.38
481 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]);
482     return 1;
483 elmex 1.1 }
484    
485 root 1.7 int
486     command_showpets (object *op, char *params)
487 elmex 1.1 {
488 root 1.7 objectlink *obl, *next;
489     int counter = 0, target = 0;
490     int have_shown_pet = 0;
491    
492     if (params != NULL)
493     target = atoi (params);
494     for (obl = first_friendly_object; obl != NULL; obl = next)
495     {
496     object *ob = obl->ob;
497    
498     next = obl->next;
499 root 1.22 if (ob->owner == op)
500 root 1.7 {
501     if (target == 0)
502     {
503     if (counter == 0)
504     new_draw_info (NDI_UNIQUE, 0, op, "Pets:");
505     new_draw_info_format (NDI_UNIQUE, 0, op, "%d %s - level %d", ++counter, &ob->name, ob->level);
506     }
507     else if (!have_shown_pet && ++counter == target)
508     {
509     new_draw_info_format (NDI_UNIQUE, 0, op, "level %d %s", ob->level, &ob->name);
510     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);
511     /* this is not a nice way to do this, it should be made to be more like the statistics command */
512     new_draw_info_format (NDI_UNIQUE, 0, op, "Str %d", ob->stats.Str);
513     new_draw_info_format (NDI_UNIQUE, 0, op, "Dex %d", ob->stats.Dex);
514     new_draw_info_format (NDI_UNIQUE, 0, op, "Con %d", ob->stats.Con);
515     new_draw_info_format (NDI_UNIQUE, 0, op, "Int %d", ob->stats.Int);
516     new_draw_info_format (NDI_UNIQUE, 0, op, "Wis %d", ob->stats.Wis);
517     new_draw_info_format (NDI_UNIQUE, 0, op, "Cha %d", ob->stats.Cha);
518     new_draw_info_format (NDI_UNIQUE, 0, op, "Pow %d", ob->stats.Pow);
519     new_draw_info_format (NDI_UNIQUE, 0, op, "wc %d damage %d ac %d ", ob->stats.wc, ob->stats.dam, ob->stats.ac);
520     have_shown_pet = 1;
521 root 1.3 }
522     }
523 elmex 1.1 }
524 root 1.7 if (counter == 0)
525     new_draw_info (NDI_UNIQUE, 0, op, "you have no pets.");
526     else if (target != 0 && have_shown_pet == 0)
527     new_draw_info (NDI_UNIQUE, 0, op, "no such pet.");
528     return 0;
529 elmex 1.1 }
530    
531 root 1.7 int
532     command_resistances (object *op, char *params)
533 elmex 1.1 {
534 root 1.7 int i;
535 elmex 1.1
536 root 1.7 if (!op)
537     return 0;
538    
539     for (i = 0; i < NROFATTACKS; i++)
540     {
541     if (i == ATNR_INTERNAL)
542     continue;
543 elmex 1.1
544 root 1.7 new_draw_info_format (NDI_UNIQUE, 0, op, "%-20s %+5d", attacktype_desc[i], op->resist[i]);
545 elmex 1.1 }
546    
547 root 1.7 /* If dragon player, let's display natural resistances */
548     if (is_dragon_pl (op))
549     {
550     int attack;
551     object *tmp;
552    
553     for (tmp = op->inv; tmp != NULL; tmp = tmp->below)
554 elmex 1.1 {
555 root 1.7 if ((tmp->type == FORCE) && (strcmp (tmp->arch->name, "dragon_skin_force") == 0))
556 elmex 1.1 {
557 root 1.7 new_draw_info (NDI_UNIQUE, 0, op, "\nNatural skin resistances:");
558     for (attack = 0; attack < NROFATTACKS; attack++)
559 elmex 1.1 {
560 root 1.7 if (atnr_is_dragon_enabled (attack))
561 elmex 1.1 {
562 root 1.7 new_draw_info_format (NDI_UNIQUE, 0, op, "%s: %d", change_resist_msg[attack], tmp->resist[attack]);
563 elmex 1.1 }
564     }
565 root 1.7 break;
566 elmex 1.1 }
567     }
568 root 1.7 }
569 elmex 1.1
570 root 1.7 return 0;
571 elmex 1.1 }
572 root 1.7
573 elmex 1.1 /*
574     * Actual commands.
575     * Those should be in small separate files (c_object.c, c_wiz.c, cmove.c,...)
576     */
577    
578    
579 root 1.7 static void
580     help_topics (object *op, int what)
581 elmex 1.1 {
582 root 1.7 DIR *dirp;
583     struct dirent *de;
584     char filename[MAX_BUF], line[80];
585     int namelen, linelen = 0;
586    
587     switch (what)
588     {
589 root 1.21 case 1:
590     sprintf (filename, "%s/wizhelp", settings.datadir);
591     new_draw_info (NDI_UNIQUE, 0, op, " Wiz commands:");
592     break;
593     case 3:
594     sprintf (filename, "%s/mischelp", settings.datadir);
595     new_draw_info (NDI_UNIQUE, 0, op, " Misc help:");
596     break;
597     default:
598     sprintf (filename, "%s/help", settings.datadir);
599     new_draw_info (NDI_UNIQUE, 0, op, " Commands:");
600     break;
601 root 1.7 }
602 root 1.21
603 root 1.7 if (!(dirp = opendir (filename)))
604     return;
605    
606     line[0] = '\0';
607 pippijn 1.45 while ((de = readdir (dirp)))
608 root 1.7 {
609 root 1.21 namelen = strlen (de->d_name);
610 root 1.7 if (namelen <= 2 && *de->d_name == '.' && (namelen == 1 || de->d_name[1] == '.'))
611     continue;
612     linelen += namelen + 1;
613     if (linelen > 42)
614     {
615     new_draw_info (NDI_UNIQUE, 0, op, line);
616     sprintf (line, " %s", de->d_name);
617     linelen = namelen + 1;
618     continue;
619 root 1.3 }
620 root 1.7 strcat (line, " ");
621     strcat (line, de->d_name);
622 elmex 1.1 }
623 root 1.7 new_draw_info (NDI_UNIQUE, 0, op, line);
624     closedir (dirp);
625 elmex 1.1 }
626    
627 root 1.7 static void
628     show_commands (object *op, int what)
629 elmex 1.1 {
630     char line[80];
631 root 1.7 int i, size, namelen, linelen = 0;
632 elmex 1.1 CommArray_s *ap;
633     extern CommArray_s Commands[], WizCommands[];
634     extern const int CommandsSize, WizCommandsSize;
635 root 1.7
636     switch (what)
637     {
638     case 1:
639     ap = WizCommands;
640     size = WizCommandsSize;
641     new_draw_info (NDI_UNIQUE, 0, op, " Wiz commands:");
642     break;
643     case 2:
644     ap = CommunicationCommands;
645     size = CommunicationCommandSize;
646     new_draw_info (NDI_UNIQUE, 0, op, " Communication commands:");
647     break;
648     default:
649     ap = Commands;
650     size = CommandsSize;
651     new_draw_info (NDI_UNIQUE, 0, op, " Commands:");
652     break;
653     }
654    
655     line[0] = '\0';
656     for (i = 0; i < size; i++)
657     {
658     namelen = strlen (ap[i].name);
659     linelen += namelen + 1;
660     if (linelen > 42)
661     {
662     new_draw_info (NDI_UNIQUE, 0, op, line);
663     sprintf (line, " %s", ap[i].name);
664     linelen = namelen + 1;
665     continue;
666     }
667     strcat (line, " ");
668     strcat (line, ap[i].name);
669     }
670     new_draw_info (NDI_UNIQUE, 0, op, line);
671 elmex 1.1 }
672    
673    
674 root 1.7 int
675     command_help (object *op, char *params)
676 elmex 1.1 {
677     struct stat st;
678     FILE *fp;
679     char filename[MAX_BUF], line[MAX_BUF];
680     int len;
681    
682 root 1.7 if (op != NULL)
683     clear_win_info (op);
684 elmex 1.1
685     /*
686     * Main help page?
687     */
688 root 1.7 if (!params)
689     {
690     sprintf (filename, "%s/def_help", settings.datadir);
691     if ((fp = fopen (filename, "r")) == NULL)
692     {
693     LOG (llevError, "Cannot open help file %s: %s\n", filename, strerror (errno));
694     return 0;
695     }
696     while (fgets (line, MAX_BUF, fp))
697     {
698     line[MAX_BUF - 1] = '\0';
699     len = strlen (line) - 1;
700     if (line[len] == '\n')
701     line[len] = '\0';
702     new_draw_info (NDI_UNIQUE, 0, op, line);
703     }
704     fclose (fp);
705 elmex 1.1 return 0;
706     }
707    
708     /*
709     * Topics list
710     */
711 root 1.7 if (!strcmp (params, "topics"))
712     {
713     help_topics (op, 3);
714     help_topics (op, 0);
715     if (QUERY_FLAG (op, FLAG_WIZ))
716     help_topics (op, 1);
717     return 0;
718 elmex 1.1 }
719 root 1.7
720 elmex 1.1 /*
721     * Commands list
722     */
723 root 1.7 if (!strcmp (params, "commands"))
724     {
725     show_commands (op, 0);
726     show_commands (op, 2); /* show comm commands */
727     if (QUERY_FLAG (op, FLAG_WIZ))
728     show_commands (op, 1);
729     return 0;
730     }
731 elmex 1.1
732     /*
733     * User wants info about command
734     */
735 root 1.7 if (strchr (params, '.') || strchr (params, ' ') || strchr (params, '/'))
736     {
737     sprintf (line, "Illegal characters in '%s'", params);
738     new_draw_info (NDI_UNIQUE, 0, op, line);
739     return 0;
740     }
741 elmex 1.1
742 root 1.7 sprintf (filename, "%s/mischelp/%s", settings.datadir, params);
743     if (stat (filename, &st) || !S_ISREG (st.st_mode))
744     {
745     if (op)
746     {
747     sprintf (filename, "%s/help/%s", settings.datadir, params);
748     if (stat (filename, &st) || !S_ISREG (st.st_mode))
749     {
750     if (QUERY_FLAG (op, FLAG_WIZ))
751     {
752     sprintf (filename, "%s/wizhelp/%s", settings.datadir, params);
753     if (stat (filename, &st) || !S_ISREG (st.st_mode))
754     goto nohelp;
755     }
756     else
757     goto nohelp;
758     }
759     }
760     }
761 elmex 1.1
762     /*
763     * Found that. Just cat it to screen.
764     */
765 root 1.7 if ((fp = fopen (filename, "r")) == NULL)
766     {
767     LOG (llevError, "Cannot open help file %s: %s\n", filename, strerror (errno));
768     return 0;
769     }
770     sprintf (line, "Help about '%s'", params);
771     new_draw_info (NDI_UNIQUE, 0, op, line);
772     while (fgets (line, MAX_BUF, fp))
773     {
774     line[MAX_BUF - 1] = '\0';
775     len = strlen (line) - 1;
776     if (line[len] == '\n')
777     line[len] = '\0';
778     new_draw_info (NDI_UNIQUE, 0, op, line);
779 elmex 1.1 }
780 root 1.7 fclose (fp);
781 elmex 1.1 return 0;
782    
783     /*
784     * No_help -escape
785     */
786 root 1.7 nohelp:
787     sprintf (line, "No help available on '%s'", params);
788     new_draw_info (NDI_UNIQUE, 0, op, line);
789 elmex 1.1 return 0;
790     }
791    
792    
793 root 1.7 int
794     onoff_value (const char *line)
795 elmex 1.1 {
796     int i;
797    
798 root 1.7 if (sscanf (line, "%d", &i))
799 elmex 1.1 return (i != 0);
800 root 1.7 switch (line[0])
801     {
802     case 'o':
803     switch (line[1])
804     {
805     case 'n':
806     return 1; /* on */
807     default:
808     return 0; /* o[ff] */
809     }
810     case 'y': /* y[es] */
811     case 'k': /* k[ylla] */
812     case 's':
813     case 'd':
814     return 1;
815     case 'n': /* n[o] */
816     case 'e': /* e[i] */
817     case 'u':
818     default:
819     return 0;
820     }
821 elmex 1.1 }
822    
823 root 1.7 int
824     command_title (object *op, char *params)
825 elmex 1.1 {
826 root 1.7 char buf[MAX_BUF];
827    
828     if (settings.set_title == FALSE)
829     {
830     new_draw_info (NDI_UNIQUE, 0, op, "You cannot change your title.");
831     return 1;
832 elmex 1.1 }
833 root 1.7
834     /* dragon players cannot change titles */
835     if (is_dragon_pl (op))
836     {
837     new_draw_info (NDI_UNIQUE, 0, op, "Dragons cannot change titles.");
838     return 1;
839     }
840    
841     if (params == NULL)
842     {
843     if (op->contr->own_title[0] == '\0')
844     sprintf (buf, "Your title is '%s'.", op->contr->title);
845     else
846     sprintf (buf, "Your title is '%s'.", op->contr->own_title);
847     new_draw_info (NDI_UNIQUE, 0, op, buf);
848     return 1;
849     }
850     if (strcmp (params, "clear") == 0 || strcmp (params, "default") == 0)
851     {
852     if (op->contr->own_title[0] == '\0')
853     new_draw_info (NDI_UNIQUE, 0, op, "Your title is the default title.");
854     else
855     new_draw_info (NDI_UNIQUE, 0, op, "Title set to default.");
856     op->contr->own_title[0] = '\0';
857     return 1;
858     }
859    
860     if ((int) strlen (params) >= MAX_NAME)
861     {
862     new_draw_info (NDI_UNIQUE, 0, op, "Title too long.");
863     return 1;
864     }
865     strcpy (op->contr->own_title, params);
866     return 1;
867 elmex 1.1 }
868    
869 root 1.7 int
870     command_kill_pets (object *op, char *params)
871 elmex 1.1 {
872 root 1.7 objectlink *obl, *next;
873     int counter = 0, removecount = 0;
874    
875     if (params == NULL)
876     {
877     terminate_all_pets (op);
878     new_draw_info (NDI_UNIQUE, 0, op, "Your pets have been killed.");
879     }
880     else
881     {
882     int target = atoi (params);
883    
884     for (obl = first_friendly_object; obl != NULL; obl = next)
885     {
886     object *ob = obl->ob;
887    
888     next = obl->next;
889 root 1.22 if (ob->owner == op)
890 root 1.7 if (++counter == target || (target == 0 && !strcasecmp (ob->name, params)))
891     {
892 root 1.20 ob->destroy ();
893 root 1.3 removecount++;
894 root 1.7 }
895 root 1.3 }
896 root 1.7 if (removecount != 0)
897     new_draw_info_format (NDI_UNIQUE, 0, op, "killed %d pets.\n", removecount);
898     else
899     new_draw_info (NDI_UNIQUE, 0, op, "Couldn't find any suitable pets to kill.\n");
900 elmex 1.1 }
901 root 1.7 return 0;
902 elmex 1.1 }