ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/server/c_misc.C
Revision: 1.6
Committed: Mon Sep 4 11:08:00 2006 UTC (17 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.5: +1 -87 lines
Log Message:
Changes...

- alternative shstr representation, saves code
- use glibs splice memory allocator (seems slower)
- use simpler memory/lifetime management for objects, no recycling

File Contents

# User Rev Content
1 elmex 1.1 /*
2     * static char *rcsid_c_misc_c =
3 root 1.6 * "$Id: c_misc.C,v 1.5 2006-09-03 00:18:42 root Exp $";
4 elmex 1.1 */
5    
6     /*
7     CrossFire, A Multiplayer game for X-windows
8    
9     Copyright (C) 2002 Mark Wedel & Crossfire Development Team
10     Copyright (C) 1992 Frank Tore Johansen
11    
12     This program is free software; you can redistribute it and/or modify
13     it under the terms of the GNU General Public License as published by
14     the Free Software Foundation; either version 2 of the License, or
15     (at your option) any later version.
16    
17     This program is distributed in the hope that it will be useful,
18     but WITHOUT ANY WARRANTY; without even the implied warranty of
19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20     GNU General Public License for more details.
21    
22     You should have received a copy of the GNU General Public License
23     along with this program; if not, write to the Free Software
24     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25    
26     The authors can be reached via e-mail at crossfire-devel@real-time.com
27     */
28    
29     #include <global.h>
30     #include <loader.h>
31     #ifndef __CEXTRACT__
32     #include <sproto.h>
33     #endif
34    
35     extern weathermap_t **weathermap;
36    
37     /* Handles misc. input request - things like hash table, malloc, maps,
38     * who, etc.
39     */
40    
41     void map_info(object *op, char *search) {
42     mapstruct *m;
43     char buf[MAX_BUF], map_path[MAX_BUF];
44     long sec = seconds();
45     new_draw_info_format(NDI_UNIQUE, 0, op,
46 root 1.3 "Current time is: %02ld:%02ld:%02ld.",
47     (sec%86400)/3600,(sec%3600)/60,sec%60);
48 elmex 1.1 new_draw_info(NDI_UNIQUE, 0,op,"Path Pl PlM IM TO Dif Reset");
49     for(m=first_map;m!=NULL;m=m->next) {
50    
51     if ( search && strstr(m->path,search)==NULL ) continue; /* Skip unwanted maps */
52     /* Print out the last 18 characters of the map name... */
53     if (strlen(m->path)<=18) strcpy(map_path, m->path);
54     else strcpy(map_path, m->path + strlen(m->path) - 18);
55     sprintf(buf,"%-18.18s %2d %2d %1d %4d %2d %02d:%02d:%02d",
56     map_path, m->players,players_on_map(m,FALSE),
57     m->in_memory,m->timeout,m->difficulty,
58 root 1.3 (MAP_WHEN_RESET(m)%86400)/3600,(MAP_WHEN_RESET(m)%3600)/60,
59 elmex 1.1 MAP_WHEN_RESET(m)%60);
60     new_draw_info(NDI_UNIQUE, 0,op,buf);
61     }
62     }
63    
64     /* This command dumps the body information for object *op.
65     * it doesn't care what the params are.
66     * This is mostly meant as a debug command.
67     */
68     int command_body(object *op, char *params)
69     {
70     int i;
71    
72     /* Too hard to try and make a header that lines everything up, so just
73     * give a description.
74     */
75     new_draw_info(NDI_UNIQUE, 0, op, "The first column is the name of the body location.");
76     new_draw_info(NDI_UNIQUE, 0, op, "The second column is how many of those locations your body has.");
77     new_draw_info(NDI_UNIQUE, 0, op, "The third column is how many slots in that location are available.");
78     for (i=0; i<NUM_BODY_LOCATIONS; i++) {
79 root 1.3 /* really debugging - normally body_used should not be set to anything
80     * if body_info isn't also set.
81     */
82     if (op->body_info[i] || op->body_used[i]) {
83     new_draw_info_format(NDI_UNIQUE, 0, op,
84     "%-30s %5d %5d", body_locations[i].use_name, op->body_info[i], op->body_used[i]);
85     }
86 elmex 1.1 }
87     if (!QUERY_FLAG(op, FLAG_USE_ARMOUR))
88 root 1.3 new_draw_info(NDI_UNIQUE, 0, op, "You are not allowed to wear armor");
89 elmex 1.1 if (!QUERY_FLAG(op, FLAG_USE_WEAPON))
90 root 1.3 new_draw_info(NDI_UNIQUE, 0, op, "You are not allowed to use weapons");
91 elmex 1.1
92     return 1;
93     }
94    
95    
96     int command_motd(object *op, char *params)
97     {
98 root 1.3 display_motd(op);
99     return 1;
100 elmex 1.1 }
101    
102     int command_bug(object *op, char *params)
103     {
104     char buf[MAX_BUF];
105    
106     if (params == NULL) {
107     new_draw_info(NDI_UNIQUE, 0,op,"what bugs?");
108     return 1;
109     }
110     strcpy(buf,op->name);
111     strcat(buf," bug-reports: ");
112     strncat(buf,++params,MAX_BUF - strlen(buf) );
113     buf[MAX_BUF - 1] = '\0';
114     bug_report(buf);
115     LOG(llevError,"%s\n",buf);
116     new_draw_info(NDI_ALL | NDI_UNIQUE, 1, NULL, buf);
117     new_draw_info(NDI_UNIQUE, 0,op, "OK, thanks!");
118     return 1;
119     }
120    
121     /*
122     * Pretty much identical to current map_info, but on a bigger scale
123     * This function returns the name of the players current region, and
124     * a description of it. It is there merely for flavour text.
125     */
126     void current_region_info(object *op) {
127     /*
128     * Ok I /suppose/ I should write a seperate function for this, but it isn't
129     * going to be /that/ slow, and won't get called much
130     */
131     region *r = get_region_by_name(get_name_of_region_for_map(op->map));
132    
133     if (!r)
134 root 1.3 return;
135     /* This should only be possible if regions are not operating on this server. */
136 elmex 1.1
137     new_draw_info_format(NDI_UNIQUE, 0,op,
138 root 1.3 "You are in %s. \n %s", get_region_longname(r), get_region_msg(r));
139 elmex 1.1 }
140    
141     void current_map_info(object *op) {
142     mapstruct *m = op->map;
143    
144     if (!m)
145 root 1.3 return;
146 elmex 1.1
147     new_draw_info_format(NDI_UNIQUE, 0,op,
148 root 1.3 "%s (%s) in %s", m->name, m->path, get_name_of_region_for_map(m));
149 elmex 1.1
150     if (QUERY_FLAG(op,FLAG_WIZ)) {
151 root 1.3 new_draw_info_format(NDI_UNIQUE, 0, op,
152     "players:%d difficulty:%d size:%dx%d start:%dx%d timeout %ld",
153     m->players, m->difficulty,
154     MAP_WIDTH(m), MAP_HEIGHT(m),
155     MAP_ENTER_X(m), MAP_ENTER_Y(m),
156     MAP_TIMEOUT(m));
157 elmex 1.1
158     }
159     if (m->msg)
160 root 1.3 new_draw_info(NDI_UNIQUE, NDI_NAVY, op, m->msg);
161 elmex 1.1 }
162    
163     #ifdef DEBUG_MALLOC_LEVEL
164     int command_malloc_verify(object *op, char *parms)
165     {
166 root 1.3 extern int malloc_verify(void);
167 elmex 1.1
168 root 1.3 if (!malloc_verify())
169     new_draw_info(NDI_UNIQUE, 0,op,"Heap is corrupted.");
170     else
171     new_draw_info(NDI_UNIQUE, 0,op,"Heap checks out OK.");
172     return 1;
173     }
174 elmex 1.1 #endif
175    
176     int command_whereabouts(object *op, char *params) {
177    
178     region *reg;
179     player *pl;
180    
181     /*
182     * reset the counter on the region, then use it to store the number of
183     * players there.
184     * I don't know how thread-safe this would be, I suspect not very....
185     */
186     for (reg=first_region;reg!=NULL;reg=reg->next) {
187     reg->counter=0;
188     }
189     for (pl=first_player;pl!=NULL;pl=pl->next)
190     if (pl->ob->map!=NULL)
191     get_region_by_map(pl->ob->map)->counter++;
192    
193     /* we only want to print out by places with a 'longname' field...*/
194     for (reg=first_region;reg!=NULL;reg=reg->next) {
195 root 1.3 if (reg->longname==NULL && reg->counter>0) {
196     if(reg->parent !=NULL) {
197     reg->parent->counter+=reg->counter;
198     reg->counter=0;
199     }
200     else /*uh oh, we shouldn't be here. */
201     LOG(llevError,"command_whereabouts() Region %s with no longname has no parent", reg->name);
202     }
203     }
204     new_draw_info_format(NDI_UNIQUE, 0,op,
205     "In the world currently there are:");
206     for (reg=first_region;reg!=NULL;reg=reg->next)
207     if(reg->counter>0)
208     new_draw_info_format(NDI_UNIQUE, 0,op,
209     "%u players in %s", reg->counter, get_region_longname(reg));
210 elmex 1.1 return 1;
211     }
212    
213     typedef struct
214     {
215     char namebuf[MAX_BUF];
216     int login_order;
217     } chars_names;
218    
219     /*local functon for qsort comparison*/
220     static int name_cmp (const chars_names *c1, const chars_names *c2)
221     {
222     return strcasecmp (c1->namebuf, c2->namebuf);
223     }
224    
225     int command_who (object *op, char *params) {
226     player *pl;
227     uint16 i;
228     region *reg;
229     char* format;
230     int num_players = 0;
231     int num_wiz = 0;
232     int num_afk = 0;
233     chars_names *chars = NULL;
234    
235     /*
236     * The who formats are defined in config to be blank. They should have been
237     * overridden by the settings file, if there are no entries however, it will
238     * have stayed blank. Since this probably isn't what is wanted, we will check if
239     * new formats have been specified, and if not we will use the old defaults.
240     */
241     if (!strcmp(settings.who_format,""))
242     strcpy(settings.who_format, "%N_%T%t%h%d%n[%m]");
243     if (!strcmp(settings.who_wiz_format,""))
244     strcpy(settings.who_wiz_format, "%N_%T%t%h%d%nLevel %l [%m](@%i)(%c)");
245     if (op == NULL || QUERY_FLAG(op, FLAG_WIZ))
246     format=settings.who_wiz_format;
247     else
248     format=settings.who_format;
249    
250     reg=get_region_from_string(params);
251    
252     for (pl=first_player;pl!=NULL;pl=pl->next) {
253 root 1.3 if (pl->ob->map == NULL)
254     continue;
255     if (pl->hidden && !QUERY_FLAG(op, FLAG_WIZ)) continue;
256    
257     if(!region_is_child_of_region(get_region_by_map(pl->ob->map),reg)) continue;
258 elmex 1.1
259 root 1.3 if (pl->state==ST_PLAYING || pl->state==ST_GET_PARTY_PASSWORD) {
260 elmex 1.1
261 root 1.3 num_players++;
262     chars = (chars_names *) realloc(chars, num_players*sizeof(chars_names));
263 elmex 1.1 if (chars == NULL) {
264 root 1.3 new_draw_info(NDI_UNIQUE, 0, op, "who failed - out of memory!");
265 elmex 1.1 return 0;
266     }
267 root 1.5 sprintf(chars[num_players-1].namebuf, "%s", &pl->ob->name);
268 root 1.3 chars[num_players-1].login_order = num_players;
269     /*Check for WIZ's & AFK's*/
270     if (QUERY_FLAG(pl->ob,FLAG_WIZ))
271     num_wiz++;
272     if (QUERY_FLAG(pl->ob,FLAG_AFK))
273     num_afk++;
274     }
275 elmex 1.1 }
276     if (first_player != (player *) NULL) {
277     if (reg == NULL)
278     new_draw_info_format(NDI_UNIQUE, 0, op, "Total Players (%d) -- WIZ(%d) AFK(%d)",
279     num_players, num_wiz, num_afk);
280 root 1.3 else if (reg->longname == NULL)
281     new_draw_info_format(NDI_UNIQUE, 0, op, "Total Players in %s (%d) -- WIZ(%d) AFK(%d)",
282 elmex 1.1 reg->name, num_players, num_wiz, num_afk);
283 root 1.3 else
284     new_draw_info_format(NDI_UNIQUE, 0, op, "Total Players in %s (%d) -- WIZ(%d) AFK(%d)",
285 elmex 1.1 reg->longname, num_players, num_wiz, num_afk);
286     }
287     qsort (chars, num_players, sizeof(chars_names), (int (*)(const void *, const void *))name_cmp);
288     for (i=0;i<num_players;i++)
289 root 1.3 display_who_entry(op, find_player(chars[i].namebuf), format);
290 elmex 1.1 free(chars);
291     return 1;
292     }
293    
294     /* Display a line of 'who' to op, about pl, using the formatting specified by format */
295     void display_who_entry(object *op, player *pl, const char *format) {
296     char tmpbuf[MAX_BUF];
297     char outbuf[MAX_BUF];
298     size_t i;
299     outbuf[0]='\0'; /* we strcat to this, so reset it here. */
300     if (pl==NULL) {
301     LOG(llevError,"display_who_entry(): I was passed a null player");
302 root 1.3 return;
303 elmex 1.1 }
304     for (i=0;i<=strlen(format);i++) {
305     if (format[i]=='%') {
306     i++;
307     get_who_escape_code_value(tmpbuf,format[i],pl);
308     strcat(outbuf, tmpbuf);
309     }
310     else if (format[i]=='_')
311     strcat(outbuf," "); /* allow '_' to be used in place of spaces */
312     else {
313     sprintf(tmpbuf,"%c",format[i]);
314     strcat(outbuf,tmpbuf);
315     }
316     }
317     new_draw_info(NDI_UNIQUE, 0, op, outbuf);
318     }
319    
320     /* Returns the value of the escape code used in the who format specifier
321     * the values are:
322     * N Name of character
323     * t title of character
324     * T the optional "the " sequence value (depend if player has own_title or not)
325     * c count
326     * n newline
327     * h [Hostile] if character is hostile, nothing otherwise
328     * d [WIZ] if character is a dm, nothing otherwise
329     * a [AFK] if character is afk, nothing otherwise
330     * l the level of the character
331     * m the map path the character is currently on
332     * M the map name of the map the character is currently on
333     * r the region name (eg scorn, wolfsburg)
334     * R the regional title (eg The Kingdom of Scorn, The Port of Wolfsburg)
335     * i player's ip adress
336     * % a literal %
337     * _ a literal underscore
338     */
339    
340     void get_who_escape_code_value(char *return_val, const char letter, player *pl) {
341    
342     switch (letter) {
343 root 1.3 case 'N' : strcpy(return_val, pl->ob->name);
344     break;
345     case 't' : strcpy(return_val,(pl->own_title[0]=='\0'?pl->title:pl->own_title));
346     break;
347 elmex 1.1 case 'T' : if (pl->own_title[0]=='\0')
348     strcpy(return_val,"the ");
349     else
350     *return_val='\0';
351     break;
352 root 1.3 case 'c' : sprintf(return_val,"%d",pl->ob->count);
353     break;
354     case 'n' : strcpy(return_val, "\n");
355     break;
356     case 'h' : strcpy(return_val,pl->peaceful?"":" [Hostile]");
357     break;
358     case 'l' : sprintf(return_val,"%d",pl->ob->level);
359     break;
360     case 'd' : strcpy(return_val,(QUERY_FLAG(pl->ob,FLAG_WIZ)?" [WIZ]":""));
361     break;
362     case 'a' : strcpy(return_val,(QUERY_FLAG(pl->ob,FLAG_AFK)?" [AFK]":""));
363     break;
364     case 'm' : strcpy(return_val,pl->ob->map->path);
365     break;
366     case 'M' : strcpy(return_val,pl->ob->map->name?pl->ob->map->name:"Untitled");
367     break;
368     case 'r' : strcpy(return_val,get_name_of_region_for_map(pl->ob->map));
369     break;
370     case 'R' : strcpy(return_val,get_region_longname(get_region_by_map(pl->ob->map)));
371     break;
372     case 'i' : strcpy(return_val,pl->socket.host);
373     break;
374     case '%' : strcpy(return_val, "%");
375     break;
376     case '_' : strcpy(return_val, "_");
377     break;
378 elmex 1.1 }
379    
380     }
381    
382    
383     int command_afk (object *op, char *params)
384     {
385     if QUERY_FLAG(op,FLAG_AFK) {
386     CLEAR_FLAG(op,FLAG_AFK);
387     new_draw_info(NDI_UNIQUE, 0, op, "You are no longer AFK");
388     }
389     else
390     {
391     SET_FLAG(op,FLAG_AFK);
392     new_draw_info(NDI_UNIQUE, 0, op, "You are now AFK");
393     }
394     return 1;
395     }
396    
397     int command_mapinfo (object *op, char *params)
398     {
399     current_map_info(op);
400     return 1;
401     }
402    
403     int command_whereami (object *op, char *params)
404     {
405     current_region_info(op);
406     return 1;
407     }
408    
409     int command_maps (object *op, char *params)
410     {
411     map_info(op,params);
412     return 1;
413     }
414    
415     int command_time (object *op, char *params)
416     {
417 root 1.2 print_tod (op);
418     return 1;
419     }
420 elmex 1.1
421     int command_weather (object *op, char *params)
422     {
423     int wx, wy, temp, sky;
424     char buf[MAX_BUF];
425    
426     if (settings.dynamiclevel < 1)
427 root 1.3 return 1;
428 elmex 1.1
429     if (op->map == NULL)
430 root 1.3 return 1;
431 elmex 1.1
432     if (worldmap_to_weathermap(op->x, op->y, &wx, &wy, op->map) != 0)
433 root 1.3 return 1;
434 elmex 1.1
435     if (QUERY_FLAG(op, FLAG_WIZ)) {
436 root 1.3 /* dump the weather, Dm style! Yo! */
437     new_draw_info_format(NDI_UNIQUE, 0, op, "Real temp: %d",
438     real_world_temperature(op->x, op->y, op->map));
439     new_draw_info_format(NDI_UNIQUE, 0, op, "Base temp: %d",
440     weathermap[wx][wy].temp);
441     new_draw_info_format(NDI_UNIQUE, 0, op, "Humid: %d",
442     weathermap[wx][wy].humid);
443     new_draw_info_format(NDI_UNIQUE, 0, op, "Wind: dir=%d speed=%d",
444     weathermap[wx][wy].winddir, weathermap[wx][wy].windspeed);
445     new_draw_info_format(NDI_UNIQUE, 0, op, "Pressure: %d",
446     weathermap[wx][wy].pressure);
447     new_draw_info_format(NDI_UNIQUE, 0, op, "Avg Elevation: %d",
448     weathermap[wx][wy].avgelev);
449     new_draw_info_format(NDI_UNIQUE, 0, op, "Rainfall: %d Water: %d",
450     weathermap[wx][wy].rainfall, weathermap[wx][wy].water);
451 elmex 1.1 }
452    
453     temp = real_world_temperature(op->x, op->y, op->map);
454     new_draw_info_format(NDI_UNIQUE, 0, op, "It's currently %d degrees "
455 root 1.3 "Centigrade out.", temp);
456 elmex 1.1
457     /* humid */
458     if (weathermap[wx][wy].humid < 20)
459 root 1.3 new_draw_info(NDI_UNIQUE, 0, op, "It is very dry.");
460 elmex 1.1 else if (weathermap[wx][wy].humid < 40)
461 root 1.3 new_draw_info(NDI_UNIQUE, 0, op, "It is very comfortable today.");
462 elmex 1.1 else if (weathermap[wx][wy].humid < 60)
463 root 1.3 new_draw_info(NDI_UNIQUE, 0, op, "It is a bit muggy.");
464 elmex 1.1 else if (weathermap[wx][wy].humid < 80)
465 root 1.3 new_draw_info(NDI_UNIQUE, 0, op, "It is muggy.");
466 elmex 1.1 else
467 root 1.3 new_draw_info(NDI_UNIQUE, 0, op, "It is uncomfortably muggy.");
468 elmex 1.1
469     /* wind */
470     switch (weathermap[wx][wy].winddir) {
471     case 1: sprintf(buf, "north"); break;
472     case 2: sprintf(buf, "northeast"); break;
473     case 3: sprintf(buf, "east"); break;
474     case 4: sprintf(buf, "southeast"); break;
475     case 5: sprintf(buf, "south"); break;
476     case 6: sprintf(buf, "southwest"); break;
477     case 7: sprintf(buf, "west"); break;
478     case 8: sprintf(buf, "northwest"); break;
479     }
480     if (weathermap[wx][wy].windspeed < 5)
481 root 1.3 new_draw_info_format(NDI_UNIQUE, 0, op, "There is a mild breeze "
482     "coming from the %s.", buf);
483 elmex 1.1 else if (weathermap[wx][wy].windspeed < 10)
484 root 1.3 new_draw_info_format(NDI_UNIQUE, 0, op, "There is a strong breeze "
485     "coming from the %s.", buf);
486 elmex 1.1 else if (weathermap[wx][wy].windspeed < 15)
487 root 1.3 new_draw_info_format(NDI_UNIQUE, 0, op, "There is a light wind "
488     "coming from the %s.", buf);
489 elmex 1.1 else if (weathermap[wx][wy].windspeed < 25)
490 root 1.3 new_draw_info_format(NDI_UNIQUE, 0, op, "There is a strong wind "
491     "coming from the %s.", buf);
492 elmex 1.1 else if (weathermap[wx][wy].windspeed < 35)
493 root 1.3 new_draw_info_format(NDI_UNIQUE, 0, op, "There is a heavy wind "
494     "coming from the %s.", buf);
495 elmex 1.1 else
496 root 1.3 new_draw_info_format(NDI_UNIQUE, 0, op, "The wind from the %s is "
497     "incredibly strong!", buf);
498 elmex 1.1
499     sky = weathermap[wx][wy].sky;
500     if (temp <= 0 && sky > SKY_OVERCAST && sky < SKY_FOG)
501 root 1.3 sky += 10; /*let it snow*/
502 elmex 1.1 switch (sky) {
503     case SKY_CLEAR: new_draw_info(NDI_UNIQUE, 0, op, "There isn''t a cloud in the sky."); break;
504     case SKY_LIGHTCLOUD: new_draw_info(NDI_UNIQUE, 0, op, "There are a few light clouds in the sky."); break;
505     case SKY_OVERCAST: new_draw_info(NDI_UNIQUE, 0, op, "The sky is cloudy and dreary."); break;
506     case SKY_LIGHT_RAIN: new_draw_info(NDI_UNIQUE, 0, op, "It is raining softly."); break;
507     case SKY_RAIN: new_draw_info(NDI_UNIQUE, 0, op, "It is raining."); break;
508     case SKY_HEAVY_RAIN: new_draw_info(NDI_UNIQUE, 0, op, "It is raining heavily."); break;
509     case SKY_HURRICANE: new_draw_info(NDI_UNIQUE, 0, op, "There is a heavy storm! You should go inside!"); break;
510     case SKY_FOG: new_draw_info(NDI_UNIQUE, 0, op, "It''s foggy and miserable."); break;
511     case SKY_HAIL: new_draw_info(NDI_UNIQUE, 0, op, "It''s hailing out! Take cover!"); break;
512     case SKY_LIGHT_SNOW: new_draw_info(NDI_UNIQUE, 0, op, "Snow is gently falling from the sky."); break;
513     case SKY_SNOW: new_draw_info(NDI_UNIQUE, 0, op, "It''s snowing out."); break;
514     case SKY_HEAVY_SNOW: new_draw_info(NDI_UNIQUE, 0, op, "The snow is falling very heavily now."); break;
515     case SKY_BLIZZARD: new_draw_info(NDI_UNIQUE, 0, op, "A full blown blizzard is in effect. You might want to take cover!"); break;
516     }
517     return 1;
518     }
519    
520     int command_archs (object *op, char *params)
521     {
522     arch_info(op);
523     return 1;
524     }
525    
526     int command_hiscore (object *op, char *params)
527     {
528     display_high_score(op,op==NULL?9999:50, params);
529     return 1;
530     }
531    
532     int command_debug (object *op, char *params)
533     {
534     int i;
535     char buf[MAX_BUF];
536     if(params==NULL || !sscanf(params, "%d", &i)) {
537     sprintf(buf,"Global debug level is %d.",settings.debug);
538     new_draw_info(NDI_UNIQUE, 0,op,buf);
539     return 1;
540     }
541     if(op != NULL && !QUERY_FLAG(op, FLAG_WIZ)) {
542     new_draw_info(NDI_UNIQUE, 0,op,"Privileged command.");
543     return 1;
544     }
545     settings.debug = (enum LogLevel) FABS(i);
546     sprintf(buf,"Set debug level to %d.", i);
547     new_draw_info(NDI_UNIQUE, 0,op,buf);
548     return 1;
549     }
550    
551    
552     /*
553     * Those dumps should be just one dump with good parser
554     */
555    
556     int command_dumpbelow (object *op, char *params)
557     {
558     if (op && op->below) {
559 root 1.3 dump_object(op->below);
560     new_draw_info(NDI_UNIQUE, 0,op,errmsg);
561 elmex 1.1 /* Let's push that item on the dm's stack */
562     dm_stack_push( op->contr, op->below->count );
563     }
564     return 0;
565     }
566    
567     int command_wizpass (object *op, char *params)
568     {
569     int i;
570    
571     if (!op)
572     return 0;
573    
574     if (!params)
575     i = (QUERY_FLAG(op, FLAG_WIZPASS)) ? 0 : 1;
576     else
577     i =onoff_value(params);
578    
579     if (i) {
580     new_draw_info(NDI_UNIQUE, 0,op, "You will now walk through walls.\n");
581 root 1.3 SET_FLAG(op, FLAG_WIZPASS);
582 elmex 1.1 } else {
583     new_draw_info(NDI_UNIQUE, 0,op, "You will now be stopped by walls.\n");
584     CLEAR_FLAG(op, FLAG_WIZPASS);
585     }
586     return 0;
587     }
588    
589     int command_wizcast (object *op, char *params)
590     {
591     int i;
592    
593     if (!op)
594     return 0;
595    
596     if (!params)
597     i = (QUERY_FLAG(op, FLAG_WIZCAST)) ? 0 : 1;
598     else
599     i = onoff_value(params);
600    
601     if (i) {
602     new_draw_info(NDI_UNIQUE, 0, op, "You can now cast spells anywhere.");
603     SET_FLAG(op, FLAG_WIZCAST);
604     } else {
605     new_draw_info(NDI_UNIQUE, 0, op, "You now cannot cast spells in no-magic areas.");
606     CLEAR_FLAG(op, FLAG_WIZCAST);
607     }
608     return 0;
609     }
610    
611     int command_dumpallobjects (object *op, char *params)
612     {
613     dump_all_objects();
614     return 0;
615     }
616    
617     int command_dumpfriendlyobjects (object *op, char *params)
618     {
619     dump_friendly_objects();
620     return 0;
621     }
622    
623     int command_dumpallarchetypes (object *op, char *params)
624     {
625     dump_all_archetypes();
626     return 0;
627     }
628    
629     int command_dumpmap (object *op, char *params)
630     {
631     if(op)
632     dump_map(op->map);
633     return 0;
634     }
635    
636     int command_dumpallmaps (object *op, char *params)
637     {
638     dump_all_maps();
639     return 0;
640     }
641    
642     int command_printlos (object *op, char *params)
643     {
644     if (op)
645     print_los(op);
646     return 0;
647     }
648    
649    
650     int command_version (object *op, char *params)
651     {
652     version(op);
653     return 0;
654     }
655    
656    
657     #ifndef BUG_LOG
658     #define BUG_LOG "bug_log"
659     #endif
660     void bug_report(const char * reportstring){
661     FILE * fp;
662     if((fp = fopen( BUG_LOG , "a")) != NULL){
663     fprintf(fp,"%s\n", reportstring);
664     fclose(fp);
665     } else {
666 root 1.4 LOG(llevError, "Cannot write bugs file %s: %s\n", BUG_LOG, strerror(errno));
667 elmex 1.1 }
668     }
669    
670     int command_output_sync(object *op, char *params)
671     {
672     int val;
673    
674     if (!params) {
675 root 1.3 new_draw_info_format(NDI_UNIQUE, 0, op,
676     "Output sync time is presently %d", op->contr->outputs_sync);
677     return 1;
678 elmex 1.1 }
679     val=atoi(params);
680     if (val>0) {
681 root 1.3 op->contr->outputs_sync = val;
682     new_draw_info_format(NDI_UNIQUE, 0, op,
683     "Output sync time now set to %d", op->contr->outputs_sync);
684 elmex 1.1 }
685     else
686 root 1.3 new_draw_info(NDI_UNIQUE, 0, op,"Invalid value for output_sync.");
687 elmex 1.1
688     return 1;
689     }
690    
691     int command_output_count(object *op, char *params)
692     {
693     int val;
694    
695     if (!params) {
696 root 1.3 new_draw_info_format(NDI_UNIQUE, 0, op,
697     "Output count is presently %d", op->contr->outputs_count);
698     return 1;
699 elmex 1.1 }
700     val=atoi(params);
701     if (val>0) {
702 root 1.3 op->contr->outputs_count = val;
703     new_draw_info_format(NDI_UNIQUE, 0, op,
704     "Output count now set to %d", op->contr->outputs_count);
705 elmex 1.1 }
706     else
707 root 1.3 new_draw_info(NDI_UNIQUE, 0, op,"Invalid value for output_count.");
708 elmex 1.1
709     return 1;
710     }
711    
712     int command_listen (object *op, char *params)
713     {
714     int i;
715    
716     if(params==NULL || !sscanf(params, "%d", &i)) {
717     new_draw_info_format(NDI_UNIQUE, 0, op,
718 root 1.3 "Set listen to what (presently %d)?", op->contr->listening);
719 elmex 1.1 return 1;
720     }
721     op->contr->listening=(char) i;
722     new_draw_info_format(NDI_UNIQUE, 0, op,
723 root 1.3 "Your verbose level is now %d.",i);
724 elmex 1.1 return 1;
725     }
726    
727     /* Prints out some useful information for the character. Everything we print
728     * out can be determined by the docs, so we aren't revealing anything extra -
729     * rather, we are making it convenient to find the values. params have
730     * no meaning here.
731     */
732     int command_statistics(object *pl, char *params)
733     {
734     if (!pl->contr) return 1;
735     #ifndef WIN32
736     new_draw_info_format(NDI_UNIQUE, 0, pl," Experience: %lld",pl->stats.exp);
737     new_draw_info_format(NDI_UNIQUE, 0, pl," Next Level: %lld",level_exp(pl->level+1, pl->expmul));
738     #else
739     new_draw_info_format(NDI_UNIQUE, 0, pl," Experience: %I64d",pl->stats.exp);
740     new_draw_info_format(NDI_UNIQUE, 0, pl," Next Level: %I64d",level_exp(pl->level+1, pl->expmul));
741     #endif
742     new_draw_info(NDI_UNIQUE, 0, pl, "\nStat Nat/Real/Max");
743    
744     new_draw_info_format(NDI_UNIQUE, 0, pl, "Str %2d/ %3d/%3d",
745 root 1.3 pl->contr->orig_stats.Str, pl->stats.Str, 20+pl->arch->clone.stats.Str);
746 elmex 1.1 new_draw_info_format(NDI_UNIQUE, 0, pl, "Dex %2d/ %3d/%3d",
747 root 1.3 pl->contr->orig_stats.Dex, pl->stats.Dex, 20+pl->arch->clone.stats.Dex);
748 elmex 1.1 new_draw_info_format(NDI_UNIQUE, 0, pl, "Con %2d/ %3d/%3d",
749 root 1.3 pl->contr->orig_stats.Con, pl->stats.Con, 20+pl->arch->clone.stats.Con);
750 elmex 1.1 new_draw_info_format(NDI_UNIQUE, 0, pl, "Int %2d/ %3d/%3d",
751 root 1.3 pl->contr->orig_stats.Int, pl->stats.Int, 20+pl->arch->clone.stats.Int);
752 elmex 1.1 new_draw_info_format(NDI_UNIQUE, 0, pl, "Wis %2d/ %3d/%3d",
753 root 1.3 pl->contr->orig_stats.Wis, pl->stats.Wis, 20+pl->arch->clone.stats.Wis);
754 elmex 1.1 new_draw_info_format(NDI_UNIQUE, 0, pl, "Pow %2d/ %3d/%3d",
755 root 1.3 pl->contr->orig_stats.Pow, pl->stats.Pow, 20+pl->arch->clone.stats.Pow);
756 elmex 1.1 new_draw_info_format(NDI_UNIQUE, 0, pl, "Cha %2d/ %3d/%3d",
757 root 1.3 pl->contr->orig_stats.Cha, pl->stats.Cha, 20+pl->arch->clone.stats.Cha);
758 elmex 1.1 new_draw_info_format(NDI_UNIQUE, 0, pl, "\nAttack Mode: %s",pl->contr->peaceful? "Peaceful":"Hostile");
759    
760     /* Can't think of anything else to print right now */
761     return 0;
762     }
763    
764     int command_fix_me(object *op, char *params)
765     {
766     sum_weight(op);
767     fix_player(op);
768     return 1;
769     }
770    
771     int command_players(object *op, char *paramss)
772     {
773     char buf[MAX_BUF];
774     char *t;
775     DIR *Dir;
776    
777     sprintf(buf,"%s/%s/",settings.localdir,settings.playerdir);
778     t=buf+strlen(buf);
779     if ((Dir=opendir(buf))!=NULL) {
780 root 1.3 const struct dirent *Entry;
781    
782     while ((Entry=readdir(Dir))!=NULL) {
783     /* skip '.' , '..' */
784     if (!((Entry->d_name[0]=='.' && Entry->d_name[1]=='\0') ||
785     (Entry->d_name[0]=='.' && Entry->d_name[1]=='.' && Entry->d_name[2]=='\0')))
786     {
787     struct stat Stat;
788 elmex 1.1
789 root 1.3 strcpy(t,Entry->d_name);
790     if (stat(buf,&Stat)==0) {
791     /* This was not posix compatible
792 elmex 1.1 * if ((Stat.st_mode & S_IFMT)==S_IFDIR) {
793     */
794     if (S_ISDIR(Stat.st_mode)){
795 root 1.3 char buf2[MAX_BUF];
796     struct tm *tm=localtime(&Stat.st_mtime);
797     sprintf(buf2,"%s\t%04d %02d %02d %02d %02d %02d",
798     Entry->d_name,
799     1900+tm->tm_year,
800     1+tm->tm_mon,
801     tm->tm_mday,
802     tm->tm_hour,
803     tm->tm_min,
804     tm->tm_sec);
805     new_draw_info(NDI_UNIQUE, 0, op, buf2);
806     }
807     }
808     }
809     }
810 elmex 1.1 }
811     closedir(Dir);
812     return 0;
813     }
814    
815    
816    
817     int command_logs (object *op, char *params)
818     {
819     int i;
820     int first;
821    
822     first=1;
823     for(i=2; i<socket_info.allocated_sockets; i++) {
824 root 1.3 if (init_sockets[i].old_mode == Old_Listen) {
825     if (first) {
826     new_draw_info(NDI_UNIQUE,0,op,"Kill-logs are sent to:");
827     first=0;
828     }
829     new_draw_info_format(NDI_UNIQUE, 0, op, "%s: %s",
830     init_sockets[i].host,init_sockets[i].comment);
831     }
832 elmex 1.1 }
833     if (first) {
834 root 1.3 new_draw_info(NDI_UNIQUE,0,op,"Nobody is currently logging kills.");
835 elmex 1.1 }
836     return 1;
837     }
838    
839     int command_applymode(object *op, char *params)
840     {
841     unapplymode unapply = op->contr->unapply;
842     static const char* const types[]={"nochoice", "never", "always"};
843    
844     if (!params) {
845 root 1.3 new_draw_info_format(NDI_UNIQUE, 0, op, "applymode is set to %s",
846     types[op->contr->unapply]);
847     return 1;
848 elmex 1.1 }
849    
850     if (!strcmp(params,"nochoice"))
851 root 1.3 op->contr->unapply=unapply_nochoice;
852 elmex 1.1 else if (!strcmp(params,"never"))
853 root 1.3 op->contr->unapply=unapply_never;
854 elmex 1.1 else if (!strcmp(params,"always"))
855 root 1.3 op->contr->unapply=unapply_always;
856 elmex 1.1 else {
857 root 1.3 new_draw_info_format(NDI_UNIQUE, 0, op,
858     "applymode: Unknown options %s, valid options are nochoice, never, always",
859     params);
860     return 0;
861 elmex 1.1 }
862     new_draw_info_format(NDI_UNIQUE, 0, op, "Applymode %s set to %s",
863 root 1.3 (unapply==op->contr->unapply?"":" now"),
864     types[op->contr->unapply]);
865 elmex 1.1 return 1;
866     }
867    
868     int command_bowmode(object *op, char *params)
869     {
870     bowtype_t oldtype=op->contr->bowtype;
871     static const char* const types[] =
872 root 1.3 {"normal", "threewide", "spreadshot", "firenorth",
873     "firene", "fireeast", "firese", "firesouth",
874     "firesw", "firewest", "firenw", "bestarrow"};
875 elmex 1.1 char buf[MAX_BUF];
876     int i, found;
877    
878     if (!params) {
879 root 1.3 new_draw_info_format(NDI_UNIQUE, 0, op, "bowmode is set to %s",
880     types[op->contr->bowtype]);
881     return 1;
882 elmex 1.1 }
883    
884     for (i=0,found=0; i<=bow_bestarrow; i++) {
885 root 1.3 if (!strcmp(params, types[i])) {
886     found++;
887     op->contr->bowtype= (bowtype_t) i;
888     break;
889     }
890 elmex 1.1 }
891     if (!found) {
892 root 1.3 sprintf(buf, "bowmode: Unknown options %s, valid options are:", params);
893     for (i=0; i<=bow_bestarrow; i++) {
894     strcat(buf, " ");
895     strcat(buf, types[i]);
896     if (i < bow_nw)
897     strcat(buf, ",");
898     else
899     strcat(buf, ".");
900     }
901     new_draw_info_format(NDI_UNIQUE, 0, op, buf);
902     return 0;
903 elmex 1.1 }
904     new_draw_info_format(NDI_UNIQUE, 0, op, "bowmode %s set to %s",
905 root 1.3 (oldtype==op->contr->bowtype?"":"now"),
906     types[op->contr->bowtype]);
907 elmex 1.1 return 1;
908     }
909    
910     int command_petmode(object *op, char *params)
911     {
912     petmode_t oldtype=op->contr->petmode;
913     static const char* const types[]={"normal", "sad", "defend", "arena"};
914    
915     if (!params) {
916 root 1.3 new_draw_info_format(NDI_UNIQUE, 0, op, "petmode is set to %s",
917     types[op->contr->petmode]);
918     return 1;
919 elmex 1.1 }
920    
921     if (!strcmp(params,"normal"))
922 root 1.3 op->contr->petmode=pet_normal;
923 elmex 1.1 else if (!strcmp(params,"sad"))
924 root 1.3 op->contr->petmode=pet_sad;
925 elmex 1.1 else if (!strcmp(params,"defend"))
926 root 1.3 op->contr->petmode=pet_defend;
927 elmex 1.1 else if (!strcmp(params,"arena"))
928 root 1.3 op->contr->petmode=pet_arena;
929 elmex 1.1 else {
930 root 1.3 new_draw_info_format(NDI_UNIQUE, 0, op,
931     "petmode: Unknown options %s, valid options are normal,"
932     "sad (seek and destroy), defend, arena", params);
933     return 0;
934 elmex 1.1 }
935     new_draw_info_format(NDI_UNIQUE, 0, op, "petmode %s set to %s",
936 root 1.3 (oldtype==op->contr->petmode?"":"now"),
937     types[op->contr->petmode]);
938 elmex 1.1 return 1;
939     }
940    
941     int command_showpets(object *op, char *params)
942     {
943     objectlink *obl, *next;
944     int counter=0, target=0;
945     int have_shown_pet=0;
946     if (params !=NULL) target= atoi(params);
947     for (obl = first_friendly_object; obl != NULL; obl = next) {
948     object *ob = obl->ob;
949     next = obl->next;
950     if (get_owner(ob) == op) {
951 root 1.3 if (target ==0) {
952     if (counter==0)
953     new_draw_info(NDI_UNIQUE, 0, op, "Pets:");
954 root 1.5 new_draw_info_format(NDI_UNIQUE, 0, op, "%d %s - level %d", ++counter, &ob->name, ob->level );
955 root 1.3 }
956     else if (!have_shown_pet && ++counter==target) {
957 root 1.5 new_draw_info_format(NDI_UNIQUE, 0, op, "level %d %s", ob->level, &ob->name);
958 root 1.3 new_draw_info_format(NDI_UNIQUE, 0, op, "%d/%d HP, %d/%d SP",
959     ob->stats.hp, ob->stats.maxhp, ob->stats.sp, ob->stats.maxsp);
960     /* this is not a nice way to do this, it should be made to be more like the statistics command */
961     new_draw_info_format(NDI_UNIQUE, 0, op, "Str %d", ob->stats.Str);
962     new_draw_info_format(NDI_UNIQUE, 0, op, "Dex %d", ob->stats.Dex);
963     new_draw_info_format(NDI_UNIQUE, 0, op, "Con %d", ob->stats.Con);
964     new_draw_info_format(NDI_UNIQUE, 0, op, "Int %d", ob->stats.Int);
965     new_draw_info_format(NDI_UNIQUE, 0, op, "Wis %d", ob->stats.Wis);
966     new_draw_info_format(NDI_UNIQUE, 0, op, "Cha %d", ob->stats.Cha);
967     new_draw_info_format(NDI_UNIQUE, 0, op, "Pow %d", ob->stats.Pow);
968     new_draw_info_format(NDI_UNIQUE, 0, op, "wc %d damage %d ac %d ",
969     ob->stats.wc, ob->stats.dam, ob->stats.ac);
970     have_shown_pet=1;
971     }
972     }
973 elmex 1.1 }
974     if (counter == 0)
975     new_draw_info(NDI_UNIQUE, 0, op, "you have no pets.");
976     else if (target !=0 && have_shown_pet==0)
977     new_draw_info(NDI_UNIQUE, 0, op, "no such pet.");
978     return 0;
979     }
980    
981     int command_usekeys(object *op, char *params)
982     {
983     usekeytype oldtype=op->contr->usekeys;
984     static const char* const types[]={"inventory", "keyrings", "containers"};
985    
986     if (!params) {
987 root 1.3 new_draw_info_format(NDI_UNIQUE, 0, op, "usekeys is set to %s",
988     types[op->contr->usekeys]);
989     return 1;
990 elmex 1.1 }
991    
992     if (!strcmp(params,"inventory"))
993 root 1.3 op->contr->usekeys=key_inventory;
994 elmex 1.1 else if (!strcmp(params,"keyrings"))
995 root 1.3 op->contr->usekeys=keyrings;
996 elmex 1.1 else if (!strcmp(params,"containers"))
997 root 1.3 op->contr->usekeys=containers;
998 elmex 1.1 else {
999 root 1.3 new_draw_info_format(NDI_UNIQUE, 0, op,
1000     "usekeys: Unknown options %s, valid options are inventory, keyrings, containers",
1001     params);
1002     return 0;
1003 elmex 1.1 }
1004     new_draw_info_format(NDI_UNIQUE, 0, op, "usekeys %s set to %s",
1005 root 1.3 (oldtype==op->contr->usekeys?"":"now"),
1006     types[op->contr->usekeys]);
1007 elmex 1.1 return 1;
1008     }
1009    
1010     int command_resistances(object *op, char *params)
1011     {
1012     int i;
1013     if (!op)
1014 root 1.3 return 0;
1015 elmex 1.1
1016     for (i=0; i<NROFATTACKS; i++) {
1017 root 1.3 if (i==ATNR_INTERNAL) continue;
1018 elmex 1.1
1019 root 1.3 new_draw_info_format(NDI_UNIQUE, 0, op, "%-20s %+5d",
1020     attacktype_desc[i], op->resist[i]);
1021 elmex 1.1 }
1022    
1023     /* If dragon player, let's display natural resistances */
1024     if ( is_dragon_pl( op ) )
1025     {
1026     int attack;
1027     object* tmp;
1028     for ( tmp = op->inv; tmp != NULL; tmp = tmp->below )
1029     {
1030     if ( ( tmp->type == FORCE ) && ( strcmp( tmp->arch->name, "dragon_skin_force" )== 0 ) )
1031     {
1032     new_draw_info( NDI_UNIQUE, 0, op, "\nNatural skin resistances:" );
1033     for ( attack = 0; attack < NROFATTACKS; attack++ )
1034     {
1035     if ( atnr_is_dragon_enabled( attack ) )
1036     {
1037     new_draw_info_format( NDI_UNIQUE, 0, op, "%s: %d", change_resist_msg[ attack ], tmp->resist[ attack ] );
1038     }
1039     }
1040     break;
1041     }
1042     }
1043     }
1044    
1045     return 0;
1046     }
1047     /*
1048     * Actual commands.
1049     * Those should be in small separate files (c_object.c, c_wiz.c, cmove.c,...)
1050     */
1051    
1052    
1053     static void help_topics(object *op, int what)
1054     {
1055     DIR *dirp;
1056     struct dirent *de;
1057     char filename[MAX_BUF], line[80];
1058     int namelen, linelen=0;
1059    
1060     switch (what) {
1061 root 1.3 case 1:
1062     sprintf(filename, "%s/wizhelp", settings.datadir);
1063     new_draw_info(NDI_UNIQUE, 0,op, " Wiz commands:");
1064     break;
1065     case 3:
1066     sprintf(filename, "%s/mischelp", settings.datadir);
1067     new_draw_info(NDI_UNIQUE, 0,op, " Misc help:");
1068     break;
1069     default:
1070     sprintf(filename, "%s/help", settings.datadir);
1071     new_draw_info(NDI_UNIQUE, 0,op, " Commands:");
1072     break;
1073 elmex 1.1 }
1074     if (!(dirp=opendir(filename)))
1075 root 1.3 return;
1076 elmex 1.1
1077     line[0] ='\0';
1078     for (de = readdir(dirp); de; de = readdir(dirp)) {
1079 root 1.3 namelen = NAMLEN(de);
1080     if (namelen <= 2 && *de->d_name == '.' &&
1081     (namelen == 1 || de->d_name[1] == '.' ) )
1082     continue;
1083     linelen +=namelen+1;
1084     if (linelen > 42) {
1085     new_draw_info(NDI_UNIQUE, 0,op, line);
1086     sprintf(line, " %s", de->d_name);
1087     linelen =namelen+1;
1088     continue;
1089     }
1090     strcat(line, " ");
1091     strcat(line, de->d_name);
1092 elmex 1.1 }
1093     new_draw_info(NDI_UNIQUE, 0,op, line);
1094     closedir(dirp);
1095     }
1096    
1097     static void show_commands(object *op, int what)
1098     {
1099     char line[80];
1100     int i, size, namelen, linelen=0;
1101     CommArray_s *ap;
1102     extern CommArray_s Commands[], WizCommands[];
1103     extern const int CommandsSize, WizCommandsSize;
1104    
1105     switch (what) {
1106     case 1:
1107     ap =WizCommands;
1108     size =WizCommandsSize;
1109     new_draw_info(NDI_UNIQUE, 0,op, " Wiz commands:");
1110     break;
1111     case 2:
1112     ap= CommunicationCommands;
1113     size= CommunicationCommandSize;
1114     new_draw_info(NDI_UNIQUE, 0, op, " Communication commands:");
1115     break;
1116     default:
1117     ap =Commands;
1118     size =CommandsSize;
1119     new_draw_info(NDI_UNIQUE, 0,op, " Commands:");
1120     break;
1121     }
1122    
1123     line[0] ='\0';
1124     for (i=0; i<size; i++) {
1125     namelen = strlen(ap[i].name);
1126     linelen +=namelen+1;
1127     if (linelen > 42) {
1128     new_draw_info(NDI_UNIQUE, 0,op, line);
1129     sprintf(line, " %s", ap[i].name);
1130     linelen =namelen+1;
1131     continue;
1132     }
1133     strcat(line, " ");
1134     strcat(line, ap[i].name);
1135     }
1136     new_draw_info(NDI_UNIQUE, 0,op, line);
1137     }
1138    
1139    
1140     int command_help (object *op, char *params)
1141     {
1142     struct stat st;
1143     FILE *fp;
1144     char filename[MAX_BUF], line[MAX_BUF];
1145     int len;
1146    
1147     if(op != NULL)
1148     clear_win_info(op);
1149    
1150     /*
1151     * Main help page?
1152     */
1153     if (!params) {
1154     sprintf(filename, "%s/def_help", settings.datadir);
1155     if ((fp=fopen(filename, "r")) == NULL) {
1156 root 1.4 LOG(llevError, "Cannot open help file %s: %s\n", filename, strerror(errno));
1157 elmex 1.1 return 0;
1158     }
1159     while (fgets(line, MAX_BUF, fp)) {
1160     line[MAX_BUF-1] ='\0';
1161     len =strlen(line)-1;
1162     if (line[len] == '\n')
1163 root 1.3 line[len] ='\0';
1164 elmex 1.1 new_draw_info(NDI_UNIQUE, 0,op, line);
1165     }
1166     fclose(fp);
1167     return 0;
1168     }
1169    
1170     /*
1171     * Topics list
1172     */
1173     if (!strcmp(params, "topics")) {
1174     help_topics(op, 3);
1175     help_topics(op, 0);
1176     if (QUERY_FLAG(op, FLAG_WIZ))
1177     help_topics(op, 1);
1178     return 0;
1179     }
1180    
1181     /*
1182     * Commands list
1183     */
1184     if (!strcmp(params, "commands")) {
1185     show_commands(op, 0);
1186     show_commands(op, 2); /* show comm commands */
1187     if (QUERY_FLAG(op, FLAG_WIZ))
1188     show_commands(op, 1);
1189     return 0;
1190     }
1191    
1192     /*
1193     * User wants info about command
1194     */
1195     if (strchr(params, '.') || strchr(params, ' ') || strchr(params, '/')) {
1196     sprintf(line, "Illegal characters in '%s'", params);
1197     new_draw_info(NDI_UNIQUE, 0,op, line);
1198     return 0;
1199     }
1200    
1201     sprintf(filename, "%s/mischelp/%s", settings.datadir, params);
1202     if (stat(filename, &st) || !S_ISREG(st.st_mode)) {
1203     if (op) {
1204     sprintf(filename, "%s/help/%s", settings.datadir, params);
1205     if (stat(filename, &st) || !S_ISREG(st.st_mode)) {
1206 root 1.3 if (QUERY_FLAG(op, FLAG_WIZ)) {
1207     sprintf(filename, "%s/wizhelp/%s", settings.datadir, params);
1208     if (stat(filename, &st) || !S_ISREG(st.st_mode))
1209     goto nohelp;
1210     } else
1211     goto nohelp;
1212 elmex 1.1 }
1213     }
1214     }
1215    
1216     /*
1217     * Found that. Just cat it to screen.
1218     */
1219     if ((fp=fopen(filename, "r")) == NULL) {
1220 root 1.4 LOG(llevError, "Cannot open help file %s: %s\n", filename, strerror(errno));
1221 elmex 1.1 return 0;
1222     }
1223     sprintf(line, "Help about '%s'", params);
1224     new_draw_info(NDI_UNIQUE, 0,op, line);
1225     while (fgets(line, MAX_BUF, fp)) {
1226     line[MAX_BUF-1] ='\0';
1227     len =strlen(line)-1;
1228     if (line[len] == '\n')
1229     line[len] ='\0';
1230     new_draw_info(NDI_UNIQUE, 0,op, line);
1231     }
1232     fclose(fp);
1233     return 0;
1234    
1235     /*
1236     * No_help -escape
1237     */
1238     nohelp:
1239     sprintf(line, "No help available on '%s'", params);
1240     new_draw_info(NDI_UNIQUE, 0,op, line);
1241     return 0;
1242     }
1243    
1244    
1245     int onoff_value(const char *line)
1246     {
1247     int i;
1248    
1249     if (sscanf(line, "%d", &i))
1250     return (i != 0);
1251     switch (line[0]) {
1252     case 'o':
1253     switch (line[1]) {
1254     case 'n': return 1; /* on */
1255     default: return 0; /* o[ff] */
1256     }
1257     case 'y': /* y[es] */
1258     case 'k': /* k[ylla] */
1259     case 's':
1260     case 'd':
1261     return 1;
1262     case 'n': /* n[o] */
1263     case 'e': /* e[i] */
1264     case 'u':
1265     default:
1266     return 0;
1267     }
1268     }
1269    
1270     int command_quit (object *op, char *params)
1271     {
1272     new_draw_info(NDI_UNIQUE, 0, op, "Quitting will delete your character PERMANENTLY. If you are sure you want to do this, then use the quit_character command instead of quit.");
1273     return 1;
1274     }
1275    
1276     int command_real_quit (object *op, char *params)
1277     {
1278     send_query(&op->contr->socket,CS_QUERY_SINGLECHAR,
1279 root 1.3 "Quitting will delete your character.\nAre you sure you want to quit (y/n):");
1280 elmex 1.1
1281     op->contr->state = ST_CONFIRM_QUIT;
1282     return 1;
1283     }
1284    
1285     /*
1286     * don't allow people to exit explore mode. It otherwise becomes
1287     * really easy to abuse this.
1288     */
1289     int command_explore (object *op, char *params)
1290     {
1291     if (settings.explore_mode == FALSE)
1292 root 1.3 return 1;
1293 elmex 1.1 /*
1294     * I guess this is the best way to see if we are solo or not. Actually,
1295     * are there any cases when first_player->next==NULL and we are not solo?
1296     */
1297     if ((first_player!=op->contr) || (first_player->next!=NULL)) {
1298 root 1.3 new_draw_info(NDI_UNIQUE, 0,op,"You can not enter explore mode if you are in a party");
1299 elmex 1.1 } else if (op->contr->explore)
1300 root 1.3 new_draw_info(NDI_UNIQUE, 0,op, "There is no return from explore mode");
1301 elmex 1.1 else {
1302 root 1.3 op->contr->explore=1;
1303     new_draw_info(NDI_UNIQUE, 0,op, "You are now in explore mode");
1304 elmex 1.1 }
1305     return 1;
1306     }
1307    
1308     int command_sound (object *op, char *params)
1309     {
1310     if (op->contr->socket.sound) {
1311     op->contr->socket.sound=0;
1312     new_draw_info(NDI_UNIQUE, 0,op, "Silence is golden...");
1313     }
1314     else {
1315     op->contr->socket.sound=1;
1316     new_draw_info(NDI_UNIQUE, 0,op, "The sounds are enabled.");
1317     }
1318     return 1;
1319     }
1320    
1321     /* Perhaps these should be in player.c, but that file is
1322     * already a bit big.
1323     */
1324    
1325     void receive_player_name(object *op,char k) {
1326    
1327     if(!check_name(op->contr,op->contr->write_buf+1)) {
1328 root 1.3 get_name(op);
1329     return;
1330 elmex 1.1 }
1331 root 1.5 op->name = op->contr->write_buf + 1;
1332     op->name_pl = op->contr->write_buf + 1;
1333 elmex 1.1 new_draw_info(NDI_UNIQUE, 0,op,op->contr->write_buf);
1334     op->contr->name_changed=1;
1335     get_password(op);
1336     }
1337    
1338     void receive_player_password(object *op,char k) {
1339    
1340     unsigned int pwd_len=strlen(op->contr->write_buf);
1341     if(pwd_len<=1||pwd_len>17) {
1342     get_name(op);
1343     return;
1344     }
1345     new_draw_info(NDI_UNIQUE, 0,op," "); /* To hide the password better */
1346    
1347     if (checkbanned(op->name, op->contr->socket.host)) {
1348 root 1.5 LOG(llevInfo, "Banned player tried to add: [%s@%s]\n", &op->name, op->contr->socket.host);
1349 elmex 1.1 new_draw_info(NDI_UNIQUE|NDI_RED, 0, op, "You are not allowed to play.");
1350     get_name(op);
1351     return;
1352     }
1353    
1354     if(op->contr->state==ST_CONFIRM_PASSWORD) {
1355     if(!check_password(op->contr->write_buf+1,op->contr->password)) {
1356     new_draw_info(NDI_UNIQUE, 0,op,"The passwords did not match.");
1357     get_name(op);
1358     return;
1359     }
1360     clear_win_info(op);
1361     display_motd(op);
1362     new_draw_info(NDI_UNIQUE, 0,op," ");
1363     new_draw_info(NDI_UNIQUE, 0,op,"Welcome, Brave New Warrior!");
1364     new_draw_info(NDI_UNIQUE, 0,op," ");
1365     Roll_Again(op);
1366     op->contr->state=ST_ROLL_STAT;
1367     return;
1368     }
1369     strcpy(op->contr->password,crypt_string(op->contr->write_buf+1,NULL));
1370     op->contr->state=ST_ROLL_STAT;
1371     check_login(op);
1372     return;
1373     }
1374    
1375    
1376     int explore_mode(void) {
1377     player *pl;
1378    
1379     if (settings.explore_mode == TRUE) {
1380 root 1.3 for (pl = first_player; pl != (player *) NULL; pl = pl->next)
1381     if (pl->explore)
1382     return 1;
1383 elmex 1.1 }
1384     return 0;
1385     }
1386    
1387    
1388     int command_title (object *op, char *params)
1389     {
1390     char buf[MAX_BUF];
1391    
1392     if (settings.set_title == FALSE) {
1393 root 1.3 new_draw_info(NDI_UNIQUE, 0, op, "You cannot change your title.");
1394     return 1;
1395 elmex 1.1 }
1396    
1397     /* dragon players cannot change titles */
1398     if (is_dragon_pl(op)) {
1399     new_draw_info(NDI_UNIQUE, 0, op, "Dragons cannot change titles.");
1400     return 1;
1401     }
1402    
1403     if(params == NULL) {
1404 root 1.3 if(op->contr->own_title[0]=='\0')
1405     sprintf(buf,"Your title is '%s'.", op->contr->title);
1406     else
1407     sprintf(buf,"Your title is '%s'.", op->contr->own_title);
1408     new_draw_info(NDI_UNIQUE, 0,op,buf);
1409     return 1;
1410 elmex 1.1 }
1411     if(strcmp(params, "clear")==0 || strcmp(params, "default")==0) {
1412 root 1.3 if(op->contr->own_title[0]=='\0')
1413     new_draw_info(NDI_UNIQUE, 0,op,"Your title is the default title.");
1414     else
1415     new_draw_info(NDI_UNIQUE, 0,op,"Title set to default.");
1416     op->contr->own_title[0]='\0';
1417     return 1;
1418 elmex 1.1 }
1419    
1420     if((int)strlen(params) >= MAX_NAME) {
1421 root 1.3 new_draw_info(NDI_UNIQUE, 0,op,"Title too long.");
1422     return 1;
1423 elmex 1.1 }
1424     strcpy(op->contr->own_title, params);
1425     return 1;
1426     }
1427    
1428     int command_save (object *op, char *params)
1429     {
1430     // if (get_map_flags(op->map, NULL, op->x, op->y, NULL, NULL) & P_NO_CLERIC) {
1431     // new_draw_info(NDI_UNIQUE, 0, op, "You can not save on unholy ground");
1432     // } else
1433     if (!op->stats.exp) {
1434 root 1.3 new_draw_info(NDI_UNIQUE, 0, op, "You don't deserve to save yet.");
1435 elmex 1.1 } else {
1436 root 1.3 if(save_player(op,1))
1437     new_draw_info(NDI_UNIQUE, 0,op,"You have been saved.");
1438     else
1439     new_draw_info(NDI_UNIQUE, 0,op,"SAVE FAILED!");
1440 elmex 1.1 }
1441     return 1;
1442     }
1443    
1444    
1445     int command_peaceful (object *op, char *params)
1446     {
1447     new_draw_info(NDI_UNIQUE, 0, op,
1448     "You cannot change your peaceful setting with this command."
1449     " Please speak to the priest in the temple of Gorokh"
1450     " if you want to become hostile or in temple of Valriel"
1451     " if you want to become peaceful again."
1452     );
1453    
1454     /*
1455     if((op->contr->peaceful=!op->contr->peaceful))
1456     new_draw_info(NDI_UNIQUE, 0,op,"You will not attack other players.");
1457     else
1458     new_draw_info(NDI_UNIQUE, 0,op,"You will attack other players.");
1459     */
1460     return 1;
1461     }
1462    
1463    
1464    
1465     int command_wimpy (object *op, char *params)
1466     {
1467     int i;
1468     char buf[MAX_BUF];
1469    
1470     if (params==NULL || !sscanf(params, "%d", &i)) {
1471 root 1.3 sprintf(buf, "Your current wimpy level is %d.", op->run_away);
1472     new_draw_info(NDI_UNIQUE, 0,op, buf);
1473     return 1;
1474 elmex 1.1 }
1475     sprintf(buf, "Your new wimpy level is %d.", i);
1476     new_draw_info(NDI_UNIQUE, 0,op, buf);
1477     op->run_away = i;
1478     return 1;
1479     }
1480    
1481    
1482     int command_brace (object *op, char *params)
1483     {
1484     if (!params)
1485     op->contr->braced =!op->contr->braced;
1486     else
1487     op->contr->braced =onoff_value(params);
1488    
1489     if(op->contr->braced)
1490     new_draw_info(NDI_UNIQUE, 0,op, "You are braced.");
1491     else
1492     new_draw_info(NDI_UNIQUE, 0,op, "Not braced.");
1493    
1494     fix_player(op);
1495     return 0;
1496     }
1497    
1498     int command_style_map_info(object *op, char *params)
1499     {
1500     extern mapstruct *styles;
1501     mapstruct *mp;
1502     int maps_used=0, mapmem=0, objects_used=0, x,y;
1503     object *tmp;
1504    
1505     for (mp = styles; mp!=NULL; mp=mp->next) {
1506 root 1.3 maps_used++;
1507     mapmem += MAP_WIDTH(mp)*MAP_HEIGHT(mp)*(sizeof(object *)+sizeof(MapSpace)) + sizeof(mapstruct);
1508     for (x=0; x<MAP_WIDTH(mp); x++) {
1509     for (y=0; y<MAP_HEIGHT(mp); y++) {
1510     for (tmp=get_map_ob(mp, x, y); tmp!=NULL; tmp=tmp->above)
1511     objects_used++;
1512     }
1513     }
1514 elmex 1.1 }
1515     new_draw_info_format(NDI_UNIQUE, 0, op, "Style maps loaded: %d", maps_used);
1516     new_draw_info(NDI_UNIQUE, 0, op, "Memory used, not");
1517     new_draw_info_format(NDI_UNIQUE, 0, op, "including objects: %d", mapmem);
1518     new_draw_info_format(NDI_UNIQUE, 0, op, "Style objects: %d", objects_used);
1519     new_draw_info_format(NDI_UNIQUE, 0, op, "Mem for objects: %d", objects_used * sizeof(object));
1520     return 0;
1521     }
1522    
1523     int command_kill_pets(object *op, char *params)
1524     {
1525     objectlink *obl, *next;
1526     int counter=0, removecount=0;
1527     if (params == NULL) {
1528     terminate_all_pets(op);
1529 root 1.3 new_draw_info(NDI_UNIQUE, 0, op, "Your pets have been killed.");
1530 elmex 1.1 }
1531     else {
1532 root 1.3 int target = atoi(params);
1533     for(obl = first_friendly_object; obl != NULL; obl = next) {
1534     object *ob = obl->ob;
1535     next = obl->next;
1536     if (get_owner(ob) == op)
1537     if (++counter==target || (target==0 && !strcasecmp(ob->name, params))) {
1538     if (!QUERY_FLAG(ob, FLAG_REMOVED))
1539     remove_ob(ob);
1540     remove_friendly_object(ob);
1541     free_object(ob);
1542     removecount++;
1543 elmex 1.1 }
1544 root 1.3 }
1545     if (removecount!=0)
1546     new_draw_info_format(NDI_UNIQUE, 0, op, "killed %d pets.\n", removecount);
1547     else
1548     new_draw_info(NDI_UNIQUE, 0, op, "Couldn't find any suitable pets to kill.\n");
1549 elmex 1.1 }
1550     return 0;
1551     }
1552