1 /*************************************************************************** 2 * Free Heroes of Might and Magic II: https://github.com/ihhub/fheroes2 * 3 * Copyright (C) 2021 * 4 * * 5 * This program is free software; you can redistribute it and/or modify * 6 * it under the terms of the GNU General Public License as published by * 7 * the Free Software Foundation; either version 2 of the License, or * 8 * (at your option) any later version. * 9 * * 10 * This program is distributed in the hope that it will be useful, * 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 13 * GNU General Public License for more details. * 14 * * 15 * You should have received a copy of the GNU General Public License * 16 * along with this program; if not, write to the * 17 * Free Software Foundation, Inc., * 18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 19 ***************************************************************************/ 20 21 #include "campaign_data.h" 22 #include "artifact.h" 23 #include "heroes.h" 24 #include "monster.h" 25 #include "resource.h" 26 #include "spell.h" 27 #include "translations.h" 28 #include <cassert> 29 30 namespace 31 { 32 const std::vector<Campaign::ScenarioIntroVideoInfo> emptyPlayback; 33 getRolandCampaignAwardData(const int scenarioID)34 std::vector<Campaign::CampaignAwardData> getRolandCampaignAwardData( const int scenarioID ) 35 { 36 std::vector<Campaign::CampaignAwardData> obtainableAwards; 37 38 switch ( scenarioID ) { 39 case 2: 40 obtainableAwards.emplace_back( 0, Campaign::CampaignAwardData::TYPE_CREATURE_ALLIANCE, Monster::DWARF, _( "Dwarven Alliance" ) ); 41 break; 42 case 5: 43 obtainableAwards.emplace_back( 1, Campaign::CampaignAwardData::TYPE_HIREABLE_HERO, Heroes::ELIZA, 0, 0, _( "Sorceress Guild" ) ); 44 break; 45 case 6: 46 obtainableAwards.emplace_back( 2, Campaign::CampaignAwardData::TYPE_CARRY_OVER_FORCES, 0, 0, 9 ); 47 break; 48 case 7: 49 obtainableAwards.emplace_back( 3, Campaign::CampaignAwardData::TYPE_GET_ARTIFACT, Artifact::ULTIMATE_CROWN, 1, 9 ); 50 break; 51 case 8: 52 obtainableAwards.emplace_back( 4, Campaign::CampaignAwardData::TYPE_DEFEAT_ENEMY_HERO, Heroes::CORLAGON, 0, 9 ); 53 break; 54 } 55 56 return obtainableAwards; 57 } 58 getArchibaldCampaignAwardData(const int scenarioID)59 std::vector<Campaign::CampaignAwardData> getArchibaldCampaignAwardData( const int scenarioID ) 60 { 61 std::vector<Campaign::CampaignAwardData> obtainableAwards; 62 63 switch ( scenarioID ) { 64 case 2: 65 obtainableAwards.emplace_back( 1, Campaign::CampaignAwardData::TYPE_HIREABLE_HERO, Heroes::BAX, 0, 0, _( "Necromancer Guild" ) ); 66 break; 67 case 3: 68 obtainableAwards.emplace_back( 2, Campaign::CampaignAwardData::TYPE_CREATURE_ALLIANCE, Monster::OGRE ); 69 obtainableAwards.emplace_back( 3, Campaign::CampaignAwardData::TYPE_CREATURE_CURSE, Monster::DWARF ); 70 break; 71 case 6: 72 obtainableAwards.emplace_back( 4, Campaign::CampaignAwardData::TYPE_CREATURE_ALLIANCE, Monster::GREEN_DRAGON, _( "Dragon Alliance" ) ); 73 break; 74 case 8: 75 obtainableAwards.emplace_back( 5, Campaign::CampaignAwardData::TYPE_GET_ARTIFACT, Artifact::ULTIMATE_CROWN ); 76 break; 77 case 9: 78 obtainableAwards.emplace_back( 6, Campaign::CampaignAwardData::TYPE_CARRY_OVER_FORCES, 0 ); 79 break; 80 } 81 82 return obtainableAwards; 83 } 84 getPriceOfLoyaltyCampaignAwardData(const int scenarioID)85 std::vector<Campaign::CampaignAwardData> getPriceOfLoyaltyCampaignAwardData( const int scenarioID ) 86 { 87 std::vector<Campaign::CampaignAwardData> obtainableAwards; 88 89 switch ( scenarioID ) { 90 case 1: 91 obtainableAwards.emplace_back( 0, Campaign::CampaignAwardData::TYPE_GET_ARTIFACT, Artifact::BREASTPLATE_ANDURAN ); 92 break; 93 case 2: 94 obtainableAwards.emplace_back( 1, Campaign::CampaignAwardData::TYPE_CREATURE_ALLIANCE, Monster::ELF, _( "Elven Alliance" ) ); 95 obtainableAwards.emplace_back( 2, Campaign::CampaignAwardData::TYPE_RESOURCE_BONUS, Resource::WOOD, 2 ); 96 break; 97 case 5: 98 obtainableAwards.emplace_back( 3, Campaign::CampaignAwardData::TYPE_GET_ARTIFACT, Artifact::HELMET_ANDURAN ); 99 break; 100 case 6: 101 // Will assemble Battle Garb of Anduran along with the previous anduran set pieces 102 // If we get all the parts, we'll obtain the Battle Garb award while removing the awards for the individual parts 103 obtainableAwards.emplace_back( 4, Campaign::CampaignAwardData::TYPE_GET_ARTIFACT, Artifact::SWORD_ANDURAN ); 104 105 // seems that Kraeger is a custom name for Dainwin in this case 106 obtainableAwards.emplace_back( 5, Campaign::CampaignAwardData::TYPE_DEFEAT_ENEMY_HERO, Heroes::DAINWIN, _( "Kraeger defeated" ) ); 107 break; 108 } 109 110 return obtainableAwards; 111 } 112 getWizardsIsleCampaignAwardData(const int scenarioID)113 std::vector<Campaign::CampaignAwardData> getWizardsIsleCampaignAwardData( const int scenarioID ) 114 { 115 std::vector<Campaign::CampaignAwardData> obtainableAwards; 116 117 switch ( scenarioID ) { 118 case 1: 119 obtainableAwards.emplace_back( 0, Campaign::CampaignAwardData::TYPE_GET_SPELL, Spell::SETEGUARDIAN ); 120 break; 121 case 2: 122 obtainableAwards.emplace_back( 1, Campaign::CampaignAwardData::TYPE_GET_ARTIFACT, Artifact::SPHERE_NEGATION ); 123 break; 124 } 125 126 return obtainableAwards; 127 } 128 getDescendantsCampaignAwardData(const int scenarioID)129 std::vector<Campaign::CampaignAwardData> getDescendantsCampaignAwardData( const int scenarioID ) 130 { 131 std::vector<Campaign::CampaignAwardData> obtainableAwards; 132 133 switch ( scenarioID ) { 134 case 2: 135 obtainableAwards.emplace_back( 0, Campaign::CampaignAwardData::TYPE_HIREABLE_HERO, Heroes::JOSEPH, 0, 0, _( "Wayward Son" ) ); 136 break; 137 case 3: 138 obtainableAwards.emplace_back( 1, Campaign::CampaignAwardData::TYPE_HIREABLE_HERO, Heroes::UNCLEIVAN, 0, 0, _( "Uncle Ivan" ) ); 139 break; 140 case 5: 141 obtainableAwards.emplace_back( 2, Campaign::CampaignAwardData::TYPE_GET_ARTIFACT, Artifact::LEGENDARY_SCEPTER ); 142 break; 143 case 6: 144 obtainableAwards.emplace_back( 3, Campaign::CampaignAwardData::TYPE_CREATURE_ALLIANCE, Monster::ELF, _( "Elven Alliance" ) ); 145 break; 146 } 147 148 return obtainableAwards; 149 } 150 getRolandCampaignData()151 Campaign::CampaignData getRolandCampaignData() 152 { 153 const std::string rolandCampaignScenarioNames[10] 154 = { _( "Force of Arms" ), _( "Annexation" ), _( "Save the Dwarves" ), _( "Carator Mines" ), _( "Turning Point" ), 155 _( "Defender" ), _( "The Gauntlet" ), _( "The Crown" ), _( "Corlagon's Defense" ), _( "Final Justice" ) }; 156 const std::string rolandCampaignDescription[10] = { 157 _( "Roland needs you to defeat the lords near his castle to begin his war of rebellion against his brother. They are not allied with each other, so they will spend" 158 " most of their time fighting with one another. Victory is yours when you have defeated all of their castles and heroes." ), 159 _( "The local lords refuse to swear allegiance to Roland, and must be subdued. They are wealthy and powerful, so be prepared for a tough fight. Capture all enemy castles to win." ), 160 _( "Your task is to defend the Dwarves against Archibald's forces. Capture all of the enemy towns and castles to win, and be sure not to lose all of the dwarf towns at once, or the enemy will have won." ), 161 _( "You will face four allied enemies in a straightforward fight for resource and treasure. Capture all of the enemy castles for victory." ), 162 _( "Your enemies are allied against you and start close by, so be ready to come out fighting. You will need to own all four castles in this small valley to win." ), 163 _( "The Sorceress' guild of Noraston has requested Roland's aid against an attack from Archibald's allies. Capture all of the enemy castles to win, and don't lose Noraston, or you'll lose the scenario. (Hint: There is an enemy castle on an island in the ocean.)" ), 164 _( "Gather as large an army as possible and capture the enemy castle within 8 weeks. You are opposed by only one enemy, but must travel a long way to get to the enemy castle. Any troops you have in your army at the end of this scenario will be with you in the final battle." ), 165 _( "Find the Crown before Archibald's heroes find it. Roland will need the Crown for the final battle against Archibald." ), 166 _( "Three allied enemies stand before you and victory, including Lord Corlagon. Roland is in a castle to the northwest, and you will lose if he falls to the enemy. Remember that capturing Lord Corlagon will ensure that he will not fight against you in the final scenario." ), 167 _( "This is the final battle. Both you and your enemy are armed to the teeth, and all are allied against you. Capture Archibald to end the war!" ) }; 168 std::vector<Campaign::ScenarioData> scenarioDatas; 169 scenarioDatas.reserve( 10 ); 170 171 scenarioDatas.emplace_back( 0, std::vector<int>{ 1 }, Campaign::ScenarioBonusData::getCampaignBonusData( 0, 0 ), "CAMPG01.H2C", rolandCampaignScenarioNames[0], 172 rolandCampaignDescription[0], 173 Campaign::VideoSequence{ { "GOOD01V.SMK", Video::VideoAction::IGNORE_VIDEO }, 174 { "GOOD01.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 175 emptyPlayback ); 176 scenarioDatas.emplace_back( 1, std::vector<int>{ 2, 3 }, Campaign::ScenarioBonusData::getCampaignBonusData( 0, 1 ), "CAMPG02.H2C", rolandCampaignScenarioNames[1], 177 rolandCampaignDescription[1], 178 Campaign::VideoSequence{ { "GOOD02W.SMK", Video::VideoAction::IGNORE_VIDEO }, 179 { "GOOD02.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 180 Campaign::VideoSequence{ { "GOOD03QW.SMK", Video::VideoAction::IGNORE_VIDEO }, 181 { "GOOD03.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); 182 scenarioDatas.emplace_back( 2, std::vector<int>{ 3 }, Campaign::ScenarioBonusData::getCampaignBonusData( 0, 2 ), "CAMPG03.H2C", rolandCampaignScenarioNames[2], 183 rolandCampaignDescription[2], emptyPlayback, 184 Campaign::VideoSequence{ { "GOOD04W.SMK", Video::VideoAction::IGNORE_VIDEO }, 185 { "GOOD04.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 186 Campaign::ScenarioVictoryCondition::STANDARD, Campaign::ScenarioLossCondition::LOSE_ALL_SORCERESS_VILLAGES ); 187 scenarioDatas.emplace_back( 3, std::vector<int>{ 4 }, Campaign::ScenarioBonusData::getCampaignBonusData( 0, 3 ), "CAMPG04.H2C", rolandCampaignScenarioNames[3], 188 rolandCampaignDescription[3], emptyPlayback, 189 Campaign::VideoSequence{ { "GOOD05V.SMK", Video::VideoAction::IGNORE_VIDEO }, 190 { "GOOD05.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); 191 scenarioDatas.emplace_back( 4, std::vector<int>{ 5 }, Campaign::ScenarioBonusData::getCampaignBonusData( 0, 4 ), "CAMPG05.H2C", rolandCampaignScenarioNames[4], 192 rolandCampaignDescription[4], emptyPlayback, emptyPlayback ); 193 scenarioDatas.emplace_back( 5, std::vector<int>{ 6, 7 }, Campaign::ScenarioBonusData::getCampaignBonusData( 0, 5 ), "CAMPG06.H2C", rolandCampaignScenarioNames[5], 194 rolandCampaignDescription[5], 195 Campaign::VideoSequence{ { "GOOD06AV.SMK", Video::VideoAction::IGNORE_VIDEO }, 196 { "GOOD06.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 197 Campaign::VideoSequence{ { "GOOD07QW.SMK", Video::VideoAction::IGNORE_VIDEO }, 198 { "GOOD07.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); 199 scenarioDatas.emplace_back( 6, std::vector<int>{ 8 }, Campaign::ScenarioBonusData::getCampaignBonusData( 0, 6 ), "CAMPG07.H2C", rolandCampaignScenarioNames[6], 200 rolandCampaignDescription[6], emptyPlayback, emptyPlayback ); 201 scenarioDatas.emplace_back( 7, std::vector<int>{ 8 }, Campaign::ScenarioBonusData::getCampaignBonusData( 0, 7 ), "CAMPG08.H2C", rolandCampaignScenarioNames[7], 202 rolandCampaignDescription[7], emptyPlayback, emptyPlayback, Campaign::ScenarioVictoryCondition::OBTAIN_ULTIMATE_CROWN ); 203 scenarioDatas.emplace_back( 8, std::vector<int>{ 9 }, Campaign::ScenarioBonusData::getCampaignBonusData( 0, 8 ), "CAMPG09.H2C", rolandCampaignScenarioNames[8], 204 rolandCampaignDescription[8], 205 Campaign::VideoSequence{ { "GOOD09W.SMK", Video::VideoAction::IGNORE_VIDEO }, 206 { "GOOD09.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 207 emptyPlayback ); 208 scenarioDatas.emplace_back( 9, std::vector<int>{}, Campaign::ScenarioBonusData::getCampaignBonusData( 0, 9 ), "CAMPG10.H2C", rolandCampaignScenarioNames[9], 209 rolandCampaignDescription[9], 210 Campaign::VideoSequence{ { "GOOD10W.SMK", Video::VideoAction::IGNORE_VIDEO }, 211 { "GOOD10.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 212 Campaign::VideoSequence{ { "LIBRARYW.SMK", Video::VideoAction::IGNORE_VIDEO }, 213 { "LIBRARY.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); 214 215 Campaign::CampaignData campaignData; 216 campaignData.setCampaignID( Campaign::ROLAND_CAMPAIGN ); 217 campaignData.setCampaignDescription( "Roland Campaign" ); 218 campaignData.setCampaignScenarios( scenarioDatas ); 219 220 return campaignData; 221 } 222 getArchibaldCampaignData()223 Campaign::CampaignData getArchibaldCampaignData() 224 { 225 const std::string archibaldCampaignScenarioNames[11] 226 = { _( "First Blood" ), _( "Barbarian Wars" ), _( "Necromancers" ), _( "Slay the Dwarves" ), _( "Turning Point" ), _( "Rebellion" ), 227 _( "Dragon Master" ), _( "Country Lords" ), _( "The Crown" ), _( "Greater Glory" ), _( "Apocalypse" ) }; 228 const std::string archibaldCampaignDescription[11] = { 229 _( "King Archibald requires you to defeat the three enemies in this region. They are not allied with one another, so they will spend most of their energy fighting" 230 " amongst themselves. You will win when you own all of the enemy castles and there are no more heroes left to fight." ), 231 _( "You must unify the barbarian tribes of the north by conquering them. As in the previous mission, the enemy is not allied against you, but they have more resources at their disposal. You will win when you own all of the enemy castles and there are no more heroes left to fight." ), 232 _( "Do-gooder wizards have taken the Necromancers' castle. You must retake it to achieve victory. Remember that while you start with a powerful army, you have no castle and must take one within 7 days, or lose this battle. (Hint: The nearest castle is to the southeast.)" ), 233 _( "The dwarves need conquering before they can interfere in King Archibald's plans. Roland's forces have more than one hero and many towns to start with, so be ready for attack from multiple directions. You must capture all of the enemy towns and castles to claim victory." ), 234 _( "Your enemies are allied against you and start close by, so be ready to come out fighting. You will need to own all four castles in this small valley to win." ), 235 _( "You must put down a peasant revolt led by Roland's forces. All are allied against you, but you have Lord Corlagon, an experienced hero, to help you. Capture all enemy castles to win." ), 236 _( "There are two enemies allied against you in this mission. Both are well armed and seek to evict you from their island. Avoid them and capture Dragon City to win." ), 237 _( "Your orders are to conquer the country lords that have sworn to serve Roland. All of the enemy castles are unified against you. Since you start without a castle, you must hurry to capture one before the end of the week. Capture all enemy castles for victory." ), 238 _( "Find the Crown before Roland's heroes find it. Archibald will need the Crown for the final battle against Roland." ), 239 _( "Gather as large an army as possible and capture the enemy castle within 8 weeks. You are opposed by only one enemy, but must travel a long way to get to the enemy castle. Any troops you have in your army at the end of this scenario will be with you in the final battle." ), 240 _( "This is the final battle. Both you and your enemy are armed to the teeth, and all are allied against you. Capture Roland to win the war, and be sure not to lose Archibald in the fight!" ) }; 241 std::vector<Campaign::ScenarioData> scenarioDatas; 242 scenarioDatas.reserve( 11 ); 243 244 scenarioDatas.emplace_back( 0, std::vector<int>{ 1 }, Campaign::ScenarioBonusData::getCampaignBonusData( 1, 0 ), "CAMPE01.H2C", archibaldCampaignScenarioNames[0], 245 archibaldCampaignDescription[0], 246 Campaign::VideoSequence{ { "EVIL01V.SMK", Video::VideoAction::IGNORE_VIDEO }, 247 { "EVIL01.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 248 emptyPlayback ); 249 scenarioDatas.emplace_back( 1, std::vector<int>{ 2, 3 }, Campaign::ScenarioBonusData::getCampaignBonusData( 1, 1 ), "CAMPE02.H2C", 250 archibaldCampaignScenarioNames[1], archibaldCampaignDescription[1], 251 Campaign::VideoSequence{ { "EVIL02W.SMK", Video::VideoAction::IGNORE_VIDEO }, 252 { "EVIL02.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 253 Campaign::VideoSequence{ { "EVIL03QW.SMK", Video::VideoAction::IGNORE_VIDEO }, 254 { "EVIL03.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); 255 scenarioDatas.emplace_back( 2, std::vector<int>{ 4 }, Campaign::ScenarioBonusData::getCampaignBonusData( 1, 2 ), "CAMPE03.H2C", archibaldCampaignScenarioNames[2], 256 archibaldCampaignDescription[2], emptyPlayback, 257 Campaign::VideoSequence{ { "EVIL05AV.SMK", Video::VideoAction::IGNORE_VIDEO }, 258 { "EVIL05.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); 259 scenarioDatas.emplace_back( 3, std::vector<int>{ 4 }, Campaign::ScenarioBonusData::getCampaignBonusData( 1, 3 ), "CAMPE04.H2C", archibaldCampaignScenarioNames[3], 260 archibaldCampaignDescription[3], emptyPlayback, 261 Campaign::VideoSequence{ { "EVIL05AV.SMK", Video::VideoAction::IGNORE_VIDEO }, 262 { "EVIL05.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); 263 scenarioDatas.emplace_back( 4, std::vector<int>{ 5 }, Campaign::ScenarioBonusData::getCampaignBonusData( 1, 4 ), "CAMPE05.H2C", archibaldCampaignScenarioNames[4], 264 archibaldCampaignDescription[4], emptyPlayback, emptyPlayback ); 265 scenarioDatas.emplace_back( 5, std::vector<int>{ 6, 7 }, Campaign::ScenarioBonusData::getCampaignBonusData( 1, 5 ), "CAMPE06.H2C", 266 archibaldCampaignScenarioNames[5], archibaldCampaignDescription[5], 267 Campaign::VideoSequence{ { "EVIL06AW.SMK", Video::VideoAction::IGNORE_VIDEO }, 268 { "EVIL06.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 269 Campaign::VideoSequence{ { "EVIL07W.SMK", Video::VideoAction::IGNORE_VIDEO }, 270 { "EVIL07.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); 271 scenarioDatas.emplace_back( 6, std::vector<int>{ 7 }, Campaign::ScenarioBonusData::getCampaignBonusData( 1, 6 ), "CAMPE07.H2C", archibaldCampaignScenarioNames[6], 272 archibaldCampaignDescription[6], emptyPlayback, Campaign::VideoSequence{ { "EVIL08.SMK", Video::VideoAction::PLAY_TILL_VIDEO_END } }, 273 Campaign::ScenarioVictoryCondition::CAPTURE_DRAGON_CITY ); 274 scenarioDatas.emplace_back( 7, std::vector<int>{ 8, 9 }, Campaign::ScenarioBonusData::getCampaignBonusData( 1, 7 ), "CAMPE08.H2C", 275 archibaldCampaignScenarioNames[7], archibaldCampaignDescription[7], emptyPlayback, 276 Campaign::VideoSequence{ { "EVIL09W.SMK", Video::VideoAction::IGNORE_VIDEO }, 277 { "EVIL09.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); 278 scenarioDatas.emplace_back( 8, std::vector<int>{ 10 }, Campaign::ScenarioBonusData::getCampaignBonusData( 1, 8 ), "CAMPE09.H2C", 279 archibaldCampaignScenarioNames[8], archibaldCampaignDescription[8], emptyPlayback, emptyPlayback, 280 Campaign::ScenarioVictoryCondition::OBTAIN_ULTIMATE_CROWN ); 281 scenarioDatas.emplace_back( 9, std::vector<int>{ 10 }, Campaign::ScenarioBonusData::getCampaignBonusData( 1, 9 ), "CAMPE10.H2C", 282 archibaldCampaignScenarioNames[9], archibaldCampaignDescription[9], emptyPlayback, emptyPlayback ); 283 scenarioDatas.emplace_back( 10, std::vector<int>{}, Campaign::ScenarioBonusData::getCampaignBonusData( 1, 10 ), "CAMPE11.H2C", archibaldCampaignScenarioNames[10], 284 archibaldCampaignDescription[10], 285 Campaign::VideoSequence{ { "EVIL11W.SMK", Video::VideoAction::IGNORE_VIDEO }, 286 { "EVIL10.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 287 Campaign::VideoSequence{ { "PRISON.SMK", Video::VideoAction::PLAY_TILL_VIDEO_END } } ); 288 289 Campaign::CampaignData campaignData; 290 campaignData.setCampaignID( Campaign::ARCHIBALD_CAMPAIGN ); 291 campaignData.setCampaignDescription( "Archibald Campaign" ); 292 campaignData.setCampaignScenarios( scenarioDatas ); 293 294 return campaignData; 295 } 296 getPriceOfLoyaltyCampaignData()297 Campaign::CampaignData getPriceOfLoyaltyCampaignData() 298 { 299 const std::string priceOfLoyaltyCampaignScenarioNames[8] = { _( "Uprising" ), _( "Island of Chaos" ), _( "Arrow's Flight" ), _( "The Abyss" ), 300 _( "The Giant's Pass" ), _( "Aurora Borealis" ), _( "Betrayal's End" ), _( "Corruption's Heart" ) }; 301 const std::string priceOfLoyaltyCampaignDescription[8] = { 302 _( "Subdue the unruly local lords in order to provide the Empire with facilities to operate in this region." ), 303 _( "Eliminate all oposition in this area. Then the first piece of the artifact will be yours." ), 304 _( "The sorceresses to the northeast are rebelling! For the good of the empire you must quash their feeble uprising on your way to the mountains." ), 305 _( "Having prepared for your arrival, Kraeger has arranged for a force of necromancers to thwart your quest. You must capture the castle of Scabsdale before the first day of the third week, or the Necromancers will be too strong for you." ), 306 _( "The barbarian despot in this area is, as yet, ignorant of your presence. Quickly, build up your forces before you are discovered and attacked! Secure the region by subduing all enemy forces." ), 307 _( "The Empire is weak in this region. You will be unable to completely subdue all forces in this area, so take what you can before reprisal strikes. Remember, your true goal is to claim the Helmet of Anduran." ), 308 _( "For the good of the Empire, eliminate Kraeger." ), 309 _( "At last, you have the opportunity and the facilities to rid the Empire of the necromancer's evil. Eradicate them completely, and you will be sung as a hero for all time." ) }; 310 std::vector<Campaign::ScenarioData> scenarioDatas; 311 scenarioDatas.reserve( 8 ); 312 313 const int campaignID = Campaign::PRICE_OF_LOYALTY_CAMPAIGN; 314 scenarioDatas.emplace_back( 0, std::vector<int>{ 1 }, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 0 ), "CAMP1_01.HXC", 315 priceOfLoyaltyCampaignScenarioNames[0], priceOfLoyaltyCampaignDescription[0], 316 Campaign::VideoSequence{ { "MIXPOL1.SMK", Video::VideoAction::IGNORE_VIDEO }, 317 { "POL1.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 318 emptyPlayback ); 319 scenarioDatas.emplace_back( 1, std::vector<int>{ 2, 3 }, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 1 ), "CAMP1_02.HXC", 320 priceOfLoyaltyCampaignScenarioNames[1], priceOfLoyaltyCampaignDescription[1], 321 Campaign::VideoSequence{ { "MIXPOL2.SMK", Video::VideoAction::IGNORE_VIDEO }, 322 { "POL2.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 323 Campaign::VideoSequence{ { "MIXPOL3.SMK", Video::VideoAction::IGNORE_VIDEO }, 324 { "POL3.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); 325 scenarioDatas.emplace_back( 2, std::vector<int>{ 4 }, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 2 ), "CAMP1_03.HXC", 326 priceOfLoyaltyCampaignScenarioNames[2], priceOfLoyaltyCampaignDescription[2], emptyPlayback, emptyPlayback ); 327 scenarioDatas.emplace_back( 3, std::vector<int>{ 5 }, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 3 ), "CAMP1_04.HXC", 328 priceOfLoyaltyCampaignScenarioNames[3], priceOfLoyaltyCampaignDescription[3], emptyPlayback, emptyPlayback ); 329 scenarioDatas.emplace_back( 4, std::vector<int>{ 5 }, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 4 ), "CAMP1_05.HXC", 330 priceOfLoyaltyCampaignScenarioNames[4], priceOfLoyaltyCampaignDescription[4], 331 Campaign::VideoSequence{ { "MIXPOL4.SMK", Video::VideoAction::IGNORE_VIDEO }, 332 { "POL4.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 333 emptyPlayback ); 334 scenarioDatas.emplace_back( 5, std::vector<int>{ 6, 7 }, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 5 ), "CAMP1_06.HXC", 335 priceOfLoyaltyCampaignScenarioNames[5], priceOfLoyaltyCampaignDescription[5], 336 Campaign::VideoSequence{ { "MIXPOL5.SMK", Video::VideoAction::IGNORE_VIDEO }, 337 { "POL5.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 338 Campaign::VideoSequence{ { "MIXPOL6.SMK", Video::VideoAction::IGNORE_VIDEO }, 339 { "POL6.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); 340 scenarioDatas.emplace_back( 6, std::vector<int>{ 7 }, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 6 ), "CAMP1_07.HXC", 341 priceOfLoyaltyCampaignScenarioNames[6], priceOfLoyaltyCampaignDescription[6], emptyPlayback, 342 Campaign::VideoSequence{ { "MIXPOL7.SMK", Video::VideoAction::IGNORE_VIDEO }, 343 { "POL7.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); 344 scenarioDatas.emplace_back( 7, std::vector<int>{}, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 7 ), "CAMP1_08.HXC", 345 priceOfLoyaltyCampaignScenarioNames[7], priceOfLoyaltyCampaignDescription[7], emptyPlayback, 346 Campaign::VideoSequence{ { "MIXPOL8.SMK", Video::VideoAction::IGNORE_VIDEO }, 347 { "POL8.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); 348 349 Campaign::CampaignData campaignData; 350 campaignData.setCampaignID( campaignID ); 351 campaignData.setCampaignScenarios( scenarioDatas ); 352 353 return campaignData; 354 } 355 getDescendantsCampaignData()356 Campaign::CampaignData getDescendantsCampaignData() 357 { 358 const std::string descendantsCampaignScenarioNames[8] = { _( "Conquer and Unify" ), _( "Border Towns" ), _( "The Wayward Son" ), _( "Crazy Uncle Ivan" ), 359 _( "The Southern War" ), _( "Ivory Gates" ), _( "The Elven Lands" ), _( "The Epic Battle" ) }; 360 const std::string descendantsCampaignDescription[8] = { 361 _( "Conquer and unite all the enemy tribes. Don't lose the hero Jarkonas, the forefather of all descendants." ), 362 _( "Your rival, the Kingdom of Harondale, is attacking weak towns on your border! Recover from their first strike and crush them completely!" ), 363 _( "Find your wayward son Joseph who is rumored to be living in the desolate lands. Do it before the first day of the third month or it will be of no help to your family." ), 364 _( "Rescue your crazy uncle Ivan. Find him before the first day of the fourth month or it will be no help to your kingdom." ), 365 _( "Destroy the barbarians who are attacking the southern border of your kingdom! Recover your fallen towns, and then invade the jungle kingdom. Leave no enemy standing." ), 366 _( "Retake the castle of Ivory Gates, which has fallen due to treachery." ), 367 _( "Gain the favor of the elves. They will not allow trees to be chopped down, so they will send you wood every 2 weeks. You must complete your mission before the first day of the seventh month, or the kingdom will surely fall." ), 368 _( "This is the final battle against your rival kingdom of Harondale. Eliminate everyone, and don't lose the hero Jarkonas VI." ) }; 369 std::vector<Campaign::ScenarioData> scenarioDatas; 370 scenarioDatas.reserve( 8 ); 371 372 const int campaignID = Campaign::DESCENDANTS_CAMPAIGN; 373 scenarioDatas.emplace_back( 0, std::vector<int>{ 1 }, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 0 ), "CAMP2_01.HXC", 374 descendantsCampaignScenarioNames[0], descendantsCampaignDescription[0], 375 Campaign::VideoSequence{ { "MIXDES9.SMK", Video::VideoAction::IGNORE_VIDEO }, 376 { "DES9.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 377 emptyPlayback ); 378 scenarioDatas.emplace_back( 1, std::vector<int>{ 2, 3 }, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 1 ), "CAMP2_02.HXC", 379 descendantsCampaignScenarioNames[1], descendantsCampaignDescription[1], 380 Campaign::VideoSequence{ { "MIXDES10.SMK", Video::VideoAction::IGNORE_VIDEO }, 381 { "DES10.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 382 Campaign::VideoSequence{ { "MIXDES11.SMK", Video::VideoAction::IGNORE_VIDEO }, 383 { "DES11.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); 384 scenarioDatas.emplace_back( 2, std::vector<int>{ 4 }, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 2 ), "CAMP2_03.HXC", 385 descendantsCampaignScenarioNames[2], descendantsCampaignDescription[2], emptyPlayback, emptyPlayback ); 386 scenarioDatas.emplace_back( 3, std::vector<int>{ 4 }, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 3 ), "CAMP2_04.HXC", 387 descendantsCampaignScenarioNames[3], descendantsCampaignDescription[3], emptyPlayback, emptyPlayback ); 388 scenarioDatas.emplace_back( 4, std::vector<int>{ 5, 6 }, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 4 ), "CAMP2_05.HXC", 389 descendantsCampaignScenarioNames[4], descendantsCampaignDescription[4], 390 Campaign::VideoSequence{ { "MIXDES12.SMK", Video::VideoAction::IGNORE_VIDEO }, 391 { "DES12.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 392 emptyPlayback ); 393 scenarioDatas.emplace_back( 5, std::vector<int>{ 7 }, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 5 ), "CAMP2_06.HXC", 394 descendantsCampaignScenarioNames[5], descendantsCampaignDescription[5], 395 Campaign::VideoSequence{ { "MIXDES13.SMK", Video::VideoAction::IGNORE_VIDEO }, 396 { "DES13.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 397 emptyPlayback ); 398 scenarioDatas.emplace_back( 6, std::vector<int>{ 7 }, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 6 ), "CAMP2_07.HXC", 399 descendantsCampaignScenarioNames[6], descendantsCampaignDescription[6], emptyPlayback, emptyPlayback ); 400 scenarioDatas.emplace_back( 7, std::vector<int>{}, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 7 ), "CAMP2_08.HXC", 401 descendantsCampaignScenarioNames[7], descendantsCampaignDescription[7], 402 Campaign::VideoSequence{ { "MIXDES14.SMK", Video::VideoAction::IGNORE_VIDEO }, 403 { "DES14.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 404 Campaign::VideoSequence{ { "MIXDES15.SMK", Video::VideoAction::IGNORE_VIDEO }, 405 { "DES15.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); 406 407 Campaign::CampaignData campaignData; 408 campaignData.setCampaignID( campaignID ); 409 campaignData.setCampaignScenarios( scenarioDatas ); 410 411 return campaignData; 412 } 413 getWizardsIsleCampaignData()414 Campaign::CampaignData getWizardsIsleCampaignData() 415 { 416 const std::string wizardsIsleCampaignScenarioNames[4] = { _( "The Shrouded Isles" ), _( "The Eternal Scrolls" ), _( "Power's End" ), _( "Fount of Wizardry" ) }; 417 const std::string wizardsIsleCampaignDescription[4] = { 418 _( "Your mission is to vanquish the warring mages in the magical Shrouded Isles. The completion of this task will give you a fighting chance against your rivals." ), 419 _( "The location of the great library has been discovered! You must make your way to it, and reclaim the city of Chronos in which it lies." ), 420 _( "Find the Orb of negation, which is said to be buried in this land. There are clues inscribed on stone obelisks which will help lead you to your price. Find the orb before the first day of the sixth month, or your rivals will surely have gotten to the fount before you." ), 421 _( "You must take control of the castle of Magic, where the fount of wizardry lies. Do this and your victory will be supreme." ) }; 422 std::vector<Campaign::ScenarioData> scenarioDatas; 423 scenarioDatas.reserve( 4 ); 424 425 const int campaignID = Campaign::WIZARDS_ISLE_CAMPAIGN; 426 scenarioDatas.emplace_back( 0, std::vector<int>{ 1 }, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 0 ), "CAMP3_01.HXC", 427 wizardsIsleCampaignScenarioNames[0], wizardsIsleCampaignDescription[0], 428 Campaign::VideoSequence{ { "MIXWIZ16.SMK", Video::VideoAction::IGNORE_VIDEO }, 429 { "WIZ16.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 430 emptyPlayback ); 431 scenarioDatas.emplace_back( 1, std::vector<int>{ 2, 3 }, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 1 ), "CAMP3_02.HXC", 432 wizardsIsleCampaignScenarioNames[1], wizardsIsleCampaignDescription[1], 433 Campaign::VideoSequence{ { "MIXWIZ17.SMK", Video::VideoAction::IGNORE_VIDEO }, 434 { "WIZ17.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 435 Campaign::VideoSequence{ { "MIXWIZ18.SMK", Video::VideoAction::IGNORE_VIDEO }, 436 { "WIZ18.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); 437 scenarioDatas.emplace_back( 2, std::vector<int>{ 3 }, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 2 ), "CAMP3_03.HXC", 438 wizardsIsleCampaignScenarioNames[2], wizardsIsleCampaignDescription[2], emptyPlayback, 439 Campaign::VideoSequence{ { "MIXWIZ19.SMK", Video::VideoAction::IGNORE_VIDEO }, 440 { "WIZ19.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 441 Campaign::ScenarioVictoryCondition::OBTAIN_SPHERE_NEGATION ); 442 scenarioDatas.emplace_back( 3, std::vector<int>{}, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 3 ), "CAMP3_04.HXC", 443 wizardsIsleCampaignScenarioNames[3], wizardsIsleCampaignDescription[3], emptyPlayback, 444 Campaign::VideoSequence{ { "MIXWIZ20.SMK", Video::VideoAction::IGNORE_VIDEO }, 445 { "WIZ20.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); 446 447 Campaign::CampaignData campaignData; 448 campaignData.setCampaignID( campaignID ); 449 campaignData.setCampaignScenarios( scenarioDatas ); 450 451 return campaignData; 452 } 453 getVoyageHomeCampaignData()454 Campaign::CampaignData getVoyageHomeCampaignData() 455 { 456 const std::string voyageHomeCampaignScenarioNames[4] = { _( "Stranded" ), _( "Pirate Isles" ), _( "King and Country" ), _( "Blood is Thicker" ) }; 457 const std::string voyageHomeCampaignDescription[4] = { 458 _( "Capture the town on the island off the southeast shore in order to construct a boat and travel back towards the mainland. Do not lose the hero Gallavant." ), 459 _( "Find and defeat Martine, the pirate leader, who resides in Pirates Cove. Do not lose Gallavant or your quest will be over." ), 460 _( "Eliminate all the other forces who oppose the rule of Lord Alberon. Gallavant must not die." ), 461 _( "Overthrow the entrenched monarchy of Lord Alberon, and claim all the land in your name. Gallavant must not die." ) }; 462 std::vector<Campaign::ScenarioData> scenarioDatas; 463 scenarioDatas.reserve( 4 ); 464 465 const int campaignID = Campaign::VOYAGE_HOME_CAMPAIGN; 466 scenarioDatas.emplace_back( 0, std::vector<int>{ 1 }, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 0 ), "CAMP4_01.HXC", 467 voyageHomeCampaignScenarioNames[0], voyageHomeCampaignDescription[0], 468 Campaign::VideoSequence{ { "MIXVOY21.SMK", Video::VideoAction::IGNORE_VIDEO }, 469 { "VOY21.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 470 emptyPlayback ); 471 scenarioDatas.emplace_back( 1, std::vector<int>{ 2, 3 }, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 1 ), "CAMP4_02.HXC", 472 voyageHomeCampaignScenarioNames[1], voyageHomeCampaignDescription[1], 473 Campaign::VideoSequence{ { "MIXVOY22.SMK", Video::VideoAction::IGNORE_VIDEO }, 474 { "VOY22.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } }, 475 Campaign::VideoSequence{ { "MIXVOY23.SMK", Video::VideoAction::IGNORE_VIDEO }, 476 { "VOY23.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); 477 scenarioDatas.emplace_back( 2, std::vector<int>{ 3 }, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 2 ), "CAMP4_03.HXC", 478 voyageHomeCampaignScenarioNames[2], voyageHomeCampaignDescription[2], emptyPlayback, 479 Campaign::VideoSequence{ { "MIXVOY24.SMK", Video::VideoAction::IGNORE_VIDEO }, 480 { "VOY24.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); 481 scenarioDatas.emplace_back( 3, std::vector<int>{}, Campaign::ScenarioBonusData::getCampaignBonusData( campaignID, 3 ), "CAMP4_04.HXC", 482 voyageHomeCampaignScenarioNames[3], voyageHomeCampaignDescription[3], emptyPlayback, 483 Campaign::VideoSequence{ { "MIXVOY25.SMK", Video::VideoAction::IGNORE_VIDEO }, 484 { "VOY25.SMK", Video::VideoAction::PLAY_TILL_AUDIO_END } } ); 485 486 Campaign::CampaignData campaignData; 487 campaignData.setCampaignID( campaignID ); 488 campaignData.setCampaignScenarios( scenarioDatas ); 489 490 return campaignData; 491 } 492 } 493 494 namespace Campaign 495 { CampaignData()496 CampaignData::CampaignData() 497 : _campaignID( 0 ) 498 {} 499 500 // this is used to get awards that are not directly obtainable via scenario clear, such as assembling artifacts getExtraCampaignAwardData(const int campaignID)501 std::vector<Campaign::CampaignAwardData> CampaignAwardData::getExtraCampaignAwardData( const int campaignID ) 502 { 503 assert( campaignID >= 0 ); 504 505 switch ( campaignID ) { 506 case PRICE_OF_LOYALTY_CAMPAIGN: { 507 std::vector<Campaign::CampaignAwardData> extraAwards; 508 extraAwards.emplace_back( 10, Campaign::CampaignAwardData::TYPE_GET_ARTIFACT, Artifact::BATTLE_GARB ); 509 return extraAwards; 510 } 511 case ROLAND_CAMPAIGN: 512 case ARCHIBALD_CAMPAIGN: 513 case DESCENDANTS_CAMPAIGN: 514 case WIZARDS_ISLE_CAMPAIGN: 515 case VOYAGE_HOME_CAMPAIGN: 516 default: 517 break; 518 } 519 520 return std::vector<Campaign::CampaignAwardData>(); 521 } 522 getScenariosAfter(const int scenarioID) const523 const std::vector<int> & CampaignData::getScenariosAfter( const int scenarioID ) const 524 { 525 for ( size_t i = 0; i < _scenarios.size(); ++i ) { 526 if ( _scenarios[i].getScenarioID() == scenarioID ) 527 return _scenarios[i].getNextMaps(); 528 } 529 530 return _scenarios[scenarioID].getNextMaps(); 531 } 532 getStartingScenarios() const533 std::vector<int> CampaignData::getStartingScenarios() const 534 { 535 std::vector<int> startingScenarios; 536 537 for ( size_t i = 0; i < _scenarios.size(); ++i ) { 538 const int scenarioID = _scenarios[i].getScenarioID(); 539 if ( isStartingScenario( scenarioID ) ) 540 startingScenarios.emplace_back( scenarioID ); 541 } 542 543 return startingScenarios; 544 } 545 isStartingScenario(const int scenarioID) const546 bool CampaignData::isStartingScenario( const int scenarioID ) const 547 { 548 // starting scenario = a scenario that is never included as a nextMap 549 for ( size_t i = 0; i < _scenarios.size(); ++i ) { 550 const std::vector<int> & nextMaps = _scenarios[i].getNextMaps(); 551 552 if ( std::find( nextMaps.begin(), nextMaps.end(), scenarioID ) != nextMaps.end() ) 553 return false; 554 } 555 556 return true; 557 } 558 isAllCampaignMapsPresent() const559 bool CampaignData::isAllCampaignMapsPresent() const 560 { 561 for ( size_t i = 0; i < _scenarios.size(); ++i ) { 562 if ( !_scenarios[i].isMapFilePresent() ) 563 return false; 564 } 565 566 return true; 567 } 568 isLastScenario(const int scenarioID) const569 bool CampaignData::isLastScenario( const int scenarioID ) const 570 { 571 assert( !_scenarios.empty() ); 572 return scenarioID == _scenarios.back().getScenarioID(); 573 } 574 setCampaignID(const int campaignID)575 void CampaignData::setCampaignID( const int campaignID ) 576 { 577 _campaignID = campaignID; 578 } 579 setCampaignScenarios(const std::vector<ScenarioData> & scenarios)580 void CampaignData::setCampaignScenarios( const std::vector<ScenarioData> & scenarios ) 581 { 582 _scenarios = scenarios; 583 } 584 setCampaignDescription(const std::string & campaignDescription)585 void CampaignData::setCampaignDescription( const std::string & campaignDescription ) 586 { 587 _campaignDescription = campaignDescription; 588 } 589 getCampaignData(const int campaignID)590 const CampaignData & CampaignData::getCampaignData( const int campaignID ) 591 { 592 switch ( campaignID ) { 593 case ROLAND_CAMPAIGN: { 594 static const Campaign::CampaignData campaign( getRolandCampaignData() ); 595 return campaign; 596 } 597 case ARCHIBALD_CAMPAIGN: { 598 static const Campaign::CampaignData campaign( getArchibaldCampaignData() ); 599 return campaign; 600 } 601 case PRICE_OF_LOYALTY_CAMPAIGN: { 602 static const Campaign::CampaignData campaign( getPriceOfLoyaltyCampaignData() ); 603 return campaign; 604 } 605 case DESCENDANTS_CAMPAIGN: { 606 static const Campaign::CampaignData campaign( getDescendantsCampaignData() ); 607 return campaign; 608 } 609 case VOYAGE_HOME_CAMPAIGN: { 610 static const Campaign::CampaignData campaign( getVoyageHomeCampaignData() ); 611 return campaign; 612 } 613 case WIZARDS_ISLE_CAMPAIGN: { 614 static const Campaign::CampaignData campaign( getWizardsIsleCampaignData() ); 615 return campaign; 616 } 617 default: { 618 // Did you add a new campaign? Add the corresponding case above. 619 assert( 0 ); 620 static const Campaign::CampaignData noCampaign; 621 return noCampaign; 622 } 623 } 624 } 625 626 // default amount to 1 for initialized campaign award data CampaignAwardData(int id,uint32_t type,uint32_t subType)627 CampaignAwardData::CampaignAwardData( int id, uint32_t type, uint32_t subType ) 628 : CampaignAwardData( id, type, subType, 1, 0 ) 629 {} 630 CampaignAwardData(int id,uint32_t type,uint32_t subType,uint32_t amount)631 CampaignAwardData::CampaignAwardData( int id, uint32_t type, uint32_t subType, uint32_t amount ) 632 : CampaignAwardData( id, type, subType, amount, 0 ) 633 {} 634 CampaignAwardData(int id,uint32_t type,uint32_t subType,const std::string & customName)635 CampaignAwardData::CampaignAwardData( int id, uint32_t type, uint32_t subType, const std::string & customName ) 636 : CampaignAwardData( id, type, subType, 1, 0, customName ) 637 {} 638 CampaignAwardData(int id,uint32_t type,uint32_t subType,uint32_t amount,int startScenarioID,const std::string & customName)639 CampaignAwardData::CampaignAwardData( int id, uint32_t type, uint32_t subType, uint32_t amount, int startScenarioID, const std::string & customName ) 640 : _id( id ) 641 , _type( type ) 642 , _subType( subType ) 643 , _amount( amount ) 644 , _startScenarioID( startScenarioID ) 645 , _customName( customName ) 646 {} 647 ToString() const648 std::string CampaignAwardData::ToString() const 649 { 650 if ( !_customName.empty() ) 651 return _customName; 652 653 switch ( _type ) { 654 case CampaignAwardData::TYPE_CREATURE_CURSE: 655 return Monster( _subType ).GetName() + std::string( _( " bane" ) ); 656 case CampaignAwardData::TYPE_CREATURE_ALLIANCE: 657 return Monster( _subType ).GetName() + std::string( _( " alliance" ) ); 658 case CampaignAwardData::TYPE_GET_ARTIFACT: 659 return Artifact( _subType ).GetName(); 660 case CampaignAwardData::TYPE_CARRY_OVER_FORCES: 661 return _( "Carry-over forces" ); 662 case CampaignAwardData::TYPE_RESOURCE_BONUS: 663 return Resource::String( _subType ) + std::string( _( " bonus" ) ); 664 case CampaignAwardData::TYPE_GET_SPELL: 665 return Spell( _subType ).GetName(); 666 case CampaignAwardData::TYPE_HIREABLE_HERO: 667 return Heroes( _subType, 0 ).GetName(); 668 case CampaignAwardData::TYPE_DEFEAT_ENEMY_HERO: 669 return Heroes( _subType, 0 ).GetName() + std::string( _( " defeated" ) ); 670 default: 671 assert( 0 ); // some new/unhandled award 672 return ""; 673 } 674 } 675 getCampaignAwardData(const int campaignID,const int scenarioID)676 std::vector<Campaign::CampaignAwardData> CampaignAwardData::getCampaignAwardData( const int campaignID, const int scenarioID ) 677 { 678 assert( campaignID >= 0 && scenarioID >= 0 ); 679 680 switch ( campaignID ) { 681 case ROLAND_CAMPAIGN: 682 return getRolandCampaignAwardData( scenarioID ); 683 case ARCHIBALD_CAMPAIGN: 684 return getArchibaldCampaignAwardData( scenarioID ); 685 case PRICE_OF_LOYALTY_CAMPAIGN: 686 return getPriceOfLoyaltyCampaignAwardData( scenarioID ); 687 case DESCENDANTS_CAMPAIGN: 688 return getDescendantsCampaignAwardData( scenarioID ); 689 case WIZARDS_ISLE_CAMPAIGN: 690 return getWizardsIsleCampaignAwardData( scenarioID ); 691 case VOYAGE_HOME_CAMPAIGN: 692 // No campaign award for voyage home! 693 return {}; 694 default: 695 // Did you add a new campaign? Add the corresponding case above. 696 assert( 0 ); 697 break; 698 } 699 700 return {}; 701 } 702 getAllianceJoiningMessage(const int monsterId)703 const char * CampaignAwardData::getAllianceJoiningMessage( const int monsterId ) 704 { 705 switch ( monsterId ) { 706 case Monster::DWARF: 707 case Monster::BATTLE_DWARF: 708 return _( "The dwarves recognize their allies and gladly join your forces." ); 709 case Monster::OGRE: 710 case Monster::OGRE_LORD: 711 return _( "The ogres recognize you as the Dwarfbane and lumber over to join you." ); 712 case Monster::GREEN_DRAGON: 713 case Monster::RED_DRAGON: 714 case Monster::BLACK_DRAGON: 715 return _( "The dragons, snarling and growling, agree to join forces with you, their 'Ally'." ); 716 case Monster::ELF: 717 case Monster::GRAND_ELF: 718 return _( 719 "As you approach the group of elves, their leader calls them all to attention. He shouts to them, \"Who of you is brave enough to join this fearless ally of ours?\" The group explodes with cheers as they run to join your ranks." ); 720 default: 721 break; 722 } 723 724 assert( 0 ); // Did you forget to add a new alliance type? 725 return nullptr; 726 } 727 getAllianceFleeingMessage(const int monsterId)728 const char * CampaignAwardData::getAllianceFleeingMessage( const int monsterId ) 729 { 730 switch ( monsterId ) { 731 case Monster::DWARF: 732 case Monster::BATTLE_DWARF: 733 return _( "The dwarves hail you, \"Any friend of Roland is a friend of ours. You may pass.\"" ); 734 case Monster::OGRE: 735 case Monster::OGRE_LORD: 736 return _( "The ogres give you a grunt of recognition, \"Archibald's allies may pass.\"" ); 737 case Monster::GREEN_DRAGON: 738 case Monster::RED_DRAGON: 739 case Monster::BLACK_DRAGON: 740 return _( 741 "The dragons see you and call out. \"Our alliance with Archibald compels us to join you. Unfortunately you have no room. A pity!\" They quickly scatter." ); 742 case Monster::ELF: 743 case Monster::GRAND_ELF: 744 return _( 745 "The elves stand at attention as you approach. Their leader calls to you and says, \"Let us not impede your progress, ally! Move on, and may victory be yours.\"" ); 746 default: 747 break; 748 } 749 750 assert( 0 ); // Did you forget to add a new alliance type? 751 return nullptr; 752 } 753 getBaneFleeingMessage(const int monsterId)754 const char * CampaignAwardData::getBaneFleeingMessage( const int monsterId ) 755 { 756 switch ( monsterId ) { 757 case Monster::DWARF: 758 case Monster::BATTLE_DWARF: 759 return _( "\"The Dwarfbane!!!!, run for your lives.\"" ); 760 default: 761 break; 762 } 763 764 assert( 0 ); // Did you forget to add a new bane type? 765 return nullptr; 766 } 767 } 768