/* Copyright (C) 1998 Pyrosoft Inc. (www.pyrosoftgames.com), Matthew Bogue 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 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include "PowerUpInterface.hpp" #include #include "GameConfig.hpp" #include "MapInterface.hpp" #include "PlayerInterface.hpp" #include "BonusUnitPowerUp.hpp" #include "UnitPowerUp.hpp" #include "EnemyRadarPowerUp.hpp" #include "Util/Log.hpp" #include "NetworkState.hpp" #include "Server.hpp" #include "NetworkServer.hpp" #include "PowerUpNetMessage.hpp" PowerUpList PowerUpInterface::powerup_list; int PowerUpInterface::power_up_limit; int PowerUpInterface::power_up_regen_time_upper_bound = 300; int PowerUpInterface::power_up_regen_time_lower_bound = 60; Timer PowerUpInterface::regen_timer; enum { _powerup_bonus_units, _powerup_unit, _powerup_enemy_radar, }; int powerup_probability_table[3] = { _powerup_unit, _powerup_bonus_units, _powerup_enemy_radar }; PowerUpList::PowerUpList() : id_counter(0) { } PowerUpList::~PowerUpList( ) { iterator i; for(i=begin(); i!=end(); i++) { delete *i; } } PowerUp* PowerUpList::find(int ID) { for(iterator i=begin(); i!=end(); i++) { PowerUp* powerup = *i; if(powerup->powerup_state.ID == ID) return powerup; } return( 0 ); } void PowerUpList::addWithID(PowerUp *powerup) { powerup->powerup_state.ID = id_counter++; push_back(powerup); } //----------------------------------------------------------------- void PowerUpInterface::setPowerUpLimits(unsigned long map_size_x, unsigned long map_size_y ) { int active_players; active_players = PlayerInterface::getActivePlayerCount(); int player_factor = int(( 0.10 ) * active_players); int power_up_limit = int( ( 0.0000625 ) * ( (map_size_x * map_size_y) ) ); power_up_limit = power_up_limit + (power_up_limit * player_factor); PowerUpInterface::power_up_limit = power_up_limit; power_up_regen_time_upper_bound = 300; power_up_regen_time_lower_bound = 60; } void PowerUpInterface::generatePowerUp() { unsigned long map_size_x, map_size_y; PowerUp *power_up = 0; float next_regen_interval; PowerUpCreateMesg create_mesg; iXY loc; if( (powerup_list.size() < (size_t) power_up_limit) ) { map_size_x = MapInterface::getWidth(); map_size_y = MapInterface::getHeight(); do { loc.x = rand() % map_size_x; loc.y = rand() % map_size_y; } while( MapInterface::getMovementValue( loc ) == 0xFF ); int prob_table_index; int powerup_type; prob_table_index = rand() % 3; powerup_type = powerup_probability_table[ prob_table_index ]; switch( powerup_type ) { case _powerup_bonus_units : power_up = new BonusUnitPowerUp( loc, powerup_type ); break; case _powerup_unit : power_up = new UnitPowerUp( loc, powerup_type ); break; case _powerup_enemy_radar : power_up = new EnemyRadarPowerUp( loc, powerup_type ); break; default: LOGGER.info("Unknown powerup type?!?"); return; } powerup_list.addWithID(power_up); create_mesg.set( power_up->powerup_state.map_loc, power_up->powerup_state.ID, power_up->powerup_state.type ); SERVER->sendMessage(&create_mesg, sizeof(PowerUpCreateMesg)); do { next_regen_interval = rand() % (power_up_regen_time_upper_bound + 1); } while( next_regen_interval < power_up_regen_time_lower_bound ); regen_timer.changePeriod( next_regen_interval ); setPowerUpLimits( map_size_x, map_size_y ); } } void PowerUpInterface::initialize( void ) { BONUS_POWERUP_ANIM.load( "powerups/Bolt.pak" ); BONUS_POWERUP_ANIM.setFPS( 15 ); BONUS_POWERUP_ANIM_SHADOW.load( "powerups/BoltS.pak" ); UNIT_POWERUP_ANIM.setTo( BONUS_POWERUP_ANIM ); UNIT_POWERUP_ANIM_SHADOW.setTo( BONUS_POWERUP_ANIM_SHADOW ); ENEMY_RADAR_POWERUP_ANIM.setTo( BONUS_POWERUP_ANIM ); ENEMY_RADAR_POWERUP_ANIM_SHADOW.setTo( BONUS_POWERUP_ANIM_SHADOW ); } void PowerUpInterface::resetLogic( void ) { unsigned long map_size_x, map_size_y; if( gameconfig->powerups == false ) { return; } powerup_list.clear(); map_size_x = MapInterface::getWidth(); map_size_y = MapInterface::getHeight(); setPowerUpLimits( map_size_x, map_size_y ); regen_timer.changePeriod( power_up_regen_time_upper_bound ); if ( NetworkState::status == _network_state_server ) { generatePowerUp(); generatePowerUp(); generatePowerUp(); } } void PowerUpInterface::updateState() { if( gameconfig->powerups == false ) { return; } if ( NetworkState::status == _network_state_server ) { if( regen_timer.count() ) { generatePowerUp(); } } for (PowerUpList::iterator i = powerup_list.begin(); i != powerup_list.end(); /* empty */) { PowerUp* powerup = *i; if(powerup->powerup_state.life_cycle_state == _power_up_lifecycle_state_inactive) { delete powerup; i = powerup_list.erase(i); } else { powerup->updateState(); i++; } } } void PowerUpInterface::offloadGraphics( SpriteSorter &sorter ) { if( gameconfig->powerups == false ) { return; } PowerUpList::iterator i; for(i=powerup_list.begin(); i!=powerup_list.end(); i++) { PowerUp* powerup = *i; powerup->offloadGraphics(sorter); } } void PowerUpInterface::netMessagePowerUpCreate(const NetMessage* message) { PowerUp *power_up = 0; PowerUpCreateMesg *create_mesg; create_mesg = (PowerUpCreateMesg *) message; switch( create_mesg->getType() ) { case _powerup_bonus_units : power_up = new BonusUnitPowerUp( iXY(create_mesg->getLocX(), create_mesg->getLocY()), _powerup_bonus_units ); break; case _powerup_unit : power_up = new UnitPowerUp( iXY(create_mesg->getLocX(), create_mesg->getLocY()), _powerup_unit ); break; case _powerup_enemy_radar : power_up = new EnemyRadarPowerUp( iXY(create_mesg->getLocX(), create_mesg->getLocY()), _powerup_enemy_radar); break; default: LOGGER.info("Unknown powerup type?!?"); return; } power_up->powerup_state.ID = create_mesg->getID(); powerup_list.push_back(power_up); } void PowerUpInterface::netMessagePowerUpHit(const NetMessage* message) { PowerUp *power_up; PowerUpHitMesg *hit_mesg; hit_mesg = (PowerUpHitMesg *) message; power_up = powerup_list.find( hit_mesg->getID() ); if (power_up != 0) { power_up->onHit( hit_mesg ); } } void PowerUpInterface::processNetMessages(const NetMessage* message ) { switch(message->message_id) { case _net_message_id_powerup_create: netMessagePowerUpCreate(message); break; case _net_message_id_powerup_hit: netMessagePowerUpHit(message); break; default: LOGGER.warning("Unknown PowerUpMessage type (id %d-%d)", message->message_class, message->message_id); break; } } void PowerUpInterface::syncPowerUps( PlayerID player_id ) { PowerUpList::iterator i; for(i=powerup_list.begin(); i!=powerup_list.end(); i++) { PowerUp* powerup_ptr = *i; PowerUpCreateMesg create_mesg; create_mesg.set( powerup_ptr->powerup_state.map_loc, powerup_ptr->powerup_state.ID, powerup_ptr->powerup_state.type ); SERVER->sendMessage(player_id, &create_mesg, sizeof(PowerUpCreateMesg)); } }