1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-03 13:01:33 +02:00

* Changed artifact handling so bonuses from constituent artifacts in combinational ones are added implicitly.

* Discovered bug when attacking guarded visitables. Needs to wait before battle is over.
This commit is contained in:
OnionKnight 2010-05-09 19:10:59 +00:00
parent adbc142ff0
commit 87e66fff31
9 changed files with 105 additions and 73 deletions

View File

@ -312,15 +312,16 @@ void SetHeroArtifacts::applyCl( CClient *cl )
if(!player)
return;
h->recreateArtBonuses();
player->heroArtifactSetChanged(h);
BOOST_FOREACH(Bonus *bonus, gained)
BOOST_FOREACH(Bonus bonus, gained)
{
player->heroBonusChanged(h,*bonus,true);
player->heroBonusChanged(h,bonus,true);
}
BOOST_FOREACH(Bonus *bonus, lost)
BOOST_FOREACH(Bonus bonus, lost)
{
player->heroBonusChanged(h,*bonus,false);
player->heroBonusChanged(h,bonus,false);
}
}

View File

@ -3,6 +3,8 @@
#include "CArtHandler.h"
#include "CLodHandler.h"
#include "CGeneralTextHandler.h"
#include <boost/bind.hpp>
#include <boost/foreach.hpp>
#include <boost/assign/std/vector.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/lexical_cast.hpp>
@ -123,6 +125,44 @@ bool CArtifact::canBeAssembledTo (const std::map<ui16, ui32> &artifWorn, ui32 ar
return true;
}
/**
* Adds all the bonuses of this artifact, including possible constituents, to
* a bonus list.
*/
void CArtifact::addBonusesTo (BonusList *otherBonuses) const
{
for(std::list<Bonus>::const_iterator i = bonuses.begin(); i != bonuses.end(); i++)
otherBonuses->push_back(*i);
if (constituents != NULL) {
BOOST_FOREACH(ui32 artifactID, *constituents) {
VLC->arth->artifacts[artifactID].addBonusesTo(otherBonuses);
}
}
}
/**
* Removes all the bonuses of this artifact, including possible constituents, from
* a bonus list.
*/
void CArtifact::removeBonusesFrom (BonusList *otherBonuses) const
{
if (constituents != NULL) {
BOOST_FOREACH(ui32 artifactID, *constituents) {
VLC->arth->artifacts[artifactID].removeBonusesFrom(otherBonuses);
}
}
while (1) {
std::list<Bonus>::const_iterator it = std::find_if(otherBonuses->begin(), otherBonuses->end(),boost::bind(Bonus::IsFrom,_1,Bonus::ARTIFACT,id));
if (it != otherBonuses->end())
otherBonuses->erase(it);
else
break;
}
}
CArtHandler::CArtHandler()
{
VLC->arth = this;
@ -521,23 +561,17 @@ void CArtHandler::addBonuses()
ART_PRIM_SKILL(128, 3, +6);
//Angelic Alliance
ART_ALL_PRIM_SKILLS(129, +21);
giveArtBonus(129, Bonus::NONEVIL_ALIGNMENT_MIX, 0);
giveArtBonus(129, Bonus::OPENING_BATTLE_SPELL, 10, 29); // Prayer
//Cloak of the Undead King
giveArtBonus(130, Bonus::SECONDARY_SKILL_PREMY, +30, 12);
giveArtBonus(130, Bonus::SECONDARY_SKILL_PREMY, +30, 12);
giveArtBonus(130, Bonus::IMPROVED_NECROMANCY, 0);
//Elixir of Life
giveArtBonus(131, Bonus::STACK_HEALTH, +4);
giveArtBonus(131, Bonus::STACK_HEALTH, +25, -1, Bonus::PERCENT_TO_BASE);
giveArtBonus(131, Bonus::HP_REGENERATION, +50);
//Armor of the Damned
ART_ATTACK_AND_DEFENSE(132, +3);
ART_POWER_AND_KNOWLEDGE(132, +2);
giveArtBonus(132, Bonus::OPENING_BATTLE_SPELL, 50, 54); // Slow
giveArtBonus(132, Bonus::OPENING_BATTLE_SPELL, 50, 47); // Disrupting Ray
giveArtBonus(132, Bonus::OPENING_BATTLE_SPELL, 50, 45); // Weakness
@ -547,26 +581,16 @@ void CArtHandler::addBonuses()
giveArtBonus(133, Bonus::CREATURE_GROWTH_PERCENT, 50);
//Power of the Dragon Father
ART_ALL_PRIM_SKILLS(134, +16);
giveArtBonus(134, Bonus::MORALE, +1);
giveArtBonus(134, Bonus::LUCK, +1);
giveArtBonus(134, Bonus::LEVEL_SPELL_IMMUNITY, 4);
//Titan's Thunder
// should also add a permanent spell book, somehow.
ART_ATTACK_AND_DEFENSE(135, +9);
ART_POWER_AND_KNOWLEDGE(135, +8);
// FIXME: should also add a permanent spell book, somehow.
giveArtBonus(135, Bonus::SPELL, 3, 57);
//Admiral's Hat
giveArtBonus(136, Bonus::SEA_MOVEMENT, +1500);
giveArtBonus(136, Bonus::WHIRLPOOL_PROTECTION, 0);
giveArtBonus(136, Bonus::SPELL, 3, 0);
giveArtBonus(136, Bonus::SPELL, 3, 1);
giveArtBonus(136, Bonus::FREE_SHIP_BOARDING, 0);
//Bow of the Sharpshooter
giveArtBonus(137, Bonus::SECONDARY_SKILL_PREMY, +30, 1);
giveArtBonus(137, Bonus::NO_SHOTING_PENALTY, 0);
giveArtBonus(137, Bonus::FREE_SHOOTING, 0);
@ -574,13 +598,13 @@ void CArtHandler::addBonuses()
giveArtBonus(138, Bonus::FULL_MANA_REGENERATION, 0);
//Ring of the Magi
giveArtBonus(139, Bonus::SPELL_DURATION, +56);
giveArtBonus(139, Bonus::SPELL_DURATION, +50);
//Cornucopia
giveArtBonus(140, Bonus::GENERATE_RESOURCE, +5, 1);
giveArtBonus(140, Bonus::GENERATE_RESOURCE, +5, 3);
giveArtBonus(140, Bonus::GENERATE_RESOURCE, +5, 4);
giveArtBonus(140, Bonus::GENERATE_RESOURCE, +5, 5);
giveArtBonus(140, Bonus::GENERATE_RESOURCE, +4, 1);
giveArtBonus(140, Bonus::GENERATE_RESOURCE, +4, 3);
giveArtBonus(140, Bonus::GENERATE_RESOURCE, +4, 4);
giveArtBonus(140, Bonus::GENERATE_RESOURCE, +4, 5);
}
void CArtHandler::clear()
@ -596,10 +620,12 @@ void CArtHandler::clear()
* Locally equips an artifact to a hero's worn slots. Unequips an already present artifact.
* Does not test if the operation is legal.
* @param artifWorn A hero's set of worn artifacts.
* @param bonuses Optional list of bonuses to update.
*/
void CArtHandler::equipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID, ui32 artifactID)
void CArtHandler::equipArtifact
(std::map<ui16, ui32> &artifWorn, ui16 slotID, ui32 artifactID, BonusList *bonuses)
{
unequipArtifact(artifWorn, slotID);
unequipArtifact(artifWorn, slotID, bonuses);
const CArtifact &artifact = artifacts[artifactID];
@ -625,14 +651,19 @@ void CArtHandler::equipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID, u
}
}
}
if (bonuses != NULL)
artifact.addBonusesTo(bonuses);
}
/**
* Locally unequips an artifact from a hero's worn slots.
* Does not test if the operation is legal.
* @param artifWorn A hero's set of worn artifacts.
* @param bonuses Optional list of bonuses to update.
*/
void CArtHandler::unequipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID)
void CArtHandler::unequipArtifact
(std::map<ui16, ui32> &artifWorn, ui16 slotID, BonusList *bonuses)
{
if (!vstd::contains(artifWorn, slotID))
return;
@ -661,4 +692,7 @@ void CArtHandler::unequipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID)
}
}
}
if (bonuses != NULL)
artifact.removeBonusesFrom(bonuses);
}

View File

@ -28,6 +28,8 @@ public:
bool isBig () const;
bool fitsAt (const std::map<ui16, ui32> &artifWorn, ui16 slot) const;
bool canBeAssembledTo (const std::map<ui16, ui32> &artifWorn, ui32 artifactID) const;
void addBonusesTo (BonusList *otherBonuses) const;
void removeBonusesFrom (BonusList *otherBonuses) const;
ui32 price;
std::vector<ui16> possibleSlots; //ids of slots where artifact can be placed
@ -56,8 +58,8 @@ public:
void addBonuses();
void clear();
bool isBigArtifact (ui32 artID) {return bigArtifacts.find(artID) != bigArtifacts.end();}
void equipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID, ui32 artifactID);
void unequipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID);
void equipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID, ui32 artifactID, BonusList *bonuses = NULL);
void unequipArtifact (std::map<ui16, ui32> &artifWorn, ui16 slotID, BonusList *bonuses = NULL);
static int convertMachineID(int id, bool creToArt);
CArtHandler();
~CArtHandler();

View File

@ -722,9 +722,9 @@ void CGHeroInstance::initHero()
if(!vstd::contains(artifWorn, 16) && type->startingSpell >= 0) //no catapult means we haven't read pre-existant set
{
VLC->arth->equipArtifact(artifWorn, 17, 0); //give spellbook
VLC->arth->equipArtifact(artifWorn, 17, 0, &bonuses); //give spellbook
}
VLC->arth->equipArtifact(artifWorn, 16, 3); //everyone has a catapult
VLC->arth->equipArtifact(artifWorn, 16, 3, &bonuses); //everyone has a catapult
if(portrait < 0 || portrait == 255)
portrait = subID;
@ -775,10 +775,14 @@ void CGHeroInstance::initHero()
switch (creID)
{
case 145: //catapult
VLC->arth->equipArtifact(artifWorn, 16, 3);
VLC->arth->equipArtifact(artifWorn, 16, 3, &bonuses);
break;
default:
VLC->arth->equipArtifact(artifWorn, 9+CArtHandler::convertMachineID(creID,true), CArtHandler::convertMachineID(creID,true));
VLC->arth->equipArtifact(
artifWorn,
9+CArtHandler::convertMachineID(creID,true),
CArtHandler::convertMachineID(creID,true),
&bonuses);
break;
}
}
@ -1057,7 +1061,7 @@ void CGHeroInstance::giveArtifact (ui32 aid)
if (artifact.isBig()) {
for (std::vector<ui16>::const_iterator it = artifact.possibleSlots.begin(); it != artifact.possibleSlots.end(); ++it) {
if (!vstd::contains(artifWorn, *it)) {
VLC->arth->equipArtifact(artifWorn, *it, aid);
VLC->arth->equipArtifact(artifWorn, *it, aid, &bonuses);
break;
}
}
@ -1073,8 +1077,7 @@ void CGHeroInstance::recreateArtBonuses()
for (std::map<ui16,ui32>::iterator ari = artifWorn.begin(); ari != artifWorn.end(); ari++)
{
CArtifact &art = VLC->arth->artifacts[ari->second];
for(std::list<Bonus>::iterator i = art.bonuses.begin(); i != art.bonuses.end(); i++)
bonuses.push_back(*i);
art.addBonusesTo(&bonuses);
}
}

View File

@ -1464,8 +1464,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
std::vector<ui16>::iterator slot = vstd::findFirstNot(hero->artifWorn,toGive->possibleSlots);
if(slot!=toGive->possibleSlots.end())
{
VLC->arth->equipArtifact(hero->artifWorn, *slot, toGive->id);
hero->recreateArtBonuses();
VLC->arth->equipArtifact(hero->artifWorn, *slot, toGive->id, &hero->bonuses);
}
else
hero->giveArtifact(toGive->id);

View File

@ -575,7 +575,7 @@ struct SetHeroArtifacts : public CPackForClient //509
h & hid & artifacts & artifWorn;
}
std::vector<Bonus*> gained, lost; //used locally as hlp when applying
BonusList gained, lost; //used locally as hlp when applying
};
struct HeroRecruited : public CPackForClient //515

View File

@ -462,11 +462,8 @@ DLL_EXPORT void SetHeroArtifacts::applyGs( CGameState *gs )
continue;
CArtifact &art = VLC->arth->artifacts[id];
for(std::list<Bonus>::iterator i = art.bonuses.begin(); i != art.bonuses.end(); i++)
{
gained.push_back(&*i);
h->bonuses.push_back(*i);
}
art.addBonusesTo(&h->bonuses);
art.addBonusesTo(&gained);
}
//update hero data
@ -480,19 +477,9 @@ DLL_EXPORT void SetHeroArtifacts::applyGs( CGameState *gs )
if(h->getArtPos(id) >= 0)
continue;
while(1)
{
std::list<Bonus>::iterator hlp = std::find_if(h->bonuses.begin(),h->bonuses.end(),boost::bind(Bonus::IsFrom,_1,Bonus::ARTIFACT,id));
if(hlp != h->bonuses.end())
{
lost.push_back(&*hlp);
h->bonuses.erase(hlp);
}
else
{
break;
}
}
CArtifact &art = VLC->arth->artifacts[id];
art.removeBonusesFrom(&h->bonuses);
art.addBonusesTo(&lost);
}
}

View File

@ -904,27 +904,27 @@ void Mapa::loadHero( CGObjectInstance * &nobj, const unsigned char * bufor, int
{
int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
if(id!=artmask)
VLC->arth->equipArtifact(nhi->artifWorn, pom, id);
VLC->arth->equipArtifact(nhi->artifWorn, pom, id, &nhi->bonuses);
}
//misc5 art //17
if(version>=SoD)
{
int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
if(id!=artmask)
VLC->arth->equipArtifact(nhi->artifWorn, 16, id);
VLC->arth->equipArtifact(nhi->artifWorn, 16, id, &nhi->bonuses);
else
VLC->arth->equipArtifact(nhi->artifWorn, 16, 3); //catapult by default
VLC->arth->equipArtifact(nhi->artifWorn, 16, 3, &nhi->bonuses); //catapult by default
}
//spellbook
int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
if(id!=artmask)
VLC->arth->equipArtifact(nhi->artifWorn, 17, id);
VLC->arth->equipArtifact(nhi->artifWorn, 17, id, &nhi->bonuses);
//19 //???what is that? gap in file or what? - it's probably fifth slot..
if(version>RoE)
{
id = readNormalNr(bufor,i, artidlen); i+=artidlen;
if(id!=artmask)
VLC->arth->equipArtifact(nhi->artifWorn, 18, id);
VLC->arth->equipArtifact(nhi->artifWorn, 18, id, &nhi->bonuses);
}
else
i+=1;
@ -1143,7 +1143,7 @@ void Mapa::readPredefinedHeroes( const unsigned char * bufor, int &i)
{
int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
if(id!=artmask)
VLC->arth->equipArtifact(cgh->artifWorn, pom, id);
VLC->arth->equipArtifact(cgh->artifWorn, pom, id, &cgh->bonuses);
}
//misc5 art //17
if(version>=SoD)
@ -1156,13 +1156,13 @@ void Mapa::readPredefinedHeroes( const unsigned char * bufor, int &i)
//spellbook
int id = readNormalNr(bufor,i, artidlen); i+=artidlen;
if(id!=artmask)
VLC->arth->equipArtifact(cgh->artifWorn, 17, id);
VLC->arth->equipArtifact(cgh->artifWorn, 17, id, &cgh->bonuses);
//19 //???what is that? gap in file or what? - it's probably fifth slot..
if(version>RoE)
{
id = readNormalNr(bufor,i, artidlen); i+=artidlen;
if(id!=artmask)
VLC->arth->equipArtifact(cgh->artifWorn, 18, id);
VLC->arth->equipArtifact(cgh->artifWorn, 18, id, &cgh->bonuses);
}
else
i+=1;

View File

@ -1700,6 +1700,18 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
sendAndApply(&tmh);
tlog5 << "Moved to " <<tmh.end<<std::endl;
// If a creature guards the tile, block visit.
if (gs->map->isInTheMap(guardPos)) {
const TerrainTile &guardTile = gs->map->terrain[guardPos.x][guardPos.y][guardPos.z];
objectVisited(guardTile.visitableObjects.back(), h);
// TODO: Need to wait until battle is over.
// Do not visit anything else if hero died.
if (h->getArmy().stacksCount() == 0)
return true;
}
//call objects if they are visited
if(t.visitableObjects.size())
@ -1715,12 +1727,6 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
// objectVisited(obj, h);
// }
// If a creature guards the tile, block visit.
if (gs->map->isInTheMap(guardPos)) {
const TerrainTile &guardTile = gs->map->terrain[guardPos.x][guardPos.y][guardPos.z];
objectVisited(guardTile.visitableObjects.back(), h);
}
tlog5 << "Movement end!\n";
return true;
}