From 99691b0f1149390403d97b643c4392ac03799e5d Mon Sep 17 00:00:00 2001 From: mateuszb Date: Sat, 20 Dec 2008 17:08:51 +0000 Subject: [PATCH] * fixed compilation error * added frenzy spell * repaired order in stack queue in case a unit has waited (it should work correctly now) * added spell positiveness info, positive spells cannot be cast on hostile stacks and vice versa --- CAdvmapInterface.cpp | 2 +- CBattleInterface.cpp | 49 +++++++++++++---- CBattleInterface.h | 2 +- CCallback.cpp | 5 ++ CCallback.h | 2 + CGameState.cpp | 117 +++++++++++++++++++++++++++++----------- CGameState.h | 1 + config/spell_info.txt | 73 +++++++++++++++++++++++++ hch/CSpellHandler.cpp | 25 ++++++++- hch/CSpellHandler.h | 1 + server/CGameHandler.cpp | 10 ++++ 11 files changed, 245 insertions(+), 42 deletions(-) create mode 100644 config/spell_info.txt diff --git a/CAdvmapInterface.cpp b/CAdvmapInterface.cpp index d073e7e06..5f9a1f93b 100644 --- a/CAdvmapInterface.cpp +++ b/CAdvmapInterface.cpp @@ -765,7 +765,7 @@ void CResDataBar::deactivate() { ClickableR::deactivate(); } -CResDataBar::CResDataBar(const std::string &defname, int x, int y, int offx, int offy, int datedist) +CResDataBar::CResDataBar(const std::string &defname, int x, int y, int offx, int offy, int resdist, int datedist) { bg = BitmapHandler::loadBitmap(defname); SDL_SetColorKey(bg,SDL_SRCCOLORKEY,SDL_MapRGB(bg->format,0,255,255)); diff --git a/CBattleInterface.cpp b/CBattleInterface.cpp index b49cc4726..aa7c7576b 100644 --- a/CBattleInterface.cpp +++ b/CBattleInterface.cpp @@ -435,12 +435,13 @@ void CBattleInterface::show(SDL_Surface * to) int yPos = 10; std::vector stacksSorted; - for(int v=0; vcb->battleGetStackQueue(); + //for(int v=0; vtile); break; } + case 56: //frenzy + { + displayEffect(17, sc->tile); + break; + } case 61: //forgetfulness { displayEffect(42, sc->tile); @@ -1470,14 +1476,39 @@ void CBattleInterface::castThisSpell(int spellID) spellSelMode = 0; if(CGI->spellh->spells[spellID].attributes.find("CREATURE_TARGET") != std::string::npos) { - spellSelMode = 3; + switch(CGI->spellh->spells[spellID].positiveness) + { + case -1 : + spellSelMode = 2; + break; + case 0: + spellSelMode = 3; + break; + case 1: + spellSelMode = 1; + break; + } } if(CGI->spellh->spells[spellID].attributes.find("CREATURE_TARGET_2") != std::string::npos) { if(castingHero && castingHero->getSpellSecLevel(spellID) < 3) - spellSelMode = 3; - else //TODO: no destination chould apply in this case { + switch(CGI->spellh->spells[spellID].positiveness) + { + case -1 : + spellSelMode = 2; + break; + case 0: + spellSelMode = 3; + break; + case 1: + spellSelMode = 1; + break; + } + } + else + { + spellSelMode = -1; } } CGI->curh->changeGraphic(3, 0); diff --git a/CBattleInterface.h b/CBattleInterface.h index 180ea0978..c578abfd7 100644 --- a/CBattleInterface.h +++ b/CBattleInterface.h @@ -137,7 +137,7 @@ private: float getAnimSpeedMultiplier() const; //returns multiplier for number of frames in a group bool spellDestSelectMode; //if true, player is choosing destination for his spell - int spellSelMode; //0 - any location, 1 - any firendly creature, 2 - any hostile creature, 3 - any creature, 4 - obstacle + int spellSelMode; //0 - any location, 1 - any firendly creature, 2 - any hostile creature, 3 - any creature, 4 - obstacle, -1 - no location BattleAction * spellToCast; //spell for which player is choosing destination class CAttHelper diff --git a/CCallback.cpp b/CCallback.cpp index fc7ceb981..8581343cb 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -491,6 +491,11 @@ std::map CCallback::battleGetStacks() return ret; } +std::vector CCallback::battleGetStackQueue() +{ + return gs->curB->getStackQueue(); +} + CCreature CCallback::battleGetCreature(int number) { boost::shared_lock lock(*gs->mx); diff --git a/CCallback.h b/CCallback.h index 8ec5fc708..111cd1671 100644 --- a/CCallback.h +++ b/CCallback.h @@ -80,6 +80,7 @@ public: virtual int battleGetPos(int stack)=0; //returns position (tile ID) of stack virtual int battleMakeAction(BattleAction* action)=0;//for casting spells by hero - DO NOT use it for moving active stack virtual std::map battleGetStacks()=0; //returns stacks on battlefield + virtual std::vector battleGetStackQueue()=0; //returns vector of stack in order of their move sequence virtual CCreature battleGetCreature(int number)=0; //returns type of creature by given number of stack //virtual bool battleMoveCreature(int ID, int dest)=0; //moves creature with id ID to dest if possible virtual std::vector battleGetAvailableHexes(int ID)=0; //reutrns numbers of hexes reachable by creature with id ID @@ -167,6 +168,7 @@ public: int battleGetPos(int stack); //returns position (tile ID) of stack int battleMakeAction(BattleAction* action);//for casting spells by hero - DO NOT use it for moving active stack std::map battleGetStacks(); //returns stacks on battlefield + std::vector battleGetStackQueue(); //returns vector of stack in order of their move sequence CCreature battleGetCreature(int number); //returns type of creature by given number of stack std::vector battleGetAvailableHexes(int ID); //reutrns numbers of hexes reachable by creature with id ID bool battleIsStackMine(int ID); //returns true if stack with id ID belongs to caller diff --git a/CGameState.cpp b/CGameState.cpp index 2679dd002..be51c71d6 100644 --- a/CGameState.cpp +++ b/CGameState.cpp @@ -1500,58 +1500,47 @@ void CGameState::loadTownDInfos() } int BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender, const CGHeroInstance * attackerHero, const CGHeroInstance * defendingHero, bool shooting) { - int attackDefenseBonus = attacker->creature->attack + (attackerHero ? attackerHero->getPrimSkillLevel(0) : 0) - (defender->creature->defence + (defendingHero ? defendingHero->getPrimSkillLevel(1) : 0)); + int attackerAttackBonus = attacker->creature->attack + (attackerHero ? attackerHero->getPrimSkillLevel(0) : 0); + if(attacker->getEffect(56)) //frenzy for attacker + { + attackerAttackBonus += (VLC->spellh->spells[attacker->getEffect(56)->id].powers[attacker->getEffect(56)->level]/100.0) *(attacker->creature->defence + (attackerHero ? attackerHero->getPrimSkillLevel(1) : 0)); + } + int defenderDefenseBonus = defender->creature->defence + (defendingHero ? defendingHero->getPrimSkillLevel(1) : 0); + if(defender->getEffect(56)) //frenzy for defender + { + defenderDefenseBonus = 0; + } + int attackDefenseBonus = attackerAttackBonus - defenderDefenseBonus; if(defender->getEffect(48)) //defender's prayer handling { - if(defender->getEffect(48)->level<=1) //none or basic - attackDefenseBonus -= 2; - else //adv or expert - attackDefenseBonus -= 4; + attackDefenseBonus -= VLC->spellh->spells[defender->getEffect(48)->id].powers[defender->getEffect(48)->level]; } if(attacker->getEffect(48)) //attacker's prayer handling { - if(attacker->getEffect(48)->level<=1) //none or basic - attackDefenseBonus += 2; - else //adv or expert - attackDefenseBonus += 4; + attackDefenseBonus += VLC->spellh->spells[attacker->getEffect(48)->id].powers[attacker->getEffect(48)->level]; } if(defender->getEffect(46)) //stone skin handling { - if(defender->getEffect(46)->level<=1) //none or basic - attackDefenseBonus -= 3; - else //adv or expert - attackDefenseBonus -= 6; + attackDefenseBonus -= VLC->spellh->spells[defender->getEffect(46)->id].powers[defender->getEffect(46)->level]; } if(attacker->getEffect(45)) //weakness handling { - if(attacker->getEffect(45)->level<=1) //none or basic - attackDefenseBonus -= 3; - else //adv or expert - attackDefenseBonus -= 6; + attackDefenseBonus -= VLC->spellh->spells[attacker->getEffect(45)->id].powers[attacker->getEffect(45)->level]; } if(!shooting && attacker->getEffect(43)) //bloodlust handling { - if(attacker->getEffect(43)->level<=1) //none or basic - attackDefenseBonus += 3; - else //adv or expert - attackDefenseBonus += 6; + attackDefenseBonus += VLC->spellh->spells[attacker->getEffect(43)->id].powers[attacker->getEffect(43)->level]; } int damageBase = 0; if(attacker->getEffect(42)) //curse handling (partial, the rest is below) { damageBase = attacker->creature->damageMin; - if(attacker->getEffect(42)->level >= 2) //adv or expert - { - damageBase -= 1; - } + damageBase -= VLC->spellh->spells[attacker->getEffect(42)->id].powers[attacker->getEffect(42)->level]; } else if(attacker->getEffect(41)) //bless handling { damageBase = attacker->creature->damageMax; - if(attacker->getEffect(41)->level >= 2) //adv or expert - { - damageBase += 1; - } + damageBase += VLC->spellh->spells[attacker->getEffect(41)->id].powers[attacker->getEffect(41)->level]; } else if(attacker->creature->damageMax == attacker->creature->damageMin) //constant damage { @@ -1698,4 +1687,72 @@ CStack * BattleInfo::getNextStack() return stacks[i]; } return NULL; //all stacks moved or defending! -} \ No newline at end of file +} + +std::vector BattleInfo::getStackQueue() +{ + std::vector ret; + std::vector taken; //if non-zero value, corresponding stack has been placed in ret + taken.resize(stacks.size()); + for(int g=0; gstate,DEFENDING)) + && stacks[i]->alive() + && (moved == 1 || !vstd::contains(stacks[i]->state,MOVED)) + && !vstd::contains(stacks[i]->state,WAITING) + && taken[i]==0) + { + if(speed == -1 || stacks[i]->speed() > speed) + { + id = i; + speed = stacks[i]->speed(); + } + } + } + if(id != -1) + { + ret.push_back(*stacks[id]); + taken[id] = 1; + } + else //choose something from not moved stacks + { + int id = -1, speed = 10000; //infinite speed + for(int i=0; istate,DEFENDING)) + && stacks[i]->alive() + && (moved == 1 || !vstd::contains(stacks[i]->state,MOVED)) + && vstd::contains(stacks[i]->state,WAITING) + && taken[i]==0) + { + if(stacks[i]->speed() < speed) //slowest one + { + id = i; + speed = stacks[i]->speed(); + } + } + } + if(id != -1) + { + ret.push_back(*stacks[id]); + taken[id] = 1; + } + else + { + break; //no stacks have been found, so none of them will be found in next iterations + } + } + } + } + return ret; +} diff --git a/CGameState.h b/CGameState.h index 6391676cf..e20beaaa6 100644 --- a/CGameState.h +++ b/CGameState.h @@ -72,6 +72,7 @@ struct DLL_EXPORT BattleInfo h & side1 & side2 & round & activeStack & siege & tile & stacks & army1 & army2 & hero1 & hero2; } CStack * getNextStack(); //which stack will have turn after current one + std::vector getStackQueue(); //returns stack in order of their movement action CStack * getStack(int stackID); CStack * getStackT(int tileID); void getAccessibilityMap(bool *accessibility, int stackToOmmit=-1); //send pointer to at least 187 allocated bytes diff --git a/config/spell_info.txt b/config/spell_info.txt new file mode 100644 index 000000000..1c416fac0 --- /dev/null +++ b/config/spell_info.txt @@ -0,0 +1,73 @@ +//additional spell info, not included in original heroes III files +//[spellID - -1 is the end of data in file] [-1 -> spell is negative for influenced creatures; 0 - spell is indifferent for them; 1 - spell is poitive for them] +0 0 +1 0 +2 0 +3 0 +4 0 +5 0 +6 0 +7 0 +8 0 +9 0 +10 0 +11 0 +12 0 +13 0 +14 0 +15 -1 +16 -1 +17 -1 +18 -1 +19 -1 +20 -1 +21 -1 +22 -1 +23 -1 +24 -1 +25 -1 +26 -1 +27 1 +28 1 +29 1 +30 1 +31 1 +32 1 +33 1 +34 1 +35 1 +36 1 +37 1 +38 1 +39 1 +40 1 +41 1 +42 -1 +43 1 +44 1 +45 -1 +46 1 +47 -1 +48 1 +49 1 +50 -1 +51 1 +52 -1 +53 1 +54 -1 +55 1 +56 1 +57 -1 +58 1 +59 -1 +60 -1 +61 -1 +62 -1 +63 1 +64 0 +65 1 +66 0 +67 0 +68 0 +69 0 +-1 \ No newline at end of file diff --git a/hch/CSpellHandler.cpp b/hch/CSpellHandler.cpp index e804db06e..dc01be28b 100644 --- a/hch/CSpellHandler.cpp +++ b/hch/CSpellHandler.cpp @@ -79,4 +79,27 @@ void CSpellHandler::loadSpells() nsp.creatureAbility = creatureAbility; spells.push_back(nsp); } -} \ No newline at end of file + //loading of additional spell traits + std::ifstream ast; + ast.open("config/spell_info.txt", std::ios::binary); + if(!ast.is_open()) + { + tlog1<<"lack of config/spell_info.txt file!"<>dump; + //reading exact info + int spellID; + ast>>spellID; + while(spellID != -1) + { + int buf; + ast>>buf; + spells[spellID].positiveness = buf; + ast>>spellID; + } + } +} diff --git a/hch/CSpellHandler.h b/hch/CSpellHandler.h index 51aafb3b1..dc9b3527e 100644 --- a/hch/CSpellHandler.h +++ b/hch/CSpellHandler.h @@ -24,6 +24,7 @@ public: std::string attributes; //reference only attributes bool combatSpell; //is this spell combat (true) or adventure (false) bool creatureAbility; //if true, only creatures can use this spell + si8 positiveness; //1 if spell is positive for influenced stacks, 0 if it is indifferent, -1 if it's negative }; class DLL_EXPORT CSpellHandler diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 11dbb1a4d..d6aad29c7 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -1400,6 +1400,16 @@ upgend: sendAndApply(&sse); break; } + case 56: //frenzy + { + SetStackEffect sse; + sse.stack = gs->curB->getStackT(ba.destinationTile)->ID; + sse.effect.id = 56; + sse.effect.level = getSchoolLevel(h,s); + sse.effect.turnsRemain = 1; //! - different duration + sendAndApply(&sse); + break; + } case 61: //forgetfulness { SetStackEffect sse;