Build magma pump on right-click

If the player selects an engineer and right-clicks on a hot spot,
order the engineer to build a magma pump there.  More generally,
try to build something on top of the clicked unit.
This commit is contained in:
kon 2010-11-10 20:43:06 +00:00
parent 8989c431f5
commit 81dd5ca909
4 changed files with 77 additions and 3 deletions

View file

@ -134,8 +134,6 @@ static std::vector<CUnitType *> getReparableUnits()
*/
static void InitAiHelper(AiHelper &aiHelper)
{
extern std::vector<ButtonAction *> UnitButtonTable;
std::vector<CUnitType *> reparableUnits = getReparableUnits();
for (int i = 0; i < (int)UnitButtonTable.size(); ++i)

View file

@ -34,6 +34,7 @@
-- Declarations
----------------------------------------------------------------------------*/
#include <vector>
#include "icons.h"
/*----------------------------------------------------------------------------
@ -221,6 +222,9 @@ extern int DoubleClickDelay;
/// Time to detect hold clicks
extern int HoldClickDelay;
/// All buttons for units
extern std::vector<ButtonAction *> UnitButtonTable;
/*----------------------------------------------------------------------------
-- Functions
----------------------------------------------------------------------------*/
@ -347,6 +351,8 @@ extern void DrawTimer(void);
extern void UpdateTimer(void);
/// Update the status line with hints from the button
extern void UpdateStatusLineForButton(const ButtonAction *button);
/// Check if the button is allowed for the unit.
extern bool IsButtonAllowed(const CUnit *, const ButtonAction *);
/// Draw the Pie Menu
extern void DrawPieMenu(void);

View file

@ -508,7 +508,7 @@ void UpdateStatusLineForButton(const ButtonAction *button)
**
** @todo FIXME: better check. (dependancy, resource, ...)
*/
static bool IsButtonAllowed(const CUnit *unit, const ButtonAction *buttonaction)
bool IsButtonAllowed(const CUnit *unit, const ButtonAction *buttonaction)
{
bool res;

View file

@ -94,6 +94,70 @@ void CancelBuildingMode(void)
UI.ButtonPanel.Update();
}
/**
** Check whether ButtonAction::UnitMask includes the specified unit
** type. If not, the user cannot click that button to give an order
** to units of that type.
**
** Even if this function returns true, the button may still be
** disabled for other reasons; call ::IsButtonAllowed to check those.
*/
static bool IsButtonAllowedForUnitType(const CUnitType *type, const ButtonAction *button)
{
return button->UnitMask == "*"
|| button->UnitMask.find(',' + type->Ident + ',') != std::string::npos;
}
/**
** Find the unit type that @a builder could build on top of @a base.
**
** @param builder The unit who would like to build something.
** @param base The building would go on top of this unit.
**
** If nothing can be built there, or is not clear which type of unit
** should be built, this function returns NULL.
*/
static CUnitType *CanBuildSomethingOnTop(const CUnit *builder, const CUnit *base)
{
// This check should in principle be in DoRightButton,
// but doing it here is easier.
if (base == NULL)
{
return NULL;
}
CUnitType *foundType = NULL;
for (std::vector<ButtonAction *>::const_iterator
iterator = UnitButtonTable.begin();
iterator != UnitButtonTable.end(); ++iterator) {
const ButtonAction *const button = *iterator;
if (button->Action == ButtonBuild
&& IsButtonAllowedForUnitType(builder->Type, button)
&& IsButtonAllowed(builder, button))
{
// Which type of unit the player could build
// by clicking this button.
CUnitType *const buildingType = UnitTypes.at(button->Value);
if (CanBuildHere(builder, buildingType, base->X, base->Y) == base)
{
// buildingType can be built on top of base.
// But is it unambiguous?
if (foundType != NULL && buildingType != foundType)
{
// Oops, we already found a different
// type that could be built here.
// Better return neither.
return NULL;
}
foundType = buildingType;
}
}
}
return foundType;
}
/**
** Called when right button is pressed
**
@ -263,6 +327,12 @@ void DoRightButton(int sx, int sy)
SendCommandFollow(unit, dest, flush);
continue;
}
// Build on top of the clicked unit
CUnitType *buildingType = CanBuildSomethingOnTop(unit, dest);
if (buildingType != NULL) {
SendCommandBuildBuilding(unit, dest->X, dest->Y, buildingType, flush);
continue;
}
// Move
SendCommandMove(unit, x, y, flush);
continue;