/* Copyright (C) 2001-2004 Stephane Magnenat & Luc-Olivier de Charrière for any question or comment contact us at or 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 3 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 "Bullet.h" #include "Game.h" #include "Sector.h" #include "Unit.h" #include "BuildingType.h" #include "GlobalContainer.h" #include #include UnitDeathAnimation::UnitDeathAnimation(int x, int y, Team *team) { this->x = x; this->y = y; this->team = team; this->ticksLeft = globalContainer->deathAnimation->getFrameCount() - 1; } Sector::Sector(Game *game) { this->game=game; this->map=&(game->map); } Sector::~Sector(void) { free(); } void Sector::setGame(Game *game) { free(); this->game=game; this->map=&(game->map); } void Sector::free(void) { for (std::list::iterator it=bullets.begin();it!=bullets.end();it++) delete (*it); bullets.clear(); for (std::list::iterator it=explosions.begin();it!=explosions.end();it++) delete (*it); explosions.clear(); for (std::list::iterator it=deathAnimations.begin();it!=deathAnimations.end();it++) delete (*it); deathAnimations.clear(); game=NULL; map=NULL; } void Sector::save(GAGCore::OutputStream *stream) { stream->writeUint32((Uint32)bullets.size(), "bulletCount"); stream->writeEnterSection("bullets"); unsigned i = 0; for (std::list::iterator it=bullets.begin();it!=bullets.end();it++) { stream->writeEnterSection(i++); (*it)->save(stream); stream->writeLeaveSection(); } stream->writeLeaveSection(); } bool Sector::load(GAGCore::InputStream *stream, Game *game, Sint32 versionMinor) { // destroy all actual bullets free(); // read the number of bullets Uint32 bulletCount = stream->readUint32("bulletCount"); // read all the bullets stream->readEnterSection("bullets"); for (Uint32 i=0; ireadEnterSection(i); bullets.push_front(new Bullet(stream, versionMinor)); stream->readLeaveSection(); } stream->readLeaveSection(); this->game=game; this->map=&(game->map); return true; } void Sector::step(void) { assert(map); assert(game); for (std::list::iterator it=bullets.begin();it!=bullets.end();++it) { Bullet *bullet = (*it); if ( bullet->ticksLeft > 0 ) { bullet->step(); } else { Uint16 gid = map->getGroundUnit(bullet->targetX, bullet->targetY); if(gid == NOGUID) gid = map->getAirUnit(bullet->targetX, bullet->targetY); if (gid != NOGUID) { // we have hit a unit int team = Unit::GIDtoTeam(gid); int id = Unit::GIDtoID(gid); boost::shared_ptr event(new UnitUnderAttackEvent(game->stepCounter, bullet->targetX, bullet->targetY, game->teams[team]->myUnits[id]->typeNum)); game->teams[team]->pushGameEvent(event); if (bullet->revealW > 0 && bullet->revealH > 0) game->map.setMapDiscovered(bullet->revealX, bullet->revealY, bullet->revealW, bullet->revealH, Team::teamNumberToMask(team)); int degats = bullet->shootDamage - game->teams[team]->myUnits[id]->getRealArmor(false); if (degats <= 0) degats = 1; game->teams[team]->myUnits[id]->hp -= degats; } else { Uint16 gid = map->getBuilding(bullet->targetX, bullet->targetY); if (gid != NOGBID) { // we have hit a building int team = Building::GIDtoTeam(gid); int id = Building::GIDtoID(gid); if (bullet->revealW > 0 && bullet->revealH > 0) game->map.setMapDiscovered(bullet->revealX, bullet->revealY, bullet->revealW, bullet->revealH, Team::teamNumberToMask(team)); Building *building = game->teams[team]->myBuildings[id]; int damage = bullet->shootDamage-building->type->armor; boost::shared_ptr event(new BuildingUnderAttackEvent(game->stepCounter, bullet->targetX, bullet->targetY, building->shortTypeNum)); game->teams[team]->pushGameEvent(event); if (damage > 0) building->hp -= damage; else building->hp--; if (building->hp <= 0) building->kill(); } } if (!globalContainer->runNoX) { // create new explosion BulletExplosion *explosion = new BulletExplosion(); explosion->x = bullet->targetX; explosion->y = bullet->targetY; explosion->ticksLeft = globalContainer->bulletExplosion->getFrameCount(); explosions.push_front(explosion); } // remove bullet delete bullet; it = bullets.erase(it); } } // handle explosions timeout for (std::list::iterator it=explosions.begin();it!=explosions.end();++it) { if ( (*it)->ticksLeft > 0 ) { (*it)->ticksLeft--; } else { delete *it; it = explosions.erase(it); } } // handle death animation for (std::list::iterator it=deathAnimations.begin();it!=deathAnimations.end();++it) { if ( (*it)->ticksLeft > 0 ) { (*it)->ticksLeft--; } else { delete *it; it = deathAnimations.erase(it); } } }