Skip to content

Commit

Permalink
Allow researching topics which labs being upgraded are already resear…
Browse files Browse the repository at this point in the history
…ching.

If researching Kittens Mk2 in lab A, then Kittens Mk2 is unavailable for research in other labs. If upgrading lab
A, then Kittens Mk2 now becomes available for research in other labs, for the duration of lab A's upgrade. If
choosing Kittens Mk2 in lab B, then the research of Kittens Mk2 is cancelled in lab A, and the user must manually
select a new research topic for the lab, such as Puppies Mk3. Otherwise, lab A continues researching Kittens Mk2
once lab A is done upgrading, as usual. The same applies if lab A is being demolished, except that lab A cannot
continue researching after it has been demolished.

This is especially useful in the case of a lab upgrade being delayed due to loss of trucks.
  • Loading branch information
Cyp committed Aug 21, 2012
1 parent 0d333a1 commit 5bac6e4
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 19 deletions.
43 changes: 32 additions & 11 deletions src/multiplay.cpp
Expand Up @@ -928,6 +928,21 @@ bool sendResearchStatus(STRUCTURE *psBuilding, uint32_t index, uint8_t player, b
return true;
}

STRUCTURE *findResearchingFacilityByResearchIndex(unsigned player, unsigned index)
{
// Go through the structs to find the one doing this topic
for (STRUCTURE *psBuilding = apsStructLists[player]; psBuilding; psBuilding = psBuilding->psNext)
{
if (psBuilding->pStructureType->type == REF_RESEARCH
&& ((RESEARCH_FACILITY *)psBuilding->pFunctionality)->psSubject
&& ((RESEARCH_FACILITY *)psBuilding->pFunctionality)->psSubject->ref - REF_RESEARCH_START == index)
{
return psBuilding;
}
}
return NULL; // Not found.
}

bool recvResearchStatus(NETQUEUE queue)
{
STRUCTURE *psBuilding;
Expand Down Expand Up @@ -986,6 +1001,22 @@ bool recvResearchStatus(NETQUEUE queue)
cancelResearch(psBuilding, ModeImmediate);
}

if (IsResearchStarted(pPlayerRes))
{
STRUCTURE *psOtherBuilding = findResearchingFacilityByResearchIndex(player, index);
ASSERT(psOtherBuilding != NULL, "Something researched but no facility.");
if (psOtherBuilding != NULL)
{
cancelResearch(psOtherBuilding, ModeImmediate);
}
}

if (!researchAvailable(index, player, ModeImmediate) && bMultiPlayer)
{
debug(LOG_ERROR, "Player %d researching impossible topic \"%s\".", player, asResearch[index].pName);
return false;
}

// Set the subject up
pResearch = &asResearch[index];
psResFacilty->psSubject = pResearch;
Expand All @@ -1007,17 +1038,7 @@ bool recvResearchStatus(NETQUEUE queue)
// If they did not say what facility it was, look it up orselves
if (!structRef)
{
// Go through the structs to find the one doing this topic
for (psBuilding = apsStructLists[player]; psBuilding; psBuilding = psBuilding->psNext)
{
if (psBuilding->pStructureType->type == REF_RESEARCH
&& psBuilding->status == SS_BUILT
&& ((RESEARCH_FACILITY *) psBuilding->pFunctionality)->psSubject
&& ((RESEARCH_FACILITY *) psBuilding->pFunctionality)->psSubject->ref - REF_RESEARCH_START == index)
{
break;
}
}
psBuilding = findResearchingFacilityByResearchIndex(player, index);
}
else
{
Expand Down
2 changes: 2 additions & 0 deletions src/multiplay.h
Expand Up @@ -231,4 +231,6 @@ extern bool multiplayPlayersReady (bool bNotifyStatus);
extern void startMultiplayerGame (void);
extern void resetReadyStatus (bool bSendOptions);

STRUCTURE *findResearchingFacilityByResearchIndex(unsigned player, unsigned index);

#endif // __INCLUDED_SRC_MULTIPLAY_H__
4 changes: 2 additions & 2 deletions src/qtscriptfuncs.cpp
Expand Up @@ -574,7 +574,7 @@ static QScriptValue js_pursueResearch(QScriptContext *context, QScriptEngine *en
int iterations = 0; // Only used to assert we're not stuck in the loop.
while (cur)
{
if (researchAvailable(cur->index, player))
if (researchAvailable(cur->index, player, ModeQueue))
{
bool started = false;
for (int i = 0; i < game.maxPlayers; i++)
Expand Down Expand Up @@ -644,7 +644,7 @@ static QScriptValue js_enumResearch(QScriptContext *context, QScriptEngine *engi
for (int i = 0; i < asResearch.size(); i++)
{
RESEARCH *psResearch = &asResearch[i];
if (!IsResearchCompleted(&asPlayerResList[player][i]) && researchAvailable(i, player))
if (!IsResearchCompleted(&asPlayerResList[player][i]) && researchAvailable(i, player, ModeQueue))
{
reslist += psResearch;
}
Expand Down
29 changes: 24 additions & 5 deletions src/research.cpp
Expand Up @@ -597,21 +597,30 @@ bool loadResearchFunctions(const char *pFunctionData, UDWORD bufferSize)
return true;
}

bool researchAvailable(int inc, int playerID)
bool researchAvailable(int inc, int playerID, QUEUE_MODE mode)
{
// Decide whether to use IsResearchCancelledPending/IsResearchStartedPending or IsResearchCancelled/IsResearchStarted.
bool (*IsResearchCancelledFunc)(PLAYER_RESEARCH const *) = IsResearchCancelledPending;
bool (*IsResearchStartedFunc)(PLAYER_RESEARCH const *) = IsResearchStartedPending;
if (mode == ModeImmediate)
{
IsResearchCancelledFunc = IsResearchCancelled;
IsResearchStartedFunc = IsResearchStarted;
}

UDWORD incPR, incS;
bool bPRFound, bStructFound;

// if its a cancelled topic - add to list
if (IsResearchCancelledPending(&asPlayerResList[playerID][inc]))
if (IsResearchCancelledFunc(&asPlayerResList[playerID][inc]))
{
return true;
}
// if the topic is possible and has not already been researched - add to list
if ((IsResearchPossible(&asPlayerResList[playerID][inc])))
{
if (!IsResearchCompleted(&asPlayerResList[playerID][inc])
&& !IsResearchStartedPending(&asPlayerResList[playerID][inc]))
&& !IsResearchStartedFunc(&asPlayerResList[playerID][inc]))
{
return true;
}
Expand All @@ -623,8 +632,18 @@ bool researchAvailable(int inc, int playerID)
return false;
}

bool researchStarted = IsResearchStartedFunc(&asPlayerResList[playerID][inc]);
if (researchStarted)
{
STRUCTURE *psBuilding = findResearchingFacilityByResearchIndex(playerID, inc); // May fail to find the structure here, if the research is merely pending, not actually started.
if (psBuilding != NULL && psBuilding->status == SS_BEING_BUILT)
{
researchStarted = false; // Although research is started, the facility is currently being upgraded or demolished, so we want to be able to research this elsewhere.
}
}

// make sure that the research is not completed or started by another researchfac
if (!IsResearchCompleted(&asPlayerResList[playerID][inc]) && !IsResearchStartedPending(&asPlayerResList[playerID][inc]))
if (!IsResearchCompleted(&asPlayerResList[playerID][inc]) && !researchStarted)
{
// Research is not completed ... also it has not been started by another researchfac

Expand Down Expand Up @@ -695,7 +714,7 @@ UWORD fillResearchList(UWORD *plist, UDWORD playerID, UWORD topic, UWORD limit)
for (inc=0; inc < asResearch.size(); inc++)
{
// if the inc matches the 'topic' - automatically add to the list
if (inc == topic || researchAvailable(inc, playerID))
if (inc == topic || researchAvailable(inc, playerID, ModeQueue))
{
*plist++ = inc;
count++;
Expand Down
2 changes: 1 addition & 1 deletion src/research.h
Expand Up @@ -149,6 +149,6 @@ void CancelAllResearch(UDWORD pl);

extern bool researchInitVars(void);

bool researchAvailable(int inc, int playerID);
bool researchAvailable(int inc, int playerID, QUEUE_MODE mode);

#endif // __INCLUDED_SRC_RESEARCH_H__

0 comments on commit 5bac6e4

Please sign in to comment.