Skip to content

Commit

Permalink
Disable useless structures and research
Browse files Browse the repository at this point in the history
If structure limits are enforced and VTOLs are disabled, disable also
AA structures and related research. This improves the AIs in no-VTOL
games. Likewise, disable useless research for no-cyborg, no-lassat and
no-satlink games.

Closes #510.
  • Loading branch information
topimiettinen committed Sep 22, 2019
1 parent 000e949 commit 188076c
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 9 deletions.
14 changes: 14 additions & 0 deletions data/mp/stats/research.json
Expand Up @@ -337,6 +337,7 @@
"statID": "Cannon2A-TMk1"
},
"R-Cyborg-Hvywpn-PulseLsr": {
"disabledWhen": 2,
"iconID": "IMAGE_RES_CYBORGTECH",
"id": "R-Cyborg-Hvywpn-PulseLsr",
"msgName": "RES_CYW_H_PLAS",
Expand Down Expand Up @@ -383,6 +384,7 @@
"statID": "Rocket-VTOL-HvyA-T"
},
"R-Cyborg-Metals01": {
"disabledWhen": 2,
"iconID": "IMAGE_RES_CYBORGTECH",
"id": "R-Cyborg-Metals01",
"imdName": "icmolql.pie",
Expand Down Expand Up @@ -649,6 +651,7 @@
"techCode": 1
},
"R-Cyborg-Transport": {
"disabledWhen": 4,
"iconID": "IMAGE_RES_CYBORGTECH",
"id": "R-Cyborg-Transport",
"keyTopic": 1,
Expand All @@ -666,6 +669,7 @@
"statID": "TransporterBody"
},
"R-Defense-AA-Laser": {
"disabledWhen": 4,
"iconID": "IMAGE_RES_DEFENCE",
"id": "R-Defense-AA-Laser",
"msgName": "RES_DEF_AALAS",
Expand Down Expand Up @@ -2997,6 +3001,7 @@
"subgroupIconID": "IMAGE_RES_GRPUPG"
},
"R-Struc-VTOLPad-Upgrade02": {
"disabledWhen": 4,
"iconID": "IMAGE_RES_STRUCTURETECH",
"id": "R-Struc-VTOLPad-Upgrade02",
"name": "Automated VTOL Rearming Mk2",
Expand Down Expand Up @@ -3098,6 +3103,7 @@
"techCode": 1
},
"R-SuperTransport": {
"disabledWhen": 4,
"iconID": "IMAGE_RES_CYBORGTECH",
"id": "R-SuperTransport",
"keyTopic": 1,
Expand Down Expand Up @@ -3360,6 +3366,7 @@
"statID": "SensorTurret1Mk1"
},
"R-Sys-Sensor-UpLink": {
"disabledWhen": 8,
"iconID": "IMAGE_RES_SYSTEMTECH",
"id": "R-Sys-Sensor-UpLink",
"keyTopic": 1,
Expand Down Expand Up @@ -4679,6 +4686,7 @@
"subgroupIconID": "IMAGE_RES_GRPACC"
},
"R-Wpn-AAGun-Damage01": {
"disabledWhen": 4,
"iconID": "IMAGE_RES_WEAPONTECH",
"id": "R-Wpn-AAGun-Damage01",
"msgName": "RES_W_AAD1",
Expand Down Expand Up @@ -5031,6 +5039,7 @@
"techCode": 1
},
"R-Wpn-AAGun02": {
"disabledWhen": 4,
"iconID": "IMAGE_RES_WEAPONTECH",
"id": "R-Wpn-AAGun02",
"keyTopic": 1,
Expand All @@ -5047,6 +5056,7 @@
"statID": "AAGun2Mk1"
},
"R-Wpn-AAGun03": {
"disabledWhen": 4,
"iconID": "IMAGE_RES_WEAPONTECH",
"id": "R-Wpn-AAGun03",
"keyTopic": 1,
Expand Down Expand Up @@ -5207,6 +5217,7 @@
"subgroupIconID": "IMAGE_RES_GRPDAM"
},
"R-Wpn-Bomb01": {
"disabledWhen": 4,
"iconID": "IMAGE_RES_WEAPONTECH",
"id": "R-Wpn-Bomb01",
"imdName": "trlvtlhe.PIE",
Expand Down Expand Up @@ -7048,6 +7059,7 @@
"statID": "HeavyLaser"
},
"R-Wpn-LasSat": {
"disabledWhen": 16,
"iconID": "IMAGE_RES_WEAPONTECH",
"id": "R-Wpn-LasSat",
"keyTopic": 1,
Expand Down Expand Up @@ -7654,6 +7666,7 @@
"statID": "Missile-HvySAM"
},
"R-Wpn-Missile-LtSAM": {
"disabledWhen": 4,
"iconID": "IMAGE_RES_WEAPONTECH",
"id": "R-Wpn-Missile-LtSAM",
"keyTopic": 1,
Expand Down Expand Up @@ -9163,6 +9176,7 @@
"subgroupIconID": "IMAGE_RES_GRPACC"
},
"R-Wpn-Sunburst": {
"disabledWhen": 4,
"iconID": "IMAGE_RES_WEAPONTECH",
"id": "R-Wpn-Sunburst",
"name": "Sunburst AA Rocket Array",
Expand Down
7 changes: 2 additions & 5 deletions src/game.cpp
Expand Up @@ -6149,10 +6149,7 @@ bool loadSaveResearch(const char *pFileName)
psPlRes = &asPlayerResList[plr][statInc];
// Copy the research status
psPlRes->ResearchStatus = (researched & RESBITS);
if (possible != 0)
{
MakeResearchPossible(psPlRes);
}
SetResearchPossible(psPlRes, possible);
psPlRes->currentPoints = points;
//for any research that has been completed - perform so that upgrade values are set up
if (researched == RESEARCHED)
Expand All @@ -6178,7 +6175,7 @@ static bool writeResearchFile(char *pFileName)
std::vector<WzString> possibles, researched, points;
for (int player = 0; player < game.maxPlayers; player++)
{
possibles.push_back(WzString::number(IsResearchPossible(&asPlayerResList[player][i])));
possibles.push_back(WzString::number(GetResearchPossible(&asPlayerResList[player][i])));
researched.push_back(WzString::number(asPlayerResList[player][i].ResearchStatus & RESBITS));
points.push_back(WzString::number(asPlayerResList[player][i].currentPoints));
if (IsResearchPossible(&asPlayerResList[player][i]) || (asPlayerResList[player][i].ResearchStatus & RESBITS) || asPlayerResList[player][i].currentPoints)
Expand Down
41 changes: 41 additions & 0 deletions src/multilimit.cpp
Expand Up @@ -369,6 +369,7 @@ void applyLimitSet()

// Get the limits and decode
const MULTISTRUCTLIMITS *pEntry = ingame.pStructureLimits;
UBYTE flags = ingame.flags & MPFLAGS_FORCELIMITS;
for (int i = 0; i < ingame.numStructureLimits; ++i)
{
int id = pEntry[i].id;
Expand Down Expand Up @@ -396,9 +397,49 @@ void applyLimitSet()
}
}
}
if (asStructureStats[id].type == REF_VTOL_FACTORY && pEntry[i].limit == 0)
{
flags |= MPFLAGS_NO_VTOLS;
}
if (asStructureStats[id].type == REF_CYBORG_FACTORY && pEntry[i].limit == 0)
{
flags |= MPFLAGS_NO_CYBORGS;
}
if (asStructureStats[id].type == REF_GENERIC && asStructureStats[id].id == "A0LasSatCommand" && pEntry[i].limit == 0)
{
flags |= MPFLAGS_NO_LASSAT;
}
if (asStructureStats[id].type == REF_SAT_UPLINK && pEntry[i].limit == 0)
{
flags |= MPFLAGS_NO_UPLINK;
}
}
}

// If structure limits are enforced and VTOLs are disabled, disable also AA structures
if ((flags & (MPFLAGS_FORCELIMITS | MPFLAGS_NO_VTOLS)) == (MPFLAGS_FORCELIMITS | MPFLAGS_NO_VTOLS))
{
for (int i = 0; i < numStructureStats; i++)
{
if (asStructureStats[i].numWeaps > 0 && asStructureStats[i].psWeapStat[0]->surfaceToAir == SHOOT_IN_AIR)
{
for (int player = 0; player < MAX_PLAYERS; player++)
{
asStructureStats[i].upgrade[player].limit = 0;
}
}
}
}
// Disable related research according to disabledWhen in research.json
if (flags & MPFLAGS_FORCELIMITS)
{
RecursivelyDisableResearchByFlags(flags & ~(MPFLAGS_FORCELIMITS | MPFLAGS_NO_UPLINK));
// Special case for LasSat and Uplink: only disable Uplink if also LasSat is disabled
if ((flags & (MPFLAGS_NO_LASSAT | MPFLAGS_NO_UPLINK)) == (MPFLAGS_NO_LASSAT | MPFLAGS_NO_UPLINK))
{
RecursivelyDisableResearchByFlags(MPFLAGS_NO_UPLINK);
}
}
freeLimitSet();
}

Expand Down
8 changes: 7 additions & 1 deletion src/multiplay.h
Expand Up @@ -82,7 +82,13 @@ struct MULTIPLAYERINGAME
UDWORD numStructureLimits; // number of limits
MULTISTRUCTLIMITS *pStructureLimits; // limits chunk.
uint8_t flags; ///< Bitmask, shows which structures are disabled.
#define MPFLAGS_FORCELIMITS 0x20 ///< Flag to force structure limits
#define MPFLAGS_NO_TANKS 0x01 ///< Flag for tanks disabled
#define MPFLAGS_NO_CYBORGS 0x02 ///< Flag for cyborgs disabled
#define MPFLAGS_NO_VTOLS 0x04 ///< Flag for VTOLs disabled
#define MPFLAGS_NO_UPLINK 0x08 ///< Flag for Satellite Uplink disabled
#define MPFLAGS_NO_LASSAT 0x10 ///< Flag for Laser Satellite Command Post disabled
#define MPFLAGS_FORCELIMITS 0x20 ///< Flag to force structure limits
#define MPFLAGS_MAX 0x3f
UDWORD skScores[MAX_PLAYERS][2]; // score+kills for local skirmish players.
char phrases[5][255]; // 5 favourite text messages.
};
Expand Down
46 changes: 46 additions & 0 deletions src/research.cpp
Expand Up @@ -164,6 +164,11 @@ bool loadResearch(WzConfig &ini)
research.techCode = TC_MINOR;
}

//get flags when to disable tech
UBYTE disabledWhen = ini.value("disabledWhen", 0).toUInt();
ASSERT(disabledWhen <= MPFLAGS_MAX, "Invalid disabled tech flag for research topic - '%s' ", getName(&research));
research.disabledWhen = disabledWhen;

//set the iconID
WzString iconID = ini.value("iconID", "").toWzString();
if (iconID.compare("") != 0)
Expand Down Expand Up @@ -367,6 +372,11 @@ bool researchAvailable(int inc, int playerID, QUEUE_MODE mode)
{
return true;
}
// Ignore disabled
if (IsResearchDisabled(&asPlayerResList[playerID][inc]))
{
return false;
}
// if the topic is possible and has not already been researched - add to list
if ((IsResearchPossible(&asPlayerResList[playerID][inc])))
{
Expand Down Expand Up @@ -1384,3 +1394,39 @@ std::vector<AllyResearch> const &listAllyResearch(unsigned ref)
}
return i->second;
}

/* Recursively disable research for all players */
static void RecursivelyDisableResearchByID(size_t index)
{
if (IsResearchDisabled(&asPlayerResList[0][index]))
{
return;
}

for (int player = 0; player < MAX_PLAYERS; ++player)
{
DisableResearch(&asPlayerResList[player][index]);
}

for (size_t inc = 0; inc < asResearch.size(); inc++)
{
for (size_t prereq = 0; prereq < asResearch[inc].pPRList.size(); prereq++)
{
if (asResearch[inc].pPRList[prereq] == index)
{
RecursivelyDisableResearchByID(inc);
}
}
}
}

void RecursivelyDisableResearchByFlags(UBYTE flags)
{
for (size_t inc = 0; inc < asResearch.size(); inc++)
{
if (asResearch[inc].disabledWhen & flags)
{
RecursivelyDisableResearchByID(inc);
}
}
}
36 changes: 33 additions & 3 deletions src/researchdef.h
Expand Up @@ -53,6 +53,7 @@ struct RESEARCH : public BASE_STATS
UDWORD researchPower; /* Power cost to research */
UBYTE keyTopic; /* Flag to indicate whether in single player
this topic must be explicitly enabled*/
UBYTE disabledWhen; /* flags when to disable tech */
std::vector<UWORD> pPRList; ///< List of research pre-requisites
std::vector<UWORD> pStructList; ///< List of structures that when built would enable this research
std::vector<UWORD> pRedStructs; ///< List of Structures that become redundant
Expand All @@ -78,7 +79,7 @@ struct PLAYER_RESEARCH

UBYTE ResearchStatus; // Bit flags ... see below

bool possible; ///< is the research possible ... so can enable topics vis scripts
UBYTE possible; ///< is the research possible ... so can enable topics vis scripts
};

#define STARTED_RESEARCH 0x01 // research in progress
Expand All @@ -90,14 +91,41 @@ struct PLAYER_RESEARCH
#define RESBITS_PENDING_ONLY (STARTED_RESEARCH_PENDING|CANCELLED_RESEARCH_PENDING)
#define RESBITS_PENDING (RESBITS|RESBITS_PENDING_ONLY)

#define RESEARCH_IMPOSSIBLE 0x00 // research is (temporarily) not possible
#define RESEARCH_POSSIBLE 0x01 // research is possible
#define RESEARCH_DISABLED 0x02 // research is disabled (e.g. most VTOL research in no-VTOL games)

static inline bool IsResearchPossible(const PLAYER_RESEARCH *research)
{
return research->possible;
return research->possible == RESEARCH_POSSIBLE;
}

static inline bool IsResearchDisabled(const PLAYER_RESEARCH *research)
{
return research->possible == RESEARCH_DISABLED;
}

static inline void MakeResearchPossible(PLAYER_RESEARCH *research)
{
research->possible = true;
if (research->possible == RESEARCH_IMPOSSIBLE)
{
research->possible = RESEARCH_POSSIBLE;
}
}

static inline void DisableResearch(PLAYER_RESEARCH *research)
{
research->possible = RESEARCH_DISABLED;
}

static inline int GetResearchPossible(const PLAYER_RESEARCH *research)
{
return research->possible;
}

static inline void SetResearchPossible(PLAYER_RESEARCH *research, UBYTE possible)
{
research->possible = possible;
}

static inline bool IsResearchCompleted(PLAYER_RESEARCH const *x)
Expand Down Expand Up @@ -163,4 +191,6 @@ static inline void ResetResearchStatus(PLAYER_RESEARCH *x)
x->ResearchStatus &= ~RESBITS_PENDING;
}

void RecursivelyDisableResearchByFlags(UBYTE flags);

#endif // __INCLUDED_RESEARCHDEF_H__

0 comments on commit 188076c

Please sign in to comment.