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

* new spell: cure

* minor changes
This commit is contained in:
mateuszb 2009-08-04 17:05:49 +00:00
parent e4580faba8
commit 1872c2d575
13 changed files with 138 additions and 40 deletions

View File

@ -300,7 +300,7 @@ BattleAction CBattleLogic::MakeDecision(int stackID)
std::vector<int> CBattleLogic::GetAvailableHexesForAttacker(CStack *defender, CStack *attacker)
std::vector<int> CBattleLogic::GetAvailableHexesForAttacker(const CStack *defender, const CStack *attacker)
{
int x = m_battleHelper.DecodeXPosition(defender->position);
int y = m_battleHelper.DecodeYPosition(defender->position);
@ -408,7 +408,7 @@ std::vector<int> CBattleLogic::GetAvailableHexesForAttacker(CStack *defender, CS
}
int new_pos = m_battleHelper.GetBattleFieldPosition(it->first, it->second);
CStack *st = m_cb->battleGetStackByPos(new_pos);
const CStack *st = m_cb->battleGetStackByPos(new_pos);
if (st == NULL || st->amount < 1)
{
@ -479,7 +479,7 @@ BattleAction CBattleLogic::MakeWait(int stackID)
BattleAction CBattleLogic::MakeAttack(int attackerID, int destinationID)
{
CStack *attackerStack = m_cb->battleGetStackByID(attackerID),
const CStack *attackerStack = m_cb->battleGetStackByID(attackerID),
*destinationStack = m_cb->battleGetStackByID(destinationID);
assert(attackerStack && destinationStack);
@ -744,7 +744,7 @@ void CBattleLogic::PrintBattleAction(const BattleAction &action) // for debug pu
message += "stack - " + boost::lexical_cast<std::string>(m_battleHelper.DecodeXPosition(action.additionalInfo));
message += ", " + boost::lexical_cast<std::string>(m_battleHelper.DecodeYPosition(action.additionalInfo));
message += ", creature - ";
CStack *c = m_cb->battleGetStackByPos(action.additionalInfo);
const CStack *c = m_cb->battleGetStackByPos(action.additionalInfo);
if (c && c->creature)
{
message += c->creature->nameRef;

View File

@ -105,7 +105,7 @@ private:
/**
* Helper function. It's used for performing an attack action.
*/
std::vector<int> GetAvailableHexesForAttacker(CStack *defender, CStack *attacker = NULL);
std::vector<int> GetAvailableHexesForAttacker(const CStack *defender, const CStack *attacker = NULL);
/**
* Just make defend action.
*/

View File

@ -442,7 +442,7 @@ int CCallback::battleGetStack(int pos)
return gs->battleGetStack(pos);
}
CStack* CCallback::battleGetStackByID(int ID)
const CStack* CCallback::battleGetStackByID(int ID)
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
if(!gs->curB) return NULL;
@ -456,7 +456,7 @@ int CCallback::battleMakeAction(BattleAction* action)
return 0;
}
CStack* CCallback::battleGetStackByPos(int pos)
const CStack* CCallback::battleGetStackByPos(int pos)
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
return battleGetStackByID(battleGetStack(pos));
@ -553,7 +553,7 @@ bool CCallback::battleIsStackMine(int ID)
bool CCallback::battleCanShoot(int ID, int dest)
{
boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
CStack *our = battleGetStackByID(ID), *dst = battleGetStackByPos(dest);
const CStack *our = battleGetStackByID(ID), *dst = battleGetStackByPos(dest);
if(!our || !dst || !gs->curB) return false;
//for(size_t g=0; g<our->effects.size(); ++g)

View File

@ -166,8 +166,8 @@ public:
virtual int battleGetObstaclesAtTile(int tile)=0; //returns bitfield
virtual std::vector<CObstacleInstance> battleGetAllObstacles()=0; //returns all obstacles on the battlefield
virtual int battleGetStack(int pos)=0; //returns ID of stack on the tile
virtual CStack * battleGetStackByID(int ID)=0; //returns stack info by given ID
virtual CStack * battleGetStackByPos(int pos)=0; //returns stack info by given pos
virtual const CStack * battleGetStackByID(int ID)=0; //returns stack info by given ID
virtual const CStack * battleGetStackByPos(int pos)=0; //returns stack info by given pos
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
@ -267,8 +267,8 @@ public:
int battleGetObstaclesAtTile(int tile); //returns bitfield
std::vector<CObstacleInstance> battleGetAllObstacles(); //returns all obstacles on the battlefield
int battleGetStack(int pos); //returns ID of stack on the tile
CStack * battleGetStackByID(int ID); //returns stack info by given ID
CStack * battleGetStackByPos(int pos); //returns stack info by given pos
const CStack * battleGetStackByID(int ID); //returns stack info by given ID
const CStack * battleGetStackByPos(int pos); //returns stack info by given pos
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

View File

@ -709,8 +709,8 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
{
if(std::find(shadedHexes.begin(),shadedHexes.end(),myNumber) == shadedHexes.end())
{
CStack *shere = LOCPLINT->cb->battleGetStackByPos(myNumber);
CStack *sactive = LOCPLINT->cb->battleGetStackByID(activeStack);
const CStack *shere = LOCPLINT->cb->battleGetStackByPos(myNumber);
const CStack *sactive = LOCPLINT->cb->battleGetStackByID(activeStack);
if(shere)
{
if(shere->owner == LOCPLINT->playerID) //our stack
@ -762,7 +762,7 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
}
else //available tile
{
CStack *sactive = LOCPLINT->cb->battleGetStackByID(activeStack);
const CStack *sactive = LOCPLINT->cb->battleGetStackByID(activeStack);
if(LOCPLINT->cb->battleGetStackByID(activeStack)->creature->isFlying())
{
CGI->curh->changeGraphic(1,2);
@ -805,7 +805,7 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
}
else
{
CStack * stackUnder = LOCPLINT->cb->battleGetStackByPos(myNumber);
const CStack * stackUnder = LOCPLINT->cb->battleGetStackByPos(myNumber);
bool whichCase; //for cases 1, 2 and 3
switch(spellSelMode)
{
@ -1031,7 +1031,7 @@ void CBattleInterface::stackMoved(int number, int destHex, bool endMoving, int d
int steps = creAnims[number]->framesInGroup(0)*getAnimSpeedMultiplier()-1;
int hexWbase = 44, hexHbase = 42;
bool twoTiles = LOCPLINT->cb->battleGetCreature(number).isDoubleWide();
CStack * movedStack = LOCPLINT->cb->battleGetStackByID(number);
const CStack * movedStack = LOCPLINT->cb->battleGetStackByID(number);
std::pair<int, int> begPosition = CBattleHex::getXYUnitAnim(curStackPos, movedStack->attackerOwned, movedStack->creature);
std::pair<int, int> endPosition = CBattleHex::getXYUnitAnim(destHex, movedStack->attackerOwned, movedStack->creature);
@ -1451,7 +1451,7 @@ bool CBattleInterface::isTileAttackable(const int & number) const
void CBattleInterface::handleEndOfMove(int stackNumber, int destinationTile)
{
CStack * movedStack = LOCPLINT->cb->battleGetStackByID(stackNumber);
const CStack * movedStack = LOCPLINT->cb->battleGetStackByID(stackNumber);
if(creAnims[stackNumber]->framesInGroup(21)!=0) // some units don't have this animation (ie. halberdier)
{
if (movedStack->creature->sounds.endMoving)
@ -1514,7 +1514,7 @@ void CBattleInterface::hexLclicked(int whichOne)
}
else
{
CStack* dest = LOCPLINT->cb->battleGetStackByPos(whichOne); //creature at destination tile; -1 if there is no one
const CStack* dest = LOCPLINT->cb->battleGetStackByPos(whichOne); //creature at destination tile; -1 if there is no one
if(!dest || !dest->alive()) //no creature at that tile
{
if(std::find(shadedHexes.begin(),shadedHexes.end(),whichOne)!=shadedHexes.end())// and it's in our range
@ -1811,8 +1811,14 @@ void CBattleInterface::spellCast(SpellCast * sc)
case 17: //lightning bolt
displayEffect(1, sc->tile);
displayEffect(spell.mainEffectAnim, sc->tile);
break;
case 35: //dispel
displayEffect(spell.mainEffectAnim, sc->tile);
case 37: //cure
for(std::set<ui32>::const_iterator it = sc->affectedCres.begin(); it != sc->affectedCres.end(); ++it)
{
displayEffect(spell.mainEffectAnim, LOCPLINT->cb->battleGetStackByID(*it)->position);
}
break;
} //switch(sc->id)
//support for resistance
@ -1861,7 +1867,8 @@ void CBattleInterface::castThisSpell(int spellID)
break;
}
}
if(CGI->spellh->spells[spellID].attributes.find("CREATURE_TARGET_2") != std::string::npos) //spell to be cast on a specific creature but massive on expert
if(CGI->spellh->spells[spellID].attributes.find("CREATURE_TARGET_1") != std::string::npos ||
CGI->spellh->spells[spellID].attributes.find("CREATURE_TARGET_2") != std::string::npos) //spell to be cast on a specific creature but massive on expert
{
if(castingHero && castingHero->getSpellSecLevel(spellID) < 3)
{
@ -2030,7 +2037,7 @@ void CBattleInterface::attackingShowHelper()
{
attackingInfo->reversing = true;
CStack* aStackp = LOCPLINT->cb->battleGetStackByID(attackingInfo->ID); //attacking stack
const CStack* aStackp = LOCPLINT->cb->battleGetStackByID(attackingInfo->ID); //attacking stack
if(aStackp == NULL)
return;
CStack aStack = *aStackp;

View File

@ -1180,7 +1180,7 @@ void CPlayerInterface::actionStarted(const BattleAction* action)
battleInt->deactivate();
CStack *stack = cb->battleGetStackByID(action->stackNumber);
const CStack *stack = cb->battleGetStackByID(action->stackNumber);
char txt[400];
if(action->actionType == 1)
@ -1252,7 +1252,7 @@ BattleAction CPlayerInterface::activeStack(int stackID) //called when it's turn
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
CStack *stack = cb->battleGetStackByID(stackID);
const CStack *stack = cb->battleGetStackByID(stackID);
if(vstd::contains(stack->state,MOVED)) //this stack has moved and makes second action -> high morale
{
std::string hlp = CGI->generaltexth->allTexts[33];
@ -1331,7 +1331,7 @@ void CPlayerInterface::battleAttack(BattleAttack *ba)
assert(curAction);
if(ba->lucky()) //lucky hit
{
CStack *stack = cb->battleGetStackByID(ba->stackAttacking);
const CStack *stack = cb->battleGetStackByID(ba->stackAttacking);
std::string hlp = CGI->generaltexth->allTexts[45];
boost::algorithm::replace_first(hlp,"%s",(stack->amount != 1) ? stack->creature->namePl.c_str() : stack->creature->nameSing.c_str());
battleInt->console->addText(hlp);
@ -1346,7 +1346,7 @@ void CPlayerInterface::battleAttack(BattleAttack *ba)
}
else
{
CStack * attacker = cb->battleGetStackByID(ba->stackAttacking);
const CStack * attacker = cb->battleGetStackByID(ba->stackAttacking);
int shift = 0;
if(ba->counter() && BattleInfo::mutualPosition(curAction->destinationTile, attacker->position) < 0)
{

View File

@ -37,7 +37,7 @@
34 1 -1 0 0 0 X
35 0 41 0 0 0 X
36 1 -1 0 0 0 0
37 1 -1 0 0 0 0
37 1 39 0 0 0 0
38 1 -1 0 0 0 0
39 1 -1 0 0 0 0
40 1 -1 0 0 0 0

View File

@ -2098,7 +2098,8 @@ std::set<CStack*> BattleInfo::getAttackedCreatures(const CSpell * s, const CGHer
}
}
}
else if(VLC->spellh->spells[s->id].attributes.find("CREATURE_TARGET_2") != std::string::npos) //spell to be cast on a specific creature but massive on expert
else if(VLC->spellh->spells[s->id].attributes.find("CREATURE_TARGET_1") != std::string::npos
|| VLC->spellh->spells[s->id].attributes.find("CREATURE_TARGET_2") != std::string::npos) //spell to be cast on a specific creature but massive on expert
{
if(caster->getSpellSchoolLevel(s) < 3) /*not expert */
{

View File

@ -904,9 +904,10 @@ struct SpellCast : public CPackForClient//3009
ui8 skill;
ui16 tile; //destination tile (may not be set in some global/mass spells
std::vector<ui32> resisted; //ids of creatures that resisted this spell
std::set<ui32> affectedCres; //ids of creatures affected by this spell, generally used if spell does not set any effect (like dispel or cure)
template <typename Handler> void serialize(Handler &h, const int version)
{
h & side & id & skill & tile & resisted;
h & side & id & skill & tile & resisted & affectedCres;
}
};
@ -950,6 +951,31 @@ struct BattleResultsApplied : public CPackForClient //3012
}
};
struct StacksHealedOrResurrected : public CPackForClient //3013
{
StacksHealedOrResurrected(){type = 3013;}
DLL_EXPORT void applyGs(CGameState *gs);
struct HealInfo
{
ui32 stackID;
ui32 healForFirstStack;
ui32 resurrectedCres;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & stackID & healForFirstStack & resurrectedCres;
}
};
std::vector<HealInfo> healedStacks;
template <typename Handler> void serialize(Handler &h, const int version)
{
h & healedStacks;
}
};
struct ShowInInfobox : public CPackForClient //107
{
ShowInInfobox(){type = 107;};

View File

@ -696,18 +696,21 @@ DLL_EXPORT void SpellCast::applyGs( CGameState *gs )
if(gs->curB && id == 35) //dispel
{
CStack *s = gs->curB->getStackT(tile);
if(s && !vstd::contains(resisted, s->ID)) //if stack exists and it didn't resist
for(std::set<ui32>::const_iterator it = affectedCres.begin(); it != affectedCres.end(); ++it)
{
s->effects.clear(); //removing all effects
//removing all features from spells
std::vector<StackFeature> tmpFeatures = s->features;
s->features.clear();
for(int i=0; i < tmpFeatures.size(); i++)
CStack *s = gs->curB->getStack(*it);
if(s && !vstd::contains(resisted, s->ID)) //if stack exists and it didn't resist
{
if(tmpFeatures[i].source != StackFeature::SPELL_EFFECT)
s->effects.clear(); //removing all effects
//removing all features from spells
std::vector<StackFeature> tmpFeatures = s->features;
s->features.clear();
for(int i=0; i < tmpFeatures.size(); i++)
{
s->features.push_back(tmpFeatures[i]);
if(tmpFeatures[i].source != StackFeature::SPELL_EFFECT)
{
s->features.push_back(tmpFeatures[i]);
}
}
}
}
@ -797,6 +800,12 @@ static std::vector<StackFeature> stackEffectToFeature(const CStack::StackEffect
break;
}
//setting positiveness
for(int g=0; g<sf.size(); ++g)
{
sf[g].positiveness = VLC->spellh->spells[sse.id].positiveness;
}
return sf;
}
@ -867,6 +876,37 @@ DLL_EXPORT void StacksInjured::applyGs( CGameState *gs )
stackAttacked.applyGs(gs);
}
DLL_EXPORT void StacksHealedOrResurrected::applyGs( CGameState *gs )
{
for(int g=0; g<healedStacks.size(); ++g)
{
CStack * changedStack = gs->curB->stacks[healedStacks[g].stackID];
changedStack->firstHPleft += healedStacks[g].healForFirstStack;
changedStack->amount += healedStacks[g].resurrectedCres;
//removal of negative effects
{
for(int h=0; h<changedStack->effects.size(); ++h)
{
if(VLC->spellh->spells[changedStack->effects[h].id].positiveness < 0)
{
changedStack->effects.erase(changedStack->effects.begin() + h);
}
}
//removing all features from negative spells
std::vector<StackFeature> tmpFeatures = changedStack->features;
changedStack->features.clear();
for(int i=0; i < tmpFeatures.size(); i++)
{
if(tmpFeatures[i].source != StackFeature::SPELL_EFFECT || tmpFeatures[i].positiveness >= 0)
{
changedStack->features.push_back(tmpFeatures[i]);
}
}
}
}
}
DLL_EXPORT void YourTurn::applyGs( CGameState *gs )
{
gs->currentPlayer = player;

View File

@ -97,6 +97,7 @@ void registerTypes2(Serializer &s)
s.template registerType<SetStackEffect>();
s.template registerType<StacksInjured>();
s.template registerType<BattleResultsApplied>();
s.template registerType<StacksHealedOrResurrected>();
s.template registerType<ShowInInfobox>();
s.template registerType<OpenWindow>();
s.template registerType<NewObject>();

View File

@ -109,6 +109,7 @@ struct StackFeature
ui8 type;//ECombatFeatures
ui8 duration;//EDuration
ui8 source;//ESource
si8 positiveness; //+1 - positive, 0 - neutral, -1 - negative; used mostly for spell features
ui16 turnsRemain; //if duration is N_TURNS it describes how long the effect will last
si16 subtype; //subtype of bonus/feature
si32 value;
@ -123,7 +124,7 @@ struct StackFeature
template <typename Handler> void serialize(Handler &h, const int version)
{
h & type & duration & source & turnsRemain & subtype & value & additionalInfo;
h & type & duration & source & positiveness & turnsRemain & subtype & value & additionalInfo;
}
};

View File

@ -2722,6 +2722,10 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
//calculating affected creatures for all spells
std::set<CStack*> attackedCres = gs->curB->getAttackedCreatures(s, h, ba.destinationTile);
for(std::set<CStack*>::const_iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
{
sc.affectedCres.insert((*it)->ID);
}
//checking if creatures resist
sc.resisted = calculateResistedStacks(s, h, secondHero, attackedCres);
@ -2752,7 +2756,7 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
BattleStackAttacked bsa;
bsa.flags |= 2;
bsa.effect = VLC->spellh->spells[ba.additionalInfo].mainEffectAnim;
bsa.damageAmount = calculateSpellDmg(&VLC->spellh->spells[ba.additionalInfo], h, *it);
bsa.damageAmount = calculateSpellDmg(s, h, *it);
bsa.stackAttacked = (*it)->ID;
prepareAttacked(bsa,*it);
si.stacks.insert(bsa);
@ -2814,6 +2818,24 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
sendAndApply(&sse);
break;
}
case 37: //cure
{
StacksHealedOrResurrected shr;
for(std::set<CStack*>::iterator it = attackedCres.begin(); it != attackedCres.end(); ++it)
{
if(vstd::contains(sc.resisted, (*it)->ID)) //this creature resisted the spell
continue;
StacksHealedOrResurrected::HealInfo hi;
hi.stackID = (*it)->ID;
int healedHP = h->getPrimSkillLevel(2) * 5 + s->powers[h->getSpellSchoolLevel(s)];
hi.healForFirstStack = std::min<ui32>(healedHP, (*it)->MaxHealth() - (*it)->firstHPleft);
hi.resurrectedCres = 0;
shr.healedStacks.push_back(hi);
}
if(!shr.healedStacks.empty())
sendAndApply(&shr);
break;
}
}
sendAndApply(&EndAction());
return true;