Browse Source

- Fixed some warnings from cppcheck
- Minor improvements to JSON validation
- Cleanup in SDL_Extensions.cpp
- Implemented new propery for creature format: idle animation duration
- Disabled idle animation of some of conflux creatures (was clearly
broken)

Ivan Savenko 12 years ago
parent
commit
71d6b0fea9

+ 3 - 3
client/Graphics.cpp

@@ -176,7 +176,7 @@ CDefEssential * Graphics::loadHeroAnim( const std::string &name, const std::vect
 				for(int e=0; e<8; ++e)
 				{
 					Cimage nci;
-					nci.bitmap = CSDL_Ext::rotate01(anim->ourImages[o+e].bitmap);
+					nci.bitmap = CSDL_Ext::verticalFlip(anim->ourImages[o+e].bitmap);
 					nci.groupNumber = rotations[p].second;
 					nci.imName = std::string();
 					anim->ourImages.push_back(nci);
@@ -218,7 +218,7 @@ void Graphics::loadHeroFlagsDetail(std::pair<std::vector<CDefEssential *> Graphi
 					for(int e=0; e<8; ++e)
 					{
 						Cimage nci;
-						nci.bitmap = CSDL_Ext::rotate01(curImgs[o+e].bitmap);
+						nci.bitmap = CSDL_Ext::verticalFlip(curImgs[o+e].bitmap);
 						nci.groupNumber = rotation.second;
 						nci.imName = std::string();
 						curImgs.push_back(nci);
@@ -236,7 +236,7 @@ void Graphics::loadHeroFlagsDetail(std::pair<std::vector<CDefEssential *> Graphi
 					for(int e=0; e<8; ++e)
 					{
 						Cimage nci;
-						nci.bitmap = CSDL_Ext::rotate01(curImgs[o+e].bitmap);
+						nci.bitmap = CSDL_Ext::verticalFlip(curImgs[o+e].bitmap);
 						nci.groupNumber = 12 + curImgs[o].groupNumber;
 						nci.imName = std::string();
 						curImgs.push_back(nci);

+ 5 - 7
client/battle/CBattleInterface.cpp

@@ -1336,10 +1336,10 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
 
 	//displaying message in console
 	bool customSpell = false;
-	bool plural = false; //add singular / plural form of creature text if this is true
-	int textID = 0;
 	if(sc->affectedCres.size() == 1)
 	{
+		bool plural = false; //add singular / plural form of creature text if this is true
+		int textID = 0;
 		std::string text = CGI->generaltexth->allTexts[195];
 		if(sc->castedByHero)
 		{
@@ -1970,8 +1970,6 @@ void CBattleInterface::startAction(const BattleAction* action)
 
 	redraw(); // redraw after deactivation, including proper handling of hovered hexes
 
-	char txt[400];
-
 	if (action->actionType == Battle::HERO_SPELL) //when hero casts spell
 	{
 		if(action->side)
@@ -2006,8 +2004,8 @@ void CBattleInterface::startAction(const BattleAction* action)
 
 	if(txtid)
 	{
-		sprintf(txt, CGI->generaltexth->allTexts[txtid].c_str(),  (stack->count != 1) ? stack->getCreature()->namePl.c_str() : stack->getCreature()->nameSing.c_str(), 0);
-		console->addText(txt);
+		std::string name = (stack->count != 1) ? stack->getCreature()->namePl.c_str() : stack->getCreature()->nameSing.c_str();
+		console->addText((boost::format(CGI->generaltexth->allTexts[txtid].c_str()) % name).str());
 	}
 
 	//displaying special abilities
@@ -3186,7 +3184,7 @@ void CBattleInterface::showProjectiles(SDL_Surface * to)
 
 		if(it->reverse)
 		{
-			SDL_Surface * rev = CSDL_Ext::rotate01(image);
+			SDL_Surface * rev = CSDL_Ext::verticalFlip(image);
 			CSDL_Ext::blit8bppAlphaTo24bpp(rev, nullptr, to, &dst);
 			SDL_FreeSurface(rev);
 		}

+ 1 - 1
client/battle/CBattleInterfaceClasses.cpp

@@ -222,7 +222,7 @@ CBattleHero::CBattleHero(const std::string & defName, bool flipG, PlayerColor pl
 	{
 		if(flip)
 		{
-			SDL_Surface * hlp = CSDL_Ext::rotate01(elem.bitmap);
+			SDL_Surface * hlp = CSDL_Ext::verticalFlip(elem.bitmap);
 			SDL_FreeSurface(elem.bitmap);
 			elem.bitmap = hlp;
 		}

+ 5 - 2
client/battle/CCreatureAnimation.cpp

@@ -68,8 +68,9 @@ float AnimationControls::getCreatureAnimationSpeed(const CCreature * creature, c
 		return speed * 2 * creature->animation.walkAnimationTime / anim->framesInGroup(type);
 
 	case CCreatureAnim::MOUSEON:
-	case CCreatureAnim::HOLDING:
 		return baseSpeed;
+	case CCreatureAnim::HOLDING:
+		return baseSpeed * creature->animation.idleAnimationTime / anim->framesInGroup(type);
 
 	case CCreatureAnim::SHOOT_UP:
 	case CCreatureAnim::SHOOT_FRONT:
@@ -452,5 +453,7 @@ void CCreatureAnimation::pause()
 
 void CCreatureAnimation::play()
 {
-	speed = 1 / speedController(this, type);
+    speed = 0;
+    if (speedController(this, type) != 0)
+        speed = 1 / speedController(this, type);
 }

+ 30 - 72
client/gui/SDL_Extensions.cpp

@@ -62,96 +62,56 @@ void blitAt(SDL_Surface * src, const SDL_Rect & pos, SDL_Surface * dst)
 		blitAt(src,pos.x,pos.y,dst);
 }
 
-void updateRect (SDL_Rect * rect, SDL_Surface * scr)
-{
-	SDL_UpdateRect(scr,rect->x,rect->y,rect->w,rect->h);
-}
-
 // Vertical flip
-SDL_Surface * CSDL_Ext::rotate01(SDL_Surface * toRot)
+SDL_Surface * CSDL_Ext::verticalFlip(SDL_Surface * toRot)
 {
 	SDL_Surface * ret = SDL_ConvertSurface(toRot, toRot->format, toRot->flags);
-	const int bpl = ret->pitch;
 	const int bpp = ret->format->BytesPerPixel;
 
-	for(int i=0; i<ret->h; i++) {
-		char *src = (char *)toRot->pixels + i*bpl;
-		char *dst = (char *)ret->pixels + i*bpl;
-		for(int j=0; j<ret->w; j++) {
-			for (int k=0; k<bpp; k++) {
-				dst[j*bpp + k] = src[(ret->w-j-1)*bpp + k];
-			}
-		}
-	}
-
-	return ret;
-}
-
-// Horizontal flip
-SDL_Surface * CSDL_Ext::hFlip(SDL_Surface * toRot)
-{
-	SDL_Surface * ret = SDL_ConvertSurface(toRot, toRot->format, toRot->flags);
-	int bpl = ret->pitch;
-
-	for(int i=0; i<ret->h; i++) {
-		memcpy((char *)ret->pixels + i*bpl, (char *)toRot->pixels + (ret->h-i-1)*bpl, bpl);
-	}
+	char * src = reinterpret_cast<char *>(toRot->pixels);
+	char * dst = reinterpret_cast<char *>(ret->pixels);
 
-	return ret;
-};
-
-///**************/
-///Rotates toRot surface by 90 degrees left
-///**************/
-SDL_Surface * CSDL_Ext::rotate02(SDL_Surface * toRot)
-{
-	SDL_Surface * ret = SDL_ConvertSurface(toRot, toRot->format, toRot->flags);
-	//SDL_SetColorKey(ret, SDL_SRCCOLORKEY, toRot->format->colorkey);
-	for(int i=0; i<ret->w; ++i)
+	for(int i=0; i<ret->h; i++)
 	{
-		for(int j=0; j<ret->h; ++j)
+		char * srcPxl = src;
+		char * dstPxl = dst + ret->w * bpp;
+
+		if (bpp == 1)
+		{
+			// much faster for 8-bit surfaces (majority of our data)
+			std::reverse_copy(src, src + ret->pitch, dst);
+		}
+		else
 		{
+			for(int j=0; j<ret->w; j++)
 			{
-				Uint8 *p = (Uint8 *)toRot->pixels + i * toRot->pitch + j * toRot->format->BytesPerPixel;
-				SDL_PutPixelWithoutRefresh(ret, i, j, p[2], p[1], p[0]);
+				dstPxl -= bpp;
+				std::copy(srcPxl, srcPxl + bpp, dstPxl);
+				srcPxl += bpp;
 			}
 		}
+		src += toRot->pitch;
+		dst += ret->pitch;
 	}
 	return ret;
 }
 
-///*************/
-///Rotates toRot surface by 180 degrees
-///*************/
-SDL_Surface * CSDL_Ext::rotate03(SDL_Surface * toRot)
+// Horizontal flip
+SDL_Surface * CSDL_Ext::horizontalFlip(SDL_Surface * toRot)
 {
 	SDL_Surface * ret = SDL_ConvertSurface(toRot, toRot->format, toRot->flags);
-	if(ret->format->BytesPerPixel!=1)
-	{
-		for(int i=0; i<ret->w; ++i)
-		{
-			for(int j=0; j<ret->h; ++j)
-			{
-				{
-					Uint8 *p = (Uint8 *)toRot->pixels + (ret->h - j - 1) * toRot->pitch + (ret->w - i - 1) * toRot->format->BytesPerPixel+2;
-					SDL_PutPixelWithoutRefresh(ret, i, j, p[2], p[1], p[0], 0);
-				}
-			}
-		}
-	}
-	else
+	char * src = reinterpret_cast<char *>(toRot->pixels);
+	char * dst = reinterpret_cast<char *>(ret->pixels) + ret->h * ret->pitch;
+
+	for(int i=0; i<ret->h; i++)
 	{
-		for(int i=0; i<ret->w; ++i)
-		{
-			for(int j=0; j<ret->h; ++j)
-			{
-				Uint8 *p = (Uint8 *)toRot->pixels + (ret->h - j - 1) * toRot->pitch + (ret->w - i - 1) * toRot->format->BytesPerPixel;
-				(*((Uint8*)ret->pixels + j*ret->pitch + i*ret->format->BytesPerPixel)) = *p;
-			}
-		}
+		dst -= ret->pitch;
+		std::copy(src, src + toRot->pitch, dst);
+		src += toRot->pitch;
 	}
 	return ret;
-}
+};
+
 Uint32 CSDL_Ext::SDL_GetPixel(SDL_Surface *surface, const int & x, const int & y, bool colorByte)
 {
 	int bpp = surface->format->BytesPerPixel;
@@ -162,9 +122,7 @@ Uint32 CSDL_Ext::SDL_GetPixel(SDL_Surface *surface, const int & x, const int & y
 	{
 	case 1:
 		if(colorByte)
-		{
 			return colorToUint32(surface->format->palette->colors+(*p));
-		}
 		else
 			return *p;
 

+ 2 - 7
client/gui/SDL_Extensions.h

@@ -34,7 +34,6 @@ struct Rect;
 extern SDL_Surface * screen, *screen2, *screenBuf;
 void blitAt(SDL_Surface * src, int x, int y, SDL_Surface * dst=screen);
 void blitAt(SDL_Surface * src, const SDL_Rect & pos, SDL_Surface * dst=screen);
-void updateRect (SDL_Rect * rect, SDL_Surface * scr = screen);
 bool isItIn(const SDL_Rect * rect, int x, int y);
 
 /**
@@ -137,16 +136,12 @@ namespace CSDL_Ext
 	void SDL_PutPixelWithoutRefresh(SDL_Surface *ekran, const int & x, const int & y, const Uint8 & R, const Uint8 & G, const Uint8 & B, Uint8 A = 255);
 	void SDL_PutPixelWithoutRefreshIfInSurf(SDL_Surface *ekran, const int & x, const int & y, const Uint8 & R, const Uint8 & G, const Uint8 & B, Uint8 A = 255);
 
-	SDL_Surface * rotate01(SDL_Surface * toRot); //vertical flip
-	SDL_Surface * hFlip(SDL_Surface * toRot); //horizontal flip
-	SDL_Surface * rotate02(SDL_Surface * toRot); //rotate 90 degrees left
-	SDL_Surface * rotate03(SDL_Surface * toRot); //rotate 180 degrees
-	SDL_Cursor * SurfaceToCursor(SDL_Surface *image, int hx, int hy); //creates cursor from bitmap
+	SDL_Surface * verticalFlip(SDL_Surface * toRot); //vertical flip
+	SDL_Surface * horizontalFlip(SDL_Surface * toRot); //horizontal flip
 	Uint32 SDL_GetPixel(SDL_Surface *surface, const int & x, const int & y, bool colorByte = false);
 	void alphaTransform(SDL_Surface * src); //adds transparency and shadows (partial handling only; see examples of using for details)
 	bool isTransparent(SDL_Surface * srf, int x, int y); //checks if surface is transparent at given position
 
-
 	Uint8 *getPxPtr(const SDL_Surface * const &srf, const int x, const int y);
 	TColorPutter getPutterFor(SDL_Surface  * const &dest, int incrementing); //incrementing: -1, 0, 1
 	TColorPutterAlpha getPutterAlphaFor(SDL_Surface  * const &dest, int incrementing); //incrementing: -1, 0, 1

+ 1 - 1
client/mapHandler.cpp

@@ -104,7 +104,7 @@ void CMapHandler::prepareFOWDefs()
 	for(auto & elem : missRot)
 	{
 		nw = graphics->FoWpartialHide->ourImages[elem];
-		nw.bitmap = CSDL_Ext::rotate01(nw.bitmap);
+		nw.bitmap = CSDL_Ext::verticalFlip(nw.bitmap);
 		graphics->FoWpartialHide->ourImages.push_back(nw);
 	}
 	//necessaary rotations added

+ 32 - 0
config/creatures/conflux.json

@@ -36,6 +36,10 @@
 		"upgrades": ["stormElemental"],
 		"graphics" :
 		{
+			"animationTime" :
+			{
+				"idle" : 0
+			},
 			"animation": "CAELEM.DEF"
 		},
 		"sound" :
@@ -82,6 +86,10 @@
 		"upgrades": ["magmaElemental"],
 		"graphics" :
 		{
+			"animationTime" :
+			{
+				"idle" : 0
+			},
 			"animation": "CEELEM.DEF"
 		},
 		"sound" :
@@ -129,6 +137,10 @@
 		"upgrades": ["energyElemental"],
 		"graphics" :
 		{
+			"animationTime" :
+			{
+				"idle" : 0
+			},
 			"animation": "CFELEM.DEF"
 		},
 		"sound" :
@@ -195,6 +207,10 @@
 		"upgrades": ["iceElemental"],
 		"graphics" :
 		{
+			"animationTime" :
+			{
+				"idle" : 0
+			},
 			"animation": "CWELEM.DEF"
 		},
 		"sound" :
@@ -334,6 +350,10 @@
 		"graphics" :
 		{
 			"animation": "CICEE.DEF",
+			"animationTime" :
+			{
+				"idle" : 0
+			},
 			"missile" :
 			{
 				"projectile": "PICEE.DEF"
@@ -379,6 +399,10 @@
 		},
 		"graphics" :
 		{
+			"animationTime" :
+			{
+				"idle" : 0
+			},
 			"animation": "CSTONE.DEF"
 		},
 		"sound" :
@@ -420,6 +444,10 @@
 		},
 		"graphics" :
 		{
+			"animationTime" :
+			{
+				"idle" : 0
+			},
 			"animation": "CSTORM.DEF",
 			"missile" :
 			{
@@ -471,6 +499,10 @@
 		},
 		"graphics" :
 		{
+			"animationTime" :
+			{
+				"idle" : 0
+			},
 			"animation": "CNRG.DEF"
 		},
 		"sound" :

+ 5 - 1
config/schemas/creature.json

@@ -172,13 +172,17 @@
 				"animationTime": {
 					"type":"object",
 					"additionalProperties" : false,
-					"required" : [ "attack", "flight", "walk" ],
+					"required" : [ "attack", "flight", "walk", "idle" ],
 					"description": "Length of several animations",
 					"properties":{
 						"attack": {
 							"type":"number",
 							"description": "attack"
 						},
+						"idle": {
+							"type":"number",
+							"description": "idle"
+						},
 						"flight": {
 							"type":"number",
 							"description": "flight"

+ 7 - 6
lib/BattleAction.cpp

@@ -15,13 +15,14 @@
 
 using namespace Battle;
 
-BattleAction::BattleAction()
+BattleAction::BattleAction():
+	side(-1),
+	stackNumber(-1),
+	actionType(INVALID),
+	destinationTile(-1),
+	additionalInfo(-1),
+	selectedStack(-1)
 {
-	side = -1;
-	stackNumber = -1;
-	actionType = INVALID;
-	destinationTile = -1;
-	additionalInfo = -1;
 }
 
 BattleAction BattleAction::makeHeal(const CStack *healer, const CStack *healed)

+ 5 - 5
lib/BattleHex.cpp

@@ -19,19 +19,19 @@ BattleHex& BattleHex::moveInDir(EDir dir, bool hasToBeValid)
 	switch(dir)
 	{
 	case TOP_LEFT:
-		setXY(y%2 ? x-1 : x, y-1, hasToBeValid);
+		setXY((y%2) ? x-1 : x, y-1, hasToBeValid);
 		break;
 	case TOP_RIGHT:
-		setXY(y%2 ? x : x+1, y-1, hasToBeValid);
+		setXY((y%2) ? x : x+1, y-1, hasToBeValid);
 		break;
 	case RIGHT:
 		setXY(x+1, y, hasToBeValid);
 		break;
 	case BOTTOM_RIGHT:
-		setXY(y%2 ? x : x+1, y+1, hasToBeValid);
+		setXY((y%2) ? x : x+1, y+1, hasToBeValid);
 		break;
 	case BOTTOM_LEFT:
-		setXY(y%2 ? x-1 : x, y+1, hasToBeValid);
+		setXY((y%2) ? x-1 : x, y+1, hasToBeValid);
 		break;
 	case LEFT:
 		setXY(x-1, y, hasToBeValid);
@@ -157,4 +157,4 @@ BattleHex BattleHex::getClosestTile(bool attackerOwned, BattleHex initialPos, st
 	boost::sort (sortedTiles, compareHorizontal);
 
 	return sortedTiles.front();
-}
+}

+ 5 - 5
lib/BattleState.cpp

@@ -300,12 +300,12 @@ struct RangeGenerator
 	{
 	};
 
-	RangeGenerator(int _min, int _max, std::function<int()> _myRand)
+	RangeGenerator(int _min, int _max, std::function<int()> _myRand):
+		min(_min),
+		remainingCount(_max - _min + 1),
+		remaining(remainingCount, true),
+		myRand(_myRand)
 	{
-		myRand = _myRand;
-		min = _min;
-		remainingCount = _max - _min + 1;
-		remaining.resize(remainingCount, true);
 	}
 
 	int generateNumber()

+ 2 - 0
lib/CBattleCallback.cpp

@@ -543,6 +543,7 @@ void CBattleInfoCallback::battleGetStackQueue(std::vector<const CStack *> &out,
 		const CStack *fastest = st[i], *other = nullptr;
 		int bestSpeed = fastest->Speed(turn);
 
+		//FIXME: comparison between bool and integer. Logic does not makes sense either
 		if(fastest->attackerOwned != lastMoved)
 		{
 			ret = fastest;
@@ -648,6 +649,7 @@ void CBattleInfoCallback::battleGetStackQueue(std::vector<const CStack *> &out,
 	{
 		if(active)
 		{
+			//FIXME: both branches contain same code!!!
 			if(out.size() && out.front() == active)
 				lastMoved = active->attackerOwned;
 			else

+ 2 - 0
lib/CCreatureHandler.cpp

@@ -531,6 +531,7 @@ void CCreatureHandler::loadUnitAnimInfo(JsonNode & graphics, CLegacyConfigParser
 	animationTime["walk"].Float() = parser.readNumber();
 	animationTime["attack"].Float() = parser.readNumber();
 	animationTime["flight"].Float() = parser.readNumber();
+	animationTime["idle"].Float() = 10.0;
 
 	JsonNode & missile = graphics["missile"];
 	JsonNode & offsets = missile["offset"];
@@ -609,6 +610,7 @@ void CCreatureHandler::loadJsonAnimation(CCreature * cre, const JsonNode & graph
 
 	const JsonNode & animationTime = graphics["animationTime"];
 	cre->animation.walkAnimationTime = animationTime["walk"].Float();
+	cre->animation.idleAnimationTime = animationTime["idle"].Float();
 	cre->animation.attackAnimationTime = animationTime["attack"].Float();
 	cre->animation.flightAnimationDistance = animationTime["flight"].Float(); //?
 

+ 4 - 2
lib/CCreatureHandler.h

@@ -55,7 +55,8 @@ public:
 
 	struct CreatureAnimation
 	{
-		double timeBetweenFidgets, walkAnimationTime, attackAnimationTime, flightAnimationDistance;
+		double timeBetweenFidgets, idleAnimationTime,
+			   walkAnimationTime, attackAnimationTime, flightAnimationDistance;
 		int upperRightMissleOffsetX, rightMissleOffsetX, lowerRightMissleOffsetX,
 		    upperRightMissleOffsetY, rightMissleOffsetY, lowerRightMissleOffsetY;
 
@@ -67,7 +68,8 @@ public:
 
 		template <typename Handler> void serialize(Handler &h, const int version)
 		{
-			h & timeBetweenFidgets & walkAnimationTime & attackAnimationTime & flightAnimationDistance;
+			h & timeBetweenFidgets & idleAnimationTime;
+			h & walkAnimationTime & attackAnimationTime & flightAnimationDistance;
 			h & upperRightMissleOffsetX & rightMissleOffsetX & lowerRightMissleOffsetX;
 			h & upperRightMissleOffsetY & rightMissleOffsetY & lowerRightMissleOffsetY;
 			h & missleFrameAngles & troopCountLocationOffset & attackClimaxFrame;

+ 3 - 3
lib/CGameState.cpp

@@ -2940,10 +2940,10 @@ DuelParameters::SideSettings::SideSettings()
 	heroId = -1;
 }
 
-DuelParameters::DuelParameters()
+DuelParameters::DuelParameters():
+    terType(ETerrainType::DIRT),
+    bfieldType(BFieldType::ROCKLANDS)
 {
-    terType = ETerrainType::DIRT;
-	bfieldType = BFieldType::ROCKLANDS;
 }
 
 DuelParameters DuelParameters::fromJSON(const std::string &fname)

+ 1 - 0
lib/CGameState.h

@@ -450,6 +450,7 @@ struct DLL_LINKAGE QuestInfo //universal interface for human and AI
 	QuestInfo (const CQuest * Quest, const CGObjectInstance * Obj, int3 Tile) :
 		quest (Quest), obj (Obj), tile (Tile){};
 
+	//FIXME: assignment operator should return QuestInfo &
 	bool operator= (const QuestInfo &qi)
 	{
 		quest = qi.quest;

+ 1 - 17
lib/CModHandler.cpp

@@ -265,7 +265,7 @@ void CContentHandler::ContentTypeHandler::loadMod(std::string modName)
 				continue;
 			}
 		}
-		// normal new object
+		// normal new object or one with index bigger that data size
 		JsonUtils::validate(data, "vcmi:" + objectName, name);
 		handler->loadObject(modName, name, data);
 	}
@@ -533,22 +533,6 @@ CModInfo & CModHandler::getModData(TModID modId)
 	assert(vstd::contains(activeMods, modId)); // not really necessary but won't hurt
 	return mod;
 }
-
-template<typename Handler>
-void CModHandler::handleData(Handler handler, const JsonNode & source, std::string listName, std::string schemaName)
-{
-	JsonNode config = JsonUtils::assembleFromFiles(source[listName].convertTo<std::vector<std::string> >());
-
-	for(auto & entry : config.Struct())
-	{
-		if (!entry.second.isNull()) // may happens if mod removed object by setting json entry to null
-		{
-			JsonUtils::validate(entry.second, schemaName, entry.first);
-			handler->load(entry.first, entry.second);
-		}
-	}
-}
-
 void CModHandler::beforeLoad()
 {
 	loadConfigFromFile("defaultMods.json");

+ 0 - 4
lib/CModHandler.h

@@ -156,10 +156,6 @@ class DLL_LINKAGE CModHandler
 	// returns load order in which all dependencies are resolved, e.g. loaded after required mods
 	// function assumes that input list is valid (checkDependencies returned true)
 	std::vector <TModID> resolveDependencies(std::vector<TModID> input) const;
-
-	// helper for loadActiveMods. Loads content from list of files
-	template<typename Handler>
-	void handleData(Handler handler, const JsonNode & source, std::string listName, std::string schemaName);
 public:
 
 	CIdentifierStorage identifiers;

+ 18 - 19
lib/CObjectHandler.cpp

@@ -294,15 +294,14 @@ PlayerColor CGObjectInstance::getOwner() const
 		return tempOwner; //won't have owner
 }
 
-CGObjectInstance::CGObjectInstance()
+CGObjectInstance::CGObjectInstance():
+	pos(-1,-1,-1),
+	ID(Obj::NO_OBJ),
+	subID(-1),
+	defInfo(nullptr),
+	tempOwner(PlayerColor::UNFLAGGABLE),
+	blockVisit(false)
 {
-	pos = int3(-1,-1,-1);
-	//state = new CLuaObjectScript();
-	ID = Obj::NO_OBJ;
-	subID = -1;
-	defInfo = nullptr;
-	tempOwner = PlayerColor::UNFLAGGABLE;
-	blockVisit = false;
 }
 CGObjectInstance::~CGObjectInstance()
 {
@@ -1036,17 +1035,17 @@ void CGHeroInstance::initObj()
 
 					const CCreature &specCreature = *VLC->creh->creatures[spec.additionalinfo]; //creature in which we have specialty
 
-					int creLevel = specCreature.level;
-					if(!creLevel)
-					{
-						if(spec.additionalinfo == 146)
-							creLevel = 5; //treat ballista as 5-level
-						else
-						{
-                            logGlobal->warnStream() << "Warning: unknown level of " << specCreature.namePl;
-							continue;
-						}
-					}
+					//int creLevel = specCreature.level;
+					//if(!creLevel)
+					//{
+					//	if(spec.additionalinfo == 146)
+					//		creLevel = 5; //treat ballista as 5-level
+					//	else
+					//	{
+					//        logGlobal->warnStream() << "Warning: unknown level of " << specCreature.namePl;
+					//		continue;
+					//	}
+					//}
 
 					//bonus->additionalInfo = spec.additionalinfo; //creature id, should not be used again - this works only with limiter
 					bonus->limiter.reset(new CCreatureTypeLimiter (specCreature, true)); //with upgrades

+ 19 - 20
lib/JsonDetail.cpp

@@ -113,7 +113,7 @@ JsonWriter::JsonWriter(std::ostream &output, const JsonNode &node):
 
 std::ostream & operator<<(std::ostream &out, const JsonNode &node)
 {
-	JsonWriter(out, node);
+	JsonWriter writer(out, node);
 	return out << "\n";
 }
 
@@ -580,7 +580,7 @@ namespace
 		{
 			JsonNode::JsonType type = stringToType.find(schema.String())->second;
 			if(type != data.getType() && data.getType() != JsonNode::DATA_NULL)
-				return validator.makeErrorMessage("Type mismatch!");
+				return validator.makeErrorMessage("Type mismatch! Expected " + schema.String());
 			return "";
 		}
 
@@ -591,7 +591,6 @@ namespace
 			//Local reference. Turn it into more easy to handle remote ref
 			if (boost::algorithm::starts_with(URI, "#"))
 				URI = validator.usedSchemas.back() + URI;
-
 			return check(JsonUtils::getSchema(URI), data, validator);
 		}
 
@@ -607,7 +606,7 @@ namespace
 					errors += validator.makeErrorMessage(result);
 			}
 			else
-				errors += validator.makeErrorMessage("Unknown format: " + schema.String());
+				errors += validator.makeErrorMessage("Unsupported format type: " + schema.String());
 			return errors;
 		}
 	}
@@ -617,14 +616,14 @@ namespace
 		std::string maxLengthCheck(Validation::ValidationData & validator, const JsonNode & baseSchema, const JsonNode & schema, const JsonNode & data)
 		{
 			if (data.String().size() > schema.Float())
-				return validator.makeErrorMessage("String too long");
+				return validator.makeErrorMessage((boost::format("String is longer than %d symbols") % schema.Float()).str());
 			return "";
 		}
 
 		std::string minLengthCheck(Validation::ValidationData & validator, const JsonNode & baseSchema, const JsonNode & schema, const JsonNode & data)
 		{
 			if (data.String().size() < schema.Float())
-				return validator.makeErrorMessage("String too short");
+				return validator.makeErrorMessage((boost::format("String is shorter than %d symbols") % schema.Float()).str());
 			return "";
 		}
 	}
@@ -637,12 +636,12 @@ namespace
 			if (baseSchema["exclusiveMaximum"].Bool())
 			{
 				if (data.Float() >= schema.Float())
-					return validator.makeErrorMessage("Value is too large");
+					return validator.makeErrorMessage((boost::format("Value is bigger than %d") % schema.Float()).str());
 			}
 			else
 			{
 				if (data.Float() >  schema.Float())
-					return validator.makeErrorMessage("Value is too large");
+					return validator.makeErrorMessage((boost::format("Value is bigger than %d") % schema.Float()).str());
 			}
 			return "";
 		}
@@ -652,12 +651,12 @@ namespace
 			if (baseSchema["exclusiveMinimum"].Bool())
 			{
 				if (data.Float() <= schema.Float())
-					return validator.makeErrorMessage("Value is too small");
+					return validator.makeErrorMessage((boost::format("Value is smaller than %d") % schema.Float()).str());
 			}
 			else
 			{
 				if (data.Float() <  schema.Float())
-					return validator.makeErrorMessage("Value is too small");
+					return validator.makeErrorMessage((boost::format("Value is smaller than %d") % schema.Float()).str());
 			}
 			return "";
 		}
@@ -666,7 +665,7 @@ namespace
 		{
 			double result = data.Float() / schema.Float();
 			if (floor(result) != result)
-				return validator.makeErrorMessage("Value is not divisible");
+				return validator.makeErrorMessage((boost::format("Value is not divisible by %d") % schema.Float()).str());
 			return "";
 		}
 	}
@@ -726,14 +725,14 @@ namespace
 		std::string minItemsCheck(Validation::ValidationData & validator, const JsonNode & baseSchema, const JsonNode & schema, const JsonNode & data)
 		{
 			if (data.Vector().size() < schema.Float())
-				return validator.makeErrorMessage("Too few items in the list");
+				return validator.makeErrorMessage((boost::format("Length is smaller than %d") % schema.Float()).str());
 			return "";
 		}
 
 		std::string maxItemsCheck(Validation::ValidationData & validator, const JsonNode & baseSchema, const JsonNode & schema, const JsonNode & data)
 		{
 			if (data.Vector().size() > schema.Float())
-				return validator.makeErrorMessage("Too many items in the list!");
+				return validator.makeErrorMessage((boost::format("Length is bigger than %d") % schema.Float()).str());
 			return "";
 		}
 
@@ -760,14 +759,14 @@ namespace
 		std::string maxPropertiesCheck(Validation::ValidationData & validator, const JsonNode & baseSchema, const JsonNode & schema, const JsonNode & data)
 		{
 			if (data.Struct().size() > schema.Float())
-				return validator.makeErrorMessage("Too many items in the list!");
+				return validator.makeErrorMessage((boost::format("Number of entries is bigger than %d") % schema.Float()).str());
 			return "";
 		}
 
 		std::string minPropertiesCheck(Validation::ValidationData & validator, const JsonNode & baseSchema, const JsonNode & schema, const JsonNode & data)
 		{
 			if (data.Struct().size() < schema.Float())
-				return validator.makeErrorMessage("Too few items in the list");
+				return validator.makeErrorMessage((boost::format("Number of entries is less than %d") % schema.Float()).str());
 			return "";
 		}
 
@@ -855,11 +854,11 @@ namespace
 				{
 					// try generic additionalItems schema
 					if (schema.getType() == JsonNode::DATA_STRUCT)
-						return propertyEntryCheck(validator, entry.second, schema, entry.first);
+                        errors += propertyEntryCheck(validator, entry.second, schema, entry.first);
 
 					// or, additionalItems field can be bool which indicates if such items are allowed
-					if (!schema.isNull() && schema.Bool() == false) // present and set to false - error
-						return validator.makeErrorMessage("Unknown entry found: " + entry.first);
+                    else if (!schema.isNull() && schema.Bool() == false) // present and set to false - error
+                        errors += validator.makeErrorMessage("Unknown entry found: " + entry.first);
 				}
 			}
 			return errors;
@@ -914,7 +913,7 @@ namespace
 			TEST_FILE("Sprites/", node.String(), EResType::IMAGE);
 			if (node.String().find(':') != std::string::npos)
 				return testAnimation(node.String().substr(0, node.String().find(':')));
-			return "Image file not found";
+			return "Image file \"" + node.String() + "\" was not found";
 		}
 
 		#undef TEST_FILE
@@ -1082,4 +1081,4 @@ namespace Validation
 		return knownFormats;
 	}
 
-} // Validation namespace
+} // Validation namespace

+ 2 - 2
lib/JsonNode.cpp

@@ -50,9 +50,9 @@ JsonNode::JsonNode(ResourceID && fileURI):
 }
 
 JsonNode::JsonNode(const JsonNode &copy):
-	type(DATA_NULL)
+	type(DATA_NULL),
+	meta(copy.meta)
 {
-	meta = copy.meta;
 	setType(copy.getType());
 	switch(type)
 	{

+ 1 - 1
lib/int3.h

@@ -18,7 +18,7 @@ public:
 	inline int3():x(0),y(0),z(0){}; //c-tor, x/y/z initialized to 0
 	inline int3(const si32 X, const si32 Y, const si32 Z):x(X),y(Y),z(Z){}; //c-tor
 	inline int3(const int3 & val) : x(val.x), y(val.y), z(val.z){} //copy c-tor
-	inline int3 operator=(const int3 & val) {x = val.x; y = val.y; z = val.z; return *this;} //assignemt operator
+	inline int3 & operator=(const int3 & val) {x = val.x; y = val.y; z = val.z; return *this;} //assignemt operator
 	~int3() {} // d-tor - does nothing
 	inline int3 operator+(const int3 & i) const //returns int3 with coordinates increased by corresponding coordinate of given int3
 		{return int3(x+i.x,y+i.y,z+i.z);}

+ 4 - 4
server/CGameHandler.cpp

@@ -2176,28 +2176,28 @@ void CGameHandler::applyAndSend(CPackForClient * info)
 
 void CGameHandler::sendAndApply(CGarrisonOperationPack * info)
 {
-	sendAndApply((CPackForClient*)info);
+	sendAndApply(static_cast<CPackForClient*>(info));
 	if(gs->map->victoryCondition.condition == EVictoryConditionType::GATHERTROOP)
 		winLoseHandle();
 }
 
 void CGameHandler::sendAndApply( SetResource * info )
 {
-	sendAndApply((CPackForClient*)info);
+	sendAndApply(static_cast<CPackForClient*>(info));
 	if(gs->map->victoryCondition.condition == EVictoryConditionType::GATHERRESOURCE)
 		checkLossVictory(info->player);
 }
 
 void CGameHandler::sendAndApply( SetResources * info )
 {
-	sendAndApply((CPackForClient*)info);
+	sendAndApply(static_cast<CPackForClient*>(info));
 	if(gs->map->victoryCondition.condition == EVictoryConditionType::GATHERRESOURCE)
 		checkLossVictory(info->player);
 }
 
 void CGameHandler::sendAndApply( NewStructures * info )
 {
-	sendAndApply((CPackForClient*)info);
+	sendAndApply(static_cast<CPackForClient*>(info));
 	if(gs->map->victoryCondition.condition == EVictoryConditionType::BUILDCITY)
 		checkLossVictory(getTown(info->tid)->tempOwner);
 }