Преглед изворни кода

Support for War Machine Factory.

Michał W. Urbańczyk пре 15 година
родитељ
комит
70fa697f8b

+ 2 - 1
CCallback.cpp

@@ -59,7 +59,8 @@ void CCallback::selectionMade(int selection, int asker)
 }
 void CCallback::recruitCreatures(const CGObjectInstance *obj, ui32 ID, ui32 amount)
 {
-	if(player!=obj->tempOwner) return;
+	if(player!=obj->tempOwner  &&  obj->ID != 106)
+		return;
 
 	RecruitCreatures pack(obj->id,ID,amount);
 	sendRequest(&pack);

+ 2 - 1
ChangeLog

@@ -32,7 +32,8 @@ TOWNS:
 - Soul Prison
 
 OBJECTS:
-
+New object supported:
+- War Machine Factory
 
 0.75 -> 0.8 (Mar 01 2010)
 GENERAL:

+ 1 - 1
client/CPlayerInterface.cpp

@@ -956,7 +956,7 @@ void CPlayerInterface::availableCreaturesChanged( const CGDwelling *town )
 		if(fs)
 			fs->draw(castleInt,false);
 	}
-	else if(GH.listInt.size() && (town->ID == 17  ||  town->ID == 20)) //external dwelling
+	else if(GH.listInt.size() && (town->ID == 17  ||  town->ID == 20  ||  town->ID == 106)) //external dwelling
 	{
 		CRecruitmentWindow *crw = dynamic_cast<CRecruitmentWindow*>(GH.topInt());
 		if(crw)

+ 4 - 0
client/GUIClasses.cpp

@@ -1858,6 +1858,10 @@ void CRecruitmentWindow::clickLeft(tribool down, bool previousState)
 			which = i;
 			int newAmount = std::min(amounts[i],creatures[i].amount);
 			slider->setAmount(newAmount);
+
+			slider->block(!newAmount);
+			max->block(!newAmount);
+
 			if(slider->value > newAmount)
 				slider->moveTo(newAmount);
 			else

+ 12 - 4
client/NetPacksClient.cpp

@@ -179,7 +179,7 @@ void RemoveObject::applyFirstCl( CClient *cl )
 	const CGObjectInstance *o = cl->getObj(id);
 	CGI->mh->hideObject(o);
 
-	int3 pos = o->pos - o->getVisitableOffset();
+	int3 pos = o->visitablePos();
 	//notify interfaces about removal
 	for(std::map<ui8, CGameInterface*>::iterator i=cl->playerint.begin();i!=cl->playerint.end();i++)
 	{
@@ -294,8 +294,16 @@ void RazeStructures::applyCl (CClient *cl)
 void SetAvailableCreatures::applyCl( CClient *cl )
 {
 	const CGDwelling *dw = static_cast<const CGDwelling*>(cl->getObj(tid));
-	if(vstd::contains(cl->playerint,dw->tempOwner))
-		cl->playerint[dw->tempOwner]->availableCreaturesChanged(dw);
+
+	//inform order about the change
+
+	int p = -1;
+	if(dw->ID == 106) //War Machines Factory is not flaggable, it's "owned" by visitor
+		p = cl->getTile(dw->visitablePos())->visitableObjects.back()->tempOwner;
+	else
+		p = dw->tempOwner;
+
+	INTERFACE_CALL_IF_PRESENT(p, availableCreaturesChanged, dw);
 }
 
 void SetHeroesInTown::applyCl( CClient *cl )
@@ -690,7 +698,7 @@ void OpenWindow::applyCl(CClient *cl)
 		{
 			const CGDwelling *dw = dynamic_cast<const CGDwelling*>(cl->getObj(id1));
 			const CArmedInstance *dst = dynamic_cast<const CArmedInstance*>(cl->getObj(id2));
-			INTERFACE_CALL_IF_PRESENT(dw->tempOwner,showRecruitmentDialog, dw, dst, window == RECRUITMENT_FIRST ? 0 : -1);
+			INTERFACE_CALL_IF_PRESENT(dst->tempOwner,showRecruitmentDialog, dw, dst, window == RECRUITMENT_FIRST ? 0 : -1);
 		}
 		break;
 	case SHIPYARD_WINDOW:

+ 38 - 7
hch/CObjectHandler.cpp

@@ -455,6 +455,11 @@ bool CGObjectInstance::hasShadowAt( int x, int y ) const
 	return false;
 }
 
+int3 CGObjectInstance::visitablePos() const
+{
+	return pos - getVisitableOffset();
+}
+
 static int lowestSpeed(const CGHeroInstance * chi)
 {
 	if(!chi->Slots().size())
@@ -1237,6 +1242,13 @@ void CGDwelling::initObj()
 		hoverName = VLC->generaltexth->creGens4[subID];
 		break;
 
+	case 106: //War Machine Factory
+		creatures.resize(3);
+		creatures[0].second.push_back(146); //Ballista 
+		creatures[1].second.push_back(147); //First Aid Tent
+		creatures[2].second.push_back(148); //Ammo Cart
+		break;
+
 	default:
 		assert(0);
 		break;
@@ -1277,7 +1289,7 @@ void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const
 		return;
 	}
 
-	if(h->tempOwner != tempOwner)
+	if(h->tempOwner != tempOwner  &&  ID != 106)
 	{
 		cb->setOwner(id, h->tempOwner);
 	}
@@ -1285,10 +1297,17 @@ void CGDwelling::onHeroVisit( const CGHeroInstance * h ) const
 	BlockingDialog bd;
 	bd.player = h->tempOwner;
 	bd.flags = BlockingDialog::ALLOW_CANCEL;
-	bd.text.addTxt(MetaString::ADVOB_TXT, ID == 17 ? 35 : 36); //{%s} Would you like to recruit %s?
-	bd.text.addReplacement(ID == 17 ? MetaString::CREGENS : MetaString::CREGENS4, subID);
-	for(size_t i = 0; i < creatures.size(); i++)
-		bd.text.addReplacement(MetaString::CRE_PL_NAMES, creatures[i].second[0]);
+	if(ID == 17 || ID == 20)
+	{
+		bd.text.addTxt(MetaString::ADVOB_TXT, ID == 17 ? 35 : 36); //{%s} Would you like to recruit %s? / {%s} Would you like to recruit %s, %s, %s, or %s?
+		bd.text.addReplacement(ID == 17 ? MetaString::CREGENS : MetaString::CREGENS4, subID);
+		for(size_t i = 0; i < creatures.size(); i++)
+			bd.text.addReplacement(MetaString::CRE_PL_NAMES, creatures[i].second[0]);
+	}
+	else if(ID == 106)
+		bd.text.addTxt(MetaString::ADVOB_TXT, 157); //{War Machine Factory} Would you like to purchase War Machines?
+	else
+		throw std::string("Illegal dwelling!");
 
 	cb->showBlockingDialog(&bd, boost::bind(&CGDwelling::heroAcceptsCreatures, this, h, _1));
 }
@@ -1298,8 +1317,8 @@ void CGDwelling::newTurn() const
 	if(cb->getDate(1) != 1) //not first day of week
 		return;
 
-	//town growths are handled separately
-	if(ID == TOWNI_TYPE)
+	//town growths and War Machines Factories are handled separately
+	if(ID == TOWNI_TYPE  ||  ID == 106)
 		return;
 
 	bool change = false;
@@ -1377,6 +1396,18 @@ void CGDwelling::heroAcceptsCreatures( const CGHeroInstance *h, ui32 answer ) co
 	}
 	else
 	{
+		if(ID == 106) //pick available War Machines
+		{
+			//there is 1 war machine available to recruit if hero doesn't have one
+			SetAvailableCreatures sac;
+			sac.tid = id;
+			sac.creatures = creatures;
+			sac.creatures[0].first = !h->getArt(13); //ballista
+			sac.creatures[1].first = !h->getArt(15); //first aid tent
+			sac.creatures[2].first = !h->getArt(14); //ammo cart
+			cb->sendAndApply(&sac);
+		}
+
 		OpenWindow ow;
 		ow.id1 = id;
 		ow.id2 = h->id;

+ 1 - 0
hch/CObjectHandler.h

@@ -180,6 +180,7 @@ public:
 	int getHeight() const; //returns height of object graphic in tiles
 	bool visitableAt(int x, int y) const; //returns true if object is visitable at location (x, y) form left top tile of image (x, y in tiles)
 	int3 getVisitableOffset() const; //returns (x,y,0) offset to first visitable tile from bottom right obj tile (0,0,0) (h3m pos)
+	int3 visitablePos() const;
 	bool blockingAt(int x, int y) const; //returns true if object is blocking location (x, y) form left top tile of image (x, y in tiles)
 	bool coveringAt(int x, int y) const; //returns true if object covers with picture location (x, y) form left top tile of maximal possible image (8 x 6 tiles) (x, y in tiles)
 	bool hasShadowAt(int x, int y) const;//returns true if object covers with shadow location (x, y) form left top tile of maximal possible image (8 x 6 tiles) (x, y in tiles)

+ 5 - 0
lib/map.cpp

@@ -1657,6 +1657,11 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
 				i+=3;
 				break;
 			}
+		case 106: //War Machine Factory
+			{
+				nobj = new CGDwelling();
+				break;
+			}
 		case 220://mine (?)
 			{
 				nobj = new CGObjectInstance();

+ 42 - 14
server/CGameHandler.cpp

@@ -1693,7 +1693,7 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
 			}
 			getTilesInRange(tmh.fowRevealed,h->getSightCenter()+(tmh.end-tmh.start),h->getSightRadious(),h->tempOwner,1);
 
-			int3 guardPos = gs->guardingCreaturePosition(int3(hmpos.x, hmpos.y, hmpos.z));
+			int3 guardPos = gs->guardingCreaturePosition(hmpos);
 			
 			tmh.result = TryMoveHero::SUCCESS;
 			tmh.attackedFrom = guardPos;
@@ -1701,7 +1701,8 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
 			tlog5 << "Moved to " <<tmh.end<<std::endl;
 
 			// If a creature guards the tile, block visit.
-			if (gs->map->isInTheMap(guardPos)) {
+			if (gs->map->isInTheMap(guardPos)) 
+			{
 				const TerrainTile &guardTile = gs->map->terrain[guardPos.x][guardPos.y][guardPos.z];
 				objectVisited(guardTile.visitableObjects.back(), h);
 
@@ -1989,7 +1990,7 @@ void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstan
 
 void CGameHandler::startBattleI( const CArmedInstance *army1, const CArmedInstance *army2, boost::function<void(BattleResult*)> cb, bool creatureBank)
 {
-	startBattleI(army1, army2, army2->pos - army2->getVisitableOffset(), cb, creatureBank);
+	startBattleI(army1, army2, army2->visitablePos(), cb, creatureBank);
 }
 
 //void CGameHandler::startBattleI(int heroID, CCreatureSet army, int3 tile, boost::function<void(BattleResult*)> cb) //for hero<=>neutral army
@@ -2511,11 +2512,17 @@ bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram )
 {
 	const CGDwelling *dw = static_cast<CGDwelling*>(gs->map->objects[objid]);
 	const CArmedInstance *dst = NULL;
+	const CCreature *c = VLC->creh->creatures[crid];
+	bool warMachine = c->hasBonusOfType(Bonus::SIEGE_WEAPON);
+
+	//TODO: test for owning
 
 	if(dw->ID == TOWNI_TYPE)
 		dst = dw;
 	else if(dw->ID == 17  ||  dw->ID == 20) //advmap dwelling
 		dst = getHero(gs->getPlayer(dw->tempOwner)->currentSelection); //TODO: check if current hero is really visiting dwelling
+	else if(dw->ID == 106)
+		dst = dynamic_cast<const CGHeroInstance *>(getTile(dw->visitablePos())->visitableObjects.back());
 
 	assert(dw && dst);
 
@@ -2540,12 +2547,12 @@ bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram )
 			break;
 		}
 	}
-	int slot = dst-> getSlotFor(crid);
+	int slot = dst->getSlotFor(crid); 
 
 	if(!found && complain("Cannot recruit: no such creatures!")
-		|| cram > VLC->creh->creatures[crid]->maxAmount(gs->getPlayer(dst->tempOwner)->resources) && complain("Cannot recruit: lack of resources!")
-		|| cram<=0	&& complain("Cannot recruit: cram <= 0!")
-		|| slot<0  && complain("Cannot recruit: no available slot!")) 
+		|| cram  >  VLC->creh->creatures[crid]->maxAmount(gs->getPlayer(dst->tempOwner)->resources) && complain("Cannot recruit: lack of resources!")
+		|| cram<=0  &&  complain("Cannot recruit: cram <= 0!")
+		|| slot<0  && !warMachine && complain("Cannot recruit: no available slot!")) 
 	{
 		return false;
 	}
@@ -2554,20 +2561,41 @@ bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram )
 	SetResources sr;
 	sr.player = dst->tempOwner;
 	for(int i=0;i<RESOURCE_QUANTITY;i++)
-		sr.res[i]  =  gs->getPlayer(dst->tempOwner)->resources[i] - (VLC->creh->creatures[crid]->cost[i] * cram);
+		sr.res[i]  =  gs->getPlayer(dst->tempOwner)->resources[i] - (c->cost[i] * cram);
 
 	SetAvailableCreatures sac;
 	sac.tid = objid;
 	sac.creatures = dw->creatures;
 	sac.creatures[level].first -= cram;
 
-	SetGarrisons sg;
-	sg.garrs[dst->id] = dst->getArmy();
-	sg.garrs[dst->id] .addToSlot(slot, crid, cram);
-
-	sendAndApply(&sr); 
+	sendAndApply(&sr);
 	sendAndApply(&sac);
-	sendAndApply(&sg);
+	
+	if(warMachine)
+	{
+		switch(crid)
+		{
+		case 146:
+			giveHeroArtifact(4, dst->id, 13);
+			break;
+		case 147:
+			giveHeroArtifact(6, dst->id, 15);
+			break;
+		case 148:
+			giveHeroArtifact(5, dst->id, 14);
+			break;
+		default:
+			complain("This war machine cannot be recruited!");
+			return false;
+		}
+	}
+	else
+	{
+		SetGarrisons sg;
+		sg.garrs[dst->id] = dst->getArmy();
+		sg.garrs[dst->id] .addToSlot(slot, crid, cram);
+		sendAndApply(&sg);
+	}
 	return true;
 }
 

+ 0 - 1
server/NetPacksServer.cpp

@@ -75,7 +75,6 @@ bool BuildStructure::applyGh( CGameHandler *gh )
 
 bool RecruitCreatures::applyGh( CGameHandler *gh )
 {
-	ERROR_IF_NOT_OWNS(tid);
 	return gh->recruitCreatures(tid,crid,amount);
 }