/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Patrick Boenzli co-programmer: */ #include "spawning_point.h" #include "util/loading/load_param.h" #include "util/loading/factory.h" #include "world_entity.h" #include "compiler.h" #include "state.h" #include "game_rules.h" #include "shared_network_data.h" /// TODO REMOVE converter.h #include "converter.h" #include "class_id_DEPRECATED.h" ObjectListDefinitionID(SpawningPoint, CL_SPAWNING_POINT); CREATE_FACTORY( SpawningPoint); /** * constructor */ SpawningPoint::SpawningPoint( const TiXmlElement * root ) { this->setAbsCoor( 0, 0, 0 ); this->init(); if (root != NULL) this->loadParams(root); } void SpawningPoint::init() { this->registerObject(this, SpawningPoint::_objectList); PRINTF(0)("Created SpawningPoint\n"); this->teamId = -1; this->localTimer = 0.0f; this->toList( OM_DEAD_TICK ); MessageManager::getInstance()->registerMessageHandler( MSGID_RESPAWN, respawnMessageHandler, NULL ); this->setSynchronized( true ); } /** * deconstructor */ SpawningPoint::~SpawningPoint () {} /** * loads the WorldEntity Specific Parameters. * @param root: the XML-Element to load the Data From */ void SpawningPoint::loadParams(const TiXmlElement* root) { /* let the world entity its stuff first */ WorldEntity::loadParams(root); /* load teamId */ LoadParam(root, "teamId", this, SpawningPoint, setTeamId) .describe("sets teamId"); } /** * pushes a world entity to the spawning queue * @param entity WorldEntity to be added */ void SpawningPoint::pushEntity(Playable* entity, float delay) { QueueEntry qe; qe.entity = entity; qe.respawnTime = this->localTimer + delay; queue.push_back( qe ); } /** * spawn the entity */ void SpawningPoint::spawn(Playable* entity) { bool found = false; for (ObjectList::const_iterator it = Playable::objectList().begin(); it != Playable::objectList().end(); ++it) { if ( *it == entity ) { found = true; break; } } if ( !found ) return; PRINTF(0)("Spawningpoint spawns Entity (%s)\n", entity->getClassCName()); entity->setAbsCoor( this->getAbsCoor() ); entity->setAbsDir( this->getAbsDir() ); //TODO set camera (not smooth) if ( State::getGameRules() ) { (State::getGameRules())->registerSpawn( entity ); } entity->respawn(); } /** * this method is called every frame * @param time: the time in seconds that has passed since the last tick * * Handle all stuff that should update with time inside this method (movement, animation, etc.) */ void SpawningPoint::tick(float dt) { this->localTimer += dt; std::list::iterator it = this->queue.begin(); for( ; it != this->queue.end(); ) { //PRINTF(0)("%f <= %f\n", it->respawnTime, this->localTimer); if( it->respawnTime <= this->localTimer) { //spawn the player this->spawn(it->entity); bool found = false; for (ObjectList::const_iterator it2 = Playable::objectList().begin(); it2 != Playable::objectList().end(); ++it2) { if ( *it2 == it->entity ) { found = true; break; } } if ( found && SharedNetworkData::getInstance()->isMasterServer() /*|| SharedNetworkData::getInstance()->isProxyServerActive()*/) this->sendRespawnMessage( it->entity->getUniqueID() ); std::list::iterator delit = it; it++; queue.erase( delit ); continue; } it++; } } /** * the entity is drawn onto the screen with this function * * This is a central function of an entity: call it to let the entity painted to the screen. * Just override this function with whatever you want to be drawn. */ void SpawningPoint::draw() const {} void SpawningPoint::sendRespawnMessage( int uniqueId ) { byte buf[2*INTSIZE]; assert( Converter::intToByteArray( this->getUniqueID(), buf, INTSIZE ) == INTSIZE ); assert( Converter::intToByteArray( uniqueId, buf + INTSIZE, INTSIZE ) == INTSIZE ); MessageManager::getInstance()->sendMessage( MSGID_RESPAWN, buf, 2*INTSIZE, RT_ALL_BUT_ME, NET_UNASSIGNED, MP_HIGHBANDWIDTH ); } /** * message handler for respawn message */ bool SpawningPoint::respawnMessageHandler( MessageType messageType, byte * data, int dataLength, void * someData, int senderId, int destinationId ) { if ( SharedNetworkData::getInstance()->isMasterServer() /*|| SharedNetworkData::getInstance()->isProxyServerActive()*/) { PRINTF(2)("server received spawn message!\n"); return true; } int spUniqueId; int uniqueId; if ( dataLength != 2*INTSIZE ) { PRINTF(2)("spawn message has wrong size: %d\n", dataLength ); return true; } assert( Converter::byteArrayToInt( data, &spUniqueId ) == INTSIZE ); assert( Converter::byteArrayToInt( data+INTSIZE, &uniqueId ) == INTSIZE ); PRINTF(0)("SPAWNMESSAGE %d\n", uniqueId); SpawningPoint * sp = NULL; Playable * playable = NULL; for (ObjectList::const_iterator it = SpawningPoint::objectList().begin(); it != SpawningPoint::objectList().end(); ++it) { PRINTF(0)("%d:%d\n", (*it)->getUniqueID(), spUniqueId); if ( (*it)->getUniqueID() == spUniqueId ) { sp = (*it); break; } } if ( !sp ) { PRINTF(0)("could not find spawning point\n"); return false; } for (ObjectList::const_iterator it = Playable::objectList().begin(); it != Playable::objectList().end(); ++it) { if ( (*it)->getUniqueID() == uniqueId ) { playable = (*it); break; } } if ( !playable ) { PRINTF(0)("could not find playable\n"); return false; } sp->spawn( playable ); return true; }