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

show rank for next droid #2727

Merged
merged 5 commits into from
Jul 5, 2022
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
74 changes: 38 additions & 36 deletions src/display3d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3935,47 +3935,49 @@ void showRangeAtPos(SDWORD centerX, SDWORD centerY, SDWORD radius)
bRangeDisplay = false;
}
}
UDWORD getDroidRankGraphicFromLevel(unsigned int level)
{
UDWORD gfxId = UDWORD_MAX;
switch (level)
{
case 0:
break;
case 1:
gfxId = IMAGE_LEV_0;
break;
case 2:
gfxId = IMAGE_LEV_1;
break;
case 3:
gfxId = IMAGE_LEV_2;
break;
case 4:
gfxId = IMAGE_LEV_3;
break;
case 5:
gfxId = IMAGE_LEV_4;
break;
case 6:
gfxId = IMAGE_LEV_5;
break;
case 7:
gfxId = IMAGE_LEV_6;
break;
case 8:
gfxId = IMAGE_LEV_7;
break;
default:
ASSERT(!"out of range droid rank", "Weird droid level in drawDroidRank");
break;
}

return gfxId;
}
/// Get the graphic ID for a droid rank
UDWORD getDroidRankGraphic(DROID *psDroid)
{
UDWORD gfxId = UDWORD_MAX;

/* Establish the numerical value of the droid's rank */
switch (getDroidLevel(psDroid))
{
case 0:
break;
case 1:
gfxId = IMAGE_LEV_0;
break;
case 2:
gfxId = IMAGE_LEV_1;
break;
case 3:
gfxId = IMAGE_LEV_2;
break;
case 4:
gfxId = IMAGE_LEV_3;
break;
case 5:
gfxId = IMAGE_LEV_4;
break;
case 6:
gfxId = IMAGE_LEV_5;
break;
case 7:
gfxId = IMAGE_LEV_6;
break;
case 8:
gfxId = IMAGE_LEV_7;
break;
default:
ASSERT(!"out of range droid rank", "Weird droid level in drawDroidRank");
break;
}

return gfxId;
return getDroidRankGraphicFromLevel(getDroidLevel(psDroid));
}

/** Will render a graphic depiction of the droid's present rank.
Expand Down
1 change: 1 addition & 0 deletions src/display3d.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ extern const Vector2i visibleTiles;

/*returns the graphic ID for a droid rank*/
UDWORD getDroidRankGraphic(DROID *psDroid);
UDWORD getDroidRankGraphicFromLevel(unsigned int level);

void setSkyBox(const char *page, float mywind, float myscale);

Expand Down
29 changes: 19 additions & 10 deletions src/droid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,14 @@ static void groupConsoleInformOfRemoval();
static void droidUpdateDroidSelfRepair(DROID *psRepairDroid);
static UDWORD calcDroidBaseBody(DROID *psDroid);

int getTopExperience(int player)
{
if (recycled_experience[player].size() == 0)
{
return 0;
}
return recycled_experience[player].top();
}
void cancelBuild(DROID *psDroid)
{
if (psDroid->order.type == DORDER_NONE || psDroid->order.type == DORDER_PATROL || psDroid->order.type == DORDER_HOLD || psDroid->order.type == DORDER_SCOUT || psDroid->order.type == DORDER_GUARD)
Expand Down Expand Up @@ -2142,17 +2150,13 @@ struct rankMap
const char *name; // name of this rank
};

unsigned int getDroidLevel(const DROID *psDroid)
unsigned int getDroidLevel(unsigned int experience, uint8_t player, uint8_t brainComponent)
{
unsigned int numKills = psDroid->experience / 65536;
unsigned int i;

// Search through the array of ranks until one is found
// which requires more kills than the droid has.
// Then fall back to the previous rank.
const BRAIN_STATS *psStats = getBrainStats(psDroid);
auto &vec = psStats->upgrade[psDroid->player].rankThresholds;
for (i = 1; i < vec.size(); ++i)
unsigned int numKills = experience / 65536;
const BRAIN_STATS *psStats = asBrainStats + brainComponent;
auto &vec = psStats->upgrade[player].rankThresholds;
ASSERT_OR_RETURN(0, vec.size() > 0, "rankThreshold was empty?");
for (int i = 1; i < vec.size(); ++i)
{
if (numKills < vec.at(i))
{
Expand All @@ -2164,6 +2168,11 @@ unsigned int getDroidLevel(const DROID *psDroid)
return vec.size() - 1;
}

unsigned int getDroidLevel(const DROID *psDroid)
{
return getDroidLevel(psDroid->experience, psDroid->player, psDroid->asBits[COMP_BRAIN]);
}

UDWORD getDroidEffectiveLevel(const DROID *psDroid)
{
UDWORD level = getDroidLevel(psDroid);
Expand Down
2 changes: 2 additions & 0 deletions src/droid.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ enum PICKTILE
extern DROID *psLastDroidHit;

std::priority_queue<int> copy_experience_queue(int player);
int getTopExperience(int player);
void add_to_experience_queue(int player, int value);

// initialise droid module
Expand Down Expand Up @@ -183,6 +184,7 @@ bool calcDroidMuzzleBaseLocation(const DROID *psDroid, Vector3i *muzzle, int wea

/* Droid experience stuff */
unsigned int getDroidLevel(const DROID *psDroid);
unsigned int getDroidLevel(unsigned int experience, uint8_t player, uint8_t brainComponent);
UDWORD getDroidEffectiveLevel(const DROID *psDroid);
const char *getDroidLevelName(const DROID *psDroid);

Expand Down
47 changes: 46 additions & 1 deletion src/hci/manufacture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
#include "manufacture.h"
#include "../mission.h"
#include "../qtscript.h"
#include "../display3d.h"

STRUCTURE *ManufactureController::highlightedFactory = nullptr;
static const uint8_t nullBrainComponent = 0; // "0" to reference "NULLxxx" components
static const uint8_t commandBrainComponent = 1; // hmm there is only 1 "CommandBrain01" anyway..

FACTORY *getFactoryOrNullptr(STRUCTURE *factory)
{
Expand Down Expand Up @@ -291,7 +294,6 @@ class ManufactureStatsButton: public StatsButton
auto production = getStats();
auto productionPending = factory && StructureIsManufacturingPending(factory);
auto objectImage = productionPending && production ? ImdObject::DroidTemplate(production): ImdObject::Component(nullptr);

displayIMD(AtlasImage(), objectImage, xOffset, yOffset);

if (productionPending && StructureIsOnHoldPending(factory))
Expand All @@ -302,6 +304,49 @@ class ManufactureStatsButton: public StatsButton
{
displayIfHighlight(xOffset, yOffset);
}
drawNextDroidRank(xOffset, yOffset);
}

// show a little icon on the bottom, indicating what rank next unit will be
// remember that when it's a commander, same rank will require twice experience
void drawNextDroidRank(int xOffset, int yOffset)
{
const auto factory = controller->getObjectAt(objectIndex);
if (!factory)
{
return;
}
const auto player = factory->player;
const auto exp = getTopExperience(player);
unsigned int lvl = 0;
if (!factory->pFunctionality->factory.psSubject)
{
// not showing icon when nothing is being built
return;
}
if (factory->pFunctionality->factory.psSubject->droidType == DROID_COMMAND)
{
lvl = getDroidLevel(exp, player, commandBrainComponent);
}
else if (factory->pFunctionality->factory.psSubject->droidType == DROID_CONSTRUCT
|| factory->pFunctionality->factory.psSubject->droidType == DROID_CYBORG_CONSTRUCT
|| factory->pFunctionality->factory.psSubject->droidType == DROID_CYBORG_REPAIR
|| factory->pFunctionality->factory.psSubject->droidType == DROID_REPAIR
|| factory->pFunctionality->factory.psSubject->droidType == DROID_TRANSPORTER
|| factory->pFunctionality->factory.psSubject->droidType == DROID_SUPERTRANSPORTER)
{
lvl = 0;
}
else
{
lvl = getDroidLevel(exp, player, nullBrainComponent);
}
const auto expgfx = getDroidRankGraphicFromLevel(lvl);
if (expgfx != UDWORD_MAX)
{
// FIXME: use offsets relative to template positon, not hardcoded values ?
iV_DrawImage(IntImages, (UWORD)expgfx, xOffset + 45, yOffset + 4);
}
}

void updateLayout() override
Expand Down