mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Fixed #730:
* crash on +5 growth week * crash on spawning wandering creatures on double growth months (how come that has not been found in previous build?) More logging for #729-like issues.
This commit is contained in:
		| @@ -106,7 +106,6 @@ public: | ||||
| 	void setBlockVis(int objid, bool bv) OVERRIDE {}; | ||||
| 	void setOwner(int objid, ui8 owner) OVERRIDE {}; | ||||
| 	void setHoverName(int objid, MetaString * name) OVERRIDE {}; | ||||
| 	void setObjProperty(int objid, int prop, si64 val) OVERRIDE {}; | ||||
| 	void changePrimSkill(int ID, int which, si64 val, bool abs=false) OVERRIDE {}; | ||||
| 	void changeSecSkill(int ID, int which, int val, bool abs=false) OVERRIDE {};  | ||||
| 	void showBlockingDialog(BlockingDialog *iw, const CFunctionList<void(ui32)> &callback) OVERRIDE {}; | ||||
|   | ||||
| @@ -509,7 +509,10 @@ void CStackInstance::giveStackExp(expType exp) | ||||
|  | ||||
| void CStackInstance::setType(int creID) | ||||
| { | ||||
| 	setType(VLC->creh->creatures[creID]); | ||||
| 	if(creID >= 0 && creID < VLC->creh->creatures.size()) | ||||
| 		setType(VLC->creh->creatures[creID]); | ||||
| 	else | ||||
| 		setType(NULL); | ||||
| } | ||||
|  | ||||
| void CStackInstance::setType(const CCreature *c) | ||||
|   | ||||
| @@ -271,8 +271,18 @@ void MetaString::getLocalString(const std::pair<ui8,ui32> &txt, std::string &dst | ||||
| 		case COLOR: | ||||
| 			vec = &VLC->generaltexth->capColors; | ||||
| 			break; | ||||
| 		default: | ||||
| 			tlog1 << "Failed string substitution because type is " << type << std::endl; | ||||
| 			dst = "#@#"; | ||||
| 			return; | ||||
| 		} | ||||
| 		dst = (*vec)[ser]; | ||||
| 		if(vec->size() <= ser) | ||||
| 		{ | ||||
| 			tlog1 << "Failed string substitution with type " << type << " because index " << ser << " is out of bounds!\n"; | ||||
| 			dst = "#!#"; | ||||
| 		} | ||||
| 		else | ||||
| 			dst = (*vec)[ser]; | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -3008,23 +3008,23 @@ void CGCreature::newTurn() const | ||||
| 	if (stacks.begin()->second->count < CREEP_SIZE && cb->getDate(1) == 1 && cb->getDate(0) > 1) | ||||
| 	{ | ||||
| 		ui32 power = temppower * (100 + WEEKLY_GROWTH)/100; | ||||
| 		cb->setObjProperty(id, 10, std::min (power/1000 , (ui32)CREEP_SIZE)); //set new amount | ||||
| 		cb->setObjProperty(id, 11, power); //increase temppower | ||||
| 		cb->setObjProperty(id, ObjProperty::MONSTER_COUNT, std::min (power/1000 , (ui32)CREEP_SIZE)); //set new amount | ||||
| 		cb->setObjProperty(id, ObjProperty::MONSTER_POWER, power); //increase temppower | ||||
| 	} | ||||
| 	if (STACK_EXP) | ||||
| 		cb->setObjProperty(id, 12, 10000); //for testing purpose | ||||
| 		cb->setObjProperty(id, ObjProperty::MONSTER_EXP, 10000); //for testing purpose | ||||
| } | ||||
| void CGCreature::setPropertyDer(ui8 what, ui32 val) | ||||
| { | ||||
| 	switch (what) | ||||
| 	{ | ||||
| 		case 10: | ||||
| 		case ObjProperty::MONSTER_COUNT: | ||||
| 			stacks[0]->count = val; | ||||
| 			break; | ||||
| 		case 11: | ||||
| 		case ObjProperty::MONSTER_POWER: | ||||
| 			temppower = val; | ||||
| 			break; | ||||
| 		case 12: | ||||
| 		case ObjProperty::MONSTER_EXP: | ||||
| 			giveStackExp(val); | ||||
| 			break; | ||||
| 		case 13: | ||||
|   | ||||
| @@ -1184,3 +1184,30 @@ void IGameEventRealizer::showInfoDialog( InfoWindow *iw ) | ||||
| { | ||||
| 	commitPackage(iw); | ||||
| } | ||||
|  | ||||
| void IGameEventRealizer::setObjProperty(int objid, int prop, si64 val) | ||||
| { | ||||
| 	SetObjectProperty sob; | ||||
| 	sob.id = objid; | ||||
| 	sob.what = prop; | ||||
| 	sob.val = val; | ||||
| 	commitPackage(&sob); | ||||
| } | ||||
|  | ||||
| const CGObjectInstance * IGameCallback::putNewObject(int ID, int subID, int3 pos) | ||||
| { | ||||
| 	NewObject no; | ||||
| 	no.ID = ID; //creature | ||||
| 	no.subID= subID; | ||||
| 	no.pos = pos; | ||||
| 	commitPackage(&no); | ||||
| 	return getObj(no.id); //id field will be filled during applaying on gs | ||||
| } | ||||
|  | ||||
| const CGCreature * IGameCallback::putNewMonster(int creID, int count, int3 pos) | ||||
| { | ||||
| 	const CGObjectInstance *m = putNewObject(54, creID, pos); | ||||
| 	setObjProperty(m->id, ObjProperty::MONSTER_COUNT, count); | ||||
| 	setObjProperty(m->id, ObjProperty::MONSTER_POWER, (si64)1000*count); | ||||
| 	return dynamic_cast<const CGCreature*>(m); | ||||
| } | ||||
|   | ||||
| @@ -55,6 +55,8 @@ class CCreatureSet; | ||||
| class CCreature; | ||||
| class CStackBasicDescriptor; | ||||
| class TeamState; | ||||
| class CGCreature; | ||||
|  | ||||
|  | ||||
| typedef std::vector<const CStack*> TStacks; | ||||
|  | ||||
| @@ -246,6 +248,7 @@ public: | ||||
| 	virtual void commitPackage(CPackForClient *pack) = 0; | ||||
|  | ||||
| 	virtual void showInfoDialog(InfoWindow *iw); | ||||
| 	virtual void setObjProperty(int objid, int prop, si64 val); | ||||
| }; | ||||
|  | ||||
| class DLL_EXPORT IGameEventCallback : public IGameEventRealizer | ||||
| @@ -256,7 +259,6 @@ public: | ||||
| 	virtual void setBlockVis(int objid, bool bv)=0; | ||||
| 	virtual void setOwner(int objid, ui8 owner)=0; | ||||
| 	virtual void setHoverName(int objid, MetaString * name)=0; | ||||
| 	virtual void setObjProperty(int objid, int prop, si64 val)=0; | ||||
| 	virtual void changePrimSkill(int ID, int which, si64 val, bool abs=false)=0; | ||||
| 	virtual void changeSecSkill(int ID, int which, int val, bool abs=false)=0;  | ||||
| 	virtual void showBlockingDialog(BlockingDialog *iw, const CFunctionList<void(ui32)> &callback)=0; | ||||
| @@ -306,7 +308,8 @@ public: | ||||
| 	virtual ~IGameCallback(){}; | ||||
|  | ||||
| 	//do sth | ||||
|  | ||||
| 	const CGObjectInstance *putNewObject(int ID, int subID, int3 pos); | ||||
| 	const CGCreature *putNewMonster(int creID, int count, int3 pos); | ||||
|  | ||||
| 	friend struct CPack; | ||||
| 	friend struct CPackForClient; | ||||
|   | ||||
| @@ -677,14 +677,18 @@ struct OpenWindow : public CPackForClient //517 | ||||
|  | ||||
| struct NewObject  : public CPackForClient //518 | ||||
| { | ||||
| 	NewObject(){type = 518;}; | ||||
| 	NewObject() | ||||
| 	{ | ||||
| 		type = 518; | ||||
| 		id = -1; | ||||
| 	} | ||||
| 	void applyCl(CClient *cl); | ||||
| 	DLL_EXPORT void applyGs(CGameState *gs); | ||||
|  | ||||
| 	ui32 ID, subID; | ||||
| 	int3 pos; | ||||
|  | ||||
| 	int id; //used internally | ||||
| 	int id; //used locally, filled during applyGs | ||||
|  | ||||
| 	template <typename Handler> void serialize(Handler &h, const int version) | ||||
| 	{ | ||||
| @@ -1022,7 +1026,8 @@ struct InfoWindow : public CPackForClient //103  - displays simple info window | ||||
| namespace ObjProperty | ||||
| { | ||||
| 	//TODO: move non general properties out to the appropriate objs classes | ||||
| 	enum {OWNER = 1, BLOCKVIS = 2, PRIMARY_STACK_COUNT = 3, VISITORS = 4, VISITED = 5, ID = 6, AVAILABLE_CREATURE = 7, SUBID = 8}; | ||||
| 	enum {OWNER = 1, BLOCKVIS = 2, PRIMARY_STACK_COUNT = 3, VISITORS = 4, VISITED = 5, ID = 6, AVAILABLE_CREATURE = 7, SUBID = 8, | ||||
| 		MONSTER_COUNT = 10, MONSTER_POWER = 11, MONSTER_EXP = 12}; | ||||
| } | ||||
|  | ||||
| struct SetObjectProperty : public CPackForClient//1001 | ||||
|   | ||||
| @@ -476,6 +476,8 @@ DLL_EXPORT void NewObject::applyGs( CGameState *gs ) | ||||
| 			cre->notGrowingTeam = cre->neverFlees = 0; | ||||
| 			cre->character = 2; | ||||
| 			cre->gainedArtifact = -1; | ||||
| 			cre->identifier = -1; | ||||
| 			cre->addToSlot(0, new CStackInstance(-1, -1)); //add placeholder stack | ||||
| 		} | ||||
| 		break; | ||||
| 	default: | ||||
|   | ||||
| @@ -811,7 +811,6 @@ void CGameHandler::newTurn() | ||||
|  | ||||
| 	if (getDate(1) == 7 && getDate(0)>1) //new week (day numbers are confusing, as day was not yet switched) | ||||
| 	{ | ||||
| 		int monsterid; | ||||
| 		int monthType = rand()%100; | ||||
| 		if(getDate(4) == 28) //new month | ||||
| 		{ | ||||
| @@ -843,7 +842,7 @@ void CGameHandler::newTurn() | ||||
| 			{ | ||||
| 				n.specialWeek = NewTurn::BONUS_GROWTH; //+5 | ||||
| 				std::pair<int,int> newMonster (54, VLC->creh->pickRandomMonster(boost::ref(rand))); | ||||
| 				monsterid = newMonster.second; | ||||
| 				n.creatureid = newMonster.second; | ||||
| 			} | ||||
| 			else | ||||
| 				n.specialWeek = NewTurn::NORMAL; | ||||
| @@ -1006,11 +1005,7 @@ void CGameHandler::newTurn() | ||||
| 			for (int i = 0; i < amount; ++i) | ||||
| 			{ | ||||
| 				tile = tiles.begin(); | ||||
| 				NewObject no; | ||||
| 				no.ID = 54; //creature | ||||
| 				no.subID= n.creatureid; | ||||
| 				no.pos = *tile; | ||||
| 				sendAndApply(&no); | ||||
| 				putNewMonster(n.creatureid, VLC->creh->creatures[n.creatureid]->getRandomAmount(std::rand), *tile); | ||||
| 				tiles.erase(tile); //not use it again | ||||
| 			} | ||||
| 		} | ||||
| @@ -1704,15 +1699,6 @@ void CGameHandler::changeSpells( int hid, bool give, const std::set<ui32> &spell | ||||
| 	sendAndApply(&cs); | ||||
| } | ||||
|  | ||||
| void CGameHandler::setObjProperty( int objid, int prop, si64 val ) | ||||
| { | ||||
| 	SetObjectProperty sob; | ||||
| 	sob.id = objid; | ||||
| 	sob.what = prop; | ||||
| 	sob.val = val; | ||||
| 	sendAndApply(&sob); | ||||
| } | ||||
|  | ||||
| void CGameHandler::sendMessageTo( CConnection &c, const std::string &message ) | ||||
| { | ||||
| 	SystemMessage sm; | ||||
|   | ||||
| @@ -133,7 +133,6 @@ public: | ||||
| 	void setBlockVis(int objid, bool bv) OVERRIDE; | ||||
| 	void setOwner(int objid, ui8 owner) OVERRIDE; | ||||
| 	void setHoverName(int objid, MetaString * name) OVERRIDE; | ||||
| 	void setObjProperty(int objid, int prop, si64 val) OVERRIDE; | ||||
| 	void changePrimSkill(int ID, int which, si64 val, bool abs=false) OVERRIDE; | ||||
| 	void changeSecSkill(int ID, int which, int val, bool abs=false) OVERRIDE;  | ||||
| 	//void showInfoDialog(InfoWindow *iw) OVERRIDE; | ||||
|   | ||||
| @@ -13,7 +13,14 @@ | ||||
| #define ERROR_AND_RETURN	do {if(c) *c << &SystemMessage("You are not allowed to perform this action!");	\ | ||||
| 							tlog1<<"Player is not allowed to perform this action!\n";	\ | ||||
| 							return false;} while(0) | ||||
| #define ERROR_IF_NOT_OWNS(id)	if(!PLAYER_OWNS(id)) ERROR_AND_RETURN | ||||
|  | ||||
| #define WRONG_PLAYER_MSG(expectedplayer) do {std::ostringstream oss;\ | ||||
| 			oss << "You were identified as player " << (int)gh->getPlayerAt(c) << " while expecting " << (int)expectedplayer;\ | ||||
| 			tlog1 << oss.str() << std::endl; \ | ||||
| 			if(c) *c << &SystemMessage(oss.str());} while(0) | ||||
|  | ||||
| #define ERROR_IF_NOT_OWNS(id)	do{if(!PLAYER_OWNS(id)){WRONG_PLAYER_MSG(gh->getOwner(id)); ERROR_AND_RETURN; }}while(0) | ||||
| #define ERROR_IF_NOT(player)	do{if(player != gh->getPlayerAt(c)){WRONG_PLAYER_MSG(player); ERROR_AND_RETURN; }}while(0) | ||||
| #define COMPLAIN_AND_RETURN(txt)	{ gh->complain(txt); ERROR_AND_RETURN; } | ||||
|  | ||||
| /* | ||||
| @@ -54,8 +61,7 @@ bool CloseServer::applyGh( CGameHandler *gh ) | ||||
|  | ||||
| bool EndTurn::applyGh( CGameHandler *gh ) | ||||
| { | ||||
| 	if(gh->getPlayerAt(c) != GS(gh)->currentPlayer) | ||||
| 		ERROR_AND_RETURN; | ||||
| 	ERROR_IF_NOT(GS(gh)->currentPlayer); | ||||
| 	gh->states.setFlag(GS(gh)->currentPlayer,&PlayerStatus::makingTurn,false); | ||||
| 	return true; | ||||
| } | ||||
| @@ -153,8 +159,7 @@ bool TradeOnMarketplace::applyGh( CGameHandler *gh ) | ||||
| 	if(hero && (player != hero->tempOwner || hero->visitablePos() != market->visitablePos())) | ||||
| 		COMPLAIN_AND_RETURN("This hero can't use this marketplace!"); | ||||
|  | ||||
| 	if(gh->getPlayerAt(c) != player)  | ||||
| 		ERROR_AND_RETURN; | ||||
| 	ERROR_IF_NOT(player); | ||||
|  | ||||
| 	switch(mode) | ||||
| 	{ | ||||
| @@ -255,6 +260,7 @@ bool CastAdvSpell::applyGh( CGameHandler *gh ) | ||||
|  | ||||
| bool PlayerMessage::applyGh( CGameHandler *gh ) | ||||
| { | ||||
| 	ERROR_IF_NOT(player); | ||||
| 	if(gh->getPlayerAt(c) != player) ERROR_AND_RETURN; | ||||
| 	gh->playerMessage(player,text); | ||||
| 	return true; | ||||
| @@ -262,8 +268,12 @@ bool PlayerMessage::applyGh( CGameHandler *gh ) | ||||
|  | ||||
| bool SetSelection::applyGh( CGameHandler *gh ) | ||||
| { | ||||
| 	if(gh->getPlayerAt(c) != player) ERROR_AND_RETURN; | ||||
| 	if(!gh->getObj(id)) ERROR_AND_RETURN; | ||||
| 	ERROR_IF_NOT(player); | ||||
| 	if(!gh->getObj(id)) | ||||
| 	{ | ||||
| 		tlog1 << "No such object...\n"; | ||||
| 		ERROR_AND_RETURN; | ||||
| 	} | ||||
| 	gh->sendAndApply(this); | ||||
| 	return true; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user