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

* resting in town with mage guild will replenih all the mana points

* battle will end when one side has only war machines
* fixed crasbug occurring on revisiting objects (by pressing space)
* started writing support for artifacts
This commit is contained in:
Michał W. Urbańczyk 2009-04-03 22:34:31 +00:00
parent f794644c2a
commit 1983aee1b2
16 changed files with 447 additions and 153 deletions

View File

@ -101,6 +101,7 @@ public:
/*****************************/
class CAdvMapInt : public CMainInterface, public KeyInterested //adventure map interface
{
void hide(); //deactivates advmap interface
public:
CAdvMapInt(int Player);
~CAdvMapInt();
@ -161,7 +162,6 @@ public:
void deactivate();
void show(SDL_Surface * to=NULL); //shows and activates adv. map interface
void hide(); //deactivates advmap interface
void update(); //redraws terrain
void select(const CArmedInstance *sel);

View File

@ -384,7 +384,7 @@ bool CCallback::swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGH
if(player!=hero1->tempOwner || player!=hero2->tempOwner)
return false;
ExchangeArtifacts ea(hero1->id, pos1, hero2->id, pos2);
ExchangeArtifacts ea(hero1->id, hero2->id, pos1, pos2);
*cl->serv << &ea;
return true;
}

View File

@ -57,8 +57,8 @@ CHeroWindow::CHeroWindow(int playerColor):
gar2button = new CHighlightableButton(0, 0, map_list_of(0,CGI->generaltexth->heroscrn[26])(3,CGI->generaltexth->heroscrn[25]), CGI->generaltexth->heroscrn[31], false, "hsbtns8.def", NULL, pos.x+604, pos.y+491, SDLK_b);
gar4button = new AdventureMapButton(CGI->generaltexth->allTexts[256], CGI->generaltexth->heroscrn[32], boost::function<void()>(), pos.x+604, pos.y+527, "hsbtns9.def", false, NULL, false);
boost::algorithm::replace_first(gar4button->hoverTexts[0],"%s",CGI->generaltexth->allTexts[43]);
leftArtRoll = new AdventureMapButton(std::string(), std::string(), boost::bind(&CHeroWindow::leftArtRoller,this), pos.x+379, pos.y+364, "hsbtns3.def", SDLK_LEFT);
rightArtRoll = new AdventureMapButton(std::string(), std::string(), boost::bind(&CHeroWindow::rightArtRoller,this), pos.x+632, pos.y+364, "hsbtns5.def", SDLK_RIGHT);
leftArtRoll = new AdventureMapButton(std::string(), std::string(), boost::bind(&CHeroWindow::scrollBackpack,this,-1), pos.x+379, pos.y+364, "hsbtns3.def", SDLK_LEFT);
rightArtRoll = new AdventureMapButton(std::string(), std::string(), boost::bind(&CHeroWindow::scrollBackpack,this,+1), pos.x+632, pos.y+364, "hsbtns5.def", SDLK_RIGHT);
for(int g=0; g<8; ++g)
@ -268,6 +268,7 @@ void CHeroWindow::setHero(const CGHeroInstance *Hero)
backpack.clear();
std::vector<SDL_Rect> slotPos;
backpackPos = 0;
slotPos += genRect(44,44,pos.x+509,pos.y+30), genRect(44,44,pos.x+567,pos.y+240), genRect(44,44,pos.x+509,pos.y+80),
genRect(44,44,pos.x+383,pos.y+68), genRect(44,44,pos.x+564,pos.y+183), genRect(44,44,pos.x+509,pos.y+130),
@ -501,56 +502,26 @@ void CHeroWindow::dismissCurrent()
void CHeroWindow::questlog()
{
}
void CHeroWindow::leftArtRoller()
void CHeroWindow::scrollBackpack(int dir)
{
if(curHero->artifacts.size()>5) //if it is <=5, we have nothing to scroll
backpackPos += dir + curHero->artifacts.size();
backpackPos %= curHero->artifacts.size();
for(size_t s=0; s<5 && s<curHero->artifacts.size(); ++s) //set new data
{
backpackPos+=curHero->artifacts.size()-1; //set new offset
CArtPlace *cur = backpack[s];
cur->slotID = 19+((s+backpackPos)%curHero->artifacts.size());
cur->ourArt = curHero->getArt(cur->slotID);
for(size_t s=0; s<5 && s<curHero->artifacts.size(); ++s) //set new data
{
backpack[s]->ourArt = &CGI->arth->artifacts[curHero->artifacts[(s+backpackPos) % curHero->artifacts.size() ]];
if(backpack[s]->ourArt)
backpack[s]->text = backpack[s]->ourArt->Description();
else
backpack[s]->text = std::string();
}
if(cur->ourArt)
cur->text = cur->ourArt->Description();
else
cur->text = std::string();
}
}
void CHeroWindow::rightArtRoller()
{
if(curHero->artifacts.size()>5) //if it is <=5, we have nothing to scroll
{
backpackPos+=1; //set new offset
for(size_t s=0; s<5 && s<curHero->artifacts.size(); ++s) //set new data
{
backpack[s]->ourArt = &CGI->arth->artifacts[curHero->artifacts[(s+backpackPos) % curHero->artifacts.size() ] ];
if(backpack[s]->ourArt)
backpack[s]->text = backpack[s]->ourArt->Description();
else
backpack[s]->text = std::string();
}
}
}
void CHeroWindow::switchHero()
{
//int y;
//SDL_GetMouseState(NULL, &y);
//for(int g=0; g<heroListMi.size(); ++g)
//{
// if(y>=94+54*g)
// {
// //quit();
// setHero(LOCPLINT->cb->getHeroInfo(player, g, false));
// //LOCPLINT->openHeroWindow(curHero);
// redrawCurBack();
// }
//}
}
void CHeroWindow::redrawCurBack()
{
if(curBack)
@ -754,7 +725,10 @@ void CArtPlace::clickLeft(boost::logic::tribool down)
//chceck if swap is possible
if(this->fitsHere(ourWindow->activeArtPlace->ourArt) && ourWindow->activeArtPlace->fitsHere(this->ourArt))
{
LOCPLINT->cb->swapArtifacts(ourWindow->curHero,slotID,ourWindow->curHero,ourWindow->activeArtPlace->slotID);
int destSlot = slotID,
srcSlot = ourWindow->activeArtPlace->slotID;
LOCPLINT->cb->swapArtifacts(ourWindow->curHero,destSlot,ourWindow->curHero,srcSlot);
const CArtifact * pmh = ourArt;
ourArt = ourWindow->activeArtPlace->ourArt;
@ -786,9 +760,7 @@ void CArtPlace::clickLeft(boost::logic::tribool down)
}
if(backID>=0) //put to backpack
{
/*ourWindow->activeArtPlace->ourArt = NULL;
ourWindow->activeArtPlace->clicked = false;
ourWindow->activeArtPlace = NULL;*/
LOCPLINT->cb->swapArtifacts(ourWindow->curHero,ourWindow->activeArtPlace->slotID,ourWindow->curHero,ourWindow->curHero->artifacts.size()+19);
}
}
}

View File

@ -123,9 +123,8 @@ public:
void redrawCurBack(); //redraws curBAck from scratch
void quit(); //stops displaying hero window
void dismissCurrent(); //dissmissed currently displayed hero (curHero)
void questlog(); //show quest log in hero window
void leftArtRoller(); //scrolls artifacts in bag left
void rightArtRoller(); //scrolls artifacts in bag right
void questlog(); //show quest log in hero window
void scrollBackpack(int dir); //dir==-1 => to left; dir==-2 => to right
void switchHero(); //changes displayed hero
//friends

View File

@ -1214,7 +1214,7 @@ void CPlayerInterface::yourTurn()
pim->unlock();
SDL_framerateDelay(mainFPSmng);
}
adventureInt->hide();
adventureInt->deactivate();
cb->endTurn();
}
@ -1785,7 +1785,7 @@ void CPlayerInterface::heroCreated(const CGHeroInstance * hero)
}
void CPlayerInterface::openTownWindow(const CGTownInstance * town)
{
adventureInt->hide();
adventureInt->deactivate();
//timeHandler t;
//t.getDif();
castleInt = new CCastleInterface(town,true);
@ -2035,7 +2035,7 @@ void CPlayerInterface::showSelDialog(const std::string &text, const std::vector<
{
boost::unique_lock<boost::recursive_mutex> un(*pim);
LOCPLINT->showingDialog->setn(true);
adventureInt->hide(); //dezaktywacja starego interfejsu
adventureInt->deactivate(); //dezaktywacja starego interfejsu
std::vector<CSelectableComponent*> intComps;
for(int i=0;i<components.size();i++)
intComps.push_back(new CSelectableComponent(*components[i])); //will be deleted by CSelWindow::close

View File

@ -211,9 +211,21 @@ void SetHeroesInTown::applyCl( CClient *cl )
void SetHeroArtifacts::applyCl( CClient *cl )
{
CGHeroInstance *t = GS(cl)->getHero(hid);
if(vstd::contains(cl->playerint,t->tempOwner))
cl->playerint[t->tempOwner]->heroArtifactSetChanged(t);
CGHeroInstance *h = GS(cl)->getHero(hid);
CGameInterface *player = (vstd::contains(cl->playerint,h->tempOwner) ? cl->playerint[h->tempOwner] : NULL);
if(!player)
return;
player->heroArtifactSetChanged(h);
BOOST_FOREACH(HeroBonus *bonus, gained)
{
player->heroBonusChanged(h,*bonus,true);
}
BOOST_FOREACH(HeroBonus *bonus, lost)
{
player->heroBonusChanged(h,*bonus,false);
}
}
void HeroRecruited::applyCl( CClient *cl )

View File

@ -19,7 +19,7 @@ typedef boost::int8_t si8; //signed int 8 bits (1 byte)
#define THC
#endif
#define NAME_VER ("VCMI 0.7d2")
#define NAME_VER ("VCMI 0.71b")
#define CONSOLE_LOGGING_LEVEL 5
#define FILE_LOGGING_LEVEL 6

View File

@ -8,6 +8,22 @@
#include "../lib/VCMI_Lib.h"
extern CLodHandler *bitmaph;
using namespace boost::assign;
const std::string & CArtifact::Name() const
{
if(name.size())
return name;
else
return VLC->generaltexth->artifNames[id];
}
const std::string & CArtifact::Description() const
{
if(description.size())
return description;
else
return VLC->generaltexth->artifDescriptions[id];
}
CArtHandler::CArtHandler()
{
VLC->arth = this;
@ -46,6 +62,7 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
artifacts.push_back(nart);
}
sortArts();
addBonuses();
}
int CArtHandler::convertMachineID(int id, bool creToArt )
@ -101,18 +118,187 @@ void CArtHandler::sortArts()
}
}
const std::string & CArtifact::Name() const
void CArtHandler::giveArtBonus( int aid, HeroBonus::BonusType type, int val, int subtype )
{
if(name.size())
return name;
else
return VLC->generaltexth->artifNames[id];
artifacts[aid].bonuses.push_back(HeroBonus(HeroBonus::PERMANENT,type,HeroBonus::ARTIFACT,val,aid,subtype));
}
const std::string & CArtifact::Description() const
void CArtHandler::addBonuses()
{
if(description.size())
return description;
else
return VLC->generaltexth->artifDescriptions[id];
}
#define ART_PRIM_SKILL(ID, whichSkill, val) giveArtBonus(ID,HeroBonus::PRIMARY_SKILL,val,whichSkill)
#define ART_MORALE(ID, val) giveArtBonus(ID,HeroBonus::MORALE,val)
#define ART_LUCK(ID, val) giveArtBonus(ID,HeroBonus::LUCK,val)
#define ART_MORALE_AND_LUCK(ID, val) giveArtBonus(ID,HeroBonus::MORALE_AND_LUCK,val)
#define ART_ALL_PRIM_SKILLS(ID, val) ART_PRIM_SKILL(ID,0,val); ART_PRIM_SKILL(ID,1,val); ART_PRIM_SKILL(ID,2,val); ART_PRIM_SKILL(ID,3,val)
#define ART_ATTACK_AND_DEFENSE(ID, val) ART_PRIM_SKILL(ID,0,val); ART_PRIM_SKILL(ID,1,val)
#define ART_POWER_AND_KNOWLEDGE(ID, val) ART_PRIM_SKILL(ID,2,val); ART_PRIM_SKILL(ID,3,val)
//Attack bonus artifacts (Weapons)
ART_PRIM_SKILL(7,0,+2); //Centaur Axe
ART_PRIM_SKILL(8,0,+3);
ART_PRIM_SKILL(9,0,+4);
ART_PRIM_SKILL(10,0,+5);
ART_PRIM_SKILL(11,0,+6);
ART_PRIM_SKILL(12,0,+12);
ART_PRIM_SKILL(12,1,-3);
//Defense bonus artifacts (Shields)
ART_PRIM_SKILL(13,1,+2); //Shield of the Dwarven Lords
ART_PRIM_SKILL(14,1,+3);
ART_PRIM_SKILL(15,1,+4);
ART_PRIM_SKILL(16,1,+5);
ART_PRIM_SKILL(17,1,+6);
ART_PRIM_SKILL(18,1,+12);
ART_PRIM_SKILL(18,0,-3);
//Knowledge bonus artifacts (Helmets)
ART_PRIM_SKILL(19,3,+1); //Helm of the Alabaster Unicorn
ART_PRIM_SKILL(20,3,+2);
ART_PRIM_SKILL(21,3,+3);
ART_PRIM_SKILL(22,3,+4);
ART_PRIM_SKILL(23,3,+5);
ART_PRIM_SKILL(24,3,+10);
ART_PRIM_SKILL(24,2,-2);
//Spell power bonus artifacts (Armours)
ART_PRIM_SKILL(25,2,+1); //Breastplate of Petrified Wood
ART_PRIM_SKILL(26,2,+2);
ART_PRIM_SKILL(27,2,+3);
ART_PRIM_SKILL(28,2,+4);
ART_PRIM_SKILL(29,2,+5);
ART_PRIM_SKILL(30,2,+10);
ART_PRIM_SKILL(30,3,-2);
//All primary skills (various)
ART_ALL_PRIM_SKILLS(31,+1); //Armor of Wonder
ART_ALL_PRIM_SKILLS(32,+2);
ART_ALL_PRIM_SKILLS(33,+3);
ART_ALL_PRIM_SKILLS(34,+4);
ART_ALL_PRIM_SKILLS(35,+5);
ART_ALL_PRIM_SKILLS(36,+6); //Helm of Heavenly Enlightenment
//Attack and Defense (various)
ART_ATTACK_AND_DEFENSE(37,+1); //Quiet Eye of the Dragon
ART_ATTACK_AND_DEFENSE(38,+2);
ART_ATTACK_AND_DEFENSE(39,+3);
ART_ATTACK_AND_DEFENSE(40,+4);
//Spell power and Knowledge (various)
ART_POWER_AND_KNOWLEDGE(41,+1); //Dragonbone Greaves
ART_POWER_AND_KNOWLEDGE(42,+2);
ART_POWER_AND_KNOWLEDGE(43,+3);
ART_POWER_AND_KNOWLEDGE(44,+4);
//Luck and morale
ART_MORALE(45,+1); //Still Eye of the Dragon
ART_LUCK(46,+1); //Clover of Fortune
ART_LUCK(47,+1); //Cards of Prophecy
ART_LUCK(48,+1); //Ladybird of Luck
ART_MORALE(49,+1); //Badge of Courage
ART_MORALE(50,+1); //Crest of Valor
ART_MORALE(51,+1); //Glyph of Gallantry
giveArtBonus(52,HeroBonus::SIGHT_RADIOUS,+1);//Speculum
giveArtBonus(53,HeroBonus::SIGHT_RADIOUS,+1);//Spyglass
//necromancy bonus
giveArtBonus(54,HeroBonus::SECONDARY_SKILL_PREMY,+5,12);//Amulet of the Undertaker
giveArtBonus(55,HeroBonus::SECONDARY_SKILL_PREMY,+10,12);//Vampire's Cowl
giveArtBonus(56,HeroBonus::SECONDARY_SKILL_PREMY,+15,12);//Dead Man's Boots
giveArtBonus(57,HeroBonus::MAGIC_RESISTANCE,+5);//Garniture of Interference
giveArtBonus(58,HeroBonus::MAGIC_RESISTANCE,+10);//Surcoat of Counterpoise
giveArtBonus(59,HeroBonus::MAGIC_RESISTANCE,+15);//Boots of Polarity
//archery bonus
giveArtBonus(60,HeroBonus::SECONDARY_SKILL_PREMY,+5,1);//Bow of Elven Cherrywood
giveArtBonus(61,HeroBonus::SECONDARY_SKILL_PREMY,+10,1);//Bowstring of the Unicorn's Mane
giveArtBonus(62,HeroBonus::SECONDARY_SKILL_PREMY,+15,1);//Angel Feather Arrows
//eagle eye bonus
giveArtBonus(63,HeroBonus::SECONDARY_SKILL_PREMY,+5,11);//Bird of Perception
giveArtBonus(64,HeroBonus::SECONDARY_SKILL_PREMY,+10,11);//Stoic Watchman
giveArtBonus(65,HeroBonus::SECONDARY_SKILL_PREMY,+15,11);//Emblem of Cognizance
//reducing cost of surrendering
giveArtBonus(66,HeroBonus::SURRENDER_DISCOUNT,+10);//Statesman's Medal
giveArtBonus(67,HeroBonus::SURRENDER_DISCOUNT,+10);//Diplomat's Ring
giveArtBonus(68,HeroBonus::SURRENDER_DISCOUNT,+10);//Ambassador's Sash
giveArtBonus(69,HeroBonus::STACKS_SPEED,+1);//Ring of the Wayfarer
giveArtBonus(70,HeroBonus::LAND_MOVEMENT,+300);//Equestrian's Gloves
giveArtBonus(71,HeroBonus::SEA_MOVEMENT,+1000);//Necklace of Ocean Guidance
giveArtBonus(72,HeroBonus::FLYING_MOVEMENT,+1);//Angel Wings
giveArtBonus(73,HeroBonus::MANA_REGENERATION,+1);//Charm of Mana
giveArtBonus(74,HeroBonus::MANA_REGENERATION,+2);//Talisman of Mana
giveArtBonus(75,HeroBonus::MANA_REGENERATION,+3);//Mystic Orb of Mana
giveArtBonus(76,HeroBonus::SPELL_DURATION,+1);//Collar of Conjuring
giveArtBonus(77,HeroBonus::SPELL_DURATION,+2);//Ring of Conjuring
giveArtBonus(78,HeroBonus::SPELL_DURATION,+3);//Cape of Conjuring
giveArtBonus(79,HeroBonus::AIR_SPELL_DMG_PREMY,+50);//Orb of the Firmament
giveArtBonus(80,HeroBonus::EARTH_SPELL_DMG_PREMY,+50);//Orb of Silt
giveArtBonus(81,HeroBonus::FIRE_SPELL_DMG_PREMY,+50);//Orb of Tempestuous Fire
giveArtBonus(82,HeroBonus::WATER_SPELL_DMG_PREMY,+50);//Orb of Driving Rain
giveArtBonus(83,HeroBonus::BLOCK_SPELLS_ABOVE_LEVEL,3);//Recanter's Cloak
giveArtBonus(84,HeroBonus::BLOCK_MORALE,0);//Spirit of Oppression
giveArtBonus(85,HeroBonus::BLOCK_LUCK,0);//Hourglass of the Evil Hour
giveArtBonus(86,HeroBonus::FIRE_SPELLS,0);//Tome of Fire Magic
giveArtBonus(87,HeroBonus::AIR_SPELLS,0);//Tome of Air Magic
giveArtBonus(88,HeroBonus::WATER_SPELLS,0);//Tome of Water Magic
giveArtBonus(89,HeroBonus::EARTH_SPELLS,0);//Tome of Earth Magic
giveArtBonus(90,HeroBonus::WATER_WALKING,0);//Boots of Levitation
giveArtBonus(91,HeroBonus::NO_SHOTING_PENALTY,0);//Golden Bow
giveArtBonus(92,HeroBonus::DISPEL_IMMUNITY,0);//Sphere of Permanence
giveArtBonus(93,HeroBonus::NEGATE_ALL_NATURAL_IMMUNITIES,0);//Orb of Vulnerability
giveArtBonus(94,HeroBonus::STACK_HEALTH,+1);//Ring of Vitality
giveArtBonus(95,HeroBonus::STACK_HEALTH,+1);//Ring of Life
giveArtBonus(96,HeroBonus::STACK_HEALTH,+2);//Vial of Lifeblood
giveArtBonus(97,HeroBonus::STACKS_SPEED,+1);//Necklace of Swiftness
giveArtBonus(98,HeroBonus::LAND_MOVEMENT,+600);//Boots of Speed
giveArtBonus(99,HeroBonus::STACKS_SPEED,+1);//Cape of Velocity
giveArtBonus(100,HeroBonus::SPELL_IMMUNITY,59);//Pendant of Dispassion
giveArtBonus(101,HeroBonus::SPELL_IMMUNITY,62);//Pendant of Second Sight
giveArtBonus(102,HeroBonus::SPELL_IMMUNITY,42);//Pendant of Holiness
giveArtBonus(103,HeroBonus::SPELL_IMMUNITY,24);//Pendant of Life
giveArtBonus(104,HeroBonus::SPELL_IMMUNITY,25);//Pendant of Death
giveArtBonus(105,HeroBonus::SPELL_IMMUNITY,60);//Pendant of Free Will
giveArtBonus(106,HeroBonus::SPELL_IMMUNITY,17);//Pendant of Negativity
giveArtBonus(107,HeroBonus::SPELL_IMMUNITY,61);//Pendant of Total Recall
giveArtBonus(108,HeroBonus::MORALE_AND_LUCK,+3);//Pendant of Courage
giveArtBonus(109,HeroBonus::GENERATE_RESOURCE,+1,4); //Everflowing Crystal Cloak
giveArtBonus(110,HeroBonus::GENERATE_RESOURCE,+1,5); //Ring of Infinite Gems
giveArtBonus(111,HeroBonus::GENERATE_RESOURCE,+1,1); //Everpouring Vial of Mercury
giveArtBonus(112,HeroBonus::GENERATE_RESOURCE,+1,2); //Inexhaustible Cart of Ore
giveArtBonus(113,HeroBonus::GENERATE_RESOURCE,+1,3); //Eversmoking Ring of Sulfur
giveArtBonus(114,HeroBonus::GENERATE_RESOURCE,+1,0); //Inexhaustible Cart of Lumber
giveArtBonus(115,HeroBonus::GENERATE_RESOURCE,+1000,6); //Endless Sack of Gold
giveArtBonus(116,HeroBonus::GENERATE_RESOURCE,+750,6); //Endless Bag of Gold
giveArtBonus(117,HeroBonus::GENERATE_RESOURCE,+500,6); //Endless Purse of Gold
giveArtBonus(118,HeroBonus::CREATURE_GROWTH,+5,2); //Legs of Legion
giveArtBonus(119,HeroBonus::CREATURE_GROWTH,+4,3); //Loins of Legion
giveArtBonus(120,HeroBonus::CREATURE_GROWTH,+3,4); //Torso of Legion
giveArtBonus(121,HeroBonus::CREATURE_GROWTH,+2,5); //Arms of Legion
giveArtBonus(122,HeroBonus::CREATURE_GROWTH,+1,6); //Head of Legion
//Sea Captain's Hat
giveArtBonus(123,HeroBonus::WHIRLPOOL_PROTECTION,0);
giveArtBonus(123,HeroBonus::SEA_MOVEMENT,+500);
giveArtBonus(123,HeroBonus::SPELL,3,0);
giveArtBonus(123,HeroBonus::SPELL,3,1);
giveArtBonus(124,HeroBonus::SPELLS_OF_LEVEL,3,1); //Spellbinder's Hat
giveArtBonus(125,HeroBonus::ENEMY_CANT_ESCAPE,0); //Shackles of War
giveArtBonus(126,HeroBonus::BLOCK_SPELLS_ABOVE_LEVEL,0);//Orb of Inhibition
}

View File

@ -1,6 +1,8 @@
#ifndef __CARTHANDLER_H__
#define __CARTHANDLER_H__
#include "../global.h"
#include "../lib/HeroBonus.h"
#include <list>
#include <string>
#include <vector>
@ -13,28 +15,29 @@ class DLL_EXPORT CArtifact //container for artifacts
public:
const std::string &Name() const;
const std::string &Description() const;
bool isAllowed; //true if we can use this artifact (map information)
//std::string desc2;
unsigned int price;
ui32 price;
std::vector<ui16> possibleSlots; //ids of slots where artifact can be placed
//bool spellBook, warMachine1, warMachine2, warMachine3, warMachine4, misc1, misc2, misc3, misc4, misc5, feet, lRing, rRing, torso, lHand, rHand, neck, shoulders, head;
EartClass aClass;
int id;
std::list<HeroBonus> bonuses; //bonuses given by artifact
template <typename Handler> void serialize(Handler &h, const int version)
{
h & isAllowed & name & description & price & possibleSlots & aClass & id ;
h & name & description & price & possibleSlots & aClass & id & bonuses;
}
};
class DLL_EXPORT CArtHandler //handles artifacts
{
void giveArtBonus(int aid, HeroBonus::BonusType type, int val, int subtype = -1);
public:
std::vector<CArtifact*> treasures, minors, majors, relics;
std::vector<CArtifact> artifacts;
void loadArtifacts(bool onlyTxt);
void sortArts();
void addBonuses();
static int convertMachineID(int id, bool creToArt);
CArtHandler();

View File

@ -348,7 +348,11 @@ bool CGHeroInstance::canWalkOnSea() const
}
int CGHeroInstance::getPrimSkillLevel(int id) const
{
return primSkills[id];
int ret = primSkills[id];
for(std::list<HeroBonus>::const_iterator i=bonuses.begin(); i != bonuses.end(); i++)
if(i->type == HeroBonus::PRIMARY_SKILL && i->subtype==id)
ret += i->val;
return ret;
}
ui8 CGHeroInstance::getSecSkillLevel(const int & ID) const
{
@ -359,24 +363,23 @@ ui8 CGHeroInstance::getSecSkillLevel(const int & ID) const
}
int CGHeroInstance::maxMovePoints(bool onLand) const
{
int ret = 1270+70*lowestSpeed(this);
if (ret>2000)
ret=2000;
int ret = std::max(2000, 1270+70*lowestSpeed(this)),
bonus = valOfBonuses(HeroBonus::MOVEMENT) + (onLand ? valOfBonuses(HeroBonus::LAND_MOVEMENT) : valOfBonuses(HeroBonus::SEA_MOVEMENT));
double bonus = 0;
double modifier = 0;
if(onLand)
{
//logistics:
switch(getSecSkillLevel(2))
{
case 1:
bonus = 0.1;
modifier = 0.1;
break;
case 2:
bonus = 0.2;
modifier = 0.2;
break;
case 3:
bonus = 0.3;
modifier = 0.3;
break;
}
}
@ -386,18 +389,19 @@ int CGHeroInstance::maxMovePoints(bool onLand) const
switch(getSecSkillLevel(2))
{
case 1:
bonus = 0.5;
modifier = 0.5;
break;
case 2:
bonus = 1.0;
modifier = 1.0;
break;
case 3:
bonus = 1.5;
modifier = 1.5;
break;
}
}
return int(ret + ret*bonus);
return int(ret + ret*modifier) + bonus;
}
ui32 CGHeroInstance::getArtAtPos(ui16 pos) const
{
if(pos<19)
@ -411,26 +415,7 @@ ui32 CGHeroInstance::getArtAtPos(ui16 pos) const
else
return -1;
}
void CGHeroInstance::setArtAtPos(ui16 pos, int art)
{
if(art<0)
{
if(pos<19)
artifWorn.erase(pos);
else
artifacts -= artifacts[pos-19];
}
else
{
if(pos<19)
artifWorn[pos] = art;
else
if(pos-19 < artifacts.size())
artifacts[pos-19] = art;
else
artifacts.push_back(art);
}
}
const CArtifact * CGHeroInstance::getArt(int pos) const
{
int id = getArtAtPos(pos);
@ -554,6 +539,15 @@ void CGHeroInstance::initHero()
hoverName = VLC->generaltexth->allTexts[15];
boost::algorithm::replace_first(hoverName,"%s",name);
boost::algorithm::replace_first(hoverName,"%s", type->heroClass->name);
//clear all bonuses from artifacts and give those from artifacts
std::remove_if(bonuses.begin(), bonuses.end(), boost::bind(HeroBonus::IsFrom,_1,HeroBonus::ARTIFACT,0xffffff));
for (std::map<ui16,ui32>::iterator ari = artifWorn.begin(); ari != artifWorn.end(); ari++)
{
CArtifact &art = VLC->arth->artifacts[ari->second];
for(std::list<HeroBonus>::iterator i = art.bonuses.begin(); i != art.bonuses.end(); i++)
bonuses.push_back(*i);
}
}
void CGHeroInstance::initHeroDefInfo()
@ -766,7 +760,21 @@ int3 CGHeroInstance::getSightCenter() const
int CGHeroInstance::getSightRadious() const
{
return 5 + getSecSkillLevel(3); //default + scouting
return 5 + getSecSkillLevel(3) + valOfBonuses(HeroBonus::SIGHT_RADIOUS); //default + scouting
}
si32 CGHeroInstance::manaRegain() const
{
return 1 + getSecSkillLevel(8) + valOfBonuses(HeroBonus::MANA_REGENERATION); //1 + Mysticism level
}
int CGHeroInstance::valOfBonuses( HeroBonus::BonusType type ) const
{
int ret = 0;
for(std::list<HeroBonus>::const_iterator i=bonuses.begin(); i != bonuses.end(); i++)
if(i->type == type)
ret += i->val;
return ret;
}
int CGTownInstance::getSightRadious() const //returns sight distance

View File

@ -229,6 +229,7 @@ public:
//////////////////////////////////////////////////////////////////////////
const HeroBonus *getBonus(int from, int id) const;
int valOfBonuses(HeroBonus::BonusType type) const;
const std::string &getBiography() const;
bool needsLastStack()const;
unsigned int getTileCost(const TerrainTile &dest, const TerrainTile &from) const; //move cost - applying pathfinding skill, road and terrain modifiers. NOT includes diagonal move penalty, last move levelling
@ -237,6 +238,7 @@ public:
float getMultiplicativeMoveBonus() const;
int3 getPosition(bool h3m) const; //h3m=true - returns position of hero object; h3m=false - returns position of hero 'manifestation'
si32 manaLimit() const; //maximum mana value for this hero (basically 10*knowledge)
si32 manaRegain() const; //how many points of mana can hero regain "naturally" in one day
bool canWalkOnSea() const;
int getCurrentLuck(int stack=-1, bool town=false) const;
std::vector<std::pair<int,std::string> > getCurrentLuckModifiers(int stack=-1, bool town=false) const; //args as above
@ -246,7 +248,6 @@ public:
ui8 getSecSkillLevel(const int & ID) const; //0 - no skill
int maxMovePoints(bool onLand) const;
ui32 getArtAtPos(ui16 pos) const; //-1 - no artifact
void setArtAtPos(ui16 pos, int art);
const CArtifact * getArt(int pos) const;
int getSpellSecLevel(int spell) const; //returns level of secondary ability (fire, water, earth, air magic) known to this hero and applicable to given spell; -1 if error
static int3 convertPosition(int3 src, bool toh3m); //toh3m=true: manifest->h3m; toh3m=false: h3m->manifest

View File

@ -4,21 +4,56 @@
struct DLL_EXPORT HeroBonus
{
enum BonusType{NONE, MOVEMENT, LAND_MOVEMENT, SEA_MOVEMENT, MORALE, LUCK, MORALE_AND_LUCK};
enum BonusType
{
//handled
NONE,
MOVEMENT, //both water/land
LAND_MOVEMENT,
SEA_MOVEMENT,
MORALE,
LUCK,
MORALE_AND_LUCK,
PRIMARY_SKILL, //uses subtype to pick skill
SIGHT_RADIOUS,
MANA_REGENERATION, //points per turn apart from normal (1 + mysticism)
//not handled yet:
MAGIC_RESISTANCE, // %
SECONDARY_SKILL_PREMY, //%
SURRENDER_DISCOUNT, //%
STACKS_SPEED,
FLYING_MOVEMENT, SPELL_DURATION, AIR_SPELL_DMG_PREMY, EARTH_SPELL_DMG_PREMY, FIRE_SPELL_DMG_PREMY,
WATER_SPELL_DMG_PREMY, BLOCK_SPELLS_ABOVE_LEVEL, WATER_WALKING, NO_SHOTING_PENALTY, DISPEL_IMMUNITY,
NEGATE_ALL_NATURAL_IMMUNITIES, STACK_HEALTH, SPELL_IMMUNITY, BLOCK_MORALE, BLOCK_LUCK, FIRE_SPELLS,
AIR_SPELLS, WATER_SPELLS, EARTH_SPELLS,
GENERATE_RESOURCE, //daily value, uses subtype (resource type)
CREATURE_GROWTH, //for legion artifacts: value - week growth bonus, subtype - monster level
WHIRLPOOL_PROTECTION, //hero won't lose army when teleporting through whirlpool
SPELL, //hero knows spell, val - skill level (0 - 3), subtype - spell id
SPELLS_OF_LEVEL, //hero knows all spells of given level, val - skill level; subtype - level
ENEMY_CANT_ESCAPE //for shackles of war
};
enum BonusDuration{PERMANENT, ONE_BATTLE, ONE_DAY, ONE_WEEK};
enum BonusSource{ARTIFACT, OBJECT};
ui8 duration; //uses BonusDuration values
ui8 type; //uses BonusType values - says to what is this bonus
si32 subtype; //-1 if not applicable
ui8 source;//uses BonusSource values - what gave that bonus
si32 val;//for morale/luck [-3,+3], others any
ui32 id; //id of object/artifact
std::string description;
HeroBonus(ui8 Dur, ui8 Type, ui8 Src, si32 Val, ui32 ID, std::string Desc)
:duration(Dur), type(Type), source(Src), val(Val), id(ID), description(Desc)
HeroBonus(ui8 Dur, ui8 Type, ui8 Src, si32 Val, ui32 ID, std::string Desc, si32 Subtype=-1)
:duration(Dur), type(Type), source(Src), val(Val), id(ID), description(Desc), subtype(Subtype)
{}
HeroBonus(){};
HeroBonus(ui8 Dur, ui8 Type, ui8 Src, si32 Val, ui32 ID, si32 Subtype=-1)
:duration(Dur), type(Type), source(Src), val(Val), id(ID), subtype(Subtype)
{}
HeroBonus()
{
subtype = -1;
}
template <typename Handler> void serialize(Handler &h, const int version)
{
h & duration & type & source & val & id & description;
@ -36,4 +71,8 @@ struct DLL_EXPORT HeroBonus
{
return hb.duration==HeroBonus::ONE_BATTLE;
}
static bool IsFrom(const HeroBonus &hb, ui8 source, ui32 id) //if id==0xffffff then id doesn't matter
{
return hb.source==source && (id==0xffffff || hb.id==id);
}
};

View File

@ -404,6 +404,7 @@ struct SetHeroArtifacts : public CPackForClient //509
SetHeroArtifacts(){type = 509;};
void applyCl(CClient *cl);
DLL_EXPORT void applyGs(CGameState *gs);
DLL_EXPORT void setArtAtPos(ui16 pos, int art);
si32 hid;
std::vector<ui32> artifacts; //hero's artifacts from bag
@ -413,6 +414,8 @@ struct SetHeroArtifacts : public CPackForClient //509
{
h & hid & artifacts & artifWorn;
}
std::vector<HeroBonus*> gained, lost; //used locally as hlp when applying
};
struct HeroRecruited : public CPackForClient //515

View File

@ -2,6 +2,7 @@
#include "../lib/NetPacks.h"
#include "../hch/CGeneralTextHandler.h"
#include "../hch/CDefObjInfoHandler.h"
#include "../hch/CArtHandler.h"
#include "../hch/CHeroHandler.h"
#include "../hch/CObjectHandler.h"
#include "../lib/VCMI_Lib.h"
@ -272,10 +273,68 @@ DLL_EXPORT void SetHeroesInTown::applyGs( CGameState *gs )
DLL_EXPORT void SetHeroArtifacts::applyGs( CGameState *gs )
{
CGHeroInstance *h = gs->getHero(hid);
std::vector<ui32> equiped, unequiped;
for(std::map<ui16,ui32>::const_iterator i = h->artifWorn.begin(); i != h->artifWorn.end(); i++)
if(!vstd::contains(artifWorn,i->first) || artifWorn[i->first] != i->second)
unequiped.push_back(i->second);
for(std::map<ui16,ui32>::const_iterator i = artifWorn.begin(); i != artifWorn.end(); i++)
if(!vstd::contains(h->artifWorn,i->first) || h->artifWorn[i->first] != i->second)
equiped.push_back(i->second);
h->artifacts = artifacts;
h->artifWorn = artifWorn;
BOOST_FOREACH(ui32 id, unequiped)
{
while(1)
{
std::list<HeroBonus>::iterator hlp = std::find_if(h->bonuses.begin(),h->bonuses.end(),boost::bind(HeroBonus::IsFrom,_1,HeroBonus::ARTIFACT,id));
if(hlp != h->bonuses.end())
{
lost.push_back(&*hlp);
h->bonuses.erase(hlp);
}
else
{
break;
}
}
}
BOOST_FOREACH(ui32 id, equiped)
{
CArtifact &art = VLC->arth->artifacts[id];
for(std::list<HeroBonus>::iterator i = art.bonuses.begin(); i != art.bonuses.end(); i++)
{
gained.push_back(&*i);
h->bonuses.push_back(*i);
}
}
}
DLL_EXPORT void SetHeroArtifacts::setArtAtPos(ui16 pos, int art)
{
if(art<0)
{
if(pos<19)
artifWorn.erase(pos);
else
artifacts -= artifacts[pos-19];
}
else
{
if(pos<19)
artifWorn[pos] = art;
else
if(pos-19 < artifacts.size())
artifacts[pos-19] = art;
else
artifacts.push_back(art);
}
}
DLL_EXPORT void HeroRecruited::applyGs( CGameState *gs )
{
CGHeroInstance *h = gs->hpool.heroesPool[hid];
@ -320,8 +379,9 @@ DLL_EXPORT void NewTurn::applyGs( CGameState *gs )
gs->day = day;
BOOST_FOREACH(NewTurn::Hero h, heroes) //give mana/movement point
{
static_cast<CGHeroInstance*>(gs->map->objects[h.id])->movement = h.move;
static_cast<CGHeroInstance*>(gs->map->objects[h.id])->mana = h.mana;
CGHeroInstance *hero = gs->getHero(h.id);
hero->movement = h.move;
hero->mana = h.mana;
}
BOOST_FOREACH(SetResources h, res) //give resources
@ -339,7 +399,7 @@ DLL_EXPORT void NewTurn::applyGs( CGameState *gs )
if(gs->getDate(1) == 7) //new week
BOOST_FOREACH(CGHeroInstance *h, gs->map->heroes)
h->bonuses.remove_if(HeroBonus::OneWeek);
h->bonuses.remove_if(HeroBonus::OneWeek);
}
DLL_EXPORT void SetObjectProperty::applyGs( CGameState *gs )

View File

@ -646,7 +646,12 @@ void CGameHandler::newTurn()
NewTurn::Hero hth;
hth.id = h->id;
hth.move = h->maxMovePoints(true); //TODO: check if hero is really on the land
hth.mana = std::max(h->mana,std::min(h->mana+1+h->getSecSkillLevel(8), h->manaLimit())); //hero regains 1 mana point + mysticism lvel
if(h->visitedTown && vstd::contains(h->visitedTown->builtBuildings,0)) //if hero starts turn in town with mage guild
hth.mana = h->manaLimit(); //restore all mana
else
hth.mana = std::max(si32(0), std::min(h->mana + h->manaRegain(), h->manaLimit()) );
n.heroes.insert(hth);
switch(h->getSecSkillLevel(13)) //handle estates - give gold
@ -1018,7 +1023,7 @@ void CGameHandler::checkForBattleEnd( std::vector<CStack*> &stacks )
hasStack[0] = hasStack[1] = false;
for(int b = 0; b<stacks.size(); ++b)
{
if(stacks[b]->alive())
if(stacks[b]->alive() && !vstd::contains(stacks[b]->abilities,SIEGE_WEAPON))
{
hasStack[1-stacks[b]->attackerOwned] = true;
}
@ -1242,28 +1247,31 @@ void CGameHandler::stopHeroVisitCastle(int obj, int heroID)
void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1 - first free slot in backpack
{
const CGHeroInstance* h = getHero(hid);
const CArtifact &art = VLC->arth->artifacts[artid];
SetHeroArtifacts sha;
sha.hid = hid;
sha.artifacts = h->artifacts;
sha.artifWorn = h->artifWorn;
if(position<0)
{
if(position == -2)
{
int i;
for(i=0; i<VLC->arth->artifacts[artid].possibleSlots.size(); i++) //try to put artifact into first avaialble slot
for(i=0; i<art.possibleSlots.size(); i++) //try to put artifact into first available slot
{
if( !vstd::contains(sha.artifWorn,VLC->arth->artifacts[artid].possibleSlots[i]) )
if( !vstd::contains(sha.artifWorn,art.possibleSlots[i]) )
{
sha.artifWorn[VLC->arth->artifacts[artid].possibleSlots[i]] = artid;
//we've found a free suitable slot
sha.artifWorn[art.possibleSlots[i]] = artid;
break;
}
}
if(i==VLC->arth->artifacts[artid].possibleSlots.size()) //if haven't find proper slot, use backpack
if(i == art.possibleSlots.size()) //if haven't find proper slot, use backpack
sha.artifacts.push_back(artid);
}
else //should be -1 => putartifact into backpack
else //should be -1 => put artifact into backpack
{
sha.artifacts.push_back(artid);
}
@ -1271,10 +1279,15 @@ void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1
else
{
if(!vstd::contains(sha.artifWorn,ui16(position)))
{
sha.artifWorn[position] = artid;
}
else
{
sha.artifacts.push_back(artid);
}
}
sendAndApply(&sha);
}
@ -1763,20 +1776,32 @@ void CGameHandler::swapArtifacts( si32 hid1, si32 hid2, ui16 slot1, ui16 slot2 )
CGHeroInstance *h1 = gs->getHero(hid1), *h2 = gs->getHero(hid2);
if((distance(h1->pos,h2->pos) > 1.0) || (h1->tempOwner != h2->tempOwner))
return;
int a1=h1->getArtAtPos(slot1), a2=h2->getArtAtPos(slot2);
const CArtifact *a1 = h1->getArt(slot1),
*a2=h2->getArt(slot2);
if(a1 && slot2<19 && !vstd::contains(a1->possibleSlots,slot2)
|| a2 && slot1<19 && !vstd::contains(a2->possibleSlots,slot1)
)
{
//artifact doesn't fit dst slot
complain("Cannot swap artifacts!");
return;
}
h2->setArtAtPos(slot2,a1);
h1->setArtAtPos(slot1,a2);
SetHeroArtifacts sha;
sha.hid = hid1;
sha.artifacts = h1->artifacts;
sha.artifWorn = h1->artifWorn;
sha.setArtAtPos(slot1,h2->getArtAtPos(slot2));
if(h1 == h2) sha.setArtAtPos(slot2,h1->getArtAtPos(slot1));
sendAndApply(&sha);
if(hid1 != hid2)
{
sha.hid = hid2;
sha.artifacts = h2->artifacts;
sha.artifWorn = h2->artifWorn;
sha.setArtAtPos(slot2,h1->getArtAtPos(slot1));
sendAndApply(&sha);
}
}
@ -1787,21 +1812,14 @@ void CGameHandler::buyArtifact( ui32 hid, si32 aid )
CGTownInstance *town = hero->visitedTown;
if(aid==0) //spellbook
{
if(!vstd::contains(town->builtBuildings,si32(0)))
if(!vstd::contains(town->builtBuildings,si32(0)) && complain("Cannot buy a spellbook, no mage guild in the town!")
|| getResource(hero->getOwner(),6)<500 && complain("Cannot buy a spellbook, not enough gold!")
|| hero->getArt(17) && complain("Cannot buy a spellbook, hero already has a one!")
)
return;
SetResource sr;
sr.player = hero->tempOwner;
sr.resid = 6;
sr.val = gs->getPlayer(hero->getOwner())->resources[6] - 500;
sendAndApply(&sr);
SetHeroArtifacts sha;
sha.hid = hid;
sha.artifacts = hero->artifacts;
sha.artifWorn = hero->artifWorn;
sha.artifWorn[17] = 0;
sendAndApply(&sha);
giveResource(hero->getOwner(),6,-500);
giveHeroArtifact(0,hid,17);
giveSpells(town,hero);
}
else if(aid < 7 && aid > 3) //war machine
@ -1814,18 +1832,9 @@ void CGameHandler::buyArtifact( ui32 hid, si32 aid )
{
return;
}
SetResource sr;
sr.player = hero->tempOwner;
sr.resid = 6;
sr.val = gs->getPlayer(hero->getOwner())->resources[6] - price;
sendAndApply(&sr);
SetHeroArtifacts sha;
sha.hid = hid;
sha.artifacts = hero->artifacts;
sha.artifWorn = hero->artifWorn;
sha.artifWorn[9+aid] = aid;
sendAndApply(&sha);
giveResource(hero->getOwner(),6,-price);
giveHeroArtifact(aid,hid,9+aid);
}
}

View File

@ -100,6 +100,8 @@ public:
void heroVisitCastle(int obj, int heroID);
void stopHeroVisitCastle(int obj, int heroID);
void giveHeroArtifact(int artid, int hid, int position); //pos==-1 - first free slot in backpack; pos==-2 - default if available or backpack
void moveArtifact(int hid, int oldPosition, int destPos);
void removeArtifact(int hid, int pos);
void startBattleI(const CCreatureSet * army1, const CCreatureSet * army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, boost::function<void(BattleResult*)> cb); //use hero=NULL for no hero
void startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb); //for hero<=>neutral army
void setAmount(int objid, ui32 val);