Przeglądaj źródła

- Extended cap or removed sign for some values that may potentially overflow
- Fixed #851

DjWarmonger 13 lat temu
rodzic
commit
1cbd7e94e4

+ 8 - 0
client/BattleInterface/CBattleInterface.cpp

@@ -2466,6 +2466,14 @@ void CBattleInterface::battleTriggerEffect(const BattleTriggerEffect & bte)
 			displayEffect(15, stack->position);
 			CCS->soundh->playSound(soundBase::FEAR);
 			break;
+		case Bonus::MORALE:
+		{
+			std::string hlp = CGI->generaltexth->allTexts[33];
+			boost::algorithm::replace_first(hlp,"%s",(stack->getName()));
+			displayEffect(20,stack->position);
+			console->addText(hlp);
+			break;
+		}
 		default:
 			return;
 	}

+ 0 - 9
client/CPlayerInterface.cpp

@@ -719,15 +719,6 @@ BattleAction CPlayerInterface::activeStack(const CStack * stack) //called when i
 	CBattleInterface *b = battleInt;
 	{
 		boost::unique_lock<boost::recursive_mutex> un(*pim);
-
-		if(vstd::contains(stack->state,EBattleStackState::MOVED)) //this stack has moved and makes second action -> high morale
-		{
-			std::string hlp = CGI->generaltexth->allTexts[33];
-			boost::algorithm::replace_first(hlp,"%s",(stack->count != 1) ? stack->getCreature()->namePl : stack->getCreature()->nameSing);
-			battleInt->displayEffect(20,stack->position);
-			battleInt->console->addText(hlp);
-		}
-
 		b->stackActivated(stack);
 		//Regeneration & mana drain go there
 	}

+ 1 - 1
client/GUIClasses.cpp

@@ -1189,7 +1189,7 @@ void CHeroList::updateMove(const CGHeroInstance* which) //draws move points bar
 			ser = i;
 	ser -= from;
 	if(ser<0 || ser >= SIZE) return;
-	int pom = std::min((which->movement)/100,(si32)mobile->ourImages.size()-1);
+	int pom = std::min((which->movement)/100,(ui32)mobile->ourImages.size()-1);
 	blitAt(mobile->ourImages[pom].bitmap,posmobx,posmoby+ser*32); //move point
 }
 

+ 4 - 4
lib/CObjectHandler.h

@@ -271,13 +271,13 @@ public:
 
 	ConstTransitivePtr<CHero> type;
 	ui64 exp; //experience points
-	si32 level; //current level of hero
+	ui32 level; //current level of hero
 	std::string name; //may be custom
 	std::string biography; //if custom
 	si32 portrait; //may be custom
-	si32 mana; // remaining spell points
+	ui32 mana; // remaining spell points
 	std::vector<std::pair<ui8,ui8> > secSkills; //first - ID of skill, second - level of skill (1 - basic, 2 - adv., 3 - expert); if hero has ability (-1, -1) it meansthat it should have default secondary abilities
-	si32 movement; //remaining movement points
+	ui32 movement; //remaining movement points
 	ui8 sex;
 	ui8 inTownGarrison; // if hero is in town garrison 
 	ConstTransitivePtr<CGTownInstance> visitedTown; //set if hero is visiting town or in the town garrison
@@ -293,7 +293,7 @@ public:
 	{
 		Patrol(){patrolling=false;patrolRadious=-1;};
 		ui8 patrolling;
-		si32 patrolRadious;
+		ui32 patrolRadious;
 		template <typename Handler> void serialize(Handler &h, const int version)
 		{
 			h & patrolling & patrolRadious;

+ 3 - 3
lib/HeroBonus.cpp

@@ -369,9 +369,9 @@ si32 IBonusBearer::Defense(bool withFrenzy /*= true*/) const
 	return ret;
 }
 
-ui16 IBonusBearer::MaxHealth() const
+ui32 IBonusBearer::MaxHealth() const
 {
-	return std::max(1, valOfBonuses(Bonus::STACK_HEALTH)); //never 0 or negative
+	return std::max(1, valOfBonuses(Bonus::STACK_HEALTH)); //never 0
 }
 
 ui32 IBonusBearer::getMinDamage() const
@@ -387,7 +387,7 @@ ui32 IBonusBearer::getMaxDamage() const
 	return valOfBonuses(Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 0) || Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 2), cachingStr.str());
 }
 
-si32 IBonusBearer::manaLimit() const
+ui32 IBonusBearer::manaLimit() const
 {
 	return si32(getPrimSkillLevel(3) * (100.0 + valOfBonuses(Bonus::SECONDARY_SKILL_PREMY, 24)) / 10.0);
 }

+ 2 - 2
lib/HeroBonus.h

@@ -494,11 +494,11 @@ public:
 	int LuckVal() const; //range [-3, +3]
 	si32 Attack() const; //get attack of stack with all modificators
 	si32 Defense(bool withFrenzy = true) const; //get defense of stack with all modificators
-	ui16 MaxHealth() const; //get max HP of stack with all modifiers
+	ui32 MaxHealth() const; //get max HP of stack with all modifiers
 	bool isLiving() const; //non-undead, non-non living or alive
 	virtual si32 magicResistance() const;
 
-	si32 manaLimit() const; //maximum mana value for this hero (basically 10*knowledge)
+	ui32 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
 	const TBonusListPtr getSpellBonuses() const;
 };

+ 1 - 1
lib/NetPacks.h

@@ -231,7 +231,7 @@ struct SetResource : public CPackForClient //102
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
 	ui8 player, resid;
-	si32 val;
+	TResourceCap val;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{

+ 1 - 1
lib/ResourceSet.cpp

@@ -16,7 +16,7 @@ bool Res::ResourceSet::nonZero() const
 	return false;
 }
 
-void Res::ResourceSet::amax(const TResource &val)
+void Res::ResourceSet::amax(const TResourceCap &val)
 {
 	for(int i = 0; i < size(); i++)
 		::vstd::amax(at(i), val);

+ 3 - 2
lib/ResourceSet.h

@@ -4,6 +4,7 @@
 #include <climits>
 
 typedef si32 TResource;
+typedef ui64 TResourceCap; //to avoid overflow when adding integers
 
 namespace Res
 {
@@ -102,7 +103,7 @@ namespace Res
 			h & static_cast<std::vector<int>&>(*this);
 		}
 
-		DLL_LINKAGE void amax(const TResource &val); //performs vstd::amax on each element
+		DLL_LINKAGE void amax(const TResourceCap &val); //performs vstd::amax on each element
 		DLL_LINKAGE bool nonZero() const; //returns true if at least one value is non-zero;
 		DLL_LINKAGE bool canAfford(const ResourceSet &price) const;
 		DLL_LINKAGE bool canBeAfforded(const ResourceSet &res) const;
@@ -112,7 +113,7 @@ namespace Res
 		{
 			struct ResEntry
 			{
-				TResource resType, resVal;
+				TResourceCap resType, resVal;
 			} cur;
 			const ResourceSet &rs;
 			void advance();

+ 14 - 4
server/CGameHandler.cpp

@@ -981,7 +981,7 @@ void CGameHandler::newTurn()
 			if(h->visitedTown && vstd::contains(h->visitedTown->builtBuildings,0)) //if hero starts turn in town with mage guild
 				hth.mana = std::max(h->mana, h->manaLimit()); //restore all mana
 			else
-				hth.mana = std::max(si32(0), std::max(h->mana, std::min(h->mana + h->manaRegain(), h->manaLimit())) ); 
+				hth.mana = std::max((ui32)(0), std::max(h->mana, std::min((ui32)(h->mana + h->manaRegain()), h->manaLimit()))); 
 
 			n.heroes.insert(hth);
 			
@@ -1471,7 +1471,7 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
 
 		//check if there is blocking visitable object
 		blockvis = false;
-		tmh.movePoints = std::max(si32(0),h->movement-cost); //take move points
+		tmh.movePoints = std::max((ui32)(0),h->movement-cost); //take move points
 		BOOST_FOREACH(CGObjectInstance *obj, t.visitableObjects)
 		{
 			if(obj != h  &&  obj->blockVisit  &&  !(obj->getPassableness() & 1<<h->tempOwner))
@@ -1627,7 +1627,7 @@ ui32 CGameHandler::showBlockingDialog( BlockingDialog *iw )
 	return 0;
 }
 
-void CGameHandler::giveResource(int player, int which, int val)
+void CGameHandler::giveResource(int player, int which, int val) //TODO: cap according to Bersy's suggestion
 {
 	if(!val) return; //don't waste time on empty call
 	SetResource sr;
@@ -5437,7 +5437,17 @@ void CGameHandler::runBattle()
 					)
 				{
 					if(rand()%24 < nextStackMorale) //this stack hasn't got morale this turn
-						++numberOfAsks; //move this stack once more
+
+						{
+							BattleTriggerEffect bte;
+							bte.stackID = next->ID;
+							bte.effect = Bonus::MORALE;
+							bte.val = 1;
+							bte.additionalInfo = 0;
+							sendAndApply(&bte); //play animation
+
+							++numberOfAsks; //move this stack once more
+						}
 				}
 
 				--numberOfAsks;