2 Copyright (C) 2003, 2010 - Wolfire Games
3 Copyright (C) 2010-2017 - Lugaru contributors (see AUTHORS file)
5 This file is part of Lugaru.
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.
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.
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/>.
23 #include "Animation/Animation.hpp"
24 #include "Audio/openal_wrapper.hpp"
25 #include "Graphic/Texture.hpp"
26 #include "Menu/Menu.hpp"
27 #include "Utils/Folders.hpp"
29 extern float screenwidth, screenheight;
30 extern float viewdistance;
32 extern float fadestart;
33 extern float texscale;
36 extern Terrain terrain;
37 extern int kTextureSize;
38 extern float texdetail;
39 extern float realtexdetail;
42 extern bool cellophane;
43 extern GLubyte bloodText[512 * 512 * 3];
44 extern GLubyte wolfbloodText[512 * 512 * 3];
45 extern bool ismotionblur;
46 extern bool trilinear;
47 extern bool musictoggle;
48 extern int environment;
49 extern bool ambientsound;
50 extern float multiplier;
51 extern int netdatanew;
53 extern bool stillloading;
55 extern bool visibleloading;
56 extern float flashamount, flashr, flashg, flashb;
57 extern int flashdelay;
58 extern int whichjointstartarray[26];
59 extern int whichjointendarray[26];
60 extern float slomospeed;
61 extern bool gamestarted;
63 extern float accountcampaignhighscore[10];
64 extern float accountcampaignfasttime[10];
65 extern float accountcampaignscore[10];
66 extern float accountcampaigntime[10];
68 extern int accountcampaignchoicesmade[10];
69 extern int accountcampaignchoices[10][5000];
71 void LOG(const std::string&, ...)
73 // !!! FIXME: write me.
80 if (Game::endgame == 2) {
81 Account::active().endGame();
85 Account::saveFile(Folders::getUserSavePath());
89 LOG("Shutting down sound system...");
91 OPENAL_StopSound(OPENAL_ALL);
93 // this is causing problems on Linux, but we'll force an _exit() a little
94 // later in the shutdown process. --ryan.
97 for (int i = 0; i < sounds_count; ++i) {
98 OPENAL_Sample_Free(samp[i]);
108 textmono = new Text();
109 skybox = new SkyBox();
112 void Game::deleteGame()
118 glDeleteTextures(1, &screentexture);
119 glDeleteTextures(1, &screentexture2);
124 void LoadSave(const std::string& fileName, GLubyte* array)
128 LOG(std::string("Loading (S)...") + fileName);
131 float temptexdetail = texdetail;
136 if (!load_image(Folders::getResourcePath(fileName).c_str(), texture)) {
137 texdetail = temptexdetail;
140 texdetail = temptexdetail;
142 int bytesPerPixel = texture.bpp / 8;
145 for (int i = 0; i < (int)(texture.sizeY * texture.sizeX * bytesPerPixel); i++) {
146 if ((i + 1) % 4 || bytesPerPixel == 3) {
147 array[tempnum] = texture.data[i];
153 //***************> ResizeGLScene() <******/
154 GLvoid Game::ReSizeGLScene(float fov, float pnear)
156 if (screenheight == 0) {
160 glViewport(0, 0, screenwidth, screenheight);
162 glMatrixMode(GL_PROJECTION);
165 gluPerspective(fov, (GLfloat)screenwidth / (GLfloat)screenheight, pnear, viewdistance);
167 glMatrixMode(GL_MODELVIEW);
171 void Game::LoadingScreen()
173 if (!visibleloading) {
177 static float loadprogress;
178 static AbsoluteTime frametime = { 0, 0 };
179 AbsoluteTime currTime = UpTime();
180 double deltaTime = (float)AbsoluteDeltaToDuration(currTime, frametime);
182 if (0 > deltaTime) { // if negative microseconds
183 deltaTime /= -1000000.0;
184 } else { // else milliseconds
188 multiplier = deltaTime;
189 if (multiplier < .001) {
192 if (multiplier > 10) {
195 if (multiplier > .05) {
196 frametime = currTime; // reset for next time interval
200 glClearColor(0, 0, 0, 1);
201 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
203 loadtime += multiplier * 4;
205 loadprogress = loadtime;
206 if (loadprogress > 100) {
212 glEnable(GL_TEXTURE_2D);
213 loadscreentexture.bind();
214 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
215 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
216 glDisable(GL_DEPTH_TEST);
217 glDisable(GL_CULL_FACE);
218 glDisable(GL_LIGHTING);
220 glMatrixMode(GL_PROJECTION);
223 glOrtho(0, screenwidth, 0, screenheight, -100, 100);
224 glMatrixMode(GL_MODELVIEW);
227 glTranslatef(screenwidth / 2, screenheight / 2, 0);
228 glScalef((float)screenwidth / 2, (float)screenheight / 2, 1);
229 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
231 glColor4f(loadprogress / 100, loadprogress / 100, loadprogress / 100, 1);
234 glTexCoord2f(.1 - loadprogress / 100, 0 + loadprogress / 100 + .3);
235 glVertex3f(-1, -1, 0.0f);
236 glTexCoord2f(.1 - loadprogress / 100, 0 + loadprogress / 100 + .3);
237 glVertex3f(1, -1, 0.0f);
238 glTexCoord2f(.1 - loadprogress / 100, 1 + loadprogress / 100 + .3);
239 glVertex3f(1, 1, 0.0f);
240 glTexCoord2f(.1 - loadprogress / 100, 1 + loadprogress / 100 + .3);
241 glVertex3f(-1, 1, 0.0f);
247 glTexCoord2f(.4 + loadprogress / 100, 0 + loadprogress / 100);
248 glVertex3f(-1, -1, 0.0f);
249 glTexCoord2f(.4 + loadprogress / 100, 0 + loadprogress / 100);
250 glVertex3f(1, -1, 0.0f);
251 glTexCoord2f(.4 + loadprogress / 100, 1 + loadprogress / 100);
252 glVertex3f(1, 1, 0.0f);
253 glTexCoord2f(.4 + loadprogress / 100, 1 + loadprogress / 100);
254 glVertex3f(-1, 1, 0.0f);
257 glDisable(GL_TEXTURE_2D);
258 glMatrixMode(GL_PROJECTION);
260 glMatrixMode(GL_MODELVIEW);
265 glEnable(GL_TEXTURE_2D);
266 loadscreentexture.bind();
267 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
268 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
269 glDisable(GL_DEPTH_TEST);
270 glDisable(GL_CULL_FACE);
271 glDisable(GL_LIGHTING);
273 glMatrixMode(GL_PROJECTION);
276 glOrtho(0, screenwidth, 0, screenheight, -100, 100);
277 glMatrixMode(GL_MODELVIEW);
280 glTranslatef(screenwidth / 2, screenheight / 2, 0);
281 glScalef((float)screenwidth / 2 * (1.5 - (loadprogress) / 200), (float)screenheight / 2 * (1.5 - (loadprogress) / 200), 1);
282 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
284 glColor4f(loadprogress / 100, loadprogress / 100, loadprogress / 100, 1);
287 glTexCoord2f(0 + .5, 0 + .5);
288 glVertex3f(-1, -1, 0.0f);
289 glTexCoord2f(1 + .5, 0 + .5);
290 glVertex3f(1, -1, 0.0f);
291 glTexCoord2f(1 + .5, 1 + .5);
292 glVertex3f(1, 1, 0.0f);
293 glTexCoord2f(0 + .5, 1 + .5);
294 glVertex3f(-1, 1, 0.0f);
297 glDisable(GL_TEXTURE_2D);
298 glMatrixMode(GL_PROJECTION);
300 glMatrixMode(GL_MODELVIEW);
305 glEnable(GL_TEXTURE_2D);
306 loadscreentexture.bind();
307 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
308 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
309 glDisable(GL_DEPTH_TEST);
310 glDisable(GL_CULL_FACE);
311 glDisable(GL_LIGHTING);
313 glMatrixMode(GL_PROJECTION);
316 glOrtho(0, screenwidth, 0, screenheight, -100, 100);
317 glMatrixMode(GL_MODELVIEW);
320 glTranslatef(screenwidth / 2, screenheight / 2, 0);
321 glScalef((float)screenwidth / 2 * (100 + loadprogress) / 100, (float)screenheight / 2 * (100 + loadprogress) / 100, 1);
322 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
324 glColor4f(loadprogress / 100, loadprogress / 100, loadprogress / 100, .4);
327 glTexCoord2f(0 + .2, 0 + .8);
328 glVertex3f(-1, -1, 0.0f);
329 glTexCoord2f(1 + .2, 0 + .8);
330 glVertex3f(1, -1, 0.0f);
331 glTexCoord2f(1 + .2, 1 + .8);
332 glVertex3f(1, 1, 0.0f);
333 glTexCoord2f(0 + .2, 1 + .8);
334 glVertex3f(-1, 1, 0.0f);
337 glDisable(GL_TEXTURE_2D);
338 glMatrixMode(GL_PROJECTION);
340 glMatrixMode(GL_MODELVIEW);
347 if (flashamount > 0) {
348 if (flashamount > 1) {
351 if (flashdelay <= 0) {
352 flashamount -= multiplier;
355 if (flashamount < 0) {
358 glDisable(GL_DEPTH_TEST);
359 glDisable(GL_CULL_FACE);
360 glDisable(GL_LIGHTING);
361 glDisable(GL_TEXTURE_2D);
363 glMatrixMode(GL_PROJECTION);
366 glOrtho(0, screenwidth, 0, screenheight, -100, 100);
367 glMatrixMode(GL_MODELVIEW);
370 glScalef(screenwidth, screenheight, 1);
371 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
373 glColor4f(flashr, flashg, flashb, flashamount);
375 glVertex3f(0, 0, 0.0f);
376 glVertex3f(256, 0, 0.0f);
377 glVertex3f(256, 256, 0.0f);
378 glVertex3f(0, 256, 0.0f);
380 glMatrixMode(GL_PROJECTION);
382 glMatrixMode(GL_MODELVIEW);
384 glEnable(GL_DEPTH_TEST);
385 glEnable(GL_CULL_FACE);
394 void FadeLoadingScreen(float howmuch)
396 static float loadprogress;
400 glClearColor(0, 0, 0, 1);
401 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
403 loadprogress = howmuch;
407 glDisable(GL_TEXTURE_2D);
408 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
409 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
410 glDisable(GL_DEPTH_TEST);
411 glDisable(GL_CULL_FACE);
412 glDisable(GL_LIGHTING);
414 glMatrixMode(GL_PROJECTION);
417 glOrtho(0, screenwidth, 0, screenheight, -100, 100);
418 glMatrixMode(GL_MODELVIEW);
421 glTranslatef(screenwidth / 2, screenheight / 2, 0);
422 glScalef((float)screenwidth / 2, (float)screenheight / 2, 1);
423 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
425 glColor4f(loadprogress / 100, 0, 0, 1);
429 glVertex3f(-1, -1, 0.0f);
431 glVertex3f(1, -1, 0.0f);
433 glVertex3f(1, 1, 0.0f);
435 glVertex3f(-1, 1, 0.0f);
438 glDisable(GL_TEXTURE_2D);
439 glMatrixMode(GL_PROJECTION);
441 glMatrixMode(GL_MODELVIEW);
449 void Game::InitGame()
453 numchallengelevels = 14;
455 Account::loadFile(Folders::getUserSavePath());
457 whichjointstartarray[0] = righthip;
458 whichjointendarray[0] = rightfoot;
460 whichjointstartarray[1] = righthip;
461 whichjointendarray[1] = rightankle;
463 whichjointstartarray[2] = righthip;
464 whichjointendarray[2] = rightknee;
466 whichjointstartarray[3] = rightknee;
467 whichjointendarray[3] = rightankle;
469 whichjointstartarray[4] = rightankle;
470 whichjointendarray[4] = rightfoot;
472 whichjointstartarray[5] = lefthip;
473 whichjointendarray[5] = leftfoot;
475 whichjointstartarray[6] = lefthip;
476 whichjointendarray[6] = leftankle;
478 whichjointstartarray[7] = lefthip;
479 whichjointendarray[7] = leftknee;
481 whichjointstartarray[8] = leftknee;
482 whichjointendarray[8] = leftankle;
484 whichjointstartarray[9] = leftankle;
485 whichjointendarray[9] = leftfoot;
487 whichjointstartarray[10] = abdomen;
488 whichjointendarray[10] = rightshoulder;
490 whichjointstartarray[11] = abdomen;
491 whichjointendarray[11] = rightelbow;
493 whichjointstartarray[12] = abdomen;
494 whichjointendarray[12] = rightwrist;
496 whichjointstartarray[13] = abdomen;
497 whichjointendarray[13] = righthand;
499 whichjointstartarray[14] = rightshoulder;
500 whichjointendarray[14] = rightelbow;
502 whichjointstartarray[15] = rightelbow;
503 whichjointendarray[15] = rightwrist;
505 whichjointstartarray[16] = rightwrist;
506 whichjointendarray[16] = righthand;
508 whichjointstartarray[17] = abdomen;
509 whichjointendarray[17] = leftshoulder;
511 whichjointstartarray[18] = abdomen;
512 whichjointendarray[18] = leftelbow;
514 whichjointstartarray[19] = abdomen;
515 whichjointendarray[19] = leftwrist;
517 whichjointstartarray[20] = abdomen;
518 whichjointendarray[20] = lefthand;
520 whichjointstartarray[21] = leftshoulder;
521 whichjointendarray[21] = leftelbow;
523 whichjointstartarray[22] = leftelbow;
524 whichjointendarray[22] = leftwrist;
526 whichjointstartarray[23] = leftwrist;
527 whichjointendarray[23] = lefthand;
529 whichjointstartarray[24] = abdomen;
530 whichjointendarray[24] = neck;
532 whichjointstartarray[25] = neck;
533 whichjointendarray[25] = head;
535 FadeLoadingScreen(0);
539 int temptexdetail = texdetail;
541 text->LoadFontTexture("Textures/Font.png");
543 textmono->LoadFontTexture("Textures/FontMono.png");
544 textmono->BuildFont();
545 texdetail = temptexdetail;
547 FadeLoadingScreen(10);
559 LOG("Initializing sound system...");
561 OPENAL_Init(44100, 32, 0);
563 OPENAL_SetSFXMasterVolume((int)(volume * 255));
567 emit_stream_np(stream_menutheme);
570 cursortexture.load("Textures/Cursor.png", 0);
572 Mapcircletexture.load("Textures/MapCircle.png", 0);
573 Mapboxtexture.load("Textures/MapBox.png", 0);
574 Maparrowtexture.load("Textures/MapArrow.png", 0);
576 temptexdetail = texdetail;
580 Mainmenuitems[0].load("Textures/Lugaru.png", 0);
581 Mainmenuitems[1].load("Textures/NewGame.png", 0);
582 Mainmenuitems[2].load("Textures/Options.png", 0);
583 Mainmenuitems[3].load("Textures/Quit.png", 0);
584 Mainmenuitems[4].load("Textures/Eyelid.png", 0);
585 Mainmenuitems[5].load("Textures/Resume.png", 0);
586 Mainmenuitems[6].load("Textures/EndGame.png", 0);
588 texdetail = temptexdetail;
590 FadeLoadingScreen(95);
596 firstLoadDone = false;
599 newscreenwidth = screenwidth;
600 newscreenheight = screenheight;
604 Animation::loadAll();
609 void Game::LoadScreenTexture()
611 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
613 if (!Game::screentexture) {
614 glGenTextures(1, &Game::screentexture);
616 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
618 glEnable(GL_TEXTURE_2D);
619 glBindTexture(GL_TEXTURE_2D, Game::screentexture);
620 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
621 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
623 glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, kTextureSize, kTextureSize, 0);
626 //TODO: move LoadStuff() closer to GameTick.cpp to get rid of various vars shared in Game.hpp
627 /* Loads models and textures which only needs to be loaded once */
628 void Game::LoadStuff()
631 float viewdistdetail;
640 visibleloading = false; //don't use loadscreentexture yet
641 loadscreentexture.load("Textures/Fire.jpg", 1);
642 visibleloading = true;
644 temptexdetail = texdetail;
646 text->LoadFontTexture("Textures/Font.png");
648 textmono->LoadFontTexture("Textures/FontMono.png");
649 textmono->BuildFont();
650 texdetail = temptexdetail;
653 viewdistance = 50 * megascale * viewdistdetail;
658 } else if (detail == 1) {
666 realtexdetail = texdetail;
670 terrain.shadowtexture.load("Textures/Shadow.png", 0);
671 terrain.bloodtexture.load("Textures/Blood.png", 0);
672 terrain.breaktexture.load("Textures/Break.png", 0);
673 terrain.bloodtexture2.load("Textures/Blood.png", 0);
675 terrain.footprinttexture.load("Textures/Footprint.png", 0);
676 terrain.bodyprinttexture.load("Textures/Bodyprint.png", 0);
677 hawktexture.load("Textures/Hawk.png", 0);
679 Sprite::cloudtexture.load("Textures/Cloud.png", 1);
680 Sprite::cloudimpacttexture.load("Textures/CloudImpact.png", 1);
681 Sprite::bloodtexture.load("Textures/BloodParticle.png", 1);
682 Sprite::snowflaketexture.load("Textures/SnowFlake.png", 1);
683 Sprite::flametexture.load("Textures/Flame.png", 1);
684 Sprite::bloodflametexture.load("Textures/BloodFlame.png", 1);
685 Sprite::smoketexture.load("Textures/Smoke.png", 1);
686 Sprite::shinetexture.load("Textures/Shine.png", 1);
687 Sprite::splintertexture.load("Textures/Splinter.png", 1);
688 Sprite::leaftexture.load("Textures/Leaf.png", 1);
689 Sprite::toothtexture.load("Textures/Tooth.png", 1);
693 ReSizeGLScene(90, .01);
697 //Set up distant light
698 light.color[0] = .95;
699 light.color[1] = .95;
701 light.ambient[0] = .2;
702 light.ambient[1] = .2;
703 light.ambient[2] = .24;
704 light.location.x = 1;
705 light.location.y = 1;
706 light.location.z = -.2;
707 Normalise(&light.location);
716 texscale = .2 / megascale / viewdistdetail;
717 terrain.scale = 3 * megascale * viewdistdetail;
719 viewer.x = terrain.size / 2 * terrain.scale;
720 viewer.z = terrain.size / 2 * terrain.scale;
722 hawk.load("Models/Hawk.solid");
723 hawk.Scale(.03, .03, .03);
724 hawk.Rotate(90, 1, 1);
725 hawk.CalculateNormals(0);
726 hawk.ScaleNormals(-1, -1, -1);
727 hawkcoords.x = terrain.size / 2 * terrain.scale - 5 - 7;
728 hawkcoords.z = terrain.size / 2 * terrain.scale - 5 - 7;
729 hawkcoords.y = terrain.getHeight(hawkcoords.x, hawkcoords.z) + 25;
731 eye.load("Models/Eye.solid");
732 eye.Scale(.03, .03, .03);
733 eye.CalculateNormals(0);
735 cornea.load("Models/Cornea.solid");
736 cornea.Scale(.03, .03, .03);
737 cornea.CalculateNormals(0);
739 iris.load("Models/Iris.solid");
740 iris.Scale(.03, .03, .03);
741 iris.CalculateNormals(0);
743 LoadSave("Textures/BloodFur.png", &bloodText[0]);
744 LoadSave("Textures/WolfBloodFur.png", &wolfbloodText[0]);
751 //Fix knife stab, too lazy to do it manually
755 // FIXME - Why this uses skeleton.joints.size() and not Animation::numjoints? (are they equal?)
756 // It seems skeleton.joints.size() is 0 at this point, so this is useless.
757 for (unsigned i = 0; i < Person::players[0]->skeleton.joints.size(); i++) {
758 for (unsigned j = 0; j < Animation::animations[knifesneakattackanim].frames.size(); j++) {
759 Animation::animations[knifesneakattackanim].frames[j].joints[i].position += moveamount;
765 for (unsigned i = 0; i < Person::players[0]->skeleton.joints.size(); i++) {
766 for (unsigned j = 0; j < Animation::animations[knifesneakattackedanim].frames.size(); j++) {
767 Animation::animations[knifesneakattackedanim].frames[j].joints[i].position += moveamount;
773 for (unsigned i = 0; i < Person::players[0]->skeleton.joints.size(); i++) {
774 Animation::animations[dead1anim].frames[1].joints[i].position = Animation::animations[dead1anim].frames[0].joints[i].position;
775 Animation::animations[dead2anim].frames[1].joints[i].position = Animation::animations[dead2anim].frames[0].joints[i].position;
776 Animation::animations[dead3anim].frames[1].joints[i].position = Animation::animations[dead3anim].frames[0].joints[i].position;
777 Animation::animations[dead4anim].frames[1].joints[i].position = Animation::animations[dead4anim].frames[0].joints[i].position;
779 Animation::animations[dead1anim].frames[0].speed = 0.001;
780 Animation::animations[dead2anim].frames[0].speed = 0.001;
781 Animation::animations[dead3anim].frames[0].speed = 0.001;
782 Animation::animations[dead4anim].frames[0].speed = 0.001;
784 Animation::animations[dead1anim].frames[1].speed = 0.001;
785 Animation::animations[dead2anim].frames[1].speed = 0.001;
786 Animation::animations[dead3anim].frames[1].speed = 0.001;
787 Animation::animations[dead4anim].frames[1].speed = 0.001;
789 for (unsigned i = 0; i < Person::players[0]->skeleton.joints.size(); i++) {
790 for (unsigned j = 0; j < Animation::animations[swordsneakattackanim].frames.size(); j++) {
791 Animation::animations[swordsneakattackanim].frames[j].joints[i].position += moveamount;
795 for (unsigned j = 0; j < Animation::animations[swordsneakattackanim].frames.size(); j++) {
796 Animation::animations[swordsneakattackanim].frames[j].weapontarget += moveamount;
801 for (unsigned i = 0; i < Person::players[0]->skeleton.joints.size(); i++) {
802 for (unsigned j = 0; j < Animation::animations[swordsneakattackedanim].frames.size(); j++) {
803 Animation::animations[swordsneakattackedanim].frames[j].joints[i].position += moveamount;
809 if (!screentexture) {
813 if (targetlevel != 7) {
814 emit_sound_at(fireendsound);
821 visibleloading = false;
822 firstLoadDone = true;