Skip to content

Commit

Permalink
Add optional difficulty level descriptions for AIs
Browse files Browse the repository at this point in the history
* support the following keys in JSON files for AIs, by difficulty level:
  * Easy: "easy_tip"
  * Medium: "medium_tip"
  * Hard: "hard_tip"
  * Insane: "insane_tip"

* keys should contain messages explaining differences between levels and
  any cheats an AI might use (e.g. power bonuses or skipping research)

* append non-empty key values to AI difficulty tooltips in an extra line

* make key values translatable

* fill out key values for all AIs installed by default

Fixes Warzone2100#419
  • Loading branch information
Forgon2100 committed Jul 4, 2019
1 parent 72fa749 commit 3bee689
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 10 deletions.
4 changes: 3 additions & 1 deletion data/mp/multiplay/skirmish/nb_generic.json
Expand Up @@ -2,6 +2,8 @@
"AI": {
"js": "nb_generic.js",
"name": "NullBot",
"tip": "Adaptive AI with multiple personalities"
"tip": "Adaptive AI with multiple personalities",
"easy_tip": "Gets ~ 25% less power from each oil derrick\nResearch is not focused on a specific weapon branch",
"insane_tip": "Gets ~ 100% more power from each oil derrick\nStarts with defensive structures and oil derricks"
}
}
4 changes: 3 additions & 1 deletion data/mp/multiplay/skirmish/nb_hover.json
Expand Up @@ -2,6 +2,8 @@
"AI": {
"js": "nb_hover.js",
"name": "Hover AI",
"tip": "Sea map AI, based on NullBot"
"tip": "Sea map AI, based on NullBot",
"easy_tip": "Gets ~ 25% less power from each oil derrick",
"insane_tip": "Gets ~ 100% more power from each oil derrick\nStarts with defensive structures and oil derricks"
}
}
4 changes: 3 additions & 1 deletion data/mp/multiplay/skirmish/nb_turtle.json
Expand Up @@ -2,6 +2,8 @@
"AI": {
"js": "nb_turtle.js",
"name": "Turtle AI",
"tip": "Tower wars AI, based on NullBot"
"tip": "Tower wars AI, based on NullBot",
"easy_tip": "Gets ~ 25% less power from each oil derrick\nResearch is not focused on a specific weapon branch",
"insane_tip": "Gets ~ 100% more power from each oil derrick\nStarts with defensive structures and oil derricks"
}
}
8 changes: 6 additions & 2 deletions data/mp/multiplay/skirmish/nexus.json
@@ -1,8 +1,12 @@
{
"AI": {
"name": "Nexus",
"slo": "nexus.slo",
"vlo": "nexus.vlo",
"name": "Nexus",
"tip": "Initial AI, now supplanted by NullBot",
"vlo": "nexus.vlo"
"easy_tip": "Gets ~ 25% less power from each oil derrick",
"medium_tip": "Research speed +40% (per minute)",
"hard_tip": "Research speed +60% (per minute)",
"insane_tip": "Gets ~ 100% more power from each oil derrick\nResearch speed +80% (per minute)\nStarts with defensive structures and oil derricks"
}
}
4 changes: 3 additions & 1 deletion data/mp/multiplay/skirmish/semperfi-js.json
Expand Up @@ -2,6 +2,8 @@
"AI": {
"js": "semperfi.js",
"name": "SemperFi JavaScript",
"tip": "Prototypical JavaScript AI focusing on rockets/missiles"
"tip": "Prototypical JavaScript AI focusing on rockets/missiles",
"easy_tip": "Gets ~ 25% less power from each oil derrick",
"insane_tip": "Gets ~ 100% more power from each oil derrick\nStarts with defensive structures and oil derricks"
}
}
7 changes: 5 additions & 2 deletions data/mp/multiplay/skirmish/semperfi.json
@@ -1,8 +1,11 @@
{
"AI": {
"name": "SemperFi",
"slo": "semperfi.slo",
"vlo": "semperfi.vlo",
"name": "SemperFi",
"tip": "Enhanced Nexus AI",
"vlo": "semperfi.vlo"
"easy_tip": "Gets ~ 25% less power from each oil derrick\nDoes not build defenses next to enemy oil derricks\nNever tries a truck rush",
"medium_tip": "Never tries a truck rush",
"insane_tip": "Gets ~ 100% more power from each oil derrick\nStarts with defensive structures and oil derricks"
}
}
8 changes: 8 additions & 0 deletions po/custom/fromJson.txt
Expand Up @@ -509,6 +509,11 @@ _("Gauss Cannon Hardpoint")
_("Gauss Cannon Python Tracks")
_("Gauss Cannon Wyvern Tracks")
_("Generates and concentrates bursts of laser energy")
_("Gets ~ 100% more power from each oil derrick\nResearch speed +80% (per minute)\nStarts with defensive structures and oil derricks")
_("Gets ~ 100% more power from each oil derrick\nStarts with defensive structures and oil derricks")
_("Gets ~ 25% less power from each oil derrick")
_("Gets ~ 25% less power from each oil derrick\nDoes not build defenses next to enemy oil derricks\nNever tries a truck rush")
_("Gets ~ 25% less power from each oil derrick\nResearch is not focused on a specific weapon branch")
_("Gives Cyborg limited flight abilities")
_("Good main battle tank and heavy artillery platform")
_("Good medium tank and support vehicle")
Expand Down Expand Up @@ -937,6 +942,7 @@ _("Needle Gun Vengeance Tracks")
_("Neural Synapse Research Brain")
_("Neural Synapse Research Brain Mk2")
_("Neural Synapse Research Brain Mk3")
_("Never tries a truck rush")
_("New AA Turret Available")
_("New Advanced Weapon Available")
_("New armored construction")
Expand Down Expand Up @@ -1138,6 +1144,8 @@ _("Research Module")
_("Research Module Available")
_("Research module expands research facilities")
_("Research speed +30%")
_("Research speed +40% (per minute)")
_("Research speed +60% (per minute)")
_("Research speed +85%")
_("Retaliation")
_("Retribution")
Expand Down
2 changes: 1 addition & 1 deletion po/parseJson.py
Expand Up @@ -8,7 +8,7 @@ def parse(obj):
if isinstance(obj, dict):
for k, v in obj.items():
parse(v)
if k in ['name', 'tip'] and isinstance(v, str):
if k in ['name', 'tip', 'easy_tip', 'medium_tip', 'hard_tip', 'insane_tip'] and isinstance(v, str):
printString(v, '_(', '\n')
elif k in ['text', 'ranks'] and isinstance(v, list):
for s in v:
Expand Down
32 changes: 31 additions & 1 deletion src/multiint.cpp
Expand Up @@ -276,6 +276,7 @@ struct AIDATA
char vlo[MAX_LEN_AI_NAME];
char js[MAX_LEN_AI_NAME];
char tip[255];
char difficultyTips[4][255]; // optional difficulty level info
int assigned; ///< How many AIs have we assigned of this type
};
static std::vector<AIDATA> aidata;
Expand Down Expand Up @@ -787,6 +788,20 @@ void readAIs()
sstrcpy(ai.vlo, aiconf.value("vlo", "").toWzString().toUtf8().c_str());
sstrcpy(ai.js, aiconf.value("js", "").toWzString().toUtf8().c_str());

const char *difficultyKeys[] = { "easy_tip", "medium_tip", "hard_tip", "insane_tip" };
for (int i = 0; i < ARRAY_SIZE(difficultyKeys); i++)
{
if (aiconf.contains(difficultyKeys[i]))
{
sstrcpy(ai.difficultyTips[i], _(aiconf.value(difficultyKeys[i], "").toWzString().toUtf8().c_str()));
}
else
{
// note that the empty string "" must never be translated
sstrcpy(ai.difficultyTips[i], "");
}
}

if (aiconf.contains("tip"))
{
sstrcpy(ai.tip, _(aiconf.value("tip", "").toWzString().toUtf8().c_str()));
Expand Down Expand Up @@ -1932,6 +1947,12 @@ static void addDifficultyChooser(int player)
case 2: sButInit.pTip = _("No holds barred"); break;
case 3: sButInit.pTip = _("Starts with advantages"); break;
}
const char *difficultyTip = aidata[NetPlay.players[player].ai].difficultyTips[i];
if (strcmp(difficultyTip, "") != 0)
{
sButInit.pTip += "\n";
sButInit.pTip += difficultyTip;
}
sButInit.pDisplay = displayDifficulty;
sButInit.UserData = i;
sButInit.pUserData = new DisplayDifficultyCache();
Expand Down Expand Up @@ -2519,8 +2540,17 @@ static void drawReadyButton(UDWORD player)
if (!NetPlay.players[player].allocated && NetPlay.players[player].ai >= 0)
{
int icon = difficultyIcon(NetPlay.players[player].difficulty);
int playerDifficulty = NetPlay.players[player].difficulty;
char tooltip[128 + 255];
sstrcpy(tooltip, _(difficultyList[playerDifficulty]));
const char *difficultyTip = aidata[NetPlay.players[player].ai].difficultyTips[playerDifficulty];
if (strcmp(difficultyTip, "") != 0)
{
sstrcat(tooltip, "\n");
sstrcat(tooltip, difficultyTip);
}
addMultiBut(psWScreen, MULTIOP_READY_FORM_ID + player, MULTIOP_DIFFICULTY_INIT_START + player, 6, 4, MULTIOP_READY_WIDTH, MULTIOP_READY_HEIGHT,
(NetPlay.isHost && !locked.difficulty) ? _("Click to change difficulty") : _(difficultyList[NetPlay.players[player].difficulty]), icon, icon, icon);
(NetPlay.isHost && !locked.difficulty) ? _("Click to change difficulty") : tooltip, icon, icon, icon);
return;
}
else if (!NetPlay.players[player].allocated)
Expand Down

0 comments on commit 3bee689

Please sign in to comment.