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

giftSingleStructure: Fixup functionality when transferring #3457

Merged
merged 2 commits into from
Nov 2, 2023
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
44 changes: 35 additions & 9 deletions src/objmem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -671,33 +671,59 @@ void addFlagPosition(FLAG_POSITION *psFlagPosToAdd)
apsFlagPosLists[psFlagPosToAdd->player] = psFlagPosToAdd;
}

/* Remove a Flag Position from the Lists */
void removeFlagPosition(FLAG_POSITION *psDel)
// Remove it from the list, but don't delete it!
static bool removeFlagPositionFromList(FLAG_POSITION *psRemove)
{
FLAG_POSITION *psPrev = nullptr, *psCurr;

ASSERT_OR_RETURN(, psDel != nullptr, "Invalid Flag Position pointer");
ASSERT_OR_RETURN(false, psRemove != nullptr, "Invalid Flag Position pointer");

if (apsFlagPosLists[psDel->player] == psDel)
if (apsFlagPosLists[psRemove->player] == psRemove)
{
apsFlagPosLists[psDel->player] = apsFlagPosLists[psDel->player]->psNext;
free(psDel);
apsFlagPosLists[psRemove->player] = apsFlagPosLists[psRemove->player]->psNext;
return true;
}
else
{
for (psCurr = apsFlagPosLists[psDel->player]; (psCurr != psDel) &&
(psCurr != nullptr); psCurr = psCurr->psNext)
for (psCurr = apsFlagPosLists[psRemove->player]; (psCurr != psRemove) &&
(psCurr != nullptr); psCurr = psCurr->psNext)
{
psPrev = psCurr;
}
if (psCurr != nullptr)
{
psPrev->psNext = psCurr->psNext;
free(psCurr);
return true;
}
}

return false;
}

/* Remove a Flag Position from the Lists */
void removeFlagPosition(FLAG_POSITION *psDel)
{
ASSERT_OR_RETURN(, psDel != nullptr, "Invalid Flag Position pointer");

if (removeFlagPositionFromList(psDel))
{
free(psDel);
}
else
{
ASSERT(false, "Did not find flag position in expected list?");
}
}

/* Transfer a Flag Position to a new player */
void transferFlagPositionToPlayer(FLAG_POSITION *psFlagPos, UDWORD originalPlayer, UDWORD newPlayer)
{
ASSERT_OR_RETURN(, psFlagPos != nullptr, "Invalid Flag Position pointer");
ASSERT(originalPlayer == psFlagPos->player, "Unexpected originalPlayer (%" PRIu32 ") does not match current flagPos->player (%" PRIu32 ")", originalPlayer, psFlagPos->player);
ASSERT(removeFlagPositionFromList(psFlagPos), "Did not find flag position in expected list?");
psFlagPos->player = newPlayer;
addFlagPosition(psFlagPos);
}

// free all flag positions
void freeAllFlagPositions()
Expand Down
2 changes: 2 additions & 0 deletions src/objmem.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ bool createFlagPosition(FLAG_POSITION **ppsNew, UDWORD player);
void addFlagPosition(FLAG_POSITION *psFlagPosToAdd);
/* Remove a Flag Position from the Lists */
void removeFlagPosition(FLAG_POSITION *psDel);
/* Transfer a Flag Position to a new player */
void transferFlagPositionToPlayer(FLAG_POSITION *psFlagPos, UDWORD originalPlayer, UDWORD newPlayer);
// free all flag positions
void freeAllFlagPositions();

Expand Down
120 changes: 120 additions & 0 deletions src/structure.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2044,6 +2044,124 @@ static bool setFunctionality(STRUCTURE *psBuilding, STRUCTURE_TYPE functionType)
return true;
}

static bool transferFixupFunctionality(STRUCTURE *psBuilding, STRUCTURE_TYPE functionType, UDWORD priorPlayer)
{
ASSERT_OR_RETURN(false, psBuilding != nullptr, "Invalid pointer");
CHECK_STRUCTURE(psBuilding);

switch (functionType)
{
case REF_FACTORY:
case REF_CYBORG_FACTORY:
case REF_VTOL_FACTORY:
case REF_RESEARCH:
case REF_POWER_GEN:
case REF_RESOURCE_EXTRACTOR:
case REF_REPAIR_FACILITY:
case REF_REARM_PAD:
case REF_WALL:
case REF_GATE:
// Structure should already have functionality
ASSERT_OR_RETURN(false, psBuilding->pFunctionality, "Structure does not already have functionality pointer?");
break;

default:
psBuilding->pFunctionality = nullptr;
break;
}

switch (functionType)
{
case REF_FACTORY:
case REF_CYBORG_FACTORY:
case REF_VTOL_FACTORY:
{
FACTORY *psFactory = &psBuilding->pFunctionality->factory;

// Reset factoryNumFlag for prior player
auto psAssemblyPoint = psFactory->psAssemblyPoint;
if (psAssemblyPoint != nullptr)
{
if (psAssemblyPoint->factoryInc < factoryNumFlag[priorPlayer][psAssemblyPoint->factoryType].size())
{
factoryNumFlag[priorPlayer][psAssemblyPoint->factoryType][psAssemblyPoint->factoryInc] = false;
}

//need to cancel the repositioning of the DP if selectedPlayer and currently moving
if (priorPlayer == selectedPlayer && psAssemblyPoint->selected)
{
cancelDeliveryRepos();
}
}

// Transfer / fix-up factory assembly point, and number
transferFlagPositionToPlayer(psFactory->psAssemblyPoint, priorPlayer, psBuilding->player);

switch (functionType)
{
case REF_FACTORY:
setFlagPositionInc(psBuilding->pFunctionality, psBuilding->player, FACTORY_FLAG);
break;
case REF_CYBORG_FACTORY:
setFlagPositionInc(psBuilding->pFunctionality, psBuilding->player, CYBORG_FLAG);
break;
case REF_VTOL_FACTORY:
setFlagPositionInc(psBuilding->pFunctionality, psBuilding->player, VTOL_FLAG);
break;
default:
ASSERT_OR_RETURN(false, false, "Invalid factory type");
}
break;
}
case REF_POWER_GEN:
case REF_HQ:
case REF_REARM_PAD:
{
break;
}
case REF_RESOURCE_EXTRACTOR:
{
RES_EXTRACTOR *psResExtracter = &psBuilding->pFunctionality->resourceExtractor;

// Make the structure inactive
psResExtracter->psPowerGen = nullptr;
break;
}
case REF_REPAIR_FACILITY:
{
REPAIR_FACILITY *psRepairFac = &psBuilding->pFunctionality->repairFacility;

// POSSIBLE TODO: Do something about the group? (Or can we just keep it?)

// Reset factoryNumFlag for prior player
auto psAssemblyPoint = psRepairFac->psDeliveryPoint;
if (psAssemblyPoint != nullptr)
{
if (psAssemblyPoint->factoryInc < factoryNumFlag[priorPlayer][psAssemblyPoint->factoryType].size())
{
factoryNumFlag[priorPlayer][psAssemblyPoint->factoryType][psAssemblyPoint->factoryInc] = false;
}

//need to cancel the repositioning of the DP if selectedPlayer and currently moving
if (priorPlayer == selectedPlayer && psAssemblyPoint->selected)
{
cancelDeliveryRepos();
}
}

// Transfer / fix-up factory assembly point, and number
transferFlagPositionToPlayer(psRepairFac->psDeliveryPoint, priorPlayer, psBuilding->player);

setFlagPositionInc(psBuilding->pFunctionality, psBuilding->player, REPAIR_FLAG);
break;
}
// Structure types without a FUNCTIONALITY
default:
break;
}

return true;
}

// Set the command droid that factory production should go to
void assignFactoryCommandDroid(STRUCTURE *psStruct, DROID *psCommander)
Expand Down Expand Up @@ -6723,6 +6841,8 @@ STRUCTURE *giftSingleStructure(STRUCTURE *psStructure, UBYTE attackPlayer, bool
}
}

transferFixupFunctionality(psStructure, psStructure->pStructureType->type, originalPlayer);

if (psStructure->status == SS_BUILT)
{
buildingComplete(psStructure);
Expand Down
Loading