diff --git a/docs/README.txt b/docs/README.txt index b5c9851b..19ca94fb 100644 --- a/docs/README.txt +++ b/docs/README.txt @@ -149,7 +149,7 @@ the default keyboard values). * Camera keyboard controls * -f => toggle free camera mode +y => toggle free camera mode w => move camera up (free camera mode only) s => move camera down (free camera mode only) a => rotate camera left (free camera mode only) @@ -185,21 +185,34 @@ n => show network status * Hotkeys (game camera mode only) * -a => activate attack command for selection -s => issue stop command to selection +, => activate attack command for selection +; => issue stop command to selection i => select next idle harvester b => select next building -d => select next damaged unit +u => select next damaged unit t => select next storage unit r => rotate building before placement +Unit commands can be activated using the keyboard by pressing corresponding +keys in the grid layout: + ++---+---+---+---+ +| q | w | e | r | ++---+---+---+---+ +| a | s | d | f | ++---+---+---+---+ +| z | x | c | v | ++---+---+---+---+ + +The position of the command for the selected unit (or group) in the UI +button grid corresponds to the key in the same position in the grid above. * Other Keys * - + => adjust game speed (disabled in multiplayer) p => pause game (disabled in multiplayer) -e => save screen shot to file -c => toggle ingame font color (and font shadow) +j => save screen shot to file +o => toggle ingame font color (and font shadow) m => show faded mesages again ? => when DebugMode=true, display debug info / => toggle mouse pointer rendering mode (OS/MG) diff --git a/mk/shared/glestkeys.ini b/mk/shared/glestkeys.ini index a3018425..1a5fd285 100644 --- a/mk/shared/glestkeys.ini +++ b/mk/shared/glestkeys.ini @@ -3,15 +3,15 @@ RenderInGamePerformance=` RenderNetworkStatus=N ShowFullConsole=M -Screenshot=E -FreeCameraMode=F +Screenshot=J +FreeCameraMode=Y ResetCameraMode=space CameraModeLeft=left CameraModeRight=right CameraModeUp=up CameraModeDown=down PauseGame=P -ChangeFontColor=C +ChangeFontColor=O GameSpeedIncrease='+' GameSpeedDecrease='-' ExitKey=escape @@ -30,16 +30,28 @@ CameraRotateLeft=A CameraRotateRight=D CameraRotateUp=S CameraRotateDown=W +CommandKey1=Q +CommandKey2=W +CommandKey3=E +CommandKey4=R +CommandKey5=A +CommandKey6=S +CommandKey7=D +CommandKey8=F +CommandKey9=Z +CommandKey10=X +CommandKey11=C +CommandKey12=V HotKeyCenterCameraOnSelection=G HotKeySelectIdleHarvesterUnit=I HotKeySelectBuiltBuilding=B HotKeyShowDebug=? HotKeyDumpWorldToLog=\ HotKeyRotateUnitDuringPlacement=R -HotKeySelectDamagedUnit=D +HotKeySelectDamagedUnit=U HotKeySelectStoreUnit=T -HotKeySelectedUnitsAttack=A -HotKeySelectedUnitsStop=S +HotKeySelectedUnitsAttack=, +HotKeySelectedUnitsStop=; HotKeyToggleOSMouseEnabled=/ ChatTeamMode=H ToggleHealthbars=# diff --git a/source/glest_game/gui/gui.cpp b/source/glest_game/gui/gui.cpp index ce6f79f6..7e86b46a 100644 --- a/source/glest_game/gui/gui.cpp +++ b/source/glest_game/gui/gui.cpp @@ -38,7 +38,7 @@ using namespace Shared::Util; namespace Glest{ namespace Game{ // ===================================================== -// class Mouse3d +// class Mouse3d // ===================================================== const float Mouse3d::fadeSpeed= 1.f/50.f; @@ -65,7 +65,7 @@ void Mouse3d::update(){ } // =============================== -// class SelectionQuad +// class SelectionQuad // =============================== SelectionQuad::SelectionQuad(){ @@ -89,7 +89,7 @@ void SelectionQuad::disable(){ } // ===================================================== -// class Gui +// class Gui // ===================================================== //constructor @@ -97,10 +97,10 @@ Gui::Gui(){ if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled) SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s] START\n",__FILE__,__FUNCTION__); lastGroupRecall = -1; - posObjWorld= Vec2i(54, 14); + posObjWorld= Vec2i(54, 14); validPosObjWorld= false; - activeCommandType= NULL; - activeCommandClass= ccStop; + activeCommandType= NULL; + activeCommandClass= ccStop; selectingBuilding= false; selectedBuildingFacing = CardinalDir(CardinalDir::NORTH); selectingPos= false; @@ -149,8 +149,8 @@ void Gui::end(){ // ==================== get ==================== const UnitType *Gui::getBuilding() const{ - assert(selectingBuilding); - return choosenBuildingType; + assert(selectingBuilding); + return choosenBuildingType; } const Object *Gui::getSelectedResourceObject() const{ if(selectedResourceObjectPos.x==-1){ @@ -196,17 +196,17 @@ bool Gui::isPlacingBuilding() const{ // ==================== set ==================== void Gui::invalidatePosObjWorld(){ - validPosObjWorld= false; + validPosObjWorld= false; } // ==================== reset state ==================== void Gui::resetState(){ - selectingBuilding= false; + selectingBuilding= false; selectedBuildingFacing = CardinalDir(CardinalDir::NORTH); selectingPos= false; selectingMeetingPoint= false; - activePos= invalidPos; + activePos= invalidPos; activeCommandClass= ccStop; activeCommandType= NULL; } @@ -215,9 +215,9 @@ void Gui::resetState(){ void Gui::update(){ - if(selectionQuad.isEnabled() && selectionQuad.getPosUp().dist(selectionQuad.getPosDown())>minQuadSize){ - computeSelected(false,false); - } + if(selectionQuad.isEnabled() && selectionQuad.getPosUp().dist(selectionQuad.getPosDown())>minQuadSize){ + computeSelected(false,false); + } mouse3d.update(); } @@ -408,45 +408,58 @@ void Gui::hotKey(SDL_KeyboardEvent key) { centerCameraOnSelection(); } //else if(key == configKeys.getCharKey("HotKeySelectIdleHarvesterUnit")) { - else if(isKeyPressed(configKeys.getSDLKey("HotKeySelectIdleHarvesterUnit"),key) == true) { + if(isKeyPressed(configKeys.getSDLKey("HotKeySelectIdleHarvesterUnit"),key) == true) { selectInterestingUnit(iutIdleHarvester); } //else if(key == configKeys.getCharKey("HotKeySelectBuiltBuilding")) { - else if(isKeyPressed(configKeys.getSDLKey("HotKeySelectBuiltBuilding"),key) == true) { + if(isKeyPressed(configKeys.getSDLKey("HotKeySelectBuiltBuilding"),key) == true) { selectInterestingUnit(iutBuiltBuilding); } //else if(key == configKeys.getCharKey("HotKeyDumpWorldToLog")) { - else if(isKeyPressed(configKeys.getSDLKey("HotKeyDumpWorldToLog"),key) == true) { + if(isKeyPressed(configKeys.getSDLKey("HotKeyDumpWorldToLog"),key) == true) { if(SystemFlags::getSystemSettingType(SystemFlags::debugSystem).enabled == true) { std::string worldLog = world->DumpWorldToLog(); SystemFlags::OutputDebug(SystemFlags::debugSystem,"In [%s::%s Line: %d] worldLog dumped to [%s]\n",__FILE__,__FUNCTION__,__LINE__,worldLog.c_str()); } } //else if(key == configKeys.getCharKey("HotKeyRotateUnitDuringPlacement")){ - else if(isKeyPressed(configKeys.getSDLKey("HotKeyRotateUnitDuringPlacement"),key) == true) { - // Here the user triggers a unit rotation while placing a unit - if(isPlacingBuilding()) { - if(getBuilding()->getRotationAllowed()){ + if(isKeyPressed(configKeys.getSDLKey("HotKeyRotateUnitDuringPlacement"),key) == true) { + // Here the user triggers a unit rotation while placing a unit + if(isPlacingBuilding()) { + if(getBuilding()->getRotationAllowed()){ ++selectedBuildingFacing; - } - } + } + } } //else if(key == configKeys.getCharKey("HotKeySelectDamagedUnit")) { - else if(isKeyPressed(configKeys.getSDLKey("HotKeySelectDamagedUnit"),key) == true) { + if(isKeyPressed(configKeys.getSDLKey("HotKeySelectDamagedUnit"),key) == true) { selectInterestingUnit(iutDamaged); } //else if(key == configKeys.getCharKey("HotKeySelectStoreUnit")) { - else if(isKeyPressed(configKeys.getSDLKey("HotKeySelectStoreUnit"),key) == true) { + if(isKeyPressed(configKeys.getSDLKey("HotKeySelectStoreUnit"),key) == true) { selectInterestingUnit(iutStore); } //else if(key == configKeys.getCharKey("HotKeySelectedUnitsAttack")) { - else if(isKeyPressed(configKeys.getSDLKey("HotKeySelectedUnitsAttack"),key) == true) { + if(isKeyPressed(configKeys.getSDLKey("HotKeySelectedUnitsAttack"),key) == true) { clickCommonCommand(ccAttack); } //else if(key == configKeys.getCharKey("HotKeySelectedUnitsStop")) { - else if(isKeyPressed(configKeys.getSDLKey("HotKeySelectedUnitsStop"),key) == true) { + if(isKeyPressed(configKeys.getSDLKey("HotKeySelectedUnitsStop"),key) == true) { clickCommonCommand(ccStop); } + + for (int i=0; igetClass() == ccBuild) { + mouseDownDisplayUnitBuild(i); + } else { + mouseDownDisplayUnitSkills(i); + } + computeDisplay(); + break; + } + } } void Gui::switchToNextDisplayColor(){ @@ -472,8 +485,10 @@ void Gui::giveOneClickOrders(){ result= commander->tryGiveCommand(&selection, activeCommandClass, Vec2i(0), (Unit*)NULL, queueKeyDown); } addOrdersResultToConsole(activeCommandClass, result); - activeCommandType= NULL; - activeCommandClass= ccStop; + activeCommandType= NULL; + activeCommandClass= ccStop; + selectingPos= false; + activePos= invalidPos; } void Gui::giveDefaultOrders(int x, int y) { @@ -543,7 +558,7 @@ void Gui::giveTwoClickOrders(int x, int y , bool prepared) { } bool queueKeyDown = isKeyDown(queueCommandKey); - //give orders to the units of this faction + //give orders to the units of this faction if(selectingBuilding == false) { if(selection.isUniform()) { result= commander->tryGiveCommand(&selection, activeCommandType, @@ -552,14 +567,14 @@ void Gui::giveTwoClickOrders(int x, int y , bool prepared) { else { result= commander->tryGiveCommand(&selection, activeCommandClass, targetPos, targetUnit,queueKeyDown); - } + } } else { //selecting building result= commander->tryGiveCommand(&selection, activeCommandType, posObjWorld, choosenBuildingType, selectedBuildingFacing,queueKeyDown); - } + } //graphical result addOrdersResultToConsole(activeCommandClass, result); @@ -585,7 +600,7 @@ void Gui::centerCameraOnSelection() { } void Gui::selectInterestingUnit(InterestingUnitType iut) { - const Faction *thisFaction = world->getThisFaction(); + const Faction *thisFaction = world->getThisFaction(); const Unit* previousUnit = NULL; bool previousFound = true; @@ -654,30 +669,7 @@ void Gui::mouseDownDisplayUnitSkills(int posDisplay) { //uniform selection if(selection.isUniform()) { - const CommandType *ct = display.getCommandType(posDisplay); - - // try to switch to next attack type - if(activeCommandClass == ccAttack && activeCommandType!=NULL) { - - int maxI = unit->getType()->getCommandTypeCount(); - int cmdTypeId = activeCommandType->getId(); - int cmdTypeIdNext = cmdTypeId+1; - - while(cmdTypeIdNext != cmdTypeId) { - if(cmdTypeIdNext >= maxI) { - cmdTypeIdNext = 0; - } - const CommandType *ctype = display.getCommandType(cmdTypeIdNext); - if(ctype != NULL && ctype->getClass() == ccAttack) { - if(ctype != NULL && unit->getFaction()->reqsOk(ctype)) { - posDisplay=cmdTypeIdNext; - ct = display.getCommandType(posDisplay); - break; - } - } - cmdTypeIdNext++; - } - } + const CommandType *ct = display.getCommandType(posDisplay); if(ct != NULL && unit->getFaction()->reqsOk(ct)) { activeCommandType= ct; @@ -690,9 +682,7 @@ void Gui::mouseDownDisplayUnitSkills(int posDisplay) { return; } } - - //non uniform selection - else { + else {//non uniform selection activeCommandType= NULL; activeCommandClass= display.getCommandClass(posDisplay); if (activeCommandClass == ccAttack) { @@ -702,14 +692,17 @@ void Gui::mouseDownDisplayUnitSkills(int posDisplay) { } //give orders depending on command type - if(!selection.isEmpty()){ + if(activeCommandClass != ccNull){ const CommandType *ct= selection.getUnit(0)->getType()->getFirstCtOfClass(activeCommandClass); if (activeCommandClass == ccAttack) { ct = selection.getUnitFromCC(ccAttack)->getType()->getFirstCtOfClass(activeCommandClass); } + if(activeCommandType!=NULL && activeCommandType->getClass()==ccBuild){ assert(selection.isUniform()); selectingBuilding= true; + selectingPos= false; + activePos= invalidPos; } else if(ct->getClicks()==cOne){ invalidatePosObjWorld(); @@ -719,7 +712,7 @@ void Gui::mouseDownDisplayUnitSkills(int posDisplay) { selectingPos= true; activePos= posDisplay; } - } + } else { posDisplay= invalidPos;} } else{ activePos= posDisplay; @@ -743,8 +736,8 @@ void Gui::mouseDownDisplayUnitBuild(int posDisplay) { activeCommandType->getClass() == ccBuild) { const BuildCommandType *bct = dynamic_cast(activeCommandType); - if(bct != NULL) { - const UnitType *ut = bct->getBuilding(posDisplay); + if(bct != NULL && bct->getBuildingCount() > posDisplay) { + const UnitType *ut = bct->getBuilding(posDisplay); const Unit *unit = selection.getFrontUnit(); if(unit != NULL && unit->getFaction() != NULL) { @@ -754,7 +747,7 @@ void Gui::mouseDownDisplayUnitBuild(int posDisplay) { choosenBuildingType = ut; selectingPos = true; - selectedBuildingFacing = CardinalDir(CardinalDir::NORTH); + selectedBuildingFacing = CardinalDir(CardinalDir::NORTH); activePos = posDisplay; } } @@ -784,8 +777,14 @@ void Gui::computeInfoString(int posDisplay){ lastPosDisplay = posDisplay; display.setInfoText(computeDefaultInfoString()); + Config &configKeys = Config::getInstance(std::pair(cfgMainKeys,cfgUserKeys)); + string commandKeyName = "CommandKey" + intToStr(posDisplay+1); if(posDisplay!=invalidPos && selection.isCommandable()){ + string hotkey = ""; + if (posDisplay < commandKeys) { + hotkey=lang.getString("HotKey")+": "+SDL_GetKeyName(configKeys.getSDLKey(commandKeyName.c_str())) +"\n\n"; + } if(!selectingBuilding){ if(posDisplay==cancelPos){ display.setInfoText(lang.getString("Cancel")); @@ -801,10 +800,10 @@ void Gui::computeInfoString(int posDisplay){ if(ct!=NULL){ if(unit->getFaction()->reqsOk(ct)){ - display.setInfoText(ct->getDesc(unit->getTotalUpgrade(),game->showTranslatedTechTree())); + display.setInfoText(hotkey+ct->getDesc(unit->getTotalUpgrade(),game->showTranslatedTechTree())); } else{ - display.setInfoText(ct->getReqDesc(game->showTranslatedTechTree())); + display.setInfoText(hotkey+ct->getReqDesc(game->showTranslatedTechTree())); if(ct->getClass()==ccUpgrade){ string text=""; const UpgradeCommandType *uct= static_cast(ct); @@ -814,20 +813,20 @@ void Gui::computeInfoString(int posDisplay){ else if(unit->getFaction()->getUpgradeManager()->isUpgraded(uct->getProducedUpgrade())){ text=lang.getString("AlreadyUpgraded")+"\n\n"; } - display.setInfoText(text+ct->getReqDesc(game->showTranslatedTechTree())); + display.setInfoText(hotkey+text+ct->getReqDesc(game->showTranslatedTechTree())); } //locked by scenario else if(ct->getClass()==ccProduce){ string text=""; const ProduceCommandType *pct= static_cast(ct); if(unit->getFaction()->isUnitLocked(pct->getProducedUnit())){ - display.setInfoText(lang.getString("LockedByScenario")+"\n\n"+ct->getReqDesc(game->showTranslatedTechTree())); + display.setInfoText(hotkey+lang.getString("LockedByScenario")+"\n\n"+ct->getReqDesc(game->showTranslatedTechTree())); } } else if(ct->getClass()==ccMorph){ const MorphCommandType *mct= static_cast(ct); if(unit->getFaction()->isUnitLocked(mct->getMorphUnit())){ - display.setInfoText(lang.getString("LockedByScenario")+"\n\n"+ct->getReqDesc(game->showTranslatedTechTree())); + display.setInfoText(hotkey+lang.getString("LockedByScenario")+"\n\n"+ct->getReqDesc(game->showTranslatedTechTree())); } } } @@ -859,19 +858,19 @@ void Gui::computeInfoString(int posDisplay){ const BuildCommandType *bct= static_cast(activeCommandType); const Unit *unit= selection.getFrontUnit(); if(unit->getFaction()->isUnitLocked(bct->getBuilding(posDisplay))){ - display.setInfoText(lang.getString("LockedByScenario")+"\n\n"+bct->getBuilding(posDisplay)->getReqDesc(game->showTranslatedTechTree())); + display.setInfoText(hotkey+lang.getString("LockedByScenario")+"\n\n"+bct->getBuilding(posDisplay)->getReqDesc(game->showTranslatedTechTree())); } else { bool translatedValue= game->showTranslatedTechTree(); const UnitType *building=bct->getBuilding(posDisplay); string str= lang.getString("BuildSpeed",(translatedValue == true ? "" : "english"))+": "+ intToStr(bct->getBuildSkillType()->getSpeed())+"\n"; - str+=""+Lang::getInstance().getString("TimeSteps",(translatedValue == true ? "" : "english"))+": "+intToStr(building->getProductionTime())+"\n"; - int64 speed=bct->getBuildSkillType()->getSpeed()+bct->getBuildSkillType()->getTotalSpeed(unit->getTotalUpgrade()); - int64 time=building->getProductionTime(); - int64 seconds=time*100/speed; - str+=""+Lang::getInstance().getString("Time",(translatedValue == true ? "" : "english"))+": "+intToStr(seconds); - str+="\n\n"; - str+=building->getReqDesc(translatedValue); - display.setInfoText(str); + str+=""+Lang::getInstance().getString("TimeSteps",(translatedValue == true ? "" : "english"))+": "+intToStr(building->getProductionTime())+"\n"; + int64 speed=bct->getBuildSkillType()->getSpeed()+bct->getBuildSkillType()->getTotalSpeed(unit->getTotalUpgrade()); + int64 time=building->getProductionTime(); + int64 seconds=time*100/speed; + str+=""+Lang::getInstance().getString("Time",(translatedValue == true ? "" : "english"))+": "+intToStr(seconds); + str+="\n\n"; + str+=building->getReqDesc(translatedValue); + display.setInfoText(hotkey+str); } } } @@ -970,10 +969,16 @@ void Gui::computeDisplay(){ if(u->isBuilt()){ //printf("u->isBuilt()\n"); - int morphPos= 8; - for(int i= 0; i < ut->getCommandTypeCount(); ++i){ + int morphPos= CommandHelper::getRowPos(crMorphs); + for(int i= 0; i < ut->getCommandTypeSortedCount(); ++i){ int displayPos= i; - const CommandType *ct= ut->getCommandType(i); + const CommandType *ct= ut->getCommandTypeSorted(i); + if(ct == NULL) { + display.setDownImage(displayPos, ut->getCancelImage()); + display.setCommandType(displayPos, ct); + display.setDownLighted(displayPos,false); + continue; + } if(ct->getClass() == ccMorph) { displayPos= morphPos++; } @@ -1022,27 +1027,40 @@ void Gui::computeDisplay(){ else{ //printf("selection.isUniform() == FALSE\n"); //non uniform selection - int lastCommand= 0; - for(int i= 0; i < ccCount; ++i){ - CommandClass cc= static_cast (i); + int basicPos = CommandHelper::getRowPos(crBasics); - //printf("computeDisplay i = %d cc = %d isshared = %d lastCommand = %d\n",i,cc,isSharedCommandClass(cc),lastCommand); + // First row is always empty + for (int i = 0; i < 5; i++) { + display.setDownImage(i, ut->getCancelImage()); + display.setCommandType(i, NULL); + display.setDownLighted(i,false); + } + + // only basics can be shared + for(auto &&cc : CommandHelper::getBasicsCC()){ + + //printf("computeDisplay i = %d cc = %d isshared = %d basicPos = %d\n",i,cc,isSharedCommandClass(cc),basicPos); const Unit* attackingUnit = NULL; if (cc == ccAttack) { attackingUnit = selection.getUnitFromCC(ccAttack); } + auto ccPos = CommandHelper::getBasicPos(cc); + if((cc == ccAttack && attackingUnit != NULL) || (isSharedCommandClass(cc) && cc != ccBuild)){ - display.setDownLighted(lastCommand, true); + display.setDownLighted(basicPos + ccPos, true); if (cc == ccAttack && attackingUnit != NULL) { - display.setDownImage(lastCommand, attackingUnit->getType()->getFirstCtOfClass(cc)->getImage()); + display.setDownImage(basicPos + ccPos, attackingUnit->getType()->getFirstCtOfClass(cc)->getImage()); } else { - display.setDownImage(lastCommand, ut->getFirstCtOfClass(cc)->getImage()); + display.setDownImage(basicPos + ccPos, ut->getFirstCtOfClass(cc)->getImage()); } - display.setCommandClass(lastCommand, cc); - lastCommand++; + display.setCommandClass(basicPos + ccPos, cc); + } else { + display.setDownImage(basicPos+ccPos, ut->getCancelImage()); + display.setCommandType(basicPos+ccPos, NULL); + display.setDownLighted(basicPos+ccPos,false); } } } @@ -1130,9 +1148,9 @@ int Gui::computePosDisplay(int x, int y){ } } else { - posDisplay= invalidPos; - //printf("In [%s:%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); - } + posDisplay= invalidPos; + //printf("In [%s:%s] Line: %d\n",__FILE__,__FUNCTION__,__LINE__); + } //printf("computePosDisplay returning = %d\n",posDisplay); @@ -1141,64 +1159,64 @@ int Gui::computePosDisplay(int x, int y){ void Gui::addOrdersResultToConsole(CommandClass cc, std::pair result) { - switch(result.first) { + switch(result.first) { case crSuccess: break; case crFailReqs: - switch(cc){ - case ccBuild: - console->addStdMessage("BuildingNoReqs",result.second); - break; - case ccProduce: - console->addStdMessage("UnitNoReqs",result.second); - break; - case ccMorph: - console->addStdMessage("MorphNoReqs",result.second); - break; - case ccUpgrade: - console->addStdMessage("UpgradeNoReqs",result.second); - break; - default: - break; - } - break; - case crFailRes: - switch(cc){ - case ccBuild: - console->addStdMessage("BuildingNoRes",result.second); - break; - case ccProduce: - console->addStdMessage("UnitNoRes",result.second); - break; - case ccMorph: - console->addStdMessage("MorphNoRes",result.second); - break; - case ccUpgrade: - console->addStdMessage("UpgradeNoRes",result.second); - break; + switch(cc){ + case ccBuild: + console->addStdMessage("BuildingNoReqs",result.second); + break; + case ccProduce: + console->addStdMessage("UnitNoReqs",result.second); + break; + case ccMorph: + console->addStdMessage("MorphNoReqs",result.second); + break; + case ccUpgrade: + console->addStdMessage("UpgradeNoReqs",result.second); + break; default: break; - } + } + break; + case crFailRes: + switch(cc){ + case ccBuild: + console->addStdMessage("BuildingNoRes",result.second); + break; + case ccProduce: + console->addStdMessage("UnitNoRes",result.second); + break; + case ccMorph: + console->addStdMessage("MorphNoRes",result.second); + break; + case ccUpgrade: + console->addStdMessage("UpgradeNoRes",result.second); + break; + default: + break; + } break; - case crFailUndefined: - console->addStdMessage("InvalidOrder",result.second); - break; + case crFailUndefined: + console->addStdMessage("InvalidOrder",result.second); + break; - case crSomeFailed: - console->addStdMessage("SomeOrdersFailed",result.second); - break; - } + case crSomeFailed: + console->addStdMessage("SomeOrdersFailed",result.second); + break; + } } bool Gui::isSharedCommandClass(CommandClass commandClass){ - for(int i=0; igetType()->getFirstCtOfClass(commandClass); + const CommandType *ct= unit->getType()->getFirstCtOfClass(commandClass); if(ct==NULL || !unit->getFaction()->reqsOk(ct)) - return false; - } - return true; + return false; + } + return true; } diff --git a/source/glest_game/gui/gui.h b/source/glest_game/gui/gui.h index c9c8905c..d44831b1 100644 --- a/source/glest_game/gui/gui.h +++ b/source/glest_game/gui/gui.h @@ -88,13 +88,14 @@ public: }; // ===================================================== -// class Gui +// class Gui // /// In game GUI // ===================================================== class Gui { public: + static const int commandKeys= 12; static const int maxSelBuff= 128*5; static const int upgradeDisplayIndex= 8; diff --git a/source/glest_game/types/command_type.cpp b/source/glest_game/types/command_type.cpp index b254a368..9b591949 100644 --- a/source/glest_game/types/command_type.cpp +++ b/source/glest_game/types/command_type.cpp @@ -31,6 +31,17 @@ using namespace Shared::Util; namespace Glest{ namespace Game{ +// ===================================================== +// class CommandHelper +// ===================================================== + +int CommandHelper::getBasicPos(CommandClass cc){ + auto basics = getBasicsCC(); + auto it = find(basics.begin(), basics.end(), cc); + if (it != basics.end()) + return it - basics.begin(); + else throw megaglest_runtime_error("Basics command have not class: " + intToStr(cc)); +} // ===================================================== // class CommandType diff --git a/source/glest_game/types/command_type.h b/source/glest_game/types/command_type.h index 913272c5..e367c1d9 100644 --- a/source/glest_game/types/command_type.h +++ b/source/glest_game/types/command_type.h @@ -54,6 +54,12 @@ enum CommandClass { ccNull }; +enum CommandRow { + crCores, + crBasics, + crMorphs, +}; + enum Clicks { cOne, cTwo @@ -66,6 +72,17 @@ enum Queueability { qAlways }; +class CommandHelper {// TODO put magic numbers to settings +public: + inline static int getRowPos(CommandRow cr) { return cr * 4; } + static int getBasicPos(CommandClass cc); + inline static vector getBasicsCC() { return { ccAttack, ccStop, ccMove, ccAttackStopped }; } + inline static vector getCoresCC() { return { ccAttack, ccProduce, ccUpgrade, ccSwitchTeam, ccHarvest, ccRepair, ccBuild }; } + +private: + CommandHelper(){ } +}; + // ===================================================== // class CommandType // diff --git a/source/glest_game/types/unit_type.cpp b/source/glest_game/types/unit_type.cpp index ca682ed7..ee7b3e03 100644 --- a/source/glest_game/types/unit_type.cpp +++ b/source/glest_game/types/unit_type.cpp @@ -880,6 +880,7 @@ void UnitType::loaddd(int id,const string &dir, const TechTree *techTree, } } } + sortCommandTypes(commandTypes); computeFirstStOfClass(); computeFirstCtOfClass(); @@ -1236,6 +1237,75 @@ void UnitType::computeFirstCtOfClass() { } } +void UnitType::sortCommandTypes(CommandTypes cts){ + try{ + CommandTypes ctCores, ctBasics = {NULL,NULL,NULL,NULL}, ctMorphs, ctAttack; + vector basicNulls = {0,1,2,3}; + + //Morphs + for(int i = (int)cts.size(); i --> 0; ) { + if(cts[i]->getClass() == ccMorph) { + ctMorphs.insert(ctMorphs.begin(), cts[i]); + cts.erase(cts.begin() + i); + } + } + + //Attacks + CommandTypeFilter(cts, ctAttack, ccAttack); + if(ctAttack.size() > 0) { + ctBasics[CommandHelper::getBasicPos(ccAttack)] = ctAttack[0];// first attack to basics + basicNulls.erase(basicNulls.begin()); + ctAttack.erase(ctAttack.begin());// another to cores, see below + } + + //Basics + for(int i = (int)cts.size(); i --> 0; ) { + for(auto &&cc : CommandHelper::getBasicsCC()){ + if(cc == ccAttack) continue;// we catch all attacks above + if(cts[i]->getClass() == cc) { + auto ccPos = CommandHelper::getBasicPos(cc); + ctBasics[ccPos] = cts[i]; + cts.erase(cts.begin() + i); + basicNulls.erase(std::remove(basicNulls.begin(), basicNulls.end(), ccPos), basicNulls.end()); + } + } + } + + //Cores + for(auto &&cc : CommandHelper::getCoresCC()){ + if(cc == ccAttack) ctCores.insert(ctCores.end(), ctAttack.begin(), ctAttack.end()); + else CommandTypeFilter(cts, ctCores, cc); + } + int nullCount = 4 - ctCores.size(); + for(int i=0; i 0; ) {// we push it to basics + ctBasics[basicNulls[i]] = ctToBasics[i]; + basicNulls.erase(basicNulls.begin() + i); + } + } + + commandTypesSorted.insert(commandTypesSorted.end(), ctCores.begin(), ctCores.end()); + commandTypesSorted.insert(commandTypesSorted.end(), ctBasics.begin(), ctBasics.end()); + commandTypesSorted.insert(commandTypesSorted.end(), ctMorphs.begin(), ctMorphs.end()); + } catch(exception &ex){ + + } +} + +void UnitType::CommandTypeFilter(CommandTypes &input, CommandTypes &output, CommandClass cc){ + std::copy_if(input.begin(), input.end(), std::back_inserter(output), [cc](CommandType* i) { + if(i->getClass() == cc) + return true; + else return false; + }); +} + const CommandType* UnitType::findCommandTypeById(int id) const{ const HarvestEmergencyReturnCommandType *result = dynamic_cast(ctHarvestEmergencyReturnCommandType.get()); if(result != NULL && id == result->getId()) { @@ -1260,6 +1330,15 @@ const CommandType *UnitType::getCommandType(int i) const { return commandTypes[i]; } +const CommandType *UnitType::getCommandTypeSorted(int i) const { + if(i >= (int)commandTypesSorted.size()) { + char szBuf[8096]=""; + snprintf(szBuf,8096,"In [%s::%s Line: %d] i >= commandTypesSorted.size(), i = %d, commandTypesSorted.size() = " MG_SIZE_T_SPECIFIER "",extractFileFromDirectoryPath(__FILE__).c_str(),__FUNCTION__,__LINE__,i,commandTypesSorted.size()); + throw megaglest_runtime_error(szBuf); + } + return commandTypesSorted[i]; +} + string UnitType::getCommandTypeListDesc() const { string desc = "Commands: "; for(int i=0; i