1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

* 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
This commit is contained in:
mateuszb 2008-12-20 17:08:51 +00:00
parent dbd6f2bc82
commit 99691b0f11
11 changed files with 245 additions and 42 deletions

View File

@ -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));

View File

@ -435,12 +435,13 @@ void CBattleInterface::show(SDL_Surface * to)
int yPos = 10;
std::vector<CStack> stacksSorted;
for(int v=0; v<stacks.size(); ++v)
{
if(stacks[v].alive()) //we don't want dead stacks to be there
stacksSorted.push_back(stacks[v]);
}
std::stable_sort(stacksSorted.begin(), stacksSorted.end(), cmpst2);
stacksSorted = LOCPLINT->cb->battleGetStackQueue();
//for(int v=0; v<stacks.size(); ++v)
//{
// if(stacks[v].alive()) //we don't want dead stacks to be there
// stacksSorted.push_back(stacks[v]);
//}
//std::stable_sort(stacksSorted.begin(), stacksSorted.end(), cmpst2);
int startFrom = -1;
for(int n=0; n<stacksSorted.size(); ++n)
{
@ -1446,6 +1447,11 @@ void CBattleInterface::spellCasted(SpellCasted * sc)
displayEffect(19, sc->tile);
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);

View File

@ -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

View File

@ -491,6 +491,11 @@ std::map<int, CStack> CCallback::battleGetStacks()
return ret;
}
std::vector<CStack> CCallback::battleGetStackQueue()
{
return gs->curB->getStackQueue();
}
CCreature CCallback::battleGetCreature(int number)
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);

View File

@ -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<int, CStack> battleGetStacks()=0; //returns stacks on battlefield
virtual std::vector<CStack> 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<int> 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<int, CStack> battleGetStacks(); //returns stacks on battlefield
std::vector<CStack> 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<int> 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

View File

@ -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!
}
}
std::vector<CStack> BattleInfo::getStackQueue()
{
std::vector<CStack> ret;
std::vector<int> taken; //if non-zero value, corresponding stack has been placed in ret
taken.resize(stacks.size());
for(int g=0; g<taken.size(); ++g)
{
taken[g] = 0;
}
for(int moved=0; moved<2; ++moved) //in first cycle we add stacks that can act in current turn, in second one the rest of them
{
for(int gc=0; gc<stacks.size(); ++gc)
{
int id = -1, speed = -1;
for(int i=0; i<stacks.size(); ++i) //find not waited stacks only
{
if((moved == 1 ||!vstd::contains(stacks[i]->state,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; i<stacks.size(); ++i) //find waited stacks only
{
if((moved == 1 ||!vstd::contains(stacks[i]->state,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;
}

View File

@ -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<CStack> 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

73
config/spell_info.txt Normal file
View File

@ -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

View File

@ -79,4 +79,27 @@ void CSpellHandler::loadSpells()
nsp.creatureAbility = creatureAbility;
spells.push_back(nsp);
}
}
//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!"<<std::endl;
}
else
{
//reading header
std::string dump;
for(int i=0; i<42; ++i) ast>>dump;
//reading exact info
int spellID;
ast>>spellID;
while(spellID != -1)
{
int buf;
ast>>buf;
spells[spellID].positiveness = buf;
ast>>spellID;
}
}
}

View File

@ -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

View File

@ -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;