diff --git a/config/specials.txt b/config/specials.txt new file mode 100644 index 000000000..3e42401b2 --- /dev/null +++ b/config/specials.txt @@ -0,0 +1,176 @@ +Hero ID Bonus Type Val Subtype Additional Info +0 2 1 0 5 +1 1 2 0 0 +2 1 4 0 0 +3 2 5 1 2 +4 2 13 0 5 +5 1 6 0 0 +6 1 146 0 0 +7 1 10 0 0 +8 2 27 0 5 +9 6 41 0 3 +10 8 45 0 0 +11 3 20 0 3 +12 1 8 0 0 +13 2 11 0 5 +14 8 48 0 0 +15 10 350 6 0 +16 2 23 0 5 +17 1 16 0 0 +18 10 350 6 0 +19 1 22 0 0 +20 2 26 0 5 +21 1 18 0 0 +22 1 24 0 0 +23 2 2 0 5 +24 8 55 1 0 +25 3 37 0 3 +26 2 24 0 5 +27 2 27 0 5 +28 2 11 0 5 +29 7 51 0 0 +30 3 16 0 3 +31 1 20 0 0 +32 1 30 0 0 +33 1 36 0 0 +34 1 32 0 0 +35 2 23 0 5 +36 1 146 0 0 +37 1 38 0 0 +38 10 1 1 0 +39 1 36 0 0 +40 3 60 0 3 +41 2 8 1 5 +42 2 11 0 5 +43 7 51 0 0 +44 1 34 0 0 +45 3 19 0 3 +46 8 53 0 0 +47 10 350 6 0 +48 1 46 0 0 +49 1 52 0 0 +50 1 48 0 0 +51 1 42 0 0 +52 10 350 6 0 +53 1 42 0 0 +54 1 146 0 0 +55 1 50 0 0 +56 2 24 0 5 +57 3 22 0 3 +58 2 8 1 5 +59 8 45 0 0 +60 10 1 3 0 +61 8 43 0 0 +62 2 25 0 5 +63 3 21 0 3 +64 1 58 0 0 +65 1 62 0 0 +66 1 64 0 0 +67 1 60 0 0 +68 1 66 0 0 +69 2 12 0 5 +70 10 350 6 0 +71 1 56 0 0 +72 3 24 0 3 +73 3 23 0 3 +74 2 25 0 5 +75 2 11 1 5 +76 3 39 0 3 +77 8 46 0 0 +78 2 12 0 5 +79 10 350 6 0 +80 1 72 0 0 +81 1 146 0 0 +82 1 78 0 0 +83 1 74 0 0 +84 10 350 6 0 +85 2 2 0 5 +86 1 80 0 0 +87 1 70 0 0 +88 3 38 0 3 +89 2 8 1 5 +90 2 25 0 5 +91 3 38 0 3 +92 2 11 1 5 +93 3 23 0 3 +94 10 1 4 0 +95 8 46 0 0 +96 1 94 0 0 +97 1 146 0 0 +98 1 88 0 0 +99 1 92 0 0 +101 1 84 0 0 +102 1 90 0 0 +103 2 22 0 5 +104 1 86 0 0 +105 2 25 0 5 +106 1 90 0 0 +107 2 2 0 5 +108 8 53 0 0 +109 8 44 0 0 +110 2 25 0 5 +111 2 11 1 5 +112 10 1 5 0 +113 1 106 0 0 +114 1 98 0 0 +115 1 100 0 0 +116 2 23 0 5 +117 1 102 0 0 +118 1 104 0 0 +119 1 146 0 0 +120 1 108 0 0 +121 2 8 1 5 +122 2 5 1 2 +123 2 27 0 5 +124 8 46 0 0 +125 2 25 0 5 +126 2 24 0 5 +127 2 11 1 5 +128 4 120 1 3 +128 4 120 2 3 +129 4 113 1 2 +129 4 113 1 1 +129 4 113 4 5 +130 4 114 1 1 +130 4 114 1 2 +130 4 114 3 2 +131 4 115 1 2 +132 4 120 1 3 +132 4 120 2 3 +133 4 113 1 2 +133 4 113 1 1 +133 4 113 4 5 +134 4 114 1 1 +134 4 114 1 2 +134 4 114 3 2 +135 4 115 1 2 +136 5 13 0 100 +137 8 53 0 0 +138 5 15 0 50 +139 8 46 0 0 +140 8 43 0 0 +141 8 47 0 0 +142 10 350 6 0 +143 10 350 6 0 +144 12 2 0 0 +145 11 14 0 0 +146 1 4 0 0 +147 9 8 0 136 +147 9 34 0 136 +148 9 2 0 137 +148 9 18 0 137 +149 4 96 1 5 +149 4 96 2 5 +149 4 96 3 10 +150 4 66 1 5 +150 4 66 2 5 +150 4 66 3 10 +151 13 1 1 5 +151 13 1 2 5 +152 1 4 0 0 +153 13 1 1 5 +153 13 1 1 5 +154 1 90 0 0 +155 4 54 1 4 +155 4 54 2 2 +155 4 54 5 1 diff --git a/hch/CHeroHandler.cpp b/hch/CHeroHandler.cpp index 5ae43eae1..beb471d85 100644 --- a/hch/CHeroHandler.cpp +++ b/hch/CHeroHandler.cpp @@ -1,14 +1,16 @@ #define VCMI_DLL #include "../stdafx.h" #include "CHeroHandler.h" -#include #include "CLodHandler.h" #include "../lib/VCMI_Lib.h" #include +#include +#include +#include +using namespace boost::spirit; extern CLodHandler * bitmaph; void loadToIt(std::string &dest, const std::string &src, int &iter, int mode); - /* * CHeroHandler.cpp, part of VCMI engine * @@ -350,6 +352,7 @@ void CHeroHandler::loadHeroes() iss >> hid >> sid; heroes[hid]->startingSpell = sid; } + inp.close(); } loadHeroClasses(); initHeroClasses(); @@ -404,6 +407,25 @@ void CHeroHandler::loadHeroes() } ballistics.push_back(bli); } + { + it = 0; + std::ifstream inp; + dump.clear(); + inp.open(DATA_DIR "/config/specials.txt"); //loading hero specials + specialInfo dummy; + si32 hid; + inp.ignore(100, '\n'); + for (int i = 0; i < 174; ++i) + { + inp >> hid; + inp >> dummy.type; + inp >> dummy.val; + inp >> dummy.subtype; + inp >> dummy.additionalinfo; + heroes[hid]->spec.push_back(dummy); //put a copy of dummy + } + inp.close(); + } } void CHeroHandler::loadHeroClasses() { diff --git a/hch/CHeroHandler.h b/hch/CHeroHandler.h index 3ba15686b..621a22650 100644 --- a/hch/CHeroHandler.h +++ b/hch/CHeroHandler.h @@ -19,6 +19,12 @@ class CHeroClass; class CDefHandler; class CGameInfo; class CGHeroInstance; +struct specialInfo +{ si32 type; + si32 val; + si32 subtype; + si32 additionalinfo; +}; class DLL_EXPORT CHero { public: @@ -33,6 +39,7 @@ public: CHeroClass * heroClass; EHeroClasses heroType; //hero class std::vector > secSkillsInit; //initial secondary skills; first - ID of skill, second - level of skill (1 - basic, 2 - adv., 3 - expert) + std::vector spec; si32 startingSpell; //-1 if none //bool operator<(CHero& drugi){if (ID < drugi.ID) return true; else return false;} diff --git a/hch/CObjectHandler.cpp b/hch/CObjectHandler.cpp index 070490f1d..5d980fa93 100644 --- a/hch/CObjectHandler.cpp +++ b/hch/CObjectHandler.cpp @@ -923,6 +923,138 @@ const std::string & CGHeroInstance::getBiography() const void CGHeroInstance::initObj() { blockVisit = true; + speciality.growthsWithLevel = false; + Bonus bonus; + for (std::vector::iterator it = type->spec.begin(); it != type->spec.end(); it++) + { + bonus.val = it->val; + bonus.id = id; //from the hero, speciality has no unique id + bonus.duration = Bonus::PERMANENT; + bonus.source = Bonus::HERO_SPECIAL; + switch (it->type) + { + case 1:// creature speciality + speciality.growthsWithLevel = true; + bonus.type = Bonus::SPECIAL_CREATURE; + bonus.valType = Bonus::ADDITIVE_VALUE; + bonus.subtype = 1; //attack + bonus.additionalInfo = level/VLC->creh->creatures[it->val]->level * VLC->creh->creatures[it->val]->attack; + speciality.bonuses.push_back (bonus); + bonus.subtype = 2; //defense + bonus.additionalInfo = level/VLC->creh->creatures[it->val]->level * VLC->creh->creatures[it->val]->defence; + speciality.bonuses.push_back (bonus); + bonus.subtype = 5; + bonus.additionalInfo = 1; //+1 speed + speciality.bonuses.push_back (bonus); + for (std::set::iterator i = VLC->creh->creatures[it->val]->upgrades.begin(); + i != VLC->creh->creatures[it->val]->upgrades.end(); i++) + { + bonus.val = *i; // for all direct upgrades of that creature + bonus.subtype = 1; //attack + bonus.additionalInfo = level/VLC->creh->creatures[*i]->level * VLC->creh->creatures[*i]->attack; + speciality.bonuses.push_back (bonus); + bonus.subtype = 2; //defense + bonus.additionalInfo = level/VLC->creh->creatures[*i]->level * VLC->creh->creatures[*i]->defence; + speciality.bonuses.push_back (bonus); + bonus.subtype = 5; + bonus.additionalInfo = 1; //+1 speed + speciality.bonuses.push_back (bonus); + } + break; + case 2://secondary skill + speciality.growthsWithLevel = true; + bonus.type = Bonus::SECONDARY_SKILL; + bonus.subtype = it->val; //skill id + bonus.val = it->additionalinfo * level; //actual value, screwed mapping :/ + switch (it->subtype) + { + case 0: //normal + bonus.valType = Bonus::PERCENT_TO_BASE; + break; + case 1: //when it's navigation or there's no 'base' at all + bonus.valType = Bonus::PERCENT_TO_ALL; + break; + } + speciality.bonuses.push_back (bonus); + break; + case 3://spell damage bonus, level dependant + speciality.growthsWithLevel = true; + bonus.type = Bonus::SPECIAL_SPELL_LEV; + bonus.subtype = it->subtype; + bonus.additionalInfo = it->additionalinfo; + speciality.bonuses.push_back (bonus); + break; + case 4://creature stat boost + bonus.type = Bonus::SPECIAL_CREATURE; + bonus.valType = Bonus::ADDITIVE_VALUE; + bonus.subtype = it->subtype; + bonus.additionalInfo = it->additionalinfo; + speciality.bonuses.push_back (bonus); + break; + case 5://spell damage bonus in percent + bonus.type = Bonus::SPECIFIC_SPELL_DAMAGE; + bonus.valType = Bonus::PERCENT_TO_ALL; + bonus.additionalInfo = it->additionalinfo; + speciality.bonuses.push_back (bonus); + break; + case 6://damage bonus for bless (Adela) + bonus.type = Bonus::SPECIAL_BLESS_DAMAGE; + bonus.additionalInfo = it->additionalinfo; //damage factor + speciality.bonuses.push_back (bonus); + break; + case 7://maxed mastery for spell + bonus.type = Bonus::MAXED_SPELL; + bonus.val = it->val; //spell id + speciality.bonuses.push_back (bonus); + break; + case 8://peculiar spells - enchantments + bonus.type = Bonus::SPECIAL_PECULIAR_ENCHANT; + bonus.val = it->val; //spell id + bonus.subtype = it->subtype; //0, 1 for Coronius + speciality.bonuses.push_back (bonus); + case 9://upgrade creatures + bonus.type = Bonus::SPECIAL_UPGRADE; + bonus.additionalInfo = it->additionalinfo; + speciality.bonuses.push_back (bonus); + for (std::set::iterator i = VLC->creh->creatures[it->val]->upgrades.begin(); + i != VLC->creh->creatures[it->val]->upgrades.end(); i++) + { + bonus.val = *i; + speciality.bonuses.push_back (bonus); //propagate for regular upgrades of base creature + } + break; + case 10://resource generation + bonus.type = Bonus::GENERATE_RESOURCE; + bonus.subtype = it->subtype; + speciality.bonuses.push_back (bonus); + break; + case 11://starting skill with mastery (Adrienne) + cb->changeSecSkill (id, it->val, it->additionalinfo); //simply give it and forget + break; + case 12://army speed + bonus.type = Bonus::STACKS_SPEED; + bonus.val = it->val; + speciality.bonuses.push_back (bonus); + break; + case 13://Dragon bonuses (Mutare) + bonus.type = Bonus::SPECIAL_CREATURE; + bonus.valType = Bonus::ADDITIVE_VALUE; + bonus.additionalInfo = it->additionalinfo; //value + bonus.subtype = it->subtype; //which stat it is + for (std::vector::iterator i = VLC->creh->creatures.begin(); i != VLC->creh->creatures.end(); i++) + { //TODO: what if creature changes type during the game (Dragon Eye Ring?) + if ((*i)->hasBonusOfType(Bonus::DRAGON_NATURE)) //TODO: implement it! + { + bonus.val = (*i)->idNumber; //for + speciality.bonuses.push_back (bonus); + } + } + default: + tlog2 << "Unexpected hero speciality " << type <<'\n'; + } + } + if (speciality.growthsWithLevel) + speciality.recalculateSpecials(); } void CGHeroInstance::setPropertyDer( ui8 what, ui32 val ) @@ -1175,6 +1307,8 @@ void CGHeroInstance::getParents(TCNodes &out, const CBonusSystemNode *root /*= N if((root == this || contains(static_cast(root))) && visitedTown) out.insert(visitedTown); + + out.insert (&speciality); } void CGHeroInstance::pushPrimSkill(int which, int val) diff --git a/hch/CObjectHandler.h b/hch/CObjectHandler.h index 8c5bede7a..a18c3e1da 100644 --- a/hch/CObjectHandler.h +++ b/hch/CObjectHandler.h @@ -305,7 +305,7 @@ public: struct DLL_EXPORT HeroSpecial : CBonusSystemNode { bool growthsWithLevel; - void RecalculateSpecials(){}; + void recalculateSpecials(){}; template void serialize(Handler &h, const int version) { h & static_cast(*this); diff --git a/lib/HeroBonus.h b/lib/HeroBonus.h index ab8505d75..2c8c0543a 100644 --- a/lib/HeroBonus.h +++ b/lib/HeroBonus.h @@ -147,7 +147,17 @@ namespace PrimarySkill BONUS_NAME(NOT_ACTIVE) \ BONUS_NAME(NO_LUCK) /*eg. when fighting on cursed ground*/ \ BONUS_NAME(NO_MORALE) /*eg. when fighting on cursed ground*/ \ - BONUS_NAME(DARKNESS) /*val = radius */ + BONUS_NAME(DARKNESS) /*val = radius */ \ + BONUS_NAME(SPECIAL_CREATURE_LEV) /*val = base id*/ \ + BONUS_NAME(SPECIAL_SECONDARY_SKILL) /*val = id, additionalInfo = value per level in percent*/ \ + BONUS_NAME(SPECIAL_SPELL_LEV) /*val = id, additionalInfo = value per level in percent*/\ + BONUS_NAME(SPECIAL_CREATURE) /*val = base id, subtype = stat, additionalInfo = value*/\ + BONUS_NAME(SPECIFIC_SPELL_DAMAGE) /*val = id of spell, additionalInfo = value*/\ + BONUS_NAME(SPECIAL_BLESS_DAMAGE) /*val = spell (bless), additionalInfo = value per level in percent*/\ + BONUS_NAME(MAXED_SPELL) /*val = id*/\ + BONUS_NAME(SPECIAL_PECULIAR_ENCHANT) /*blesses and curses with id = val dependent on unit's level, subtype = 0 or 1 for Coronius*/\ + BONUS_NAME(SPECIAL_UPGRADE) /*val = base, additionalInfo = target */\ + BONUS_NAME(DRAGON_NATURE) /*TODO: implement it!*/ struct DLL_EXPORT Bonus { @@ -180,6 +190,7 @@ struct DLL_EXPORT Bonus TOWN_STRUCTURE, HERO_BASE_SKILL, SECONDARY_SKILL, + HERO_SPECIAL, ARMY };