diff --git a/data/_ui/tooltips.txt b/data/_ui/tooltips.txt index 52bcb3359295..9a233f3cfa18 100644 --- a/data/_ui/tooltips.txt +++ b/data/_ui/tooltips.txt @@ -1303,6 +1303,9 @@ tip "Fleet: Gather around me" `Command your fleet to gather around your flagship. If only some escorts are selected, only sends the command to those escorts. You can also command escorts to gather around another ship by right clicking on a friendly ship.` `With , change the formation pattern in your fleet.` +tip "Fleet: Toggle hold fire" + `Command your fleet to stop firing except if they are given a specific target to shoot at afterwards. If only some escorts are selected, only sends the command to those escorts.` + tip "Fleet: Hold position" `Command your fleet to hold its current position. If only some escorts are selected, only sends the command to those escorts. This command can also be sent by right clicking on empty space.` diff --git a/keys.txt b/keys.txt index 81848bcefcb5..886616ab38f5 100644 --- a/keys.txt +++ b/keys.txt @@ -25,6 +25,7 @@ "Toggle fast-forward" 1073741881 "Show help" 1073741882 "Fleet: Fight my target" 102 +"Fleet: Toggle hold fire" 121 "Fleet: Gather around me" 103 "Fleet: Hold position" 104 "Fleet: Toggle ammo usage" 117 diff --git a/source/AI.cpp b/source/AI.cpp index 26ef97851267..f3810f73ac6d 100644 --- a/source/AI.cpp +++ b/source/AI.cpp @@ -547,7 +547,12 @@ void AI::UpdateKeys(PlayerInfo &player, Command &activeCommands) } else if(activeCommands.Has(Command::FIGHT) && !shift && targetAsteroid) IssueAsteroidTarget(targetAsteroid); - if(activeCommands.Has(Command::HOLD) && !shift) + if(activeCommands.Has(Command::HOLD_FIRE) && !shift) + { + newOrders.SetHoldFire(); + IssueOrders(newOrders, "holding fire."); + } + if(activeCommands.Has(Command::HOLD_POSITION) && !shift) { newOrders.SetHoldPosition(); IssueOrders(newOrders, "holding position."); @@ -1410,8 +1415,13 @@ shared_ptr AI::FindTarget(const Ship &ship) const if(isYours) { auto it = orders.find(&ship); - if(it != orders.end() && (it->second.HasAttack() || it->second.HasFinishOff())) - return it->second.GetTargetShip(); + if(it != orders.end()) + { + if(it->second.HasAttack() || it->second.HasFinishOff()) + return it->second.GetTargetShip(); + else if(it->second.HasHoldFire()) + return target; + } } // If this ship is not armed, do not make it fight. @@ -3723,10 +3733,15 @@ void AI::AutoFire(const Ship &ship, FireCommand &command, bool secondary, bool i if(ship.IsYours()) { auto it = orders.find(&ship); - if(it != orders.end() && it->second.GetTargetShip() == currentTarget) + if(it != orders.end()) { - disabledOverride = (it->second.HasFinishOff()); - friendlyOverride = disabledOverride | (it->second.HasAttack()); + if(it->second.HasHoldFire()) + return; + if(it->second.GetTargetShip() == currentTarget) + { + disabledOverride = (it->second.HasFinishOff()); + friendlyOverride = disabledOverride || (it->second.HasAttack()); + } } } bool currentIsEnemy = currentTarget diff --git a/source/Command.cpp b/source/Command.cpp index d4985fa6fec1..ba543d2c655c 100644 --- a/source/Command.cpp +++ b/source/Command.cpp @@ -77,13 +77,14 @@ const Command Command::FASTFORWARD(ONE << 26, "Toggle fast-forward"); const Command Command::HELP(ONE << 27, "Show help"); const Command Command::FIGHT(ONE << 28, "Fleet: Fight my target"); const Command Command::GATHER(ONE << 29, "Fleet: Gather around me"); -const Command Command::HOLD(ONE << 30, "Fleet: Hold position"); -const Command Command::HARVEST(ONE << 31, "Fleet: Harvest flotsam"); -const Command Command::AMMO(ONE << 32, "Fleet: Toggle ammo usage"); -const Command Command::AUTOSTEER(ONE << 33, "Auto steer"); -const Command Command::WAIT(ONE << 34, ""); -const Command Command::STOP(ONE << 35, ""); -const Command Command::SHIFT(ONE << 36, ""); +const Command Command::HOLD_FIRE(ONE << 30, "Fleet: Toggle hold fire"); +const Command Command::HOLD_POSITION(ONE << 31, "Fleet: Hold position"); +const Command Command::HARVEST(ONE << 32, "Fleet: Harvest flotsam"); +const Command Command::AMMO(ONE << 33, "Fleet: Toggle ammo usage"); +const Command Command::AUTOSTEER(ONE << 34, "Auto steer"); +const Command Command::WAIT(ONE << 35, ""); +const Command Command::STOP(ONE << 36, ""); +const Command Command::SHIFT(ONE << 37, ""); @@ -271,7 +272,7 @@ void Command::Load(const DataNode &node) {"hail", Command::HAIL}, {"scan", Command::SCAN}, {"jump", Command::JUMP}, - {"mouseturninghold", Command::MOUSE_TURNING_HOLD}, + {"mouse turning hold", Command::MOUSE_TURNING_HOLD}, {"fleet jump", Command::FLEET_JUMP}, {"target", Command::TARGET}, {"nearest", Command::NEAREST}, @@ -284,7 +285,8 @@ void Command::Load(const DataNode &node) {"fastforward", Command::FASTFORWARD}, {"fight", Command::FIGHT}, {"gather", Command::GATHER}, - {"hold", Command::HOLD}, + {"hold fire", Command::HOLD_FIRE}, + {"hold position", Command::HOLD_POSITION}, {"ammo", Command::AMMO}, {"nearest asteroid", Command::NEAREST_ASTEROID}, {"wait", Command::WAIT}, diff --git a/source/Command.h b/source/Command.h index cd942bbfe8b1..9e81dcc9ab51 100644 --- a/source/Command.h +++ b/source/Command.h @@ -66,7 +66,8 @@ class Command { // Escort commands: static const Command FIGHT; static const Command GATHER; - static const Command HOLD; + static const Command HOLD_FIRE; + static const Command HOLD_POSITION; static const Command AMMO; static const Command HARVEST; // This command is given in combination with JUMP or LAND and tells a ship diff --git a/source/Orders.cpp b/source/Orders.cpp index 778ff1c2eafb..15b07b34b415 100644 --- a/source/Orders.cpp +++ b/source/Orders.cpp @@ -37,15 +37,22 @@ namespace { // the key order. If an order isn't present in the mask of the key order // then it will be set to false when the key order is given to a ship. const map ORDER_MASKS = { - {Orders::HOLD_POSITION, OrderSet(0)}, - {Orders::HOLD_ACTIVE, OrderSet(0)}, - {Orders::MOVE_TO, OrderSet(0)}, - {Orders::KEEP_STATION, OrderSet(0)}, - {Orders::GATHER, OrderSet(0)}, + {Orders::HOLD_POSITION, OrderSet(1 << Orders::HOLD_FIRE)}, + {Orders::HOLD_ACTIVE, OrderSet(1 << Orders::HOLD_FIRE)}, + {Orders::HOLD_FIRE, OrderSet( + (1 << Orders::HOLD_POSITION) + + (1 << Orders::HOLD_ACTIVE) + + (1 << Orders::MOVE_TO) + + (1 << Orders::KEEP_STATION) + + (1 << Orders::GATHER) + + (1 << Orders::HARVEST))}, + {Orders::MOVE_TO, OrderSet(1 << Orders::HOLD_FIRE)}, + {Orders::KEEP_STATION, OrderSet(1 << Orders::HOLD_FIRE)}, + {Orders::GATHER, OrderSet(1 << Orders::HOLD_FIRE)}, {Orders::ATTACK, OrderSet(0)}, {Orders::FINISH_OFF, OrderSet(0)}, {Orders::MINE, OrderSet(0)}, - {Orders::HARVEST, OrderSet(0)}, + {Orders::HARVEST, OrderSet(1 << Orders::HOLD_FIRE)}, }; } @@ -65,6 +72,13 @@ void Orders::SetHoldActive() +void Orders::SetHoldFire() +{ + ApplyOrder(OrderType::HOLD_FIRE); +} + + + void Orders::SetMoveTo() { ApplyOrder(OrderType::MOVE_TO); @@ -128,6 +142,13 @@ bool Orders::HasHoldActive() const +bool Orders::HasHoldFire() const +{ + return activeOrders.test(OrderType::HOLD_FIRE); +} + + + bool Orders::HasMoveTo() const { return activeOrders.test(OrderType::MOVE_TO); diff --git a/source/Orders.h b/source/Orders.h index c6dcff3c788a..7e61d4f578dd 100644 --- a/source/Orders.h +++ b/source/Orders.h @@ -35,6 +35,7 @@ class Orders { // HOLD_ACTIVE is the same command as HOLD_POSITION, but it is given when a ship // actively needs to move back to the position it was holding. HOLD_ACTIVE, + HOLD_FIRE, MOVE_TO, KEEP_STATION, GATHER, @@ -57,6 +58,7 @@ class Orders { // Set and get the active order types on this order. void SetHoldPosition(); void SetHoldActive(); + void SetHoldFire(); void SetMoveTo(); void SetKeepStation(); void SetGather(); @@ -67,6 +69,7 @@ class Orders { bool HasHoldPosition() const; bool HasHoldActive() const; + bool HasHoldFire() const; bool HasMoveTo() const; bool HasKeepStation() const; bool HasGather() const; diff --git a/source/PreferencesPanel.cpp b/source/PreferencesPanel.cpp index 95e18880c23b..92a90253c7a3 100644 --- a/source/PreferencesPanel.cpp +++ b/source/PreferencesPanel.cpp @@ -480,7 +480,8 @@ void PreferencesPanel::DrawControls() Command::DEPLOY, Command::FIGHT, Command::GATHER, - Command::HOLD, + Command::HOLD_FIRE, + Command::HOLD_POSITION, Command::AMMO, Command::HARVEST, Command::NONE,