mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Now parsing CREXPBON into Bonus System, with limiters. StackExperience class removed.
Exp ranks are now calculated, though exp is never set.
This commit is contained in:
		| @@ -628,25 +628,29 @@ void CCreatureHandler::loadCreatures() | ||||
| 		buf = bitmaph->getTextFile("CREXPBON.TXT"); | ||||
| 		int it = 0; | ||||
| 		si32 creid = -1; | ||||
| 		commonBonuses.resize(8); //8 tiers | ||||
| 		stackExperience b; | ||||
| 		b.expBonuses.resize(10); | ||||
| 		Bonus b; //prototype with some default properties | ||||
| 		b.source = Bonus::STACK_EXPERIENCE; | ||||
| 		b.valType = Bonus::ADDITIVE_VALUE; | ||||
| 		b.additionalInfo = 0; | ||||
| 		b.enable = false; //Bonuses are always active by default | ||||
| 		BonusList bl; | ||||
|  | ||||
| 		loadToIt (dump2, buf, it, 3); //ignore first line | ||||
| 		loadToIt (dump2, buf, it, 4); //ignore index | ||||
| 		loadStackExp(b, buf, it); | ||||
|  | ||||
| 		loadStackExp(b, bl, buf, it); | ||||
| 		BOOST_FOREACH(Bonus * b, bl) | ||||
| 			addBonusForAllCreatures(b); //health bonus is common for all | ||||
|  | ||||
| 		loadToIt (dump2, buf, it, 4); //crop comment | ||||
| 		for (i = 0; i < 8; ++i) | ||||
| 		for (i = 1; i < 8; ++i) | ||||
| 		{ | ||||
| 			commonBonuses[i].push_back(new stackExperience(b));//health bonus common for all | ||||
| 			for (int j = 0; j < 4; ++j) //four modifiers common for tiers | ||||
| 			{ | ||||
| 				loadToIt (dump2, buf, it, 4); //ignore index | ||||
| 				loadStackExp(b, buf, it); | ||||
| 				commonBonuses[i].push_back(new stackExperience(b)); | ||||
| 				bl.clear(); | ||||
| 				loadStackExp(b, bl, buf, it); | ||||
| 				BOOST_FOREACH(Bonus * b, bl) | ||||
| 					addBonusForTier(i, b); | ||||
| 				loadToIt (dump2, buf, it, 3); //crop comment | ||||
| 			} | ||||
| 		} | ||||
| @@ -654,20 +658,33 @@ void CCreatureHandler::loadCreatures() | ||||
| 		{ | ||||
| 			loadToIt(creid, buf, it, 4); //get index | ||||
| 			b.id = creid; //id = this particular creature ID | ||||
| 			loadStackExp(b, buf, it); | ||||
| 			creatures[creid]->bonuses.push_back(new stackExperience(b)); //experience list is common for creatures of that type | ||||
| 			loadStackExp(b, creatures[creid]->bonuses, buf, it); //add directly to CCreature Node | ||||
| 			loadToIt (dump2, buf, it, 3); //crop comment | ||||
| 		} while (it < buf.size()); | ||||
|  | ||||
| //  		BOOST_FOREACH(CCreature *c, creatures) | ||||
| //  		{ | ||||
| //  			if (it = c->level < 7) | ||||
| //  				std::copy(commonBonuses[it-1].begin(), commonBonuses[it-1].end(), c->bonuses.begin()); | ||||
| //  			else | ||||
| //  				std::copy(commonBonuses[7].begin(), commonBonuses[7].end(), c->bonuses.begin()); //common for tiers 8+ | ||||
| //  		} | ||||
| 	} //end of stack experience | ||||
| 		//Calculate rank exp values, formula appears complicated bu no parsing needed | ||||
| 		expRanks.resize(8); | ||||
| 		int dif = 0; | ||||
| 		it = 8000; //ignore name of this variable | ||||
| 		expRanks[0].push_back(it); | ||||
| 		for (int j = 1; j < 10; ++j) //used for tiers 8-10, and all other probably | ||||
| 		{ | ||||
| 			expRanks[0].push_back(expRanks[0][j-1] + dif); | ||||
| 			dif += it/5; | ||||
| 		} | ||||
| 		for (int i = 1; i < 8; ++i) | ||||
| 		{ | ||||
| 			dif = 0; | ||||
| 			it = 1000 * i; | ||||
| 			expRanks[i].push_back(it); | ||||
| 			for (int j = 1; j < 10; ++j) | ||||
| 			{ | ||||
| 				expRanks[i].push_back(expRanks[i][j-1] + dif); | ||||
| 				dif += it/5; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 	}//end of Stack Experience | ||||
| 	//experiment - add 100 to attack for creatures of tier 1 | ||||
| // 	Bonus *b = new Bonus(Bonus::PERMANENT, Bonus::PRIMARY_SKILL, Bonus::OTHER, +100, 0, 0); | ||||
| // 	addBonusForTier(1, b); | ||||
| @@ -743,15 +760,18 @@ void CCreatureHandler::loadUnitAnimInfo(CCreature & unit, std::string & src, int | ||||
| 	i+=2; | ||||
| } | ||||
|  | ||||
| void CCreatureHandler::loadStackExp(stackExperience & b, std::string & src, int & it) //help function for parsing CREXPBON.txt, assuming all its details are already defined | ||||
| { | ||||
| void CCreatureHandler::loadStackExp(Bonus & b, BonusList & bl, std::string & src, int & it) //help function for parsing CREXPBON.txt | ||||
| { //TODO: handle rank limiters | ||||
| 	std::string buf, mod; | ||||
| 	bool enable = false; //some bonuses are activated with values 2 or 1 | ||||
| 	loadToIt(buf, src, it, 4); | ||||
| 	loadToIt(mod, src, it, 4); | ||||
|  | ||||
| 	switch (buf[0]) | ||||
| 	{ | ||||
| 	case 'H': | ||||
| 		b.type = Bonus::STACK_HEALTH; | ||||
| 		b.valType = Bonus::PERCENT_TO_BASE; | ||||
| 		break; | ||||
| 	case 'A': | ||||
| 		b.type = Bonus::PRIMARY_SKILL; | ||||
| @@ -784,7 +804,7 @@ void CCreatureHandler::loadStackExp(stackExperience & b, std::string & src, int | ||||
| 		b.type = Bonus::ADDITIONAL_RETALIATION; break; | ||||
|  | ||||
| 	case 'f': //on-off skill | ||||
| 		b.enable = true; //sometimes format is: 2 -> 0, 1 -> 1 | ||||
| 		enable = true; //sometimes format is: 2 -> 0, 1 -> 1 | ||||
| 		switch (mod[0]) | ||||
| 		{ | ||||
| 			case 'A': | ||||
| @@ -808,7 +828,7 @@ void CCreatureHandler::loadStackExp(stackExperience & b, std::string & src, int | ||||
| 			case 'p': //Mind spells | ||||
| 			case 'P': | ||||
| 				{ | ||||
| 					loadMindImmunity(b, src, it); | ||||
| 					loadMindImmunity(b, bl, src, it); | ||||
| 					return; | ||||
| 				} | ||||
| 				return; | ||||
| @@ -829,7 +849,7 @@ void CCreatureHandler::loadStackExp(stackExperience & b, std::string & src, int | ||||
| 		} | ||||
| 		break; | ||||
| 	case 'w': //specific spell immunities, enabled/disabled | ||||
| 		b.enable = true; | ||||
| 		enable = true; | ||||
| 		switch (mod[0]) | ||||
| 		{ | ||||
| 			case 'B': //Blind | ||||
| @@ -877,11 +897,11 @@ void CCreatureHandler::loadStackExp(stackExperience & b, std::string & src, int | ||||
| 		break; | ||||
|  | ||||
| 	case 'i': | ||||
| 		b.enable = true; | ||||
| 		enable = true; | ||||
| 		b.type = Bonus::NO_DISTANCE_PENALTY; | ||||
| 		break; | ||||
| 	case 'o': | ||||
| 		b.enable = true; | ||||
| 		enable = true; | ||||
| 		b.type = Bonus::NO_OBSTACLES_PENALTY; | ||||
| 		break; | ||||
|  | ||||
| @@ -902,28 +922,51 @@ void CCreatureHandler::loadStackExp(stackExperience & b, std::string & src, int | ||||
| 	{ | ||||
| 		case '+': | ||||
| 		case '=': //should we allow percent values to stack or pick highest? | ||||
| 			b.valType = Bonus::BASE_NUMBER; | ||||
| 			b.valType = Bonus::ADDITIVE_VALUE; | ||||
| 			break; | ||||
| 	} | ||||
| 	loadToIt (b.val, src, it, 4); //basic value, not particularly useful but existent | ||||
| 	for (int i = 0; i < 10; ++i) | ||||
|  | ||||
| 	//limiters, range | ||||
| 	si32 lastVal, curVal, lastLev = 0; | ||||
|  | ||||
| 	if (enable) //0 and 2 means non-active, 1 - active | ||||
| 	{ | ||||
| 		loadToIt (b.expBonuses[i], src, it, 4); //vector must have length 10 | ||||
| 	} | ||||
| 	if (b.enable) //switch 2 to 0 | ||||
| 	{ | ||||
| 		if (b.val == 2) | ||||
| 			b.val = 0; | ||||
| 		for (int i = 0; i < 10; ++i) | ||||
| 		b.val = 0; //on-off ability, no value specified | ||||
| 		loadToIt (curVal, src, it, 4); // 0 level is never active | ||||
| 		for (int i = 1; i < 11; ++i) | ||||
| 		{ | ||||
| 			if (b.expBonuses[i] == 2) | ||||
| 				b.expBonuses[i] = 0; | ||||
| 			else break; //higher levels are rarely disabled? | ||||
| 			loadToIt (curVal, src, it, 4); | ||||
| 			if (curVal == 1) | ||||
| 			{ | ||||
| 				b.limiter.reset (new ExpRankLimiter(i)); | ||||
| 				bl.push_back(new Bonus(b)); | ||||
| 				break; //never turned off it seems | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		loadToIt (lastVal, src, it, 4); //basic value, not particularly useful but existent | ||||
| 		for (int i = 1; i < 11; ++i) | ||||
| 		{ | ||||
| 			loadToIt (curVal, src, it, 4); | ||||
| 			if (curVal > lastVal) //threshold, add last bonus | ||||
| 			{ | ||||
| 				b.val = lastVal; | ||||
| 				b.limiter.reset (new ExpRankLimiter(i)); | ||||
| 				bl.push_back(new Bonus(b)); | ||||
| 				lastLev = i; //start new range from here, i = previous rank | ||||
| 			} | ||||
| 			else if (curVal < lastVal) | ||||
| 			{ | ||||
| 				b.val = lastVal; | ||||
| 				b.limiter.reset (new RankRangeLimiter(lastLev, i)); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CCreatureHandler::loadMindImmunity(stackExperience & b, std::string & src, int & it) | ||||
| void CCreatureHandler::loadMindImmunity(Bonus & b, BonusList & bl, std::string & src, int & it) | ||||
| { | ||||
| 	CCreature * cre = creatures[b.id]; //odd workaround | ||||
|  | ||||
| @@ -944,7 +987,7 @@ void CCreatureHandler::loadMindImmunity(stackExperience & b, std::string & src, | ||||
| 	for (int g=0; g < mindSpells.size(); ++g) | ||||
| 	{ | ||||
| 		b.subtype = mindSpells[g]; | ||||
| 		cre->bonuses.push_back(new stackExperience(b)); | ||||
| 		cre->bonuses.push_back(new Bonus(b)); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -99,7 +99,8 @@ public: | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT CCreatureHandler | ||||
| {	 | ||||
| { | ||||
| private: //? | ||||
| 	CBonusSystemNode allCreatures, creaturesOfLevel[CREATURES_PER_TOWN + 1];//index 0 is used for creatures of unknown tier or outside <1-7> range | ||||
| public: | ||||
| 	std::set<int> notUsedMonsters; | ||||
| @@ -112,13 +113,13 @@ public: | ||||
| 	int factionToTurretCreature[F_NUMBER]; //which creature's animation should be used to dispaly creature in turret while siege | ||||
|  | ||||
| 	std::map<TBonusType, std::pair<std::string, std::string> > stackBonuses; // bonus => name, description | ||||
| 	std::vector<BonusList> commonBonuses; // levels 1-8 from CREXPBON.txt | ||||
| 	std::vector<std::vector<ui32>> expRanks; // stack experience needed for certain rank, index 0 for other tiers (?) | ||||
|  | ||||
| 	void loadCreatures(); | ||||
| 	void loadAnimationInfo(); | ||||
| 	void loadUnitAnimInfo(CCreature & unit, std::string & src, int & i); | ||||
| 	void loadStackExp(stackExperience & b, std::string & src, int & it); | ||||
| 	void loadMindImmunity(stackExperience & b, std::string & src, int & it); //multiple bonuses at once | ||||
| 	void loadStackExp(Bonus & b, BonusList & bl, std::string & src, int & it); | ||||
| 	void loadMindImmunity(Bonus & b, BonusList & bl, std::string & src, int & it); //multiple bonuses at once | ||||
| 	int stringToNumber(std::string & s);//help function for parsing CREXPBON.txt | ||||
|  | ||||
| 	bool isGood (si8 faction) const; | ||||
|   | ||||
| @@ -430,6 +430,29 @@ int CStackInstance::getQuantityID() const | ||||
| 	return CCreature::getQuantityID(count); | ||||
| } | ||||
|  | ||||
| int CStackInstance::getExpRank() const | ||||
| { | ||||
| 	int tier = type->level; | ||||
| 	if (isbetw(tier, 1, 7)) | ||||
| 	{ | ||||
| 		for (int i = VLC->creh->expRanks[tier].size()-2; i >-1; --i)//sic! | ||||
| 		{ //exp values vary from 1st level to max exp at 11th level | ||||
| 			if (experience >= VLC->creh->expRanks[tier][i]) | ||||
| 				return ++i; //faster, but confusing - 0 index mean 1st level of experience | ||||
| 		} | ||||
| 		return 0; | ||||
| 	} | ||||
| 	else //higher tier | ||||
| 	{ | ||||
| 		for (int i = VLC->creh->expRanks[tier].size()-2; i >-1; --i) | ||||
| 		{ | ||||
| 			if (experience >= VLC->creh->expRanks[0][i]) | ||||
| 				return ++i; | ||||
| 		} | ||||
| 		return 0; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CStackInstance::setType(int creID) | ||||
| { | ||||
| 	setType(VLC->creh->creatures[creID]); | ||||
|   | ||||
| @@ -49,6 +49,7 @@ public: | ||||
|  | ||||
| 	int getQuantityID() const; | ||||
| 	std::string getQuantityTXT(bool capitalized = true) const; | ||||
| 	int getExpRank() const; | ||||
| 	void init(); | ||||
| 	CStackInstance(); | ||||
| 	CStackInstance(TCreature id, TQuantity count); | ||||
|   | ||||
| @@ -771,4 +771,14 @@ bool CreatureAlignmentLimiter::limit(const Bonus *b, const CBonusSystemNode &nod | ||||
| 		tlog1 << "Warning: illegal alignment in limiter!\n"; | ||||
| 		return true; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| ExpRankLimiter::ExpRankLimiter(ui8 Rank) | ||||
| 	:rank(Rank) | ||||
| { | ||||
| } | ||||
|  | ||||
| RankRangeLimiter::RankRangeLimiter(ui8 Min, ui8 Max) | ||||
| 	:min(Min), max(Max) | ||||
| { | ||||
| } | ||||
| @@ -304,18 +304,6 @@ struct DLL_EXPORT Bonus | ||||
| 	Bonus *addLimiter(ILimiter *Limiter); //returns this for convenient chain-calls | ||||
| }; | ||||
|  | ||||
| struct DLL_EXPORT stackExperience : public Bonus | ||||
| { | ||||
| 	std::vector<si32> expBonuses; // variations for levels 1-10, copied to val field; | ||||
| 	bool enable; //if true - turns ability on / off for zero value | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| 		h & static_cast<Bonus&>(this); | ||||
| 		h & expBonuses & enable; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| DLL_EXPORT std::ostream & operator<<(std::ostream &out, const Bonus &bonus); | ||||
|  | ||||
| class BonusList : public std::list<Bonus*> | ||||
| @@ -630,6 +618,32 @@ public: | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT ExpRankLimiter : public ILimiter //applies to creatures with Rank >= rank | ||||
| { | ||||
| public: | ||||
| 	ui8 rank; | ||||
|  | ||||
| 	ExpRankLimiter(ui8 Rank); | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| 		h & rank; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT RankRangeLimiter : public ILimiter //applies to creatures with min <= Rank <= max | ||||
| { | ||||
| public: | ||||
| 	ui8 min, max; | ||||
|  | ||||
| 	RankRangeLimiter(ui8 Min, ui8 Max); | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| 		h & min & max; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| const CCreature *retrieveCreature(const CBonusSystemNode *node); | ||||
|  | ||||
| namespace Selector | ||||
|   | ||||
		Reference in New Issue
	
	Block a user