// ============================================================== // 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 "selection.h" #include #include "unit_type.h" #include "gui.h" #include "config.h" #include "world.h" #include "leak_dumper.h" using namespace std; namespace Glest{ namespace Game{ // ===================================================== // class Selection // ===================================================== void Selection::init(Gui *gui, int factionIndex, int teamIndex) { this->factionIndex= factionIndex; this->teamIndex = teamIndex; this->gui= gui; } Selection::~Selection(){ clear(); } bool Selection::select(Unit *unit) { bool result = false; //check size //if(selectedUnits.size() >= maxUnits){ if(selectedUnits.size() >= Config::getInstance().getInt("MaxUnitSelectCount",intToStr(maxUnits).c_str())) { return result; } // Fix Bug reported on sourceforge.net: Glest::Game::Selection::select crash with NULL pointer - ID: 3608835 if(unit != NULL) { //check if already selected for(int i=0; i < selectedUnits.size(); ++i) { if(selectedUnits[i ]== unit) { return true; } } //check if dead if(unit->isDead()) { return false; } //check if multisel if(!unit->getType()->getMultiSelect() && !isEmpty()) { return false; } //check if enemy if(unit->getFactionIndex() != factionIndex && !isEmpty()) { return false; } //check existing enemy if(selectedUnits.size()==1 && selectedUnits.front()->getFactionIndex() != factionIndex) { clear(); } //check existing multisel if(selectedUnits.size()==1 && !selectedUnits.front()->getType()->getMultiSelect()){ clear(); } if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] unit selected [%s]\n",__FILE__,__FUNCTION__,__LINE__,unit->toString().c_str()); unit->addObserver(this); int unitTypeId=unit->getType()->getId(); bool inserted=false; for(int i=0; i < selectedUnits.size(); ++i) { int currentTypeId=selectedUnits[i]->getType()->getId(); if(unitTypeId<=currentTypeId) { //place unit here selectedUnits.insert(selectedUnits.begin()+i,unit); inserted=true; break; } else if(unitTypeId>currentTypeId) { //do nothing } } if( !inserted ){ selectedUnits.push_back(unit); } result = true; gui->onSelectionChanged(); } return result; } void Selection::select(const UnitContainer &units){ //add units to gui for(UnitIterator it= units.begin(); it!=units.end(); ++it){ select(*it); } } void Selection::unSelect(const UnitContainer &units){ //add units to gui for(UnitIterator it= units.begin(); it!=units.end(); ++it){ for(int i=0; ionSelectionChanged(); } void Selection::clear(){ //clear list selectedUnits.clear(); } bool Selection::isUniform() const{ if(selectedUnits.empty()){ return true; } const UnitType *ut= selectedUnits.front()->getType(); for(int i=0; igetType()!=ut){ return false; } } return true; } bool Selection::isEnemy() const { return selectedUnits.size() == 1 && selectedUnits.front()->getFactionIndex() != factionIndex; } bool Selection::isObserver() const { return selectedUnits.size() == 1 && (teamIndex == (GameConstants::maxPlayers -1 + fpt_Observer)); } bool Selection::isCommandable() const { //printf("\n\n\n\n********* selection.isCommandable() ---> isEmpty() [%d] isEnemy() [%d] selectedUnits.size() [%d]\n\n",isEmpty(),isEnemy(),(int)selectedUnits.size()); return !isEmpty() && !isEnemy() && !(selectedUnits.size()==1 && !selectedUnits.front()->isAlive()); } bool Selection::isCancelable() const{ return selectedUnits.size() > 1 || (selectedUnits.size() == 1 && selectedUnits[0]->anyCommand(true)); } bool Selection::isMeetable() const{ return isUniform() && isCommandable() && selectedUnits.front()->getType()->getMeetingPoint(); } Vec3f Selection::getRefPos() const{ return getFrontUnit()->getCurrVector(); } bool Selection::hasUnit(const Unit* unit) const{ return find(selectedUnits.begin(), selectedUnits.end(), unit)!=selectedUnits.end(); } void Selection::assignGroup(int groupIndex,const UnitContainer *pUnits) { if(groupIndex < 0 || groupIndex >= maxGroups) { throw megaglest_runtime_error("Invalid value for groupIndex = " + intToStr(groupIndex)); } //clear group groups[groupIndex].clear(); //assign new group const UnitContainer *addUnits = &selectedUnits; if(pUnits != NULL) { addUnits = pUnits; } for(unsigned int i = 0; i < addUnits->size(); ++i) { groups[groupIndex].push_back((*addUnits)[i]); } } void Selection::addUnitToGroup(int groupIndex,Unit *unit) { if(groupIndex < 0 || groupIndex >= maxGroups) { throw megaglest_runtime_error("Invalid value for groupIndex = " + intToStr(groupIndex)); } if(unit != NULL) { groups[groupIndex].push_back(unit); } } void Selection::removeUnitFromGroup(int groupIndex,int unitId) { if(groupIndex < 0 || groupIndex >= maxGroups) { throw megaglest_runtime_error("Invalid value for groupIndex = " + intToStr(groupIndex)); } for(unsigned int i = 0; i < groups[groupIndex].size(); ++i) { Unit *unit = groups[groupIndex][i]; if(unit != NULL && unit->getId() == unitId) { groups[groupIndex].erase(groups[groupIndex].begin() + i); break; } } } vector Selection::getUnitsForGroup(int groupIndex) { if(groupIndex < 0 || groupIndex >= maxGroups) { throw megaglest_runtime_error("Invalid value for groupIndex = " + intToStr(groupIndex)); } return groups[groupIndex]; } void Selection::recallGroup(int groupIndex){ if(groupIndex < 0 || groupIndex >= maxGroups) { throw megaglest_runtime_error("Invalid value for groupIndex = " + intToStr(groupIndex)); } clear(); for(int i=0; ionSelectionChanged(); } } } void Selection::saveGame(XmlNode *rootNode) const { std::map mapTagReplacements; XmlNode *selectionNode = rootNode->addChild("Selection"); // int factionIndex; selectionNode->addAttribute("factionIndex",intToStr(factionIndex), mapTagReplacements); // int teamIndex; selectionNode->addAttribute("teamIndex",intToStr(teamIndex), mapTagReplacements); // UnitContainer selectedUnits; for(unsigned int i = 0; i < selectedUnits.size(); i++) { Unit *unit = selectedUnits[i]; XmlNode *selectedUnitsNode = selectionNode->addChild("selectedUnits"); selectedUnitsNode->addAttribute("unitId",intToStr(unit->getId()), mapTagReplacements); } // UnitContainer groups[maxGroups]; for(unsigned int x = 0; x < maxGroups; ++x) { XmlNode *groupsNode = selectionNode->addChild("groups"); for(unsigned int i = 0; i < groups[x].size(); ++i) { Unit *unit = groups[x][i]; XmlNode *selectedUnitsNode = groupsNode->addChild("selectedUnits"); selectedUnitsNode->addAttribute("unitId",intToStr(unit->getId()), mapTagReplacements); } } // Gui *gui; } void Selection::loadGame(const XmlNode *rootNode, World *world) { const XmlNode *selectionNode = rootNode->getChild("Selection"); // vector fowPixmap1NodeList = minimapNode->getChildList("fowPixmap1"); // for(unsigned int i = 0; i < fowPixmap1NodeList.size(); ++i) { // XmlNode *fowPixmap1Node = fowPixmap1NodeList[i]; // // int pixelIndex = fowPixmap1Node->getAttribute("index")->getIntValue(); // fowPixmap1->getPixels()[pixelIndex] = fowPixmap1Node->getAttribute("pixel")->getIntValue(); // } // int factionIndex; factionIndex = selectionNode->getAttribute("factionIndex")->getIntValue(); // int teamIndex; teamIndex = selectionNode->getAttribute("teamIndex")->getIntValue(); // UnitContainer selectedUnits; // for(unsigned int i = 0; i < selectedUnits.size(); i++) { // Unit *unit = selectedUnits[i]; // // XmlNode *selectedUnitsNode = selectionNode->addChild("selectedUnits"); // selectedUnitsNode->addAttribute("id",intToStr(unit->getId()), mapTagReplacements); // } vector selectedUnitsNodeList = selectionNode->getChildList("selectedUnits"); for(unsigned int i = 0; i < selectedUnitsNodeList.size(); ++i) { XmlNode *selectedUnitsNode = selectedUnitsNodeList[i]; int unitId = selectedUnitsNode->getAttribute("unitId")->getIntValue(); Unit *unit = world->findUnitById(unitId); //assert(unit != NULL); //printf("#1 Unit [%s], group: %d\n",unit->getType()->getName().c_str(),i); selectedUnits.push_back(unit); } // UnitContainer groups[maxGroups]; // for(unsigned int x = 0; x < maxGroups; ++x) { // XmlNode *groupsNode = selectionNode->addChild("groups"); // for(unsigned int i = 0; i < groups[x].size(); ++i) { // Unit *unit = groups[x][i]; // // XmlNode *selectedUnitsNode = groupsNode->addChild("selectedUnits"); // selectedUnitsNode->addAttribute("unitId",intToStr(unit->getId()), mapTagReplacements); // } // } vector groupsNodeList = selectionNode->getChildList("groups"); for(unsigned int i = 0; i < groupsNodeList.size(); ++i) { XmlNode *groupsNode = groupsNodeList[i]; vector selectedGroupsUnitsNodeList = groupsNode->getChildList("selectedUnits"); for(unsigned int j = 0; j < selectedGroupsUnitsNodeList.size(); ++j) { XmlNode *selectedGroupsUnitsNode = selectedGroupsUnitsNodeList[j]; int unitId = selectedGroupsUnitsNode->getAttribute("unitId")->getIntValue(); Unit *unit = world->findUnitById(unitId); //assert(unit != NULL); //printf("Unit #2 [%s], group: %d\n",unit->getType()->getName().c_str(),i); groups[i].push_back(unit); } } // Gui *gui; } }}//end namespace