diff --git a/source/glest_game/game/commander.cpp b/source/glest_game/game/commander.cpp index 8dd88b11..8dc4ee6c 100644 --- a/source/glest_game/game/commander.cpp +++ b/source/glest_game/game/commander.cpp @@ -40,13 +40,14 @@ void Commander::init(World *world){ this->world= world; } -CommandResult Commander::tryGiveCommand(const Unit* unit, const CommandType *commandType, const Vec2i &pos, const UnitType* unitType, CardinalDir facing) const{ - NetworkCommand networkCommand(this->world,nctGiveCommand, unit->getId(), commandType->getId(), pos, unitType->getId(), facing); +CommandResult Commander::tryGiveCommand(const Unit* unit, const CommandType *commandType, const Vec2i &pos, const UnitType* unitType, CardinalDir facing, bool tryQueue) const{ + + NetworkCommand networkCommand(this->world,nctGiveCommand, unit->getId(), commandType->getId(), pos, unitType->getId(), -1, facing, tryQueue); return pushNetworkCommand(&networkCommand); } -CommandResult Commander::tryGiveCommand(const Selection *selection, CommandClass commandClass, const Vec2i &pos, const Unit *targetUnit) const{ - +CommandResult Commander::tryGiveCommand(const Selection *selection, CommandClass commandClass, const Vec2i &pos, const Unit *targetUnit, bool tryQueue) const{ + if(!selection->isEmpty()){ Vec2i refPos, currPos; CommandResultContainer results; @@ -61,7 +62,7 @@ CommandResult Commander::tryGiveCommand(const Selection *selection, CommandClass 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(this->world,nctGiveCommand, unitId, ct->getId(), currPos, -1, targetId); + NetworkCommand networkCommand(this->world,nctGiveCommand, unitId, ct->getId(), currPos, -1, targetId, -1, tryQueue); //every unit is ordered to a different pos CommandResult result= pushNetworkCommand(&networkCommand); @@ -78,7 +79,7 @@ CommandResult Commander::tryGiveCommand(const Selection *selection, CommandClass } } -CommandResult Commander::tryGiveCommand(const Selection *selection, const CommandType *commandType, const Vec2i &pos, const Unit *targetUnit) const{ +CommandResult Commander::tryGiveCommand(const Selection *selection, const CommandType *commandType, const Vec2i &pos, const Unit *targetUnit, bool tryQueue) const{ if(!selection->isEmpty() && commandType!=NULL){ Vec2i refPos; CommandResultContainer results; @@ -90,7 +91,7 @@ CommandResult Commander::tryGiveCommand(const Selection *selection, const Comman 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(this->world,nctGiveCommand, unitId, commandType->getId(), currPos, -1, targetId); + NetworkCommand networkCommand(this->world,nctGiveCommand, unitId, commandType->getId(), currPos, -1, targetId, -1, tryQueue); //every unit is ordered to a different position CommandResult result= pushNetworkCommand(&networkCommand); @@ -105,7 +106,7 @@ CommandResult Commander::tryGiveCommand(const Selection *selection, const Comman } //auto command -CommandResult Commander::tryGiveCommand(const Selection *selection, const Vec2i &pos, const Unit *targetUnit) const{ +CommandResult Commander::tryGiveCommand(const Selection *selection, const Vec2i &pos, const Unit *targetUnit, bool tryQueue) const{ if(!selection->isEmpty()){ Vec2i refPos, currPos; @@ -125,7 +126,7 @@ CommandResult Commander::tryGiveCommand(const Selection *selection, const Vec2i if(commandType!=NULL){ int targetId= targetUnit==NULL? Unit::invalidId: targetUnit->getId(); int unitId= selection->getUnit(i)->getId(); - NetworkCommand networkCommand(this->world,nctGiveCommand, unitId, commandType->getId(), currPos, -1, targetId); + NetworkCommand networkCommand(this->world,nctGiveCommand, unitId, commandType->getId(), currPos, -1, targetId, -1, tryQueue); CommandResult result= pushNetworkCommand(&networkCommand); results.push_back(result); @@ -196,7 +197,7 @@ CommandResult Commander::computeResult(const CommandResultContainer &results) co if(results[i]!=crSuccess){ return crSomeFailed; } - } + }http://de.wikipedia.org/wiki/Iatrogen return crSuccess; } } @@ -309,7 +310,7 @@ void Commander::giveNetworkCommand(NetworkCommand* networkCommand) const { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] found nctGiveCommand networkCommand->getUnitId() = %d\n",__FILE__,__FUNCTION__,__LINE__,networkCommand->getUnitId()); Command* command= buildCommand(networkCommand); - unit->giveCommand(command); + unit->giveCommand(command, networkCommand->getWantQueue()); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] found nctGiveCommand networkCommand->getUnitId() = %d\n",__FILE__,__FUNCTION__,__LINE__,networkCommand->getUnitId()); } diff --git a/source/glest_game/game/commander.h b/source/glest_game/game/commander.h index e94ebfd0..c512e37b 100644 --- a/source/glest_game/game/commander.h +++ b/source/glest_game/game/commander.h @@ -50,10 +50,10 @@ public: void init(World *world); void updateNetwork(); - CommandResult tryGiveCommand(const Unit* unit, const CommandType *commandType, const Vec2i &pos, const UnitType* unitType, CardinalDir facing) 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 tryGiveCommand(const Unit* unit, const CommandType *commandType, const Vec2i &pos, const UnitType* unitType, CardinalDir facing, bool tryQueue = false) const; + CommandResult tryGiveCommand(const Selection *selection, CommandClass commandClass, const Vec2i &pos= Vec2i(0), const Unit *targetUnit= NULL, bool tryQueue = false) const; + CommandResult tryGiveCommand(const Selection *selection, const CommandType *commandType, const Vec2i &pos= Vec2i(0), const Unit *targetUnit= NULL, bool tryQueue = false) const; + CommandResult tryGiveCommand(const Selection *selection, const Vec2i &pos, const Unit *targetUnit= NULL, bool tryQueue = false) const; CommandResult tryCancelCommand(const Selection *selection) const; void trySetMeetingPoint(const Unit* unit, const Vec2i &pos) const; CommandResult pushNetworkCommand(const NetworkCommand* networkCommand) const; diff --git a/source/glest_game/gui/gui.cpp b/source/glest_game/gui/gui.cpp index 78693af6..18cacec5 100644 --- a/source/glest_game/gui/gui.cpp +++ b/source/glest_game/gui/gui.cpp @@ -371,11 +371,12 @@ void Gui::onSelectionChanged(){ void Gui::giveOneClickOrders(){ CommandResult result; + bool shiftDown = isKeyDown(vkShift); if(selection.isUniform()){ - result= commander->tryGiveCommand(&selection, activeCommandType); + result= commander->tryGiveCommand(&selection, activeCommandType, Vec2i(0), (Unit*)NULL, shiftDown); } else{ - result= commander->tryGiveCommand(&selection, activeCommandClass); + result= commander->tryGiveCommand(&selection, activeCommandClass, Vec2i(0), (Unit*)NULL, shiftDown); } addOrdersResultToConsole(activeCommandClass, result); activeCommandType= NULL; @@ -392,8 +393,9 @@ void Gui::giveDefaultOrders(int x, int y){ return; } + bool shiftDown = isKeyDown(vkShift); //give order - CommandResult result= commander->tryGiveCommand(&selection, targetPos, targetUnit); + CommandResult result= commander->tryGiveCommand(&selection, targetPos, targetUnit, shiftDown); //graphical result addOrdersResultToConsole(activeCommandClass, result); @@ -424,19 +426,20 @@ void Gui::giveTwoClickOrders(int x, int y){ return; } + bool shiftDown = isKeyDown(vkShift); //give orders to the units of this faction if(!selectingBuilding){ if(selection.isUniform()){ - result= commander->tryGiveCommand(&selection, activeCommandType, targetPos, targetUnit); + result= commander->tryGiveCommand(&selection, activeCommandType, targetPos, targetUnit,shiftDown); } else{ - result= commander->tryGiveCommand(&selection, activeCommandClass, targetPos, targetUnit); - } + result= commander->tryGiveCommand(&selection, activeCommandClass, targetPos, targetUnit,shiftDown); + } } else{ //selecting building result= commander->tryGiveCommand(selection.getFrontUnit(), - activeCommandType, posObjWorld, choosenBuildingType, selectedBuildingFacing ); + activeCommandType, posObjWorld, choosenBuildingType, selectedBuildingFacing,shiftDown); } //graphical result diff --git a/source/glest_game/network/network_types.cpp b/source/glest_game/network/network_types.cpp index c19e07be..46cbb426 100644 --- a/source/glest_game/network/network_types.cpp +++ b/source/glest_game/network/network_types.cpp @@ -27,13 +27,14 @@ namespace Glest{ namespace Game{ // class NetworkCommand // ===================================================== -NetworkCommand::NetworkCommand(World *world, int networkCommandType, int unitId, int commandTypeId, const Vec2i &pos, int unitTypeId, int targetId, int facing) +NetworkCommand::NetworkCommand(World *world, int networkCommandType, int unitId, int commandTypeId, const Vec2i &pos, int unitTypeId, int targetId, int facing, bool wantQueue) : networkCommandType(networkCommandType) , unitId(unitId) , commandTypeId(commandTypeId) , positionX(pos.x) , positionY(pos.y) - , unitTypeId(unitTypeId) { + , unitTypeId(unitTypeId) + , wantQueue(wantQueue) { assert(targetId == -1 || facing == -1); this->targetId = targetId >= 0 ? targetId : facing; @@ -72,8 +73,8 @@ void NetworkCommand::preprocessNetworkCommand(World *world) { string NetworkCommand::toString() const { char szBuf[1024]=""; - sprintf(szBuf,"networkCommandType = %d\nunitId = %d\ncommandTypeId = %d\npositionX = %d\nthis->positionY = %d\nunitTypeId = %d\ntargetId = %d", - networkCommandType,unitId,commandTypeId,positionX,this->positionY,unitTypeId,targetId); + sprintf(szBuf,"networkCommandType = %d\nunitId = %d\ncommandTypeId = %d\npositionX = %d\nthis->positionY = %d\nunitTypeId = %d\ntargetId = %d\nwantQueue= %d", + networkCommandType,unitId,commandTypeId,positionX,this->positionY,unitTypeId,targetId,wantQueue); string result = szBuf; return result; diff --git a/source/glest_game/network/network_types.h b/source/glest_game/network/network_types.h index adcb493f..29bd7a37 100644 --- a/source/glest_game/network/network_types.h +++ b/source/glest_game/network/network_types.h @@ -67,6 +67,7 @@ private: int16 positionY; int16 unitTypeId; int16 targetId; + int16 wantQueue; public: NetworkCommand(){}; @@ -78,7 +79,8 @@ public: const Vec2i &pos= Vec2i(0), int unitTypeId= -1, int targetId= -1, - int facing= -1); + int facing= -1, + bool wantQueue = false); //NetworkCommand(int networkCommandType, NetworkCommandSubType ncstType, int unitId, int value1, int value2=-1); @@ -88,6 +90,7 @@ public: Vec2i getPosition() const {return Vec2i(positionX, positionY);} int getUnitTypeId() const {return unitTypeId;} int getTargetId() const {return targetId;} + int getWantQueue() const {return wantQueue;} void preprocessNetworkCommand(World *world); string toString() const; diff --git a/source/glest_game/type_instances/unit.cpp b/source/glest_game/type_instances/unit.cpp index e5c5b743..de132504 100644 --- a/source/glest_game/type_instances/unit.cpp +++ b/source/glest_game/type_instances/unit.cpp @@ -98,13 +98,16 @@ Unit *UnitReference::getUnit() const{ // ===================================================== const float Unit::speedDivider= 100.f; -const int Unit::maxDeadCount= 500; //time in until the corpse disapears +const int Unit::maxDeadCount= 1000; //time in until the corpse disapears - should be about 40 seconds const float Unit::highlightTime= 0.5f; const int Unit::invalidId= -1; +set Unit::livingUnits; +set Unit::livingUnitsp; + // ============================ Constructor & destructor ============================= -Unit::Unit(int id, const Vec2i &pos, const UnitType *type, Faction *faction, Map *map, CardinalDir placeFacing) { +Unit::Unit(int id, const Vec2i &pos, const UnitType *type, Faction *faction, Map *map, CardinalDir placeFacing):id(id) { SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] START\n",__FILE__,__FUNCTION__); allowRotateUnits = Config::getInstance().getBool("AllowRotateUnits","0"); @@ -116,7 +119,6 @@ Unit::Unit(int id, const Vec2i &pos, const UnitType *type, Faction *faction, Map this->type=type; this->faction=faction; this->map= map; - this->id= id; level= NULL; setModelFacing(placeFacing); @@ -161,9 +163,22 @@ Unit::Unit(int id, const Vec2i &pos, const UnitType *type, Faction *faction, Map this->currSkill=getType()->getFirstStOfClass(scStop); //SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] END\n",__FILE__,__FUNCTION__); + livingUnits.insert(id); + livingUnitsp.insert(this); } Unit::~Unit(){ + //Just to be sure, should already be removed + if (livingUnits.erase(id)) { + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] START\n",__FILE__,__FUNCTION__); + //Only an error if not called at end + } + + //Just to be sure, should already be removed + if (livingUnitsp.erase(this)) { + SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] START\n",__FILE__,__FUNCTION__); + + } //remove commands while(!commands.empty()){ delete commands.back(); @@ -453,15 +468,15 @@ unsigned int Unit::getCommandSize() const{ } //give one command (clear, and push back) -CommandResult Unit::giveCommand(Command *command){ +CommandResult Unit::giveCommand(Command *command, bool tryQueue){ SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] START\n",__FILE__,__FUNCTION__); - if(command->getCommandType()->isQueuable()){ + if(command->getCommandType()->isQueuable(tryQueue)){ //cancel current command if it is not queuable SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); - if(!commands.empty() && !commands.front()->getCommandType()->isQueuable()){ + if(!commands.empty() && !commands.back()->getCommandType()->isQueueAppendable()){ SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d]\n",__FILE__,__FUNCTION__,__LINE__); cancelCommand(); } @@ -513,6 +528,15 @@ CommandResult Unit::finishCommand(){ commands.erase(commands.begin()); unitPath.clear(); + while (!commands.empty()) { + if (commands.front()->getUnit() != NULL && livingUnitsp.find(commands.front()->getUnit()) == livingUnitsp.end()) { + delete commands.front(); + commands.erase(commands.begin()); + } else { + break; + } + } + return crSuccess; } @@ -578,6 +602,8 @@ void Unit::kill(){ } void Unit::undertake(){ + livingUnits.erase(id); + livingUnitsp.erase(this); faction->removeUnit(this); } diff --git a/source/glest_game/type_instances/unit.h b/source/glest_game/type_instances/unit.h index e9dbc472..ebf95ca9 100644 --- a/source/glest_game/type_instances/unit.h +++ b/source/glest_game/type_instances/unit.h @@ -17,6 +17,7 @@ #include "particle.h" #include "skill_type.h" #include "game_constants.h" +#include namespace Glest{ namespace Game{ @@ -28,6 +29,8 @@ using Shared::Graphics::Vec3f; using Shared::Graphics::Vec2i; using Shared::Graphics::Model; +using std::set; + class Map; class Faction; class Unit; @@ -123,7 +126,7 @@ class Unit{ private: typedef list Commands; typedef list Observers; - typedef list UnitParticleSystems; + typedef list UnitParticleSystems; public: static const float speedDivider; @@ -131,9 +134,12 @@ public: static const float highlightTime; static const int invalidId; + static set livingUnits; + static set livingUnitsp; + private: - int id; + const int id; int hp; int ep; int loadCount; @@ -180,9 +186,9 @@ private: Observers observers; UnitParticleSystems unitParticleSystems; UnitParticleSystems damageParticleSystems; - - bool allowRotateUnits; - CardinalDir modelFacing; + + bool allowRotateUnits; + CardinalDir modelFacing; public: Unit(int id, const Vec2i &pos, const UnitType *type, Faction *faction, Map *map, CardinalDir placeFacing); @@ -266,7 +272,7 @@ public: bool anyCommand() const; Command *getCurrCommand() const; unsigned int getCommandSize() const; - CommandResult giveCommand(Command *command); //give a command + CommandResult giveCommand(Command *command, bool tryQueue = false); //give a command CommandResult finishCommand(); //command finished CommandResult cancelCommand(); //cancel canceled @@ -297,10 +303,10 @@ public: bool morph(const MorphCommandType *mct); CommandResult checkCommand(Command *command) const; void applyCommand(Command *command); - - void setModelFacing(CardinalDir value); - CardinalDir getModelFacing() { return modelFacing; } - + + void setModelFacing(CardinalDir value); + CardinalDir getModelFacing() { return modelFacing; } + private: float computeHeight(const Vec2i &pos) const; void updateTarget(); diff --git a/source/glest_game/types/command_type.h b/source/glest_game/types/command_type.h index 3d9785b6..087a2435 100644 --- a/source/glest_game/types/command_type.h +++ b/source/glest_game/types/command_type.h @@ -51,6 +51,13 @@ enum Clicks{ cTwo }; +enum Queueability { + qNever, + qOnRequest, + qOnlyLast, + qAlways +}; + // ===================================================== // class CommandType // @@ -72,7 +79,15 @@ public: 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;} + virtual Queueability isQueuable() const {return qOnRequest;} + bool isQueuable(bool tryQueue) const { + Queueability q = isQueuable(); + return (q == qAlways) || ((q == qOnRequest || q == qOnlyLast) && tryQueue); + } + bool isQueueAppendable() const { + Queueability q = isQueuable(); + return (q != qNever) && (q != qOnlyLast); + } //get CommandClass getClass() const; @@ -94,7 +109,7 @@ public: 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 Queueability isQueuable() const {return qNever;} //get const StopSkillType *getStopSkillType() const {return stopSkillType;}; }; @@ -213,6 +228,7 @@ public: 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 Queueability isQueuable() const {return qOnRequest;} //get const MoveSkillType *getMoveSkillType() const {return moveSkillType;} @@ -269,7 +285,7 @@ public: virtual string getReqDesc() const; virtual string toString() const; virtual const ProducibleType *getProduced() const; - virtual bool isQueuable() const {return true;} + virtual Queueability isQueuable() const {return qAlways;} //get const ProduceSkillType *getProduceSkillType() const {return produceSkillType;} @@ -294,7 +310,7 @@ public: virtual string toString() const; virtual string getReqDesc() const; virtual const ProducibleType *getProduced() const; - virtual bool isQueuable() const {return true;} + virtual Queueability isQueuable() const {return qOnRequest;} //get const UpgradeSkillType *getUpgradeSkillType() const {return upgradeSkillType;} @@ -319,6 +335,7 @@ public: virtual string toString() const; virtual string getReqDesc() const; virtual const ProducibleType *getProduced() const; + Queueability isQueuable() const {return qOnlyLast;} //After morph anything can happen //get const MorphSkillType *getMorphSkillType() const {return morphSkillType;}