Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatic assignment of units produced in factories to groups #3628

Merged
merged 18 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/basedef.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ struct BASE_OBJECT : public SIMPLE_OBJECT

SCREEN_DISP_DATA sDisplay; ///< screen coordinate details
UBYTE group = 0; ///< Which group selection is the droid currently in?
UBYTE repairGroup = UBYTE_MAX; ///< Group to be set when the unit has been repaired
UBYTE selected; ///< Whether the object is selected (might want this elsewhere)
UBYTE visible[MAX_PLAYERS]; ///< Whether object is visible to specific player
UBYTE seenThisTick[MAX_PLAYERS]; ///< Whether object has been seen this tick by the specific player.
Expand Down
10 changes: 10 additions & 0 deletions src/cmddroid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,13 @@ bool cmdDroidAddDroid(DROID *psCommander, DROID *psDroid)
ASSERT_OR_RETURN(false, psDroid != nullptr, "psDroid is null?");

auto initialDroidGroup = psDroid->group;
auto initialDroidRepairGroup = psDroid->repairGroup;

if (psCommander->psGroup == nullptr)
{
psGroup = grpCreate();
psGroup->add(psCommander);
psDroid->repairGroup = UBYTE_MAX;
psDroid->group = UBYTE_MAX;
}

Expand All @@ -103,6 +105,7 @@ bool cmdDroidAddDroid(DROID *psCommander, DROID *psDroid)
addedToGroup = true;

psCommander->psGroup->add(psDroid);
psDroid->repairGroup = UBYTE_MAX;
psDroid->group = UBYTE_MAX;

// set the secondary states for the unit
Expand All @@ -121,6 +124,13 @@ bool cmdDroidAddDroid(DROID *psCommander, DROID *psDroid)
addConsoleMessage(_("Commander needs a higher level to command more units"), DEFAULT_JUSTIFY, SYSTEM_MESSAGE);
lastMaxCmdLimitMsgTime = gameTime;
}

if (initialDroidGroup != UBYTE_MAX)
{
psDroid->group = initialDroidGroup;
SelectGroupDroid(psDroid);
}
psDroid->repairGroup = initialDroidRepairGroup;
}

if (initialDroidGroup != psDroid->group)
Expand Down
78 changes: 69 additions & 9 deletions src/display3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ static void displayDynamicObjects(const glm::mat4 &viewMatrix, const glm::mat4 &
static void displayStaticObjects(const glm::mat4 &viewMatrix, const glm::mat4 &perspectiveViewMatrix);
static void displayFeatures(const glm::mat4 &viewMatrix, const glm::mat4 &perspectiveViewMatrix);
static UDWORD getTargettingGfx();
static void drawDroidGroupNumber(DROID *psDroid);
static void drawGroupNumber(BASE_OBJECT *psObject);
static void trackHeight(int desiredHeight);
static void renderSurroundings(const glm::mat4& projectionMatrix, const glm::mat4 &skyboxViewMatrix);
static void locateMouse();
Expand Down Expand Up @@ -501,7 +501,7 @@ class BatchedObjectStatusRenderer
drawDroidRank(psDroid);
drawDroidSensorLock(psDroid);
drawDroidCmndNo(psDroid);
drawDroidGroupNumber(psDroid);
drawGroupNumber(psDroid);
}
}
// 3. weapon reload bar
Expand All @@ -517,6 +517,10 @@ class BatchedObjectStatusRenderer
{
drawStructureTargetOriginIcon(psStruct, i);
}
if (psStruct->isFactory())
{
drawGroupNumber(psStruct);
}
}
// 3. structure weapon reload bars
batchedMultiRectRenderer.drawRects(3);
Expand Down Expand Up @@ -3636,14 +3640,59 @@ static void drawDroidAndStructureSelections()
}

/* ---------------------------------------------------------------------------- */
/// X offset to display the group number at
/// X/Y offset to display the group number at
#define GN_X_OFFSET (8)
/// Draw the number of the group the droid is in next to the droid
static void drawDroidGroupNumber(DROID *psDroid)
#define GN_Y_OFFSET (3)
enum GROUPNUMBER_TYPE
{
GN_NORMAL,
GN_DAMAGED,
GN_FACTORY
};
/// rendering of the object's group next to the object itself,
/// or the group that will be assigned to the object after production in the factory
static void drawGroupNumber(BASE_OBJECT *psObject)
{
UWORD id = UWORD_MAX;
UBYTE groupNumber = UBYTE_MAX;
int32_t x = 0, y = 0;
GROUPNUMBER_TYPE groupNumberType = GN_NORMAL;

if (auto *psDroid = castDroid(psObject))
{
int32_t xShift = psDroid->sDisplay.screenR + GN_X_OFFSET;
int32_t yShift = psDroid->sDisplay.screenR;

switch (psDroid->group)
x = psDroid->sDisplay.screenX - xShift;
y = psDroid->sDisplay.screenY + yShift;

if (psDroid->repairGroup != UBYTE_MAX)
{
groupNumber = psDroid->repairGroup;
groupNumberType = GN_DAMAGED;
}
else
{
groupNumber = psDroid->group;
}
}
else if (auto *psStruct = castStructure(psObject))
{
// same as in queueStructureHealth
int32_t scale = static_cast<int32_t>(MAX(psStruct->pStructureType->baseWidth, psStruct->pStructureType->baseBreadth));
int32_t width = scale * 20;
int32_t scrX = psStruct->sDisplay.screenX;
int32_t scrY = static_cast<int32_t>(psStruct->sDisplay.screenY) + (scale * 10);
int32_t scrR = width;

x = scrX - scrR - GN_X_OFFSET;
y = scrY - GN_Y_OFFSET;

groupNumber = psStruct->productToGroup;
groupNumberType = GN_FACTORY;
}

switch (groupNumber)
{
case 0:
id = IMAGE_GN_0;
Expand Down Expand Up @@ -3681,9 +3730,20 @@ static void drawDroidGroupNumber(DROID *psDroid)

if (id != UWORD_MAX)
{
int xShift = psDroid->sDisplay.screenR + GN_X_OFFSET;
int yShift = psDroid->sDisplay.screenR;
iV_DrawImage(IntImages, id, psDroid->sDisplay.screenX - xShift, psDroid->sDisplay.screenY + yShift);
switch (groupNumberType)
{
case GN_NORMAL:
iV_DrawImage(IntImages, id, x, y);
break;
case GN_DAMAGED:
iV_DrawImageTint(IntImages, id, x, y, pal_RGBA(255, 0, 0, 255) /* red */);
break;
case GN_FACTORY:
iV_DrawImageTint(IntImages, id, x, y, pal_RGBA(255, 220, 115, 255) /* gold */);
break;
default:
break;
}
}
}

Expand Down
99 changes: 90 additions & 9 deletions src/droid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ void recycleDroid(DROID *psDroid)
{
addEffect(&position, EFFECT_EXPLOSION, EXPLOSION_TYPE_DISCOVERY, false, nullptr, false, gameTime - deltaGameTime + 1);
}

CHECK_DROID(psDroid);
}

Expand Down Expand Up @@ -874,7 +874,7 @@ void droidUpdate(DROID *psDroid)
droidUpdateDroidSelfRepair(psDroid);
}


/* Update the fire damage data */
if (psDroid->periodicalDamageStart != 0 && psDroid->periodicalDamageStart != gameTime - deltaGameTime) // -deltaGameTime, since projectiles are updated after droids.
{
Expand Down Expand Up @@ -1226,6 +1226,18 @@ int getRecoil(WEAPON const &weapon)
return 0;
}

/* Droid was completely repaired by another droid, auto-repair, or repair facility */
void droidWasFullyRepairedBase(DROID *psDroid)
{
if (psDroid->repairGroup != UBYTE_MAX)
{
psDroid->group = psDroid->repairGroup;
psDroid->repairGroup = UBYTE_MAX;
SelectGroupDroid(psDroid);
intGroupsChanged(psDroid->group); // update groups UI
}
}

void droidWasFullyRepaired(DROID *psDroid, const REPAIR_FACILITY *psRepairFac)
{
const bool prevWasRTR = psDroid->order.type == DORDER_RTR || psDroid->order.type == DORDER_RTR_SPECIFIED;
Expand All @@ -1247,7 +1259,9 @@ void droidWasFullyRepaired(DROID *psDroid, const REPAIR_FACILITY *psRepairFac)
objTrace(psDroid->id, "Repair complete - guarding the place at x=%i y=%i", psDroid->pos.x, psDroid->pos.y);
orderDroidLoc(psDroid, DORDER_GUARD, psDroid->pos.x, psDroid->pos.y, ModeImmediate);
}
}

droidWasFullyRepairedBase(psDroid);
}

bool droidUpdateRepair(DROID *psDroid)
{
Expand Down Expand Up @@ -1305,7 +1319,12 @@ static bool droidUpdateDroidRepairBase(DROID *psRepairDroid, DROID *psDroidToRep

CHECK_DROID(psRepairDroid);
/* if not finished repair return true else complete repair and return false */
return psDroidToRepair->body < psDroidToRepair->originalBody;
bool needMoreRepair = psDroidToRepair->body < psDroidToRepair->originalBody;
if (!needMoreRepair)
{
droidWasFullyRepairedBase(psDroidToRepair);
}
return needMoreRepair;
}

bool droidUpdateDroidRepair(DROID *psRepairDroid)
Expand Down Expand Up @@ -1829,7 +1848,8 @@ void templateSetParts(const DROID *psDroid, DROID_TEMPLATE *psTemplate)
}

/* Make all the droids for a certain player a member of a specific group */
void assignDroidsToGroup(UDWORD playerNumber, UDWORD groupNumber, bool clearGroup)
/* If a structure is selected, set its group to which droids will be automatically assigned */
void assignObjectToGroup(UDWORD playerNumber, UDWORD groupNumber, bool clearGroup)
{
bool bAtLeastOne = false;
size_t numCleared = 0;
Expand All @@ -1838,6 +1858,16 @@ void assignDroidsToGroup(UDWORD playerNumber, UDWORD groupNumber, bool clearGrou

if (groupNumber < UBYTE_MAX)
{
/* Run through all the structures */
for (STRUCTURE *psStruct : apsStructLists[playerNumber])
{
if (psStruct->selected && psStruct->isFactory())
{
psStruct->productToGroup = (UBYTE)groupNumber;
return;
}
}

/* Run through all the droids */
for (DROID* psDroid : apsDroidLists[playerNumber])
{
Expand All @@ -1853,6 +1883,7 @@ void assignDroidsToGroup(UDWORD playerNumber, UDWORD groupNumber, bool clearGrou
{
/* Set them to the right group - they can only be a member of one group */
psDroid->group = (UBYTE)groupNumber;
psDroid->repairGroup = UBYTE_MAX;
bAtLeastOne = true;
}
}
Expand Down Expand Up @@ -1880,17 +1911,27 @@ void assignDroidsToGroup(UDWORD playerNumber, UDWORD groupNumber, bool clearGrou
}


void removeDroidsFromGroup(UDWORD playerNumber)
void removeObjectFromGroup(UDWORD playerNumber)
{
unsigned removedCount = 0;

ASSERT_OR_RETURN(, playerNumber < MAX_PLAYERS, "Invalid player: %" PRIu32 "", playerNumber);

for (STRUCTURE *psStruct : apsStructLists[playerNumber])
{
if (psStruct->selected && psStruct->isFactory())
{
psStruct->productToGroup = UBYTE_MAX;
return;
}
}

for (DROID* psDroid : apsDroidLists[playerNumber])
{
if (psDroid->selected)
{
psDroid->group = UBYTE_MAX;
psDroid->repairGroup = UBYTE_MAX;
removedCount++;
}
}
Expand Down Expand Up @@ -3449,7 +3490,7 @@ bool isSelectable(DROID const *psDroid)

// Select a droid and do any necessary housekeeping.
//
void SelectDroid(DROID *psDroid)
void SelectDroid(DROID *psDroid, bool programmaticSelection)
{
if (!isSelectable(psDroid))
{
Expand All @@ -3458,8 +3499,48 @@ void SelectDroid(DROID *psDroid)

psDroid->selected = true;
intRefreshScreen();
triggerEventSelected();
jsDebugSelected(psDroid);
if (!programmaticSelection)
{
triggerEventSelected();
jsDebugSelected(psDroid);
}
}

// If all other droids with psGroupDroid's group are selected, add psGroupDroid to the selection after production/repair/etc.
//
void SelectGroupDroid(DROID *psGroupDroid)
{
std::vector<DROID*> groupDroids;
for (DROID *psDroid : apsDroidLists[psGroupDroid->player])
{
// skip itself because psGroupDroid may already exist in apsDroidLists
if (psDroid == psGroupDroid)
{
continue;
}
if (psDroid->group == psGroupDroid->group)
{
groupDroids.push_back(psDroid);
}
}

if (!groupDroids.empty())
{
bool bDoSelection = true;
for (DROID *psDroid : groupDroids)
{
if (!psDroid->selected)
{
bDoSelection = false;
break;
}
}

if (bDoSelection)
{
SelectDroid(psGroupDroid, true);
}
}
}

// De-select a droid and do any necessary housekeeping.
Expand Down
9 changes: 6 additions & 3 deletions src/droid.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,8 @@ DROID_TYPE droidType(const DROID *psDroid);
/* Return the type of a droid from it's template */
DROID_TYPE droidTemplateType(const DROID_TEMPLATE *psTemplate);

void assignDroidsToGroup(UDWORD playerNumber, UDWORD groupNumber, bool clearGroup);
void removeDroidsFromGroup(UDWORD playerNumber);
void assignObjectToGroup(UDWORD playerNumber, UDWORD groupNumber, bool clearGroup);
void removeObjectFromGroup(UDWORD playerNumber);

bool activateNoGroup(UDWORD playerNumber, const SELECTIONTYPE selectionType, const SELECTION_CLASS selectionClass, const bool bOnScreen);

Expand Down Expand Up @@ -278,7 +278,10 @@ void deleteTemplateFromProduction(DROID_TEMPLATE *psTemplate, unsigned player, Q
bool isSelectable(DROID const *psDroid);

// Select a droid and do any necessary housekeeping.
void SelectDroid(DROID *psDroid);
void SelectDroid(DROID *psDroid, bool programmaticSelection = false);

// If all other droids with psGroupDroid's group are selected, add psGroupDroid to the selection after production/repair/etc.
void SelectGroupDroid(DROID *psGroupDroid);

// De-select a droid and do any necessary housekeeping.
void DeSelectDroid(DROID *psDroid);
Expand Down
4 changes: 2 additions & 2 deletions src/hci/groups.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class GroupsUIController: public std::enable_shared_from_this<GroupsUIController
size_t numberCommandedByGroup = 0; // the number of droids commanded by commanders in this group
uint64_t totalGroupMaxHealth = 0;
DROID_TEMPLATE displayDroidTemplate;

uint8_t currAttackGlowAlpha = 0;

// used for calculating display info
Expand Down Expand Up @@ -94,7 +94,7 @@ class GroupsUIController: public std::enable_shared_from_this<GroupsUIController

void assignSelectedDroidsToGroup(size_t groupNumber)
{
assignDroidsToGroup(selectedPlayer, groupNumber, true);
assignObjectToGroup(selectedPlayer, groupNumber, true);
}

private:
Expand Down
Loading
Loading