mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Support for overriding victory/defeat conditions from h3m map or
campaign: - new file MapFormatJson that implements small subset of Json map format, as described on wiki - vcmi will read overrides from file config/mapOverrides.json (currently empty) - Json writer for logical expressions TODO: write data for map overrides
This commit is contained in:
		
							
								
								
									
										171
									
								
								lib/mapping/MapFormatJson.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										171
									
								
								lib/mapping/MapFormatJson.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,171 @@ | ||||
| /* | ||||
| * MapFormatJson.cpp, part of VCMI engine | ||||
| * | ||||
| * Authors: listed in file AUTHORS in main folder | ||||
| * | ||||
| * License: GNU General Public License v2.0 or later | ||||
| * Full text of license available in license.txt file, in main folder | ||||
| * | ||||
| */ | ||||
|  | ||||
| #include "StdInc.h" | ||||
| #include "MapFormatJson.h" | ||||
|  | ||||
| #include "CMap.h" | ||||
| #include "../CModHandler.h" | ||||
| #include "../VCMI_Lib.h" | ||||
|  | ||||
| static const std::string conditionNames[] = { | ||||
| "haveArtifact", "haveCreatures", "haveResources",   "haveBuilding", | ||||
| "control",      "destroy",       "transport", | ||||
| "daysPassed",   "isHuman",       "daysWithoutTown", "standardWin" | ||||
| }; | ||||
|  | ||||
| static const std::string typeNames[] = { "victory", "defeat" }; | ||||
|  | ||||
| CMapLoaderJson::CMapLoaderJson(JsonNode stream): | ||||
| 	input(stream) | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| std::unique_ptr<CMap> CMapLoaderJson::loadMap() | ||||
| { | ||||
| 	map = new CMap(); | ||||
| 	mapHeader.reset(map); | ||||
| 	readMap(); | ||||
| 	mapHeader.reset(); | ||||
| 	return std::unique_ptr<CMap>(map); | ||||
| } | ||||
|  | ||||
| std::unique_ptr<CMapHeader> CMapLoaderJson::loadMapHeader() | ||||
| { | ||||
| 	mapHeader.reset(new CMapHeader); | ||||
| 	readHeader(); | ||||
| 	return std::move(mapHeader); | ||||
| } | ||||
|  | ||||
| /* | ||||
| 	//This code can be used to write map header to console or file in its Json representation | ||||
|  | ||||
| 	JsonNode out; | ||||
| 	JsonNode data; | ||||
| 	data["victoryString"].String() = mapHeader->victoryMessage; | ||||
| 	data["defeatString"].String() = mapHeader->defeatMessage; | ||||
|  | ||||
| 	data["victoryIconIndex"].Float() = mapHeader->victoryIconIndex; | ||||
| 	data["defeatIconIndex"].Float() = mapHeader->defeatIconIndex; | ||||
|  | ||||
| 	for (const TriggeredEvent & entry : mapHeader->triggeredEvents) | ||||
| 	{ | ||||
| 		JsonNode event; | ||||
| 		event["message"].String() = entry.onFulfill; | ||||
| 		event["effect"]["messageToSend"].String() = entry.effect.toOtherMessage; | ||||
| 		event["effect"]["type"].String() = typeNames[entry.effect.type]; | ||||
| 		event["condition"] = entry.trigger.toJson(eventToJson); | ||||
| 		data["triggeredEvents"][entry.identifier] = event; | ||||
| 	} | ||||
|  | ||||
| 	out[mapHeader->name] = data; | ||||
| 	logGlobal->errorStream() << out; | ||||
|  | ||||
| JsonNode eventToJson(const EventCondition & cond) | ||||
| { | ||||
| 	JsonNode ret; | ||||
| 	ret.Vector().resize(2); | ||||
| 	ret.Vector()[0].String() = conditionNames[size_t(cond.condition)]; | ||||
| 	JsonNode & data = ret.Vector()[1]; | ||||
| 	data["type"].Float() = cond.objectType; | ||||
| 	data["value"].Float() = cond.value; | ||||
| 	data["position"].Vector().resize(3); | ||||
| 	data["position"].Vector()[0].Float() = cond.position.x; | ||||
| 	data["position"].Vector()[1].Float() = cond.position.y; | ||||
| 	data["position"].Vector()[2].Float() = cond.position.z; | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
| */ | ||||
| void CMapLoaderJson::patchMapHeader(std::unique_ptr<CMapHeader> & header) | ||||
| { | ||||
| 	header.swap(mapHeader); | ||||
| 	if (!input.isNull()) | ||||
| 		readPatchData(); | ||||
| 	header.swap(mapHeader); | ||||
| } | ||||
|  | ||||
| void CMapLoaderJson::readMap() | ||||
| { | ||||
| 	readHeader(); | ||||
| 	assert(0); // Not implemented, vcmi does not have its own map format right now | ||||
| } | ||||
|  | ||||
| void CMapLoaderJson::readHeader() | ||||
| { | ||||
| 	//TODO: read such data like map name & size | ||||
| 	readPatchData(); | ||||
| 	readPlayerInfo(); | ||||
| 	assert(0); // Not implemented | ||||
| } | ||||
|  | ||||
| void CMapLoaderJson::readPatchData() | ||||
| { | ||||
| 	mapHeader->victoryMessage = input["victoryString"].String(); | ||||
| 	mapHeader->victoryIconIndex = input["victoryIconIndex"].Float(); | ||||
|  | ||||
| 	mapHeader->defeatMessage = input["defeatString"].String(); | ||||
| 	mapHeader->defeatIconIndex = input["defeatIconIndex"].Float(); | ||||
|  | ||||
| 	readTriggeredEvents(); | ||||
| } | ||||
|  | ||||
| void CMapLoaderJson::readTriggeredEvents() | ||||
| { | ||||
| 	mapHeader->triggeredEvents.clear(); | ||||
|  | ||||
| 	for (auto & entry : input["triggeredEvents"].Struct()) | ||||
| 	{ | ||||
| 		TriggeredEvent event; | ||||
| 		event.identifier = entry.first; | ||||
| 		readTriggeredEvent(event, entry.second); | ||||
| 		mapHeader->triggeredEvents.push_back(event); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static EventCondition JsonToCondition(const JsonNode & node) | ||||
| { | ||||
| 	EventCondition event; | ||||
| 	event.condition = EventCondition::EWinLoseType(vstd::find_pos(conditionNames, node.Vector()[0].String())); | ||||
| 	if (node.Vector().size() > 1) | ||||
| 	{ | ||||
| 		const JsonNode & data = node.Vector()[1]; | ||||
| 		if (data["type"].getType() == JsonNode::DATA_STRING) | ||||
| 			event.objectType = VLC->modh->identifiers.getIdentifier(data["type"]).get(); | ||||
| 		if (data["type"].getType() == JsonNode::DATA_FLOAT) | ||||
| 			event.objectType = data["type"].Float(); | ||||
|  | ||||
| 		if (!data["value"].isNull()) | ||||
| 			event.value = data["value"].Float(); | ||||
|  | ||||
| 		if (!data["position"].isNull()) | ||||
| 		{ | ||||
| 			event.position.x = data["position"].Vector()[0].Float(); | ||||
| 			event.position.y = data["position"].Vector()[1].Float(); | ||||
| 			event.position.z = data["position"].Vector()[2].Float(); | ||||
| 		} | ||||
| 	} | ||||
| 	return event; | ||||
| } | ||||
|  | ||||
| void CMapLoaderJson::readTriggeredEvent(TriggeredEvent & event, const JsonNode & source) | ||||
| { | ||||
| 	event.onFulfill = source["message"].String(); | ||||
| 	event.description = source["description"].String(); | ||||
| 	event.effect.type = vstd::find_pos(typeNames, source["effect"]["type"].String()); | ||||
| 	event.effect.toOtherMessage = source["effect"]["messageToSend"].String(); | ||||
| 	event.trigger = EventExpression(source["condition"], JsonToCondition); // logical expression | ||||
| } | ||||
|  | ||||
| void CMapLoaderJson::readPlayerInfo() | ||||
| { | ||||
| 	assert(0); // Not implemented | ||||
| } | ||||
		Reference in New Issue
	
	Block a user