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:
parent
adbc142ff0
commit
87e66fff31
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
16
lib/map.cpp
16
lib/map.cpp
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user