Kaynağa Gözat

Merge pull request #4391 from Laserlicht/bank_support

[HotA] Bank support
Ivan Savenko 1 yıl önce
ebeveyn
işleme
84f29183c8

+ 10 - 0
CCallback.cpp

@@ -217,6 +217,16 @@ bool CCallback::buildBuilding(const CGTownInstance *town, BuildingID buildingID)
 	return true;
 }
 
+bool CCallback::triggerTownSpecialBuildingAction(const CGTownInstance *town, BuildingSubID::EBuildingSubID subBuildingID)
+{
+	if(town->tempOwner!=player)
+		return false;
+
+	TriggerTownSpecialBuildingAction pack(town->id, subBuildingID);
+	sendRequest(&pack);
+	return true;
+}
+
 void CBattleCallback::battleMakeSpellAction(const BattleID & battleID, const BattleAction & action)
 {
 	assert(action.actionType == EActionType::HERO_SPELL);

+ 2 - 0
CCallback.h

@@ -76,6 +76,7 @@ public:
 	//town
 	virtual void recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero, const HeroTypeID & nextHero=HeroTypeID::NONE)=0;
 	virtual bool buildBuilding(const CGTownInstance *town, BuildingID buildingID)=0;
+	virtual bool triggerTownSpecialBuildingAction(const CGTownInstance *town, BuildingSubID::EBuildingSubID subBuildingID)=0;
 	virtual void recruitCreatures(const CGDwelling *obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level=-1)=0;
 	virtual bool upgradeCreature(const CArmedInstance *obj, SlotID stackPos, CreatureID newID=CreatureID::NONE)=0; //if newID==-1 then best possible upgrade will be made
 	virtual void swapGarrisonHero(const CGTownInstance *town)=0;
@@ -182,6 +183,7 @@ public:
 	void manageHeroCostume(ObjectInstanceID hero, size_t costumeIdx, bool saveCostume) override;
 	void eraseArtifactByClient(const ArtifactLocation & al) override;
 	bool buildBuilding(const CGTownInstance *town, BuildingID buildingID) override;
+	bool triggerTownSpecialBuildingAction(const CGTownInstance *town, BuildingSubID::EBuildingSubID subBuildingID) override;
 	void recruitCreatures(const CGDwelling * obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level=-1) override;
 	bool dismissCreature(const CArmedInstance *obj, SlotID stackPos) override;
 	bool upgradeCreature(const CArmedInstance *obj, SlotID stackPos, CreatureID newID=CreatureID::NONE) override;

+ 3 - 0
Mods/vcmi/config/vcmi/english.json

@@ -304,6 +304,9 @@
 	"vcmi.townHall.greetingCustomUntil"     : " until next battle.",
 	"vcmi.townHall.greetingInTownMagicWell" : "%s has restored your spell points to maximum.",
 
+	"vcmi.townStructure.bank.borrow" : "You enter the bank. A banker sees you and says: \"We have made a special offer for you. You can take a loan of 2500 gold from us for 5 days. You will have to repay 500 gold every day.\"",
+	"vcmi.townStructure.bank.payBack" : "You enter the bank. A banker sees you and says: \"You have already got your loan. Pay it back before taking a new one.\"",
+
 	"vcmi.logicalExpressions.anyOf"  : "Any of the following:",
 	"vcmi.logicalExpressions.allOf"  : "All of the following:",
 	"vcmi.logicalExpressions.noneOf" : "None of the following:",

+ 19 - 0
client/windows/CCastleInterface.cpp

@@ -814,6 +814,10 @@ void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuil
 						enterAnyThievesGuild();
 						break;
 
+				case BuildingSubID::BANK:
+						enterBank();
+						break;
+
 				default:
 						enterBuilding(building);
 						break;
@@ -1054,6 +1058,21 @@ void CCastleBuildings::enterAnyThievesGuild()
 	LOCPLINT->showInfoDialog(CGI->generaltexth->translate("vcmi.adventureMap.noTownWithTavern"));
 }
 
+void CCastleBuildings::enterBank()
+{
+	std::vector<std::shared_ptr<CComponent>> components;
+	if(town->bonusValue.second > 0)
+	{
+		components.push_back(std::make_shared<CComponent>(ComponentType::RESOURCE_PER_DAY, GameResID(GameResID::GOLD), -500));
+		LOCPLINT->showInfoDialog(CGI->generaltexth->translate("vcmi.townStructure.bank.payBack"), components);
+	}
+	else{
+	
+		components.push_back(std::make_shared<CComponent>(ComponentType::RESOURCE, GameResID(GameResID::GOLD), 2500));
+		LOCPLINT->showYesNoDialog(CGI->generaltexth->translate("vcmi.townStructure.bank.borrow"), [this](){ LOCPLINT->cb->triggerTownSpecialBuildingAction(town, BuildingSubID::BANK); }, nullptr, components);
+	}
+}
+
 void CCastleBuildings::enterAnyMarket()
 {
 	if(town->builtBuildings.count(BuildingID::MARKETPLACE))

+ 1 - 0
client/windows/CCastleInterface.h

@@ -170,6 +170,7 @@ public:
 	void enterMagesGuild();
 	void enterAnyMarket();
 	void enterAnyThievesGuild();
+	void enterBank();
 	void enterToTheQuickRecruitmentWindow();
 
 	void buildingClicked(BuildingID building, BuildingSubID::EBuildingSubID subID = BuildingSubID::NONE, BuildingID upgrades = BuildingID::NONE);

+ 1 - 0
lib/constants/Enumerations.h

@@ -51,6 +51,7 @@ namespace BuildingSubID
 		LIGHTHOUSE,
 		TREASURY,
 		THIEVES_GUILD,
+		BANK,
 		CUSTOM_VISITING_BONUS,
 		CUSTOM_VISITING_REWARD
 	};

+ 2 - 1
lib/constants/StringConstants.h

@@ -199,7 +199,8 @@ namespace MappedKeys
 		{ "experienceVisitingBonus", BuildingSubID::EXPERIENCE_VISITING_BONUS },
 		{ "lighthouse", BuildingSubID::LIGHTHOUSE },
 		{ "treasury", BuildingSubID::TREASURY },
-		{ "thievesGuild", BuildingSubID::THIEVES_GUILD }
+		{ "thievesGuild", BuildingSubID::THIEVES_GUILD },
+		{ "bank", BuildingSubID::BANK }
 	};
 
 	static const std::map<std::string, EMarketMode> MARKET_NAMES_TO_TYPES =

+ 8 - 0
lib/mapObjects/CGTownInstance.cpp

@@ -619,6 +619,14 @@ void CGTownInstance::newTurn(vstd::RNG & rand) const
 	
 	for(const auto * rewardableBuilding : getBonusingBuildings(BuildingSubID::CUSTOM_VISITING_REWARD))
 		rewardableBuilding->newTurn(rand);
+		
+	if(hasBuilt(BuildingSubID::BANK) && bonusValue.second > 0)
+	{
+		TResources res;
+		res[EGameResID::GOLD] = -500;
+		cb->giveResources(getOwner(), res);
+		cb->setObjPropertyValue(id, ObjProperty::BONUS_VALUE_SECOND, bonusValue.second - 500);
+	}
 }
 /*
 int3 CGTownInstance::getSightCenter() const

+ 1 - 1
lib/mapObjects/CGTownInstance.h

@@ -66,7 +66,7 @@ public:
 	std::vector<SpellID> possibleSpells, obligatorySpells;
 	std::vector<std::vector<SpellID> > spells; //spells[level] -> vector of spells, first will be available in guild
 	std::vector<CCastleEvent> events;
-	std::pair<si32, si32> bonusValue;//var to store town bonuses (rampart = resources from mystic pond);
+	std::pair<si32, si32> bonusValue;//var to store town bonuses (rampart = resources from mystic pond, factory = save debts);
 
 	//////////////////////////////////////////////////////////////////////////
 	template <typename Handler> void serialize(Handler &h)

+ 1 - 0
lib/networkPacks/NetPackVisitor.h

@@ -128,6 +128,7 @@ public:
 	virtual void visitBulkSmartSplitStack(BulkSmartSplitStack & pack) {}
 	virtual void visitDisbandCreature(DisbandCreature & pack) {}
 	virtual void visitBuildStructure(BuildStructure & pack) {}
+	virtual void visitTriggerTownSpecialBuildingAction(TriggerTownSpecialBuildingAction & pack) {}
 	virtual void visitRazeStructure(RazeStructure & pack) {}
 	virtual void visitRecruitCreatures(RecruitCreatures & pack) {}
 	virtual void visitUpgradeCreature(UpgradeCreature & pack) {}

+ 5 - 0
lib/networkPacks/NetPacksLib.cpp

@@ -590,6 +590,11 @@ void BuildStructure::visitTyped(ICPackVisitor & visitor)
 	visitor.visitBuildStructure(*this);
 }
 
+void TriggerTownSpecialBuildingAction::visitTyped(ICPackVisitor & visitor)
+{
+	visitor.visitTriggerTownSpecialBuildingAction(*this);
+}
+
 void RazeStructure::visitTyped(ICPackVisitor & visitor)
 {
 	visitor.visitRazeStructure(*this);

+ 21 - 0
lib/networkPacks/PacksForServer.h

@@ -280,6 +280,27 @@ struct DLL_LINKAGE BuildStructure : public CPackForServer
 	}
 };
 
+struct DLL_LINKAGE TriggerTownSpecialBuildingAction : public CPackForServer
+{
+	TriggerTownSpecialBuildingAction() = default;
+	TriggerTownSpecialBuildingAction(const ObjectInstanceID & TID, const BuildingSubID::EBuildingSubID SID)
+		: tid(TID)
+		, sid(SID)
+	{
+	}
+	ObjectInstanceID tid;
+	BuildingSubID::EBuildingSubID sid;
+
+	void visitTyped(ICPackVisitor & visitor) override;
+
+	template <typename Handler> void serialize(Handler & h)
+	{
+		h & static_cast<CPackForServer &>(*this);
+		h & tid;
+		h & sid;
+	}
+};
+
 struct DLL_LINKAGE RazeStructure : public BuildStructure
 {
 	void visitTyped(ICPackVisitor & visitor) override;

+ 1 - 0
lib/registerTypes/RegisterTypesServerPacks.h

@@ -27,6 +27,7 @@ void registerTypesServerPacks(Serializer &s)
 	s.template registerType<CPackForServer, ArrangeStacks>();
 	s.template registerType<CPackForServer, DisbandCreature>();
 	s.template registerType<CPackForServer, BuildStructure>();
+	s.template registerType<CPackForServer, TriggerTownSpecialBuildingAction>();
 	s.template registerType<CPackForServer, RecruitCreatures>();
 	s.template registerType<CPackForServer, UpgradeCreature>();
 	s.template registerType<CPackForServer, GarrisonHeroSwap>();

+ 19 - 0
server/CGameHandler.cpp

@@ -2497,6 +2497,25 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
 	return true;
 }
 
+bool CGameHandler::triggerTownSpecialBuildingAction(ObjectInstanceID tid, BuildingSubID::EBuildingSubID sid)
+{
+	const CGTownInstance * t = getTown(tid);
+
+	if(t->town->getBuildingType(sid) == BuildingID::NONE)
+		return false;
+
+	if(sid == BuildingSubID::EBuildingSubID::BANK)
+	{
+		TResources res;
+		res[EGameResID::GOLD] = 2500;
+		giveResources(t->getOwner(), res);
+
+		setObjPropertyValue(t->id, ObjProperty::BONUS_VALUE_SECOND, 2500);
+	}
+
+	return true;
+}
+
 bool CGameHandler::razeStructure (ObjectInstanceID tid, BuildingID bid)
 {
 ///incomplete, simply erases target building

+ 1 - 0
server/CGameHandler.h

@@ -213,6 +213,7 @@ public:
 	bool upgradeCreature( ObjectInstanceID objid, SlotID pos, CreatureID upgID );
 	bool recruitCreatures(ObjectInstanceID objid, ObjectInstanceID dst, CreatureID crid, ui32 cram, si32 level, PlayerColor player);
 	bool buildStructure(ObjectInstanceID tid, BuildingID bid, bool force=false);//force - for events: no cost, no checkings
+	bool triggerTownSpecialBuildingAction(ObjectInstanceID tid, BuildingSubID::EBuildingSubID sid);
 	bool razeStructure(ObjectInstanceID tid, BuildingID bid);
 	bool disbandCreature( ObjectInstanceID id, SlotID pos );
 	bool arrangeStacks( ObjectInstanceID id1, ObjectInstanceID id2, ui8 what, SlotID p1, SlotID p2, si32 val, PlayerColor player);

+ 8 - 0
server/NetPacksServer.cpp

@@ -139,6 +139,14 @@ void ApplyGhNetPackVisitor::visitBuildStructure(BuildStructure & pack)
 	result = gh.buildStructure(pack.tid, pack.bid);
 }
 
+void ApplyGhNetPackVisitor::visitTriggerTownSpecialBuildingAction(TriggerTownSpecialBuildingAction & pack)
+{
+	gh.throwIfWrongOwner(&pack, pack.tid);
+	gh.throwIfPlayerNotActive(&pack);
+
+	result = gh.triggerTownSpecialBuildingAction(pack.tid, pack.sid);
+}
+
 void ApplyGhNetPackVisitor::visitRecruitCreatures(RecruitCreatures & pack)
 {
 	gh.throwIfWrongPlayer(&pack);

+ 1 - 0
server/ServerNetPackVisitors.h

@@ -41,6 +41,7 @@ public:
 	void visitBulkSmartSplitStack(BulkSmartSplitStack & pack) override;
 	void visitDisbandCreature(DisbandCreature & pack) override;
 	void visitBuildStructure(BuildStructure & pack) override;
+	void visitTriggerTownSpecialBuildingAction(TriggerTownSpecialBuildingAction & pack) override;
 	void visitRecruitCreatures(RecruitCreatures & pack) override;
 	void visitUpgradeCreature(UpgradeCreature & pack) override;
 	void visitGarrisonHeroSwap(GarrisonHeroSwap & pack) override;