mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Fixed Duel mode. Integrated some changes from programmingChallenge branch - it's possible to define duel parameters using JSON.
This commit is contained in:
		| @@ -848,56 +848,8 @@ void CGameState::init(StartInfo * si) | ||||
| 		} | ||||
| 		break; | ||||
| 	case StartInfo::DUEL: | ||||
| 		{ | ||||
| 			DuelParameters dp; | ||||
| 			try | ||||
| 			{ | ||||
| 				CLoadFile lf(scenarioOps->mapname); | ||||
| 				lf >> dp; | ||||
| 			} | ||||
| 			catch(...) | ||||
| 			{} | ||||
|  | ||||
|  | ||||
| 			const CArmedInstance *armies[2] = {0}; | ||||
| 			const CGHeroInstance *heroes[2] = {0}; | ||||
| 			CGTownInstance *town = NULL; | ||||
|  | ||||
| 			for(int i = 0; i < 2; i++) | ||||
| 			{ | ||||
| 				CArmedInstance *obj = NULL; | ||||
| 				if(dp.sides[i].heroId >= 0) | ||||
| 				{ | ||||
| 					CGHeroInstance *h = new CGHeroInstance(); | ||||
| 					armies[i] = heroes[i] = h; | ||||
| 					obj = h; | ||||
| 					h->subID = dp.sides[i].heroId; | ||||
| 					h->initHero(h->subID); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					CGCreature *c = new CGCreature(); | ||||
| 					armies[i] = obj = c; | ||||
| 					c->subID = 34; | ||||
|  | ||||
| 				} | ||||
|  | ||||
| 				obj->initObj(); | ||||
| 				obj->setOwner(i); | ||||
|  | ||||
| 				for(int j = 0; j < ARRAY_COUNT(dp.sides[i].stacks); j++) | ||||
| 				{ | ||||
| 					int cre = dp.sides[i].stacks[j].type, count = dp.sides[i].stacks[j].count; | ||||
| 					if(count || obj->hasStackAtSlot(j)) | ||||
| 						obj->setCreature(j, cre, count); | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			curB = BattleInfo::setupBattle(int3(), dp.bfieldType, dp.terType, armies, heroes, false, town); | ||||
| 			curB->localInit(); | ||||
| 			return; | ||||
| 		} | ||||
| 		break; | ||||
| 		initDuel(); | ||||
| 		return; | ||||
| 	default: | ||||
| 		tlog1 << "Wrong mode: " << (int)scenarioOps->mode << std::endl; | ||||
| 		return; | ||||
| @@ -1527,6 +1479,108 @@ void CGameState::init(StartInfo * si) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CGameState::initDuel() | ||||
| { | ||||
| 	DuelParameters dp; | ||||
| 	try //CLoadFile likes throwing | ||||
| 	{ | ||||
| 		if(boost::algorithm::ends_with(scenarioOps->mapname, ".json")) | ||||
| 		{ | ||||
| 			tlog0 << "Loading duel settings from JSON file: " << scenarioOps->mapname << std::endl; | ||||
| 			dp = DuelParameters::fromJSON(scenarioOps->mapname); | ||||
| 			tlog0 << "JSON file has been successfully read!\n"; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			CLoadFile lf(scenarioOps->mapname); | ||||
| 			lf >> dp; | ||||
| 		} | ||||
| 	} | ||||
| 	catch(...) | ||||
| 	{ | ||||
| 		tlog1 << "Cannot load duel settings from " << scenarioOps->mapname << std::endl; | ||||
| 		throw; | ||||
| 	} | ||||
|  | ||||
| 	const CArmedInstance *armies[2] = {0}; | ||||
| 	const CGHeroInstance *heroes[2] = {0}; | ||||
| 	CGTownInstance *town = NULL; | ||||
|  | ||||
| 	for(int i = 0; i < 2; i++) | ||||
| 	{ | ||||
| 		CArmedInstance *obj = NULL; | ||||
| 		if(dp.sides[i].heroId >= 0) | ||||
| 		{ | ||||
| 			const DuelParameters::SideSettings &ss = dp.sides[i]; | ||||
| 			CGHeroInstance *h = new CGHeroInstance(); | ||||
| 			armies[i] = heroes[i] = h; | ||||
| 			obj = h; | ||||
| 			h->subID = ss.heroId; | ||||
| 			for(int i = 0; i < ss.heroPrimSkills.size(); i++) | ||||
| 				h->pushPrimSkill(i, ss.heroPrimSkills[i]); | ||||
|  | ||||
| 			if(ss.spells.size()) | ||||
| 			{ | ||||
| 				h->putArtifact(ArtifactPosition::SPELLBOOK, CArtifactInstance::createNewArtifactInstance(0)); | ||||
| 				boost::copy(ss.spells, std::inserter(h->spells, h->spells.begin())); | ||||
| 			} | ||||
|  | ||||
| 			BOOST_FOREACH(auto &parka, ss.artifacts) | ||||
| 			{ | ||||
| 				h->putArtifact(parka.first, parka.second); | ||||
| 			} | ||||
|  | ||||
| 			typedef const std::pair<si32, si8> &TSecSKill; | ||||
| 			BOOST_FOREACH(TSecSKill secSkill, ss.heroSecSkills) | ||||
| 				h->setSecSkillLevel((CGHeroInstance::SecondarySkill)secSkill.first, secSkill.second, 1); | ||||
|  | ||||
| 			h->initHero(h->subID); | ||||
| 			obj->initObj(); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			CGCreature *c = new CGCreature(); | ||||
| 			armies[i] = obj = c; | ||||
| 			//c->subID = 34; | ||||
| 		} | ||||
|  | ||||
| 		obj->setOwner(i); | ||||
|  | ||||
| 		for(int j = 0; j < ARRAY_COUNT(dp.sides[i].stacks); j++) | ||||
| 		{ | ||||
| 			TCreature cre = dp.sides[i].stacks[j].type; | ||||
| 			TQuantity count = dp.sides[i].stacks[j].count; | ||||
| 			if(count || obj->hasStackAtSlot(j)) | ||||
| 				obj->setCreature(j, cre, count); | ||||
| 		} | ||||
|  | ||||
| 		BOOST_FOREACH(const DuelParameters::CusomCreature &cc, dp.creatures) | ||||
| 		{ | ||||
| 			CCreature *c = VLC->creh->creatures[cc.id]; | ||||
| 			if(cc.attack >= 0) | ||||
| 				c->getBonus(Selector::typeSubtype(Bonus::PRIMARY_SKILL, PrimarySkill::ATTACK))->val = cc.attack; | ||||
| 			if(cc.defense >= 0) | ||||
| 				c->getBonus(Selector::typeSubtype(Bonus::PRIMARY_SKILL, PrimarySkill::DEFENSE))->val = cc.defense; | ||||
| 			if(cc.speed >= 0) | ||||
| 				c->getBonus(Selector::type(Bonus::STACKS_SPEED))->val = cc.speed; | ||||
| 			if(cc.HP >= 0) | ||||
| 				c->getBonus(Selector::type(Bonus::STACK_HEALTH))->val = cc.HP; | ||||
| 			if(cc.dmg >= 0) | ||||
| 			{ | ||||
| 				c->getBonus(Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 1))->val = cc.dmg; | ||||
| 				c->getBonus(Selector::typeSubtype(Bonus::CREATURE_DAMAGE, 2))->val = cc.dmg; | ||||
| 			} | ||||
| 			if(cc.shoots >= 0) | ||||
| 				c->getBonus(Selector::type(Bonus::SHOTS))->val = cc.shoots; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	curB = BattleInfo::setupBattle(int3(), dp.bfieldType, dp.terType, armies, heroes, false, town); | ||||
| 	curB->obstacles = dp.obstacles; | ||||
| 	curB->localInit(); | ||||
| 	return; | ||||
| } | ||||
|  | ||||
| int CGameState::battleGetBattlefieldType(int3 tile) const | ||||
| { | ||||
| 	if(tile==int3() && curB) | ||||
| @@ -2723,6 +2777,88 @@ DuelParameters::DuelParameters() | ||||
| 	bfieldType = 15; | ||||
| } | ||||
|  | ||||
| DuelParameters DuelParameters::fromJSON(const std::string &fname) | ||||
| { | ||||
| 	DuelParameters ret; | ||||
|  | ||||
| 	const JsonNode duelData(fname); | ||||
| 	ret.terType = duelData["terType"].Float(); | ||||
| 	ret.bfieldType = duelData["bfieldType"].Float(); | ||||
| 	BOOST_FOREACH(const JsonNode &n, duelData["sides"].Vector()) | ||||
| 	{ | ||||
| 		SideSettings &ss = ret.sides[(int)n["side"].Float()]; | ||||
| 		int i = 0; | ||||
| 		BOOST_FOREACH(const JsonNode &stackNode, n["army"].Vector()) | ||||
| 		{ | ||||
| 			ss.stacks[i].type = stackNode.Vector()[0].Float(); | ||||
| 			ss.stacks[i].count = stackNode.Vector()[1].Float(); | ||||
| 			i++; | ||||
| 		} | ||||
|  | ||||
| 		if(n["heroid"].getType() == JsonNode::DATA_FLOAT) | ||||
| 			ss.heroId = n["heroid"].Float(); | ||||
| 		else | ||||
| 			ss.heroId = -1; | ||||
|  | ||||
| 		BOOST_FOREACH(const JsonNode &n, n["heroPrimSkills"].Vector()) | ||||
| 			ss.heroPrimSkills.push_back(n.Float()); | ||||
|  | ||||
| 		BOOST_FOREACH(const JsonNode &skillNode, n["heroSecSkills"].Vector()) | ||||
| 		{ | ||||
| 			std::pair<si32, si8> secSkill; | ||||
| 			secSkill.first = skillNode.Vector()[0].Float(); | ||||
| 			secSkill.second = skillNode.Vector()[1].Float(); | ||||
| 			ss.heroSecSkills.push_back(secSkill); | ||||
| 		} | ||||
|  | ||||
| 		assert(ss.heroPrimSkills.empty() || ss.heroPrimSkills.size() == GameConstants::PRIMARY_SKILLS); | ||||
|  | ||||
| 		if(ss.heroId != -1) | ||||
| 			BOOST_FOREACH(const JsonNode &spell, n["spells"].Vector()) | ||||
| 				ss.spells.insert(spell.Float()); | ||||
| 	} | ||||
|  | ||||
| 	BOOST_FOREACH(const JsonNode &n, duelData["obstacles"].Vector()) | ||||
| 	{ | ||||
| 		auto oi = make_shared<CObstacleInstance>(); | ||||
| 		if(n.getType() == JsonNode::DATA_VECTOR) | ||||
| 		{ | ||||
| 			oi->ID = n.Vector()[0].Float(); | ||||
| 			oi->pos = n.Vector()[1].Float(); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			assert(n.getType() == JsonNode::DATA_FLOAT); | ||||
| 			oi->ID = 21; | ||||
| 			oi->pos = n.Float(); | ||||
| 		} | ||||
| 		oi->uniqueID = ret.obstacles.size(); | ||||
| 		ret.obstacles.push_back(oi); | ||||
| 	} | ||||
|  | ||||
| 	BOOST_FOREACH(const JsonNode &n, duelData["creatures"].Vector()) | ||||
| 	{ | ||||
| 		CusomCreature cc; | ||||
| 		cc.id = n["id"].Float(); | ||||
|  | ||||
| #define retreive(name)								\ | ||||
| 	if(n[ #name ].getType() == JsonNode::DATA_FLOAT)\ | ||||
| 	cc.name = n[ #name ].Float();			\ | ||||
| 	else											\ | ||||
| 	cc.name = -1; | ||||
|  | ||||
| 		retreive(attack); | ||||
| 		retreive(defense); | ||||
| 		retreive(HP); | ||||
| 		retreive(dmg); | ||||
| 		retreive(shoots); | ||||
| 		retreive(speed); | ||||
| 		ret.creatures.push_back(cc); | ||||
| 	} | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| TeamState::TeamState() | ||||
| { | ||||
| 	setNodeType(TEAM); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user