Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/network/src/story_entities/world.cc @ 5971

Last change on this file since 5971 was 5971, checked in by patrick, 18 years ago

network: the branche is stable again

File size: 21.5 KB
Line 
1/*
2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
12   main-programmer: Patrick Boenzli
13   co-programmer: Christian Meyer
14   co-programmer: Benjamin Grauer
15*/
16
17#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_WORLD
18
19#include "world.h"
20
21#include "shell_command.h"
22
23#include "state.h"
24
25#include "p_node.h"
26#include "null_parent.h"
27#include "pilot_node.h"
28#include "world_entity.h"
29#include "player.h"
30#include "camera.h"
31#include "environment.h"
32#include "skysphere.h"
33#include "skybox.h"
34#include "satellite.h"
35#include "test_entity.h"
36#include "terrain.h"
37#include "light.h"
38#include "load_param.h"
39#include "shell.h"
40
41#include "garbage_collector.h"
42#include "fast_factory.h"
43#include "animation_player.h"
44#include "particle_engine.h"
45#include "graphics_engine.h"
46#include "physics_engine.h"
47#include "fields.h"
48
49#include "md2Model.h"
50
51#include "glmenu_imagescreen.h"
52#include "list.h"
53#include "game_loader.h"
54
55#include "animation3d.h"
56
57#include "substring.h"
58
59#include "factory.h"
60
61#include "weapons/projectile.h"
62#include "event_handler.h"
63#include "sound_engine.h"
64#include "ogg_player.h"
65
66#include "class_list.h"
67
68#include "cd_engine.h"
69#include "npcs/npc_test1.h"
70#include "shader.h"
71
72#include "network_manager.h"
73#include "playable.h"
74
75
76SHELL_COMMAND(speed, World, setSpeed);
77SHELL_COMMAND(togglePNodeVisibility, World, togglePNodeVisibility);
78SHELL_COMMAND(toggleBVVisibility, World, toggleBVVisibility);
79
80using namespace std;
81
82//! This creates a Factory to fabricate a World
83CREATE_FACTORY(World, CL_WORLD);
84
85World::World(const TiXmlElement* root)
86{
87  this->constuctorInit("", -1);
88  this->path = NULL;
89
90  this->loadParams(root);
91}
92
93/**
94  *  create a new World
95
96    This creates a new empty world!
97*/
98World::World (const char* name)
99{
100  this->path = NULL;
101  this->constuctorInit(name, -1);
102}
103
104/**
105 *  creates a new World...
106 * @param worldID with this ID
107*/
108World::World (int worldID)
109{
110  this->path = NULL;
111  this->constuctorInit(NULL, worldID);
112}
113
114/**
115 *  remove the World from memory
116
117    delete everything explicitly, that isn't contained in the parenting tree!
118    things contained in the tree are deleted automaticaly
119 */
120World::~World ()
121{
122  delete this->shell;
123  PRINTF(3)("World::~World() - deleting current world\n");
124
125
126  // here everything that is alocated by the World is deleted
127  delete this->entities;
128  State::setWorldEntityList(NULL);
129
130  delete this->localPlayer;
131
132  // delete all the initialized Engines.
133  FastFactory::flushAll(true);
134  delete LightManager::getInstance();
135  delete ParticleEngine::getInstance();
136  delete AnimationPlayer::getInstance();
137  delete PhysicsEngine::getInstance();
138
139  // external engines initialized by the orxonox-class get deleted
140  SoundEngine::getInstance()->flushAllBuffers();
141  SoundEngine::getInstance()->flushAllSources();
142
143
144  // erease everything that is left.
145  delete NullParent::getInstance();
146
147  Shader::suspendShader();
148
149  // unload the resources !!
150  ResourceManager::getInstance()->unloadAllByPriority(RP_LEVEL);
151
152  delete[] this->path;
153}
154
155/**
156 * initializes the world.
157 * @param name the name of the world
158 * @param worldID the ID of this world
159 *
160 * set all stuff here that is world generic and does not use to much memory
161 * because the real init() function StoryEntity::init() will be called
162 * shortly before start of the game.
163 * since all worlds are initiated/referenced before they will be started.
164 * NO LEVEL LOADING HERE - NEVER!
165*/
166void World::constuctorInit(const char* name, int worldID)
167{
168  this->setClassID(CL_WORLD, "World");
169
170  this->setName(name);
171  this->debugWorldNr = worldID;
172  this->gameTime = 0.0f;
173  this->setSpeed(1.0);
174  this->music = NULL;
175  this->shell = NULL;
176  this->entities = NULL;
177  this->localPlayer = NULL;
178  this->localCamera = NULL;
179
180  this->showPNodes = false;
181  this->showBV = false;
182}
183
184/**
185 * loads the parameters of a World from an XML-element
186 * @param root the XML-element to load from
187 */
188void World::loadParams(const TiXmlElement* root)
189{
190  PRINTF(4)("Creating a World\n");
191
192  LoadParam(root, "identifier", this, World, setStoryID)
193    .describe("Sets the StoryID of this world");
194
195  LoadParam(root, "nextid", this, World, setNextStoryID)
196    .describe("Sets the ID of the next world");
197
198  LoadParam(root, "path", this, World, setPath)
199    .describe("The Filename of this World (relative from the data-dir)");
200}
201
202/**
203 * this is executed just before load
204 *
205 * since the load function sometimes needs data, that has been initialized
206 * before the load and after the proceeding storyentity has finished
207*/
208ErrorMessage World::preLoad()
209{
210  State::setWorldEntityList(this->entities = new tList<WorldEntity>());
211  this->cycle = 0;
212
213  /* init the world interface */
214  this->shell = new Shell();
215
216  LightManager::getInstance();
217  NullParent::getInstance ();
218
219  AnimationPlayer::getInstance(); // initializes the animationPlayer
220  ParticleEngine::getInstance();
221  PhysicsEngine::getInstance();
222
223  this->localCamera = new Camera();
224  this->localCamera->setName ("World-Camera");
225
226  State::setCamera(this->localCamera, this->localCamera->getTarget());
227
228  GraphicsEngine::getInstance()->displayFPS(true);
229
230  CDEngine::getInstance()->setEntityList( this->entities);
231}
232
233
234/**
235 *  loads the World by initializing all resources, and set their default values.
236*/
237ErrorMessage World::load()
238{
239  PRINTF(3)("> Loading world: '%s'\n", getPath());
240  TiXmlElement* element;
241  GameLoader* loader = GameLoader::getInstance();
242
243  if( getPath() == NULL)
244    {
245      PRINTF(1)("World has no path specified for loading");
246      this->loadDebugWorld(this->getStoryID());
247      return (ErrorMessage){213,"Path not specified","World::load()"};
248    }
249
250  TiXmlDocument* XMLDoc = new TiXmlDocument( getPath());
251  // load the campaign document
252  if( !XMLDoc->LoadFile())
253  {
254    // report an error
255    PRINTF(1)("loading XML File: %s @ %s:l%d:c%d\n", XMLDoc->ErrorDesc(), this->getPath(), XMLDoc->ErrorRow(), XMLDoc->ErrorCol());
256    delete XMLDoc;
257    return (ErrorMessage){213,"XML File parsing error","World::load()"};
258  }
259
260  // check basic validity
261  TiXmlElement* root = XMLDoc->RootElement();
262  assert( root != NULL);
263
264  if( root == NULL || root->Value() == NULL || strcmp( root->Value(), "WorldDataFile"))
265    {
266      // report an error
267      PRINTF(1)("Specified XML File is not an orxonox world data file (WorldDataFile element missing)\n");
268      delete XMLDoc;
269      return (ErrorMessage){213,"Path not a WorldDataFile","World::load()"};
270    }
271
272  // load the parameters
273  // name
274  const char* string = grabParameter( root, "name");
275  if( string == NULL)
276    {
277      PRINTF(2)("World is missing a proper 'name'\n");
278      this->setName("Unknown");
279    }
280  else
281    {
282      this->setName(string);
283    }
284
285  ////////////////
286  // LOADSCREEN //
287  ////////////////
288  element = root->FirstChildElement("LoadScreen");
289  if (element == NULL)
290    {
291      PRINTF(2)("no LoadScreen specified, loading default\n");
292
293      glmis->setBackgroundImage("pictures/load_screen.jpg");
294      this->glmis->setMaximum(8);
295      this->glmis->draw();
296    }
297  else
298    {
299      this->glmis->loadParams(element);
300      this->glmis->draw();
301    }
302  this->glmis->draw();
303
304  ////////////////////////
305  // find WorldEntities //
306  ////////////////////////
307
308  element = root->FirstChildElement("WorldEntities");
309
310  if( element == NULL)
311    {
312      PRINTF(1)("World is missing 'WorldEntities'\n");
313    }
314  else
315    {
316      element = element->FirstChildElement();
317      // load Players/Objects/Whatever
318      PRINTF(4)("Loading WorldEntities\n");
319      while( element != NULL)
320        {
321          BaseObject* created = (loader->fabricate(element));
322          if( created != NULL )
323          {
324            if(created->isA(CL_WORLD_ENTITY))
325              this->spawn(dynamic_cast<WorldEntity*>(created));
326            printf("Created a %s: %s\n", created->getClassName(), created->getName());
327          }
328
329          // if we load a 'Player' we use it as localPlayer
330
331
332          //todo do this more elegant
333          if( element->Value() != NULL && !strcmp( element->Value(), "SkyBox"))
334            sky = dynamic_cast<SkyBox*>(created);
335          if( element->Value() != NULL && !strcmp( element->Value(), "Terrain"))
336          {
337            terrain = dynamic_cast<Terrain*>(created);
338            CDEngine::getInstance()->setTerrain(terrain);
339          }
340          element = element->NextSiblingElement();
341          glmis->step(); //! @todo temporary
342        }
343      PRINTF(4)("Done loading WorldEntities\n");
344    }
345
346    //////////////////////////////
347    // LOADING ADDITIONAL STUFF //
348    //////////////////////////////
349
350    LoadParamXML(root, "LightManager", LightManager::getInstance(), LightManager, loadParams);
351
352   LoadParamXML(root, "ParticleEngine", ParticleEngine::getInstance(), ParticleEngine, loadParams);
353//   LoadParamXML(root, "PhysicsEngine", PhysicsEngine::getInstance(), PhysicsEngine, loadParams);
354
355  // free the XML data
356
357  delete XMLDoc;
358  /* GENERIC LOADING PROCESS FINISHED */
359
360
361  // Create a Player
362  this->localPlayer = new Player();
363
364  Playable* playable;
365  const list<BaseObject*>* playableList = ClassList::getList(CL_PLAYABLE);
366  if (playableList != NULL)
367  {
368    playable = dynamic_cast<Playable*>(playableList->front());
369    this->localPlayer->setControllable(playable);
370  }
371
372  // bind camera
373  playable->addChild (this->localCamera);
374
375//   //localCamera->setParent(TrackNode::getInstance());
376//  tn->addChild(this->localCamera);
377  localCamera->setClipRegion(1, 10000.0);
378  localCamera->lookAt(playable);
379//  this->localPlayer->setParentMode(PNODE_ALL);
380  if (sky != NULL)
381  {
382    this->sky->setParent(this->localCamera);
383    this->sky->setParentMode(PNODE_MOVEMENT);
384  }
385
386  // initialize debug coord system
387  objectList = glGenLists(1);
388  glNewList (objectList, GL_COMPILE);
389
390  glEndList();
391
392  SoundEngine::getInstance()->setListener(this->localCamera);
393
394
395
396  ////////////
397  // STATIC //
398  ////////////
399
400
401//   TestEntity* testEntity = new TestEntity();
402//   testEntity->setRelCoor(Vector(570, 10, -15));
403//   testEntity->setRelDir(Quaternion(M_PI, Vector(0, 1, 0)));
404//   this->spawn(testEntity);
405
406  for(int i = 0; i < 100; i++)
407  {
408    WorldEntity* tmp = new NPCTest1();
409    char npcChar[10];
410    sprintf (npcChar, "NPC_%d", i);
411        tmp->setName(npcChar);
412    tmp->setAbsCoor(((float)rand()/RAND_MAX) * 5000, 50/*+ (float)rand()/RAND_MAX*20*/, ((float)rand()/RAND_MAX -.5) *30);
413    this->spawn(tmp);
414  }
415
416  this->music = NULL;//(OggPlayer*)ResourceManager::getInstance()->load("sound/00-luke_grey_-_hypermode.ogg", OGG, RP_LEVEL);
417  //music->playback();
418}
419
420
421
422/**
423 * creates a debug world: only for experimental stuff
424*/
425void World::loadDebugWorld(int worldID)
426{
427  /*monitor progress*/
428  this->glmis->step();
429  // stuff beyond this point remains to be loaded properly
430
431  // LIGHT initialisation
432  LightManager::getInstance()->setAmbientColor(.1,.1,.1);
433//  LightManager::getInstance()->addLight();
434  LightManager::getInstance()->debug();
435
436  switch(this->debugWorldNr)
437    {
438      /*
439        this loads the hard-coded debug world. this only for simplicity and will be
440        removed by a reald world-loader, which interprets a world-file.
441        if you want to add an own debug world, just add a case DEBUG_WORLD_[nr] and
442        make whatever you want...
443      */
444    case DEBUG_WORLD_0:
445      {
446        LightManager::getInstance()->getLight()->setAbsCoor(-5.0, 10.0, -40.0);
447        /*monitor progress*/
448        this->glmis->step();
449
450        // bind camera
451        this->localCamera = new Camera();
452        this->localCamera->setName ("camera");
453        /*monitor progress*/
454        this->glmis->step();
455
456
457        // Create SkySphere
458        this->sky = new Skysphere("pictures/sky-replace.jpg");
459        this->sky->setName("SkySphere");
460        this->spawn(this->sky);
461        this->localCamera->addChild(this->sky);
462        this->sky->setParentMode(PNODE_MOVEMENT);
463        /*monitor progress*/
464        this->glmis->step();
465
466
467        terrain = new Terrain("worlds/newGround.obj");
468        terrain->setRelCoor(Vector(0,-10,0));
469        this->spawn(terrain);
470        /*monitor progress*/
471        this->glmis->step();
472
473        this->glmis->step();
474        break;
475      }
476    case DEBUG_WORLD_1:
477      {
478
479        break;
480      }
481    case DEBUG_WORLD_2:
482      {
483
484        break;
485      }
486    default:
487      break;
488    }
489}
490
491/**
492 *  initializes a new World shortly before start
493 *
494 * this is the function, that will be loaded shortly before the world is
495 * started
496*/
497ErrorMessage World::init()
498{
499  this->bPause = false;
500
501  /* update the object position before game start - so there are no wrong coordinates used in the first processing */
502  NullParent::getInstance()->updateNode (0.001f);
503  NullParent::getInstance()->updateNode (0.001f);
504
505}
506
507
508/**
509 *  starts the World
510*/
511ErrorMessage World::start()
512{
513  PRINTF(3)("World::start() - starting current World: nr %i\n", this->debugWorldNr);
514  this->bQuitOrxonox = false;
515  this->bQuitCurrentGame = false;
516  this->mainLoop();
517}
518
519/**
520 *  stops the world.
521
522   This happens, when the player decides to end the Level.
523*/
524ErrorMessage World::stop()
525{
526  PRINTF(3)("World::stop() - got stop signal\n");
527  this->bQuitCurrentGame = true;
528}
529
530/**
531 *  pauses the Game
532*/
533ErrorMessage World::pause()
534{
535  this->isPaused = true;
536}
537
538/**
539 *  ends the pause Phase
540*/
541ErrorMessage World::resume()
542{
543  this->isPaused = false;
544}
545
546/**
547 *  destroys the World
548*/
549ErrorMessage World::destroy()
550{
551
552}
553
554/**
555 *  shows the loading screen
556*/
557void World::displayLoadScreen ()
558{
559  PRINTF(3)("World::displayLoadScreen - start\n");
560
561  //GLMenuImageScreen*
562  this->glmis = new GLMenuImageScreen();
563  this->glmis->setMaximum(8);
564
565  PRINTF(3)("World::displayLoadScreen - end\n");
566}
567
568/**
569 *  removes the loadscreen, and changes over to the game
570
571   @todo take out the delay
572*/
573void World::releaseLoadScreen ()
574{
575  PRINTF(3)("World::releaseLoadScreen - start\n");
576  this->glmis->setValue(this->glmis->getMaximum());
577  PRINTF(3)("World::releaseLoadScreen - end\n");
578  delete this->glmis;
579}
580
581
582/**
583 *  gets the list of entities from the world
584 * @returns entity list
585*/
586tList<WorldEntity>* World::getEntities()
587{
588  return this->entities;
589}
590
591
592/**
593 *  this returns the current game time
594 * @returns elapsed game time
595*/
596double World::getGameTime()
597{
598  return this->gameTime;
599}
600
601
602/**
603 *  function to put your own debug stuff into it. it can display informations about
604   the current class/procedure
605*/
606void World::debug()
607{
608  PRINTF(0)("Printing out the List of alive WorldEntities:\n");
609  tIterator<WorldEntity>* iterator = this->entities->getIterator();
610  WorldEntity* entity = iterator->firstElement();
611  while( entity != NULL)
612  {
613    PRINTF(0)("%s::%s\n", entity->getClassName(), entity->getName());
614    entity = iterator->nextElement();
615  }
616  delete iterator;
617}
618
619
620/**
621  \brief main loop of the world: executing all world relevant function
622
623  in this loop we synchronize (if networked), handle input events, give the heart-beat to
624  all other member-entities of the world (tick to player, enemies etc.), checking for
625  collisions drawing everything to the screen.
626*/
627void World::mainLoop()
628{
629  this->lastFrame = SDL_GetTicks ();
630  PRINTF(3)("World::mainLoop() - Entering main loop\n");
631
632  while( !this->bQuitOrxonox && !this->bQuitCurrentGame) /* @todo implement pause */
633    {
634      ++this->cycle;
635      PRINTF(4)("World::mainloop() - number of entities: %i\n", this->entities->getSize());
636      // Network
637      this->synchronize ();
638      // Process input
639      this->handleInput ();
640      if( this->bQuitCurrentGame || this->bQuitOrxonox)
641          break;
642      // Process time
643      this->tick ();
644      // Process collision
645      this->collide ();
646      // Update the state
647      this->update ();
648      // Draw
649      this->display ();
650    }
651
652  PRINTF(3)("World::mainLoop() - Exiting the main loop\n");
653}
654
655
656/**
657 *  synchronize local data with remote data
658*/
659void World::synchronize ()
660{
661  // Get remote input
662  // Update synchronizables
663/*  NetworkManager::getInstance()->synchronize();*/
664}
665
666
667/**
668 *  run all input processing
669
670   the command node is the central input event dispatcher. the node uses the even-queue from
671   sdl and has its own event-passing-queue.
672*/
673void World::handleInput ()
674{
675  EventHandler::getInstance()->process();
676
677  // remoteinput
678}
679
680
681/**
682 *  advance the timeline
683
684   this calculates the time used to process one frame (with all input handling, drawing, etc)
685   the time is mesured in ms and passed to all world-entities and other classes that need
686   a heart-beat.
687*/
688void World::tick ()
689{
690  Uint32 currentFrame = SDL_GetTicks();
691  if(!this->bPause)
692    {
693      this->dt = currentFrame - this->lastFrame;
694
695      if( this->dt > 10)
696        {
697          float fps = 1000/dt;
698
699          // temporary, only for showing how fast the text-engine is
700          char tmpChar[20];
701          sprintf(tmpChar, "fps: %4.0f", fps);
702        }
703      else
704        {
705          /* the frame-rate is limited to 100 frames per second, all other things are for
706             nothing.
707          */
708          PRINTF(3)("fps = 1000 - frame rate is adjusted\n");
709          SDL_Delay(10-dt);
710          this->dt = 10;
711        }
712
713      this->dtS = (float)this->dt / 1000.0 * this->speed;
714      this->gameTime += this->dtS;
715
716      tIterator<WorldEntity>* iterator = this->entities->getIterator();
717      WorldEntity* entity = iterator->firstElement();
718      while( entity != NULL)
719        {
720          entity->tick (this->dtS);
721          entity = iterator->nextElement();
722        }
723      delete iterator;
724
725      /* update tick the rest */
726      this->localCamera->tick(this->dtS);
727      // tick the engines
728      AnimationPlayer::getInstance()->tick(this->dtS);
729//      if (this->cycle > 5)
730        PhysicsEngine::getInstance()->tick(this->dtS);
731
732      ParticleEngine::getInstance()->tick(this->dtS);
733      GarbageCollector::getInstance()->tick(this->dtS);
734
735
736      /** actualy the Graphics Engine should tick the world not the other way around...
737         but since we like the things not too complicated we got it this way around
738         until there is need or time to do it the other way around.
739         @todo: GraphicsEngine ticks world: separation of processes and data...
740
741        bensch: in my opinion the GraphicsEngine could draw the world, but not tick it,
742         beceause graphics have nothing(or at least not much) to do with Motion.
743      */
744      GraphicsEngine::getInstance()->tick(this->dtS);
745    }
746  this->lastFrame = currentFrame;
747}
748
749
750/**
751 *  this function gives the world a consistant state
752
753   after ticking (updating the world state) this will give a constistant
754   state to the whole system.
755*/
756void World::update()
757{
758  GarbageCollector::getInstance()->update();
759  GraphicsEngine::getInstance()->update(this->dtS);
760  NullParent::getInstance()->updateNode (this->dtS);
761
762  SoundEngine::getInstance()->update();
763  //music->update();
764}
765
766
767void World::collide()
768{
769  CDEngine::getInstance()->checkCollisions();
770}
771
772/**
773 *  render the current frame
774
775   clear all buffers and draw the world
776*/
777void World::display ()
778{
779  // clear buffer
780  glClear( GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
781  // set camera
782  this->localCamera->apply ();
783  // draw world
784  this->draw();
785  // draw HUD
786  /** @todo draw HUD */
787  // flip buffers
788  GraphicsEngine::swapBuffers();
789  //SDL_Surface* screen = Orxonox::getInstance()->getScreen ();
790  //SDL_Flip (screen);
791}
792
793
794/**
795 *  runs through all entities calling their draw() methods
796 */
797void World::draw ()
798{
799  /* draw entities */
800  WorldEntity* entity;
801  glLoadIdentity();
802  tIterator<WorldEntity>* iterator = this->entities->getIterator();
803  entity = iterator->firstElement();
804  while( entity != NULL )
805  {
806    if( entity->isVisible() ) entity->draw();
807    if( unlikely( this->showBV)) entity->drawBVTree(3, 226);  // to draw the bounding boxes of the objects at level 2 for debug purp
808    entity = iterator->nextElement();
809  }
810  delete iterator;
811
812  glCallList (objectList);
813
814  ParticleEngine::getInstance()->draw();
815
816  if (unlikely(this->showPNodes))
817    NullParent::getInstance()->debugDraw(0);
818
819  GraphicsEngine::getInstance()->draw();
820  //TextEngine::getInstance()->draw();
821}
822
823/**
824 *  add and spawn a new entity to this world
825 * @param entity to be added
826*/
827void World::spawn(WorldEntity* entity)
828{
829  this->entities->add (entity);
830  entity->postSpawn ();
831}
832
833
834/**
835 *  add and spawn a new entity to this world
836 * @param entity to be added
837 * @param absCoor At what coordinates to add this entity.
838 * @param absDir In which direction should it look.
839*/
840void World::spawn(WorldEntity* entity, Vector* absCoor, Quaternion* absDir)
841{
842  this->entities->add (entity);
843
844  entity->setAbsCoor (*absCoor);
845  entity->setAbsDir (*absDir);
846
847  entity->postSpawn ();
848}
849
850
851/**
852 *  add and spawn a new entity to this world
853 * @param entity to be added
854 * @param entity to be added to (PNode)
855 * @param At what relative  coordinates to add this entity.
856 * @param In which relative direction should it look.
857*/
858void World::spawn(WorldEntity* entity, PNode* parentNode,
859                  Vector* relCoor, Quaternion* relDir)
860{
861  if( parentNode != NULL)
862    {
863      parentNode->addChild (entity);
864
865      entity->setRelCoor (*relCoor);
866      entity->setRelDir (*relDir);
867
868      this->entities->add (entity);
869
870      entity->postSpawn ();
871    }
872}
873
874void World::setPath( const char* name)
875{
876  if (this->path)
877    delete this->path;
878  if (ResourceManager::isFile(name))
879  {
880    this->path = new char[strlen(name)+1];
881    strcpy(this->path, name);
882  }
883  else
884    {
885      this->path = new char[strlen(ResourceManager::getInstance()->getDataDir()) + strlen(name) +1];
886      sprintf(this->path, "%s%s", ResourceManager::getInstance()->getDataDir(), name);
887    }
888}
889
890const char* World::getPath( void)
891{
892  return path;
893}
Note: See TracBrowser for help on using the repository browser.