Bläddra i källkod

* a bit more work on campaigns; hero crossover still buggy

mateuszb 12 år sedan
förälder
incheckning
3958364884

+ 1 - 1
client/CHeroWindow.cpp

@@ -215,7 +215,7 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded /*= fals
 	//primary skills support
 	for(size_t g=0; g<primSkillAreas.size(); ++g)
 	{
-		primSkillAreas[g]->bonusValue = heroWArt.getPrimSkillLevel(g);
+		primSkillAreas[g]->bonusValue = heroWArt.getPrimSkillLevel(static_cast<PrimarySkill::PrimarySkill>(g));
 	}
 
 	//secondary skills support

+ 1 - 1
client/CKingdomInterface.cpp

@@ -316,7 +316,7 @@ si64 InfoBoxHeroData::getValue()
 	switch(type)
 	{
 	case HERO_PRIMARY_SKILL:
-		return hero->getPrimSkillLevel(index);
+		return hero->getPrimSkillLevel(static_cast<PrimarySkill::PrimarySkill>(index));
 	case HERO_MANA:
 		return hero->mana;
 	case HERO_EXPERIENCE:

+ 2 - 2
client/GUIClasses.cpp

@@ -5041,9 +5041,9 @@ void CExchangeWindow::prepareBackground()
 	{
 		CHeroWithMaybePickedArtifact heroWArt = CHeroWithMaybePickedArtifact(this, heroInst[b]);
 		//printing primary skills' amounts
-		for(int m=0; m<4; ++m)
+		for(int m=0; m<GameConstants::PRIMARY_SKILLS; ++m)
 			new CLabel(352 + 93 * b, 35 + 36 * m, FONT_SMALL, CENTER, Colors::WHITE,
-		               boost::lexical_cast<std::string>(heroWArt.getPrimSkillLevel(m)));
+		               boost::lexical_cast<std::string>(heroWArt.getPrimSkillLevel(static_cast<PrimarySkill::PrimarySkill>(m))));
 
 		//printing secondary skills
 		for(int m=0; m<heroInst[b]->secSkills.size(); ++m)

+ 84 - 19
lib/CGameState.cpp

@@ -161,7 +161,7 @@ void MetaString::getLocalString(const std::pair<ui8,ui32> &txt, std::string &dst
 	else if(type == MINE_EVNTS)
 	{
 		dst = VLC->generaltexth->mines[ser].second;
-	}
+	} 
 	else if(type == SPELL_NAME)
 	{
 		dst = VLC->spellh->spells[ser]->name;
@@ -1092,14 +1092,16 @@ void CGameState::init(StartInfo * si)
 
 	/*************************replace hero placeholders*****************************/
 	tlog4 << "\tReplacing hero placeholders";
+	std::vector<std::tuple<CGHeroInstance*, int> > campHeroReplacements; //instance, id in vector
 	if (scenarioOps->campState)
 	{
 		auto replaceHero = [&](int objId, CGHeroInstance * ghi)
 		{
-			ghi->tempOwner = getHumanPlayerInfo()[0]->color;
-			ghi->id = objId;
-			gs->map->objects[objId] = ghi;
-			gs->map->heroes.push_back(ghi);
+			campHeroReplacements.push_back(std::make_tuple(ghi, objId));
+// 			ghi->tempOwner = getHumanPlayerInfo()[0]->color;
+// 			ghi->id = objId;
+// 			gs->map->objects[objId] = ghi;
+// 			gs->map->heroes.push_back(ghi);
 		};
 
 		auto campaign = scenarioOps->campState;
@@ -1248,28 +1250,91 @@ void CGameState::init(StartInfo * si)
 			continue;
 		}
 		CGHeroInstance * vhi = map->heroes[i];
-		if(vhi->sex == 0xff) //campaign heroes already come initialized -- I hope this will skip them
+		vhi->initHero();
+		players.find(vhi->getOwner())->second.heroes.push_back(vhi);
+		hids.erase(vhi->subID);
+	}
+
+	BOOST_FOREACH(auto obj, campHeroReplacements)
+	{
+		CGHeroInstance * hero = new CGHeroInstance(),
+			* oldHero = std::get<0>(obj);
+		hero->initHero(oldHero->subID);
+		hero->id = std::get<1>(obj);
+		map->objects[hero->id] = hero;
+		map->heroes.push_back(hero);
+		const auto & travelOptions = scenarioOps->campState->getCurrentScenario().travelOptions;
+
+		if (travelOptions.whatHeroKeeps & 1)
+		{
+			//giving exp
+			hero->exp = oldHero->exp;
+		}
+		if (travelOptions.whatHeroKeeps & 2)
+		{
+			//giving prim skills
+			for(int g=0; g<GameConstants::PRIMARY_SKILLS; ++g)
+			{
+				hero->getBonusLocalFirst(Selector::type(Bonus::PRIMARY_SKILL) &&
+					Selector::subtype(g) && Selector::sourceType(Bonus::HERO_BASE_SKILL) )->val
+					= oldHero->getBonusLocalFirst(Selector::type(Bonus::PRIMARY_SKILL) &&
+					Selector::subtype(g) && Selector::sourceType(Bonus::HERO_BASE_SKILL) )->val;
+			}
+		}
+		if (travelOptions.whatHeroKeeps & 4)
+		{
+			//giving sec skills
+			hero->secSkills = oldHero->secSkills;
+		}
+		if (travelOptions.whatHeroKeeps & 8)
+		{
+			//giving spells
+			hero->spells = oldHero->spells;
+		}
+		if (travelOptions.whatHeroKeeps & 16)
+		{
+			//giving artifacts
+			size_t totalArts = GameConstants::BACKPACK_START + oldHero->artifactsInBackpack.size();
+			for (size_t i=0; i<totalArts; i++ )
+			{
+				const ArtSlotInfo *info = oldHero->getSlot(i);
+				if (!info)
+					continue;
+
+				const CArtifactInstance *art = info->artifact;
+				if (!art)//FIXME: check spellbook and catapult behaviour
+					continue;
+
+				int id  = art->artType->id;
+				assert( 8*18 > id );//number of arts that fits into h3m format
+				bool takeable = travelOptions.artifsKeptByHero[id / 8] & ( 1 << (id%8) );
+
+				if (takeable)
+					hero->setNewArtSlot(i, const_cast<CArtifactInstance*>(oldHero->getSlot(i)->artifact.get()), false);
+			}
+		}
+
+		//giving creatures
+		if(!oldHero->stacks.empty())
 		{
-			vhi->initHero();
-			players.find(vhi->getOwner())->second.heroes.push_back(vhi);
-			hids.erase(vhi->subID);
+			hero->stacks = oldHero->stacks;
 		}
 	}
 
-	for (ui32 i=0; i<map->objects.size();i++) //prisons
+	BOOST_FOREACH(auto obj, map->objects) //prisons
 	{
-		if (map->objects[i] && map->objects[i]->ID == Obj::PRISON)
-			hids.erase(map->objects[i]->subID);
+		if(obj && obj->ID == Obj::PRISON)
+			hids.erase(obj->subID);
 	}
 
-	for(ui32 i=0; i<map->predefinedHeroes.size(); i++)
+	BOOST_FOREACH(auto ph, map->predefinedHeroes)
 	{
-		if(!vstd::contains(hids,map->predefinedHeroes[i]->subID))
+		if(!vstd::contains(hids, ph->subID))
 			continue;
-		map->predefinedHeroes[i]->initHero();
-		hpool.heroesPool[map->predefinedHeroes[i]->subID] = map->predefinedHeroes[i];
-		hpool.pavailable[map->predefinedHeroes[i]->subID] = 0xff;
-		hids.erase(map->predefinedHeroes[i]->subID);
+		ph->initHero();
+		hpool.heroesPool[ph->subID] = ph;
+		hpool.pavailable[ph->subID] = 0xff;
+		hids.erase(ph->subID);
 	}
 
 	BOOST_FOREACH(int hid, hids) //all not used allowed heroes go with default state into the pool
@@ -2796,7 +2861,7 @@ void InfoAboutHero::initFromHero(const CGHeroInstance *h, bool detailed)
 
 		for (int i = 0; i < GameConstants::PRIMARY_SKILLS ; i++)
 		{
-			details->primskills[i] = h->getPrimSkillLevel(i);
+			details->primskills[i] = h->getPrimSkillLevel(static_cast<PrimarySkill::PrimarySkill>(i));
 		}
 	}
 }

+ 3 - 3
lib/CObjectHandler.cpp

@@ -1286,7 +1286,7 @@ void CGHeroInstance::setPropertyDer( ui8 what, ui32 val )
 
 double CGHeroInstance::getHeroStrength() const
 {
-	return sqrt((1.0 + 0.05*getPrimSkillLevel(0)) * (1.0 + 0.05*getPrimSkillLevel(1)));
+	return sqrt((1.0 + 0.05*getPrimSkillLevel(PrimarySkill::ATTACK)) * (1.0 + 0.05*getPrimSkillLevel(PrimarySkill::DEFENSE)));
 }
 
 ui64 CGHeroInstance::getTotalStrength() const
@@ -4115,9 +4115,9 @@ bool CQuest::checkQuest (const CGHeroInstance * h) const
 				return true;
 			return false;
 		case MISSION_PRIMARY_STAT:
-			for (int i = 0; i < 4; ++i)
+			for (int i = 0; i < GameConstants::PRIMARY_SKILLS; ++i)
 			{
-				if (h->getPrimSkillLevel(i) < m2stats[i])
+				if (h->getPrimSkillLevel(static_cast<PrimarySkill::PrimarySkill>(i)) < m2stats[i])
 					return false;
 			}
 			return true;

+ 1 - 1
lib/HeroBonus.cpp

@@ -466,7 +466,7 @@ si32 IBonusBearer::manaLimit() const
 		/ 10.0);
 }
 
-int IBonusBearer::getPrimSkillLevel(int id) const
+int IBonusBearer::getPrimSkillLevel(PrimarySkill::PrimarySkill id) const
 {
 	int ret = 0;
 	if(id == PrimarySkill::ATTACK)

+ 1 - 1
lib/HeroBonus.h

@@ -541,7 +541,7 @@ public:
 	ui8 howManyEffectsSet(ui16 id) const; //returns amount of effects with given id set for this stack
 
 	si32 manaLimit() const; //maximum mana value for this hero (basically 10*knowledge)
-	int getPrimSkillLevel(int id) const; //0-attack, 1-defence, 2-spell power, 3-knowledge
+	int getPrimSkillLevel(PrimarySkill::PrimarySkill id) const;
 	const TBonusListPtr getSpellBonuses() const;
 };
 

+ 4 - 2
lib/IGameCallback.cpp

@@ -330,14 +330,16 @@ int CGameInfoCallback::estimateSpellDamage(const CSpell * sp, const CGHeroInstan
 	if(!gs->curB) //no battle
 	{
 		if (hero) //but we see hero's spellbook
-			return gs->curB->calculateSpellDmg(sp, hero, NULL, hero->getSpellSchoolLevel(sp), hero->getPrimSkillLevel(2));
+			return gs->curB->calculateSpellDmg(
+				sp, hero, NULL, hero->getSpellSchoolLevel(sp), hero->getPrimSkillLevel(PrimarySkill::SPELL_POWER));
 		else
 			return 0; //mage guild
 	}
 	//gs->getHero(gs->currentPlayer)
 	//const CGHeroInstance * ourHero = gs->curB->heroes[0]->tempOwner == player ? gs->curB->heroes[0] : gs->curB->heroes[1];
 	const CGHeroInstance * ourHero = hero;
-	return gs->curB->calculateSpellDmg(sp, ourHero, NULL, ourHero->getSpellSchoolLevel(sp), ourHero->getPrimSkillLevel(2));
+	return gs->curB->calculateSpellDmg(
+		sp, ourHero, NULL, ourHero->getSpellSchoolLevel(sp), ourHero->getPrimSkillLevel(PrimarySkill::SPELL_POWER));
 }
 
 void CGameInfoCallback::getThievesGuildInfo(SThievesGuildInfo & thi, const CGObjectInstance * obj)

+ 1 - 1
lib/Mapping/CCampaignHandler.cpp

@@ -381,7 +381,7 @@ void CCampaignScenario::prepareCrossoverHeroes( std::vector<CGHeroInstance *> he
 				assert( 8*18 > id );//number of arts that fits into h3m format
 				bool takeable = travelOptions.artifsKeptByHero[id / 8] & ( 1 << (id%8) );
 
-				if (takeable)
+				if (!takeable)
 					hero->eraseArtSlot(i);
 			}
 		}

+ 2 - 1
server/CGameHandler.cpp

@@ -4455,7 +4455,8 @@ bool CGameHandler::makeCustomAction( BattleAction &ba )
 				StartAction start_action(ba);
 				sendAndApply(&start_action); //start spell casting
 
-				handleSpellCasting (ba.additionalInfo, skill, ba.destinationTile, ba.side, h->tempOwner, h, secondHero, h->getPrimSkillLevel(2),
+				handleSpellCasting (ba.additionalInfo, skill, ba.destinationTile, ba.side, h->tempOwner,
+									h, secondHero, h->getPrimSkillLevel(PrimarySkill::SPELL_POWER),
 									ECastingMode::HERO_CASTING, NULL, ba.selectedStack);
 
 				sendAndApply(&end_action);