]> git.jsancho.org Git - lugaru.git/blob - Source/Devtools/ConsoleCmds.cpp
Creating map saving folder if needed
[lugaru.git] / Source / Devtools / ConsoleCmds.cpp
1 /*
2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2016 - Lugaru contributors (see AUTHORS file)
4
5 This file is part of Lugaru.
6
7 Lugaru is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 Lugaru is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Lugaru.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "Devtools/ConsoleCmds.hpp"
22
23 #include "Game.hpp"
24 #include "Level/Dialog.hpp"
25 #include "Level/Hotspot.hpp"
26 #include "Utils/Folders.hpp"
27 #include "Tutorial.hpp"
28
29 const char *cmd_names[cmd_count] = {
30 #define DECLARE_COMMAND(cmd) #cmd,
31 #include "ConsoleCmds.def"
32 #undef  DECLARE_COMMAND
33 };
34
35 console_handler cmd_handlers[cmd_count] = {
36 #define DECLARE_COMMAND(cmd) ch_##cmd,
37 #include "ConsoleCmds.def"
38 #undef  DECLARE_COMMAND
39 };
40
41 using namespace Game;
42
43 /* globals */
44
45 extern bool campaign;
46 extern bool cellophane;
47 extern int editoractive;
48 extern int editorpathtype;
49 extern int environment;
50 extern float fadestart;
51 extern float slomospeed;
52 extern float slomofreq;
53 extern int hostile;
54 extern int maptype;
55 extern int slomo;
56 extern float slomodelay;
57 extern bool skyboxtexture;
58 extern float skyboxr;
59 extern float skyboxg;
60 extern float skyboxb;
61 extern float skyboxlightr;
62 extern float skyboxlightg;
63 extern float skyboxlightb;
64 extern Terrain terrain;
65 extern float viewdistance;
66
67 /* defined in GameTick.cpp */
68
69 extern int whichlevel;
70
71 float tintr = 1, tintg = 1, tintb = 1;
72
73 /* Helpers used in console commands */
74
75 /* Return true if PFX is a prefix of STR (case-insensitive).  */
76 static bool stripfx(const char *str, const char *pfx)
77 {
78     return !strncasecmp(str, pfx, strlen(pfx));
79 }
80
81 static void set_proportion(int pnum, const char *args)
82 {
83     float headprop, bodyprop, armprop, legprop;
84
85     sscanf(args, "%f%f%f%f", &headprop, &bodyprop, &armprop, &legprop);
86
87     if (Person::players[pnum]->creature == wolftype) {
88         Person::players[pnum]->proportionhead = 1.1 * headprop;
89         Person::players[pnum]->proportionbody = 1.1 * bodyprop;
90         Person::players[pnum]->proportionarms = 1.1 * armprop;
91         Person::players[pnum]->proportionlegs = 1.1 * legprop;
92     } else if (Person::players[pnum]->creature == rabbittype) {
93         Person::players[pnum]->proportionhead = 1.2 * headprop;
94         Person::players[pnum]->proportionbody = 1.05 * bodyprop;
95         Person::players[pnum]->proportionarms = 1.00 * armprop;
96         Person::players[pnum]->proportionlegs = 1.1 * legprop;
97         Person::players[pnum]->proportionlegs.y = 1.05 * legprop;
98     }
99 }
100
101 static void set_protection(int pnum, const char *args)
102 {
103     float head, high, low;
104     sscanf(args, "%f%f%f", &head, &high, &low);
105
106     Person::players[pnum]->protectionhead = head;
107     Person::players[pnum]->protectionhigh = high;
108     Person::players[pnum]->protectionlow  = low;
109 }
110
111 static void set_armor(int pnum, const char *args)
112 {
113     float head, high, low;
114     sscanf(args, "%f%f%f", &head, &high, &low);
115
116     Person::players[pnum]->armorhead = head;
117     Person::players[pnum]->armorhigh = high;
118     Person::players[pnum]->armorlow  = low;
119 }
120
121 static void set_metal(int pnum, const char *args)
122 {
123     float head, high, low;
124     sscanf(args, "%f%f%f", &head, &high, &low);
125
126     Person::players[pnum]->metalhead = head;
127     Person::players[pnum]->metalhigh = high;
128     Person::players[pnum]->metallow  = low;
129 }
130
131 static void set_noclothes(int pnum, const char*)
132 {
133     Person::players[pnum]->numclothes = 0;
134     Person::players[pnum]->skeleton.drawmodel.textureptr.load(
135         creatureskin[Person::players[pnum]->creature][Person::players[pnum]->whichskin], 1,
136         &Person::players[pnum]->skeleton.skinText[0], &Person::players[pnum]->skeleton.skinsize);
137 }
138
139 static void set_clothes(int pnum, const char *args)
140 {
141     char buf[64];
142     snprintf(buf, 63, "Textures/%s.png", args);
143
144     int id = Person::players[pnum]->numclothes;
145     strncpy(Person::players[pnum]->clothes[id], buf, 64);
146     Person::players[pnum]->clothestintr[id] = tintr;
147     Person::players[pnum]->clothestintg[id] = tintg;
148     Person::players[pnum]->clothestintb[id] = tintb;
149     Person::players[pnum]->numclothes++;
150
151     if (!Person::players[pnum]->addClothes(id))
152         return;
153
154     Person::players[pnum]->DoMipmaps();
155 }
156
157 /* Console commands themselves */
158
159 void ch_quit(const char *)
160 {
161     tryquit = 1;
162 }
163
164 void ch_map(const char *args)
165 {
166     if (!LoadLevel(args)) {
167         // FIXME: Reduce code duplication with GameTick (should come from a Console class)
168         for (int k = 14; k >= 1; k--) {
169             consoletext[k] = consoletext[k - 1];
170         }
171         consoletext[0] = std::string("Could not load the requested level '") + args + "', aborting.";
172         consoleselected = 0;
173     }
174     whichlevel = -2;
175     campaign = 0;
176 }
177
178 void ch_save(const char *args)
179 {
180     std::string map_path = Folders::getUserDataPath() + "/Maps";
181     Folders::makeDirectory(map_path);
182     map_path = map_path + "/" + args;
183
184     int mapvers = 12;
185
186     FILE *tfile;
187     tfile = fopen( map_path.c_str(), "wb" );
188     if (tfile == NULL) {
189         perror((std::string("Couldn't open file ") + map_path + " for saving").c_str());
190         return;
191     }
192     fpackf(tfile, "Bi", mapvers);
193     fpackf(tfile, "Bi", maptype);
194     fpackf(tfile, "Bi", hostile);
195     fpackf(tfile, "Bf Bf", viewdistance, fadestart);
196     fpackf(tfile, "Bb Bf Bf Bf", skyboxtexture, skyboxr, skyboxg, skyboxb);
197     fpackf(tfile, "Bf Bf Bf", skyboxlightr, skyboxlightg, skyboxlightb);
198     fpackf(tfile, "Bf Bf Bf Bf Bf Bi", Person::players[0]->coords.x, Person::players[0]->coords.y, Person::players[0]->coords.z,
199            Person::players[0]->yaw, Person::players[0]->targetyaw, Person::players[0]->num_weapons);
200     if (Person::players[0]->num_weapons > 0 && Person::players[0]->num_weapons < 5)
201         for (int j = 0; j < Person::players[0]->num_weapons; j++)
202             fpackf(tfile, "Bi", weapons[Person::players[0]->weaponids[j]].getType());
203
204     fpackf(tfile, "Bf Bf Bf", Person::players[0]->armorhead, Person::players[0]->armorhigh, Person::players[0]->armorlow);
205     fpackf(tfile, "Bf Bf Bf", Person::players[0]->protectionhead, Person::players[0]->protectionhigh, Person::players[0]->protectionlow);
206     fpackf(tfile, "Bf Bf Bf", Person::players[0]->metalhead, Person::players[0]->metalhigh, Person::players[0]->metallow);
207     fpackf(tfile, "Bf Bf", Person::players[0]->power, Person::players[0]->speedmult);
208
209     fpackf(tfile, "Bi", Person::players[0]->numclothes);
210
211     fpackf(tfile, "Bi Bi", Person::players[0]->whichskin, Person::players[0]->creature);
212
213     Dialog::saveDialogs(tfile);
214
215     for (int k = 0; k < Person::players[0]->numclothes; k++) {
216         int templength = strlen(Person::players[0]->clothes[k]);
217         fpackf(tfile, "Bi", templength);
218         for (int l = 0; l < templength; l++)
219             fpackf(tfile, "Bb", Person::players[0]->clothes[k][l]);
220         fpackf(tfile, "Bf Bf Bf", Person::players[0]->clothestintr[k], Person::players[0]->clothestintg[k], Person::players[0]->clothestintb[k]);
221     }
222
223     fpackf(tfile, "Bi", environment);
224
225     fpackf(tfile, "Bi", Object::objects.size());
226
227     for (unsigned int k = 0; k < Object::objects.size(); k++) {
228         fpackf(tfile, "Bi Bf Bf Bf Bf Bf Bf", Object::objects[k]->type, Object::objects[k]->yaw, Object::objects[k]->pitch,
229                Object::objects[k]->position.x, Object::objects[k]->position.y, Object::objects[k]->position.z, Object::objects[k]->scale);
230     }
231
232     fpackf(tfile, "Bi", Hotspot::hotspots.size());
233     for (unsigned i = 0; i < Hotspot::hotspots.size(); i++) {
234         fpackf(tfile, "Bi Bf Bf Bf Bf", Hotspot::hotspots[i].type, Hotspot::hotspots[i].size, Hotspot::hotspots[i].position.x, Hotspot::hotspots[i].position.y, Hotspot::hotspots[i].position.z);
235         int templength = strlen(Hotspot::hotspots[i].text);
236         fpackf(tfile, "Bi", templength);
237         for (int l = 0; l < templength; l++)
238             fpackf(tfile, "Bb", Hotspot::hotspots[i].text[l]);
239     }
240
241     fpackf(tfile, "Bi", Person::players.size());
242     if (Person::players.size() > maxplayers) {
243         cout << "Warning: this level contains more players than allowed" << endl;
244     }
245     for (unsigned j = 1; j < Person::players.size(); j++) {
246         fpackf(tfile, "Bi Bi Bf Bf Bf Bi Bi Bf Bb Bf", Person::players[j]->whichskin, Person::players[j]->creature,
247                Person::players[j]->coords.x, Person::players[j]->coords.y, Person::players[j]->coords.z,
248                Person::players[j]->num_weapons, Person::players[j]->howactive, Person::players[j]->scale, Person::players[j]->immobile, Person::players[j]->yaw);
249         if (Person::players[j]->num_weapons < 5)
250             for (int k = 0; k < Person::players[j]->num_weapons; k++)
251                 fpackf(tfile, "Bi", weapons[Person::players[j]->weaponids[k]].getType());
252         if (Person::players[j]->numwaypoints < 30) {
253             fpackf(tfile, "Bi", Person::players[j]->numwaypoints);
254             for (int k = 0; k < Person::players[j]->numwaypoints; k++) {
255                 fpackf(tfile, "Bf", Person::players[j]->waypoints[k].x);
256                 fpackf(tfile, "Bf", Person::players[j]->waypoints[k].y);
257                 fpackf(tfile, "Bf", Person::players[j]->waypoints[k].z);
258                 fpackf(tfile, "Bi", Person::players[j]->waypointtype[k]);
259             }
260             fpackf(tfile, "Bi", Person::players[j]->waypoint);
261         } else {
262             Person::players[j]->numwaypoints = 0;
263             Person::players[j]->waypoint = 0;
264             fpackf(tfile, "Bi Bi Bi", Person::players[j]->numwaypoints, Person::players[j]->waypoint, Person::players[j]->waypoint);
265         }
266
267         fpackf(tfile, "Bf Bf Bf", Person::players[j]->armorhead, Person::players[j]->armorhigh, Person::players[j]->armorlow);
268         fpackf(tfile, "Bf Bf Bf", Person::players[j]->protectionhead, Person::players[j]->protectionhigh, Person::players[j]->protectionlow);
269         fpackf(tfile, "Bf Bf Bf", Person::players[j]->metalhead, Person::players[j]->metalhigh, Person::players[j]->metallow);
270         fpackf(tfile, "Bf Bf", Person::players[j]->power, Person::players[j]->speedmult);
271
272         float headprop, bodyprop, armprop, legprop;
273         if (Person::players[j]->creature == wolftype) {
274             headprop = Person::players[j]->proportionhead.x / 1.1;
275             bodyprop = Person::players[j]->proportionbody.x / 1.1;
276             armprop = Person::players[j]->proportionarms.x / 1.1;
277             legprop = Person::players[j]->proportionlegs.x / 1.1;
278         } else {
279             // rabbittype
280             headprop = Person::players[j]->proportionhead.x / 1.2;
281             bodyprop = Person::players[j]->proportionbody.x / 1.05;
282             armprop = Person::players[j]->proportionarms.x / 1.00;
283             legprop = Person::players[j]->proportionlegs.x / 1.1;
284         }
285
286         fpackf(tfile, "Bf Bf Bf Bf", headprop, bodyprop, armprop, legprop);
287
288         fpackf(tfile, "Bi", Person::players[j]->numclothes);
289         if (Person::players[j]->numclothes)
290             for (int k = 0; k < Person::players[j]->numclothes; k++) {
291                 int templength;
292                 templength = strlen(Person::players[j]->clothes[k]);
293                 fpackf(tfile, "Bi", templength);
294                 for (int l = 0; l < templength; l++)
295                     fpackf(tfile, "Bb", Person::players[j]->clothes[k][l]);
296                 fpackf(tfile, "Bf Bf Bf", Person::players[j]->clothestintr[k], Person::players[j]->clothestintg[k], Person::players[j]->clothestintb[k]);
297             }
298     }
299
300     fpackf(tfile, "Bi", numpathpoints);
301     for (int j = 0; j < numpathpoints; j++) {
302         fpackf(tfile, "Bf Bf Bf Bi", pathpoint[j].x, pathpoint[j].y, pathpoint[j].z, numpathpointconnect[j]);
303         for (int k = 0; k < numpathpointconnect[j]; k++)
304             fpackf(tfile, "Bi", pathpointconnect[j][k]);
305     }
306
307     fpackf(tfile, "Bf Bf Bf Bf", mapcenter.x, mapcenter.y, mapcenter.z, mapradius);
308
309     fclose(tfile);
310 }
311
312 void ch_cellar(const char *)
313 {
314     Person::players[0]->skeleton.drawmodel.textureptr.load("Textures/Furdarko.jpg", 1, &Person::players[0]->skeleton.skinText[0], &Person::players[0]->skeleton.skinsize);
315 }
316
317 void ch_tint(const char *args)
318 {
319     sscanf(args, "%f%f%f", &tintr, &tintg, &tintb);
320 }
321
322 void ch_tintr(const char *args)
323 {
324     tintr = atof(args);
325 }
326
327 void ch_tintg(const char *args)
328 {
329     tintg = atof(args);
330 }
331
332 void ch_tintb(const char *args)
333 {
334     tintb = atof(args);
335 }
336
337 void ch_speed(const char *args)
338 {
339     Person::players[0]->speedmult = atof(args);
340 }
341
342 void ch_strength(const char *args)
343 {
344     Person::players[0]->power = atof(args);
345 }
346
347 void ch_power(const char *args)
348 {
349     Person::players[0]->power = atof(args);
350 }
351
352 void ch_size(const char *args)
353 {
354     Person::players[0]->scale = atof(args) * .2;
355 }
356
357 void ch_sizenear(const char *args)
358 {
359     int closest = findClosestPlayer();
360     if (closest >= 0)
361         Person::players[closest]->scale = atof(args) * .2;
362 }
363
364 void ch_proportion(const char *args)
365 {
366     set_proportion(0, args);
367 }
368
369 void ch_proportionnear(const char *args)
370 {
371     int closest = findClosestPlayer();
372     if (closest >= 0)
373         set_proportion(closest, args);
374 }
375
376 void ch_protection(const char *args)
377 {
378     set_protection(0, args);
379 }
380
381 void ch_protectionnear(const char *args)
382 {
383     int closest = findClosestPlayer();
384     if (closest >= 0)
385         set_protection(closest, args);
386 }
387
388 void ch_armor(const char *args)
389 {
390     set_armor(0, args);
391 }
392
393 void ch_armornear(const char *args)
394 {
395     int closest = findClosestPlayer();
396     if (closest >= 0)
397         set_armor(closest, args);
398 }
399
400 void ch_protectionreset(const char *)
401 {
402     set_protection(0, "1 1 1");
403     set_armor(0, "1 1 1");
404 }
405
406 void ch_metal(const char *args)
407 {
408     set_metal(0, args);
409 }
410
411 void ch_noclothes(const char *args)
412 {
413     set_noclothes(0, args);
414 }
415
416 void ch_noclothesnear(const char *args)
417 {
418     int closest = findClosestPlayer();
419     if (closest >= 0)
420         set_noclothes(closest, args);
421 }
422
423 void ch_clothes(const char *args)
424 {
425     set_clothes(0, args);
426 }
427
428 void ch_clothesnear(const char *args)
429 {
430     int closest = findClosestPlayer();
431     if (closest >= 0)
432         set_clothes(closest, args);
433 }
434
435 void ch_belt(const char *)
436 {
437     Person::players[0]->skeleton.clothes = !Person::players[0]->skeleton.clothes;
438 }
439
440
441 void ch_cellophane(const char *)
442 {
443     cellophane = !cellophane;
444     float mul = (cellophane ? 0 : 1);
445
446     for (auto player : Person::players) {
447         player->proportionhead.z = player->proportionhead.x * mul;
448         player->proportionbody.z = player->proportionbody.x * mul;
449         player->proportionarms.z = player->proportionarms.x * mul;
450         player->proportionlegs.z = player->proportionlegs.x * mul;
451     }
452 }
453
454 void ch_funnybunny(const char *)
455 {
456     Person::players[0]->creature = rabbittype;
457     Person::players[0]->skeletonLoad(true);
458     Person::players[0]->scale = .2;
459     Person::players[0]->headless = 0;
460     Person::players[0]->damagetolerance = 200;
461     set_proportion(0, "1 1 1 1");
462 }
463
464 void ch_wolfie(const char *)
465 {
466     Person::players[0]->creature = wolftype;
467     Person::players[0]->skeletonLoad();
468     Person::players[0]->damagetolerance = 300;
469     set_proportion(0, "1 1 1 1");
470 }
471
472 void ch_wolfieisgod(const char *args)
473 {
474     ch_wolfie(args);
475 }
476
477 void ch_wolf(const char *)
478 {
479     Person::players[0]->skeleton.drawmodel.textureptr.load("Textures/Wolf.jpg", 1, &Person::players[0]->skeleton.skinText[0], &Person::players[0]->skeleton.skinsize);
480 }
481
482 void ch_snowwolf(const char *)
483 {
484     Person::players[0]->skeleton.drawmodel.textureptr.load("Textures/SnowWolf.jpg", 1, &Person::players[0]->skeleton.skinText[0], &Person::players[0]->skeleton.skinsize);
485 }
486
487 void ch_darkwolf(const char *)
488 {
489     Person::players[0]->skeleton.drawmodel.textureptr.load("Textures/DarkWolf.jpg", 1, &Person::players[0]->skeleton.skinText[0], &Person::players[0]->skeleton.skinsize);
490 }
491
492 void ch_lizardwolf(const char *)
493 {
494     Person::players[0]->skeleton.drawmodel.textureptr.load("Textures/LizardWolf.jpg", 1, &Person::players[0]->skeleton.skinText[0], &Person::players[0]->skeleton.skinsize);
495 }
496
497 void ch_white(const char *)
498 {
499     Person::players[0]->skeleton.drawmodel.textureptr.load("Textures/Fur.jpg", 1, &Person::players[0]->skeleton.skinText[0], &Person::players[0]->skeleton.skinsize);
500 }
501
502 void ch_brown(const char *)
503 {
504     Person::players[0]->skeleton.drawmodel.textureptr.load("Textures/Fur3.jpg", 1, &Person::players[0]->skeleton.skinText[0], &Person::players[0]->skeleton.skinsize);
505 }
506
507 void ch_black(const char *)
508 {
509     Person::players[0]->skeleton.drawmodel.textureptr.load("Textures/Fur2.jpg", 1, &Person::players[0]->skeleton.skinText[0], &Person::players[0]->skeleton.skinsize);
510 }
511
512 void ch_sizemin(const char *)
513 {
514     for (unsigned i = 1; i < Person::players.size(); i++)
515         if (Person::players[i]->scale < 0.8 * 0.2)
516             Person::players[i]->scale = 0.8 * 0.2;
517 }
518
519 void ch_tutorial(const char *args)
520 {
521     Tutorial::active = atoi(args);
522 }
523
524 void ch_hostile(const char *args)
525 {
526     hostile = atoi(args);
527 }
528
529 void ch_type(const char *args)
530 {
531     int n = sizeof(editortypenames) / sizeof(editortypenames[0]);
532     for (int i = 0; i < n; i++)
533         if (stripfx(args, editortypenames[i])) {
534             editoractive = i;
535             break;
536         }
537 }
538
539 void ch_path(const char *args)
540 {
541     unsigned int n = sizeof(pathtypenames) / sizeof(pathtypenames[0]);
542     for (unsigned int i = 0; i < n; i++)
543         if (stripfx(args, pathtypenames[i])) {
544             editorpathtype = i;
545             break;
546         }
547 }
548
549 void ch_hs(const char *args)
550 {
551     float size;
552     int type, shift;
553     sscanf(args, "%f%d %n", &size, &type, &shift);
554
555     Hotspot::hotspots.emplace_back(Person::players[0]->coords, type, size);
556
557     strcpy(Hotspot::hotspots.back().text, args + shift);
558     strcat(Hotspot::hotspots.back().text, "\n");
559 }
560
561 void ch_dialogue(const char *args)
562 {
563     int type;
564     char buf1[32];
565
566     sscanf(args, "%d %31s", &type, buf1);
567     std::string filename = std::string("Dialogues/") + buf1 + ".txt";
568
569     Dialog::dialogs.push_back(Dialog(type, filename));
570
571     Dialog::directing = true;
572     Dialog::indialogue = 0;
573     Dialog::whichdialogue = Dialog::dialogs.size();
574 }
575
576 void ch_fixdialogue(const char *args)
577 {
578     char buf1[32];
579     int whichdi;
580
581     sscanf(args, "%d %31s", &whichdi, buf1);
582     std::string filename = std::string("Dialogues/") + buf1 + ".txt";
583
584     Dialog::dialogs[whichdi] = Dialog(Dialog::dialogs[whichdi].type, filename);
585 }
586
587 void ch_fixtype(const char *args)
588 {
589     int dlg;
590     sscanf(args, "%d", &dlg);
591     Dialog::dialogs[0].type = dlg;
592 }
593
594 void ch_fixrotation(const char *)
595 {
596     int playerId = Dialog::currentScene().participantfocus;
597     Dialog::currentDialog().participantyaw[playerId] = Person::players[playerId]->yaw;
598 }
599
600 void ch_ddialogue(const char *)
601 {
602     if (!Dialog::dialogs.empty()) {
603         Dialog::dialogs.pop_back();
604     }
605 }
606
607 void ch_dhs(const char *)
608 {
609     if (!Hotspot::hotspots.empty()) {
610         Hotspot::hotspots.pop_back();
611     }
612 }
613
614 void ch_immobile(const char *)
615 {
616     Person::players[0]->immobile = 1;
617 }
618
619 void ch_allimmobile(const char *)
620 {
621     for (unsigned i = 1; i < Person::players.size(); i++)
622         Person::players[i]->immobile = 1;
623 }
624
625 void ch_mobile(const char *)
626 {
627     Person::players[0]->immobile = 0;
628 }
629
630 void ch_default(const char *)
631 {
632     Person::players[0]->armorhead = 1;
633     Person::players[0]->armorhigh = 1;
634     Person::players[0]->armorlow = 1;
635     Person::players[0]->protectionhead = 1;
636     Person::players[0]->protectionhigh = 1;
637     Person::players[0]->protectionlow = 1;
638     Person::players[0]->metalhead = 1;
639     Person::players[0]->metalhigh = 1;
640     Person::players[0]->metallow = 1;
641     Person::players[0]->power = 1;
642     Person::players[0]->speedmult = 1;
643     Person::players[0]->scale = 1;
644
645     if (Person::players[0]->creature == wolftype) {
646         Person::players[0]->proportionhead = 1.1;
647         Person::players[0]->proportionbody = 1.1;
648         Person::players[0]->proportionarms = 1.1;
649         Person::players[0]->proportionlegs = 1.1;
650     } else if (Person::players[0]->creature == rabbittype) {
651         Person::players[0]->proportionhead = 1.2;
652         Person::players[0]->proportionbody = 1.05;
653         Person::players[0]->proportionarms = 1.00;
654         Person::players[0]->proportionlegs = 1.1;
655         Person::players[0]->proportionlegs.y = 1.05;
656     }
657
658     Person::players[0]->numclothes = 0;
659     Person::players[0]->skeleton.drawmodel.textureptr.load(
660         creatureskin[Person::players[0]->creature][Person::players[0]->whichskin], 1,
661         &Person::players[0]->skeleton.skinText[0], &Person::players[0]->skeleton.skinsize);
662
663     editoractive = typeactive;
664     Person::players[0]->immobile = 0;
665 }
666
667 void ch_play(const char *args)
668 {
669     int dlg;
670     sscanf(args, "%d", &dlg);
671     Dialog::whichdialogue = dlg;
672
673     if (Dialog::whichdialogue >= int(Dialog::dialogs.size())) {
674         return;
675     }
676
677     Dialog::currentDialog().play();
678 }
679
680 void ch_mapkilleveryone(const char *)
681 {
682     maptype = mapkilleveryone;
683 }
684
685 void ch_mapkillmost(const char *)
686 {
687     maptype = mapkillmost;
688 }
689
690 void ch_mapkillsomeone(const char *)
691 {
692     maptype = mapkillsomeone;
693 }
694
695 void ch_mapgosomewhere(const char *)
696 {
697     maptype = mapgosomewhere;
698 }
699
700 void ch_viewdistance(const char *args)
701 {
702     viewdistance = atof(args) * 100;
703 }
704
705 void ch_fadestart(const char *args)
706 {
707     fadestart = atof(args);
708 }
709
710 void ch_slomo(const char *args)
711 {
712     slomospeed = atof(args);
713     slomo = !slomo;
714     slomodelay = 1000;
715 }
716
717 void ch_slofreq(const char *args)
718 {
719     slomofreq = atof(args);
720 }
721
722 void ch_skytint(const char *args)
723 {
724     sscanf(args, "%f%f%f", &skyboxr, &skyboxg, &skyboxb);
725
726     skyboxlightr = skyboxr;
727     skyboxlightg = skyboxg;
728     skyboxlightb = skyboxb;
729
730     SetUpLighting();
731
732     terrain.DoShadows();
733     Object::DoShadows();
734 }
735
736 void ch_skylight(const char *args)
737 {
738     sscanf(args, "%f%f%f", &skyboxlightr, &skyboxlightg, &skyboxlightb);
739
740     SetUpLighting();
741
742     terrain.DoShadows();
743     Object::DoShadows();
744 }
745
746 void ch_skybox(const char*)
747 {
748     skyboxtexture = !skyboxtexture;
749
750     SetUpLighting();
751
752     terrain.DoShadows();
753     Object::DoShadows();
754 }