diff --git a/source/glest_game/facilities/auto_test.cpp b/source/glest_game/facilities/auto_test.cpp new file mode 100644 index 000000000..db01799b0 --- /dev/null +++ b/source/glest_game/facilities/auto_test.cpp @@ -0,0 +1,83 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2009 Martiño Figueroa +// +// You can redistribute this code 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 +// ============================================================== + +#include "auto_test.h" + +#include "program.h" +#include "main_menu.h" +#include "menu_state_new_game.h" +#include "menu_state_scenario.h" +#include "game.h" + +#include "leak_dumper.h" +#include "config.h" + +namespace Glest{ namespace Game{ + +// ===================================================== +// class AutoTest +// ===================================================== + +const time_t AutoTest::invalidTime = -1; +const time_t AutoTest::gameTime = 60*20; + +// ===================== PUBLIC ======================== + +AutoTest::AutoTest(){ + gameStartTime = invalidTime; + random.init(time(NULL)); +} + +AutoTest & AutoTest::getInstance(){ + static AutoTest autoTest; + return autoTest; +} + +void AutoTest::updateIntro(Program *program){ + program->setState(new MainMenu(program)); +} + +void AutoTest::updateRoot(Program *program, MainMenu *mainMenu){ + mainMenu->setState(new MenuStateNewGame(program, mainMenu)); +} + +void AutoTest::updateNewGame(Program *program, MainMenu *mainMenu){ + mainMenu->setState(new MenuStateScenario(program, mainMenu, Config::getInstance().getPathListForType(ptScenarios))); +} + +void AutoTest::updateScenario(MenuStateScenario *menuStateScenario){ + gameStartTime = invalidTime; + + int scenarioIndex = random.randRange(0, menuStateScenario->getScenarioCount()-1); + menuStateScenario->setScenario(scenarioIndex); + + menuStateScenario->launchGame(); +} + +void AutoTest::updateGame(Game *game){ + + // record start time + if(gameStartTime==invalidTime) + { + gameStartTime = time(NULL); + } + + // quit if we've espend enough time in the game + if(time(NULL)-gameStartTime>gameTime){ + game->quitGame(); + } +} + +void AutoTest::updateBattleEnd(Program *program){ + program->setState(new MainMenu(program)); +} + +}}//end namespace diff --git a/source/glest_game/game/commander.cpp b/source/glest_game/game/commander.cpp new file mode 100644 index 000000000..fbd4a2fda --- /dev/null +++ b/source/glest_game/game/commander.cpp @@ -0,0 +1,380 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2008 Martiño Figueroa +// +// You can redistribute this code 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 +// ============================================================== + +#include "commander.h" + +#include "world.h" +#include "unit.h" +#include "conversion.h" +#include "upgrade.h" +#include "command.h" +#include "command_type.h" +#include "network_manager.h" +#include "console.h" +#include "config.h" +#include "platform_util.h" +#include "leak_dumper.h" +#include "game.h" + +using namespace Shared::Graphics; +using namespace Shared::Util; +using namespace Shared::Platform; + +namespace Glest{ namespace Game{ + +// ===================================================== +// class Commander +// ===================================================== + +// ===================== PUBLIC ======================== + +void Commander::init(World *world){ + this->world= world; +} + +CommandResult Commander::tryGiveCommand(const Unit* unit, const CommandType *commandType, const Vec2i &pos, const UnitType* unitType) const{ + NetworkCommand networkCommand(nctGiveCommand, unit->getId(), commandType->getId(), pos, unitType->getId()); + return pushNetworkCommand(&networkCommand); +} + +CommandResult Commander::tryGiveCommand(const Selection *selection, CommandClass commandClass, const Vec2i &pos, const Unit *targetUnit) const{ + + if(!selection->isEmpty()){ + Vec2i refPos, currPos; + CommandResultContainer results; + + refPos= computeRefPos(selection); + + //give orders to all selected units + for(int i=0; igetCount(); ++i){ + const Unit *unit= selection->getUnit(i); + const CommandType *ct= unit->getType()->getFirstCtOfClass(commandClass); + if(ct!=NULL){ + int targetId= targetUnit==NULL? Unit::invalidId: targetUnit->getId(); + int unitId= selection->getUnit(i)->getId(); + Vec2i currPos= computeDestPos(refPos, selection->getUnit(i)->getPos(), pos); + NetworkCommand networkCommand(nctGiveCommand, unitId, ct->getId(), currPos, -1, targetId); + + //every unit is ordered to a different pos + CommandResult result= pushNetworkCommand(&networkCommand); + results.push_back(result); + } + else{ + results.push_back(crFailUndefined); + } + } + return computeResult(results); + } + else{ + return crFailUndefined; + } +} + +CommandResult Commander::tryGiveCommand(const Selection *selection, const CommandType *commandType, const Vec2i &pos, const Unit *targetUnit) const{ + if(!selection->isEmpty() && commandType!=NULL){ + Vec2i refPos; + CommandResultContainer results; + + refPos= computeRefPos(selection); + + //give orders to all selected units + for(int i=0; igetCount(); ++i){ + int targetId= targetUnit==NULL? Unit::invalidId: targetUnit->getId(); + int unitId= selection->getUnit(i)->getId(); + Vec2i currPos= computeDestPos(refPos, selection->getUnit(i)->getPos(), pos); + NetworkCommand networkCommand(nctGiveCommand, unitId, commandType->getId(), currPos, -1, targetId); + + //every unit is ordered to a different position + CommandResult result= pushNetworkCommand(&networkCommand); + results.push_back(result); + } + + return computeResult(results); + } + else{ + return crFailUndefined; + } +} + +//auto command +CommandResult Commander::tryGiveCommand(const Selection *selection, const Vec2i &pos, const Unit *targetUnit) const{ + if(!selection->isEmpty()){ + + Vec2i refPos, currPos; + CommandResultContainer results; + + //give orders to all selected units + refPos= computeRefPos(selection); + for(int i=0; igetCount(); ++i){ + + //every unit is ordered to a different pos + currPos= computeDestPos(refPos, selection->getUnit(i)->getPos(), pos); + + //get command type + const CommandType *commandType= selection->getUnit(i)->computeCommandType(pos, targetUnit); + + //give commands + if(commandType!=NULL){ + int targetId= targetUnit==NULL? Unit::invalidId: targetUnit->getId(); + int unitId= selection->getUnit(i)->getId(); + NetworkCommand networkCommand(nctGiveCommand, unitId, commandType->getId(), currPos, -1, targetId); + + CommandResult result= pushNetworkCommand(&networkCommand); + results.push_back(result); + } + else{ + results.push_back(crFailUndefined); + } + } + return computeResult(results); + } + else{ + return crFailUndefined; + } +} + +CommandResult Commander::tryCancelCommand(const Selection *selection) const{ + + for(int i=0; igetCount(); ++i){ + NetworkCommand command(nctCancelCommand, selection->getUnit(i)->getId()); + pushNetworkCommand(&command); + } + + return crSuccess; +} + +void Commander::trySetMeetingPoint(const Unit* unit, const Vec2i &pos)const{ + NetworkCommand command(nctSetMeetingPoint, unit->getId(), -1, pos); + pushNetworkCommand(&command); +} + + +// ==================== PRIVATE ==================== + +Vec2i Commander::computeRefPos(const Selection *selection) const{ + Vec2i total= Vec2i(0); + for(int i=0; igetCount(); ++i){ + total= total+selection->getUnit(i)->getPos(); + } + + return Vec2i(total.x/ selection->getCount(), total.y/ selection->getCount()); +} + +Vec2i Commander::computeDestPos(const Vec2i &refUnitPos, const Vec2i &unitPos, const Vec2i &commandPos) const{ + Vec2i pos; + Vec2i posDiff= unitPos-refUnitPos; + + if(abs(posDiff.x)>=3){ + posDiff.x= posDiff.x % 3; + } + + if(abs(posDiff.y)>=3){ + posDiff.y= posDiff.y % 3; + } + + pos= commandPos+posDiff; + world->getMap()->clampPos(pos); + return pos; +} + +CommandResult Commander::computeResult(const CommandResultContainer &results) const{ + switch(results.size()){ + case 0: + return crFailUndefined; + case 1: + return results.front(); + default: + for(int i=0; ifindUnitById(networkCommand->getUnitId()); + CommandResult cr= crSuccess; + + //validate unit + if(unit==NULL){ + char szBuf[1024]=""; + sprintf(szBuf,"In [%s::%s - %d] Command refers to non existant unit id = %d. Game out of synch.", + __FILE__,__FUNCTION__,__LINE__,networkCommand->getUnitId()); + throw runtime_error(szBuf); + } + + //add the command to the interface + gameNetworkInterface->requestCommand(networkCommand); + + //calculate the result of the command + if(networkCommand->getNetworkCommandType()==nctGiveCommand){ + Command* command= buildCommand(networkCommand); + cr= unit->checkCommand(command); + delete command; + } + return cr; +} + +void Commander::updateNetwork(){ + NetworkManager &networkManager= NetworkManager::getInstance(); + + //chech that this is a keyframe + if( !networkManager.isNetworkGame() || (world->getFrameCount() % GameConstants::networkFramePeriod)==0){ + + GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface(); + + //update the keyframe + gameNetworkInterface->updateKeyframe(world->getFrameCount()); + + //give pending commands + for(int i= 0; i < gameNetworkInterface->getPendingCommandCount(); ++i){ + giveNetworkCommand(gameNetworkInterface->getPendingCommand(i)); + } + gameNetworkInterface->clearPendingCommands(); + } +} + +void Commander::giveNetworkCommandSpecial(const NetworkCommand* networkCommand) const { + switch(networkCommand->getNetworkCommandType()) { + case nctNetworkCommand: { + if(Socket::enableDebugText) printf("In [%s::%s Line: %d] found nctNetworkCommand\n",__FILE__,__FUNCTION__,__LINE__); + switch(networkCommand->getCommandTypeId()) { + case ncstRotateUnit: { + if(Socket::enableDebugText) printf("In [%s::%s Line: %d] found ncstRotateUnit [%d]\n",__FILE__,__FUNCTION__,__LINE__,networkCommand->getTargetId()); + + //!!! + int unitTypeId = networkCommand->getUnitId(); + int factionIndex = networkCommand->getUnitTypeId(); + int rotateAmount = networkCommand->getTargetId(); + + //const Faction *faction = world->getFaction(factionIndex); + //const UnitType* unitType= world->findUnitTypeById(faction->getType(), factionIndex); + + char unitKey[50]=""; + sprintf(unitKey,"%d_%d",unitTypeId,factionIndex); + + if(Socket::enableDebugText) printf("In [%s::%s Line: %d] unitKey = [%s]\n",__FILE__,__FUNCTION__,__LINE__,unitKey); + + Game *game = this->world->getGame(); + Gui *gui = game->getGui(); + gui->setUnitTypeBuildRotation(unitKey,rotateAmount); + //unit->setRotateAmount(networkCommand->getTargetId()); + + if(Socket::enableDebugText) printf("In [%s::%s Line: %d] found ncstRotateUnit [%d]\n",__FILE__,__FUNCTION__,__LINE__,networkCommand->getTargetId()); + } + break; + } + if(Socket::enableDebugText) printf("In [%s::%s Line: %d] found nctNetworkCommand\n",__FILE__,__FUNCTION__,__LINE__); + } + break; + default: + assert(false); + } +} + +void Commander::giveNetworkCommand(const NetworkCommand* networkCommand) const { + + if(networkCommand->getNetworkCommandType() == nctNetworkCommand) { + giveNetworkCommandSpecial(networkCommand); + } + else { + Unit* unit= world->findUnitById(networkCommand->getUnitId()); + + //exec ute command, if unit is still alive + if(unit!=NULL) { + switch(networkCommand->getNetworkCommandType()){ + case nctGiveCommand:{ + assert(networkCommand->getCommandTypeId()!=CommandType::invalidId); + + if(Socket::enableDebugText) printf("In [%s::%s Line: %d] found nctGiveCommand networkCommand->getUnitId() = %d\n",__FILE__,__FUNCTION__,__LINE__,networkCommand->getUnitId()); + + Command* command= buildCommand(networkCommand); + unit->giveCommand(command); + + if(Socket::enableDebugText) printf("In [%s::%s Line: %d] found nctGiveCommand networkCommand->getUnitId() = %d\n",__FILE__,__FUNCTION__,__LINE__,networkCommand->getUnitId()); + } + break; + case nctCancelCommand: { + if(Socket::enableDebugText) printf("In [%s::%s Line: %d] found nctCancelCommand\n",__FILE__,__FUNCTION__,__LINE__); + unit->cancelCommand(); + if(Socket::enableDebugText) printf("In [%s::%s Line: %d] found nctCancelCommand\n",__FILE__,__FUNCTION__,__LINE__); + } + break; + case nctSetMeetingPoint: { + if(Socket::enableDebugText) printf("In [%s::%s Line: %d] found nctSetMeetingPoint\n",__FILE__,__FUNCTION__,__LINE__); + unit->setMeetingPos(networkCommand->getPosition()); + if(Socket::enableDebugText) printf("In [%s::%s Line: %d] found nctSetMeetingPoint\n",__FILE__,__FUNCTION__,__LINE__); + } + break; + default: + assert(false); + } + } + else { + if(Socket::enableDebugText) printf("In [%s::%s Line: %d] NULL Unit for id = %d, networkCommand->getNetworkCommandType() = %d\n",__FILE__,__FUNCTION__,__LINE__,networkCommand->getUnitId(),networkCommand->getNetworkCommandType()); + } + } +} + +Command* Commander::buildCommand(const NetworkCommand* networkCommand) const{ + assert(networkCommand->getNetworkCommandType()==nctGiveCommand); + + Unit* target= NULL; + const CommandType* ct= NULL; + const Unit* unit= world->findUnitById(networkCommand->getUnitId()); + + //validate unit + if(unit == NULL) { + char szBuf[1024]=""; + sprintf(szBuf,"In [%s::%s - %d] Can not find unit with id: %d. Game out of synch.", + __FILE__,__FUNCTION__,__LINE__,networkCommand->getUnitId()); + + throw runtime_error(szBuf); + } + + const UnitType* unitType= world->findUnitTypeById(unit->getFaction()->getType(), networkCommand->getUnitTypeId()); + ct= unit->getType()->findCommandTypeById(networkCommand->getCommandTypeId()); + + //validate command type + if(ct == NULL) { + + char szBuf[1024]=""; + sprintf(szBuf,"In [%s::%s - %d] Can not find command type with id = %d in unit = %d [%s]. Game out of synch.", + __FILE__,__FUNCTION__,__LINE__,networkCommand->getCommandTypeId(),unit->getId(), unit->getDesc().c_str()); + + throw runtime_error(szBuf); + } + + //get target, the target might be dead due to lag, cope with it + if(networkCommand->getTargetId()!=Unit::invalidId){ + target= world->findUnitById(networkCommand->getTargetId()); + } + + //create command + Command *command= NULL; + if(unitType!=NULL){ + command= new Command(ct, networkCommand->getPosition(), unitType); + } + else if(target==NULL){ + command= new Command(ct, networkCommand->getPosition()); + } + else{ + command= new Command(ct, target); + } + + //issue command + return command; +} + +}}//end namespace diff --git a/source/glest_game/game/commander.h b/source/glest_game/game/commander.h new file mode 100644 index 000000000..b719f7948 --- /dev/null +++ b/source/glest_game/game/commander.h @@ -0,0 +1,69 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2008 Martiño Figueroa +// +// You can redistribute this code 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 +// ============================================================== + +#ifndef _GLEST_GAME_COMMANDER_H_ +#define _GLEST_GAME_COMMANDER_H_ + +#include + +#include "vec.h" +#include "selection.h" +#include "command_type.h" + +using std::vector; + +namespace Glest{ namespace Game{ + +using Shared::Graphics::Vec2i; + +class World; +class Unit; +class Command; +class CommandType; +class NetworkCommand; + +// ===================================================== +// class Commander +// +/// Gives commands to the units +// ===================================================== + +class Commander{ +private: + typedef vector CommandResultContainer; + +private: + World *world; + +public: + void init(World *world); + void updateNetwork(); + + CommandResult tryGiveCommand(const Unit* unit, const CommandType *commandType, const Vec2i &pos, const UnitType* unitType) const; + CommandResult tryGiveCommand(const Selection *selection, CommandClass commandClass, const Vec2i &pos= Vec2i(0), const Unit *targetUnit= NULL) const; + CommandResult tryGiveCommand(const Selection *selection, const CommandType *commandType, const Vec2i &pos= Vec2i(0), const Unit *targetUnit= NULL) const; + CommandResult tryGiveCommand(const Selection *selection, const Vec2i &pos, const Unit *targetUnit= NULL) const; + CommandResult tryCancelCommand(const Selection *selection) const; + void trySetMeetingPoint(const Unit* unit, const Vec2i &pos) const; + CommandResult pushNetworkCommand(const NetworkCommand* networkCommand) const; + void giveNetworkCommandSpecial(const NetworkCommand* networkCommand) const; + +private: + Vec2i computeRefPos(const Selection *selection) const; + Vec2i computeDestPos(const Vec2i &refUnitPos, const Vec2i &unitPos, const Vec2i &commandPos) const; + CommandResult computeResult(const CommandResultContainer &results) const; + void giveNetworkCommand(const NetworkCommand* networkCommand) const; + Command* buildCommand(const NetworkCommand* networkCommand) const; +}; + +}} //end namespace + +#endif diff --git a/source/glest_game/game/game.cpp b/source/glest_game/game/game.cpp index 8145a6da7..5bc21e628 100644 --- a/source/glest_game/game/game.cpp +++ b/source/glest_game/game/game.cpp @@ -93,8 +93,10 @@ void Game::load(){ logger.setSubtitle(formatString(scenarioName)); } + Config &config = Config::getInstance(); + //tileset - world.loadTileset("tilesets/"+tilesetName, &checksum); + world.loadTileset(config.getPathListForType(ptTilesets), tilesetName, &checksum); set factions; for ( int i=0; i < gameSettings.getFactionCount(); ++i ) { @@ -102,7 +104,7 @@ void Game::load(){ } //tech, load before map because of resources - world.loadTech("techs/"+techName, factions, &checksum); + world.loadTech(config.getPathListForType(ptTechs), techName, factions, &checksum); //map world.loadMap(Map::getMapPath(mapName), &checksum); @@ -110,7 +112,7 @@ void Game::load(){ //scenario if(!scenarioName.empty()){ Lang::getInstance().loadScenarioStrings(gameSettings.getScenarioDir(), scenarioName); - world.loadScenario(Scenario::getScenarioPath(gameSettings.getScenarioDir(), scenarioName), &checksum); + world.loadScenario(gameSettings.getScenarioDir(), &checksum); } } diff --git a/source/glest_game/graphics/renderer.cpp b/source/glest_game/graphics/renderer.cpp index 2fb6f4d95..e962737ea 100644 --- a/source/glest_game/graphics/renderer.cpp +++ b/source/glest_game/graphics/renderer.cpp @@ -1369,7 +1369,7 @@ void Renderer::renderUnits(){ //!!! if(allowRotateUnits == true) { float rotateAmount = unit->getRotateAmount(); - if(rotateAmount >= 0) { + if(rotateAmount > 0) { //if(Socket::enableDebugText) printf("In [%s::%s] rotate unit id = %d amount = %f\n",__FILE__,__FUNCTION__,unit->getId(),rotateAmount); glRotatef(rotateAmount, 0.f, 1.f, 0.f); } diff --git a/source/glest_game/gui/gui.cpp b/source/glest_game/gui/gui.cpp index 65adda3ad..221437af4 100644 --- a/source/glest_game/gui/gui.cpp +++ b/source/glest_game/gui/gui.cpp @@ -28,6 +28,10 @@ #include "faction.h" #include "leak_dumper.h" +#include "network_types.h" +#include "network_manager.h" + + using namespace Shared::Graphics; using namespace Shared::Util; @@ -311,6 +315,10 @@ void Gui::groupKey(int groupIndex){ } } +void Gui::setUnitTypeBuildRotation(string unitKey, float value) { + unitTypeBuildRotation[unitKey] = value; +} + float Gui::getUnitTypeBuildRotation(string unitKey) const { float rotationValue = -1; @@ -335,7 +343,7 @@ void Gui::hotKey(char key){ selectInterestingUnit(iutBuiltBuilding); } else if(key=='R'){ - //!!! + // Here the user triggers a unit rotation while placing a unit if(allowRotateUnits == true && isPlacingBuilding()) { const UnitType *unitType = getBuilding(); int factionIndex = world->getThisFactionIndex(); @@ -354,6 +362,20 @@ void Gui::hotKey(char key){ } unitTypeBuildRotation[unitKey] = unitTypeRotation; + //!!! + //if(allowRotateUnits == true && unitRotation > 0) { + if(Socket::enableDebugText) printf("In [%s::%s] before sending nctNetworkCommand RotateUnit unitTypeid = %d, factionIndex = %d, unitTypeRotation = %f\n",__FILE__,__FUNCTION__,unitType->getId(),factionIndex,unitTypeRotation); + + //unitRotation = 0; + NetworkCommand networkCommand(nctNetworkCommand, ncstRotateUnit, unitType->getId(), factionIndex, (int)unitTypeRotation); + //CommandResult result= game->getCommander()->pushNetworkCommand(&networkCommand); + GameNetworkInterface *gameNetworkInterface= NetworkManager::getInstance().getGameNetworkInterface(); + gameNetworkInterface->requestCommand(&networkCommand); + + //if(Socket::enableDebugText) printf("In [%s::%s] after sending nctNetworkCommand RotateUnit [%d] result = %d\n",__FILE__,__FUNCTION__,builtUnit->getId(),result); + if(Socket::enableDebugText) printf("In [%s::%s] after sending nctNetworkCommand RotateUnit unitTypeid = %d, factionIndex = %d, unitTypeRotation = %f\n",__FILE__,__FUNCTION__,unitType->getId(),factionIndex,unitTypeRotation); + //} + if(Socket::enableDebugText) printf("In [%s::%s] unitType->getId() = %d NEW unitTypeRotation = %f\n",__FILE__,__FUNCTION__,unitType->getId(),unitTypeRotation); } else { diff --git a/source/glest_game/gui/gui.h b/source/glest_game/gui/gui.h index 708063905..909397e3a 100644 --- a/source/glest_game/gui/gui.h +++ b/source/glest_game/gui/gui.h @@ -176,6 +176,7 @@ public: void onSelectionChanged(); float getUnitTypeBuildRotation(string unitKey) const; + void setUnitTypeBuildRotation(string unitKey, float value); private: diff --git a/source/glest_game/menu/menu_state_custom_game.cpp b/source/glest_game/menu/menu_state_custom_game.cpp index 81bede301..21120a922 100644 --- a/source/glest_game/menu/menu_state_custom_game.cpp +++ b/source/glest_game/menu/menu_state_custom_game.cpp @@ -51,8 +51,9 @@ MenuStateCustomGame::MenuStateCustomGame(Program *program, MainMenu *mainMenu, b buttonPlayNow.init(525, 180, 125); //map listBox - findAll("maps/*.gbm", glestMaps, true, true); - findAll("maps/*.mgm", megaMaps, true, false); + Config &config = Config::getInstance(); + findAll(config.getPathListForType(ptMaps), "*.gbm", glestMaps, true, false); + findAll(config.getPathListForType(ptMaps), "*.mgm", megaMaps, true, false); mapFiles.resize(glestMaps.size() + megaMaps.size()); if (!glestMaps.empty()) { @@ -74,8 +75,8 @@ MenuStateCustomGame::MenuStateCustomGame(Program *program, MainMenu *mainMenu, b labelMapInfo.init(200, 230, 200, 40); //tileset listBox - findAll("tilesets/*.", results); - if(results.size()==0){ + findDirs(config.getPathListForType(ptTilesets), results); + if(results.size() == 0) { throw runtime_error("There is no tile set"); } tilesetFiles= results; @@ -87,9 +88,9 @@ MenuStateCustomGame::MenuStateCustomGame(Program *program, MainMenu *mainMenu, b labelTileset.init(400, 290); //tech Tree listBox - findAll("techs/*.", results); - if(results.size()==0){ - throw runtime_error("There is no tech tree"); + findDirs(config.getPathListForType(ptTechs), results); + if(results.size() == 0) { + throw runtime_error("There are no tech trees"); } techTreeFiles= results; for(int i= 0; i techPaths = config.getPathListForType(ptTechs); + for(int idx = 0; idx < techPaths.size(); idx++) { + string &techPath = techPaths[idx]; + findAll(techPath + "/" + techTreeFiles[listBoxTechTree.getSelectedItemIndex()] + "/factions/*.", results, false, false); + + if(results.size() > 0) { + break; + } + } + + if(results.size() == 0) { throw runtime_error("There is no factions for this tech tree"); - } + } for(int i=0; i results; - findAll("techs/"+techTreeFiles[listBoxTechTree.getSelectedItemIndex()]+"/factions/*.", results); - if(results.size()==0){ - throw runtime_error("There is no factions for this tech tree"); - } - factionFiles= results; - for(int i= 0; i techPaths = config.getPathListForType(ptTechs); + for(int idx = 0; idx < techPaths.size(); idx++) { + string &techPath = techPaths[idx]; + + findAll(techPath + "/" + techTreeFiles[listBoxTechTree.getSelectedItemIndex()] + "/factions/*.", results, false, false); + if(results.size() > 0) { + break; + } } + + if(results.size() == 0) { + throw runtime_error("There is no factions for this tech tree"); + } + factionFiles= results; + for(int i= 0; isetState(new MenuStateCustomGame(program, mainMenu)); + } + else if(buttonScenario.mouseClick(x, y)){ + soundRenderer.playFx(coreData.getClickSoundB()); + mainMenu->setState(new MenuStateScenario(program, mainMenu, Config::getInstance().getPathListForType(ptScenarios))); + } + else if(buttonTutorial.mouseClick(x, y)){ + soundRenderer.playFx(coreData.getClickSoundB()); + mainMenu->setState(new MenuStateScenario(program, mainMenu, Config::getInstance().getPathListForType(ptTutorials))); + } + else if(buttonReturn.mouseClick(x, y)){ + soundRenderer.playFx(coreData.getClickSoundB()); + mainMenu->setState(new MenuStateRoot(program, mainMenu)); + } +} + +void MenuStateNewGame::mouseMove(int x, int y, const MouseState *ms){ + buttonCustomGame.mouseMove(x, y); + buttonScenario.mouseMove(x, y); + buttonTutorial.mouseMove(x, y); + buttonReturn.mouseMove(x, y); +} + +void MenuStateNewGame::render(){ + Renderer &renderer= Renderer::getInstance(); + + renderer.renderButton(&buttonCustomGame); + renderer.renderButton(&buttonScenario); + renderer.renderButton(&buttonTutorial); + renderer.renderButton(&buttonReturn); +} + +void MenuStateNewGame::update(){ + if(Config::getInstance().getBool("AutoTest")){ + AutoTest::getInstance().updateNewGame(program, mainMenu); + } +} + +}}//end namespace diff --git a/source/glest_game/menu/menu_state_scenario.cpp b/source/glest_game/menu/menu_state_scenario.cpp new file mode 100644 index 000000000..f144dd202 --- /dev/null +++ b/source/glest_game/menu/menu_state_scenario.cpp @@ -0,0 +1,257 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2005 Marti�o Figueroa +// +// You can redistribute this code 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 +// ============================================================== + +#include "menu_state_scenario.h" + +#include "renderer.h" +#include "menu_state_new_game.h" +#include "sound_renderer.h" +#include "core_data.h" +#include "menu_state_options.h" +#include "network_manager.h" +#include "config.h" +#include "auto_test.h" +#include "game.h" + +#include "leak_dumper.h" + +namespace Glest{ namespace Game{ + +using namespace Shared::Xml; + +// ===================================================== +// class MenuStateScenario +// ===================================================== + +MenuStateScenario::MenuStateScenario(Program *program, MainMenu *mainMenu, const vector &dirList): + MenuState(program, mainMenu, "scenario") +{ + Lang &lang= Lang::getInstance(); + NetworkManager &networkManager= NetworkManager::getInstance(); + vector results; + + this->dirList = dirList; + + labelInfo.init(350, 350); + labelInfo.setFont(CoreData::getInstance().getMenuFontNormal()); + + buttonReturn.init(350, 200, 125); + buttonPlayNow.init(525, 200, 125); + + listBoxScenario.init(350, 400, 190); + labelScenario.init(350, 430); + + buttonReturn.setText(lang.get("Return")); + buttonPlayNow.setText(lang.get("PlayNow")); + + labelScenario.setText(lang.get("Scenario")); + + //scenario listbox + findDirs(dirList, results); + scenarioFiles = results; + if(results.size() == 0) { + throw runtime_error("There are no scenarios"); + } + for(int i= 0; isetState(new MenuStateNewGame(program, mainMenu)); + } + else if(buttonPlayNow.mouseClick(x,y)){ + soundRenderer.playFx(coreData.getClickSoundC()); + launchGame(); + } + else if(listBoxScenario.mouseClick(x, y)){ + loadScenarioInfo(Scenario::getScenarioPath(dirList, scenarioFiles[listBoxScenario.getSelectedItemIndex()]), &scenarioInfo); + labelInfo.setText(scenarioInfo.desc); + } +} + +void MenuStateScenario::mouseMove(int x, int y, const MouseState *ms){ + + listBoxScenario.mouseMove(x, y); + + buttonReturn.mouseMove(x, y); + buttonPlayNow.mouseMove(x, y); +} + +void MenuStateScenario::render(){ + + Renderer &renderer= Renderer::getInstance(); + + renderer.renderLabel(&labelInfo); + renderer.renderLabel(&labelScenario); + renderer.renderListBox(&listBoxScenario); + + renderer.renderButton(&buttonReturn); + renderer.renderButton(&buttonPlayNow); +} + +void MenuStateScenario::update(){ + if(Config::getInstance().getBool("AutoTest")){ + AutoTest::getInstance().updateScenario(this); + } +} + +void MenuStateScenario::launchGame(){ + GameSettings gameSettings; + loadGameSettings(&scenarioInfo, &gameSettings); + program->setState(new Game(program, &gameSettings)); +} + +void MenuStateScenario::setScenario(int i){ + listBoxScenario.setSelectedItemIndex(i); + loadScenarioInfo(Scenario::getScenarioPath(dirList, scenarioFiles[listBoxScenario.getSelectedItemIndex()]), &scenarioInfo); +} + +void MenuStateScenario::loadScenarioInfo(string file, ScenarioInfo *scenarioInfo){ + + Lang &lang= Lang::getInstance(); + + XmlTree xmlTree; + xmlTree.load(file); + + const XmlNode *scenarioNode= xmlTree.getRootNode(); + const XmlNode *difficultyNode= scenarioNode->getChild("difficulty"); + scenarioInfo->difficulty = difficultyNode->getAttribute("value")->getIntValue(); + if( scenarioInfo->difficulty < dVeryEasy || scenarioInfo->difficulty > dInsane ) + { + throw std::runtime_error("Invalid difficulty"); + } + + const XmlNode *playersNode= scenarioNode->getChild("players"); + + for(int i= 0; ihasChildAtIndex("player",i)){ + playerNode = playersNode->getChild("player", i); + factionControl = strToControllerType( playerNode->getAttribute("control")->getValue() ); + } + else{ + factionControl=ctClosed; + } + + scenarioInfo->factionControls[i] = factionControl; + + if(factionControl != ctClosed){ + int teamIndex = playerNode->getAttribute("team")->getIntValue(); + + if( teamIndex < 1 || teamIndex > GameConstants::maxPlayers ) + { + throw runtime_error("Team out of range: " + intToStr(teamIndex) ); + } + + scenarioInfo->teams[i]= playerNode->getAttribute("team")->getIntValue(); + scenarioInfo->factionTypeNames[i]= playerNode->getAttribute("faction")->getValue(); + } + + scenarioInfo->mapName = scenarioNode->getChild("map")->getAttribute("value")->getValue(); + scenarioInfo->tilesetName = scenarioNode->getChild("tileset")->getAttribute("value")->getValue(); + scenarioInfo->techTreeName = scenarioNode->getChild("tech-tree")->getAttribute("value")->getValue(); + scenarioInfo->defaultUnits = scenarioNode->getChild("default-units")->getAttribute("value")->getBoolValue(); + scenarioInfo->defaultResources = scenarioNode->getChild("default-resources")->getAttribute("value")->getBoolValue(); + scenarioInfo->defaultVictoryConditions = scenarioNode->getChild("default-victory-conditions")->getAttribute("value")->getBoolValue(); + } + + //add player info + scenarioInfo->desc= lang.get("Player") + ": "; + for(int i=0; ifactionControls[i] == ctHuman ) + { + scenarioInfo->desc+= formatString(scenarioInfo->factionTypeNames[i]); + break; + } + } + + //add misc info + string difficultyString = "Difficulty" + intToStr(scenarioInfo->difficulty); + + scenarioInfo->desc+= "\n"; + scenarioInfo->desc+= lang.get("Difficulty") + ": " + lang.get(difficultyString) +"\n"; + scenarioInfo->desc+= lang.get("Map") + ": " + formatString(scenarioInfo->mapName) + "\n"; + scenarioInfo->desc+= lang.get("Tileset") + ": " + formatString(scenarioInfo->tilesetName) + "\n"; + scenarioInfo->desc+= lang.get("TechTree") + ": " + formatString(scenarioInfo->techTreeName) + "\n"; +} + +void MenuStateScenario::loadGameSettings(const ScenarioInfo *scenarioInfo, GameSettings *gameSettings){ + + int factionCount= 0; + + gameSettings->setDescription(formatString(scenarioFiles[listBoxScenario.getSelectedItemIndex()])); + gameSettings->setMap(scenarioInfo->mapName); + gameSettings->setTileset(scenarioInfo->tilesetName); + gameSettings->setTech(scenarioInfo->techTreeName); + gameSettings->setScenario(scenarioFiles[listBoxScenario.getSelectedItemIndex()]); + gameSettings->setScenarioDir(Scenario::getScenarioPath(dirList, scenarioFiles[listBoxScenario.getSelectedItemIndex()])); + gameSettings->setDefaultUnits(scenarioInfo->defaultUnits); + gameSettings->setDefaultResources(scenarioInfo->defaultResources); + gameSettings->setDefaultVictoryConditions(scenarioInfo->defaultVictoryConditions); + + for(int i=0; i(scenarioInfo->factionControls[i]); + if(ct!=ctClosed){ + if(ct==ctHuman){ + gameSettings->setThisFactionIndex(factionCount); + } + gameSettings->setFactionControl(factionCount, ct); + gameSettings->setTeam(factionCount, scenarioInfo->teams[i]-1); + gameSettings->setStartLocationIndex(factionCount, i); + gameSettings->setFactionTypeName(factionCount, scenarioInfo->factionTypeNames[i]); + factionCount++; + } + } + + gameSettings->setFactionCount(factionCount); +} + +ControlType MenuStateScenario::strToControllerType(const string &str){ + if(str=="closed"){ + return ctClosed; + } + else if(str=="cpu-easy"){ + return ctCpuEasy; + } + else if(str=="cpu"){ + return ctCpu; + } + else if(str=="cpu-ultra"){ + return ctCpuUltra; + } + else if(str=="cpu-mega"){ + return ctCpuMega; + } + else if(str=="human"){ + return ctHuman; + } + + throw std::runtime_error("Unknown controller type: " + str); +} + +}}//end namespace diff --git a/source/glest_game/menu/menu_state_scenario.h b/source/glest_game/menu/menu_state_scenario.h new file mode 100644 index 000000000..9eb3fcaa3 --- /dev/null +++ b/source/glest_game/menu/menu_state_scenario.h @@ -0,0 +1,69 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2005 Martiño Figueroa +// +// You can redistribute this code 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 +// ============================================================== + +#ifndef _GLEST_GAME_MENUSTATESCENARIO_H_ +#define _GLEST_GAME_MENUSTATESCENARIO_H_ + +#include "main_menu.h" + +namespace Glest{ namespace Game{ + +// =============================== +// class MenuStateScenario +// =============================== + +class MenuStateScenario: public MenuState{ +private: + enum Difficulty{ + dVeryEasy, + dEasy, + dMedium, + dHard, + dVeryHard, + dInsane + }; + + GraphicButton buttonReturn; + GraphicButton buttonPlayNow; + + GraphicLabel labelInfo; + GraphicLabel labelScenario; + GraphicListBox listBoxScenario; + + vector scenarioFiles; + + ScenarioInfo scenarioInfo; + vector dirList; + +public: + MenuStateScenario(Program *program, MainMenu *mainMenu, const vector &dirList); + + void mouseClick(int x, int y, MouseButton mouseButton); + void mouseMove(int x, int y, const MouseState *mouseState); + void render(); + void update(); + + void launchGame(); + void setScenario(int i); + int getScenarioCount() const { return listBoxScenario.getItemCount(); } + +private: + void loadScenarioInfo(string file, ScenarioInfo *scenarioInfo); + void loadGameSettings(const ScenarioInfo *scenarioInfo, GameSettings *gameSettings); + Difficulty computeDifficulty(const ScenarioInfo *scenarioInfo); + ControlType strToControllerType(const string &str); + +}; + + +}}//end namespace + +#endif diff --git a/source/glest_game/network/network_interface.cpp b/source/glest_game/network/network_interface.cpp index cf57375fd..e052268de 100644 --- a/source/glest_game/network/network_interface.cpp +++ b/source/glest_game/network/network_interface.cpp @@ -116,6 +116,15 @@ GameNetworkInterface::GameNetworkInterface(){ quit= false; } +void GameNetworkInterface::requestCommand(const NetworkCommand *networkCommand, bool insertAtStart) { + if(insertAtStart == false) { + requestedCommands.push_back(*networkCommand); + } + else { + requestedCommands.insert(requestedCommands.begin(),*networkCommand); + } +} + // ===================================================== // class FileTransferSocketThread // ===================================================== diff --git a/source/glest_game/network/network_interface.h b/source/glest_game/network/network_interface.h index 7f362fed1..f51ea3609 100644 --- a/source/glest_game/network/network_interface.h +++ b/source/glest_game/network/network_interface.h @@ -135,7 +135,7 @@ public: virtual string getNetworkStatus() const= 0; //access functions - void requestCommand(const NetworkCommand *networkCommand) {requestedCommands.push_back(*networkCommand);} + void requestCommand(const NetworkCommand *networkCommand, bool insertAtStart=false); int getPendingCommandCount() const {return pendingCommands.size();} const NetworkCommand* getPendingCommand(int i) const {return &pendingCommands[i];} void clearPendingCommands() {pendingCommands.clear();} diff --git a/source/glest_game/network/network_types.cpp b/source/glest_game/network/network_types.cpp new file mode 100644 index 000000000..645c1f185 --- /dev/null +++ b/source/glest_game/network/network_types.cpp @@ -0,0 +1,42 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2008 Martiño Figueroa +// +// You can redistribute this code 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 +// ============================================================== + +#include "network_types.h" + +#include "leak_dumper.h" + +namespace Glest{ namespace Game{ + +// ===================================================== +// class NetworkCommand +// ===================================================== + +NetworkCommand::NetworkCommand(int networkCommandType, int unitId, int commandTypeId, const Vec2i &pos, int unitTypeId, int targetId){ + this->networkCommandType= networkCommandType; + this->unitId= unitId; + this->commandTypeId= commandTypeId; + this->positionX= pos.x; + this->positionY= pos.y; + this->unitTypeId= unitTypeId; + this->targetId= targetId; +} + +NetworkCommand::NetworkCommand(int networkCommandType, NetworkCommandSubType ncstType, int unitId, int value1, int value2) { + this->networkCommandType= networkCommandType; + this->unitId= unitId; + this->commandTypeId= ncstType; + this->positionX= -1; + this->positionY= -1; + this->unitTypeId= value1; + this->targetId= value2; +} + +}}//end namespace diff --git a/source/glest_game/network/network_types.h b/source/glest_game/network/network_types.h new file mode 100644 index 000000000..7c2d76e46 --- /dev/null +++ b/source/glest_game/network/network_types.h @@ -0,0 +1,85 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2008 Martiño Figueroa +// +// You can redistribute this code 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 +// ============================================================== + +#ifndef _GLEST_GAME_NETWORKTYPES_H_ +#define _GLEST_GAME_NETWORKTYPES_H_ + +#include + +#include "types.h" +#include "vec.h" + +using std::string; +using Shared::Platform::int8; +using Shared::Platform::int16; +using Shared::Platform::int32; +using Shared::Graphics::Vec2i; + +namespace Glest{ namespace Game{ + +// ===================================================== +// class NetworkString +// ===================================================== + +template +class NetworkString{ +private: + char buffer[S]; + +public: + NetworkString() {memset(buffer, 0, S);} + void operator=(const string& str) {strncpy(buffer, str.c_str(), S-1);} + string getString() const {return buffer;} +}; + +// ===================================================== +// class NetworkCommand +// ===================================================== + +enum NetworkCommandType { + nctGiveCommand, + nctCancelCommand, + nctSetMeetingPoint, + nctNetworkCommand +}; + +enum NetworkCommandSubType { + ncstRotateUnit +}; + +#pragma pack(push, 2) +class NetworkCommand{ +private: + int16 networkCommandType; + int16 unitId; + int16 commandTypeId; + int16 positionX; + int16 positionY; + int16 unitTypeId; + int16 targetId; + +public: + NetworkCommand(){}; + NetworkCommand(int networkCommandType, int unitId, int commandTypeId= -1, const Vec2i &pos= Vec2i(0), int unitTypeId= -1, int targetId= -1); + NetworkCommand(int networkCommandType, NetworkCommandSubType ncstType, int unitId, int value1, int value2=-1); + + NetworkCommandType getNetworkCommandType() const {return static_cast(networkCommandType);} + int getUnitId() const {return unitId;} + int getCommandTypeId() const {return commandTypeId;} + Vec2i getPosition() const {return Vec2i(positionX, positionY);} + int getUnitTypeId() const {return unitTypeId;} + int getTargetId() const {return targetId;} +}; +#pragma pack(pop) + +}}//end namespace + +#endif diff --git a/source/glest_game/type_instances/unit.cpp b/source/glest_game/type_instances/unit.cpp index c792da6a2..7fb017589 100644 --- a/source/glest_game/type_instances/unit.cpp +++ b/source/glest_game/type_instances/unit.cpp @@ -24,7 +24,7 @@ #include "core_data.h" #include "renderer.h" #include "leak_dumper.h" -//#include "socket.h" +#include "socket.h" using namespace Shared::Graphics; using namespace Shared::Util; @@ -106,8 +106,9 @@ const int Unit::invalidId= -1; Unit::Unit(int id, const Vec2i &pos, const UnitType *type, Faction *faction, Map *map, float unitPlacementRotation) { - //if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); + if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); allowRotateUnits = Config::getInstance().getBool("AllowRotateUnits","0"); + rotateAmount= -1; Random random; @@ -177,7 +178,7 @@ Unit::~Unit(){ } stopDamageParticles(); - delete [] cellMap; + if(cellMap == NULL) delete [] cellMap; cellMap = NULL; } @@ -454,16 +455,20 @@ unsigned int Unit::getCommandSize() const{ //give one command (clear, and push back) CommandResult Unit::giveCommand(Command *command){ - //if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); + if(Socket::enableDebugText) printf("In [%s::%s] START\n",__FILE__,__FUNCTION__); if(command->getCommandType()->isQueuable()){ //cancel current command if it is not queuable + if(Socket::enableDebugText) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); + if(!commands.empty() && !commands.front()->getCommandType()->isQueuable()){ + if(Socket::enableDebugText) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); cancelCommand(); } } else{ //empty command queue + if(Socket::enableDebugText) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); clearCommands(); unitPath.clear(); } @@ -471,8 +476,10 @@ CommandResult Unit::giveCommand(Command *command){ //if(Socket::enableDebugText) printf("In [%s::%s] A\n",__FILE__,__FUNCTION__); //check command + if(Socket::enableDebugText) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); CommandResult result= checkCommand(command); if(result==crSuccess){ + if(Socket::enableDebugText) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); applyCommand(command); } @@ -480,13 +487,15 @@ CommandResult Unit::giveCommand(Command *command){ //push back command if(result== crSuccess){ + if(Socket::enableDebugText) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); commands.push_back(command); } else{ + if(Socket::enableDebugText) printf("In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); delete command; } - //if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__); + if(Socket::enableDebugText) printf("In [%s::%s] END\n",__FILE__,__FUNCTION__); return result; } @@ -693,24 +702,25 @@ bool Unit::update(){ animProgress= currSkill->getClass()==scDie? 1.f: 0.f; } + bool return_value = false; //checks if(progress>=1.f){ lastRotation= targetRotation; if(currSkill->getClass()!=scDie){ progress= 0.f; - return true; + return_value = true; } else{ progress= 1.f; deadCount++; if(deadCount>=maxDeadCount){ toBeUndertaken= true; - return false; + return_value = false; } } } - return false; + return return_value; } void Unit::tick(){ @@ -1124,7 +1134,8 @@ bool Unit::getCellMapCell(int x, int y) const { void Unit::setRotateAmount(float value) { if(allowRotateUnits == true) { rotateAmount = value; - //if(Socket::enableDebugText) printf("In [%s::%s] unit id = %d [%s] rotate amount = %f\n",__FILE__,__FUNCTION__,getId(), getFullName().c_str(),rotateAmount); + //if(Socket::enableDebugText && rotateAmount > 0) printf("In [%s::%s Line: %d] unit id = %d [%s] rotate amount = %f\n",__FILE__,__FUNCTION__,__LINE__, getId(), getFullName().c_str(),rotateAmount); + if(Socket::enableDebugText ) printf("In [%s::%s Line: %d] unit id = %d rotate amount = %f cellMap = %s\n",__FILE__,__FUNCTION__,__LINE__, getId(), rotateAmount,(cellMap == NULL ? "NULL" : "Valid")); const UnitType *ut= getType(); if(ut != NULL && ut->hasCellMap() == true) { @@ -1132,7 +1143,7 @@ void Unit::setRotateAmount(float value) { if(rotateAmount > 0) { - delete [] cellMap; + if(cellMap == NULL) delete [] cellMap; cellMap = new bool[matrixSize * matrixSize]; for(int iRow = 0; iRow < matrixSize; ++iRow) { @@ -1180,6 +1191,9 @@ void Unit::setRotateAmount(float value) { } */ } + + //if(Socket::enableDebugText && rotateAmount > 0) printf("In [%s::%s Line: %d] unit id = %d [%s] rotate amount = %f\n",__FILE__,__FUNCTION__,__LINE__, getId(), getFullName().c_str(),rotateAmount); + if(Socket::enableDebugText ) printf("In [%s::%s Line: %d] unit id = %d rotate amount = %f\n",__FILE__,__FUNCTION__,__LINE__, getId(),rotateAmount); } } diff --git a/source/glest_game/types/command_type.cpp b/source/glest_game/types/command_type.cpp new file mode 100644 index 000000000..d47be32d0 --- /dev/null +++ b/source/glest_game/types/command_type.cpp @@ -0,0 +1,745 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2008 Martiño Figueroa +// +// You can redistribute this code 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 +// ============================================================== + +#include "command_type.h" + +#include +#include + +#include "upgrade_type.h" +#include "unit_type.h" +#include "sound.h" +#include "util.h" +#include "leak_dumper.h" +#include "graphics_interface.h" +#include "tech_tree.h" +#include "faction_type.h" +#include "unit_updater.h" +#include "renderer.h" +#include "leak_dumper.h" +#include "socket.h" + +using namespace Shared::Util; + +namespace Glest{ namespace Game{ + + +// ===================================================== +// class CommandType +// ===================================================== + +//get +CommandClass CommandType::getClass() const{ + assert(this!=NULL); + return commandTypeClass; +} + +void CommandType::load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut){ + this->id= id; + name= n->getChild("name")->getAttribute("value")->getRestrictedValue(); + + //image + const XmlNode *imageNode= n->getChild("image"); + image= Renderer::getInstance().newTexture2D(rsGame); + image->load(dir+"/"+imageNode->getAttribute("path")->getRestrictedValue()); + + //unit requirements + const XmlNode *unitRequirementsNode= n->getChild("unit-requirements"); + for(int i=0; igetChildCount(); ++i){ + const XmlNode *unitNode= unitRequirementsNode->getChild("unit", i); + string name= unitNode->getAttribute("name")->getRestrictedValue(); + unitReqs.push_back(ft->getUnitType(name)); + } + + //upgrade requirements + const XmlNode *upgradeRequirementsNode= n->getChild("upgrade-requirements"); + for(int i=0; igetChildCount(); ++i){ + const XmlNode *upgradeReqNode= upgradeRequirementsNode->getChild("upgrade", i); + string name= upgradeReqNode->getAttribute("name")->getRestrictedValue(); + upgradeReqs.push_back(ft->getUpgradeType(name)); + } +} + +// ===================================================== +// class StopCommandType +// ===================================================== + +//varios +StopCommandType::StopCommandType(){ + commandTypeClass= ccStop; + clicks= cOne; +} + +void StopCommandType::update(UnitUpdater *unitUpdater, Unit *unit) const{ + unitUpdater->updateStop(unit); +} + +string StopCommandType::getDesc(const TotalUpgrade *totalUpgrade) const{ + string str; + Lang &lang= Lang::getInstance(); + + str= name+"\n"; + str+= lang.get("ReactionSpeed")+": "+ intToStr(stopSkillType->getSpeed())+"\n"; + if(stopSkillType->getEpCost()!=0) + str+= lang.get("EpCost")+": "+intToStr(stopSkillType->getEpCost())+"\n"; + + return str; +} + +string StopCommandType::toString() const{ + Lang &lang= Lang::getInstance(); + return lang.get("Stop"); +} + +void StopCommandType::load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut){ + CommandType::load(id, n, dir, tt, ft, ut); + + //stop + string skillName= n->getChild("stop-skill")->getAttribute("value")->getRestrictedValue(); + stopSkillType= static_cast(ut.getSkillType(skillName, scStop)); +} + + +// ===================================================== +// class MoveCommandType +// ===================================================== + +//varios +MoveCommandType::MoveCommandType(){ + commandTypeClass= ccMove; + clicks= cTwo; +} + +void MoveCommandType::update(UnitUpdater *unitUpdater, Unit *unit) const{ + unitUpdater->updateMove(unit); +} + +void MoveCommandType::load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut){ + CommandType::load(id, n, dir, tt, ft, ut); + + //move + string skillName= n->getChild("move-skill")->getAttribute("value")->getRestrictedValue(); + moveSkillType= static_cast(ut.getSkillType(skillName, scMove)); +} + +string MoveCommandType::getDesc(const TotalUpgrade *totalUpgrade) const{ + string str; + Lang &lang= Lang::getInstance(); + + str= name+"\n"; + str+= lang.get("WalkSpeed")+": "+ intToStr(moveSkillType->getSpeed()); + if(totalUpgrade->getMoveSpeed()!=0){ + str+= "+" + intToStr(totalUpgrade->getMoveSpeed()); + } + str+="\n"; + if(moveSkillType->getEpCost()!=0){ + str+= lang.get("EpCost")+": "+intToStr(moveSkillType->getEpCost())+"\n"; + } + + return str; +} + +string MoveCommandType::toString() const{ + Lang &lang= Lang::getInstance(); + return lang.get("Move"); +} + +// ===================================================== +// class AttackCommandType +// ===================================================== + +//varios +AttackCommandType::AttackCommandType(){ + commandTypeClass= ccAttack; + clicks= cTwo; +} + +void AttackCommandType::update(UnitUpdater *unitUpdater, Unit *unit) const{ + unitUpdater->updateAttack(unit); +} + +void AttackCommandType::load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut){ + CommandType::load(id, n, dir, tt, ft, ut); + + //move + string skillName= n->getChild("move-skill")->getAttribute("value")->getRestrictedValue(); + moveSkillType= static_cast(ut.getSkillType(skillName, scMove)); + + //attack + skillName= n->getChild("attack-skill")->getAttribute("value")->getRestrictedValue(); + attackSkillType= static_cast(ut.getSkillType(skillName, scAttack)); +} + +string AttackCommandType::getDesc(const TotalUpgrade *totalUpgrade) const{ + string str; + Lang &lang= Lang::getInstance(); + + str= name+"\n"; + if(attackSkillType->getEpCost()!=0){ + str+= lang.get("EpCost") + ": " + intToStr(attackSkillType->getEpCost()) + "\n"; + } + + //attack strength + str+= lang.get("AttackStrenght")+": "; + str+= intToStr(attackSkillType->getAttackStrength()-attackSkillType->getAttackVar()); + str+= "..."; + str+= intToStr(attackSkillType->getAttackStrength()+attackSkillType->getAttackVar()); + if(totalUpgrade->getAttackStrength()!=0){ + str+= "+"+intToStr(totalUpgrade->getAttackStrength()); + } + str+= " ("+ attackSkillType->getAttackType()->getName() +")"; + str+= "\n"; + + //splash radius + if(attackSkillType->getSplashRadius()!=0){ + str+= lang.get("SplashRadius")+": "+intToStr(attackSkillType->getSplashRadius())+"\n"; + } + + //attack distance + str+= lang.get("AttackDistance")+": "+intToStr(attackSkillType->getAttackRange()); + if(totalUpgrade->getAttackRange()!=0){ + str+= "+"+intToStr(totalUpgrade->getAttackRange()!=0); + } + str+="\n"; + + //attack fields + str+= lang.get("Fields") + ": "; + for(int i= 0; i < fieldCount; i++){ + Field field = static_cast(i); + if( attackSkillType->getAttackField(field) ) + { + str+= SkillType::fieldToStr(field) + " "; + } + } + str+="\n"; + + //movement speed + str+= lang.get("WalkSpeed")+": "+ intToStr(moveSkillType->getSpeed()) ; + if(totalUpgrade->getMoveSpeed()!=0){ + str+= "+"+intToStr(totalUpgrade->getMoveSpeed()); + } + str+="\n"; + + str+= lang.get("AttackSpeed")+": "+ intToStr(attackSkillType->getSpeed()) +"\n"; + + return str; +} + +string AttackCommandType::toString() const{ + Lang &lang= Lang::getInstance(); + return lang.get("Attack"); +} + + +// ===================================================== +// class AttackStoppedCommandType +// ===================================================== + +//varios +AttackStoppedCommandType::AttackStoppedCommandType(){ + commandTypeClass= ccAttackStopped; + clicks= cOne; +} + +void AttackStoppedCommandType::update(UnitUpdater *unitUpdater, Unit *unit) const{ + unitUpdater->updateAttackStopped(unit); +} + +void AttackStoppedCommandType::load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut){ + CommandType::load(id, n, dir, tt, ft, ut); + + //stop + string skillName= n->getChild("stop-skill")->getAttribute("value")->getRestrictedValue(); + stopSkillType= static_cast(ut.getSkillType(skillName, scStop)); + + //attack + skillName= n->getChild("attack-skill")->getAttribute("value")->getRestrictedValue(); + attackSkillType= static_cast(ut.getSkillType(skillName, scAttack)); +} + +string AttackStoppedCommandType::getDesc(const TotalUpgrade *totalUpgrade) const{ + Lang &lang= Lang::getInstance(); + string str; + + str= name+"\n"; + if(attackSkillType->getEpCost()!=0){ + str+= lang.get("EpCost")+": "+intToStr(attackSkillType->getEpCost())+"\n"; + } + + //attack strength + str+= lang.get("AttackStrenght")+": "; + str+= intToStr(attackSkillType->getAttackStrength()-attackSkillType->getAttackVar()); + str+="..."; + str+= intToStr(attackSkillType->getAttackStrength()+attackSkillType->getAttackVar()); + if(totalUpgrade->getAttackStrength()!=0) + str+= "+"+intToStr(totalUpgrade->getAttackStrength()); + str+= " ("+ attackSkillType->getAttackType()->getName() +")"; + str+="\n"; + + //splash radius + if(attackSkillType->getSplashRadius()!=0){ + str+= lang.get("SplashRadius")+": "+intToStr(attackSkillType->getSplashRadius())+"\n"; + } + + //attack distance + str+= lang.get("AttackDistance")+": "+floatToStr(attackSkillType->getAttackRange()); + if(totalUpgrade->getAttackRange()!=0){ + str+= "+"+intToStr(totalUpgrade->getAttackRange()!=0); + } + str+="\n"; + + //attack fields + str+= lang.get("Fields") + ": "; + for(int i= 0; i < fieldCount; i++){ + Field field = static_cast(i); + if( attackSkillType->getAttackField(field) ) + { + str+= SkillType::fieldToStr(field) + " "; + } + } + str+="\n"; + + return str; +} + +string AttackStoppedCommandType::toString() const{ + Lang &lang= Lang::getInstance(); + return lang.get("AttackStopped"); +} + + +// ===================================================== +// class BuildCommandType +// ===================================================== + +//varios +BuildCommandType::BuildCommandType(){ + commandTypeClass= ccBuild; + clicks= cTwo; +} + +BuildCommandType::~BuildCommandType(){ + deleteValues(builtSounds.getSounds().begin(), builtSounds.getSounds().end()); + deleteValues(startSounds.getSounds().begin(), startSounds.getSounds().end()); +} + +void BuildCommandType::update(UnitUpdater *unitUpdater, Unit *unit) const{ + unitUpdater->updateBuild(unit); +} + +void BuildCommandType::load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut){ + CommandType::load(id, n, dir, tt, ft, ut); + + //move + string skillName= n->getChild("move-skill")->getAttribute("value")->getRestrictedValue(); + moveSkillType= static_cast(ut.getSkillType(skillName, scMove)); + + //build + skillName= n->getChild("build-skill")->getAttribute("value")->getRestrictedValue(); + buildSkillType= static_cast(ut.getSkillType(skillName, scBuild)); + + //buildings built + const XmlNode *buildingsNode= n->getChild("buildings"); + for(int i=0; igetChildCount(); ++i){ + const XmlNode *buildingNode= buildingsNode->getChild("building", i); + string name= buildingNode->getAttribute("name")->getRestrictedValue(); + buildings.push_back(ft->getUnitType(name)); + } + + //start sound + const XmlNode *startSoundNode= n->getChild("start-sound"); + if(startSoundNode->getAttribute("enabled")->getBoolValue()){ + startSounds.resize(startSoundNode->getChildCount()); + for(int i=0; igetChildCount(); ++i){ + const XmlNode *soundFileNode= startSoundNode->getChild("sound-file", i); + string path= soundFileNode->getAttribute("path")->getRestrictedValue(); + StaticSound *sound= new StaticSound(); + sound->load(dir + "/" + path); + startSounds[i]= sound; + } + } + + //built sound + const XmlNode *builtSoundNode= n->getChild("built-sound"); + if(builtSoundNode->getAttribute("enabled")->getBoolValue()){ + builtSounds.resize(builtSoundNode->getChildCount()); + for(int i=0; igetChildCount(); ++i){ + const XmlNode *soundFileNode= builtSoundNode->getChild("sound-file", i); + string path= soundFileNode->getAttribute("path")->getRestrictedValue(); + StaticSound *sound= new StaticSound(); + sound->load(dir + "/" + path); + builtSounds[i]= sound; + } + } +} + +string BuildCommandType::getDesc(const TotalUpgrade *totalUpgrade) const{ + string str; + Lang &lang= Lang::getInstance(); + + str= name+"\n"; + str+= lang.get("BuildSpeed")+": "+ intToStr(buildSkillType->getSpeed())+"\n"; + if(buildSkillType->getEpCost()!=0){ + str+= lang.get("EpCost")+": "+intToStr(buildSkillType->getEpCost())+"\n"; + } + + return str; +} + +string BuildCommandType::toString() const{ + Lang &lang= Lang::getInstance(); + return lang.get("Build"); +} + +// ===================================================== +// class HarvestCommandType +// ===================================================== + +//varios +HarvestCommandType::HarvestCommandType(){ + commandTypeClass= ccHarvest; + clicks= cTwo; +} + +void HarvestCommandType::update(UnitUpdater *unitUpdater, Unit *unit) const{ + unitUpdater->updateHarvest(unit); +} + +void HarvestCommandType::load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut){ + + CommandType::load(id, n, dir, tt, ft, ut); + + //move + string skillName= n->getChild("move-skill")->getAttribute("value")->getRestrictedValue(); + moveSkillType= static_cast(ut.getSkillType(skillName, scMove)); + + //harvest + skillName= n->getChild("harvest-skill")->getAttribute("value")->getRestrictedValue(); + harvestSkillType= static_cast(ut.getSkillType(skillName, scHarvest)); + + //stop loaded + skillName= n->getChild("stop-loaded-skill")->getAttribute("value")->getRestrictedValue(); + stopLoadedSkillType= static_cast(ut.getSkillType(skillName, scStop)); + + //move loaded + skillName= n->getChild("move-loaded-skill")->getAttribute("value")->getRestrictedValue(); + moveLoadedSkillType= static_cast(ut.getSkillType(skillName, scMove)); + + //resources can harvest + const XmlNode *resourcesNode= n->getChild("harvested-resources"); + for(int i=0; igetChildCount(); ++i){ + const XmlNode *resourceNode= resourcesNode->getChild("resource", i); + harvestedResources.push_back(tt->getResourceType(resourceNode->getAttribute("name")->getRestrictedValue())); + } + + maxLoad= n->getChild("max-load")->getAttribute("value")->getIntValue(); + hitsPerUnit= n->getChild("hits-per-unit")->getAttribute("value")->getIntValue(); +} + +string HarvestCommandType::getDesc(const TotalUpgrade *totalUpgrade) const{ + + Lang &lang= Lang::getInstance(); + string str; + + str= name+"\n"; + str+= lang.get("HarvestSpeed")+": "+ intToStr(harvestSkillType->getSpeed()/hitsPerUnit)+"\n"; + str+= lang.get("MaxLoad")+": "+ intToStr(maxLoad)+"\n"; + str+= lang.get("LoadedSpeed")+": "+ intToStr(moveLoadedSkillType->getSpeed())+"\n"; + if(harvestSkillType->getEpCost()!=0){ + str+= lang.get("EpCost")+": "+intToStr(harvestSkillType->getEpCost())+"\n"; + } + str+=lang.get("Resources")+":\n"; + for(int i=0; igetName()+"\n"; + } + + return str; +} + +string HarvestCommandType::toString() const{ + Lang &lang= Lang::getInstance(); + return lang.get("Harvest"); +} + +bool HarvestCommandType::canHarvest(const ResourceType *resourceType) const{ + return find(harvestedResources.begin(), harvestedResources.end(), resourceType) != harvestedResources.end(); +} + +// ===================================================== +// class RepairCommandType +// ===================================================== + +//varios +RepairCommandType::RepairCommandType(){ + commandTypeClass= ccRepair; + clicks= cTwo; +} + +RepairCommandType::~RepairCommandType(){ +} + +void RepairCommandType::update(UnitUpdater *unitUpdater, Unit *unit) const{ + unitUpdater->updateRepair(unit); +} + +void RepairCommandType::load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut){ + + CommandType::load(id, n, dir, tt, ft, ut); + + //move + string skillName= n->getChild("move-skill")->getAttribute("value")->getRestrictedValue(); + moveSkillType= static_cast(ut.getSkillType(skillName, scMove)); + + //repair + skillName= n->getChild("repair-skill")->getAttribute("value")->getRestrictedValue(); + repairSkillType= static_cast(ut.getSkillType(skillName, scRepair)); + + //repaired units + const XmlNode *unitsNode= n->getChild("repaired-units"); + for(int i=0; igetChildCount(); ++i){ + const XmlNode *unitNode= unitsNode->getChild("unit", i); + repairableUnits.push_back(ft->getUnitType(unitNode->getAttribute("name")->getRestrictedValue())); + } +} + +string RepairCommandType::getDesc(const TotalUpgrade *totalUpgrade) const{ + Lang &lang= Lang::getInstance(); + string str; + + str= name+"\n"; + str+= lang.get("RepairSpeed")+": "+ intToStr(repairSkillType->getSpeed())+"\n"; + if(repairSkillType->getEpCost()!=0){ + str+= lang.get("EpCost")+": "+intToStr(repairSkillType->getEpCost())+"\n"; + } + + str+="\n"+lang.get("CanRepair")+":\n"; + for(int i=0; i(repairableUnits[i]))->getName()+"\n"; + } + + return str; +} + +string RepairCommandType::toString() const{ + Lang &lang= Lang::getInstance(); + return lang.get("Repair"); +} + +//get +bool RepairCommandType::isRepairableUnitType(const UnitType *unitType) const{ + for(int i=0; i(repairableUnits[i])==unitType){ + return true; + } + } + return false; +} + +// ===================================================== +// class ProduceCommandType +// ===================================================== + +//varios +ProduceCommandType::ProduceCommandType(){ + commandTypeClass= ccProduce; + clicks= cOne; +} + +void ProduceCommandType::update(UnitUpdater *unitUpdater, Unit *unit) const{ + unitUpdater->updateProduce(unit); +} + +void ProduceCommandType::load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut){ + CommandType::load(id, n, dir, tt, ft, ut); + + //produce + string skillName= n->getChild("produce-skill")->getAttribute("value")->getRestrictedValue(); + produceSkillType= static_cast(ut.getSkillType(skillName, scProduce)); + + string producedUnitName= n->getChild("produced-unit")->getAttribute("name")->getRestrictedValue(); + producedUnit= ft->getUnitType(producedUnitName); +} + +string ProduceCommandType::getDesc(const TotalUpgrade *totalUpgrade) const{ + string str= name+"\n"; + Lang &lang= Lang::getInstance(); + + //prod speed + str+= lang.get("ProductionSpeed")+": "+ intToStr(produceSkillType->getSpeed()); + if(totalUpgrade->getProdSpeed()!=0){ + str+="+" + intToStr(totalUpgrade->getProdSpeed()); + } + str+="\n"; + + //mpcost + if(produceSkillType->getEpCost()!=0){ + str+= lang.get("EpCost")+": "+intToStr(produceSkillType->getEpCost())+"\n"; + } + + str+= "\n" + getProducedUnit()->getReqDesc(); + + return str; +} + +string ProduceCommandType::toString() const{ + Lang &lang= Lang::getInstance(); + return lang.get("Produce"); +} + +string ProduceCommandType::getReqDesc() const{ + return RequirableType::getReqDesc()+"\n"+getProducedUnit()->getReqDesc(); +} + +const ProducibleType *ProduceCommandType::getProduced() const{ + return producedUnit; +} + +// ===================================================== +// class UpgradeCommandType +// ===================================================== + +//varios +UpgradeCommandType::UpgradeCommandType(){ + commandTypeClass= ccUpgrade; + clicks= cOne; +} + +void UpgradeCommandType::update(UnitUpdater *unitUpdater, Unit *unit) const{ + unitUpdater->updateUpgrade(unit); +} + +void UpgradeCommandType::load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut){ + + CommandType::load(id, n, dir, tt, ft, ut); + + //upgrade + string skillName= n->getChild("upgrade-skill")->getAttribute("value")->getRestrictedValue(); + upgradeSkillType= static_cast(ut.getSkillType(skillName, scUpgrade)); + + string producedUpgradeName= n->getChild("produced-upgrade")->getAttribute("name")->getRestrictedValue(); + producedUpgrade= ft->getUpgradeType(producedUpgradeName); + +} + +string UpgradeCommandType::getDesc(const TotalUpgrade *totalUpgrade) const{ + string str; + Lang &lang= Lang::getInstance(); + + str= name+"\n"; + str+= lang.get("UpgradeSpeed")+": "+ intToStr(upgradeSkillType->getSpeed())+"\n"; + if(upgradeSkillType->getEpCost()!=0) + str+= lang.get("EpCost")+": "+intToStr(upgradeSkillType->getEpCost())+"\n"; + + str+= "\n"+getProducedUpgrade()->getReqDesc(); + + return str; +} + +string UpgradeCommandType::toString() const{ + Lang &lang= Lang::getInstance(); + return lang.get("Upgrade"); +} + +string UpgradeCommandType::getReqDesc() const{ + return RequirableType::getReqDesc()+"\n"+getProducedUpgrade()->getReqDesc(); +} + +const ProducibleType *UpgradeCommandType::getProduced() const{ + return producedUpgrade; +} + +// ===================================================== +// class MorphCommandType +// ===================================================== + +//varios +MorphCommandType::MorphCommandType(){ + commandTypeClass= ccMorph; + clicks= cOne; +} + +void MorphCommandType::update(UnitUpdater *unitUpdater, Unit *unit) const{ + unitUpdater->updateMorph(unit); +} + +void MorphCommandType::load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut){ + CommandType::load(id, n, dir, tt, ft, ut); + + //morph skill + string skillName= n->getChild("morph-skill")->getAttribute("value")->getRestrictedValue(); + morphSkillType= static_cast(ut.getSkillType(skillName, scMorph)); + + //morph unit + string morphUnitName= n->getChild("morph-unit")->getAttribute("name")->getRestrictedValue(); + morphUnit= ft->getUnitType(morphUnitName); + + //discount + discount= n->getChild("discount")->getAttribute("value")->getIntValue(); +} + +string MorphCommandType::getDesc(const TotalUpgrade *totalUpgrade) const{ + string str= name+"\n"; + Lang &lang= Lang::getInstance(); + + //prod speed + str+= lang.get("MorphSpeed")+": "+ intToStr(morphSkillType->getSpeed())+"\n"; + + //mpcost + if(morphSkillType->getEpCost()!=0){ + str+= lang.get("EpCost")+": "+intToStr(morphSkillType->getEpCost())+"\n"; + } + + //discount + if(discount!=0){ + str+= lang.get("Discount")+": "+intToStr(discount)+"%\n"; + } + + str+= "\n"+getProduced()->getReqDesc(); + + return str; +} + +string MorphCommandType::toString() const{ + Lang &lang= Lang::getInstance(); + return lang.get("Morph"); +} + +string MorphCommandType::getReqDesc() const{ + return RequirableType::getReqDesc() + "\n" + getProduced()->getReqDesc(); +} + +const ProducibleType *MorphCommandType::getProduced() const{ + return morphUnit; +} + +// ===================================================== +// class CommandFactory +// ===================================================== + +CommandTypeFactory::CommandTypeFactory(){ + registerClass("stop"); + registerClass("move"); + registerClass("attack"); + registerClass("attack_stopped"); + registerClass("build"); + registerClass("harvest"); + registerClass("repair"); + registerClass("produce"); + registerClass("upgrade"); + registerClass("morph"); +} + +CommandTypeFactory &CommandTypeFactory::getInstance(){ + static CommandTypeFactory ctf; + return ctf; +} + +}}//end namespace diff --git a/source/glest_game/types/command_type.h b/source/glest_game/types/command_type.h new file mode 100644 index 000000000..3d9785b61 --- /dev/null +++ b/source/glest_game/types/command_type.h @@ -0,0 +1,343 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2008 Martiño Figueroa +// +// You can redistribute this code 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 +// ============================================================== + +#ifndef _GLEST_GAME_COMMANDTYPE_H_ +#define _GLEST_GAME_COMMANDTYPE_H_ + +#include "element_type.h" +#include "resource_type.h" +#include "lang.h" +#include "skill_type.h" +#include "factory.h" +#include "xml_parser.h" +#include "sound_container.h" + +namespace Glest{ namespace Game{ + +using Shared::Util::MultiFactory; + +class UnitUpdater; +class Unit; +class UnitType; +class TechTree; +class FactionType; + +enum CommandClass{ + ccStop, + ccMove, + ccAttack, + ccAttackStopped, + ccBuild, + ccHarvest, + ccRepair, + ccProduce, + ccUpgrade, + ccMorph, + + ccCount, + ccNull +}; + +enum Clicks{ + cOne, + cTwo +}; + +// ===================================================== +// class CommandType +// +/// A complex action performed by a unit, composed by skills +// ===================================================== + +class CommandType: public RequirableType{ +protected: + CommandClass commandTypeClass; + Clicks clicks; + int id; + +public: + static const int invalidId= -1; + +public: + virtual void update(UnitUpdater *unitUpdater, Unit *unit) const= 0; + virtual void load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut); + virtual string getDesc(const TotalUpgrade *totalUpgrade) const= 0; + virtual string toString() const= 0; + virtual const ProducibleType *getProduced() const {return NULL;} + virtual bool isQueuable() const {return false;} + + //get + CommandClass getClass() const; + Clicks getClicks() const {return clicks;} + int getId() const {return id;} +}; + +// =============================== +// class StopCommandType +// =============================== + +class StopCommandType: public CommandType{ +private: + const StopSkillType* stopSkillType; + +public: + StopCommandType(); + virtual void update(UnitUpdater *unitUpdater, Unit *unit) const; + virtual void load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut); + virtual string getDesc(const TotalUpgrade *totalUpgrade) const; + virtual string toString() const; + + //get + const StopSkillType *getStopSkillType() const {return stopSkillType;}; +}; + + +// =============================== +// class MoveCommandType +// =============================== + +class MoveCommandType: public CommandType{ +private: + const MoveSkillType *moveSkillType; + +public: + MoveCommandType(); + virtual void update(UnitUpdater *unitUpdater, Unit *unit) const; + virtual void load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut); + virtual string getDesc(const TotalUpgrade *totalUpgrade) const; + virtual string toString() const; + + //get + const MoveSkillType *getMoveSkillType() const {return moveSkillType;}; +}; + + +// =============================== +// class AttackCommandType +// =============================== + +class AttackCommandType: public CommandType{ +private: + const MoveSkillType* moveSkillType; + const AttackSkillType* attackSkillType; + +public: + AttackCommandType(); + virtual void update(UnitUpdater *unitUpdater, Unit *unit) const; + virtual void load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut); + virtual string getDesc(const TotalUpgrade *totalUpgrade) const; + virtual string toString() const; + + //get + const MoveSkillType * getMoveSkillType() const {return moveSkillType;} + const AttackSkillType * getAttackSkillType() const {return attackSkillType;} +}; + +// ======================================= +// class AttackStoppedCommandType +// ======================================= + +class AttackStoppedCommandType: public CommandType{ +private: + const StopSkillType* stopSkillType; + const AttackSkillType* attackSkillType; + +public: + AttackStoppedCommandType(); + virtual void update(UnitUpdater *unitUpdater, Unit *unit) const; + virtual void load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut); + virtual string getDesc(const TotalUpgrade *totalUpgrade) const; + virtual string toString() const; + + //get + const StopSkillType * getStopSkillType() const {return stopSkillType;} + const AttackSkillType * getAttackSkillType() const {return attackSkillType;} +}; + + +// =============================== +// class BuildCommandType +// =============================== + +class BuildCommandType: public CommandType{ +private: + const MoveSkillType* moveSkillType; + const BuildSkillType* buildSkillType; + vector buildings; + SoundContainer startSounds; + SoundContainer builtSounds; + +public: + BuildCommandType(); + ~BuildCommandType(); + virtual void update(UnitUpdater *unitUpdater, Unit *unit) const; + virtual void load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut); + virtual string getDesc(const TotalUpgrade *totalUpgrade) const; + virtual string toString() const; + + //get + const MoveSkillType *getMoveSkillType() const {return moveSkillType;} + const BuildSkillType *getBuildSkillType() const {return buildSkillType;} + int getBuildingCount() const {return buildings.size();} + const UnitType * getBuilding(int i) const {return buildings[i];} + StaticSound *getStartSound() const {return startSounds.getRandSound();} + StaticSound *getBuiltSound() const {return builtSounds.getRandSound();} +}; + + +// =============================== +// class HarvestCommandType +// =============================== + +class HarvestCommandType: public CommandType{ +private: + const MoveSkillType *moveSkillType; + const MoveSkillType *moveLoadedSkillType; + const HarvestSkillType *harvestSkillType; + const StopSkillType *stopLoadedSkillType; + vector harvestedResources; + int maxLoad; + int hitsPerUnit; + +public: + HarvestCommandType(); + virtual void update(UnitUpdater *unitUpdater, Unit *unit) const; + virtual void load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut); + virtual string getDesc(const TotalUpgrade *totalUpgrade) const; + virtual string toString() const; + + //get + const MoveSkillType *getMoveSkillType() const {return moveSkillType;} + const MoveSkillType *getMoveLoadedSkillType() const {return moveLoadedSkillType;} + const HarvestSkillType *getHarvestSkillType() const {return harvestSkillType;} + const StopSkillType *getStopLoadedSkillType() const {return stopLoadedSkillType;} + int getMaxLoad() const {return maxLoad;} + int getHitsPerUnit() const {return hitsPerUnit;} + int getHarvestedResourceCount() const {return harvestedResources.size();} + const ResourceType* getHarvestedResource(int i) const {return harvestedResources[i];} + bool canHarvest(const ResourceType *resourceType) const; +}; + + +// =============================== +// class RepairCommandType +// =============================== + +class RepairCommandType: public CommandType{ +private: + const MoveSkillType* moveSkillType; + const RepairSkillType* repairSkillType; + vector repairableUnits; + +public: + RepairCommandType(); + ~RepairCommandType(); + virtual void update(UnitUpdater *unitUpdater, Unit *unit) const; + virtual void load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut); + virtual string getDesc(const TotalUpgrade *totalUpgrade) const; + virtual string toString() const; + + //get + const MoveSkillType *getMoveSkillType() const {return moveSkillType;}; + const RepairSkillType *getRepairSkillType() const {return repairSkillType;}; + bool isRepairableUnitType(const UnitType *unitType) const; +}; + + +// =============================== +// class ProduceCommandType +// =============================== + +class ProduceCommandType: public CommandType{ +private: + const ProduceSkillType* produceSkillType; + const UnitType *producedUnit; + +public: + ProduceCommandType(); + virtual void update(UnitUpdater *unitUpdater, Unit *unit) const; + virtual void load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut); + virtual string getDesc(const TotalUpgrade *totalUpgrade) const; + virtual string getReqDesc() const; + virtual string toString() const; + virtual const ProducibleType *getProduced() const; + virtual bool isQueuable() const {return true;} + + //get + const ProduceSkillType *getProduceSkillType() const {return produceSkillType;} + const UnitType *getProducedUnit() const {return producedUnit;} +}; + + +// =============================== +// class UpgradeCommandType +// =============================== + +class UpgradeCommandType: public CommandType{ +private: + const UpgradeSkillType* upgradeSkillType; + const UpgradeType* producedUpgrade; + +public: + UpgradeCommandType(); + virtual void update(UnitUpdater *unitUpdater, Unit *unit) const; + virtual void load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut); + virtual string getDesc(const TotalUpgrade *totalUpgrade) const; + virtual string toString() const; + virtual string getReqDesc() const; + virtual const ProducibleType *getProduced() const; + virtual bool isQueuable() const {return true;} + + //get + const UpgradeSkillType *getUpgradeSkillType() const {return upgradeSkillType;} + const UpgradeType *getProducedUpgrade() const {return producedUpgrade;} +}; + +// =============================== +// class MorphCommandType +// =============================== + +class MorphCommandType: public CommandType{ +private: + const MorphSkillType* morphSkillType; + const UnitType* morphUnit; + int discount; + +public: + MorphCommandType(); + virtual void update(UnitUpdater *unitUpdater, Unit *unit) const; + virtual void load(int id, const XmlNode *n, const string &dir, const TechTree *tt, const FactionType *ft, const UnitType &ut); + virtual string getDesc(const TotalUpgrade *totalUpgrade) const; + virtual string toString() const; + virtual string getReqDesc() const; + virtual const ProducibleType *getProduced() const; + + //get + const MorphSkillType *getMorphSkillType() const {return morphSkillType;} + const UnitType *getMorphUnit() const {return morphUnit;} + int getDiscount() const {return discount;} +}; + +// =============================== +// class CommandFactory +// =============================== + +class CommandTypeFactory: public MultiFactory{ +private: + CommandTypeFactory(); + +public: + static CommandTypeFactory &getInstance(); +}; + +}}//end namespace + +#endif diff --git a/source/glest_game/types/tech_tree.cpp b/source/glest_game/types/tech_tree.cpp new file mode 100644 index 000000000..753ae73f4 --- /dev/null +++ b/source/glest_game/types/tech_tree.cpp @@ -0,0 +1,214 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2008 Martiño Figueroa +// +// You can redistribute this code 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 +// ============================================================== + +#include "tech_tree.h" + +#include + +#include "util.h" +#include "resource.h" +#include "faction_type.h" +#include "logger.h" +#include "xml_parser.h" +#include "platform_util.h" +#include "game_util.h" +#include "leak_dumper.h" + +using namespace Shared::Util; +using namespace Shared::Xml; + +namespace Glest{ namespace Game{ + +// ===================================================== +// class TechTree +// ===================================================== + +void TechTree::loadTech(const vector pathList, const string &techName, set &factions, Checksum* checksum) { + for(int idx = 0; idx < pathList.size(); idx++) { + string path = pathList[idx] + "/" + techName; + if(isdir(path.c_str()) == true) { + load(path, factions, checksum); + break; + } + } +} + +void TechTree::load(const string &dir, set &factions, Checksum* checksum) { + + string str; + vector filenames; + string name= lastDir(dir); + + Logger::getInstance().add("TechTree: "+ formatString(name), true); + + //load resources + str= dir+"/resources/*."; + + try{ + findAll(str, filenames); + resourceTypes.resize(filenames.size()); + + for(int i=0; iaddFile(path); + + xmlTree.load(path); + const XmlNode *techTreeNode= xmlTree.getRootNode(); + + //attack types + const XmlNode *attackTypesNode= techTreeNode->getChild("attack-types"); + attackTypes.resize(attackTypesNode->getChildCount()); + for(int i=0; igetChild("attack-type", i); + attackTypes[i].setName(attackTypeNode->getAttribute("name")->getRestrictedValue()); + attackTypes[i].setId(i); + } + + //armor types + const XmlNode *armorTypesNode= techTreeNode->getChild("armor-types"); + armorTypes.resize(armorTypesNode->getChildCount()); + for(int i=0; igetChild("armor-type", i); + armorTypes[i].setName(armorTypeNode->getAttribute("name")->getRestrictedValue()); + armorTypes[i].setId(i); + } + + //damage multipliers + damageMultiplierTable.init(attackTypes.size(), armorTypes.size()); + const XmlNode *damageMultipliersNode= techTreeNode->getChild("damage-multipliers"); + for(int i=0; igetChildCount(); ++i){ + const XmlNode *damageMultiplierNode= damageMultipliersNode->getChild("damage-multiplier", i); + const AttackType *attackType= getAttackType(damageMultiplierNode->getAttribute("attack")->getRestrictedValue()); + const ArmorType *armorType= getArmorType(damageMultiplierNode->getAttribute("armor")->getRestrictedValue()); + float multiplier= damageMultiplierNode->getAttribute("value")->getFloatValue(); + damageMultiplierTable.setDamageMultiplier(attackType, armorType, multiplier); + } + } + } + catch(const exception &e){ + throw runtime_error("Error loading Tech Tree: "+ dir + "\n" + e.what()); + } + + //load factions + str= dir+"/factions/*."; + try{ + factionTypes.resize(factions.size()); + + int i=0; + for ( set::iterator it = factions.begin(); it != factions.end(); ++it ) { + str=dir+"/factions/" + *it; + factionTypes[i++].load(str, this, checksum); + } + } + catch(const exception &e){ + throw runtime_error("Error loading Faction Types: "+ dir + "\n" + e.what()); + } + +} + +TechTree::~TechTree(){ + Logger::getInstance().add("Tech tree", true); +} + + +// ==================== get ==================== + +const FactionType *TechTree::getType(const string &name) const{ + for(int i=0; igetResourceNumber()==i && rt->getClass()==rcTech) + return getResourceType(j); + } + + return getFirstTechResourceType(); +} + +const ResourceType *TechTree::getFirstTechResourceType() const{ + for(int i=0; igetResourceNumber()==1 && rt->getClass()==rcTech) + return getResourceType(i); + } + + throw runtime_error("This tech tree has not tech resources, one at least is required"); +} + +const ResourceType *TechTree::getResourceType(const string &name) const{ + + for(int i=0; i + +#include "util.h" +#include "resource_type.h" +#include "faction_type.h" +#include "damage_multiplier.h" + +namespace Glest{ namespace Game{ + +// ===================================================== +// class TechTree +// +/// A set of factions and resources +// ===================================================== + +class TechTree{ +private: + typedef vector ResourceTypes; + typedef vector FactionTypes; + typedef vector ArmorTypes; + typedef vector AttackTypes; + +private: + string desc; + ResourceTypes resourceTypes; + FactionTypes factionTypes; + ArmorTypes armorTypes; + AttackTypes attackTypes; + DamageMultiplierTable damageMultiplierTable; + +public: + void loadTech(const vector pathList, const string &techName, set &factions, Checksum* checksum); + void load(const string &dir, set &factions, Checksum* checksum); + ~TechTree(); + + //get + int getResourceTypeCount() const {return resourceTypes.size();} + int getTypeCount() const {return factionTypes.size();} + const FactionType *getType(int i) const {return &factionTypes[i];} + const ResourceType *getResourceType(int i) const {return &resourceTypes[i];} + const string &getDesc() const {return desc;} + const FactionType *getType(const string &name) const; + const ResourceType *getResourceType(const string &name) const; + const ResourceType *getTechResourceType(int i) const; + const ResourceType *getFirstTechResourceType() const; + const ArmorType *getArmorType(const string &name) const; + const AttackType *getAttackType(const string &name) const; + float getDamageMultiplier(const AttackType *att, const ArmorType *art) const; +}; + +}} //end namespace + +#endif diff --git a/source/glest_game/types/unit_type.cpp b/source/glest_game/types/unit_type.cpp index 624159f82..3259db825 100644 --- a/source/glest_game/types/unit_type.cpp +++ b/source/glest_game/types/unit_type.cpp @@ -521,7 +521,9 @@ void UnitType::computeFirstStOfClass(){ } } -void UnitType::computeFirstCtOfClass(){ +void UnitType::computeFirstCtOfClass(){ + printf("In [%s::%s Line: %d] \n",__FILE__,__FUNCTION__,__LINE__); + for(int j=0; j pathList = config.getPathListForType(ptMaps); + for(int idx = 0; idx < pathList.size(); idx++) { + const string &map_path = pathList[idx]; + const string mega = map_path + "/" + mapName + ".mgm"; + const string glest = map_path + "/" + mapName + ".gbm"; + if (fileExists(mega)) { + return mega; + } + else if (fileExists(glest)) { + return glest; + } + } + + throw runtime_error("Map " + mapName + " not found."); } // ===================================================== diff --git a/source/glest_game/world/scenario.cpp b/source/glest_game/world/scenario.cpp new file mode 100644 index 000000000..683c2bdd0 --- /dev/null +++ b/source/glest_game/world/scenario.cpp @@ -0,0 +1,101 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2005 Martiño Figueroa +// +// You can redistribute this code 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 +// ============================================================== + +#include "scenario.h" + +#include + +#include "logger.h" +#include "xml_parser.h" +#include "util.h" +#include "game_util.h" +#include "leak_dumper.h" +#include + +using namespace Shared::Xml; +using namespace Shared::Util; +using namespace std; + +namespace Glest{ namespace Game{ + +// ===================================================== +// class Scenario +// ===================================================== + +Scenario::~Scenario(){ + +} + +void Scenario::load(const string &path){ + try{ + string name= cutLastExt(lastDir(path)); + Logger::getInstance().add("Scenario: "+formatString(name), true); + + //parse xml + XmlTree xmlTree; + xmlTree.load(path); + const XmlNode *scenarioNode= xmlTree.getRootNode(); + const XmlNode *scriptsNode= scenarioNode->getChild("scripts"); + + for(int i= 0; igetChildCount(); ++i){ + const XmlNode *scriptNode = scriptsNode->getChild(i); + + scripts.push_back(Script(getFunctionName(scriptNode), scriptNode->getText())); + } + } + //Exception handling (conversions and so on); + catch(const exception &e){ + throw runtime_error("Error: " + path + "\n" + e.what()); + } +} + +int Scenario::getScenarioPathIndex(const vector dirList, const string &scenarioName) { + int iIndex = 0; + for(int idx = 0; idx < dirList.size(); idx++) { + string scenarioFile = dirList[idx] + "/" + scenarioName + "/" + scenarioName + ".xml"; + if(fileExists(scenarioFile) == true) { + iIndex = idx; + break; + } + } + + return iIndex; +} + +string Scenario::getScenarioPath(const vector dirList, const string &scenarioName){ + string scenarioFile = ""; + for(int idx = 0; idx < dirList.size(); idx++) { + scenarioFile = dirList[idx] + "/" + scenarioName + "/" + scenarioName + ".xml"; + if(fileExists(scenarioFile) == true) { + break; + } + } + + return scenarioFile; +} + +string Scenario::getScenarioPath(const string &dir, const string &scenarioName){ + string scenarioFile = dir + "/" + scenarioName + "/" + scenarioName + ".xml"; + //printf("dir [%s] scenarioName [%s] scenarioFile [%s]\n",dir.c_str(),scenarioName.c_str(),scenarioFile.c_str()); + + return scenarioFile; +} + +string Scenario::getFunctionName(const XmlNode *scriptNode){ + string name= scriptNode->getName(); + + for(int i= 0; igetAttributeCount(); ++i){ + name+= "_" + scriptNode->getAttribute(i)->getValue(); + } + return name; +} + +}}//end namespace diff --git a/source/glest_game/world/scenario.h b/source/glest_game/world/scenario.h new file mode 100644 index 000000000..784fb48f8 --- /dev/null +++ b/source/glest_game/world/scenario.h @@ -0,0 +1,72 @@ +// ============================================================== +// This file is part of Glest (www.glest.org) +// +// Copyright (C) 2001-2005 Martiño Figueroa +// +// You can redistribute this code 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 +// ============================================================== + +#ifndef _GLEST_GAME_SCENARIO_H_ +#define _GLEST_GAME_SCENARIO_H_ + +#include +#include + +#include "xml_parser.h" + +using std::string; +using std::vector; +using std::pair; + +using Shared::Xml::XmlNode; + +namespace Glest{ namespace Game{ + +// ===================================================== +// class Script +// ===================================================== + +class Script{ +private: + string name; + string code; + +public: + Script(const string &name, const string &code) {this->name= name; this->code= code;} + + const string &getName() const {return name;} + const string &getCode() const {return code;} +}; + +// ===================================================== +// class Scenario +// ===================================================== + +class Scenario{ +private: + typedef pair NameScriptPair; + typedef vector