Skip to content

Commit

Permalink
[TD] Adds support for [ThemeControl] section in rules.ini.
Browse files Browse the repository at this point in the history
  • Loading branch information
OmniBlade committed Jun 26, 2024
1 parent f9f4aba commit e88c8eb
Show file tree
Hide file tree
Showing 7 changed files with 232 additions and 43 deletions.
35 changes: 35 additions & 0 deletions tiberiandawn/conquer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3947,6 +3947,41 @@ void Blit_Hid_Page_To_Seen_Buff(void)
HidPage.Blit(SeenBuff);
}

/***********************************************************************************************
* Owner_From_Name -- Convert an owner name into a bitfield. *
* *
* This will take an owner specification and convert it into a bitfield that represents *
* it. Sometimes this will be just a single house bit, but other times it could be *
* all the allies or soviet house bits combined. *
* *
* INPUT: text -- Pointer to the text to convert into a house bitfield. *
* *
* OUTPUT: Returns with the houses specified. The value is in the form of a bit field with *
* one bit per house type. *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 08/12/1996 JLB : Created. *
*=============================================================================================*/
int Owner_From_Name(char const* text)
{
int ownable = 0;
if (stricmp(text, "nod") == 0) {
ownable |= HOUSEF_BAD;
} else {
if (stricmp(text, "gdi") == 0) {
ownable |= HOUSEF_GOOD;
} else {
HousesType h = HouseTypeClass::From_Name(text);
if (h != HOUSE_NONE && (h < HOUSE_MULTI1 || h > HOUSE_MULTI6)) {
ownable |= (1 << h);
}
}
}
return (ownable);
}

/***********************************************************************************************
* Shake_The_Screen -- Dispatcher that shakes the screen. *
* *
Expand Down
3 changes: 3 additions & 0 deletions tiberiandawn/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,9 @@ typedef enum HousesType : signed char
#define HOUSEF_MULTI4 (1 << HOUSE_MULTI4)
#define HOUSEF_MULTI5 (1 << HOUSE_MULTI5)
#define HOUSEF_MULTI6 (1 << HOUSE_MULTI6)
#define HOUSEF_OTHERS \
(HOUSEF_NEUTRAL | HOUSEF_JP | HOUSEF_MULTI1 | HOUSEF_MULTI2 | HOUSEF_MULTI3 | HOUSEF_MULTI4 | HOUSEF_MULTI5 \
| HOUSEF_MULTI6)

typedef enum PlayerColorType : signed char
{
Expand Down
1 change: 1 addition & 0 deletions tiberiandawn/function.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ void Explosion_Damage(COORDINATE coord, unsigned strength, TechnoClass* source,
/*
** CONQUER.CPP
*/
int Owner_From_Name(char const* text);
void Center_About_Objects(void);
bool Force_CD_Available(int cd);
void Handle_View(int view, int action = 0);
Expand Down
76 changes: 76 additions & 0 deletions tiberiandawn/rules.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,82 @@ bool RulesClass::Export_AI(CCINIClass& ini)
ini.Put_Fixed(AI, "PowerEmergency", PowerEmergencyFraction);
return (true);
}
/***********************************************************************************************
* RulesClass::Themes -- Fetches the theme control values from the INI database. *
* *
* The musical theme availability is controlled by the scenario and the player's house *
* choice. These controls can be specified in the theme control section of the INI *
* database. *
* *
* INPUT: ini -- Reference to the INI database to process. *
* *
* OUTPUT: bool; Was the theme section found and processed? *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 08/11/1996 JLB : Created. *
*=============================================================================================*/
bool RulesClass::Themes(CCINIClass& ini)
{
static char const* const THEMECONTROL = "ThemeControl";

if (ini.Is_Present(THEMECONTROL)) {
for (ThemeType theme = THEME_FIRST; theme < THEME_COUNT; theme++) {
if (ini.Is_Present(THEMECONTROL, Theme.Base_Name(theme))) {

char buffer[128];
int scen = 1;
int owners = HOUSEF_GOOD | HOUSEF_BAD | HOUSEF_OTHERS;

ini.Get_String(THEMECONTROL, Theme.Base_Name(theme), "", buffer, sizeof(buffer));
char const* token = strtok(buffer, ",");
if (token != NULL) {
scen = atoi(token);
}

token = strtok(NULL, ",");
if (token != NULL) {
owners = Owner_From_Name(token);
}

Theme.Set_Theme_Data(theme, scen, owners);
}
}
return (true);
}
return (false);
}

bool RulesClass::Export_Themes(CCINIClass& ini)
{
static char const* const THEMECONTROL = "ThemeControl";

for (ThemeType theme = THEME_FIRST; theme < THEME_COUNT; theme++) {

char buffer[128];
int scen = Theme.Scenario(theme);
int owners = Theme.Owner(theme);

const char* owner_name;
switch (owners) {
case HOUSEF_GOOD:
owner_name = ",GDI";
break;
case HOUSEF_BAD:
owner_name = ",Nod";
break;
default:
owner_name = "";
break;
}

snprintf(buffer, sizeof(buffer), "%d,%s", scen, owner_name);
ini.Put_String(THEMECONTROL, Theme.Base_Name(theme), buffer);
}

return true;
}

/***********************************************************************************************
* RulesClass::IQ -- Fetches the IQ control values from the INI database. *
Expand Down
2 changes: 2 additions & 0 deletions tiberiandawn/rules.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,14 @@ class RulesClass
bool General(CCINIClass& ini);
bool Recharge(CCINIClass& ini);
bool AI(CCINIClass& ini);
bool Themes(CCINIClass& ini);
bool IQ(CCINIClass& ini);
bool Difficulty(CCINIClass& ini);
bool Export(CCINIClass& file);
bool Export_General(CCINIClass& ini);
bool Export_Recharge(CCINIClass& ini);
bool Export_AI(CCINIClass& ini);
bool Export_Themes(CCINIClass& ini);
bool Export_IQ(CCINIClass& ini);
bool Export_Difficulty(CCINIClass& ini);

Expand Down
146 changes: 103 additions & 43 deletions tiberiandawn/theme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,44 +54,44 @@
** These are the actual filename list for the theme sample files.
*/
ThemeClass::ThemeControl ThemeClass::_themes[THEME_COUNT] = {
{"AIRSTRIK", TXT_THEME_AIRSTRIKE, 0, 200, false, false, false, true},
{"80MX226M", TXT_THEME_80MX, 0, 248, false, false, false, true},
{"CHRG226M", TXT_THEME_CHRG, 0, 256, true, false, false, true},
{"CREP226M", TXT_THEME_CREP, 0, 222, true, false, false, true},
{"DRIL226M", TXT_THEME_DRIL, 0, 272, true, false, false, true},
{"DRON226M", TXT_THEME_DRON, 0, 275, true, false, false, true},
{"FIST226M", TXT_THEME_FIST, 0, 212, true, false, false, true},
{"RECN226M", TXT_THEME_RECON, 0, 261, true, false, false, true},
{"VOIC226M", TXT_THEME_VOICE, 0, 306, true, false, false, true},
{"HEAVYG", TXT_THEME_HEAVYG, 0, 180, true, false, false, true},
{"J1", TXT_THEME_J1, 4, 187, true, false, false, true},
{"AIRSTRIK", TXT_THEME_AIRSTRIKE, 0, 200, false, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"80MX226M", TXT_THEME_80MX, 0, 248, false, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"CHRG226M", TXT_THEME_CHRG, 0, 256, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"CREP226M", TXT_THEME_CREP, 0, 222, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"DRIL226M", TXT_THEME_DRIL, 0, 272, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"DRON226M", TXT_THEME_DRON, 0, 275, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"FIST226M", TXT_THEME_FIST, 0, 212, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"RECN226M", TXT_THEME_RECON, 0, 261, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"VOIC226M", TXT_THEME_VOICE, 0, 306, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"HEAVYG", TXT_THEME_HEAVYG, 0, 180, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"J1", TXT_THEME_J1, 4, 187, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
// {"J1", TXT_THEME_J1, 4, 187, false, false,false,true},
{"JDI_V2", TXT_THEME_JDI_V2, 5, 183, true, false, false, true},
{"RADIO", TXT_THEME_RADIO, 6, 183, true, false, false, true},
{"RAIN", TXT_THEME_RAIN, 7, 156, true, false, false, true},
{"AOI", TXT_THEME_AOI, 0, 168, true, true, false, true},
{"CCTHANG", TXT_THEME_CCTHANG, 12, 193, true, false, false, true},
{"DIE", TXT_THEME_DIE, 11, 162, false, false, false, true},
{"FWP", TXT_THEME_FWP, 10, 53, true, false, false, true},
{"IND", TXT_THEME_IND, 1, 175, true, false, false, true},
{"IND2", TXT_THEME_IND2, 1, 38, true, false, false, true},
{"JUSTDOIT", TXT_THEME_JUSTDOIT, 9, 142, true, false, false, true},
{"LINEFIRE", TXT_THEME_LINEFIRE, 8, 125, true, false, false, true},
{"MARCH", TXT_THEME_MARCH, 7, 157, true, false, false, true},
{"TARGET", TXT_THEME_TARGET, 0, 173, true, false, false, true},
{"NOMERCY", TXT_THEME_NOMERCY, 2, 204, true, false, false, true},
{"OTP", TXT_THEME_OTP, 3, 182, true, false, false, true},
{"PRP", TXT_THEME_PRP, 4, 211, true, false, false, true},
{"ROUT", TXT_THEME_ROUT, 12, 121, false, true, false, true},
{"HEART", TXT_THEME_HEART, 5, 206, false, true, false, true},
{"STOPTHEM", TXT_THEME_STOPTHEM, 0, 190, true, false, false, true},
{"TROUBLE", TXT_THEME_TROUBLE, 6, 191, true, true, false, true},
{"WARFARE", TXT_THEME_WARFARE, 0, 182, true, false, false, true},
{"BEFEARED", TXT_THEME_BEFEARED, 13, 164, false, true, false, true},
{"I_AM", TXT_THEME_IAM, 6, 161, false, false, false, true},
{"WIN1", TXT_THEME_WIN1, 0, 41, false, true, true, true},
{"MAP1", TXT_THEME_WIN1, 0, 61, false, false, true, true},
{"VALKYRIE", TXT_THEME_VALK, 0, 306, false, false, true, true},
{"JDI_V2", TXT_THEME_JDI_V2, 5, 183, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"RADIO", TXT_THEME_RADIO, 6, 183, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"RAIN", TXT_THEME_RAIN, 7, 156, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"AOI", TXT_THEME_AOI, 0, 168, true, true, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"CCTHANG", TXT_THEME_CCTHANG, 12, 193, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"DIE", TXT_THEME_DIE, 11, 162, false, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"FWP", TXT_THEME_FWP, 10, 53, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"IND", TXT_THEME_IND, 1, 175, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"IND2", TXT_THEME_IND2, 1, 38, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"JUSTDOIT", TXT_THEME_JUSTDOIT, 9, 142, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"LINEFIRE", TXT_THEME_LINEFIRE, 8, 125, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"MARCH", TXT_THEME_MARCH, 7, 157, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"TARGET", TXT_THEME_TARGET, 0, 173, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"NOMERCY", TXT_THEME_NOMERCY, 2, 204, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"OTP", TXT_THEME_OTP, 3, 182, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"PRP", TXT_THEME_PRP, 4, 211, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"ROUT", TXT_THEME_ROUT, 12, 121, false, true, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"HEART", TXT_THEME_HEART, 5, 206, false, true, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"STOPTHEM", TXT_THEME_STOPTHEM, 0, 190, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"TROUBLE", TXT_THEME_TROUBLE, 6, 191, true, true, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"WARFARE", TXT_THEME_WARFARE, 0, 182, true, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"BEFEARED", TXT_THEME_BEFEARED, 13, 164, false, true, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"I_AM", TXT_THEME_IAM, 6, 161, false, false, false, true, HOUSEF_GOOD | HOUSEF_BAD},
{"WIN1", TXT_THEME_WIN1, 0, 41, false, true, true, true, HOUSEF_GOOD | HOUSEF_BAD},
{"MAP1", TXT_THEME_WIN1, 0, 61, false, false, true, true, HOUSEF_GOOD | HOUSEF_BAD},
{"VALKYRIE", TXT_THEME_VALK, 0, 306, false, false, true, true, HOUSEF_GOOD | HOUSEF_BAD},
};

/***********************************************************************************************
Expand Down Expand Up @@ -467,12 +467,43 @@ bool ThemeClass::Is_Allowed(ThemeType index) const
}
}

return (_themes[index].Available
&& (_themes[index].Normal ||
// (index == THEME_MAP1 && ScenarioInit) ||
((Special.IsVariation && _themes[index].Variation && index != THEME_WIN1)
&& (!Is_Demo() || (GameToPlay != GAME_NORMAL || _themes[index].Scenario <= (int)Scen.Scenario))
&& (index != THEME_J1 || Special.IsJurassic))));
if ((unsigned)index >= THEME_COUNT)
return (true);

/*
** If the theme is not present, then it certainly isn't allowed.
*/
if (!_themes[index].Available)
return (false);

/*
** Only normal themes (playable during battle) are considered allowed.
*/
if (!_themes[index].Normal)
return (false);

/*
** If the theme is not allowed to be played by the player's house, then don't allow
** it. If the player's house hasn't yet been determined, then presume this test
** passes.
*/
if (PlayerPtr != NULL && ((1 << PlayerPtr->ActLike) & _themes[index].Owner) == 0)
return (false);

if (!Special.IsVariation || !_themes[index].Variation || index == THEME_WIN1)
return (false);

/*
** If the scenario doesn't allow this theme yet, then return the failure flag. The
** scenario check only makes sense for solo play.
*/
if (Is_Demo() || (GameToPlay == GAME_NORMAL && Scen.Scenario < _themes[index].Scenario))
return (false);

/*
** Since all otehr tests passed, return if its not the special dino theme.
*/
return (index != THEME_J1 || Special.IsJurassic);
}

/***********************************************************************************************
Expand Down Expand Up @@ -551,3 +582,32 @@ void ThemeClass::Scan(void)
// }
}
}

/***********************************************************************************************
* ThemeClass::Set_Theme_Data -- Set the theme data for scenario and owner. *
* *
* This is an override function used to set a particular theme's initial scenario and *
* owner values. Typically, the rules control file will be the source of calling this *
* routine. *
* *
* INPUT: theme -- The theme to set these override values for. *
* *
* scenario -- The first scenario when this theme becomes available on the play list. *
* *
* owners -- A bitfield representing the owners allowed to play this song. *
* *
* OUTPUT: none *
* *
* WARNINGS: none *
* *
* HISTORY: *
* 08/12/1996 JLB : Created. *
*=============================================================================================*/
void ThemeClass::Set_Theme_Data(ThemeType theme, int scenario, int owners)
{
if (theme != THEME_NONE) {
_themes[theme].Normal = true;
_themes[theme].Scenario = scenario;
_themes[theme].Owner = owners;
}
}
12 changes: 12 additions & 0 deletions tiberiandawn/theme.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class ThemeClass
bool Variation; // Is there a variation to the score?
bool Repeat; // Always repeat this score?
bool Available; // Is the score available?
int Owner; // What houses are allowed to play this theme (bit field)?
} ThemeControl;

static ThemeControl _themes[THEME_COUNT];
Expand Down Expand Up @@ -89,8 +90,19 @@ class ThemeClass
};
int Still_Playing(void);
ThemeType Next_Song(ThemeType index);
void Set_Theme_Data(ThemeType theme, int scenario, int owners);
bool Is_Allowed(ThemeType index) const;
static void /*_pascal*/ Scan(void);

static int Scenario(ThemeType index)
{
return _themes[index].Scenario;
}

static int Owner(ThemeType index)
{
return _themes[index].Owner;
}
};

#endif

0 comments on commit e88c8eb

Please sign in to comment.