mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there. * Declared existing Entity APIs. * Added basic script context caching * Started Lua script module * Started Lua spell effect API * Started script state persistence * Started battle info callback binding * CommitPackage removed * Extracted spells::Caster to own header; Expanded Spell API. * implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C * !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented * Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key) * Re-enabled VERM macros. * !?GM0 added * !?TM implemented * Added !!MF:N * Started !?OB, !!BM, !!HE, !!OW, !!UN * Added basic support of w-variables * Added support for ERM indirect variables * Made !?FU regular trigger * !!re (ERA loop receiver) implemented * Fixed ERM receivers with zero args.
This commit is contained in:
		| @@ -29,7 +29,7 @@ matrix: | ||||
|     env: VCMI_PLATFORM='mxe' MXE_TARGET=i686-w64-mingw32.shared VCMI_CMAKE_FLAGS='-DENABLE_TEST=0' | ||||
|     sudo: required | ||||
|   - os: osx | ||||
|     env: VCMI_PLATFORM='mac' | ||||
|     env: VCMI_PLATFORM='mac' VCMI_CMAKE_FLAGS='-DENABLE_TEST=0' | ||||
|  | ||||
| addons: | ||||
|   apt: | ||||
|   | ||||
| @@ -69,7 +69,7 @@ | ||||
| 			<Add option="-Wno-overloaded-virtual" /> | ||||
| 			<Add option="-DBOOST_ALL_DYN_LINK" /> | ||||
| 			<Add option="-DBOOST_SYSTEM_NO_DEPRECATED" /> | ||||
| 			<Add option="-D_WIN32_WINNT=0x0501" /> | ||||
| 			<Add option="-D_WIN32_WINNT=0x0600" /> | ||||
| 			<Add option="-D_WIN32" /> | ||||
| 			<Add directory="$(#boost.include)" /> | ||||
| 			<Add directory="../../include" /> | ||||
| @@ -100,9 +100,6 @@ | ||||
| 		<Unit filename="common.h" /> | ||||
| 		<Unit filename="main.cpp" /> | ||||
| 		<Extensions> | ||||
| 			<code_completion /> | ||||
| 			<envvars /> | ||||
| 			<debugger /> | ||||
| 			<lib_finder disable_auto="1" /> | ||||
| 		</Extensions> | ||||
| 	</Project> | ||||
|   | ||||
| @@ -10,8 +10,6 @@ | ||||
| #include "StdInc.h" | ||||
| #include "BattleAI.h" | ||||
|  | ||||
| #include <vstd/RNG.h> | ||||
|  | ||||
| #include "StackWithBonuses.h" | ||||
| #include "EnemyInfo.h" | ||||
| #include "../../lib/CStopWatch.h" | ||||
| @@ -26,26 +24,6 @@ | ||||
| #define LOGL(text) print(text) | ||||
| #define LOGFL(text, formattingEl) print(boost::str(boost::format(text) % formattingEl)) | ||||
|  | ||||
| class RNGStub : public vstd::RNG | ||||
| { | ||||
| public: | ||||
| 	vstd::TRandI64 getInt64Range(int64_t lower, int64_t upper) override | ||||
| 	{ | ||||
| 		return [=]()->int64_t | ||||
| 		{ | ||||
| 			return (lower + upper)/2; | ||||
| 		}; | ||||
| 	} | ||||
|  | ||||
| 	vstd::TRand getDoubleRange(double lower, double upper) override | ||||
| 	{ | ||||
| 		return [=]()->double | ||||
| 		{ | ||||
| 			return (lower + upper)/2; | ||||
| 		}; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| enum class SpellTypes | ||||
| { | ||||
| 	ADVENTURE, BATTLE, OTHER | ||||
| @@ -53,10 +31,10 @@ enum class SpellTypes | ||||
|  | ||||
| SpellTypes spellType(const CSpell * spell) | ||||
| { | ||||
| 	if(!spell->isCombatSpell() || spell->isCreatureAbility()) | ||||
| 	if(!spell->isCombat() || spell->isCreatureAbility()) | ||||
| 		return SpellTypes::OTHER; | ||||
|  | ||||
| 	if(spell->isOffensiveSpell() || spell->hasEffects() || spell->hasBattleEffects()) | ||||
| 	if(spell->isOffensive() || spell->hasEffects() || spell->hasBattleEffects()) | ||||
| 		return SpellTypes::BATTLE; | ||||
|  | ||||
| 	return SpellTypes::OTHER; | ||||
| @@ -83,7 +61,9 @@ std::vector<BattleHex> CBattleAI::getBrokenWallMoatHexes() const | ||||
| } | ||||
|  | ||||
| CBattleAI::CBattleAI() | ||||
| 	: side(-1), wasWaitingForRealize(false), wasUnlockingGs(false) | ||||
| 	: side(-1), | ||||
| 	wasWaitingForRealize(false), | ||||
| 	wasUnlockingGs(false) | ||||
| { | ||||
| } | ||||
|  | ||||
| @@ -97,12 +77,13 @@ CBattleAI::~CBattleAI() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CBattleAI::init(std::shared_ptr<CBattleCallback> CB) | ||||
| void CBattleAI::init(std::shared_ptr<Environment> ENV, std::shared_ptr<CBattleCallback> CB) | ||||
| { | ||||
| 	setCbc(CB); | ||||
| 	env = ENV; | ||||
| 	cb = CB; | ||||
| 	playerID = *CB->getPlayerID(); //TODO should be sth in callback | ||||
| 	wasWaitingForRealize = cb->waitTillRealize; | ||||
| 	wasWaitingForRealize = CB->waitTillRealize; | ||||
| 	wasUnlockingGs = CB->unlockGsWhenWaiting; | ||||
| 	CB->waitTillRealize = true; | ||||
| 	CB->unlockGsWhenWaiting = false; | ||||
| @@ -131,7 +112,7 @@ BattleAction CBattleAI::activeStack( const CStack * stack ) | ||||
|  | ||||
| 		attemptCastingSpell(); | ||||
|  | ||||
| 		if(auto ret = getCbc()->battleIsFinished()) | ||||
| 		if(auto ret = cb->battleIsFinished()) | ||||
| 		{ | ||||
| 			//spellcast may finish battle | ||||
| 			//send special preudo-action | ||||
| @@ -144,7 +125,7 @@ BattleAction CBattleAI::activeStack( const CStack * stack ) | ||||
| 			return *action; | ||||
| 		//best action is from effective owner point if view, we are effective owner as we received "activeStack" | ||||
|  | ||||
| 	 | ||||
|  | ||||
| 		//evaluate casting spell for spellcasting stack | ||||
| 		boost::optional<PossibleSpellcast> bestSpellcast(boost::none); | ||||
| 		//TODO: faerie dragon type spell should be selected by server | ||||
| @@ -174,7 +155,7 @@ BattleAction CBattleAI::activeStack( const CStack * stack ) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		HypotheticBattle hb(getCbc()); | ||||
| 		HypotheticBattle hb(env.get(), cb); | ||||
|  | ||||
| 		PotentialTargets targets(stack, &hb); | ||||
|  | ||||
| @@ -199,7 +180,7 @@ BattleAction CBattleAI::activeStack( const CStack * stack ) | ||||
| 				); | ||||
|  | ||||
| 				return BattleAction::makeMeleeAttack(stack,	bestAttack.attack.defender->getPosition(), bestAttack.from); | ||||
| 			} | ||||
| 		} | ||||
| 		} | ||||
| 		else if(bestSpellcast.is_initialized()) | ||||
| 		{ | ||||
| @@ -210,7 +191,7 @@ BattleAction CBattleAI::activeStack( const CStack * stack ) | ||||
| 			if(stack->waited()) | ||||
| 			{ | ||||
| 				//ThreatMap threatsToUs(stack); // These lines may be usefull but they are't used in the code. | ||||
| 				auto dists = getCbc()->getReachability(stack); | ||||
| 				auto dists = cb->getReachability(stack); | ||||
| 				if(!targets.unreachableEnemies.empty()) | ||||
| 				{ | ||||
| 					auto closestEnemy = vstd::minElementByFun(targets.unreachableEnemies, [&](const battle::Unit * enemy) -> int | ||||
| @@ -242,7 +223,7 @@ BattleAction CBattleAI::activeStack( const CStack * stack ) | ||||
| 					return BattleAction::makeMove(stack, stack->getPosition().cloneInDirection(BattleHex::RIGHT)); | ||||
| 				else | ||||
| 					return goTowardsNearest(stack, brokenWallMoat); | ||||
| 			} | ||||
| 	} | ||||
| 		} | ||||
| 	} | ||||
| 	catch(boost::thread_interrupted &) | ||||
| @@ -279,10 +260,10 @@ BattleAction CBattleAI::goTowardsNearest(const CStack * stack, std::vector<Battl | ||||
|  | ||||
| 		if(stack->coversPos(hex)) | ||||
| 		{ | ||||
| 			logAi->warn("Warning: already standing on neighbouring tile!"); | ||||
| 			//We shouldn't even be here... | ||||
| 			return BattleAction::makeDefend(stack); | ||||
| 		} | ||||
| 		logAi->warn("Warning: already standing on neighbouring tile!"); | ||||
| 		//We shouldn't even be here... | ||||
| 		return BattleAction::makeDefend(stack); | ||||
| 	} | ||||
| 	} | ||||
|  | ||||
| 	BattleHex bestNeighbor = hexes.front(); | ||||
| @@ -330,7 +311,7 @@ BattleAction CBattleAI::useCatapult(const CStack * stack) | ||||
| 	if(cb->battleGetGateState() == EGateState::CLOSED) | ||||
| 	{ | ||||
| 		targetHex = cb->wallPartToBattleHex(EWallPart::GATE); | ||||
| 	} | ||||
| } | ||||
| 	else | ||||
| 	{ | ||||
| 		EWallPart::EWallPart wallParts[] = { | ||||
| @@ -381,9 +362,9 @@ void CBattleAI::attemptCastingSpell() | ||||
| 	LOGL("Casting spells sounds like fun. Let's see..."); | ||||
| 	//Get all spells we can cast | ||||
| 	std::vector<const CSpell*> possibleSpells; | ||||
| 	vstd::copy_if(VLC->spellh->objects, std::back_inserter(possibleSpells), [hero](const CSpell *s) -> bool | ||||
| 	vstd::copy_if(VLC->spellh->objects, std::back_inserter(possibleSpells), [hero, this](const CSpell *s) -> bool | ||||
| 	{ | ||||
| 		return s->canBeCast(getCbc().get(), spells::Mode::HERO, hero); | ||||
| 		return s->canBeCast(cb.get(), spells::Mode::HERO, hero); | ||||
| 	}); | ||||
| 	LOGFL("I can cast %d spells.", possibleSpells.size()); | ||||
|  | ||||
| @@ -398,7 +379,7 @@ void CBattleAI::attemptCastingSpell() | ||||
| 	std::vector<PossibleSpellcast> possibleCasts; | ||||
| 	for(auto spell : possibleSpells) | ||||
| 	{ | ||||
| 		spells::BattleCast temp(getCbc().get(), hero, spells::Mode::HERO, spell); | ||||
| 		spells::BattleCast temp(cb.get(), hero, spells::Mode::HERO, spell); | ||||
|  | ||||
| 		for(auto & target : temp.findPotentialTargets()) | ||||
| 		{ | ||||
| @@ -500,8 +481,6 @@ void CBattleAI::attemptCastingSpell() | ||||
| 		return ourTurnSpan >= minTurnSpan; | ||||
| 	}; | ||||
|  | ||||
| 	RNGStub rngStub; | ||||
|  | ||||
| 	ValueMap valueOfStack; | ||||
| 	ValueMap healthOfStack; | ||||
|  | ||||
| @@ -536,7 +515,8 @@ void CBattleAI::attemptCastingSpell() | ||||
| 	{ | ||||
| 		bool enemyHadTurn = false; | ||||
|  | ||||
| 		HypotheticBattle state(cb); | ||||
| 		HypotheticBattle state(env.get(), cb); | ||||
|  | ||||
| 		evaluateQueue(valueOfStack, turnOrder, &state, 0, &enemyHadTurn); | ||||
|  | ||||
| 		if(!enemyHadTurn) | ||||
| @@ -551,13 +531,17 @@ void CBattleAI::attemptCastingSpell() | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	auto evaluateSpellcast = [&] (PossibleSpellcast * ps) | ||||
| 	struct ScriptsCache | ||||
| 	{ | ||||
| 		HypotheticBattle state(cb); | ||||
| 		//todo: re-implement scripts context cache | ||||
| 	}; | ||||
|  | ||||
| 	auto evaluateSpellcast = [&] (PossibleSpellcast * ps, std::shared_ptr<ScriptsCache>) | ||||
| 	{ | ||||
| 		HypotheticBattle state(env.get(), cb); | ||||
|  | ||||
| 		spells::BattleCast cast(&state, hero, spells::Mode::HERO, ps->spell); | ||||
| 		cast.target = ps->dest; | ||||
| 		cast.cast(&state, rngStub); | ||||
| 		cast.castEval(state.getServerCallback(), ps->dest); | ||||
| 		ValueMap newHealthOfStack; | ||||
| 		ValueMap newValueOfStack; | ||||
|  | ||||
| @@ -617,10 +601,12 @@ void CBattleAI::attemptCastingSpell() | ||||
| 		} | ||||
| 	}; | ||||
|  | ||||
| 	std::vector<std::function<void()>> tasks; | ||||
| 	using EvalRunner = ThreadPool<ScriptsCache>; | ||||
|  | ||||
| 	EvalRunner::Tasks tasks; | ||||
|  | ||||
| 	for(PossibleSpellcast & psc : possibleCasts) | ||||
| 		tasks.push_back(std::bind(evaluateSpellcast, &psc)); | ||||
| 		tasks.push_back(std::bind(evaluateSpellcast, &psc, _1)); | ||||
|  | ||||
| 	uint32_t threadCount = boost::thread::hardware_concurrency(); | ||||
|  | ||||
| @@ -632,8 +618,15 @@ void CBattleAI::attemptCastingSpell() | ||||
|  | ||||
| 	CStopWatch timer; | ||||
|  | ||||
| 	CThreadHelper threadHelper(&tasks, threadCount); | ||||
| 	threadHelper.run(); | ||||
| 	std::vector<std::shared_ptr<ScriptsCache>> scriptsPool; | ||||
|  | ||||
| 	for(uint32_t idx = 0; idx < threadCount; idx++) | ||||
| 	{ | ||||
| 		scriptsPool.emplace_back(); | ||||
| 	} | ||||
|  | ||||
| 	EvalRunner runner(&tasks, scriptsPool); | ||||
| 	runner.run(); | ||||
|  | ||||
| 	LOGFL("Evaluation took %d ms", timer.getDiff()); | ||||
|  | ||||
| @@ -666,9 +659,9 @@ void CBattleAI::evaluateCreatureSpellcast(const CStack * stack, PossibleSpellcas | ||||
| 	using ValueMap = PossibleSpellcast::ValueMap; | ||||
|  | ||||
| 	RNGStub rngStub; | ||||
| 	HypotheticBattle state(getCbc()); | ||||
| 	TStacks all = getCbc()->battleGetAllStacks(false); | ||||
| 	 | ||||
| 	HypotheticBattle state(env.get(), cb); | ||||
| 	TStacks all = cb->battleGetAllStacks(false); | ||||
|  | ||||
| 	ValueMap healthOfStack; | ||||
| 	ValueMap newHealthOfStack; | ||||
|  | ||||
| @@ -678,8 +671,7 @@ void CBattleAI::evaluateCreatureSpellcast(const CStack * stack, PossibleSpellcas | ||||
| 	} | ||||
|  | ||||
| 	spells::BattleCast cast(&state, stack, spells::Mode::CREATURE_ACTIVE, ps.spell); | ||||
| 	cast.target = ps.dest; | ||||
| 	cast.cast(&state, rngStub); | ||||
| 	cast.castEval(state.getServerCallback(), ps.dest); | ||||
|  | ||||
| 	for(auto unit : all) | ||||
| 	{ | ||||
| @@ -710,7 +702,7 @@ void CBattleAI::evaluateCreatureSpellcast(const CStack * stack, PossibleSpellcas | ||||
| 	} | ||||
|  | ||||
| 	ps.value = totalGain; | ||||
| }; | ||||
| } | ||||
|  | ||||
| void CBattleAI::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool Side) | ||||
| { | ||||
|   | ||||
| @@ -51,6 +51,7 @@ class CBattleAI : public CBattleGameInterface | ||||
| { | ||||
| 	int side; | ||||
| 	std::shared_ptr<CBattleCallback> cb; | ||||
| 	std::shared_ptr<Environment> env; | ||||
|  | ||||
| 	//Previous setting of cb | ||||
| 	bool wasWaitingForRealize, wasUnlockingGs; | ||||
| @@ -59,7 +60,7 @@ public: | ||||
| 	CBattleAI(); | ||||
| 	~CBattleAI(); | ||||
|  | ||||
| 	void init(std::shared_ptr<CBattleCallback> CB) override; | ||||
| 	void init(std::shared_ptr<Environment> ENV, std::shared_ptr<CBattleCallback> CB) override; | ||||
| 	void attemptCastingSpell(); | ||||
|  | ||||
| 	void evaluateCreatureSpellcast(const CStack * stack, PossibleSpellcast & ps); //for offensive damaging spells only | ||||
| @@ -74,7 +75,7 @@ public: | ||||
| 	//void actionFinished(const BattleAction &action) override;//occurs AFTER every action taken by any stack or by the hero | ||||
| 	//void actionStarted(const BattleAction &action) override;//occurs BEFORE every action taken by any stack or by the hero | ||||
| 	//void battleAttack(const BattleAttack *ba) override; //called when stack is performing attack | ||||
| 	//void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa, const std::vector<MetaString> & battleLog) override; //called when stack receives damage (after battleAttack()) | ||||
| 	//void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa) override; //called when stack receives damage (after battleAttack()) | ||||
| 	//void battleEnd(const BattleResult *br) override; | ||||
| 	//void battleResultsApplied() override; //called when all effects of last battle are applied | ||||
| 	//void battleNewRoundFirst(int round) override; //called at the beginning of each turn before changes are applied; | ||||
|   | ||||
| @@ -10,8 +10,9 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <vcmi/spells/Magic.h> | ||||
|  | ||||
| #include "../../lib/battle/Destination.h" | ||||
| #include "../../lib/spells/Magic.h" | ||||
|  | ||||
| class CSpell; | ||||
|  | ||||
|   | ||||
| @@ -9,8 +9,14 @@ | ||||
|  */ | ||||
| #include "StdInc.h" | ||||
| #include "StackWithBonuses.h" | ||||
| #include "../../lib/NetPacksBase.h" | ||||
|  | ||||
| #include <vcmi/events/EventBus.h> | ||||
|  | ||||
| #include "../../lib/NetPacks.h" | ||||
| #include "../../lib/CStack.h" | ||||
| #include "../../lib/ScriptHandler.h" | ||||
|  | ||||
| using scripting::Pool; | ||||
|  | ||||
| void actualizeEffect(TBonusListPtr target, const Bonus & ef) | ||||
| { | ||||
| @@ -191,19 +197,27 @@ void StackWithBonuses::removeUnitBonus(const CSelector & selector) | ||||
| 	vstd::erase_if(bonusesToUpdate, [&](const Bonus & b){return selector(&b);}); | ||||
| } | ||||
|  | ||||
| void StackWithBonuses::spendMana(const spells::PacketSender * server, const int spellCost) const | ||||
| void StackWithBonuses::spendMana(ServerCallback * server, const int spellCost) const | ||||
| { | ||||
| 	//TODO: evaluate cast use | ||||
| } | ||||
|  | ||||
| HypotheticBattle::HypotheticBattle(Subject realBattle) | ||||
| HypotheticBattle::HypotheticBattle(const Environment * ENV, Subject realBattle) | ||||
| 	: BattleProxy(realBattle), | ||||
| 	env(ENV), | ||||
| 	bonusTreeVersion(1) | ||||
| { | ||||
| 	auto activeUnit = realBattle->battleActiveUnit(); | ||||
| 	activeUnitId = activeUnit ? activeUnit->unitId() : -1; | ||||
|  | ||||
| 	nextId = 0xF0000000; | ||||
| 	nextId = 0x00F00000; | ||||
|  | ||||
| 	eventBus.reset(new events::EventBus()); | ||||
|  | ||||
| 	localEnvironment.reset(new HypotheticEnvironment(this, env)); | ||||
| 	serverCallback.reset(new HypotheticServerCallback(this)); | ||||
|  | ||||
| 	pool.reset(new scripting::PoolImpl(localEnvironment.get(), serverCallback.get())); | ||||
| } | ||||
|  | ||||
| bool HypotheticBattle::unitHasAmmoCart(const battle::Unit * unit) const | ||||
| @@ -348,6 +362,11 @@ void HypotheticBattle::removeUnit(uint32_t id) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void HypotheticBattle::updateUnit(uint32_t id, const JsonNode & data) | ||||
| { | ||||
| 	//TODO: | ||||
| } | ||||
|  | ||||
| void HypotheticBattle::addUnitBonus(uint32_t id, const std::vector<Bonus> & bonus) | ||||
| { | ||||
| 	getForUpdate(id)->addUnitBonus(bonus); | ||||
| @@ -400,3 +419,107 @@ int64_t HypotheticBattle::getTreeVersion() const | ||||
| { | ||||
| 	return getBattleNode()->getTreeVersion() + bonusTreeVersion; | ||||
| } | ||||
|  | ||||
| Pool * HypotheticBattle::getContextPool() const | ||||
| { | ||||
| 	return pool.get(); | ||||
| } | ||||
|  | ||||
| ServerCallback * HypotheticBattle::getServerCallback() | ||||
| { | ||||
| 	return serverCallback.get(); | ||||
| } | ||||
|  | ||||
| HypotheticBattle::HypotheticServerCallback::HypotheticServerCallback(HypotheticBattle * owner_) | ||||
| 	:owner(owner_) | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| void HypotheticBattle::HypotheticServerCallback::complain(const std::string & problem) | ||||
| { | ||||
| 	logAi->error(problem); | ||||
| } | ||||
|  | ||||
| bool HypotheticBattle::HypotheticServerCallback::describeChanges() const | ||||
| { | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| vstd::RNG * HypotheticBattle::HypotheticServerCallback::getRNG() | ||||
| { | ||||
| 	return &rngStub; | ||||
| } | ||||
|  | ||||
| void HypotheticBattle::HypotheticServerCallback::apply(CPackForClient * pack) | ||||
| { | ||||
| 	logAi->error("Package of type %s is not allowed in battle evaluation", typeid(pack).name()); | ||||
| } | ||||
|  | ||||
| void HypotheticBattle::HypotheticServerCallback::apply(BattleLogMessage * pack) | ||||
| { | ||||
| 	pack->applyBattle(owner); | ||||
| } | ||||
|  | ||||
| void HypotheticBattle::HypotheticServerCallback::apply(BattleStackMoved * pack) | ||||
| { | ||||
| 	pack->applyBattle(owner); | ||||
| } | ||||
|  | ||||
| void HypotheticBattle::HypotheticServerCallback::apply(BattleUnitsChanged * pack) | ||||
| { | ||||
| 	pack->applyBattle(owner); | ||||
| } | ||||
|  | ||||
| void HypotheticBattle::HypotheticServerCallback::apply(SetStackEffect * pack) | ||||
| { | ||||
| 	pack->applyBattle(owner); | ||||
| } | ||||
|  | ||||
| void HypotheticBattle::HypotheticServerCallback::apply(StacksInjured * pack) | ||||
| { | ||||
| 	pack->applyBattle(owner); | ||||
| } | ||||
|  | ||||
| void HypotheticBattle::HypotheticServerCallback::apply(BattleObstaclesChanged * pack) | ||||
| { | ||||
| 	pack->applyBattle(owner); | ||||
| } | ||||
|  | ||||
| void HypotheticBattle::HypotheticServerCallback::apply(CatapultAttack * pack) | ||||
| { | ||||
| 	pack->applyBattle(owner); | ||||
| } | ||||
|  | ||||
| HypotheticBattle::HypotheticEnvironment::HypotheticEnvironment(HypotheticBattle * owner_, const Environment * upperEnvironment) | ||||
| 	: owner(owner_), | ||||
| 	env(upperEnvironment) | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| const Services * HypotheticBattle::HypotheticEnvironment::services() const | ||||
| { | ||||
| 	return env->services(); | ||||
| } | ||||
|  | ||||
| const Environment::BattleCb * HypotheticBattle::HypotheticEnvironment::battle() const | ||||
| { | ||||
| 	return owner; | ||||
| } | ||||
|  | ||||
| const Environment::GameCb * HypotheticBattle::HypotheticEnvironment::game() const | ||||
| { | ||||
| 	return env->game(); | ||||
| } | ||||
|  | ||||
| vstd::CLoggerBase * HypotheticBattle::HypotheticEnvironment::logger() const | ||||
| { | ||||
| 	return env->logger(); | ||||
| } | ||||
|  | ||||
| events::EventBus * HypotheticBattle::HypotheticEnvironment::eventBus() const | ||||
| { | ||||
| 	return owner->eventBus.get(); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -8,6 +8,12 @@ | ||||
|  * | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
| #include <vstd/RNG.h> | ||||
|  | ||||
| #include <vcmi/Environment.h> | ||||
| #include <vcmi/ServerCallback.h> | ||||
|  | ||||
| #include "../../lib/HeroBonus.h" | ||||
| #include "../../lib/battle/BattleProxy.h" | ||||
| #include "../../lib/battle/CUnitState.h" | ||||
| @@ -15,10 +21,30 @@ | ||||
| class HypotheticBattle; | ||||
| class CStack; | ||||
|  | ||||
| ///Fake random generator, used by AI to evaluate random server behavior | ||||
| class RNGStub : public vstd::RNG | ||||
| { | ||||
| public: | ||||
| 	vstd::TRandI64 getInt64Range(int64_t lower, int64_t upper) override | ||||
| 	{ | ||||
| 		return [=]()->int64_t | ||||
| 		{ | ||||
| 			return (lower + upper)/2; | ||||
| 		}; | ||||
| 	} | ||||
|  | ||||
| 	vstd::TRand getDoubleRange(double lower, double upper) override | ||||
| 	{ | ||||
| 		return [=]()->double | ||||
| 		{ | ||||
| 			return (lower + upper)/2; | ||||
| 		}; | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| class StackWithBonuses : public battle::CUnitState, public virtual IBonusBearer | ||||
| { | ||||
| public: | ||||
|  | ||||
| 	std::vector<Bonus> bonusesToAdd; | ||||
| 	std::vector<Bonus> bonusesToUpdate; | ||||
| 	std::set<std::shared_ptr<Bonus>> bonusesToRemove; | ||||
| @@ -53,7 +79,7 @@ public: | ||||
|  | ||||
| 	void removeUnitBonus(const CSelector & selector); | ||||
|  | ||||
| 	void spendMana(const spells::PacketSender * server, const int spellCost) const override; | ||||
| 	void spendMana(ServerCallback * server, const int spellCost) const override; | ||||
|  | ||||
| private: | ||||
| 	const IBonusBearer * origBearer; | ||||
| @@ -72,7 +98,9 @@ class HypotheticBattle : public BattleProxy, public battle::IUnitEnvironment | ||||
| public: | ||||
| 	std::map<uint32_t, std::shared_ptr<StackWithBonuses>> stackStates; | ||||
|  | ||||
| 	HypotheticBattle(Subject realBattle); | ||||
| 	const Environment * env; | ||||
|  | ||||
| 	HypotheticBattle(const Environment * ENV, Subject realBattle); | ||||
|  | ||||
| 	bool unitHasAmmoCart(const battle::Unit * unit) const override; | ||||
| 	PlayerColor unitEffectiveOwner(const battle::Unit * unit) const override; | ||||
| @@ -90,6 +118,7 @@ public: | ||||
| 	void setUnitState(uint32_t id, const JsonNode & data, int64_t healthDelta) override; | ||||
| 	void moveUnit(uint32_t id, BattleHex destination) override; | ||||
| 	void removeUnit(uint32_t id) override; | ||||
| 	void updateUnit(uint32_t id, const JsonNode & data) override; | ||||
|  | ||||
| 	void addUnitBonus(uint32_t id, const std::vector<Bonus> & bonus) override; | ||||
| 	void updateUnitBonus(uint32_t id, const std::vector<Bonus> & bonus) override; | ||||
| @@ -107,8 +136,59 @@ public: | ||||
|  | ||||
| 	int64_t getTreeVersion() const; | ||||
|  | ||||
| 	scripting::Pool * getContextPool() const override; | ||||
|  | ||||
| 	ServerCallback * getServerCallback(); | ||||
|  | ||||
| private: | ||||
|  | ||||
| 	class HypotheticServerCallback : public ServerCallback | ||||
| 	{ | ||||
| 	public: | ||||
| 		HypotheticServerCallback(HypotheticBattle * owner_); | ||||
|  | ||||
| 		void complain(const std::string & problem) override; | ||||
| 		bool describeChanges() const override; | ||||
|  | ||||
| 		vstd::RNG * getRNG() override; | ||||
|  | ||||
| 		void apply(CPackForClient * pack) override; | ||||
|  | ||||
| 		void apply(BattleLogMessage * pack) override; | ||||
| 		void apply(BattleStackMoved * pack) override; | ||||
| 		void apply(BattleUnitsChanged * pack) override; | ||||
| 		void apply(SetStackEffect * pack) override; | ||||
| 		void apply(StacksInjured * pack) override; | ||||
| 		void apply(BattleObstaclesChanged * pack) override; | ||||
| 		void apply(CatapultAttack * pack) override; | ||||
| 	private: | ||||
| 		HypotheticBattle * owner; | ||||
| 		RNGStub rngStub; | ||||
| 	}; | ||||
|  | ||||
| 	class HypotheticEnvironment : public Environment | ||||
| 	{ | ||||
| 	public: | ||||
| 		HypotheticEnvironment(HypotheticBattle * owner_, const Environment * upperEnvironment); | ||||
|  | ||||
| 		const Services * services() const override; | ||||
| 		const BattleCb * battle() const override; | ||||
| 		const GameCb * game() const override; | ||||
| 		vstd::CLoggerBase * logger() const override; | ||||
| 		events::EventBus * eventBus() const override; | ||||
|  | ||||
| 	private: | ||||
| 		HypotheticBattle * owner; | ||||
| 		const Environment * env; | ||||
| 	}; | ||||
|  | ||||
| 	int32_t bonusTreeVersion; | ||||
| 	int32_t activeUnitId; | ||||
| 	mutable uint32_t nextId; | ||||
|  | ||||
| 	std::unique_ptr<HypotheticServerCallback> serverCallback; | ||||
| 	std::unique_ptr<HypotheticEnvironment> localEnvironment; | ||||
|  | ||||
| 	mutable std::shared_ptr<scripting::Pool> pool; | ||||
| 	mutable std::shared_ptr<events::EventBus> eventBus; | ||||
| }; | ||||
|   | ||||
| @@ -12,12 +12,22 @@ | ||||
|  | ||||
| #include "../../lib/CRandomGenerator.h" | ||||
|  | ||||
| void CEmptyAI::init(std::shared_ptr<CCallback> CB) | ||||
| void CEmptyAI::saveGame(BinarySerializer & h, const int version) | ||||
| { | ||||
| } | ||||
|  | ||||
| void CEmptyAI::loadGame(BinaryDeserializer & h, const int version) | ||||
| { | ||||
| } | ||||
|  | ||||
| void CEmptyAI::init(std::shared_ptr<Environment> ENV, std::shared_ptr<CCallback> CB) | ||||
| { | ||||
| 	cb = CB; | ||||
| 	env = ENV; | ||||
| 	human=false; | ||||
| 	playerID = *cb->getMyColor(); | ||||
| } | ||||
|  | ||||
| void CEmptyAI::yourTurn() | ||||
| { | ||||
| 	cb->endTurn(); | ||||
|   | ||||
| @@ -19,7 +19,10 @@ class CEmptyAI : public CGlobalAI | ||||
| 	std::shared_ptr<CCallback> cb; | ||||
|  | ||||
| public: | ||||
| 	void init(std::shared_ptr<CCallback> CB) override; | ||||
| 	virtual void saveGame(BinarySerializer & h, const int version) override; | ||||
| 	virtual void loadGame(BinaryDeserializer & h, const int version) override; | ||||
|  | ||||
| 	void init(std::shared_ptr<Environment> ENV, std::shared_ptr<CCallback> CB) override; | ||||
| 	void yourTurn() override; | ||||
| 	void heroGotLevel(const CGHeroInstance *hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> &skills, QueryID queryID) override; | ||||
| 	void commanderGotLevel (const CCommanderInstance * commander, std::vector<ui32> skills, QueryID queryID) override; | ||||
|   | ||||
| @@ -63,7 +63,7 @@ | ||||
| 			<Add option="-Wno-unused-parameter" /> | ||||
| 			<Add option="-Wno-overloaded-virtual" /> | ||||
| 			<Add option="-fpermissive" /> | ||||
| 			<Add option="-D_WIN32_WINNT=0x0501" /> | ||||
| 			<Add option="-D_WIN32_WINNT=0x0600" /> | ||||
| 			<Add option="-D_WIN32" /> | ||||
| 			<Add option="-DBOOST_ALL_DYN_LINK" /> | ||||
| 			<Add directory="$(#boost.include)" /> | ||||
| @@ -80,9 +80,6 @@ | ||||
| 		</Unit> | ||||
| 		<Unit filename="exp_funcs.cpp" /> | ||||
| 		<Extensions> | ||||
| 			<code_completion /> | ||||
| 			<envvars /> | ||||
| 			<debugger /> | ||||
| 			<lib_finder disable_auto="1" /> | ||||
| 		</Extensions> | ||||
| 	</Project> | ||||
|   | ||||
| @@ -18,6 +18,7 @@ | ||||
| 				<Linker> | ||||
| 					<Add option="-lboost_system$(#boost.libsuffix32)" /> | ||||
| 					<Add option="-lVCMI_lib" /> | ||||
| 					<Add directory="$(#boost.lib32)" /> | ||||
| 				</Linker> | ||||
| 			</Target> | ||||
| 			<Target title="Release-win32"> | ||||
| @@ -34,6 +35,7 @@ | ||||
| 					<Add option="-s" /> | ||||
| 					<Add option="-lboost_system$(#boost.libsuffix32)" /> | ||||
| 					<Add option="-lVCMI_lib" /> | ||||
| 					<Add directory="$(#boost.lib32)" /> | ||||
| 				</Linker> | ||||
| 			</Target> | ||||
| 			<Target title="Debug-win64"> | ||||
| @@ -41,10 +43,11 @@ | ||||
| 				<Option output="../StupidAI" imp_lib="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).a" def_file="$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME).def" prefix_auto="1" extension_auto="1" /> | ||||
| 				<Option object_output="obj/Debug/x64" /> | ||||
| 				<Option type="3" /> | ||||
| 				<Option compiler="gcc" /> | ||||
| 				<Option compiler="gnu_gcc_compiler_x64" /> | ||||
| 				<Linker> | ||||
| 					<Add option="-lboost_system$(#boost.libsuffix64)" /> | ||||
| 					<Add option="-lVCMI_lib" /> | ||||
| 					<Add directory="$(#boost.lib64)" /> | ||||
| 				</Linker> | ||||
| 			</Target> | ||||
| 		</Build> | ||||
| @@ -61,13 +64,12 @@ | ||||
| 			<Add option="-Wno-overloaded-virtual" /> | ||||
| 			<Add option="-DBOOST_ALL_DYN_LINK" /> | ||||
| 			<Add option="-DBOOST_SYSTEM_NO_DEPRECATED" /> | ||||
| 			<Add option="-D_WIN32_WINNT=0x0501" /> | ||||
| 			<Add option="-D_WIN32_WINNT=0x0600" /> | ||||
| 			<Add option="-D_WIN32" /> | ||||
| 			<Add directory="$(#boost.include)" /> | ||||
| 			<Add directory="../../include" /> | ||||
| 		</Compiler> | ||||
| 		<Linker> | ||||
| 			<Add directory="$(#boost.lib32)" /> | ||||
| 			<Add directory="../.." /> | ||||
| 		</Linker> | ||||
| 		<Unit filename="StdInc.h"> | ||||
| @@ -77,10 +79,6 @@ | ||||
| 		<Unit filename="StupidAI.cpp" /> | ||||
| 		<Unit filename="StupidAI.h" /> | ||||
| 		<Unit filename="main.cpp" /> | ||||
| 		<Extensions> | ||||
| 			<code_completion /> | ||||
| 			<envvars /> | ||||
| 			<debugger /> | ||||
| 		</Extensions> | ||||
| 		<Extensions /> | ||||
| 	</Project> | ||||
| </CodeBlocks_project_file> | ||||
|   | ||||
| @@ -28,9 +28,10 @@ CStupidAI::~CStupidAI() | ||||
| 	print("destroyed"); | ||||
| } | ||||
|  | ||||
| void CStupidAI::init(std::shared_ptr<CBattleCallback> CB) | ||||
| void CStupidAI::init(std::shared_ptr<Environment> ENV, std::shared_ptr<CBattleCallback> CB) | ||||
| { | ||||
| 	print("init called, saving ptr to IBattleCallback"); | ||||
| 	env = ENV; | ||||
| 	cbc = cb = CB; | ||||
| } | ||||
|  | ||||
| @@ -74,10 +75,12 @@ static bool willSecondHexBlockMoreEnemyShooters(const BattleHex &h1, const Battl | ||||
| 	int shooters[2] = {0}; //count of shooters on hexes | ||||
|  | ||||
| 	for(int i = 0; i < 2; i++) | ||||
| 	{ | ||||
| 		for (auto & neighbour : (i ? h2 : h1).neighbouringTiles()) | ||||
| 			if(const CStack *s = cbc->battleGetStackByPos(neighbour)) | ||||
| 				if(s->getCreature()->isShooting()) | ||||
| 						shooters[i]++; | ||||
| 			if(const CStack * s = cbc->battleGetStackByPos(neighbour)) | ||||
| 				if(s->isShooter()) | ||||
| 					shooters[i]++; | ||||
| 	} | ||||
|  | ||||
| 	return shooters[0] < shooters[1]; | ||||
| } | ||||
| @@ -173,7 +176,7 @@ void CStupidAI::battleAttack(const BattleAttack *ba) | ||||
| 	print("battleAttack called"); | ||||
| } | ||||
|  | ||||
| void CStupidAI::battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa, const std::vector<MetaString> & battleLog) | ||||
| void CStupidAI::battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa) | ||||
| { | ||||
| 	print("battleStacksAttacked called"); | ||||
| } | ||||
| @@ -293,15 +296,3 @@ BattleAction CStupidAI::goTowards(const CStack * stack, std::vector<BattleHex> h | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CStupidAI::saveGame(BinarySerializer & h, const int version) | ||||
| { | ||||
| 	//TODO to be implemented with saving/loading during the battles | ||||
| 	assert(0); | ||||
| } | ||||
|  | ||||
| void CStupidAI::loadGame(BinaryDeserializer & h, const int version) | ||||
| { | ||||
| 	//TODO to be implemented with saving/loading during the battles | ||||
| 	assert(0); | ||||
| } | ||||
|   | ||||
| @@ -18,19 +18,20 @@ class CStupidAI : public CBattleGameInterface | ||||
| { | ||||
| 	int side; | ||||
| 	std::shared_ptr<CBattleCallback> cb; | ||||
| 	std::shared_ptr<Environment> env; | ||||
|  | ||||
| 	void print(const std::string &text) const; | ||||
| public: | ||||
| 	CStupidAI(); | ||||
| 	~CStupidAI(); | ||||
|  | ||||
| 	void init(std::shared_ptr<CBattleCallback> CB) override; | ||||
| 	void init(std::shared_ptr<Environment> ENV, std::shared_ptr<CBattleCallback> CB) override; | ||||
| 	void actionFinished(const BattleAction &action) override;//occurs AFTER every action taken by any stack or by the hero | ||||
| 	void actionStarted(const BattleAction &action) override;//occurs BEFORE every action taken by any stack or by the hero | ||||
| 	BattleAction activeStack(const CStack * stack) override; //called when it's turn of that stack | ||||
|  | ||||
| 	void battleAttack(const BattleAttack *ba) override; //called when stack is performing attack | ||||
| 	void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa, const std::vector<MetaString> & battleLog) override; //called when stack receives damage (after battleAttack()) | ||||
| 	void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa) override; //called when stack receives damage (after battleAttack()) | ||||
| 	void battleEnd(const BattleResult *br) override; | ||||
| 	//void battleResultsApplied() override; //called when all effects of last battle are applied | ||||
| 	void battleNewRoundFirst(int round) override; //called at the beginning of each turn before changes are applied; | ||||
| @@ -42,9 +43,6 @@ public: | ||||
| 	void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) override; //called by engine when battle starts; side=0 - left, side=1 - right | ||||
| 	void battleCatapultAttacked(const CatapultAttack & ca) override; //called when catapult makes an attack | ||||
|  | ||||
| 	virtual void saveGame(BinarySerializer & h, const int version) override; | ||||
| 	virtual void loadGame(BinaryDeserializer & h, const int version) override; | ||||
|  | ||||
| private: | ||||
| 	BattleAction goTowards(const CStack * stack, std::vector<BattleHex> hexes) const; | ||||
| }; | ||||
|   | ||||
| @@ -279,7 +279,7 @@ creInfo infoFromDC(const dwellingContent & dc) | ||||
| 	ci.creID = dc.second.size() ? dc.second.back() : CreatureID(-1); //should never be accessed | ||||
| 	if (ci.creID != -1) | ||||
| 	{ | ||||
| 		ci.cre = VLC->creh->creatures[ci.creID]; | ||||
| 		ci.cre = VLC->creh->objects[ci.creID]; | ||||
| 		ci.level = ci.cre->level; //this is cretaure tier, while tryRealize expects dwelling level. Ignore. | ||||
| 	} | ||||
| 	else | ||||
|   | ||||
| @@ -139,7 +139,9 @@ float FuzzyHelper::evaluate(Goals::VisitHero & g) | ||||
| { | ||||
| 	auto obj = ai->myCb->getObj(ObjectInstanceID(g.objid)); //we assume for now that these goals are similar | ||||
| 	if(!obj) | ||||
| 	{ | ||||
| 		return -100; //hero died in the meantime | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		g.setpriority(Goals::VisitTile(obj->visitablePos()).sethero(g.hero).accept(this)); | ||||
|   | ||||
| @@ -91,7 +91,7 @@ std::string AbstractGoal::name() const //TODO: virtualize | ||||
| 	} | ||||
| 	break; | ||||
| 	case GET_ART_TYPE: | ||||
| 		desc = "GET ARTIFACT OF TYPE " + VLC->arth->artifacts[aid]->Name(); | ||||
| 		desc = "GET ARTIFACT OF TYPE " + VLC->artifacts()->getByIndex(aid)->getName(); | ||||
| 		break; | ||||
| 	case VISIT_TILE: | ||||
| 		desc = "VISIT TILE " + tile.toString(); | ||||
|   | ||||
| @@ -33,16 +33,16 @@ TSubgoal AdventureSpellCast::whatToDoToAchieve() | ||||
|  | ||||
| 	auto spell = getSpell(); | ||||
|  | ||||
| 	logAi->trace("Decomposing adventure spell cast of %s for hero %s", spell->name, hero->name); | ||||
| 	logAi->trace("Decomposing adventure spell cast of %s for hero %s", spell->getName(), hero->name); | ||||
|  | ||||
| 	if(!spell->isAdventureSpell()) | ||||
| 		throw cannotFulfillGoalException(spell->name + " is not an adventure spell."); | ||||
| 	if(!spell->isAdventure()) | ||||
| 		throw cannotFulfillGoalException(spell->getName() + " is not an adventure spell."); | ||||
|  | ||||
| 	if(!hero->canCastThisSpell(spell)) | ||||
| 		throw cannotFulfillGoalException("Hero can not cast " + spell->name); | ||||
| 		throw cannotFulfillGoalException("Hero can not cast " + spell->getName()); | ||||
|  | ||||
| 	if(hero->mana < hero->getSpellCost(spell)) | ||||
| 		throw cannotFulfillGoalException("Hero has not enough mana to cast " + spell->name); | ||||
| 		throw cannotFulfillGoalException("Hero has not enough mana to cast " + spell->getName()); | ||||
|  | ||||
| 	if(spellID == SpellID::TOWN_PORTAL && town && town->visitingHero) | ||||
| 		throw cannotFulfillGoalException("The town is already occupied by " + town->visitingHero->name); | ||||
| @@ -75,10 +75,10 @@ void AdventureSpellCast::accept(VCAI * ai) | ||||
|  | ||||
| std::string AdventureSpellCast::name() const | ||||
| { | ||||
| 	return "AdventureSpellCast " + spellID.toSpell()->name; | ||||
| 	return "AdventureSpellCast " + getSpell()->getName(); | ||||
| } | ||||
|  | ||||
| std::string AdventureSpellCast::completeMessage() const | ||||
| { | ||||
| 	return "Spell casted successfully  " + spellID.toSpell()->name; | ||||
| 	return "Spell cast successfully " + getSpell()->getName(); | ||||
| } | ||||
|   | ||||
| @@ -158,7 +158,7 @@ TGoalVec GatherArmy::getAllPossibleSubgoals() | ||||
| 						{ | ||||
| 							for(auto & creatureID : creLevel.second) | ||||
| 							{ | ||||
| 								auto creature = VLC->creh->creatures[creatureID]; | ||||
| 								auto creature = VLC->creh->objects[creatureID]; | ||||
| 								if(ai->ah->freeResources().canAfford(creature->cost)) | ||||
| 									objs.push_back(obj); //TODO: reserve resources? | ||||
| 							} | ||||
|   | ||||
| @@ -93,7 +93,7 @@ TGoalVec GatherTroops::getAllPossibleSubgoals() | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		auto creature = VLC->creh->creatures[objid]; | ||||
| 		auto creature = VLC->creh->objects[objid]; | ||||
| 		if(t->subID == creature->faction) //TODO: how to force AI to build unupgraded creatures? :O | ||||
| 		{ | ||||
| 			auto creatures = vstd::tryAt(t->town->creatures, creature->level - 1); | ||||
| @@ -110,7 +110,7 @@ TGoalVec GatherTroops::getAllPossibleSubgoals() | ||||
| 				solutions.push_back(sptr(BuyArmy(t, creature->AIValue * this->value).setobjid(objid))); | ||||
| 			} | ||||
| 			/*else //disable random building requests for now - this code needs to know a lot of town/resource context to do more good than harm | ||||
| 			{	 | ||||
| 			{ | ||||
| 				return sptr(BuildThis(bid, t).setpriority(priority)); | ||||
| 			}*/ | ||||
| 		} | ||||
| @@ -129,7 +129,7 @@ TGoalVec GatherTroops::getAllPossibleSubgoals() | ||||
| 			{ | ||||
| 				for(auto type : creature.second) | ||||
| 				{ | ||||
| 					if(type == objid && ai->ah->freeResources().canAfford(VLC->creh->creatures[type]->cost)) | ||||
| 					if(type == objid && ai->ah->freeResources().canAfford(VLC->creh->objects[type]->cost)) | ||||
| 						vstd::concatenate(solutions, ai->ah->howToVisitObj(obj)); | ||||
| 				} | ||||
| 			} | ||||
|   | ||||
| @@ -41,7 +41,7 @@ MapObjectsEvaluator::MapObjectsEvaluator() | ||||
| 					objectDatabase[CompoundMapObjectID(primaryID, secondaryID)] = 0; | ||||
| 				} | ||||
| 			} | ||||
| 		}	 | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -62,7 +62,7 @@ boost::optional<int> MapObjectsEvaluator::getObjectValue(const CGObjectInstance | ||||
| 	{ | ||||
| 		//special case handling: in-game heroes have hero ID as object subID, but when reading configs available hero object subID's are hero classes | ||||
| 		auto hero = dynamic_cast<const CGHeroInstance*>(obj); | ||||
| 		return getObjectValue(obj->ID, hero->type->heroClass->id); | ||||
| 		return getObjectValue(obj->ID, hero->type->heroClass->getIndex()); | ||||
| 	} | ||||
| 	else if(obj->ID == Obj::PRISON) | ||||
| 	{ | ||||
| @@ -77,7 +77,7 @@ boost::optional<int> MapObjectsEvaluator::getObjectValue(const CGObjectInstance | ||||
| 		{ | ||||
| 			for(auto & creatureID : creLevel.second) | ||||
| 			{ | ||||
| 				auto creature = VLC->creh->creatures[creatureID]; | ||||
| 				auto creature = VLC->creh->objects[creatureID]; | ||||
| 				aiValue += (creature->AIValue * creature->growth); | ||||
| 			} | ||||
| 		} | ||||
|   | ||||
| @@ -60,7 +60,7 @@ void AIPathfinder::updatePaths(std::vector<HeroPtr> heroes) | ||||
| 		cb->calculatePaths(config, hero); | ||||
| 	}; | ||||
|  | ||||
| 	std::vector<Task> calculationTasks; | ||||
| 	std::vector<CThreadHelper::Task> calculationTasks; | ||||
|  | ||||
| 	for(HeroPtr hero : heroes) | ||||
| 	{ | ||||
|   | ||||
| @@ -78,7 +78,7 @@ | ||||
| 			<Add option="-Wno-overloaded-virtual" /> | ||||
| 			<Add option="-DBOOST_ALL_DYN_LINK" /> | ||||
| 			<Add option="-DBOOST_SYSTEM_NO_DEPRECATED" /> | ||||
| 			<Add option="-D_WIN32_WINNT=0x0501" /> | ||||
| 			<Add option="-D_WIN32_WINNT=0x0600" /> | ||||
| 			<Add option="-D_WIN32" /> | ||||
| 			<Add option="-DFL_CPP11" /> | ||||
| 			<Add directory="$(#boost.include)" /> | ||||
| @@ -185,9 +185,6 @@ | ||||
| 		<Unit filename="VCAI.h" /> | ||||
| 		<Unit filename="main.cpp" /> | ||||
| 		<Extensions> | ||||
| 			<code_completion /> | ||||
| 			<envvars /> | ||||
| 			<debugger /> | ||||
| 			<lib_finder disable_auto="1" /> | ||||
| 		</Extensions> | ||||
| 	</Project> | ||||
|   | ||||
| @@ -579,9 +579,10 @@ void VCAI::showWorldViewEx(const std::vector<ObjectPosInfo> & objectPositions) | ||||
| 	NET_EVENT_HANDLER; | ||||
| } | ||||
|  | ||||
| void VCAI::init(std::shared_ptr<CCallback> CB) | ||||
| void VCAI::init(std::shared_ptr<Environment> ENV, std::shared_ptr<CCallback> CB) | ||||
| { | ||||
| 	LOG_TRACE(logAi); | ||||
| 	env = ENV; | ||||
| 	myCb = CB; | ||||
| 	cbc = CB; | ||||
|  | ||||
| @@ -868,7 +869,7 @@ void VCAI::mainLoop() | ||||
| 		goalsToRemove.clear(); | ||||
| 		elementarGoals.clear(); | ||||
| 		ultimateGoalsFromBasic.clear(); | ||||
| 		 | ||||
|  | ||||
| 		ah->updatePaths(getMyHeroes()); | ||||
|  | ||||
| 		logAi->debug("Main loop: decomposing %i basic goals", basicGoals.size()); | ||||
| @@ -1082,7 +1083,7 @@ void VCAI::pickBestCreatures(const CArmedInstance * destinationArmy, const CArme | ||||
| 						&& (!destinationArmy->hasStackAtSlot(i) || destinationArmy->getCreature(i) == targetCreature)) | ||||
| 					{ | ||||
| 						auto weakest = ah->getWeakestCreature(bestArmy); | ||||
| 						 | ||||
|  | ||||
| 						if(weakest->creature == targetCreature) | ||||
| 						{ | ||||
| 							if(1 == source->getStackCount(j)) | ||||
| @@ -1233,7 +1234,7 @@ void VCAI::recruitCreatures(const CGDwelling * d, const CArmedInstance * recruit | ||||
| 		int count = d->creatures[i].first; | ||||
| 		CreatureID creID = d->creatures[i].second.back(); | ||||
|  | ||||
| 		vstd::amin(count, ah->freeResources() / VLC->creh->creatures[creID]->cost); | ||||
| 		vstd::amin(count, ah->freeResources() / VLC->creh->objects[creID]->cost); | ||||
| 		if(count > 0) | ||||
| 			cb->recruitCreatures(d, recruiter, creID, count, i); | ||||
| 	} | ||||
|   | ||||
| @@ -139,7 +139,7 @@ public: | ||||
|  | ||||
| 	std::string getBattleAIName() const override; | ||||
|  | ||||
| 	void init(std::shared_ptr<CCallback> CB) override; | ||||
| 	void init(std::shared_ptr<Environment> ENV, std::shared_ptr<CCallback> CB) override; | ||||
| 	void yourTurn() override; | ||||
|  | ||||
| 	void heroGotLevel(const CGHeroInstance * hero, PrimarySkill::PrimarySkill pskill, std::vector<SecondarySkill> & skills, QueryID queryID) override; //pskill is gained primary skill, interface has to choose one of given skills and call callback with selection id | ||||
|   | ||||
| @@ -22,7 +22,6 @@ | ||||
| #include "lib/CHeroHandler.h" | ||||
| #include "lib/NetPacks.h" | ||||
| #include "client/mapHandler.h" | ||||
| #include "lib/spells/CSpellHandler.h" | ||||
| #include "lib/CArtHandler.h" | ||||
| #include "lib/GameConstants.h" | ||||
| #include "lib/CPlayerState.h" | ||||
| @@ -328,26 +327,21 @@ int CCallback::mergeOrSwapStacks(const CArmedInstance *s1, const CArmedInstance | ||||
| 		return swapCreatures(s1, s2, p1, p2); | ||||
| } | ||||
|  | ||||
| void CCallback::registerGameInterface(std::shared_ptr<IGameEventsReceiver> gameEvents) | ||||
| { | ||||
| 	cl->additionalPlayerInts[*player].push_back(gameEvents); | ||||
| } | ||||
|  | ||||
| void CCallback::registerBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents) | ||||
| { | ||||
| 	cl->additionalBattleInts[*player].push_back(battleEvents); | ||||
| } | ||||
|  | ||||
| void CCallback::unregisterGameInterface(std::shared_ptr<IGameEventsReceiver> gameEvents) | ||||
| { | ||||
| 	cl->additionalPlayerInts[*player] -= gameEvents; | ||||
| } | ||||
|  | ||||
| void CCallback::unregisterBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents) | ||||
| { | ||||
| 	cl->additionalBattleInts[*player] -= battleEvents; | ||||
| } | ||||
|  | ||||
| scripting::Pool * CBattleCallback::getContextPool() const | ||||
| { | ||||
| 	return cl->getGlobalContextPool(); | ||||
| } | ||||
|  | ||||
| CBattleCallback::CBattleCallback(boost::optional<PlayerColor> Player, CClient *C ) | ||||
| { | ||||
| 	player = Player; | ||||
|   | ||||
| @@ -10,6 +10,7 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include "lib/CGameInfoCallback.h" | ||||
| #include "lib/battle/CPlayerBattleCallback.h" | ||||
| #include "lib/int3.h" // for int3 | ||||
|  | ||||
| class CGHeroInstance; | ||||
| @@ -92,11 +93,12 @@ public: | ||||
| 	int battleMakeAction(const BattleAction * action) override;//for casting spells by hero - DO NOT use it for moving active stack | ||||
| 	bool battleMakeTacticAction(BattleAction * action) override; // performs tactic phase actions | ||||
|  | ||||
| 	scripting::Pool * getContextPool() const override; | ||||
|  | ||||
| 	friend class CCallback; | ||||
| 	friend class CClient; | ||||
| }; | ||||
|  | ||||
| class CPlayerInterface; | ||||
| class CCallback : public CPlayerSpecificInfoCallback, public IGameActionCallback, public CBattleCallback | ||||
| { | ||||
| public: | ||||
| @@ -111,9 +113,7 @@ public: | ||||
| 	virtual void calculatePaths(const CGHeroInstance *hero, CPathsInfo &out); | ||||
|  | ||||
| 	//Set of metrhods that allows adding more interfaces for this player that'll receive game event call-ins. | ||||
| 	void registerGameInterface(std::shared_ptr<IGameEventsReceiver> gameEvents); | ||||
| 	void registerBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents); | ||||
| 	void unregisterGameInterface(std::shared_ptr<IGameEventsReceiver> gameEvents); | ||||
| 	void unregisterBattleInterface(std::shared_ptr<IBattleEventsReceiver> battleEvents); | ||||
|  | ||||
| //commands | ||||
|   | ||||
| @@ -20,6 +20,7 @@ sudo apt-get install -qq cmake ninja-build libboost1.54-all-dev zlib1g-dev | ||||
| sudo apt-get install -qq libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev | ||||
| sudo apt-get install -qq libavformat-dev libswscale-dev | ||||
| sudo apt-get install -qq qt57declarative | ||||
| sudo apt-get install -qq libluajit-5.1-dev | ||||
|  | ||||
| #setup compiler | ||||
| source /opt/qt57/bin/qt57-env.sh | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| #!/bin/sh | ||||
|  | ||||
| brew update | ||||
| brew install smpeg2 libpng freetype sdl2 sdl2_ttf sdl2_image qt5 ffmpeg ninja | ||||
| brew install smpeg2 libpng freetype sdl2 sdl2_ttf sdl2_image qt5 ffmpeg ninja luajit | ||||
| brew install sdl2_mixer | ||||
|  | ||||
| export CMAKE_PREFIX_PATH="/usr/local/opt/qt5:$CMAKE_PREFIX_PATH" | ||||
|   | ||||
| @@ -4,17 +4,17 @@ | ||||
| sudo apt-get install -qq nsis ninja-build | ||||
|  | ||||
| # MXE repository was too slow for Travis far too often | ||||
| wget https://github.com/vcmi/vcmi-deps-mxe/releases/download/2018-02-10/mxe-$MXE_TARGET-2018-02-10.tar | ||||
| tar -xvf mxe-$MXE_TARGET-2018-02-10.tar | ||||
| wget https://github.com/vcmi/vcmi-deps-mxe/releases/download/2019-06-28/mxe-i686-w64-mingw32.shared-2019-06-28.tar | ||||
| tar -xvf mxe-i686-w64-mingw32.shared-2019-06-28.tar | ||||
| sudo dpkg -i mxe-*.deb | ||||
| sudo apt-get install -f --yes | ||||
|  | ||||
| if false; then | ||||
| # Add MXE repository and key | ||||
| echo "deb http://pkg.mxe.cc/repos/apt/debian wheezy main" \ | ||||
| echo "deb http://pkg.mxe.cc/repos/apt trusty main" \ | ||||
|     | sudo tee /etc/apt/sources.list.d/mxeapt.list | ||||
|  | ||||
| sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys D43A795B73B16ABE9643FE1AFD8FFF16DB45C6AB | ||||
| sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 86B72ED9 | ||||
|  | ||||
| # Install needed packages | ||||
| sudo apt-get update -qq | ||||
| @@ -30,7 +30,8 @@ mxe-$MXE_TARGET-sdl2-mixer \ | ||||
| mxe-$MXE_TARGET-sdl2-ttf \ | ||||
| mxe-$MXE_TARGET-ffmpeg \ | ||||
| mxe-$MXE_TARGET-qt \ | ||||
| mxe-$MXE_TARGET-qtbase | ||||
| mxe-$MXE_TARGET-qtbase \ | ||||
| mxe-i686-w64-mingw32.static-luajit | ||||
|  | ||||
| fi # Disable | ||||
|  | ||||
|   | ||||
| @@ -44,7 +44,8 @@ set(VCMI_VERSION_MAJOR 0) | ||||
| set(VCMI_VERSION_MINOR 99) | ||||
| set(VCMI_VERSION_PATCH 0) | ||||
|  | ||||
| option(ENABLE_ERM "Enable compilation of ERM scripting module" OFF) | ||||
| option(ENABLE_ERM "Enable compilation of ERM scripting module" ON) | ||||
| option(ENABLE_LUA "Enable compilation of LUA scripting module" ON) | ||||
| option(ENABLE_LAUNCHER "Enable compilation of launcher" ON) | ||||
| option(ENABLE_TEST "Enable compilation of unit tests" ON) | ||||
| option(ENABLE_PCH "Enable compilation using precompiled headers" ON) | ||||
| @@ -122,7 +123,6 @@ if(APPLE) | ||||
| endif(APPLE) | ||||
|  | ||||
| if(WIN32) | ||||
| 	add_definitions(-DBOOST_THREAD_USE_LIB) | ||||
| 	# Windows Vista or newer for FuzzyLite 6 to compile | ||||
| 	add_definitions(-D_WIN32_WINNT=0x0600) | ||||
|  | ||||
| @@ -231,6 +231,21 @@ if(ENABLE_LAUNCHER) | ||||
| 	find_package(Qt5Network REQUIRED) | ||||
| endif() | ||||
|  | ||||
| if(ENABLE_LUA) | ||||
| 	# MXE paths hardcoded for current dependencies pack - tried and could not make it work another way | ||||
| 	if((MINGW) AND (${CMAKE_CROSSCOMPILING}) AND (DEFINED MSYS)) | ||||
| 		set(LUA_INCLUDE_DIR "/usr/lib/mxe/usr/i686-w64-mingw32.static/include/luajit-2.0") | ||||
| 		set(LUA_LIBRARY "/usr/lib/mxe/usr/i686-w64-mingw32.static/lib/libluajit-5.1.a") | ||||
| 	endif() | ||||
| 	find_package(LuaJIT) | ||||
| 	if(LUAJIT_FOUND) | ||||
| 		message(STATUS "Using LuaJIT provided by system") | ||||
| 	else() | ||||
| 		message(STATUS "Cannot find LuaJIT! Fallback to using usual Lua.") | ||||
| 		find_package(Lua REQUIRED) | ||||
| 	endif() | ||||
| endif() | ||||
|  | ||||
| ############################################ | ||||
| #        Output directories                # | ||||
| ############################################ | ||||
| @@ -294,6 +309,9 @@ set(SCRIPTING_LIB_DIR "${LIB_DIR}/scripting") | ||||
| if(ENABLE_ERM) | ||||
| 	add_subdirectory(scripting/erm) | ||||
| endif() | ||||
| if(ENABLE_LUA) | ||||
| 	add_subdirectory(scripting/lua) | ||||
| endif() | ||||
| if(NOT MINIZIP_FOUND) | ||||
| 	add_subdirectory_with_folder("3rdparty" lib/minizip) | ||||
| 	set(MINIZIP_LIBRARIES minizip) | ||||
| @@ -315,6 +333,7 @@ endif() | ||||
| ####################################### | ||||
|  | ||||
| install(DIRECTORY config DESTINATION ${DATA_DIR}) | ||||
| install(DIRECTORY scripts DESTINATION ${DATA_DIR}) | ||||
| install(DIRECTORY Mods DESTINATION ${DATA_DIR}) | ||||
|  | ||||
| # that script is useless for Windows | ||||
|   | ||||
							
								
								
									
										18
									
								
								Global.h
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								Global.h
									
									
									
									
									
								
							| @@ -727,24 +727,6 @@ namespace vstd | ||||
| 	} | ||||
|  | ||||
| 	using boost::math::round; | ||||
|  | ||||
| 	static std::pair<std::string, std::string> splitStringToPair(std::string input, char separator) | ||||
| 	{ | ||||
| 		std::pair<std::string, std::string> ret; | ||||
| 		size_t splitPos = input.find(separator); | ||||
|  | ||||
| 		if (splitPos == std::string::npos) | ||||
| 		{ | ||||
| 			ret.first.clear(); | ||||
| 			ret.second = input; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			ret.first = input.substr(0, splitPos); | ||||
| 			ret.second = input.substr(splitPos + 1); | ||||
| 		} | ||||
| 		return ret; | ||||
| 	} | ||||
| } | ||||
| using vstd::operator-=; | ||||
| using vstd::make_unique; | ||||
|   | ||||
| @@ -1,40 +0,0 @@ | ||||
| VERM | ||||
| ; standard verm file, global engine things should be put here | ||||
|  | ||||
| !?PI; | ||||
| ; example 1 --- Hello World | ||||
| ![print ^Hello world!^] | ||||
|  | ||||
| ; example 2 --- simple arithmetics | ||||
| ![defun add [x y] [+ x y]] | ||||
| ![print [add 2 3]] | ||||
|  | ||||
| ; example 3 --- semantic macros | ||||
| ![defmacro do-n-times [times body] | ||||
| 	`[progn | ||||
| 		[setq do-counter 0] | ||||
| 		[setq do-max ,times] | ||||
| 		[do [< do-counter do-max] | ||||
| 			[progn  | ||||
| 				[setq do-counter [+ do-counter 1]] | ||||
| 				,body | ||||
| 			] | ||||
| 		] | ||||
| 	] | ||||
| ] | ||||
| ![do-n-times 4 [print ^tekst\n^]] | ||||
|  | ||||
|  | ||||
| ; example 4 --- conditional expression | ||||
| ![if [> 2 1] [print ^Wieksze^] [print ^Mniejsze^]] | ||||
|  | ||||
| ; example 5 --- lambda expressions | ||||
| ![[lambda [x y] [if [> x y] [print ^wieksze^] [print ^mniejsze^]]] 2 3] | ||||
|  | ||||
| ; example 6 --- resursion | ||||
| ![defun factorial [n] | ||||
| 	[if [= n 0] 1 | ||||
| 		[* n [factorial [- n 1]]] | ||||
| 	] | ||||
| ] | ||||
| ![print [factorial 8]] | ||||
| @@ -1,14 +0,0 @@ | ||||
| ZVSE | ||||
| !?PI; | ||||
| 	!!VRv2777:S4; | ||||
| 	!!DO1/0/5/1&v2777<>1:P0; | ||||
|  | ||||
| !?FU1; | ||||
| 	!!VRv2778:Sx16%2; | ||||
| 	!!IF&x16>3:M^Hello world number %X16! To duza liczba^; | ||||
| 	!!IF&v2778==0&x16<=3:M^Hello world number %X16! To mala parzysta liczba^; | ||||
| 	!!IF&v2778==1&x16<=3:M^Hello world number %X16! To mala nieparzysta liczba^; | ||||
|  | ||||
| !?PI; | ||||
| 	!!VRz10:S^Composed hello ^; | ||||
| 	!!IF:M^%Z10%%world%%, v2777=%V2777, v2778=%V2778!^; | ||||
| @@ -9,8 +9,6 @@ | ||||
|  */ | ||||
| #include "StdInc.h" | ||||
| #include "CGameInfo.h" | ||||
| #include "../lib/CSkillHandler.h" | ||||
| #include "../lib/CGeneralTextHandler.h" | ||||
|  | ||||
| #include "../lib/VCMI_Lib.h" | ||||
|  | ||||
| @@ -24,13 +22,14 @@ CGameInfo::CGameInfo() | ||||
| 	generaltexth = nullptr; | ||||
| 	mh = nullptr; | ||||
| 	townh = nullptr; | ||||
| 	globalServices = nullptr; | ||||
| } | ||||
|  | ||||
| void CGameInfo::setFromLib() | ||||
| { | ||||
| 	globalServices = VLC; | ||||
| 	modh = VLC->modh; | ||||
| 	generaltexth = VLC->generaltexth; | ||||
| 	arth = VLC->arth; | ||||
| 	creh = VLC->creh; | ||||
| 	townh = VLC->townh; | ||||
| 	heroh = VLC->heroh; | ||||
| @@ -39,3 +38,58 @@ void CGameInfo::setFromLib() | ||||
| 	skillh = VLC->skillh; | ||||
| 	objtypeh = VLC->objtypeh; | ||||
| } | ||||
|  | ||||
| const ArtifactService * CGameInfo::artifacts() const | ||||
| { | ||||
| 	return globalServices->artifacts(); | ||||
| } | ||||
|  | ||||
| const CreatureService * CGameInfo::creatures() const | ||||
| { | ||||
| 	return globalServices->creatures(); | ||||
| } | ||||
|  | ||||
| const FactionService * CGameInfo::factions() const | ||||
| { | ||||
| 	return globalServices->factions(); | ||||
| } | ||||
|  | ||||
| const HeroClassService * CGameInfo::heroClasses() const | ||||
| { | ||||
| 	return globalServices->heroClasses(); | ||||
| } | ||||
|  | ||||
| const HeroTypeService * CGameInfo::heroTypes() const | ||||
| { | ||||
| 	return globalServices->heroTypes(); | ||||
| } | ||||
|  | ||||
| const scripting::Service * CGameInfo::scripts()  const | ||||
| { | ||||
| 	return globalServices->scripts(); | ||||
| } | ||||
|  | ||||
| const spells::Service * CGameInfo::spells()  const | ||||
| { | ||||
| 	return globalServices->spells(); | ||||
| } | ||||
|  | ||||
| const SkillService * CGameInfo::skills() const | ||||
| { | ||||
| 	return globalServices->skills(); | ||||
| } | ||||
|  | ||||
| void CGameInfo::updateEntity(Metatype metatype, int32_t index, const JsonNode & data) | ||||
| { | ||||
| 	logGlobal->error("CGameInfo::updateEntity call is not expected."); | ||||
| } | ||||
|  | ||||
| spells::effects::Registry * CGameInfo::spellEffects() | ||||
| { | ||||
| 	return nullptr; | ||||
| } | ||||
|  | ||||
| const spells::effects::Registry * CGameInfo::spellEffects() const | ||||
| { | ||||
| 	return globalServices->spellEffects(); | ||||
| } | ||||
|   | ||||
| @@ -9,11 +9,12 @@ | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
| #include <vcmi/Services.h> | ||||
|  | ||||
| #include "../lib/ConstTransitivePtr.h" | ||||
|  | ||||
| class CModHandler; | ||||
| class CMapHandler; | ||||
| class CArtHandler; | ||||
| class CHeroHandler; | ||||
| class CCreatureHandler; | ||||
| class CSpellHandler; | ||||
| @@ -48,11 +49,25 @@ extern CClientState * CCS; | ||||
|  | ||||
| /// CGameInfo class | ||||
| /// for allowing different functions for accessing game informations | ||||
| class CGameInfo | ||||
| class CGameInfo : public Services | ||||
| { | ||||
| public: | ||||
| 	const ArtifactService * artifacts() const override; | ||||
| 	const CreatureService * creatures() const override; | ||||
| 	const FactionService * factions() const override; | ||||
| 	const HeroClassService * heroClasses() const override; | ||||
| 	const HeroTypeService * heroTypes() const override; | ||||
| 	const scripting::Service * scripts() const override; | ||||
| 	const spells::Service * spells() const override; | ||||
| 	const SkillService * skills() const override; | ||||
|  | ||||
| 	void updateEntity(Metatype metatype, int32_t index, const JsonNode & data) override; | ||||
|  | ||||
| 	const spells::effects::Registry * spellEffects() const override; | ||||
| 	spells::effects::Registry * spellEffects() override; | ||||
|  | ||||
|  | ||||
| 	ConstTransitivePtr<CModHandler> modh; //public? | ||||
| 	ConstTransitivePtr<CArtHandler> arth; | ||||
| 	ConstTransitivePtr<CHeroHandler> heroh; | ||||
| 	ConstTransitivePtr<CCreatureHandler> creh; | ||||
| 	ConstTransitivePtr<CSpellHandler> spellh; | ||||
| @@ -65,8 +80,8 @@ public: | ||||
|  | ||||
| 	void setFromLib(); | ||||
|  | ||||
| 	friend class CClient; | ||||
|  | ||||
| 	CGameInfo(); | ||||
| private: | ||||
| 	const Services * globalServices; | ||||
| }; | ||||
| extern const CGameInfo* CGI; | ||||
|   | ||||
| @@ -14,6 +14,8 @@ | ||||
|  | ||||
| #include <boost/program_options.hpp> | ||||
|  | ||||
| #include <vcmi/scripting/Service.h> | ||||
|  | ||||
| #include "gui/SDL_Extensions.h" | ||||
| #include "CGameInfo.h" | ||||
| #include "mapHandler.h" | ||||
| @@ -46,9 +48,9 @@ | ||||
| #include "../lib/NetPacks.h" | ||||
| #include "CMessage.h" | ||||
| #include "../lib/CModHandler.h" | ||||
| #include "../lib/ScriptHandler.h" | ||||
| #include "../lib/CTownHandler.h" | ||||
| #include "../lib/CArtHandler.h" | ||||
| #include "../lib/CScriptingModule.h" | ||||
| #include "../lib/GameConstants.h" | ||||
| #include "gui/CGuiHandler.h" | ||||
| #include "../lib/logging/CBasicLogConfigurator.h" | ||||
| @@ -95,14 +97,13 @@ SDL_Surface *screen = nullptr, //main screen surface | ||||
| 	*screen2 = nullptr, //and hlp surface (used to store not-active interfaces layer) | ||||
| 	*screenBuf = screen; //points to screen (if only advmapint is present) or screen2 (else) - should be used when updating controls which are not regularly redrawed | ||||
|  | ||||
| std::queue<SDL_Event> events; | ||||
| std::queue<SDL_Event> SDLEventsQueue; | ||||
| boost::mutex eventsM; | ||||
|  | ||||
| static po::variables_map vm; | ||||
|  | ||||
| //static bool setResolution = false; //set by event handling thread after resolution is adjusted | ||||
|  | ||||
| static bool ermInteractiveMode = false; //structurize when time is right | ||||
| void processCommand(const std::string &message); | ||||
| static void setScreenRes(int w, int h, int bpp, bool fullscreen, int displayIndex, bool resetVideo=true); | ||||
| void playIntro(); | ||||
| @@ -576,29 +577,10 @@ void processCommand(const std::string &message) | ||||
| //	if(LOCPLINT && LOCPLINT->cingconsole) | ||||
| //		LOCPLINT->cingconsole->print(message); | ||||
|  | ||||
| 	if(ermInteractiveMode) | ||||
| 	{ | ||||
| 		if(cn == "exit") | ||||
| 		{ | ||||
| 			ermInteractiveMode = false; | ||||
| 			return; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			if(CSH->client && CSH->client->erm) | ||||
| 				CSH->client->erm->executeUserCommand(message); | ||||
| 			std::cout << "erm>"; | ||||
| 		} | ||||
| 	} | ||||
| 	else if(message==std::string("die, fool")) | ||||
| 	if(message==std::string("die, fool")) | ||||
| 	{ | ||||
| 		exit(EXIT_SUCCESS); | ||||
| 	} | ||||
| 	else if(cn == "erm") | ||||
| 	{ | ||||
| 		ermInteractiveMode = true; | ||||
| 		std::cout << "erm>"; | ||||
| 	} | ||||
| 	else if(cn==std::string("activate")) | ||||
| 	{ | ||||
| 		int what; | ||||
| @@ -725,6 +707,28 @@ void processCommand(const std::string &message) | ||||
| 		std::cout << "\rExtracting done :)\n"; | ||||
| 		std::cout << " Extracted files can be found in " << outPath << " directory\n"; | ||||
| 	} | ||||
| 	else if(message=="get scripts") | ||||
| 	{ | ||||
| 		std::cout << "Command accepted.\t"; | ||||
|  | ||||
| 		const bfs::path outPath = | ||||
| 			VCMIDirs::get().userCachePath() / "extracted" / "scripts"; | ||||
|  | ||||
| 		bfs::create_directories(outPath); | ||||
|  | ||||
| 		for(auto & kv : VLC->scriptHandler->objects) | ||||
| 		{ | ||||
| 			std::string name = kv.first; | ||||
| 			boost::algorithm::replace_all(name,":","_"); | ||||
|  | ||||
| 			const scripting::ScriptImpl * script = kv.second.get(); | ||||
| 			bfs::path filePath = outPath / (name + ".lua"); | ||||
| 			bfs::ofstream file(filePath); | ||||
| 			file << script->getSource(); | ||||
| 		} | ||||
| 		std::cout << "\rExtracting done :)\n"; | ||||
| 		std::cout << " Extracted files can be found in " << outPath << " directory\n"; | ||||
| 	} | ||||
| 	else if(message=="get txt") | ||||
| 	{ | ||||
| 		std::cout << "Command accepted.\t"; | ||||
| @@ -891,7 +895,7 @@ void processCommand(const std::string &message) | ||||
| 	{ | ||||
| 		YourTurn yt; | ||||
| 		yt.player = player; | ||||
| 		yt.daysWithoutCastle = CSH->client->getPlayer(player)->daysWithoutCastle; | ||||
| 		yt.daysWithoutCastle = CSH->client->getPlayerState(player)->daysWithoutCastle; | ||||
| 		yt.applyCl(CSH->client); | ||||
| 	}; | ||||
|  | ||||
| @@ -1360,7 +1364,7 @@ static void handleEvent(SDL_Event & ev) | ||||
|  | ||||
| 	{ | ||||
| 		boost::unique_lock<boost::mutex> lock(eventsM); | ||||
| 		events.push(ev); | ||||
| 		SDLEventsQueue.push(ev); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -13,8 +13,6 @@ | ||||
| #include "CMusicHandler.h" | ||||
| #include "CGameInfo.h" | ||||
| #include "SDLRWwrapper.h" | ||||
| #include "../lib/CCreatureHandler.h" | ||||
| #include "../lib/spells/CSpellHandler.h" | ||||
| #include "../lib/JsonNode.h" | ||||
| #include "../lib/GameConstants.h" | ||||
| #include "../lib/filesystem/Filesystem.h" | ||||
|   | ||||
| @@ -12,7 +12,6 @@ | ||||
| #include "../lib/CConfigHandler.h" | ||||
| #include "../lib/CSoundBase.h" | ||||
|  | ||||
| class CSpell; | ||||
| struct _Mix_Music; | ||||
| struct SDL_RWops; | ||||
| typedef struct _Mix_Music Mix_Music; | ||||
|   | ||||
| @@ -8,6 +8,9 @@ | ||||
|  * | ||||
|  */ | ||||
| #include "StdInc.h" | ||||
|  | ||||
| #include <vcmi/Artifact.h> | ||||
|  | ||||
| #include "windows/CAdvmapInterface.h" | ||||
| #include "battle/CBattleInterface.h" | ||||
| #include "battle/CBattleInterfaceClasses.h" | ||||
| @@ -82,7 +85,7 @@ using namespace CSDL_Ext; | ||||
|  | ||||
| void processCommand(const std::string &message, CClient *&client); | ||||
|  | ||||
| extern std::queue<SDL_Event> events; | ||||
| extern std::queue<SDL_Event> SDLEventsQueue; | ||||
| extern boost::mutex eventsM; | ||||
| boost::recursive_mutex * CPlayerInterface::pim = new boost::recursive_mutex; | ||||
|  | ||||
| @@ -144,9 +147,10 @@ CPlayerInterface::~CPlayerInterface() | ||||
| 	if (LOCPLINT == this) | ||||
| 		LOCPLINT = nullptr; | ||||
| } | ||||
| void CPlayerInterface::init(std::shared_ptr<CCallback> CB) | ||||
| void CPlayerInterface::init(std::shared_ptr<Environment> ENV, std::shared_ptr<CCallback> CB) | ||||
| { | ||||
| 	cb = CB; | ||||
| 	env = ENV; | ||||
| 	initializeHeroTownList(); | ||||
|  | ||||
| 	// always recreate advmap interface to avoid possible memory-corruption bugs | ||||
| @@ -372,10 +376,10 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details) | ||||
| 	//check if user cancelled movement | ||||
| 	{ | ||||
| 		boost::unique_lock<boost::mutex> un(eventsM); | ||||
| 		while(!events.empty()) | ||||
| 		while(!SDLEventsQueue.empty()) | ||||
| 		{ | ||||
| 			SDL_Event ev = events.front(); | ||||
| 			events.pop(); | ||||
| 			SDL_Event ev = SDLEventsQueue.front(); | ||||
| 			SDLEventsQueue.pop(); | ||||
| 			switch(ev.type) | ||||
| 			{ | ||||
| 			case SDL_MOUSEBUTTONDOWN: | ||||
| @@ -692,7 +696,7 @@ void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet | ||||
| 	if (settings["adventure"]["quickCombat"].Bool()) | ||||
| 	{ | ||||
| 		autofightingAI = CDynLibHandler::getNewBattleAI(settings["server"]["friendlyAI"].String()); | ||||
| 		autofightingAI->init(cb); | ||||
| 		autofightingAI->init(env, cb); | ||||
| 		autofightingAI->battleStart(army1, army2, int3(0,0,0), hero1, hero2, side); | ||||
| 		isAutoFightOn = true; | ||||
| 		cb->registerBattleInterface(autofightingAI); | ||||
| @@ -707,7 +711,7 @@ void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet | ||||
| 	BATTLE_EVENT_POSSIBLE_RETURN; | ||||
| } | ||||
|  | ||||
| void CPlayerInterface::battleUnitsChanged(const std::vector<UnitChanges> & units, const std::vector<CustomEffectInfo> & customEffects, const std::vector<MetaString> & battleLog) | ||||
| void CPlayerInterface::battleUnitsChanged(const std::vector<UnitChanges> & units, const std::vector<CustomEffectInfo> & customEffects) | ||||
| { | ||||
| 	EVENT_HANDLER_CALLED_BY_CLIENT; | ||||
| 	BATTLE_EVENT_POSSIBLE_RETURN; | ||||
| @@ -769,7 +773,6 @@ void CPlayerInterface::battleUnitsChanged(const std::vector<UnitChanges> & units | ||||
| 	} | ||||
|  | ||||
| 	battleInt->displayCustomEffects(customEffects); | ||||
| 	battleInt->displayBattleLog(battleLog); | ||||
| } | ||||
|  | ||||
| void CPlayerInterface::battleObstaclesChanged(const std::vector<ObstacleChanges> & obstacles) | ||||
| @@ -919,6 +922,14 @@ void CPlayerInterface::battleEnd(const BattleResult *br) | ||||
| 	battleInt->battleFinished(*br); | ||||
| } | ||||
|  | ||||
| void CPlayerInterface::battleLogMessage(const std::vector<MetaString> & lines) | ||||
| { | ||||
| 	EVENT_HANDLER_CALLED_BY_CLIENT; | ||||
| 	BATTLE_EVENT_POSSIBLE_RETURN; | ||||
|  | ||||
| 	battleInt->displayBattleLog(lines); | ||||
| } | ||||
|  | ||||
| void CPlayerInterface::battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance) | ||||
| { | ||||
| 	EVENT_HANDLER_CALLED_BY_CLIENT; | ||||
| @@ -948,7 +959,7 @@ void CPlayerInterface::battleTriggerEffect (const BattleTriggerEffect & bte) | ||||
| 	RETURN_IF_QUICK_COMBAT; | ||||
| 	battleInt->battleTriggerEffect(bte); | ||||
| } | ||||
| void CPlayerInterface::battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa, const std::vector<MetaString> & battleLog) | ||||
| void CPlayerInterface::battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa) | ||||
| { | ||||
| 	EVENT_HANDLER_CALLED_BY_CLIENT; | ||||
| 	BATTLE_EVENT_POSSIBLE_RETURN; | ||||
| @@ -977,7 +988,7 @@ void CPlayerInterface::battleStacksAttacked(const std::vector<BattleStackAttacke | ||||
| 		StackAttackedInfo to_put = {defender, elem.damageAmount, elem.killedAmount, attacker, remoteAttack, elem.killed(), elem.willRebirth(), elem.cloneKilled()}; | ||||
| 		arg.push_back(to_put); | ||||
| 	} | ||||
| 	battleInt->stacksAreAttacked(arg, battleLog); | ||||
| 	battleInt->stacksAreAttacked(arg); | ||||
| } | ||||
| void CPlayerInterface::battleAttack(const BattleAttack * ba) | ||||
| { | ||||
| @@ -1424,29 +1435,20 @@ void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHer | ||||
|  * Shows the dialog that appears when right-clicking an artifact that can be assembled | ||||
|  * into a combinational one on an artifact screen. Does not require the combination of | ||||
|  * artifacts to be legal. | ||||
|  * @param artifactID ID of a constituent artifact. | ||||
|  * @param assembleTo ID of artifact to assemble a constituent into, not used when assemble | ||||
|  * is false. | ||||
|  * @param assemble True if the artifact is to be assembled, false if it is to be disassembled. | ||||
|  */ | ||||
| void CPlayerInterface::showArtifactAssemblyDialog (ui32 artifactID, ui32 assembleTo, bool assemble, CFunctionList<bool()> onYes, CFunctionList<bool()> onNo) | ||||
| void CPlayerInterface::showArtifactAssemblyDialog(const Artifact * artifact, const Artifact * assembledArtifact, CFunctionList<bool()> onYes) | ||||
| { | ||||
| 	const CArtifact &artifact = *CGI->arth->artifacts[artifactID]; | ||||
| 	std::string text = artifact.Description(); | ||||
| 	std::string text = artifact->getDescription(); | ||||
| 	text += "\n\n"; | ||||
| 	std::vector<std::shared_ptr<CComponent>> scs; | ||||
|  | ||||
| 	if(assemble) | ||||
| 	if(assembledArtifact) | ||||
| 	{ | ||||
| 		const CArtifact &assembledArtifact = *CGI->arth->artifacts[assembleTo]; | ||||
|  | ||||
| 		// You possess all of the components to... | ||||
| 		text += boost::str(boost::format(CGI->generaltexth->allTexts[732]) % assembledArtifact.Name()); | ||||
| 		text += boost::str(boost::format(CGI->generaltexth->allTexts[732]) % assembledArtifact->getName()); | ||||
|  | ||||
| 		// Picture of assembled artifact at bottom. | ||||
| 		auto sc = std::make_shared<CComponent>(CComponent::artifact, assembledArtifact.id, 0); | ||||
| 		//sc->description = assembledArtifact.Description(); | ||||
| 		//sc->subtitle = assembledArtifact.Name(); | ||||
| 		auto sc = std::make_shared<CComponent>(CComponent::artifact, assembledArtifact->getIndex(), 0); | ||||
| 		scs.push_back(sc); | ||||
| 	} | ||||
| 	else | ||||
| @@ -1455,7 +1457,7 @@ void CPlayerInterface::showArtifactAssemblyDialog (ui32 artifactID, ui32 assembl | ||||
| 		text += CGI->generaltexth->allTexts[733]; | ||||
| 	} | ||||
|  | ||||
| 	showYesNoDialog(text, onYes, onNo, scs); | ||||
| 	showYesNoDialog(text, onYes, nullptr, scs); | ||||
| } | ||||
|  | ||||
| void CPlayerInterface::requestRealized( PackageApplied *pa ) | ||||
| @@ -1612,8 +1614,8 @@ void CPlayerInterface::playerBlocked(int reason, bool start) | ||||
| { | ||||
| 	if(reason == PlayerBlocked::EReason::UPCOMING_BATTLE) | ||||
| 	{ | ||||
| 		if(CSH->howManyPlayerInterfaces() > 1 && LOCPLINT != this && LOCPLINT->makingTurn == false)  | ||||
| 		{  | ||||
| 		if(CSH->howManyPlayerInterfaces() > 1 && LOCPLINT != this && LOCPLINT->makingTurn == false) | ||||
| 		{ | ||||
| 			//one of our players who isn't last in order got attacked not by our another player (happens for example in hotseat mode) | ||||
| 			boost::unique_lock<boost::mutex> lock(eventsM); //TODO: copied from yourTurn, no idea if it's needed | ||||
| 			LOCPLINT = this; | ||||
| @@ -2236,13 +2238,13 @@ void CPlayerInterface::advmapSpellCast(const CGHeroInstance * caster, int spellI | ||||
| 	if(spellID == SpellID::FLY || spellID == SpellID::WATER_WALK) | ||||
| 		eraseCurrentPathOf(caster, false); | ||||
|  | ||||
| 	const CSpell * spell = CGI->spellh->objects.at(spellID); | ||||
| 	const spells::Spell * spell = CGI->spells()->getByIndex(spellID); | ||||
|  | ||||
| 	if(spellID == SpellID::VIEW_EARTH) | ||||
| 	{ | ||||
| 		//TODO: implement on server side | ||||
| 		int level = caster->getSpellSchoolLevel(spell); | ||||
| 		adventureInt->worldViewOptions.showAllTerrain = (level>2); | ||||
| 		const auto level = caster->getSpellSchoolLevel(spell); | ||||
| 		adventureInt->worldViewOptions.showAllTerrain = (level > 2); | ||||
| 	} | ||||
|  | ||||
| 	auto castSoundPath = spell->getCastSound(); | ||||
| @@ -2360,7 +2362,7 @@ void CPlayerInterface::acceptTurn() | ||||
| 		components.push_back(Component(Component::FLAG, playerColor.getNum(), 0, 0)); | ||||
| 		MetaString text; | ||||
|  | ||||
| 		const auto & optDaysWithoutCastle = cb->getPlayer(playerColor)->daysWithoutCastle; | ||||
| 		const auto & optDaysWithoutCastle = cb->getPlayerState(playerColor)->daysWithoutCastle; | ||||
|  | ||||
| 		if(optDaysWithoutCastle) | ||||
| 		{ | ||||
| @@ -2646,9 +2648,9 @@ bool CPlayerInterface::capturedAllEvents() | ||||
| 	if (ignoreEvents) | ||||
| 	{ | ||||
| 		boost::unique_lock<boost::mutex> un(eventsM); | ||||
| 		while(!events.empty()) | ||||
| 		while(!SDLEventsQueue.empty()) | ||||
| 		{ | ||||
| 			events.pop(); | ||||
| 			SDLEventsQueue.pop(); | ||||
| 		} | ||||
| 		return true; | ||||
| 	} | ||||
|   | ||||
| @@ -19,6 +19,8 @@ | ||||
| #define sprintf_s snprintf | ||||
| #endif | ||||
|  | ||||
| class Artifact; | ||||
|  | ||||
| class CButton; | ||||
| class CToggleGroup; | ||||
| struct TryMoveHero; | ||||
| @@ -62,7 +64,9 @@ namespace boost | ||||
| class CPlayerInterface : public CGameInterface, public IUpdateable | ||||
| { | ||||
| 	const CArmedInstance * currentSelection; | ||||
|  | ||||
| public: | ||||
| 	std::shared_ptr<Environment> env; | ||||
| 	ObjectInstanceID destinationTeleport; //contain -1 or object id if teleportation | ||||
| 	int3 destinationTeleportPos; | ||||
|  | ||||
| @@ -183,21 +187,22 @@ public: | ||||
| 	void battleEnd(const BattleResult *br) override; //end of battle | ||||
| 	void battleNewRoundFirst(int round) override; //called at the beginning of each turn before changes are applied; used for HP regen handling | ||||
| 	void battleNewRound(int round) override; //called at the beginning of each turn, round=-1 is the tactic phase, round=0 is the first "normal" turn | ||||
| 	void battleLogMessage(const std::vector<MetaString> & lines) override; | ||||
| 	void battleStackMoved(const CStack * stack, std::vector<BattleHex> dest, int distance) override; | ||||
| 	void battleSpellCast(const BattleSpellCast *sc) override; | ||||
| 	void battleStacksEffectsSet(const SetStackEffect & sse) override; //called when a specific effect is set to stacks | ||||
| 	void battleTriggerEffect(const BattleTriggerEffect & bte) override; //various one-shot effect | ||||
| 	void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa, const std::vector<MetaString> & battleLog) override; | ||||
| 	void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa) override; | ||||
| 	void battleStartBefore(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2) override; //called by engine just before battle starts; side=0 - left, side=1 - right | ||||
| 	void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) override; //called by engine when battle starts; side=0 - left, side=1 - right | ||||
| 	void battleUnitsChanged(const std::vector<UnitChanges> & units, const std::vector<CustomEffectInfo> & customEffects, const std::vector<MetaString> & battleLog) override; | ||||
| 	void battleUnitsChanged(const std::vector<UnitChanges> & units, const std::vector<CustomEffectInfo> & customEffects) override; | ||||
| 	void battleObstaclesChanged(const std::vector<ObstacleChanges> & obstacles) override; | ||||
| 	void battleCatapultAttacked(const CatapultAttack & ca) override; //called when catapult makes an attack | ||||
| 	void battleGateStateChanged(const EGateState state) override; | ||||
| 	void yourTacticPhase(int distance) override; | ||||
|  | ||||
| 	//-------------// | ||||
| 	void showArtifactAssemblyDialog(ui32 artifactID, ui32 assembleTo, bool assemble, CFunctionList<bool()> onYes, CFunctionList<bool()> onNo); | ||||
| 	void showArtifactAssemblyDialog(const Artifact * artifact, const Artifact * assembledArtifact, CFunctionList<bool()> onYes); | ||||
| 	void garrisonsChanged(std::vector<const CGObjectInstance *> objs); | ||||
| 	void garrisonChanged(const CGObjectInstance * obj); | ||||
| 	void heroKilled(const CGHeroInstance* hero); | ||||
| @@ -210,7 +215,7 @@ public: | ||||
| 	void openTownWindow(const CGTownInstance * town); //shows townscreen | ||||
| 	void openHeroWindow(const CGHeroInstance * hero); //shows hero window with given hero | ||||
| 	void updateInfo(const CGObjectInstance * specific); | ||||
| 	void init(std::shared_ptr<CCallback> CB) override; | ||||
| 	void init(std::shared_ptr<Environment> ENV, std::shared_ptr<CCallback> CB) override; | ||||
| 	int3 repairScreenPos(int3 pos); //returns position closest to pos we can center screen on | ||||
| 	void activateForSpectator(); // TODO: spectator probably need own player interface class | ||||
|  | ||||
|   | ||||
| @@ -45,6 +45,8 @@ | ||||
| #include <boost/uuid/uuid_generators.hpp> | ||||
| #include "../lib/serializer/Cast.h" | ||||
|  | ||||
| #include <vcmi/events/EventBus.h> | ||||
|  | ||||
| template<typename T> class CApplyOnLobby; | ||||
|  | ||||
| #ifdef VCMI_ANDROID | ||||
|   | ||||
| @@ -44,11 +44,12 @@ | ||||
| #include "lobby/CBonusSelection.h" | ||||
| #include "battle/CBattleInterface.h" | ||||
| #include "../lib/CThreadHelper.h" | ||||
| #include "../lib/CScriptingModule.h" | ||||
| #include "../lib/registerTypes/RegisterTypes.h" | ||||
| #include "gui/CGuiHandler.h" | ||||
| #include "CMT.h" | ||||
| #include "CServerHandler.h" | ||||
| #include "../lib/ScriptHandler.h" | ||||
| #include <vcmi/events/EventBus.h> | ||||
|  | ||||
| #ifdef VCMI_ANDROID | ||||
| #include "lib/CAndroidVMHelper.h" | ||||
| @@ -105,6 +106,39 @@ public: | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| CPlayerEnvironment::CPlayerEnvironment(PlayerColor player_, CClient * cl_, std::shared_ptr<CCallback> mainCallback_) | ||||
| 	: player(player_), | ||||
| 	cl(cl_), | ||||
| 	mainCallback(mainCallback_) | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| const Services * CPlayerEnvironment::services() const | ||||
| { | ||||
| 	return VLC; | ||||
| } | ||||
|  | ||||
| vstd::CLoggerBase * CPlayerEnvironment::logger() const | ||||
| { | ||||
| 	return logGlobal; | ||||
| } | ||||
|  | ||||
| events::EventBus * CPlayerEnvironment::eventBus() const | ||||
| { | ||||
| 	return cl->eventBus();//always get actual value | ||||
| } | ||||
|  | ||||
| const CPlayerEnvironment::BattleCb * CPlayerEnvironment::battle() const | ||||
| { | ||||
| 	return mainCallback.get(); | ||||
| } | ||||
|  | ||||
| const CPlayerEnvironment::GameCb * CPlayerEnvironment::game() const | ||||
| { | ||||
| 	return mainCallback.get(); | ||||
| } | ||||
|  | ||||
|  | ||||
| CClient::CClient() | ||||
| { | ||||
| @@ -114,7 +148,36 @@ CClient::CClient() | ||||
| 	registerTypesClientPacks2(*applier); | ||||
| 	IObjectInterface::cb = this; | ||||
| 	gs = nullptr; | ||||
| 	erm = nullptr; | ||||
| } | ||||
|  | ||||
| CClient::~CClient() | ||||
| { | ||||
| 	IObjectInterface::cb = nullptr; | ||||
| } | ||||
|  | ||||
| const Services * CClient::services() const | ||||
| { | ||||
| 	return VLC; //todo: this should be CGI | ||||
| } | ||||
|  | ||||
| const CClient::BattleCb * CClient::battle() const | ||||
| { | ||||
| 	return this; | ||||
| } | ||||
|  | ||||
| const CClient::GameCb * CClient::game() const | ||||
| { | ||||
| 	return this; | ||||
| } | ||||
|  | ||||
| vstd::CLoggerBase * CClient::logger() const | ||||
| { | ||||
| 	return logGlobal; | ||||
| } | ||||
|  | ||||
| events::EventBus * CClient::eventBus() const | ||||
| { | ||||
| 	return clientEventBus.get(); | ||||
| } | ||||
|  | ||||
| void CClient::newGame() | ||||
| @@ -122,11 +185,14 @@ void CClient::newGame() | ||||
| 	CSH->th->update(); | ||||
| 	CMapService mapService; | ||||
| 	gs = new CGameState(); | ||||
| 	gs->preInit(VLC); | ||||
| 	logNetwork->trace("\tCreating gamestate: %i", CSH->th->getDiff()); | ||||
| 	gs->init(&mapService, CSH->si.get(), settings["general"]["saveRandomMaps"].Bool()); | ||||
| 	logNetwork->trace("Initializing GameState (together): %d ms", CSH->th->getDiff()); | ||||
|  | ||||
| 	initMapHandler(); | ||||
| 	reinitScripting(); | ||||
| 	initPlayerEnvironments(); | ||||
| 	initPlayerInterfaces(); | ||||
| } | ||||
|  | ||||
| @@ -168,10 +234,16 @@ void CClient::loadGame() | ||||
| 		throw; //obviously we cannot continue here | ||||
| 	} | ||||
| 	logNetwork->trace("Loaded common part of save %d ms", CSH->th->getDiff()); | ||||
|  | ||||
| 	gs->preInit(VLC); | ||||
| 	gs->updateOnLoad(CSH->si.get()); | ||||
| 	initMapHandler(); | ||||
|  | ||||
| 	reinitScripting(); | ||||
|  | ||||
| 	initPlayerEnvironments(); | ||||
|  | ||||
| 	serialize(loader->serializer, loader->serializer.fileVersion); | ||||
|  | ||||
| 	initPlayerInterfaces(); | ||||
| } | ||||
|  | ||||
| @@ -190,6 +262,13 @@ void CClient::serialize(BinarySerializer & h, const int version) | ||||
| 		h & i->second->human; | ||||
| 		i->second->saveGame(h, version); | ||||
| 	} | ||||
|  | ||||
| 	if(version >= 800) | ||||
| 	{ | ||||
| 		JsonNode scriptsState; | ||||
| 		clientScripts->serializeState(h.saving, scriptsState); | ||||
| 		h & scriptsState; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CClient::serialize(BinaryDeserializer & h, const int version) | ||||
| @@ -253,6 +332,17 @@ void CClient::serialize(BinaryDeserializer & h, const int version) | ||||
| 		} | ||||
| 		nInt.reset(); | ||||
| 	} | ||||
|  | ||||
| 	{ | ||||
| 		JsonNode scriptsState; | ||||
| 		if(version >= 800) | ||||
| 		{ | ||||
| 			h & scriptsState; | ||||
| 		} | ||||
|  | ||||
| 		clientScripts->serializeState(h.saving, scriptsState); | ||||
| 	} | ||||
|  | ||||
| 	logNetwork->trace("Loaded client part of save %d ms", CSH->th->getDiff()); | ||||
| } | ||||
|  | ||||
| @@ -270,6 +360,8 @@ void CClient::save(const std::string & fname) | ||||
|  | ||||
| void CClient::endGame() | ||||
| { | ||||
| 	clientScripts.reset(); | ||||
|  | ||||
| 	//suggest interfaces to finish their stuff (AI should interrupt any bg working threads) | ||||
| 	for(auto & i : playerint) | ||||
| 		i.second->finish(); | ||||
| @@ -296,8 +388,8 @@ void CClient::endGame() | ||||
|  | ||||
| 	playerint.clear(); | ||||
| 	battleints.clear(); | ||||
| 	callbacks.clear(); | ||||
| 	battleCallbacks.clear(); | ||||
| 	playerEnvironments.clear(); | ||||
| 	logNetwork->info("Deleted playerInts."); | ||||
| 	logNetwork->info("Client stopped."); | ||||
| } | ||||
| @@ -319,6 +411,24 @@ void CClient::initMapHandler() | ||||
| 	pathCache.clear(); | ||||
| } | ||||
|  | ||||
| void CClient::initPlayerEnvironments() | ||||
| { | ||||
| 	playerEnvironments.clear(); | ||||
|  | ||||
| 	auto allPlayers = CSH->getAllClientPlayers(CSH->c->connectionID); | ||||
|  | ||||
| 	for(auto & color : allPlayers) | ||||
| 	{ | ||||
| 		logNetwork->info("Preparing environment for player %s", color.getStr()); | ||||
| 		playerEnvironments[color] = std::make_shared<CPlayerEnvironment>(color, this, std::make_shared<CCallback>(gs, color, this)); | ||||
| 	} | ||||
|  | ||||
| 	if(settings["session"]["spectate"].Bool()) | ||||
| 	{ | ||||
| 		playerEnvironments[PlayerColor::SPECTATOR] = std::make_shared<CPlayerEnvironment>(PlayerColor::SPECTATOR, this, std::make_shared<CCallback>(gs, boost::none, this)); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CClient::initPlayerInterfaces() | ||||
| { | ||||
| 	for(auto & elem : gs->scenarioOps->playerInfos) | ||||
| @@ -327,19 +437,20 @@ void CClient::initPlayerInterfaces() | ||||
| 		if(!vstd::contains(CSH->getAllClientPlayers(CSH->c->connectionID), color)) | ||||
| 			continue; | ||||
|  | ||||
| 		if(vstd::contains(playerint, color)) | ||||
| 			continue; | ||||
|  | ||||
| 		logNetwork->trace("Preparing interface for player %s", color.getStr()); | ||||
| 		if(elem.second.isControlledByAI()) | ||||
| 		if(!vstd::contains(playerint, color)) | ||||
| 		{ | ||||
| 			auto AiToGive = aiNameForPlayer(elem.second, false); | ||||
| 			logNetwork->info("Player %s will be lead by %s", color, AiToGive); | ||||
| 			installNewPlayerInterface(CDynLibHandler::getNewAI(AiToGive), color); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			installNewPlayerInterface(std::make_shared<CPlayerInterface>(color), color); | ||||
| 			logNetwork->info("Preparing interface for player %s", color.getStr()); | ||||
| 			if(elem.second.isControlledByAI()) | ||||
| 			{ | ||||
| 				auto AiToGive = aiNameForPlayer(elem.second, false); | ||||
| 				logNetwork->info("Player %s will be lead by %s", color.getStr(), AiToGive); | ||||
| 				installNewPlayerInterface(CDynLibHandler::getNewAI(AiToGive), color); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				logNetwork->info("Player %s will be lead by human", color.getStr()); | ||||
| 				installNewPlayerInterface(std::make_shared<CPlayerInterface>(color), color); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| @@ -379,41 +490,32 @@ std::string CClient::aiNameForPlayer(bool battleAI) | ||||
| 	return goodAI; | ||||
| } | ||||
|  | ||||
| void CClient::installNewPlayerInterface(std::shared_ptr<CGameInterface> gameInterface, boost::optional<PlayerColor> color, bool battlecb) | ||||
| void CClient::installNewPlayerInterface(std::shared_ptr<CGameInterface> gameInterface, PlayerColor color, bool battlecb) | ||||
| { | ||||
| 	boost::unique_lock<boost::recursive_mutex> un(*CPlayerInterface::pim); | ||||
| 	PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE); | ||||
|  | ||||
| 	if(!color) | ||||
| 		privilegedGameEventReceivers.push_back(gameInterface); | ||||
| 	playerint[color] = gameInterface; | ||||
|  | ||||
| 	playerint[colorUsed] = gameInterface; | ||||
|  | ||||
| 	logGlobal->trace("\tInitializing the interface for player %s", colorUsed); | ||||
| 	logGlobal->trace("\tInitializing the interface for player %s", color.getStr()); | ||||
| 	auto cb = std::make_shared<CCallback>(gs, color, this); | ||||
| 	callbacks[colorUsed] = cb; | ||||
| 	battleCallbacks[colorUsed] = cb; | ||||
| 	gameInterface->init(cb); | ||||
| 	battleCallbacks[color] = cb; | ||||
| 	gameInterface->init(playerEnvironments.at(color), cb); | ||||
|  | ||||
| 	installNewBattleInterface(gameInterface, color, battlecb); | ||||
| } | ||||
|  | ||||
| void CClient::installNewBattleInterface(std::shared_ptr<CBattleGameInterface> battleInterface, boost::optional<PlayerColor> color, bool needCallback) | ||||
| void CClient::installNewBattleInterface(std::shared_ptr<CBattleGameInterface> battleInterface, PlayerColor color, bool needCallback) | ||||
| { | ||||
| 	boost::unique_lock<boost::recursive_mutex> un(*CPlayerInterface::pim); | ||||
| 	PlayerColor colorUsed = color.get_value_or(PlayerColor::UNFLAGGABLE); | ||||
|  | ||||
| 	if(!color) | ||||
| 		privilegedBattleEventReceivers.push_back(battleInterface); | ||||
|  | ||||
| 	battleints[colorUsed] = battleInterface; | ||||
| 	battleints[color] = battleInterface; | ||||
|  | ||||
| 	if(needCallback) | ||||
| 	{ | ||||
| 		logGlobal->trace("\tInitializing the battle interface for player %s", *color); | ||||
| 		logGlobal->trace("\tInitializing the battle interface for player %s", color.getStr()); | ||||
| 		auto cbc = std::make_shared<CBattleCallback>(color, this); | ||||
| 		battleCallbacks[colorUsed] = cbc; | ||||
| 		battleInterface->init(cbc); | ||||
| 		battleCallbacks[color] = cbc; | ||||
| 		battleInterface->init(playerEnvironments.at(color), cbc); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -437,14 +539,6 @@ void CClient::handlePack(CPack * pack) | ||||
| 	delete pack; | ||||
| } | ||||
|  | ||||
| void CClient::commitPackage(CPackForClient * pack) | ||||
| { | ||||
| 	CommitPackage cp; | ||||
| 	cp.freePack = false; | ||||
| 	cp.packToCommit = pack; | ||||
| 	sendRequest(&cp, PlayerColor::NEUTRAL); | ||||
| } | ||||
|  | ||||
| int CClient::sendRequest(const CPackForServer * request, PlayerColor player) | ||||
| { | ||||
| 	static ui32 requestCounter = 0; | ||||
| @@ -464,6 +558,7 @@ int CClient::sendRequest(const CPackForServer * request, PlayerColor player) | ||||
|  | ||||
| void CClient::battleStarted(const BattleInfo * info) | ||||
| { | ||||
| 	setBattle(info); | ||||
| 	for(auto & battleCb : battleCallbacks) | ||||
| 	{ | ||||
| 		if(vstd::contains_if(info->sides, [&](const SideInBattle& side) {return side.color == battleCb.first; }) | ||||
| @@ -472,9 +567,6 @@ void CClient::battleStarted(const BattleInfo * info) | ||||
| 			battleCb.second->setBattle(info); | ||||
| 		} | ||||
| 	} | ||||
| // 	for(ui8 side : info->sides) | ||||
| // 		if(battleCallbacks.count(side)) | ||||
| // 			battleCallbacks[side]->setBattle(info); | ||||
|  | ||||
| 	std::shared_ptr<CPlayerInterface> att, def; | ||||
| 	auto & leftSide = info->sides[0], & rightSide = info->sides[1]; | ||||
| @@ -552,6 +644,8 @@ void CClient::battleFinished() | ||||
|  | ||||
| 	if(settings["session"]["spectate"].Bool() && !settings["session"]["spectate-skip-battle"].Bool()) | ||||
| 		battleCallbacks[PlayerColor::SPECTATOR]->setBattle(nullptr); | ||||
|  | ||||
| 	setBattle(nullptr); | ||||
| } | ||||
|  | ||||
| void CClient::startPlayerBattleAction(PlayerColor color) | ||||
| @@ -645,6 +739,23 @@ PlayerColor CClient::getLocalPlayer() const | ||||
| 	return getCurrentPlayer(); | ||||
| } | ||||
|  | ||||
| scripting::Pool * CClient::getGlobalContextPool() const | ||||
| { | ||||
| 	return clientScripts.get(); | ||||
| } | ||||
|  | ||||
| scripting::Pool * CClient::getContextPool() const | ||||
| { | ||||
| 	return clientScripts.get(); | ||||
| } | ||||
|  | ||||
| void CClient::reinitScripting() | ||||
| { | ||||
| 	clientEventBus = make_unique<events::EventBus>(); | ||||
| 	clientScripts.reset(new scripting::PoolImpl(this)); | ||||
| } | ||||
|  | ||||
|  | ||||
| #ifdef VCMI_ANDROID | ||||
| extern "C" JNIEXPORT void JNICALL Java_eu_vcmi_vcmi_NativeMethods_notifyServerClosed(JNIEnv * env, jobject cls) | ||||
| { | ||||
|   | ||||
| @@ -9,8 +9,11 @@ | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
| #include <vcmi/Environment.h> | ||||
|  | ||||
| #include "../lib/IGameCallback.h" | ||||
| #include "../lib/battle/BattleAction.h" | ||||
| #include "../lib/battle/CBattleInfoCallback.h" | ||||
| #include "../lib/CStopWatch.h" | ||||
| #include "../lib/int3.h" | ||||
| #include "../lib/CondSh.h" | ||||
| @@ -28,7 +31,6 @@ class CGameInterface; | ||||
| class CCallback; | ||||
| class BattleAction; | ||||
| class CClient; | ||||
| class CScriptingModule; | ||||
| struct CPathsInfo; | ||||
| class BinaryDeserializer; | ||||
| class BinarySerializer; | ||||
| @@ -37,6 +39,16 @@ namespace boost { class thread; } | ||||
| template<typename T> class CApplier; | ||||
| class CBaseForCLApply; | ||||
|  | ||||
| namespace scripting | ||||
| { | ||||
| 	class PoolImpl; | ||||
| } | ||||
|  | ||||
| namespace events | ||||
| { | ||||
| 	class EventBus; | ||||
| } | ||||
|  | ||||
| template<typename T> | ||||
| class ThreadSafeVector | ||||
| { | ||||
| @@ -95,32 +107,40 @@ public: | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| /// Class which handles client - server logic | ||||
| class CClient : public IGameCallback | ||||
| class CPlayerEnvironment : public Environment | ||||
| { | ||||
| public: | ||||
| 	PlayerColor player; | ||||
| 	CClient * cl; | ||||
| 	std::shared_ptr<CCallback> mainCallback; | ||||
|  | ||||
| 	CPlayerEnvironment(PlayerColor player_, CClient * cl_, std::shared_ptr<CCallback> mainCallback_); | ||||
| 	const Services * services() const override; | ||||
| 	vstd::CLoggerBase * logger() const override; | ||||
| 	events::EventBus * eventBus() const override; | ||||
| 	const BattleCb * battle() const override; | ||||
| 	const GameCb * game() const override; | ||||
| }; | ||||
|  | ||||
| /// Class which handles client - server logic | ||||
| class CClient : public IGameCallback, public CBattleInfoCallback, public Environment | ||||
| { | ||||
| 	std::shared_ptr<CApplier<CBaseForCLApply>> applier; | ||||
|  | ||||
| 	mutable boost::mutex pathCacheMutex; | ||||
| 	std::map<const CGHeroInstance *, std::shared_ptr<CPathsInfo>> pathCache; | ||||
|  | ||||
| 	std::map<PlayerColor, std::shared_ptr<boost::thread>> playerActionThreads; | ||||
| 	void waitForMoveAndSend(PlayerColor color); | ||||
|  | ||||
| public: | ||||
| 	std::map<PlayerColor, std::shared_ptr<CCallback>> callbacks; //callbacks given to player interfaces | ||||
| 	std::map<PlayerColor, std::shared_ptr<CBattleCallback>> battleCallbacks; //callbacks given to player interfaces | ||||
| 	std::vector<std::shared_ptr<IGameEventsReceiver>> privilegedGameEventReceivers; //scripting modules, spectator interfaces | ||||
| 	std::vector<std::shared_ptr<IBattleEventsReceiver>> privilegedBattleEventReceivers; //scripting modules, spectator interfaces | ||||
| 	std::map<PlayerColor, std::shared_ptr<CGameInterface>> playerint; | ||||
| 	std::map<PlayerColor, std::shared_ptr<CBattleGameInterface>> battleints; | ||||
|  | ||||
| 	std::map<PlayerColor, std::vector<std::shared_ptr<IGameEventsReceiver>>> additionalPlayerInts; | ||||
| 	std::map<PlayerColor, std::vector<std::shared_ptr<IBattleEventsReceiver>>> additionalBattleInts; | ||||
|  | ||||
| 	boost::optional<BattleAction> curbaction; | ||||
|  | ||||
| 	CScriptingModule * erm; | ||||
| 	CClient(); | ||||
| 	~CClient(); | ||||
|  | ||||
| 	const Services * services() const override; | ||||
| 	const BattleCb * battle() const override; | ||||
| 	const GameCb * game() const override; | ||||
| 	vstd::CLoggerBase * logger() const override; | ||||
| 	events::EventBus * eventBus() const override; | ||||
|  | ||||
| 	void newGame(); | ||||
| 	void loadGame(); | ||||
| @@ -131,17 +151,16 @@ public: | ||||
| 	void endGame(); | ||||
|  | ||||
| 	void initMapHandler(); | ||||
| 	void initPlayerEnvironments(); | ||||
| 	void initPlayerInterfaces(); | ||||
| 	std::string aiNameForPlayer(const PlayerSettings & ps, bool battleAI); //empty means no AI -> human | ||||
| 	std::string aiNameForPlayer(bool battleAI); | ||||
| 	void installNewPlayerInterface(std::shared_ptr<CGameInterface> gameInterface, boost::optional<PlayerColor> color, bool battlecb = false); | ||||
| 	void installNewBattleInterface(std::shared_ptr<CBattleGameInterface> battleInterface, boost::optional<PlayerColor> color, bool needCallback = true); | ||||
|  | ||||
| 	void installNewPlayerInterface(std::shared_ptr<CGameInterface> gameInterface, PlayerColor color, bool battlecb = false); | ||||
| 	void installNewBattleInterface(std::shared_ptr<CBattleGameInterface> battleInterface, PlayerColor color, bool needCallback = true); | ||||
|  | ||||
| 	static ThreadSafeVector<int> waitingRequest; //FIXME: make this normal field (need to join all threads before client destruction) | ||||
|  | ||||
| 	void handlePack(CPack * pack); //applies the given pack and deletes it | ||||
| 	void commitPackage(CPackForClient * pack) override; | ||||
| 	int sendRequest(const CPackForServer * request, PlayerColor player); //returns ID given to that request | ||||
|  | ||||
| 	void battleStarted(const BattleInfo * info); | ||||
| @@ -160,7 +179,6 @@ public: | ||||
|  | ||||
| 	void changeSpells(const CGHeroInstance * hero, bool give, const std::set<SpellID> & spells) override {}; | ||||
| 	bool removeObject(const CGObjectInstance * obj) override {return false;}; | ||||
| 	void setBlockVis(ObjectInstanceID objid, bool bv) override {}; | ||||
| 	void setOwner(const CGObjectInstance * obj, PlayerColor owner) override {}; | ||||
| 	void changePrimSkill(const CGHeroInstance * hero, PrimarySkill::PrimarySkill which, si64 val, bool abs = false) override {}; | ||||
| 	void changeSecSkill(const CGHeroInstance * hero, SecondarySkill which, int val, bool abs = false) override {}; | ||||
| @@ -190,7 +208,6 @@ public: | ||||
| 	void putArtifact(const ArtifactLocation & al, const CArtifactInstance * a) override {}; | ||||
| 	void removeArtifact(const ArtifactLocation & al) override {}; | ||||
| 	bool moveArtifact(const ArtifactLocation & al1, const ArtifactLocation & al2) override {return false;}; | ||||
| 	void synchronizeArtifactHandlerLists() override {}; | ||||
|  | ||||
| 	void showCompInfo(ShowInInfobox * comp) override {}; | ||||
| 	void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) override {}; | ||||
| @@ -199,7 +216,6 @@ public: | ||||
| 	void startBattlePrimary(const CArmedInstance * army1, const CArmedInstance * army2, int3 tile, const CGHeroInstance * hero1, const CGHeroInstance * hero2, bool creatureBank = false, const CGTownInstance * town = nullptr) override {}; //use hero=nullptr for no hero | ||||
| 	void startBattleI(const CArmedInstance * army1, const CArmedInstance * army2, int3 tile, bool creatureBank = false) override {}; //if any of armies is hero, hero will be used | ||||
| 	void startBattleI(const CArmedInstance * army1, const CArmedInstance * army2, bool creatureBank = false) override {}; //if any of armies is hero, hero will be used, visitable tile of second obj is place of battle | ||||
| 	void setAmount(ObjectInstanceID objid, ui32 val) override {}; | ||||
| 	bool moveHero(ObjectInstanceID hid, int3 dst, ui8 teleporting, bool transit = false, PlayerColor asker = PlayerColor::NEUTRAL) override {return false;}; | ||||
| 	void giveHeroBonus(GiveBonus * bonus) override {}; | ||||
| 	void setMovePoints(SetMovePoints * smp) override {}; | ||||
| @@ -211,4 +227,28 @@ public: | ||||
|  | ||||
| 	void changeFogOfWar(int3 center, ui32 radius, PlayerColor player, bool hide) override {} | ||||
| 	void changeFogOfWar(std::unordered_set<int3, ShashInt3> & tiles, PlayerColor player, bool hide) override {} | ||||
|  | ||||
| 	void setObjProperty(ObjectInstanceID objid, int prop, si64 val) override {} | ||||
|  | ||||
| 	void showInfoDialog(InfoWindow * iw) override {}; | ||||
| 	void showInfoDialog(const std::string & msg, PlayerColor player) override {}; | ||||
|  | ||||
| 	scripting::Pool * getGlobalContextPool() const override; | ||||
| 	scripting::Pool * getContextPool() const override; | ||||
| private: | ||||
| 	std::map<PlayerColor, std::shared_ptr<CBattleCallback>> battleCallbacks; //callbacks given to player interfaces | ||||
| 	std::map<PlayerColor, std::shared_ptr<CPlayerEnvironment>> playerEnvironments; | ||||
|  | ||||
| 	std::shared_ptr<scripting::PoolImpl> clientScripts; | ||||
| 	std::unique_ptr<events::EventBus> clientEventBus; | ||||
|  | ||||
| 	std::shared_ptr<CApplier<CBaseForCLApply>> applier; | ||||
|  | ||||
| 	mutable boost::mutex pathCacheMutex; | ||||
| 	std::map<const CGHeroInstance *, std::shared_ptr<CPathsInfo>> pathCache; | ||||
|  | ||||
| 	std::map<PlayerColor, std::shared_ptr<boost::thread>> playerActionThreads; | ||||
|  | ||||
| 	void waitForMoveAndSend(PlayerColor color); | ||||
| 	void reinitScripting(); | ||||
| }; | ||||
|   | ||||
| @@ -10,6 +10,14 @@ | ||||
| #include "StdInc.h" | ||||
| #include "Graphics.h" | ||||
|  | ||||
| #include <vcmi/Entity.h> | ||||
| #include <vcmi/ArtifactService.h> | ||||
| #include <vcmi/CreatureService.h> | ||||
| #include <vcmi/FactionService.h> | ||||
| #include <vcmi/HeroTypeService.h> | ||||
| #include <vcmi/SkillService.h> | ||||
| #include <vcmi/spells/Service.h> | ||||
|  | ||||
| #include "../lib/filesystem/Filesystem.h" | ||||
| #include "../lib/filesystem/CBinaryReader.h" | ||||
| #include "gui/SDL_Extensions.h" | ||||
| @@ -19,19 +27,15 @@ | ||||
| #include "CGameInfo.h" | ||||
| #include "../lib/VCMI_Lib.h" | ||||
| #include "../CCallback.h" | ||||
| #include "../lib/CHeroHandler.h" | ||||
| #include "../lib/CTownHandler.h" | ||||
| #include "../lib/CGeneralTextHandler.h" | ||||
| #include "../lib/CCreatureHandler.h" | ||||
| #include "CBitmapHandler.h" | ||||
| #include "../lib/CSkillHandler.h" | ||||
| #include "../lib/spells/CSpellHandler.h" | ||||
| #include "../lib/CGameState.h" | ||||
| #include "../lib/JsonNode.h" | ||||
| #include "../lib/vcmi_endian.h" | ||||
| #include "../lib/CStopWatch.h" | ||||
| #include "../lib/mapObjects/CObjectClassesHandler.h" | ||||
| #include "../lib/mapObjects/CObjectHandler.h" | ||||
| #include "../lib/CHeroHandler.h" | ||||
|  | ||||
| using namespace CSDL_Ext; | ||||
|  | ||||
| @@ -163,9 +167,9 @@ void Graphics::load() | ||||
|  | ||||
| void Graphics::loadHeroAnimations() | ||||
| { | ||||
| 	for(auto & elem : CGI->heroh->classes.heroClasses) | ||||
| 	for(auto & elem : CGI->heroh->classes.objects) | ||||
| 	{ | ||||
| 		for (auto & templ : VLC->objtypeh->getHandlerFor(Obj::HERO, elem->id)->getTemplates()) | ||||
| 		for (auto & templ : VLC->objtypeh->getHandlerFor(Obj::HERO, elem->getIndex())->getTemplates()) | ||||
| 		{ | ||||
| 			if (!heroAnimations.count(templ.animationFile)) | ||||
| 				heroAnimations[templ.animationFile] = loadHeroAnimation(templ.animationFile); | ||||
| @@ -423,74 +427,36 @@ void Graphics::loadErmuToPicture() | ||||
| 	assert (etp_idx == 44); | ||||
| } | ||||
|  | ||||
| void Graphics::addImageListEntry(size_t index, std::string listName, std::string imageName) | ||||
| void Graphics::addImageListEntry(size_t index, const std::string & listName, const std::string & imageName) | ||||
| { | ||||
| 	if (!imageName.empty()) | ||||
| 	{ | ||||
| 		JsonNode entry; | ||||
| 		entry["frame"].Float() = static_cast<double>(index); | ||||
| 		entry["frame"].Integer() = index; | ||||
| 		entry["file"].String() = imageName; | ||||
|  | ||||
| 		imageLists["SPRITES/" + listName]["images"].Vector().push_back(entry); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void Graphics::addImageListEntries(const EntityService * service) | ||||
| { | ||||
| 	auto cb = std::bind(&Graphics::addImageListEntry, this, _1, _2, _3); | ||||
|  | ||||
| 	auto loopCb = [&](const Entity * entity, bool & stop) | ||||
| 	{ | ||||
| 		entity->registerIcons(cb); | ||||
| 	}; | ||||
|  | ||||
| 	service->forEachBase(loopCb); | ||||
| } | ||||
|  | ||||
| void Graphics::initializeImageLists() | ||||
| { | ||||
| 	for(const CCreature * creature : CGI->creh->creatures) | ||||
| 	{ | ||||
| 		addImageListEntry(creature->iconIndex, "CPRSMALL", creature->smallIconName); | ||||
| 		addImageListEntry(creature->iconIndex, "TWCRPORT", creature->largeIconName); | ||||
| 	} | ||||
|  | ||||
| 	for(const CHero * hero : CGI->heroh->heroes) | ||||
| 	{ | ||||
| 		addImageListEntry(hero->imageIndex, "UN32", hero->iconSpecSmall); | ||||
| 		addImageListEntry(hero->imageIndex, "UN44", hero->iconSpecLarge); | ||||
| 		addImageListEntry(hero->imageIndex, "PORTRAITSLARGE", hero->portraitLarge); | ||||
| 		addImageListEntry(hero->imageIndex, "PORTRAITSSMALL", hero->portraitSmall); | ||||
| 	} | ||||
|  | ||||
| 	for(const CArtifact * art : CGI->arth->artifacts) | ||||
| 	{ | ||||
| 		addImageListEntry(art->iconIndex, "ARTIFACT", art->image); | ||||
| 		addImageListEntry(art->iconIndex, "ARTIFACTLARGE", art->large); | ||||
| 	} | ||||
|  | ||||
| 	for(const CFaction * faction : CGI->townh->factions) | ||||
| 	{ | ||||
| 		if (faction->town) | ||||
| 		{ | ||||
| 			auto & info = faction->town->clientInfo; | ||||
| 			addImageListEntry(info.icons[0][0], "ITPT", info.iconLarge[0][0]); | ||||
| 			addImageListEntry(info.icons[0][1], "ITPT", info.iconLarge[0][1]); | ||||
| 			addImageListEntry(info.icons[1][0], "ITPT", info.iconLarge[1][0]); | ||||
| 			addImageListEntry(info.icons[1][1], "ITPT", info.iconLarge[1][1]); | ||||
|  | ||||
| 			addImageListEntry(info.icons[0][0] + 2, "ITPA", info.iconSmall[0][0]); | ||||
| 			addImageListEntry(info.icons[0][1] + 2, "ITPA", info.iconSmall[0][1]); | ||||
| 			addImageListEntry(info.icons[1][0] + 2, "ITPA", info.iconSmall[1][0]); | ||||
| 			addImageListEntry(info.icons[1][1] + 2, "ITPA", info.iconSmall[1][1]); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	for(const CSpell * spell : CGI->spellh->objects) | ||||
| 	{ | ||||
| 		addImageListEntry(spell->id, "SPELLS", spell->iconBook); | ||||
| 		addImageListEntry(spell->id+1, "SPELLINT", spell->iconEffect); | ||||
| 		addImageListEntry(spell->id, "SPELLBON", spell->iconScenarioBonus); | ||||
| 		addImageListEntry(spell->id, "SPELLSCR", spell->iconScroll); | ||||
| 	} | ||||
|  | ||||
| 	for(const CSkill * skill : CGI->skillh->objects) | ||||
| 	{ | ||||
| 		for(int level = 1; level <= 3; level++) | ||||
| 		{ | ||||
| 			int frame = 2 + level + 3 * skill->id; | ||||
| 			const CSkill::LevelInfo & skillAtLevel = skill->at(level); | ||||
| 			addImageListEntry(frame, "SECSK32", skillAtLevel.iconSmall); | ||||
| 			addImageListEntry(frame, "SECSKILL", skillAtLevel.iconMedium); | ||||
| 			addImageListEntry(frame, "SECSK82", skillAtLevel.iconLarge); | ||||
| 		} | ||||
| 	} | ||||
| 	addImageListEntries(CGI->creatures()); | ||||
| 	addImageListEntries(CGI->heroTypes()); | ||||
| 	addImageListEntries(CGI->artifacts()); | ||||
| 	addImageListEntries(CGI->factions()); | ||||
| 	addImageListEntries(CGI->spells()); | ||||
| 	addImageListEntries(CGI->skills()); | ||||
| } | ||||
|   | ||||
| @@ -23,6 +23,7 @@ struct InfoAboutTown; | ||||
| class CGObjectInstance; | ||||
| class ObjectTemplate; | ||||
| class CAnimation; | ||||
| class EntityService; | ||||
|  | ||||
| enum EFonts | ||||
| { | ||||
| @@ -32,7 +33,9 @@ enum EFonts | ||||
| /// Handles fonts, hero images, town images, various graphics | ||||
| class Graphics | ||||
| { | ||||
| 	void addImageListEntry(size_t index, std::string listName, std::string imageName); | ||||
| 	void addImageListEntry(size_t index, const std::string & listName, const std::string & imageName); | ||||
|  | ||||
| 	void addImageListEntries(const EntityService * service); | ||||
|  | ||||
| 	void initializeBattleGraphics(); | ||||
| 	void loadPaletteAndColors(); | ||||
|   | ||||
| @@ -45,12 +45,6 @@ | ||||
|  | ||||
| // TODO: as Tow suggested these template should all be part of CClient | ||||
| // This will require rework spectator interface properly though | ||||
| template<typename T, typename ... Args, typename ... Args2> | ||||
| void callPrivilegedInterfaces(CClient * cl, void (T::*ptr)(Args...), Args2 && ...args) | ||||
| { | ||||
| 	for(auto &ger : cl->privilegedGameEventReceivers) | ||||
| 		((*ger).*ptr)(std::forward<Args2>(args)...); | ||||
| } | ||||
|  | ||||
| template<typename T, typename ... Args, typename ... Args2> | ||||
| bool callOnlyThatInterface(CClient * cl, PlayerColor player, void (T::*ptr)(Args...), Args2 && ...args) | ||||
| @@ -67,7 +61,6 @@ template<typename T, typename ... Args, typename ... Args2> | ||||
| bool callInterfaceIfPresent(CClient * cl, PlayerColor player, void (T::*ptr)(Args...), Args2 && ...args) | ||||
| { | ||||
| 	bool called = callOnlyThatInterface(cl, player, ptr, std::forward<Args2>(args)...); | ||||
| 	callPrivilegedInterfaces(cl, ptr, std::forward<Args2>(args)...); | ||||
| 	return called; | ||||
| } | ||||
|  | ||||
| @@ -84,18 +77,10 @@ void callOnlyThatBattleInterface(CClient * cl, PlayerColor player, void (T::*ptr | ||||
| 	} | ||||
| } | ||||
|  | ||||
| template<typename T, typename ... Args, typename ... Args2> | ||||
| void callPrivilegedBattleInterfaces(CClient * cl, void (T::*ptr)(Args...), Args2 && ...args) | ||||
| { | ||||
| 	for(auto & ber : cl->privilegedBattleEventReceivers) | ||||
| 		((*ber).*ptr)(std::forward<Args2>(args)...); | ||||
| } | ||||
|  | ||||
| template<typename T, typename ... Args, typename ... Args2> | ||||
| void callBattleInterfaceIfPresent(CClient * cl, PlayerColor player, void (T::*ptr)(Args...), Args2 && ...args) | ||||
| { | ||||
| 	callOnlyThatInterface(cl, player, ptr, std::forward<Args2>(args)...); | ||||
| 	callPrivilegedBattleInterfaces(cl, ptr, std::forward<Args2>(args)...); | ||||
| } | ||||
|  | ||||
| //calls all normal interfaces and privileged ones, playerints may be updated when iterating over it, so we need a copy | ||||
| @@ -116,10 +101,8 @@ void callBattleInterfaceIfPresentForBothSides(CClient * cl, void (T::*ptr)(Args. | ||||
| 	{ | ||||
| 		callOnlyThatBattleInterface(cl, PlayerColor::SPECTATOR, ptr, std::forward<Args2>(args)...); | ||||
| 	} | ||||
| 	callPrivilegedBattleInterfaces(cl, ptr, std::forward<Args2>(args)...); | ||||
| } | ||||
|  | ||||
|  | ||||
| void SetResources::applyCl(CClient *cl) | ||||
| { | ||||
| 	//todo: inform on actual resource set transfered | ||||
| @@ -307,7 +290,7 @@ void GiveBonus::applyCl(CClient *cl) | ||||
| 		break; | ||||
| 	case PLAYER: | ||||
| 		{ | ||||
| 			const PlayerState *p = GS(cl)->getPlayer(PlayerColor(id)); | ||||
| 			const PlayerState *p = GS(cl)->getPlayerState(PlayerColor(id)); | ||||
| 			callInterfaceIfPresent(cl, PlayerColor(id), &IGameEventsReceiver::playerBonusChanged, *p->getBonusList().back(), true); | ||||
| 		} | ||||
| 		break; | ||||
| @@ -351,7 +334,7 @@ void RemoveBonus::applyCl(CClient *cl) | ||||
| 		break; | ||||
| 	case PLAYER: | ||||
| 		{ | ||||
| 			//const PlayerState *p = GS(cl)->getPlayer(id); | ||||
| 			//const PlayerState *p = GS(cl)->getPlayerState(id); | ||||
| 			callInterfaceIfPresent(cl, PlayerColor(id), &IGameEventsReceiver::playerBonusChanged, bonus, false); | ||||
| 		} | ||||
| 		break; | ||||
| @@ -370,7 +353,7 @@ void RemoveObject::applyFirstCl(CClient *cl) | ||||
| 	{ | ||||
| 		//below line contains little cheat for AI so it will be aware of deletion of enemy heroes that moved or got re-covered by FoW | ||||
| 		//TODO: loose requirements as next AI related crashes appear, for example another player collects object that got re-covered by FoW, unsure if AI code workarounds this | ||||
| 		if(GS(cl)->isVisible(o, i->first) || (!cl->getPlayer(i->first)->human && o->ID == Obj::HERO && o->tempOwner != i->first)) | ||||
| 		if(GS(cl)->isVisible(o, i->first) || (!cl->getPlayerState(i->first)->human && o->ID == Obj::HERO && o->tempOwner != i->first)) | ||||
| 			i->second->objectRemoved(o); | ||||
| 	} | ||||
| } | ||||
| @@ -387,7 +370,7 @@ void TryMoveHero::applyFirstCl(CClient *cl) | ||||
| 	//check if playerint will have the knowledge about movement - if not, directly update maphandler | ||||
| 	for(auto i=cl->playerint.begin(); i!=cl->playerint.end(); i++) | ||||
| 	{ | ||||
| 		auto ps = GS(cl)->getPlayer(i->first); | ||||
| 		auto ps = GS(cl)->getPlayerState(i->first); | ||||
| 		if(ps && (GS(cl)->isVisible(start - int3(1, 0, 0), i->first) || GS(cl)->isVisible(end - int3(1, 0, 0), i->first))) | ||||
| 		{ | ||||
| 			if(ps->human) | ||||
| @@ -611,8 +594,6 @@ void BattleStart::applyFirstCl(CClient *cl) | ||||
| 		info->tile, info->sides[0].hero, info->sides[1].hero); | ||||
| 	callOnlyThatBattleInterface(cl, PlayerColor::SPECTATOR, &IBattleEventsReceiver::battleStartBefore, info->sides[0].armyObject, info->sides[1].armyObject, | ||||
| 		info->tile, info->sides[0].hero, info->sides[1].hero); | ||||
| 	callPrivilegedBattleInterfaces(cl, &IBattleEventsReceiver::battleStartBefore, info->sides[0].armyObject, info->sides[1].armyObject, | ||||
| 		info->tile, info->sides[0].hero, info->sides[1].hero); | ||||
| } | ||||
|  | ||||
| void BattleStart::applyCl(CClient *cl) | ||||
| @@ -651,6 +632,11 @@ void BattleSetActiveStack::applyCl(CClient *cl) | ||||
| 	cl->startPlayerBattleAction(playerToCall); | ||||
| } | ||||
|  | ||||
| void BattleLogMessage::applyCl(CClient * cl) | ||||
| { | ||||
| 	callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleLogMessage, lines); | ||||
| } | ||||
|  | ||||
| void BattleTriggerEffect::applyCl(CClient * cl) | ||||
| { | ||||
| 	callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleTriggerEffect, *this); | ||||
| @@ -680,7 +666,7 @@ void BattleAttack::applyFirstCl(CClient *cl) | ||||
|  | ||||
| void BattleAttack::applyCl(CClient *cl) | ||||
| { | ||||
| 	callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleStacksAttacked, bsa, battleLog); | ||||
| 	callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleStacksAttacked, bsa); | ||||
| } | ||||
|  | ||||
| void StartAction::applyFirstCl(CClient *cl) | ||||
| @@ -702,7 +688,7 @@ void SetStackEffect::applyCl(CClient *cl) | ||||
|  | ||||
| void StacksInjured::applyCl(CClient *cl) | ||||
| { | ||||
| 	callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleStacksAttacked, stacks, battleLog); | ||||
| 	callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleStacksAttacked, stacks); | ||||
| } | ||||
|  | ||||
| void BattleResultsApplied::applyCl(CClient *cl) | ||||
| @@ -714,7 +700,7 @@ void BattleResultsApplied::applyCl(CClient *cl) | ||||
|  | ||||
| void BattleUnitsChanged::applyCl(CClient * cl) | ||||
| { | ||||
| 	callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleUnitsChanged, changedStacks, customEffects, battleLog); | ||||
| 	callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleUnitsChanged, changedStacks, customEffects); | ||||
| } | ||||
|  | ||||
| void BattleObstaclesChanged::applyCl(CClient *cl) | ||||
| @@ -795,7 +781,7 @@ void PlayerMessageClient::applyCl(CClient *cl) | ||||
| 	if(player.isSpectator()) | ||||
| 		str << "Spectator: " << text; | ||||
| 	else | ||||
| 		str << cl->getPlayer(player)->nodeName() <<": " << text; | ||||
| 		str << cl->getPlayerState(player)->nodeName() <<": " << text; | ||||
| 	if(LOCPLINT) | ||||
| 		LOCPLINT->cingconsole->print(str.str()); | ||||
| } | ||||
| @@ -918,3 +904,9 @@ void SetAvailableArtifacts::applyCl(CClient *cl) | ||||
| 		callInterfaceIfPresent(cl, cl->getTile(bm->visitablePos())->visitableObjects.back()->tempOwner, &IGameEventsReceiver::availableArtifactsChanged, bm); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| void EntitiesChanged::applyCl(CClient *cl) | ||||
| { | ||||
| 	cl->invalidatePaths(); | ||||
| } | ||||
|   | ||||
| @@ -4,6 +4,7 @@ | ||||
| 	<Project> | ||||
| 		<Option title="VCMI_client" /> | ||||
| 		<Option pch_mode="2" /> | ||||
| 		<Option default_target="Debug-win64" /> | ||||
| 		<Option compiler="gcc" /> | ||||
| 		<Build> | ||||
| 			<Target title="Debug-win32"> | ||||
| @@ -13,7 +14,6 @@ | ||||
| 				<Option object_output="../obj/Client/Debug/x86" /> | ||||
| 				<Option type="1" /> | ||||
| 				<Option compiler="gcc" /> | ||||
| 				<Option parameters="--testmap=Maps/Reclamation --spectate --spectate-skip-battle --spectate-ignore-hero" /> | ||||
| 				<Compiler> | ||||
| 					<Add option="-Og" /> | ||||
| 					<Add option="-g" /> | ||||
| @@ -91,7 +91,7 @@ | ||||
| 			<Add option="-isystem $(#boost.include)" /> | ||||
| 			<Add option="-DBOOST_ALL_DYN_LINK" /> | ||||
| 			<Add option="-DBOOST_SYSTEM_NO_DEPRECATED" /> | ||||
| 			<Add option="-D_WIN32_WINNT=0x0501" /> | ||||
| 			<Add option="-D_WIN32_WINNT=0x0600" /> | ||||
| 			<Add option="-D_WIN32" /> | ||||
| 			<Add option="-DBOOST_UUID_RANDOM_PROVIDER_FORCE_WINCRYPT" /> | ||||
| 			<Add directory="../client" /> | ||||
| @@ -246,10 +246,6 @@ | ||||
| 		<Unit filename="windows/QuickRecruitmentWindow.cpp" /> | ||||
| 		<Unit filename="windows/QuickRecruitmentWindow.h" /> | ||||
| 		<Extensions> | ||||
| 			<code_completion /> | ||||
| 			<envvars /> | ||||
| 			<debugger /> | ||||
| 			<lib_finder disable_auto="1" /> | ||||
| 			<DoxyBlocks> | ||||
| 				<comment_style block="0" line="0" /> | ||||
| 				<doxyfile_project /> | ||||
| @@ -259,6 +255,7 @@ | ||||
| 				<doxyfile_dot /> | ||||
| 				<general /> | ||||
| 			</DoxyBlocks> | ||||
| 			<lib_finder disable_auto="1" /> | ||||
| 		</Extensions> | ||||
| 	</Project> | ||||
| </CodeBlocks_project_file> | ||||
|   | ||||
| @@ -29,7 +29,6 @@ | ||||
| #include "../../lib/CStack.h" | ||||
| #include "../../lib/CTownHandler.h" | ||||
| #include "../../lib/mapObjects/CGTownInstance.h" | ||||
| #include "../../lib/spells/CSpellHandler.h" | ||||
|  | ||||
| CBattleAnimation::CBattleAnimation(CBattleInterface * _owner) | ||||
| 	: owner(_owner), ID(_owner->animIDhelper++) | ||||
| @@ -762,15 +761,15 @@ bool CShootingAnimation::init() | ||||
| 	if(shooterInfo->idNumber == CreatureID::ARROW_TOWERS) | ||||
| 	{ | ||||
| 		int creID = owner->siegeH->town->town->clientInfo.siegeShooter; | ||||
| 		shooterInfo = CGI->creh->creatures[creID]; | ||||
| 		shooterInfo = CGI->creh->operator[](creID); | ||||
| 	} | ||||
| 	if(!shooterInfo->animation.missleFrameAngles.size()) | ||||
| 		logAnim->error("Mod error: Creature '%s' on the Archer's tower is not a shooter. Mod should be fixed. Trying to use archer's data instead..." | ||||
| 			, shooterInfo->nameSing); | ||||
| 	 | ||||
| 	auto & angles = shooterInfo->animation.missleFrameAngles.size()  | ||||
|  | ||||
| 	auto & angles = shooterInfo->animation.missleFrameAngles.size() | ||||
| 		? shooterInfo->animation.missleFrameAngles | ||||
| 		: CGI->creh->creatures[CreatureID::ARCHER]->animation.missleFrameAngles; | ||||
| 		: CGI->creh->operator[](CreatureID::ARCHER)->animation.missleFrameAngles; | ||||
|  | ||||
| 	ProjectileInfo spi; | ||||
| 	spi.shotDone = false; | ||||
|   | ||||
| @@ -38,6 +38,8 @@ | ||||
| #include "../../lib/CondSh.h" | ||||
| #include "../../lib/CRandomGenerator.h" | ||||
| #include "../../lib/spells/CSpellHandler.h" | ||||
| #include "../../lib/spells/ISpellMechanics.h" | ||||
| #include "../../lib/spells/Problem.h" | ||||
| #include "../../lib/CTownHandler.h" | ||||
| #include "../../lib/CGameState.h" | ||||
| #include "../../lib/mapping/CMap.h" | ||||
| @@ -398,7 +400,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet | ||||
| 	for(auto hex : bfield) | ||||
| 		addChild(hex.get()); | ||||
|  | ||||
| 	if (tacticsMode) | ||||
| 	if(tacticsMode) | ||||
| 		bTacticNextStack(); | ||||
|  | ||||
| 	CCS->musich->stopMusic(); | ||||
| @@ -415,7 +417,6 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet | ||||
| 	}; | ||||
|  | ||||
| 	CCS->soundh->setCallback(battleIntroSoundChannel, onIntroPlayed); | ||||
| 	memset(stackCountOutsideHexes, 1, GameConstants::BFIELD_SIZE *sizeof(bool)); //initialize array with trues | ||||
|  | ||||
| 	currentAction = PossiblePlayerBattleAction::INVALID; | ||||
| 	selectedAction = PossiblePlayerBattleAction::INVALID; | ||||
| @@ -579,7 +580,7 @@ void CBattleInterface::keyPressed(const SDL_KeyboardEvent & key) | ||||
| 		if(!battleActionsStarted) | ||||
| 			CCS->soundh->stopSound(battleIntroSoundChannel); | ||||
| 		else | ||||
| 			endCastingSpell(); | ||||
| 		endCastingSpell(); | ||||
| 	} | ||||
| } | ||||
| void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent) | ||||
| @@ -794,7 +795,7 @@ void CBattleInterface::bSurrenderf() | ||||
| 	if (cost >= 0) | ||||
| 	{ | ||||
| 		std::string enemyHeroName = curInt->cb->battleGetEnemyHero().name; | ||||
| 		if(enemyHeroName.empty()) | ||||
| 		if (enemyHeroName.empty()) | ||||
| 		{ | ||||
| 			logGlobal->warn("Surrender performed without enemy hero, should not happen!"); | ||||
| 			enemyHeroName = "#ENEMY#"; | ||||
| @@ -871,7 +872,7 @@ void CBattleInterface::bAutofightf() | ||||
| 		blockUI(true); | ||||
|  | ||||
| 		auto ai = CDynLibHandler::getNewBattleAI(settings["server"]["friendlyAI"].String()); | ||||
| 		ai->init(curInt->cb); | ||||
| 		ai->init(curInt->env, curInt->cb); | ||||
| 		ai->battleStart(army1, army2, int3(0,0,0), attackingHeroInstance, defendingHeroInstance, curInt->cb->battleGetMySide()); | ||||
| 		curInt->autofightingAI = ai; | ||||
| 		curInt->cb->registerBattleInterface(ai); | ||||
| @@ -910,14 +911,14 @@ void CBattleInterface::bSpellf() | ||||
|  | ||||
| 		if (blockingBonus->source == Bonus::ARTIFACT) | ||||
| 		{ | ||||
| 			const int artID = blockingBonus->sid; | ||||
| 			const int32_t artID = blockingBonus->sid; | ||||
| 			//If we have artifact, put name of our hero. Otherwise assume it's the enemy. | ||||
| 			//TODO check who *really* is source of bonus | ||||
| 			std::string heroName = myHero->hasArt(artID) ? myHero->name : enemyHero().name; | ||||
|  | ||||
| 			//%s wields the %s, an ancient artifact which creates a p dead to all magic. | ||||
| 			LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[683]) | ||||
| 										% heroName % CGI->arth->artifacts[artID]->Name())); | ||||
| 										% heroName % CGI->artifacts()->getByIndex(artID)->getName())); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -964,7 +965,7 @@ void CBattleInterface::unitAdded(const CStack * stack) | ||||
|  | ||||
| 	if(stack->initialPosition < 0) //turret | ||||
| 	{ | ||||
| 		const CCreature *turretCreature = CGI->creh->creatures[siegeH->town->town->clientInfo.siegeShooter]; | ||||
| 		const CCreature *turretCreature = CGI->creh->objects[siegeH->town->town->clientInfo.siegeShooter]; | ||||
|  | ||||
| 		creAnims[stack->ID] = AnimationControls::getAnimation(turretCreature); | ||||
|  | ||||
| @@ -1012,7 +1013,7 @@ void CBattleInterface::initStackProjectile(const CStack * stack) | ||||
| { | ||||
| 	const CCreature * creature;//creature whose shots should be loaded | ||||
| 	if(stack->getCreature()->idNumber == CreatureID::ARROW_TOWERS) | ||||
| 		creature = CGI->creh->creatures[siegeH->town->town->clientInfo.siegeShooter]; | ||||
| 		creature = CGI->creh->objects[siegeH->town->town->clientInfo.siegeShooter]; | ||||
| 	else | ||||
| 		creature = stack->getCreature(); | ||||
|  | ||||
| @@ -1062,7 +1063,7 @@ void CBattleInterface::stackMoved(const CStack *stack, std::vector<BattleHex> de | ||||
| 	waitForAnims(); | ||||
| } | ||||
|  | ||||
| void CBattleInterface::stacksAreAttacked(std::vector<StackAttackedInfo> attackedInfos, const std::vector<MetaString> & battleLog) | ||||
| void CBattleInterface::stacksAreAttacked(std::vector<StackAttackedInfo> attackedInfos) | ||||
| { | ||||
| 	for(auto & attackedInfo : attackedInfos) | ||||
| 	{ | ||||
| @@ -1089,8 +1090,6 @@ void CBattleInterface::stacksAreAttacked(std::vector<StackAttackedInfo> attacked | ||||
| 		killedBySide.at(side) += attackedInfo.amountKilled; | ||||
| 	} | ||||
|  | ||||
| 	int killed = killedBySide[0] + killedBySide[1]; | ||||
|  | ||||
| 	for(ui8 side = 0; side < 2; side++) | ||||
| 	{ | ||||
| 		if(killedBySide.at(side) > killedBySide.at(1-side)) | ||||
| @@ -1106,11 +1105,6 @@ void CBattleInterface::stacksAreAttacked(std::vector<StackAttackedInfo> attacked | ||||
| 		if (attackedInfo.cloneKilled) | ||||
| 			stackRemoved(attackedInfo.defender->ID); | ||||
| 	} | ||||
|  | ||||
| 	if(!battleLog.empty()) | ||||
| 		displayBattleLog(battleLog); | ||||
| 	else | ||||
| 		printConsoleAttacked(attackedInfos.front().defender, damage, killed, attackedInfos.front().attacker, (targets > 1)); //creatures perish | ||||
| } | ||||
|  | ||||
| void CBattleInterface::stackAttacking( const CStack *attacker, BattleHex dest, const CStack *attacked, bool shooting ) | ||||
| @@ -1377,9 +1371,6 @@ void CBattleInterface::spellCast(const BattleSpellCast * sc) | ||||
| 			displayEffect(elem.effect, stack->getPosition()); | ||||
| 	} | ||||
|  | ||||
| 	//displaying message in console | ||||
| 	displayBattleLog(sc->battleLog); | ||||
|  | ||||
| 	waitForAnims(); | ||||
| 	//mana absorption | ||||
| 	if (sc->manaGained > 0) | ||||
| @@ -1393,9 +1384,6 @@ void CBattleInterface::spellCast(const BattleSpellCast * sc) | ||||
|  | ||||
| void CBattleInterface::battleStacksEffectsSet(const SetStackEffect & sse) | ||||
| { | ||||
| 	for(const MetaString & line : sse.battleLog) | ||||
| 		console->addText(line.toString()); | ||||
|  | ||||
| 	if(activeStack != nullptr) | ||||
| 		redrawBackgroundWithHexes(activeStack); | ||||
| } | ||||
| @@ -1474,28 +1462,19 @@ void CBattleInterface::displayEffect(ui32 effect, BattleHex destTile) | ||||
| 	addNewAnim(new CEffectAnimation(this, customAnim, destTile)); | ||||
| } | ||||
|  | ||||
| void CBattleInterface::displaySpellAnimation(const CSpell::TAnimation & animation, BattleHex destinationTile) | ||||
| { | ||||
| 	if (animation.pause > 0) | ||||
| 	{ | ||||
| 		addNewAnim(new CDummyAnimation(this, animation.pause)); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		addNewAnim(new CEffectAnimation(this, animation.resourceName, destinationTile, false, animation.verticalPosition == VerticalPosition::BOTTOM)); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CBattleInterface::displaySpellCast(SpellID spellID, BattleHex destinationTile) | ||||
| { | ||||
| 	const CSpell *spell = spellID.toSpell(); | ||||
| 	const CSpell * spell = spellID.toSpell(); | ||||
|  | ||||
| 	if (spell == nullptr) | ||||
| 	if(spell == nullptr) | ||||
| 		return; | ||||
|  | ||||
| 	for (const CSpell::TAnimation & animation : spell->animationInfo.cast) | ||||
| 	for(const CSpell::TAnimation & animation : spell->animationInfo.cast) | ||||
| 	{ | ||||
| 		displaySpellAnimation(animation, destinationTile); | ||||
| 		if(animation.pause > 0) | ||||
| 			addNewAnim(new CDummyAnimation(this, animation.pause)); | ||||
| 		else | ||||
| 			addNewAnim(new CEffectAnimation(this, animation.resourceName, destinationTile, false, animation.verticalPosition == VerticalPosition::BOTTOM)); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -1503,25 +1482,32 @@ void CBattleInterface::displaySpellEffect(SpellID spellID, BattleHex destination | ||||
| { | ||||
| 	const CSpell *spell = spellID.toSpell(); | ||||
|  | ||||
| 	if (spell == nullptr) | ||||
| 	if(spell == nullptr) | ||||
| 		return; | ||||
|  | ||||
| 	for (const CSpell::TAnimation & animation : spell->animationInfo.affect) | ||||
| 	for(const CSpell::TAnimation & animation : spell->animationInfo.affect) | ||||
| 	{ | ||||
| 		displaySpellAnimation(animation, destinationTile); | ||||
| 		if(animation.pause > 0) | ||||
| 			addNewAnim(new CDummyAnimation(this, animation.pause)); | ||||
| 		else | ||||
| 			addNewAnim(new CEffectAnimation(this, animation.resourceName, destinationTile, false, animation.verticalPosition == VerticalPosition::BOTTOM)); | ||||
|  | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CBattleInterface::displaySpellHit(SpellID spellID, BattleHex destinationTile) | ||||
| { | ||||
| 	const CSpell *spell = spellID.toSpell(); | ||||
| 	const CSpell * spell = spellID.toSpell(); | ||||
|  | ||||
| 	if (spell == nullptr) | ||||
| 	if(spell == nullptr) | ||||
| 		return; | ||||
|  | ||||
| 	for (const CSpell::TAnimation & animation : spell->animationInfo.hit) | ||||
| 	for(const CSpell::TAnimation & animation : spell->animationInfo.hit) | ||||
| 	{ | ||||
| 		displaySpellAnimation(animation, destinationTile); | ||||
| 		if(animation.pause > 0) | ||||
| 			addNewAnim(new CDummyAnimation(this, animation.pause)); | ||||
| 		else | ||||
| 			addNewAnim(new CEffectAnimation(this, animation.resourceName, destinationTile, false, animation.verticalPosition == VerticalPosition::BOTTOM)); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -1712,9 +1698,19 @@ void CBattleInterface::enterCreatureCastingMode() | ||||
|  | ||||
| 	if (vstd::contains(possibleActions, PossiblePlayerBattleAction::NO_LOCATION)) | ||||
| 	{ | ||||
| 		const spells::Caster *caster = activeStack; | ||||
| 		const CSpell *spell = SpellID(creatureSpellToCast).toSpell(); | ||||
| 		const bool isCastingPossible = spell->canBeCastAt(curInt->cb.get(), spells::Mode::CREATURE_ACTIVE, caster, BattleHex::INVALID); | ||||
| 		const spells::Caster * caster = activeStack; | ||||
| 		const CSpell * spell = SpellID(creatureSpellToCast).toSpell(); | ||||
|  | ||||
| 		spells::Target target; | ||||
| 		target.emplace_back(); | ||||
|  | ||||
|  | ||||
| 		spells::BattleCast cast(curInt->cb.get(), caster, spells::Mode::CREATURE_ACTIVE, spell); | ||||
|  | ||||
| 		auto m = spell->battleMechanics(&cast); | ||||
| 		spells::detail::ProblemImpl ignored; | ||||
|  | ||||
| 		const bool isCastingPossible = m->canBeCastAt(ignored, target); | ||||
|  | ||||
| 		if (isCastingPossible) | ||||
| 		{ | ||||
| @@ -1732,7 +1728,7 @@ void CBattleInterface::enterCreatureCastingMode() | ||||
| 		auto actionFilterPredicate = [](const PossiblePlayerBattleAction x) | ||||
| 		{ | ||||
| 			return (x != PossiblePlayerBattleAction::ANY_LOCATION) && (x != PossiblePlayerBattleAction::NO_LOCATION) && | ||||
| 				(x != PossiblePlayerBattleAction::FREE_LOCATION) && (x != PossiblePlayerBattleAction::AIMED_SPELL_CREATURE) &&  | ||||
| 				(x != PossiblePlayerBattleAction::FREE_LOCATION) && (x != PossiblePlayerBattleAction::AIMED_SPELL_CREATURE) && | ||||
| 				(x != PossiblePlayerBattleAction::OBSTACLE); | ||||
| 		}; | ||||
|  | ||||
| @@ -1766,7 +1762,7 @@ void CBattleInterface::reorderPossibleActionsPriority(const CStack * stack, Mous | ||||
| 		case PossiblePlayerBattleAction::OBSTACLE: | ||||
| 			if(!stack->hasBonusOfType(Bonus::NO_SPELLCAST_BY_DEFAULT) && context == MouseHoveredHexContext::OCCUPIED_HEX) | ||||
| 				return 1; | ||||
| 			else | ||||
| 					else | ||||
| 				return 100;//bottom priority | ||||
| 			break; | ||||
| 		case PossiblePlayerBattleAction::RANDOM_GENIE_SPELL: | ||||
| @@ -1784,9 +1780,9 @@ void CBattleInterface::reorderPossibleActionsPriority(const CStack * stack, Mous | ||||
| 		case PossiblePlayerBattleAction::MOVE_STACK: | ||||
| 			return 8; break; | ||||
| 		case PossiblePlayerBattleAction::CATAPULT: | ||||
| 			return 9; break;		 | ||||
| 			return 9; break; | ||||
| 		case PossiblePlayerBattleAction::HEAL: | ||||
| 			return 10; break;	 | ||||
| 			return 10; break; | ||||
| 		default: | ||||
| 			return 200; break; | ||||
| 		} | ||||
| @@ -1800,39 +1796,6 @@ void CBattleInterface::reorderPossibleActionsPriority(const CStack * stack, Mous | ||||
| 	std::make_heap(possibleActions.begin(), possibleActions.end(), comparer); | ||||
| } | ||||
|  | ||||
| void CBattleInterface::printConsoleAttacked(const CStack * defender, int dmg, int killed, const CStack * attacker, bool multiple) | ||||
| { | ||||
| 	std::string formattedText; | ||||
| 	if(attacker) //ignore if stacks were killed by spell | ||||
| 	{ | ||||
| 		MetaString text; | ||||
| 		attacker->addText(text, MetaString::GENERAL_TXT, 376); | ||||
| 		attacker->addNameReplacement(text); | ||||
| 		text.addReplacement(dmg); | ||||
| 		formattedText = text.toString(); | ||||
| 	} | ||||
|  | ||||
| 	if(killed > 0) | ||||
| 	{ | ||||
| 		if(attacker) | ||||
| 			formattedText.append(" "); | ||||
|  | ||||
| 		boost::format txt; | ||||
| 		if(killed > 1) | ||||
| 		{ | ||||
| 			txt = boost::format(CGI->generaltexth->allTexts[379]) % killed % (multiple ? CGI->generaltexth->allTexts[43] : defender->getCreature()->namePl); // creatures perish | ||||
| 		} | ||||
| 		else //killed == 1 | ||||
| 		{ | ||||
| 			txt = boost::format(CGI->generaltexth->allTexts[378]) % (multiple ? CGI->generaltexth->allTexts[42] : defender->getCreature()->nameSing); // creature perishes | ||||
| 		} | ||||
| 		std::string trimmed = boost::to_string(txt); | ||||
| 		boost::algorithm::trim(trimmed); // these default h3 texts have unnecessary new lines, so get rid of them before displaying | ||||
| 		formattedText.append(trimmed); | ||||
| 	} | ||||
| 	console->addText(formattedText); | ||||
| } | ||||
|  | ||||
| void CBattleInterface::endAction(const BattleAction* action) | ||||
| { | ||||
| 	const CStack *stack = curInt->cb->battleGetStackByID(action->stackNumber); | ||||
| @@ -2571,7 +2534,16 @@ bool CBattleInterface::isCastingPossibleHere(const CStack *sactive, const CStack | ||||
| 		else | ||||
| 		{ | ||||
| 			const spells::Mode mode = creatureCasting ? spells::Mode::CREATURE_ACTIVE : spells::Mode::HERO; | ||||
| 			isCastingPossible = sp->canBeCastAt(curInt->cb.get(), mode, caster, myNumber); | ||||
|  | ||||
| 			spells::Target target; | ||||
| 			target.emplace_back(myNumber); | ||||
|  | ||||
| 			spells::BattleCast cast(curInt->cb.get(), caster, mode, sp); | ||||
|  | ||||
| 			auto m = sp->battleMechanics(&cast); | ||||
| 			spells::detail::ProblemImpl problem; //todo: display problem in status bar | ||||
|  | ||||
| 			isCastingPossible = m->canBeCastAt(problem, target); | ||||
| 		} | ||||
| 	} | ||||
| 	else | ||||
| @@ -3050,7 +3022,7 @@ void CBattleInterface::show(SDL_Surface *to) | ||||
| 	showProjectiles(to); | ||||
|  | ||||
| 	if(battleActionsStarted) | ||||
| 		updateBattleAnimations(); | ||||
| 	updateBattleAnimations(); | ||||
|  | ||||
| 	SDL_SetClipRect(to, &buf); //restoring previous clip_rect | ||||
|  | ||||
| @@ -3064,7 +3036,7 @@ void CBattleInterface::show(SDL_Surface *to) | ||||
| 		//we may have changed active interface (another side in hot-seat), | ||||
| 		// so we can't continue drawing with old setting. | ||||
| 		show(to); | ||||
| 	}		 | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void CBattleInterface::showBackground(SDL_Surface *to) | ||||
| @@ -3172,7 +3144,9 @@ void CBattleInterface::showHighlightedHexes(SDL_Surface *to) | ||||
| 				if(caster && spell) //when casting spell | ||||
| 				{ | ||||
| 					// printing shaded hex(es) | ||||
| 					auto shaded = spell->rangeInHexes(curInt->cb.get(), mode, caster, currentlyHoveredHex); | ||||
| 					spells::BattleCast event(curInt->cb.get(), caster, mode, spell); | ||||
| 					auto shaded = spell->battleMechanics(&event)->rangeInHexes(currentlyHoveredHex); | ||||
|  | ||||
| 					for(BattleHex shadedHex : shaded) | ||||
| 					{ | ||||
| 						if((shadedHex.getX() != 0) && (shadedHex.getX() != GameConstants::BFIELD_WIDTH - 1)) | ||||
| @@ -3691,7 +3665,17 @@ void CBattleInterface::redrawBackgroundWithHexes(const CStack *activeStack) | ||||
| 	attackableHexes.clear(); | ||||
| 	if (activeStack) | ||||
| 		occupyableHexes = curInt->cb->battleGetAvailableHexes(activeStack, true, &attackableHexes); | ||||
| 	curInt->cb->battleGetStackCountOutsideHexes(stackCountOutsideHexes); | ||||
|  | ||||
| 	auto fillStackCountOutsideHexes = [&]() | ||||
| 	{ | ||||
| 		auto accessibility = curInt->cb->getAccesibility(); | ||||
|  | ||||
| 		for(int i = 0; i < accessibility.size(); i++) | ||||
| 			stackCountOutsideHexes.at(i) = (accessibility[i] == EAccessibility::ACCESSIBLE); | ||||
| 	}; | ||||
|  | ||||
| 	fillStackCountOutsideHexes(); | ||||
|  | ||||
| 	//prepare background graphic with hexes and shaded hexes | ||||
| 	blitAt(background, 0, 0, backgroundWithHexes); | ||||
|  | ||||
|   | ||||
| @@ -9,7 +9,9 @@ | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
| #include "../../lib/ConstTransitivePtr.h" //may be reundant | ||||
| #include <vcmi/spells/Magic.h> | ||||
|  | ||||
| #include "../../lib/ConstTransitivePtr.h" //may be redundant | ||||
| #include "../../lib/GameConstants.h" | ||||
|  | ||||
| #include "CBattleAnimations.h" | ||||
| @@ -50,6 +52,7 @@ class CBattleGameInterface; | ||||
| struct CustomEffectInfo; | ||||
| class CAnimation; | ||||
| class IImage; | ||||
| class CSpell; | ||||
|  | ||||
| /// Small struct which contains information about the id of the attacked stack, the damage dealt,... | ||||
| struct StackAttackedInfo | ||||
| @@ -153,7 +156,7 @@ private: | ||||
| 	void activateStack(); //sets activeStack to stackToActivate etc. //FIXME: No, it's not clear at all | ||||
| 	std::vector<BattleHex> occupyableHexes, //hexes available for active stack | ||||
| 		attackableHexes; //hexes attackable by active stack | ||||
| 	bool stackCountOutsideHexes[GameConstants::BFIELD_SIZE]; // hexes that when in front of a unit cause it's amount box to move back | ||||
| 	std::array<bool, GameConstants::BFIELD_SIZE> stackCountOutsideHexes; // hexes that when in front of a unit cause it's amount box to move back | ||||
| 	BattleHex previouslyHoveredHex; //number of hex that was hovered by the cursor a while ago | ||||
| 	BattleHex currentlyHoveredHex; //number of hex that is supposed to be hovered (for a while it may be inappropriately set, but will be renewed soon) | ||||
| 	int attackingHex; //hex from which the stack would perform attack with current cursor | ||||
| @@ -187,8 +190,6 @@ private: | ||||
| 	//force active stack to cast a spell if possible | ||||
| 	void enterCreatureCastingMode(); | ||||
|  | ||||
| 	void printConsoleAttacked(const CStack *defender, int dmg, int killed, const CStack *attacker, bool Multiple); | ||||
|  | ||||
| 	std::list<ProjectileInfo> projectiles; //projectiles flying on battlefield | ||||
| 	void giveCommand(EActionType action, BattleHex tile = BattleHex(), si32 additional = -1); | ||||
| 	void sendCommand(BattleAction *& command, const CStack * actor = nullptr); | ||||
| @@ -340,7 +341,7 @@ public: | ||||
| 	void stackActivated(const CStack *stack); //active stack has been changed | ||||
| 	void stackMoved(const CStack *stack, std::vector<BattleHex> destHex, int distance); //stack with id number moved to destHex | ||||
| 	void waitForAnims(); | ||||
| 	void stacksAreAttacked(std::vector<StackAttackedInfo> attackedInfos, const std::vector<MetaString> & battleLog); //called when a certain amount of stacks has been attacked | ||||
| 	void stacksAreAttacked(std::vector<StackAttackedInfo> attackedInfos); //called when a certain amount of stacks has been attacked | ||||
| 	void stackAttacking(const CStack *attacker, BattleHex dest, const CStack *attacked, bool shooting); //called when stack with id ID is attacking something on hex dest | ||||
| 	void newRoundFirst( int round ); | ||||
| 	void newRound(int number); //caled when round is ended; number is the number of round | ||||
| @@ -361,8 +362,6 @@ public: | ||||
| 	void displaySpellEffect(SpellID spellID, BattleHex destinationTile); //displays spell`s affected animation | ||||
| 	void displaySpellHit(SpellID spellID, BattleHex destinationTile); //displays spell`s affected animation | ||||
|  | ||||
| 	void displaySpellAnimation(const CSpell::TAnimation & animation, BattleHex destinationTile); | ||||
|  | ||||
| 	void battleTriggerEffect(const BattleTriggerEffect & bte); | ||||
| 	void setBattleCursor(const int myNumber); //really complex and messy, sets attackingHex | ||||
| 	void endAction(const BattleAction* action); | ||||
|   | ||||
| @@ -448,8 +448,8 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult & br, CPlayerInterfa | ||||
|  | ||||
| 			if(best != stacks.end()) //should be always but to be safe... | ||||
| 			{ | ||||
| 				icons.push_back(std::make_shared<CAnimImage>("TWCRPORT", (*best)->type->idNumber+2, 0, xs[i], 38)); | ||||
| 				sideNames[i] = CGI->creh->creatures[(*best)->type->idNumber]->namePl; | ||||
| 				icons.push_back(std::make_shared<CAnimImage>("TWCRPORT", (*best)->type->getIconIndex(), 0, xs[i], 38)); | ||||
| 				sideNames[i] = (*best)->type->getPluralName(); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| @@ -471,7 +471,7 @@ CBattleResultWindow::CBattleResultWindow(const BattleResult & br, CPlayerInterfa | ||||
| 			int yPos = 344 + step * 97; | ||||
| 			for(auto & elem : br.casualties[step]) | ||||
| 			{ | ||||
| 				icons.push_back(std::make_shared<CAnimImage>("CPRSMALL", CGI->creh->creatures[elem.first]->iconIndex, 0, xPos, yPos)); | ||||
| 				icons.push_back(std::make_shared<CAnimImage>("CPRSMALL", CGI->creatures()->getByIndex(elem.first)->getIconIndex(), 0, xPos, yPos)); | ||||
| 				std::ostringstream amount; | ||||
| 				amount<<elem.second; | ||||
| 				labels.push_back(std::make_shared<CLabel>(xPos + 16, yPos + 42, FONT_SMALL, CENTER, Colors::WHITE, amount.str())); | ||||
|   | ||||
| @@ -23,7 +23,7 @@ | ||||
| #include "../CPlayerInterface.h" | ||||
| #include "../battle/CBattleInterface.h" | ||||
|  | ||||
| extern std::queue<SDL_Event> events; | ||||
| extern std::queue<SDL_Event> SDLEventsQueue; | ||||
| extern boost::mutex eventsM; | ||||
|  | ||||
| boost::thread_specific_ptr<bool> inGuiThread; | ||||
| @@ -188,18 +188,18 @@ void CGuiHandler::handleEvents() | ||||
| 		return; | ||||
|  | ||||
| 	boost::unique_lock<boost::mutex> lock(eventsM); | ||||
| 	while(!events.empty()) | ||||
| 	while(!SDLEventsQueue.empty()) | ||||
| 	{ | ||||
| 		continueEventHandling = true; | ||||
| 		SDL_Event ev = events.front(); | ||||
| 		SDL_Event ev = SDLEventsQueue.front(); | ||||
| 		current = &ev; | ||||
| 		events.pop(); | ||||
| 		SDLEventsQueue.pop(); | ||||
|  | ||||
| 		// In a sequence of mouse motion events, skip all but the last one. | ||||
| 		// This prevents freezes when every motion event takes longer to handle than interval at which | ||||
| 		// the events arrive (like dragging on the minimap in world view, with redraw at every event) | ||||
| 		// so that the events would start piling up faster than they can be processed. | ||||
| 		if ((ev.type == SDL_MOUSEMOTION) && !events.empty() && (events.front().type == SDL_MOUSEMOTION)) | ||||
| 		if ((ev.type == SDL_MOUSEMOTION) && !SDLEventsQueue.empty() && (SDLEventsQueue.front().type == SDL_MOUSEMOTION)) | ||||
| 			continue; | ||||
|  | ||||
| 		handleCurrentEvent(); | ||||
|   | ||||
| @@ -10,6 +10,10 @@ | ||||
| #include "StdInc.h" | ||||
|  | ||||
| #include "CBonusSelection.h" | ||||
|  | ||||
| #include <vcmi/spells/Spell.h> | ||||
| #include <vcmi/spells/Service.h> | ||||
|  | ||||
| #include "CSelectionBase.h" | ||||
|  | ||||
| #include "../CGameInfo.h" | ||||
| @@ -34,9 +38,7 @@ | ||||
| #include "../../lib/filesystem/Filesystem.h" | ||||
| #include "../../lib/CGeneralTextHandler.h" | ||||
|  | ||||
| #include "../../lib/CArtHandler.h" | ||||
| #include "../../lib/CBuildingHandler.h" | ||||
| #include "../../lib/spells/CSpellHandler.h" | ||||
|  | ||||
| #include "../../lib/CSkillHandler.h" | ||||
| #include "../../lib/CTownHandler.h" | ||||
| @@ -176,13 +178,13 @@ void CBonusSelection::createBonusesIcons() | ||||
| 		{ | ||||
| 		case CScenarioTravel::STravelBonus::SPELL: | ||||
| 			desc = CGI->generaltexth->allTexts[715]; | ||||
| 			boost::algorithm::replace_first(desc, "%s", CGI->spellh->objects[bonDescs[i].info2]->name); | ||||
| 			boost::algorithm::replace_first(desc, "%s", CGI->spells()->getByIndex(bonDescs[i].info2)->getName()); | ||||
| 			break; | ||||
| 		case CScenarioTravel::STravelBonus::MONSTER: | ||||
| 			picNumber = bonDescs[i].info2 + 2; | ||||
| 			desc = CGI->generaltexth->allTexts[717]; | ||||
| 			boost::algorithm::replace_first(desc, "%d", boost::lexical_cast<std::string>(bonDescs[i].info3)); | ||||
| 			boost::algorithm::replace_first(desc, "%s", CGI->creh->creatures[bonDescs[i].info2]->namePl); | ||||
| 			boost::algorithm::replace_first(desc, "%s", CGI->creatures()->getByIndex(bonDescs[i].info2)->getPluralName()); | ||||
| 			break; | ||||
| 		case CScenarioTravel::STravelBonus::BUILDING: | ||||
| 		{ | ||||
| @@ -202,18 +204,18 @@ void CBonusSelection::createBonusesIcons() | ||||
| 			picName = graphics->ERMUtoPicture[faction][buildID]; | ||||
| 			picNumber = -1; | ||||
|  | ||||
| 			if(vstd::contains(CGI->townh->factions[faction]->town->buildings, buildID)) | ||||
| 				desc = CGI->townh->factions[faction]->town->buildings.find(buildID)->second->Name(); | ||||
| 			if(vstd::contains((*CGI->townh)[faction]->town->buildings, buildID)) | ||||
| 				desc = (*CGI->townh)[faction]->town->buildings.find(buildID)->second->Name(); | ||||
|  | ||||
| 			break; | ||||
| 		} | ||||
| 		case CScenarioTravel::STravelBonus::ARTIFACT: | ||||
| 			desc = CGI->generaltexth->allTexts[715]; | ||||
| 			boost::algorithm::replace_first(desc, "%s", CGI->arth->artifacts[bonDescs[i].info2]->Name()); | ||||
| 			boost::algorithm::replace_first(desc, "%s", CGI->artifacts()->getByIndex(bonDescs[i].info2)->getName()); | ||||
| 			break; | ||||
| 		case CScenarioTravel::STravelBonus::SPELL_SCROLL: | ||||
| 			desc = CGI->generaltexth->allTexts[716]; | ||||
| 			boost::algorithm::replace_first(desc, "%s", CGI->spellh->objects[bonDescs[i].info2]->name); | ||||
| 			boost::algorithm::replace_first(desc, "%s", CGI->spells()->getByIndex(bonDescs[i].info2)->getName()); | ||||
| 			break; | ||||
| 		case CScenarioTravel::STravelBonus::PRIMARY_SKILL: | ||||
| 		{ | ||||
| @@ -318,7 +320,7 @@ void CBonusSelection::createBonusesIcons() | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				boost::algorithm::replace_first(desc, "%s", CGI->heroh->heroes[bonDescs[i].info2]->name); | ||||
| 				boost::algorithm::replace_first(desc, "%s", CGI->heroh->objects[bonDescs[i].info2]->name); | ||||
| 			} | ||||
| 			break; | ||||
| 		} | ||||
|   | ||||
| @@ -83,7 +83,7 @@ size_t OptionsTab::CPlayerSettingsHelper::getImageIndex() | ||||
| 		TOWN_RANDOM = 38,  TOWN_NONE = 39, // Special frames in ITPA | ||||
| 		HERO_RANDOM = 163, HERO_NONE = 164 // Special frames in PortraitsSmall | ||||
| 	}; | ||||
| 	auto factionIndex = settings.castle >= CGI->townh->factions.size() ? 0 : settings.castle; | ||||
| 	auto factionIndex = settings.castle >= CGI->townh->size() ? 0 : settings.castle; | ||||
|  | ||||
| 	switch(type) | ||||
| 	{ | ||||
| @@ -95,7 +95,7 @@ size_t OptionsTab::CPlayerSettingsHelper::getImageIndex() | ||||
| 		case PlayerSettings::RANDOM: | ||||
| 			return TOWN_RANDOM; | ||||
| 		default: | ||||
| 			return CGI->townh->factions[factionIndex]->town->clientInfo.icons[true][false] + 2; | ||||
| 			return (*CGI->townh)[factionIndex]->town->clientInfo.icons[true][false] + 2; | ||||
| 		} | ||||
| 	case HERO: | ||||
| 		switch(settings.hero) | ||||
| @@ -108,11 +108,10 @@ size_t OptionsTab::CPlayerSettingsHelper::getImageIndex() | ||||
| 		{ | ||||
| 			if(settings.heroPortrait >= 0) | ||||
| 				return settings.heroPortrait; | ||||
| 			auto index = settings.hero >= CGI->heroh->heroes.size() ? 0 : settings.hero; | ||||
| 			return CGI->heroh->heroes[index]->imageIndex; | ||||
| 			auto index = settings.hero >= CGI->heroh->size() ? 0 : settings.hero; | ||||
| 			return (*CGI->heroh)[index]->imageIndex; | ||||
| 		} | ||||
| 		} | ||||
|  | ||||
| 	case BONUS: | ||||
| 	{ | ||||
| 		switch(settings.bonus) | ||||
| @@ -125,7 +124,7 @@ size_t OptionsTab::CPlayerSettingsHelper::getImageIndex() | ||||
| 			return GOLD; | ||||
| 		case PlayerSettings::RESOURCE: | ||||
| 		{ | ||||
| 			switch(CGI->townh->factions[factionIndex]->town->primaryRes) | ||||
| 			switch((*CGI->townh)[factionIndex]->town->primaryRes) | ||||
| 			{ | ||||
| 			case Res::WOOD_AND_ORE: | ||||
| 				return WOOD_ORE; | ||||
| @@ -181,11 +180,11 @@ std::string OptionsTab::CPlayerSettingsHelper::getName() | ||||
| 			return CGI->generaltexth->allTexts[522]; | ||||
| 		default: | ||||
| 		{ | ||||
| 			auto factionIndex = settings.castle >= CGI->townh->factions.size() ? 0 : settings.castle; | ||||
| 			return CGI->townh->factions[factionIndex]->name; | ||||
| 		} | ||||
| 			auto factionIndex = settings.castle >= CGI->townh->size() ? 0 : settings.castle; | ||||
| 			return (*CGI->townh)[factionIndex]->name; | ||||
| 		} | ||||
| 	} | ||||
| 	} | ||||
| 	case HERO: | ||||
| 	{ | ||||
| 		switch(settings.hero) | ||||
| @@ -198,8 +197,8 @@ std::string OptionsTab::CPlayerSettingsHelper::getName() | ||||
| 		{ | ||||
| 			if(!settings.heroName.empty()) | ||||
| 				return settings.heroName; | ||||
| 			auto index = settings.hero >= CGI->heroh->heroes.size() ? 0 : settings.hero; | ||||
| 			return CGI->heroh->heroes[index]->name; | ||||
| 			auto index = settings.hero >= CGI->heroh->size() ? 0 : settings.hero; | ||||
| 			return (*CGI->heroh)[index]->name; | ||||
| 		} | ||||
| 		} | ||||
| 	} | ||||
| @@ -245,8 +244,8 @@ std::string OptionsTab::CPlayerSettingsHelper::getTitle() | ||||
| } | ||||
| std::string OptionsTab::CPlayerSettingsHelper::getSubtitle() | ||||
| { | ||||
| 	auto factionIndex = settings.castle >= CGI->townh->factions.size() ? 0 : settings.castle; | ||||
| 	auto heroIndex = settings.hero >= CGI->heroh->heroes.size() ? 0 : settings.hero; | ||||
| 	auto factionIndex = settings.castle >= CGI->townh->size() ? 0 : settings.castle; | ||||
| 	auto heroIndex = settings.hero >= CGI->heroh->size() ? 0 : settings.hero; | ||||
|  | ||||
| 	switch(type) | ||||
| 	{ | ||||
| @@ -255,7 +254,7 @@ std::string OptionsTab::CPlayerSettingsHelper::getSubtitle() | ||||
| 	case HERO: | ||||
| 	{ | ||||
| 		if(settings.hero >= 0) | ||||
| 			return getName() + " - " + CGI->heroh->heroes[heroIndex]->heroClass->name; | ||||
| 			return getName() + " - " + (*CGI->heroh)[heroIndex]->heroClass->name; | ||||
| 		return getName(); | ||||
| 	} | ||||
|  | ||||
| @@ -267,7 +266,7 @@ std::string OptionsTab::CPlayerSettingsHelper::getSubtitle() | ||||
| 			return CGI->generaltexth->allTexts[87]; //500-1000 | ||||
| 		case PlayerSettings::RESOURCE: | ||||
| 		{ | ||||
| 			switch(CGI->townh->factions[factionIndex]->town->primaryRes) | ||||
| 			switch((*CGI->townh)[factionIndex]->town->primaryRes) | ||||
| 			{ | ||||
| 			case Res::MERCURY: | ||||
| 				return CGI->generaltexth->allTexts[694]; | ||||
| @@ -289,7 +288,7 @@ std::string OptionsTab::CPlayerSettingsHelper::getSubtitle() | ||||
|  | ||||
| std::string OptionsTab::CPlayerSettingsHelper::getDescription() | ||||
| { | ||||
| 	auto factionIndex = settings.castle >= CGI->townh->factions.size() ? 0 : settings.castle; | ||||
| 	auto factionIndex = settings.castle >= CGI->townh->size() ? 0 : settings.castle; | ||||
|  | ||||
| 	switch(type) | ||||
| 	{ | ||||
| @@ -309,7 +308,7 @@ std::string OptionsTab::CPlayerSettingsHelper::getDescription() | ||||
| 			return CGI->generaltexth->allTexts[92]; //At the start of the game, 500-1000 gold is added to your Kingdom's resource pool | ||||
| 		case PlayerSettings::RESOURCE: | ||||
| 		{ | ||||
| 			switch(CGI->townh->factions[factionIndex]->town->primaryRes) | ||||
| 			switch((*CGI->townh)[factionIndex]->town->primaryRes) | ||||
| 			{ | ||||
| 			case Res::MERCURY: | ||||
| 				return CGI->generaltexth->allTexts[690]; | ||||
| @@ -376,9 +375,9 @@ void OptionsTab::CPlayerOptionTooltipBox::genTownWindow() | ||||
| 	pos = Rect(0, 0, 228, 290); | ||||
| 	genHeader(); | ||||
| 	labelAssociatedCreatures = std::make_shared<CLabel>(pos.w / 2 + 8, 122, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[79]); | ||||
| 	auto factionIndex = settings.castle >= CGI->townh->factions.size() ? 0 : settings.castle; | ||||
| 	auto factionIndex = settings.castle >= CGI->townh->size() ? 0 : settings.castle; | ||||
| 	std::vector<std::shared_ptr<CComponent>> components; | ||||
| 	const CTown * town = CGI->townh->factions[factionIndex]->town; | ||||
| 	const CTown * town = (*CGI->townh)[factionIndex]->town; | ||||
|  | ||||
| 	for(auto & elem : town->creatures) | ||||
| 	{ | ||||
| @@ -393,10 +392,10 @@ void OptionsTab::CPlayerOptionTooltipBox::genHeroWindow() | ||||
| 	pos = Rect(0, 0, 292, 226); | ||||
| 	genHeader(); | ||||
| 	labelHeroSpeciality = std::make_shared<CLabel>(pos.w / 2 + 4, 117, FONT_MEDIUM, CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[78]); | ||||
| 	auto heroIndex = settings.hero >= CGI->heroh->heroes.size() ? 0 : settings.hero; | ||||
| 	auto heroIndex = settings.hero >= CGI->heroh->size() ? 0 : settings.hero; | ||||
|  | ||||
| 	imageSpeciality = std::make_shared<CAnimImage>("UN44", CGI->heroh->heroes[heroIndex]->imageIndex, 0, pos.w / 2 - 22, 134); | ||||
| 	labelSpecialityName = std::make_shared<CLabel>(pos.w / 2, 188, FONT_SMALL, CENTER, Colors::WHITE, CGI->heroh->heroes[heroIndex]->specName); | ||||
| 	imageSpeciality = std::make_shared<CAnimImage>("UN44", (*CGI->heroh)[heroIndex]->imageIndex, 0, pos.w / 2 - 22, 134); | ||||
| 	labelSpecialityName = std::make_shared<CLabel>(pos.w / 2, 188, FONT_SMALL, CENTER, Colors::WHITE, (*CGI->heroh)[heroIndex]->specName); | ||||
| } | ||||
|  | ||||
| void OptionsTab::CPlayerOptionTooltipBox::genBonusWindow() | ||||
|   | ||||
| @@ -25,7 +25,6 @@ | ||||
| #include "../../CCallback.h" | ||||
|  | ||||
| #include "../../lib/CArtHandler.h" | ||||
| #include "../../lib/spells/CSpellHandler.h" | ||||
| #include "../../lib/CGeneralTextHandler.h" | ||||
|  | ||||
| #include "../../lib/mapObjects/CGHeroInstance.h" | ||||
| @@ -45,10 +44,11 @@ void CHeroArtPlace::createImage() | ||||
| 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); | ||||
|  | ||||
| 	si32 imageIndex = 0; | ||||
| 	if(ourArt) | ||||
| 		imageIndex = ourArt->artType->iconIndex; | ||||
|  | ||||
| 	if(locked) | ||||
| 		imageIndex = ArtifactID::ART_LOCK; | ||||
| 	else if(ourArt) | ||||
| 		imageIndex = ourArt->artType->getIconIndex(); | ||||
|  | ||||
| 	image = std::make_shared<CAnimImage>("artifact", imageIndex); | ||||
| 	if(!ourArt) | ||||
| @@ -68,7 +68,7 @@ void CHeroArtPlace::lockSlot(bool on) | ||||
| 	if (on) | ||||
| 		image->setFrame(ArtifactID::ART_LOCK); | ||||
| 	else if (ourArt) | ||||
| 		image->setFrame(ourArt->artType->iconIndex); | ||||
| 		image->setFrame(ourArt->artType->getIconIndex()); | ||||
| 	else | ||||
| 		image->setFrame(0); | ||||
| } | ||||
| @@ -172,7 +172,7 @@ void CHeroArtPlace::clickLeft(tribool down, bool previousState) | ||||
| 					else if(cur->isBig()) | ||||
| 					{ | ||||
| 						//war machines cannot go to backpack | ||||
| 						LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[153]) % cur->Name())); | ||||
| 						LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[153]) % cur->getName())); | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| @@ -197,18 +197,6 @@ void CHeroArtPlace::clickLeft(tribool down, bool previousState) | ||||
| 				(!ourArt || ourOwner->curHero->tempOwner == LOCPLINT->playerID)) | ||||
| 			{ | ||||
| 				setMeAsDest(); | ||||
| // | ||||
| // 				// Special case when the dest artifact can't be fit into the src slot. | ||||
| // 				//CGI->arth->unequipArtifact(ourOwner->curHero->artifWorn, slotID); | ||||
| // 				const CArtifactsOfHero* srcAOH = ourOwner->commonInfo->src.AOH; | ||||
| // 				ui16 srcSlotID = ourOwner->commonInfo->src.slotID; | ||||
| // 				if (ourArt && srcSlotID < 19 && !ourArt->canBePutAt(ArtifactLocation(srcAOH->curHero, srcSlotID))) | ||||
| // 				{ | ||||
| // 					// Put dest artifact into owner's backpack. | ||||
| // 					ourOwner->commonInfo->src.AOH = ourOwner; | ||||
| // 					ourOwner->commonInfo->src.slotID = ourOwner->curHero->artifacts.size() + 19; | ||||
| // 				} | ||||
|  | ||||
| 				ourOwner->realizeCurrentTransaction(); | ||||
| 			} | ||||
| 		} | ||||
| @@ -226,14 +214,12 @@ bool CHeroArtPlace::askToAssemble(const CArtifactInstance *art, ArtifactPosition | ||||
| 	for(const CArtifact *combination : assemblyPossibilities) | ||||
| 	{ | ||||
| 		LOCPLINT->showArtifactAssemblyDialog( | ||||
| 			art->artType->id, | ||||
| 			combination->id, | ||||
| 			true, | ||||
| 			std::bind(&CCallback::assembleArtifacts, LOCPLINT->cb.get(), hero, slot, true, combination->id), | ||||
| 			0); | ||||
| 			art->artType, | ||||
| 			combination, | ||||
| 			std::bind(&CCallback::assembleArtifacts, LOCPLINT->cb.get(), hero, slot, true, combination->id)); | ||||
|  | ||||
| 		if(assemblyPossibilities.size() > 2) | ||||
| 			logGlobal->warn("More than one possibility of assembling on %s... taking only first", art->artType->Name()); | ||||
| 			logGlobal->warn("More than one possibility of assembling on %s... taking only first", art->artType->getName()); | ||||
| 		return true; | ||||
| 	} | ||||
| 	return false; | ||||
| @@ -243,14 +229,14 @@ void CHeroArtPlace::clickRight(tribool down, bool previousState) | ||||
| { | ||||
| 	if(ourArt && down && !locked && text.size() && !picked)  //if there is no description or it's a lock, do nothing ;] | ||||
| 	{ | ||||
| 		if (slotID < GameConstants::BACKPACK_START) | ||||
| 		if(slotID < GameConstants::BACKPACK_START) | ||||
| 		{ | ||||
| 			if(ourOwner->allowedAssembling) | ||||
| 			{ | ||||
| 				std::vector<const CArtifact *> assemblyPossibilities = ourArt->assemblyPossibilities(ourOwner->curHero); | ||||
|  | ||||
| 				// If the artifact can be assembled, display dialog. | ||||
| 				if (askToAssemble(ourArt, slotID, ourOwner->curHero)) | ||||
| 				if(askToAssemble(ourArt, slotID, ourOwner->curHero)) | ||||
| 				{ | ||||
| 					return; | ||||
| 				} | ||||
| @@ -259,11 +245,9 @@ void CHeroArtPlace::clickRight(tribool down, bool previousState) | ||||
| 				if(ourArt->canBeDisassembled()) | ||||
| 				{ | ||||
| 					LOCPLINT->showArtifactAssemblyDialog( | ||||
| 						ourArt->artType->id, | ||||
| 						0, | ||||
| 						false, | ||||
| 						std::bind(&CCallback::assembleArtifacts, LOCPLINT->cb.get(), ourOwner->curHero, slotID, false, ArtifactID()), | ||||
| 						0); | ||||
| 						ourArt->artType, | ||||
| 						nullptr, | ||||
| 						std::bind(&CCallback::assembleArtifacts, LOCPLINT->cb.get(), ourOwner->curHero, slotID, false, ArtifactID())); | ||||
| 					return; | ||||
| 				} | ||||
| 			} | ||||
| @@ -294,7 +278,7 @@ void CHeroArtPlace::select () | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	CCS->curh->dragAndDropCursor(make_unique<CAnimImage>("artifact", ourArt->artType->iconIndex)); | ||||
| 	CCS->curh->dragAndDropCursor(make_unique<CAnimImage>("artifact", ourArt->artType->getIconIndex())); | ||||
| 	ourOwner->commonInfo->src.setTo(this, false); | ||||
| 	ourOwner->markPossibleSlots(ourArt); | ||||
|  | ||||
| @@ -389,7 +373,7 @@ void CHeroArtPlace::setArtifact(const CArtifactInstance *art) | ||||
| 	} | ||||
|  | ||||
| 	image->enable(); | ||||
| 	image->setFrame(locked ? ArtifactID::ART_LOCK : art->artType->iconIndex); | ||||
| 	image->setFrame(locked ? ArtifactID::ART_LOCK : art->artType->getIconIndex()); | ||||
|  | ||||
| 	text = art->getEffectiveDescription(ourOwner->curHero); | ||||
|  | ||||
| @@ -414,7 +398,7 @@ void CHeroArtPlace::setArtifact(const CArtifactInstance *art) | ||||
| 	if (locked) // Locks should appear as empty. | ||||
| 		hoverText = CGI->generaltexth->allTexts[507]; | ||||
| 	else | ||||
| 		hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1]) % ourArt->artType->Name()); | ||||
| 		hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1]) % ourArt->artType->getName()); | ||||
| } | ||||
|  | ||||
| void CArtifactsOfHero::SCommonPart::reset() | ||||
| @@ -769,7 +753,7 @@ void CArtifactsOfHero::artifactMoved(const ArtifactLocation &src, const Artifact | ||||
| 			commonInfo->src.art = dst.getArt(); | ||||
| 			commonInfo->src.slotID = dst.slot; | ||||
| 			assert(commonInfo->src.AOH); | ||||
| 			CCS->curh->dragAndDropCursor(make_unique<CAnimImage>("artifact", dst.getArt()->artType->iconIndex)); | ||||
| 			CCS->curh->dragAndDropCursor(make_unique<CAnimImage>("artifact", dst.getArt()->artType->getIconIndex())); | ||||
| 			markPossibleSlots(dst.getArt()); | ||||
| 		} | ||||
| 	} | ||||
| @@ -1020,7 +1004,7 @@ void CCommanderArtPlace::createImage() | ||||
|  | ||||
| 	int imageIndex = 0; | ||||
| 	if(ourArt) | ||||
| 		imageIndex = ourArt->artType->iconIndex; | ||||
| 		imageIndex = ourArt->artType->getIconIndex(); | ||||
|  | ||||
| 	image = std::make_shared<CAnimImage>("artifact", imageIndex); | ||||
| 	if(!ourArt) | ||||
| @@ -1055,7 +1039,7 @@ void CCommanderArtPlace::setArtifact(const CArtifactInstance * art) | ||||
| 	} | ||||
|  | ||||
| 	image->enable(); | ||||
| 	image->setFrame(art->artType->iconIndex); | ||||
| 	image->setFrame(art->artType->getIconIndex()); | ||||
|  | ||||
| 	text = art->getEffectiveDescription(); | ||||
|  | ||||
|   | ||||
| @@ -112,7 +112,7 @@ const std::vector<std::string> CComponent::getFileName() | ||||
| 	case spell:      return gen(spellsArr); | ||||
| 	case morale:     return gen(moraleArr); | ||||
| 	case luck:       return gen(luckArr); | ||||
| 	case building:   return std::vector<std::string>(4, CGI->townh->factions[subtype]->town->clientInfo.buildingsIcons); | ||||
| 	case building:   return std::vector<std::string>(4, (*CGI->townh)[subtype]->town->clientInfo.buildingsIcons); | ||||
| 	case hero:       return gen(heroArr); | ||||
| 	case flag:       return gen(flagArr); | ||||
| 	} | ||||
| @@ -127,8 +127,8 @@ size_t CComponent::getIndex() | ||||
| 	case primskill:  return subtype; | ||||
| 	case secskill:   return subtype*3 + 3 + val - 1; | ||||
| 	case resource:   return subtype; | ||||
| 	case creature:   return CGI->creh->creatures[subtype]->iconIndex; | ||||
| 	case artifact:   return CGI->arth->artifacts[subtype]->iconIndex; | ||||
| 	case creature:   return CGI->creatures()->getByIndex(subtype)->getIconIndex(); | ||||
| 	case artifact:   return CGI->artifacts()->getByIndex(subtype)->getIconIndex(); | ||||
| 	case experience: return 4; | ||||
| 	case spell:      return subtype; | ||||
| 	case morale:     return val+3; | ||||
| @@ -159,15 +159,15 @@ std::string CComponent::getDescription() | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			art.reset(CArtifactInstance::createScroll(static_cast<SpellID>(val))); | ||||
| 			art.reset(CArtifactInstance::createScroll(SpellID(val))); | ||||
| 		} | ||||
| 		return art->getEffectiveDescription(); | ||||
| 	} | ||||
| 	case experience: return CGI->generaltexth->allTexts[241]; | ||||
| 	case spell:      return CGI->spellh->objects[subtype]->getLevelInfo(val).description; | ||||
| 	case spell:      return CGI->spellh->objects[subtype]->getLevelDescription(val); | ||||
| 	case morale:     return CGI->generaltexth->heroscrn[ 4 - (val>0) + (val<0)]; | ||||
| 	case luck:       return CGI->generaltexth->heroscrn[ 7 - (val>0) + (val<0)]; | ||||
| 	case building:   return CGI->townh->factions[subtype]->town->buildings[BuildingID(val)]->Description(); | ||||
| 	case building:   return (*CGI->townh)[subtype]->town->buildings[BuildingID(val)]->Description(); | ||||
| 	case hero:       return ""; | ||||
| 	case flag:       return ""; | ||||
| 	} | ||||
| @@ -193,8 +193,8 @@ std::string CComponent::getSubtitleInternal() | ||||
| 	case primskill:  return boost::str(boost::format("%+d %s") % val % (subtype < 4 ? CGI->generaltexth->primarySkillNames[subtype] : CGI->generaltexth->allTexts[387])); | ||||
| 	case secskill:   return CGI->generaltexth->levels[val-1] + "\n" + CGI->skillh->skillName(subtype); | ||||
| 	case resource:   return boost::lexical_cast<std::string>(val); | ||||
| 	case creature:   return (val? boost::lexical_cast<std::string>(val) + " " : "") + CGI->creh->creatures[subtype]->*(val != 1 ? &CCreature::namePl : &CCreature::nameSing); | ||||
| 	case artifact:   return CGI->arth->artifacts[subtype]->Name(); | ||||
| 	case creature:   return (val? boost::lexical_cast<std::string>(val) + " " : "") + CGI->creh->objects[subtype]->*(val != 1 ? &CCreature::namePl : &CCreature::nameSing); | ||||
| 	case artifact:   return CGI->artifacts()->getByIndex(subtype)->getName(); | ||||
| 	case experience: | ||||
| 		{ | ||||
| 			if(subtype == 1) //+1 level - tree of knowledge | ||||
| @@ -208,15 +208,15 @@ std::string CComponent::getSubtitleInternal() | ||||
| 				return boost::lexical_cast<std::string>(val); //amount of experience OR level required for seer hut; | ||||
| 			} | ||||
| 		} | ||||
| 	case spell:      return CGI->spellh->objects[subtype]->name; | ||||
| 	case spell:      return CGI->spells()->getByIndex(subtype)->getName(); | ||||
| 	case morale:     return ""; | ||||
| 	case luck:       return ""; | ||||
| 	case building: | ||||
| 		{ | ||||
| 			auto building = CGI->townh->factions[subtype]->town->buildings[BuildingID(val)]; | ||||
| 			auto building = (*CGI->townh)[subtype]->town->buildings[BuildingID(val)]; | ||||
| 			if(!building) | ||||
| 			{ | ||||
| 				logGlobal->error("Town of faction %s has no building #%d", CGI->townh->factions[subtype]->town->faction->name, val); | ||||
| 				logGlobal->error("Town of faction %s has no building #%d", (*CGI->townh)[subtype]->town->faction->name, val); | ||||
| 				return (boost::format("Missing building #%d") % val).str(); | ||||
| 			} | ||||
| 			return building->Name(); | ||||
| @@ -224,7 +224,7 @@ std::string CComponent::getSubtitleInternal() | ||||
| 	case hero:       return ""; | ||||
| 	case flag:       return CGI->generaltexth->capColors[subtype]; | ||||
| 	} | ||||
| 	assert(0); | ||||
| 	logGlobal->error("Invalid CComponent type: %d", (int)compType); | ||||
| 	return ""; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -355,7 +355,7 @@ void CGarrisonSlot::update() | ||||
| 	if(creature) | ||||
| 	{ | ||||
| 		creatureImage->enable(); | ||||
| 		creatureImage->setFrame(creature->iconIndex); | ||||
| 		creatureImage->setFrame(creature->getIconIndex()); | ||||
|  | ||||
| 		stackCount->enable(); | ||||
| 		stackCount->setText(boost::lexical_cast<std::string>(myStack->count)); | ||||
| @@ -367,12 +367,12 @@ void CGarrisonSlot::update() | ||||
| 	} | ||||
| } | ||||
|  | ||||
| CGarrisonSlot::CGarrisonSlot(CGarrisonInt * Owner, int x, int y, SlotID IID, CGarrisonSlot::EGarrisonType Upg, const CStackInstance * Creature) | ||||
| 	: ID(IID), | ||||
| 	owner(Owner), | ||||
| 	myStack(Creature), | ||||
| 	creature(nullptr), | ||||
| 	upg(Upg) | ||||
| CGarrisonSlot::CGarrisonSlot(CGarrisonInt * Owner, int x, int y, SlotID IID, CGarrisonSlot::EGarrisonType Upg, const CStackInstance * creature_) | ||||
|     : ID(IID), | ||||
|     owner(Owner), | ||||
|     myStack(creature_), | ||||
|     creature(creature_ ? creature_->type : nullptr), | ||||
|     upg(Upg) | ||||
| { | ||||
| 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); | ||||
|  | ||||
| @@ -382,7 +382,7 @@ CGarrisonSlot::CGarrisonSlot(CGarrisonInt * Owner, int x, int y, SlotID IID, CGa | ||||
| 	std::string imgName = owner->smallIcons ? "cprsmall" : "TWCRPORT"; | ||||
|  | ||||
| 	creatureImage =  std::make_shared<CAnimImage>(imgName, 0); | ||||
| 	creatureImage->disable(); | ||||
| 		creatureImage->disable(); | ||||
|  | ||||
| 	selectionImage = std::make_shared<CAnimImage>(imgName, 1); | ||||
| 	selectionImage->disable(); | ||||
| @@ -496,13 +496,13 @@ CGarrisonInt::CGarrisonInt(int x, int y, int inx, const Point & garsOffset, | ||||
| 		const CArmedInstance * s1, const CArmedInstance * s2, | ||||
| 		bool _removableUnits, bool smallImgs, bool _twoRows) | ||||
| 	: highlighted(nullptr), | ||||
| 	inSplittingMode(false), | ||||
| 	interx(inx), | ||||
| 	garOffset(garsOffset), | ||||
| 	pb(false), | ||||
| 	smallIcons(smallImgs), | ||||
| 	removableUnits(_removableUnits), | ||||
| 	twoRows(_twoRows) | ||||
|     inSplittingMode(false), | ||||
|     interx(inx), | ||||
|     garOffset(garsOffset), | ||||
|     pb(false), | ||||
|     smallIcons(smallImgs), | ||||
|     removableUnits(_removableUnits), | ||||
|     twoRows(_twoRows) | ||||
| { | ||||
| 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); | ||||
|  | ||||
|   | ||||
| @@ -53,7 +53,7 @@ public: | ||||
| 	void clickRight(tribool down, bool previousState) override; | ||||
| 	void clickLeft(tribool down, bool previousState) override; | ||||
| 	void update(); | ||||
| 	CGarrisonSlot(CGarrisonInt *Owner, int x, int y, SlotID IID, EGarrisonType Upg=EGarrisonType::UP, const CStackInstance * Creature=nullptr); | ||||
| 	CGarrisonSlot(CGarrisonInt *Owner, int x, int y, SlotID IID, EGarrisonType Upg=EGarrisonType::UP, const CStackInstance * creature_ = nullptr); | ||||
|  | ||||
| 	void splitIntoParts(EGarrisonType type, int amount, int maxOfSplittedSlots); | ||||
| 	void handleSplittingShortcuts(); | ||||
|   | ||||
| @@ -243,7 +243,7 @@ void CArmyTooltip::init(const InfoAboutArmy &army) | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		icons.push_back(std::make_shared<CAnimImage>("CPRSMALL", slot.second.type->iconIndex, 0, slotsPos[slot.first.getNum()].x, slotsPos[slot.first.getNum()].y)); | ||||
| 		icons.push_back(std::make_shared<CAnimImage>("CPRSMALL", slot.second.type->getIconIndex(), 0, slotsPos[slot.first.getNum()].x, slotsPos[slot.first.getNum()].y)); | ||||
|  | ||||
| 		std::string subtitle; | ||||
| 		if(army.army.isDetailed) | ||||
| @@ -443,12 +443,12 @@ CCreaturePic::CCreaturePic(int x, int y, const CCreature * cre, bool Big, bool A | ||||
|  | ||||
| 	TFaction faction = cre->faction; | ||||
|  | ||||
| 	assert(CGI->townh->factions.size() > faction); | ||||
| 	assert(CGI->townh->size() > faction); | ||||
|  | ||||
| 	if(Big) | ||||
| 		bg = std::make_shared<CPicture>(CGI->townh->factions[faction]->creatureBg130); | ||||
| 		bg = std::make_shared<CPicture>((*CGI->townh)[faction]->creatureBg130); | ||||
| 	else | ||||
| 		bg = std::make_shared<CPicture>(CGI->townh->factions[faction]->creatureBg120); | ||||
| 		bg = std::make_shared<CPicture>((*CGI->townh)[faction]->creatureBg120); | ||||
| 	anim = std::make_shared<CCreatureAnim>(0, 0, cre->animDefName); | ||||
| 	anim->clipRect(cre->isDoubleWide()?170:150, 155, bg->pos.w, bg->pos.h); | ||||
| 	anim->startPreview(cre->hasBonusOfType(Bonus::SIEGE_WEAPON)); | ||||
|   | ||||
| @@ -112,11 +112,11 @@ void CBuildingRect::hover(bool on) | ||||
| void CBuildingRect::clickLeft(tribool down, bool previousState) | ||||
| { | ||||
| 	if( previousState && getBuilding() && area && !down && (parent->selectedBuilding==this)) | ||||
| 		if (!CSDL_Ext::isTransparent(area, GH.current->motion.x - pos.x, GH.current->motion.y - pos.y)) //inside building image | ||||
| 		if (!CSDL_Ext::isTransparent(area, GH.current->motion.x-pos.x, GH.current->motion.y-pos.y) ) //inside building image | ||||
| 		{ | ||||
| 			auto building = getBuilding(); | ||||
| 			parent->buildingClicked(building->bid, building->subId, building->upgrade); | ||||
| 		} | ||||
| } | ||||
| } | ||||
|  | ||||
| void CBuildingRect::clickRight(tribool down, bool previousState) | ||||
| @@ -231,7 +231,7 @@ std::string CBuildingRect::getSubtitle()//hover text for building | ||||
| 		if(availableCreatures.size()) | ||||
| 		{ | ||||
| 			int creaID = availableCreatures.back();//taking last of available creatures | ||||
| 			return CGI->generaltexth->allTexts[16] + " " + CGI->creh->creatures.at(creaID)->namePl; | ||||
| 			return CGI->generaltexth->allTexts[16] + " " + CGI->creh->objects.at(creaID)->namePl; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| @@ -271,7 +271,7 @@ CDwellingInfoBox::CDwellingInfoBox(int centerX, int centerY, const CGTownInstanc | ||||
| 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE); | ||||
| 	background->colorize(Town->tempOwner); | ||||
|  | ||||
| 	const CCreature * creature = CGI->creh->creatures.at(Town->creatures.at(level).second.back()); | ||||
| 	const CCreature * creature = CGI->creh->objects.at(Town->creatures.at(level).second.back()); | ||||
|  | ||||
| 	title = std::make_shared<CLabel>(80, 30, FONT_SMALL, CENTER, Colors::WHITE, creature->namePl); | ||||
| 	animation = std::make_shared<CCreaturePic>(30, 44, creature, true, true); | ||||
| @@ -607,7 +607,7 @@ void CCastleBuildings::recreate() | ||||
| 		const CStructure * toAdd = *boost::max_element(entry.second, [=](const CStructure * a, const CStructure * b) | ||||
| 		{ | ||||
| 			return build->getDistance(a->building->bid) | ||||
| 				 < build->getDistance(b->building->bid); | ||||
| 			     < build->getDistance(b->building->bid); | ||||
| 		}); | ||||
|  | ||||
| 		buildings.push_back(std::make_shared<CBuildingRect>(this, town, toAdd)); | ||||
| @@ -731,7 +731,7 @@ void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuil | ||||
|  | ||||
| 				case BuildingSubID::FOUNTAIN_OF_FORTUNE: | ||||
| 						enterFountain(building, subID, upgrades); | ||||
| 						break; | ||||
| 					break; | ||||
|  | ||||
| 				case BuildingSubID::FREELANCERS_GUILD: | ||||
| 						if(getHero()) | ||||
| @@ -751,7 +751,7 @@ void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuil | ||||
| 						if(upgrades == BuildingID::TAVERN) | ||||
| 							LOCPLINT->showTavernWindow(town); | ||||
| 						else | ||||
| 							enterBuilding(building); | ||||
| 						enterBuilding(building); | ||||
| 						break; | ||||
|  | ||||
| 				case BuildingSubID::CASTLE_GATE: | ||||
| @@ -794,9 +794,11 @@ void CCastleBuildings::enterBlacksmith(ArtifactID artifactID) | ||||
| 		LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % town->town->buildings.find(BuildingID::BLACKSMITH)->second->Name())); | ||||
| 		return; | ||||
| 	} | ||||
| 	int price = CGI->arth->artifacts[artifactID]->price; | ||||
| 	auto art = artifactID.toArtifact(CGI->artifacts()); | ||||
|  | ||||
| 	int price = art->getPrice(); | ||||
| 	bool possible = LOCPLINT->cb->getResourceAmount(Res::GOLD) >= price && !hero->hasArt(artifactID); | ||||
| 	CreatureID cre = artifactID.toArtifact()->warMachine; | ||||
| 	CreatureID cre = art->getWarMachine(); | ||||
| 	GH.pushIntT<CBlacksmithDialog>(possible, cre, artifactID, hero->id); | ||||
| } | ||||
|  | ||||
| @@ -844,7 +846,7 @@ void CCastleBuildings::enterToTheQuickRecruitmentWindow() | ||||
|  | ||||
| void CCastleBuildings::enterFountain(const BuildingID & building, BuildingSubID::EBuildingSubID subID, BuildingID::EBuildingID upgrades) | ||||
| { | ||||
| 	std::vector<std::shared_ptr<CComponent>> comps(1, std::make_shared<CComponent>(CComponent::building,town->subID, building)); | ||||
| 	std::vector<std::shared_ptr<CComponent>> comps(1, std::make_shared<CComponent>(CComponent::building,town->subID,building)); | ||||
| 	std::string descr = town->town->buildings.find(building)->second->Description(); | ||||
| 	std::string hasNotProduced; | ||||
| 	std::string hasProduced; | ||||
| @@ -878,9 +880,9 @@ void CCastleBuildings::enterFountain(const BuildingID & building, BuildingSubID: | ||||
| 		else //Mystic Pond produced something; | ||||
| 		{ | ||||
| 			descr += "\n\n" + hasProduced; | ||||
| 			boost::algorithm::replace_first(descr, "%s", CGI->generaltexth->restypes[town->bonusValue.first]); | ||||
| 			boost::algorithm::replace_first(descr, "%d", boost::lexical_cast<std::string>(town->bonusValue.second)); | ||||
| 		} | ||||
| 		boost::algorithm::replace_first(descr,"%s",CGI->generaltexth->restypes[town->bonusValue.first]); | ||||
| 		boost::algorithm::replace_first(descr,"%d",boost::lexical_cast<std::string>(town->bonusValue.second)); | ||||
| 	} | ||||
| 	} | ||||
| 	LOCPLINT->showInfoDialog(descr, comps); | ||||
| } | ||||
| @@ -972,9 +974,9 @@ CCreaInfo::CCreaInfo(Point position, const CGTownInstance * Town, int Level, boo | ||||
| 	addUsedEvents(LCLICK | RCLICK | HOVER); | ||||
|  | ||||
| 	ui32 creatureID = town->creatures[level].second.back(); | ||||
| 	creature = CGI->creh->creatures[creatureID]; | ||||
| 	creature = CGI->creh->objects[creatureID]; | ||||
|  | ||||
| 	picture = std::make_shared<CAnimImage>("CPRSMALL", creature->iconIndex, 0, 8, 0); | ||||
| 	picture = std::make_shared<CAnimImage>("CPRSMALL", creature->getIconIndex(), 0, 8, 0); | ||||
|  | ||||
| 	std::string value; | ||||
| 	if(showAvailable) | ||||
| @@ -1627,7 +1629,7 @@ CFortScreen::RecruitArea::RecruitArea(int posX, int posY, const CGTownInstance * | ||||
| 		Rect sizes(287, 4, 96, 18); | ||||
| 		values.push_back(std::make_shared<LabeledValue>(sizes, CGI->generaltexth->allTexts[190], CGI->generaltexth->fcommands[0], getMyCreature()->getAttack(false))); | ||||
| 		sizes.y+=20; | ||||
| 		values.push_back(std::make_shared<LabeledValue>(sizes, CGI->generaltexth->allTexts[191], CGI->generaltexth->fcommands[1], getMyCreature()->getDefence(false))); | ||||
| 		values.push_back(std::make_shared<LabeledValue>(sizes, CGI->generaltexth->allTexts[191], CGI->generaltexth->fcommands[1], getMyCreature()->getDefense(false))); | ||||
| 		sizes.y+=21; | ||||
| 		values.push_back(std::make_shared<LabeledValue>(sizes, CGI->generaltexth->allTexts[199], CGI->generaltexth->fcommands[2], getMyCreature()->getMinDamage(false), getMyCreature()->getMaxDamage(false))); | ||||
| 		sizes.y+=20; | ||||
| @@ -1642,9 +1644,9 @@ CFortScreen::RecruitArea::RecruitArea(int posX, int posY, const CGTownInstance * | ||||
| const CCreature * CFortScreen::RecruitArea::getMyCreature() | ||||
| { | ||||
| 	if(!town->creatures.at(level).second.empty()) // built | ||||
| 		return VLC->creh->creatures[town->creatures.at(level).second.back()]; | ||||
| 		return VLC->creh->objects[town->creatures.at(level).second.back()]; | ||||
| 	if(!town->town->creatures.at(level).empty()) // there are creatures on this level | ||||
| 		return VLC->creh->creatures[town->town->creatures.at(level).front()]; | ||||
| 		return VLC->creh->objects[town->town->creatures.at(level).front()]; | ||||
| 	return nullptr; | ||||
| } | ||||
|  | ||||
| @@ -1750,13 +1752,13 @@ CMageGuildScreen::Scroll::Scroll(Point position, const CSpell *Spell) | ||||
| void CMageGuildScreen::Scroll::clickLeft(tribool down, bool previousState) | ||||
| { | ||||
| 	if(down) | ||||
| 		LOCPLINT->showInfoDialog(spell->getLevelInfo(0).description, std::make_shared<CComponent>(CComponent::spell, spell->id)); | ||||
| 		LOCPLINT->showInfoDialog(spell->getLevelDescription(0), std::make_shared<CComponent>(CComponent::spell, spell->id)); | ||||
| } | ||||
|  | ||||
| void CMageGuildScreen::Scroll::clickRight(tribool down, bool previousState) | ||||
| { | ||||
| 	if(down) | ||||
| 		CRClickPopup::createAndPush(spell->getLevelInfo(0).description, std::make_shared<CComponent>(CComponent::spell, spell->id)); | ||||
| 		CRClickPopup::createAndPush(spell->getLevelDescription(0), std::make_shared<CComponent>(CComponent::spell, spell->id)); | ||||
| } | ||||
|  | ||||
| void CMageGuildScreen::Scroll::hover(bool on) | ||||
| @@ -1781,15 +1783,15 @@ CBlacksmithDialog::CBlacksmithDialog(bool possible, CreatureID creMachineID, Art | ||||
| 	animBG = std::make_shared<CPicture>("TPSMITBK", 64, 50); | ||||
| 	animBG->needRefresh = true; | ||||
|  | ||||
| 	const CCreature * creature = CGI->creh->creatures[creMachineID]; | ||||
| 	const CCreature * creature = CGI->creh->objects[creMachineID]; | ||||
| 	anim = std::make_shared<CCreatureAnim>(64, 50, creature->animDefName); | ||||
| 	anim->clipRect(113,125,200,150); | ||||
|  | ||||
| 	title = std::make_shared<CLabel>(165, 28, FONT_BIG, CENTER, Colors::YELLOW, | ||||
| 				boost::str(boost::format(CGI->generaltexth->allTexts[274]) % creature->nameSing)); | ||||
| 	            boost::str(boost::format(CGI->generaltexth->allTexts[274]) % creature->nameSing)); | ||||
| 	costText = std::make_shared<CLabel>(165, 218, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->jktexts[43]); | ||||
| 	costValue = std::make_shared<CLabel>(165, 290, FONT_MEDIUM, CENTER, Colors::WHITE, | ||||
| 					boost::lexical_cast<std::string>(CGI->arth->artifacts[aid]->price)); | ||||
| 	                boost::lexical_cast<std::string>(aid.toArtifact(CGI->artifacts())->getPrice())); | ||||
|  | ||||
| 	std::string text = boost::str(boost::format(CGI->generaltexth->allTexts[595]) % creature->nameSing); | ||||
| 	buy = std::make_shared<CButton>(Point(42, 312), "IBUY30.DEF", CButton::tooltip(text), [&](){ close(); }, SDLK_RETURN); | ||||
|   | ||||
| @@ -10,6 +10,9 @@ | ||||
| #include "StdInc.h" | ||||
| #include "CCreatureWindow.h" | ||||
|  | ||||
| #include <vcmi/spells/Spell.h> | ||||
| #include <vcmi/spells/Service.h> | ||||
|  | ||||
| #include "../CGameInfo.h" | ||||
| #include "../CPlayerInterface.h" | ||||
| #include "../widgets/Buttons.h" | ||||
| @@ -26,7 +29,6 @@ | ||||
| #include "../../lib/CGeneralTextHandler.h" | ||||
| #include "../../lib/CModHandler.h" | ||||
| #include "../../lib/CHeroHandler.h" | ||||
| #include "../../lib/spells/CSpellHandler.h" | ||||
| #include "../../lib/CGameState.h" | ||||
|  | ||||
| using namespace CSDL_Ext; | ||||
| @@ -193,7 +195,7 @@ CStackWindow::ActiveSpellsSection::ActiveSpellsSection(CStackWindow * owner, int | ||||
| 	std::vector<si32> spells = battleStack->activeSpells(); | ||||
| 	for(si32 effect : spells) | ||||
| 	{ | ||||
| 		const CSpell * sp = CGI->spellh->objects[effect]; | ||||
| 		const spells::Spell * spell = CGI->spells()->getByIndex(effect); | ||||
|  | ||||
| 		std::string spellText; | ||||
|  | ||||
| @@ -204,7 +206,7 @@ CStackWindow::ActiveSpellsSection::ActiveSpellsSection(CStackWindow * owner, int | ||||
| 		if (hasGraphics) | ||||
| 		{ | ||||
| 			spellText = CGI->generaltexth->allTexts[610]; //"%s, duration: %d rounds." | ||||
| 			boost::replace_first(spellText, "%s", sp->name); | ||||
| 			boost::replace_first(spellText, "%s", spell->getName()); | ||||
| 			//FIXME: support permanent duration | ||||
| 			int duration = battleStack->getBonusLocalFirst(Selector::source(Bonus::SPELL_EFFECT,effect))->turnsRemain; | ||||
| 			boost::replace_first(spellText, "%d", boost::lexical_cast<std::string>(duration)); | ||||
| @@ -320,7 +322,7 @@ CStackWindow::ButtonsSection::ButtonsSection(CStackWindow * owner, int yOffset) | ||||
| 			}; | ||||
| 			auto upgradeBtn = std::make_shared<CButton>(Point(221 + (int)buttonIndex * 40, 5), "stackWindow/upgradeButton", CGI->generaltexth->zelp[446], onClick, SDLK_1); | ||||
|  | ||||
| 			upgradeBtn->addOverlay(std::make_shared<CAnimImage>("CPRSMALL", VLC->creh->creatures[upgradeInfo.info.newID[buttonIndex]]->iconIndex)); | ||||
| 			upgradeBtn->addOverlay(std::make_shared<CAnimImage>("CPRSMALL", VLC->creh->objects[upgradeInfo.info.newID[buttonIndex]]->iconIndex)); | ||||
|  | ||||
| 			upgrade[buttonIndex] = upgradeBtn; | ||||
| 		} | ||||
| @@ -520,7 +522,7 @@ CStackWindow::MainSection::MainSection(CStackWindow * owner, int yOffset, bool s | ||||
| 	if(battleStack != nullptr) // in battle | ||||
| 	{ | ||||
| 		addStatLabel(EStat::ATTACK, parent->info->creature->getAttack(battleStack->isShooter()), battleStack->getAttack(battleStack->isShooter())); | ||||
| 		addStatLabel(EStat::DEFENCE, parent->info->creature->getDefence(battleStack->isShooter()), battleStack->getDefence(battleStack->isShooter())); | ||||
| 		addStatLabel(EStat::DEFENCE, parent->info->creature->getDefense(battleStack->isShooter()), battleStack->getDefense(battleStack->isShooter())); | ||||
| 		addStatLabel(EStat::DAMAGE, parent->info->stackNode->getMinDamage(battleStack->isShooter()) * dmgMultiply, battleStack->getMaxDamage(battleStack->isShooter()) * dmgMultiply); | ||||
| 		addStatLabel(EStat::HEALTH, parent->info->creature->MaxHealth(), battleStack->MaxHealth()); | ||||
| 		addStatLabel(EStat::SPEED, parent->info->creature->Speed(), battleStack->Speed()); | ||||
| @@ -540,7 +542,7 @@ CStackWindow::MainSection::MainSection(CStackWindow * owner, int yOffset, bool s | ||||
| 		const bool caster = parent->info->stackNode->valOfBonuses(Bonus::CASTS); | ||||
|  | ||||
| 		addStatLabel(EStat::ATTACK, parent->info->creature->getAttack(shooter), parent->info->stackNode->getAttack(shooter)); | ||||
| 		addStatLabel(EStat::DEFENCE, parent->info->creature->getDefence(shooter), parent->info->stackNode->getDefence(shooter)); | ||||
| 		addStatLabel(EStat::DEFENCE, parent->info->creature->getDefense(shooter), parent->info->stackNode->getDefense(shooter)); | ||||
| 		addStatLabel(EStat::DAMAGE, parent->info->stackNode->getMinDamage(shooter) * dmgMultiply, parent->info->stackNode->getMaxDamage(shooter) * dmgMultiply); | ||||
| 		addStatLabel(EStat::HEALTH, parent->info->creature->MaxHealth(), parent->info->stackNode->MaxHealth()); | ||||
| 		addStatLabel(EStat::SPEED, parent->info->creature->Speed(), parent->info->stackNode->Speed()); | ||||
|   | ||||
| @@ -16,7 +16,6 @@ | ||||
| class CButton; | ||||
| struct SDL_Surface; | ||||
| class CGHeroInstance; | ||||
| class CArtifact; | ||||
| class CHeroWindow; | ||||
| class LClickableAreaHero; | ||||
| class LRClickableAreaWText; | ||||
|   | ||||
| @@ -163,7 +163,7 @@ std::string InfoBoxAbstractHeroData::getNameText() | ||||
| 	case HERO_EXPERIENCE: | ||||
| 		return CGI->generaltexth->jktexts[6]; | ||||
| 	case HERO_SPECIAL: | ||||
| 		return CGI->heroh->heroes[getSubID()]->specName; | ||||
| 		return CGI->heroh->objects[getSubID()]->specName; | ||||
| 	case HERO_SECONDARY_SKILL: | ||||
| 		if (getValue()) | ||||
| 			return CGI->skillh->skillName(getSubID()); | ||||
| @@ -229,7 +229,7 @@ size_t InfoBoxAbstractHeroData::getImageIndex() | ||||
| 	switch (type) | ||||
| 	{ | ||||
| 	case HERO_SPECIAL: | ||||
| 		return VLC->heroh->heroes[getSubID()]->imageIndex; | ||||
| 		return CGI->heroh->objects[getSubID()]->imageIndex; | ||||
| 	case HERO_PRIMARY_SKILL: | ||||
| 		return getSubID(); | ||||
| 	case HERO_MANA: | ||||
| @@ -256,7 +256,7 @@ void InfoBoxAbstractHeroData::prepareMessage(std::string & text, std::shared_ptr | ||||
| 	switch (type) | ||||
| 	{ | ||||
| 	case HERO_SPECIAL: | ||||
| 		text = CGI->heroh->heroes[getSubID()]->specDescr; | ||||
| 		text = CGI->heroh->objects[getSubID()]->specDescr; | ||||
| 		break; | ||||
| 	case HERO_PRIMARY_SKILL: | ||||
| 		text = CGI->generaltexth->arraytxt[2+getSubID()]; | ||||
|   | ||||
| @@ -120,7 +120,7 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m | ||||
|  | ||||
| 	for(const auto spell : mySpells) | ||||
| 	{ | ||||
| 		int * sitesPerOurTab = spell->isCombatSpell() ? sitesPerTabBattle : sitesPerTabAdv; | ||||
| 		int * sitesPerOurTab = spell->isCombat() ? sitesPerTabBattle : sitesPerTabAdv; | ||||
|  | ||||
| 		++sitesPerOurTab[4]; | ||||
|  | ||||
| @@ -332,7 +332,7 @@ void CSpellWindow::computeSpellsPerArea() | ||||
| 	spellsCurSite.reserve(mySpells.size()); | ||||
| 	for(const CSpell * spell : mySpells) | ||||
| 	{ | ||||
| 		if(spell->isCombatSpell() ^ !battleSpellsOnly | ||||
| 		if(spell->isCombat() ^ !battleSpellsOnly | ||||
| 			&& ((selectedTab == 4) || spell->school.at((ESpellSchool)selectedTab)) | ||||
| 			) | ||||
| 		{ | ||||
| @@ -522,7 +522,7 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState) | ||||
| { | ||||
| 	if(mySpell && !down) | ||||
| 	{ | ||||
| 		int spellCost = owner->myInt->cb->getSpellCost(mySpell, owner->myHero); | ||||
| 		auto spellCost = owner->myInt->cb->getSpellCost(mySpell, owner->myHero); | ||||
| 		if(spellCost > owner->myHero->mana) //insufficient mana | ||||
| 		{ | ||||
| 			owner->myInt->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[206]) % spellCost % owner->myHero->mana)); | ||||
| @@ -531,8 +531,8 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState) | ||||
|  | ||||
| 		//anything that is not combat spell is adventure spell | ||||
| 		//this not an error in general to cast even creature ability with hero | ||||
| 		const bool combatSpell = mySpell->isCombatSpell(); | ||||
| 		if(mySpell->isCombatSpell() != !mySpell->isAdventureSpell()) | ||||
| 		const bool combatSpell = mySpell->isCombat(); | ||||
| 		if(combatSpell == mySpell->isAdventure()) | ||||
| 		{ | ||||
| 			logGlobal->error("Spell have invalid flags"); | ||||
| 			return; | ||||
| @@ -545,7 +545,7 @@ void CSpellWindow::SpellArea::clickLeft(tribool down, bool previousState) | ||||
| 		if((combatSpell ^ inCombat) || inCastle) | ||||
| 		{ | ||||
| 			std::vector<std::shared_ptr<CComponent>> hlp(1, std::make_shared<CComponent>(CComponent::spell, mySpell->id, 0)); | ||||
| 			owner->myInt->showInfoDialog(mySpell->getLevelInfo(schoolLevel).description, hlp); | ||||
| 			owner->myInt->showInfoDialog(mySpell->getLevelDescription(schoolLevel), hlp); | ||||
| 		} | ||||
| 		else if(combatSpell) | ||||
| 		{ | ||||
| @@ -600,7 +600,7 @@ void CSpellWindow::SpellArea::clickRight(tribool down, bool previousState) | ||||
| 			boost::algorithm::replace_first(dmgInfo, "%d", boost::lexical_cast<std::string>(causedDmg)); | ||||
| 		} | ||||
|  | ||||
| 		CRClickPopup::createAndPush(mySpell->getLevelInfo(schoolLevel).description + dmgInfo, std::make_shared<CComponent>(CComponent::spell, mySpell->id)); | ||||
| 		CRClickPopup::createAndPush(mySpell->getLevelDescription(schoolLevel) + dmgInfo, std::make_shared<CComponent>(CComponent::spell, mySpell->id)); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -625,7 +625,7 @@ void CSpellWindow::SpellArea::setSpell(const CSpell * spell) | ||||
| 	mySpell = spell; | ||||
| 	if(mySpell) | ||||
| 	{ | ||||
| 		int whichSchool = 0; //0 - air magic, 1 - fire magic, 2 - water magic, 3 - earth magic, | ||||
| 		int32_t whichSchool = 0; //0 - air magic, 1 - fire magic, 2 - water magic, 3 - earth magic, | ||||
| 		schoolLevel = owner->myHero->getSpellSchoolLevel(mySpell, &whichSchool); | ||||
| 		auto spellCost = owner->myInt->cb->getSpellCost(mySpell, owner->myHero); | ||||
|  | ||||
|   | ||||
| @@ -114,9 +114,9 @@ int CTradeWindow::CTradeableItem::getIndex() | ||||
| 	case ARTIFACT_TYPE: | ||||
| 	case ARTIFACT_INSTANCE: | ||||
| 	case ARTIFACT_PLACEHOLDER: | ||||
| 		return VLC->arth->artifacts[id]->iconIndex; | ||||
| 		return CGI->artifacts()->getByIndex(id)->getIconIndex(); | ||||
| 	case CREATURE: | ||||
| 		return VLC->creh->creatures[id]->iconIndex; | ||||
| 		return CGI->creatures()->getByIndex(id)->getIconIndex(); | ||||
| 	default: | ||||
| 		return -1; | ||||
| 	} | ||||
| @@ -244,13 +244,13 @@ void CTradeWindow::CTradeableItem::hover(bool on) | ||||
| 	{ | ||||
| 	case CREATURE: | ||||
| 	case CREATURE_PLACEHOLDER: | ||||
| 		GH.statusbar->setText(boost::str(boost::format(CGI->generaltexth->allTexts[481]) % CGI->creh->creatures[id]->namePl)); | ||||
| 		GH.statusbar->setText(boost::str(boost::format(CGI->generaltexth->allTexts[481]) % CGI->creh->objects[id]->namePl)); | ||||
| 		break; | ||||
| 	case ARTIFACT_PLACEHOLDER: | ||||
| 		if(id < 0) | ||||
| 			GH.statusbar->setText(CGI->generaltexth->zelp[582].first); | ||||
| 		else | ||||
| 			GH.statusbar->setText(CGI->arth->artifacts[id]->Name()); | ||||
| 			GH.statusbar->setText(CGI->artifacts()->getByIndex(id)->getName()); | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
| @@ -263,13 +263,13 @@ void CTradeWindow::CTradeableItem::clickRight(tribool down, bool previousState) | ||||
| 		{ | ||||
| 		case CREATURE: | ||||
| 		case CREATURE_PLACEHOLDER: | ||||
| 			//GH.statusbar->print(boost::str(boost::format(CGI->generaltexth->allTexts[481]) % CGI->creh->creatures[id]->namePl)); | ||||
| 			//GH.statusbar->print(boost::str(boost::format(CGI->generaltexth->allTexts[481]) % CGI->creh->objects[id]->namePl)); | ||||
| 			break; | ||||
| 		case ARTIFACT_TYPE: | ||||
| 		case ARTIFACT_PLACEHOLDER: | ||||
| 			//TODO: it's would be better for market to contain actual CArtifactInstance and not just ids of certain artifact type so we can use getEffectiveDescription. | ||||
| 			if(id >= 0) | ||||
| 				adventureInt->handleRightClick(CGI->arth->artifacts[id]->Description(), down); | ||||
| 				adventureInt->handleRightClick(CGI->artifacts()->getByIndex(id)->getDescription(), down); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| @@ -285,14 +285,14 @@ std::string CTradeWindow::CTradeableItem::getName(int number) const | ||||
| 		return CGI->generaltexth->restypes[id]; | ||||
| 	case CREATURE: | ||||
| 		if(number == 1) | ||||
| 			return CGI->creh->creatures[id]->nameSing; | ||||
| 			return CGI->creh->objects[id]->nameSing; | ||||
| 		else | ||||
| 			return CGI->creh->creatures[id]->namePl; | ||||
| 			return CGI->creh->objects[id]->namePl; | ||||
| 	case ARTIFACT_TYPE: | ||||
| 	case ARTIFACT_INSTANCE: | ||||
| 		return CGI->arth->artifacts[id]->Name(); | ||||
| 		return CGI->artifacts()->getByIndex(id)->getName(); | ||||
| 	} | ||||
| 	assert(0); | ||||
| 	logGlobal->error("Invalid trade item type: %d", (int)type); | ||||
| 	return ""; | ||||
| } | ||||
|  | ||||
| @@ -668,14 +668,14 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket * Market, const CGHeroInsta | ||||
| 		switch (mode) | ||||
| 		{ | ||||
| 		case EMarketMode::CREATURE_RESOURCE: | ||||
| 			title = CGI->townh->factions[ETownType::STRONGHOLD]->town->buildings[BuildingID::FREELANCERS_GUILD]->Name(); | ||||
| 			title = (*CGI->townh)[ETownType::STRONGHOLD]->town->buildings[BuildingID::FREELANCERS_GUILD]->Name(); | ||||
| 			break; | ||||
| 		case EMarketMode::RESOURCE_ARTIFACT: | ||||
| 			title = CGI->townh->factions[market->o->subID]->town->buildings[BuildingID::ARTIFACT_MERCHANT]->Name(); | ||||
| 			title = (*CGI->townh)[market->o->subID]->town->buildings[BuildingID::ARTIFACT_MERCHANT]->Name(); | ||||
| 			sliderNeeded = false; | ||||
| 			break; | ||||
| 		case EMarketMode::ARTIFACT_RESOURCE: | ||||
| 			title = CGI->townh->factions[market->o->subID]->town->buildings[BuildingID::ARTIFACT_MERCHANT]->Name(); | ||||
| 			title = (*CGI->townh)[market->o->subID]->town->buildings[BuildingID::ARTIFACT_MERCHANT]->Name(); | ||||
| 			sliderNeeded = false; | ||||
| 			break; | ||||
| 		default: | ||||
|   | ||||
| @@ -159,7 +159,7 @@ void CRecruitmentWindow::buy() | ||||
| 		if(dst->ID == Obj::HERO) | ||||
| 		{ | ||||
| 			txt = CGI->generaltexth->allTexts[425]; //The %s would join your hero, but there aren't enough provisions to support them. | ||||
| 			boost::algorithm::replace_first(txt, "%s", slider->getValue() > 1 ? CGI->creh->creatures[crid]->namePl : CGI->creh->creatures[crid]->nameSing); | ||||
| 			boost::algorithm::replace_first(txt, "%s", slider->getValue() > 1 ? CGI->creh->objects[crid]->namePl : CGI->creh->objects[crid]->nameSing); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| @@ -249,7 +249,7 @@ void CRecruitmentWindow::availableCreaturesChanged() | ||||
|  | ||||
| 		//create new cards | ||||
| 		for(auto & creature : boost::adaptors::reverse(dwelling->creatures[i].second)) | ||||
| 			cards.push_back(std::make_shared<CCreatureCard>(this, CGI->creh->creatures[creature], amount)); | ||||
| 			cards.push_back(std::make_shared<CCreatureCard>(this, CGI->creh->objects[creature], amount)); | ||||
| 	} | ||||
|  | ||||
| 	const int creatureWidth = 102; | ||||
| @@ -1040,7 +1040,7 @@ CPuzzleWindow::CPuzzleWindow(const int3 & GrailPos, double discoveredRatio) | ||||
|  | ||||
| 	int faction = LOCPLINT->cb->getStartInfo()->playerInfos.find(LOCPLINT->playerID)->second.castle; | ||||
|  | ||||
| 	auto & puzzleMap = CGI->townh->factions[faction]->puzzleMap; | ||||
| 	auto & puzzleMap = (*CGI->townh)[faction]->puzzleMap; | ||||
|  | ||||
| 	for(auto & elem : puzzleMap) | ||||
| 	{ | ||||
| @@ -1276,10 +1276,10 @@ CUniversityWindow::CUniversityWindow(const CGHeroInstance * _hero, const IMarket | ||||
| 		{ | ||||
| 			auto faction = town->town->faction->index; | ||||
| 			auto bid = town->town->getSpecialBuilding(BuildingSubID::MAGIC_UNIVERSITY)->bid; | ||||
| 			titlePic = std::make_shared<CAnimImage>(CGI->townh->factions[faction]->town->clientInfo.buildingsIcons, bid); | ||||
| 			titlePic = std::make_shared<CAnimImage>((*CGI->townh)[faction]->town->clientInfo.buildingsIcons, bid); | ||||
| 		} | ||||
| 		else | ||||
| 			titlePic = std::make_shared<CAnimImage>(CGI->townh->factions[ETownType::CONFLUX]->town->clientInfo.buildingsIcons, BuildingID::MAGIC_UNIVERSITY); | ||||
| 			titlePic = std::make_shared<CAnimImage>((*CGI->townh)[ETownType::CONFLUX]->town->clientInfo.buildingsIcons, BuildingID::MAGIC_UNIVERSITY); | ||||
| 	} | ||||
| 	else | ||||
| 		titlePic = std::make_shared<CPicture>("UNIVBLDG"); | ||||
|   | ||||
							
								
								
									
										50
									
								
								cmake_modules/FindLuaJIT.cmake
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								cmake_modules/FindLuaJIT.cmake
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| # Locate LuaJIT library | ||||
| # This module defines | ||||
| #  LUAJIT_FOUND, if false, do not try to link to Lua | ||||
| #  LUA_INCLUDE_DIR, where to find lua.h | ||||
| #  LUA_VERSION_STRING, the version of Lua found (since CMake 2.8.8) | ||||
| # | ||||
| # This module is similar to FindLua51.cmake except that it finds LuaJit instead. | ||||
|  | ||||
| FIND_PATH(LUA_INCLUDE_DIR luajit.h | ||||
| 	HINTS | ||||
| 	$ENV{LUA_DIR} | ||||
| 	PATH_SUFFIXES include/luajit include/luajit-2.1 include/luajit-2.0 include/luajit-5_1-2.1 include/luajit-5_1-2.0 include | ||||
| 	PATHS | ||||
| 	~/Library/Frameworks | ||||
| 	/Library/Frameworks | ||||
| 	/sw # Fink | ||||
| 	/opt/local # DarwinPorts | ||||
| 	/opt/csw # Blastwave | ||||
| 	/opt | ||||
| ) | ||||
|  | ||||
| FIND_LIBRARY(LUA_LIBRARY | ||||
| 	NAMES luajit-5.1 lua51 | ||||
| 	HINTS | ||||
| 	$ENV{LUA_DIR} | ||||
| 	PATH_SUFFIXES lib64 lib | ||||
| 	PATHS | ||||
| 	~/Library/Frameworks | ||||
| 	/Library/Frameworks | ||||
| 	/sw | ||||
| 	/opt/local | ||||
| 	/opt/csw | ||||
| 	/opt | ||||
| ) | ||||
|  | ||||
| IF(LUA_INCLUDE_DIR AND EXISTS "${LUA_INCLUDE_DIR}/luajit.h") | ||||
| 	FILE(STRINGS "${LUA_INCLUDE_DIR}/luajit.h" lua_version_str REGEX "^#define[ \t]+LUA_RELEASE[ \t]+\"LuaJIT .+\"") | ||||
|  | ||||
| 	STRING(REGEX REPLACE "^#define[ \t]+LUA_RELEASE[ \t]+\"LuaJIT ([^\"]+)\".*" "\\1" LUA_VERSION_STRING "${lua_version_str}") | ||||
| 	UNSET(lua_version_str) | ||||
| ENDIF() | ||||
|  | ||||
| INCLUDE(FindPackageHandleStandardArgs) | ||||
| # handle the QUIETLY and REQUIRED arguments and set LUAJIT_FOUND to TRUE if | ||||
| # all listed variables are TRUE | ||||
| FIND_PACKAGE_HANDLE_STANDARD_ARGS(LuaJit | ||||
| 	REQUIRED_VARS LUA_LIBRARY LUA_INCLUDE_DIR | ||||
| 	VERSION_VAR LUA_VERSION_STRING) | ||||
|  | ||||
| MARK_AS_ADVANCED(LUA_INCLUDE_DIR LUA_LIBRARY LUA_MATH_LIBRARY) | ||||
| @@ -48,6 +48,10 @@ | ||||
| 		"MODS/": | ||||
| 		[ | ||||
| 			{"type" : "dir",  "path" : "Mods", "depth": 1} | ||||
| 		], | ||||
| 		"SCRIPTS/": | ||||
| 		[ | ||||
| 			{"type" : "dir",  "path" : "scripts"} | ||||
| 		] | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -92,6 +92,11 @@ | ||||
| 			"description": "List of configuration files for objects", | ||||
| 			"items": { "type":"string", "format" : "textFile" } | ||||
| 		}, | ||||
| 		"scripts": { | ||||
| 			"type":"array", | ||||
| 			"description": "List of configuration files for scripts", | ||||
| 			"items": { "type":"string", "format" : "textFile" } | ||||
| 		}, | ||||
| 		"spells": { | ||||
| 			"type":"array", | ||||
| 			"description": "List of configuration files for spells", | ||||
| @@ -106,7 +111,7 @@ | ||||
| 			"type":"array", | ||||
| 			"description": "List of configuration files for RMG templates", | ||||
| 			"items": { "type":"string", "format" : "textFile" } | ||||
| 		 | ||||
|  | ||||
| 		}, | ||||
|  | ||||
| 		"changelog" : { | ||||
|   | ||||
							
								
								
									
										22
									
								
								config/schemas/script.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								config/schemas/script.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| { | ||||
| 	"type" : "object", | ||||
| 	"$schema" : "http://json-schema.org/draft-04/schema", | ||||
|  | ||||
| 	"title" : "VCMI script format", | ||||
| 	"description" : "Format used to configure script environment", | ||||
|  | ||||
|  | ||||
| 	"required" : ["source"], | ||||
|  | ||||
| 	"properties" : { | ||||
| 		"source" : { | ||||
| 			"type": "string", | ||||
| 			"description": "Full VFS path to script source (extension required)" | ||||
| 		}, | ||||
| 		"implements" :{ | ||||
| 			"type": "string", | ||||
| 			"enum": ["ANYTHING", "BATTLE_EFFECT"], | ||||
| 			"description": "" | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										27
									
								
								include/vcmi/Artifact.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								include/vcmi/Artifact.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| /* | ||||
|  * Artifact.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "Entity.h" | ||||
|  | ||||
| class ArtifactID; | ||||
| class CreatureID; | ||||
|  | ||||
| class DLL_LINKAGE Artifact : public EntityWithBonuses<ArtifactID> | ||||
| { | ||||
| public: | ||||
| 	virtual bool isBig() const = 0; | ||||
| 	virtual bool isTradable() const = 0; | ||||
| 	virtual const std::string & getDescription() const = 0; | ||||
| 	virtual const std::string & getEventText() const = 0; | ||||
| 	virtual uint32_t getPrice() const = 0; | ||||
| 	virtual CreatureID getWarMachine() const = 0; | ||||
| }; | ||||
							
								
								
									
										21
									
								
								include/vcmi/ArtifactService.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								include/vcmi/ArtifactService.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| /* | ||||
|  * ArtifactService.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "EntityService.h" | ||||
|  | ||||
| class ArtifactID; | ||||
| class Artifact; | ||||
|  | ||||
| class DLL_LINKAGE ArtifactService : public EntityServiceT<ArtifactID, Artifact> | ||||
| { | ||||
| public: | ||||
| }; | ||||
							
								
								
									
										45
									
								
								include/vcmi/Creature.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								include/vcmi/Creature.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| /* | ||||
|  * Creature.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "Entity.h" | ||||
|  | ||||
| class CreatureID; | ||||
|  | ||||
| class DLL_LINKAGE Creature : public EntityWithBonuses<CreatureID> | ||||
| { | ||||
| public: | ||||
| 	virtual const std::string & getPluralName() const = 0; | ||||
| 	virtual const std::string & getSingularName() const = 0; | ||||
| 	virtual uint32_t getMaxHealth() const = 0; | ||||
|  | ||||
| 	virtual int32_t getAdvMapAmountMin() const = 0; | ||||
| 	virtual int32_t getAdvMapAmountMax() const = 0; | ||||
| 	virtual int32_t getAIValue() const = 0; | ||||
| 	virtual int32_t getFightValue() const = 0; | ||||
| 	virtual int32_t getLevel() const = 0; | ||||
| 	virtual int32_t getGrowth() const = 0; | ||||
| 	virtual int32_t getHorde() const = 0; | ||||
| 	virtual int32_t getFactionIndex() const = 0; | ||||
|  | ||||
| 	virtual int32_t getBaseAttack() const = 0; | ||||
| 	virtual int32_t getBaseDefense() const = 0; | ||||
| 	virtual int32_t getBaseDamageMin() const = 0; | ||||
| 	virtual int32_t getBaseDamageMax() const = 0; | ||||
| 	virtual int32_t getBaseHitPoints() const = 0; | ||||
| 	virtual int32_t getBaseSpellPoints() const = 0; | ||||
| 	virtual int32_t getBaseSpeed() const = 0; | ||||
| 	virtual int32_t getBaseShots() const = 0; | ||||
|  | ||||
| 	virtual int32_t getCost(int32_t resIndex) const = 0; | ||||
|  | ||||
| 	virtual bool isDoubleWide() const = 0; | ||||
| }; | ||||
							
								
								
									
										21
									
								
								include/vcmi/CreatureService.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								include/vcmi/CreatureService.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| /* | ||||
|  * CreatureService.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "EntityService.h" | ||||
|  | ||||
| class CreatureID; | ||||
| class Creature; | ||||
|  | ||||
| class DLL_LINKAGE CreatureService : public EntityServiceT<CreatureID, Creature> | ||||
| { | ||||
| public: | ||||
| }; | ||||
							
								
								
									
										42
									
								
								include/vcmi/Entity.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								include/vcmi/Entity.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| /* | ||||
|  * Entity.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| class IBonusBearer; | ||||
|  | ||||
| class DLL_LINKAGE Entity | ||||
| { | ||||
| public: | ||||
| 	using IconRegistar = std::function<void(int32_t index, const std::string & listName, const std::string & imageName)>; | ||||
|  | ||||
| 	virtual ~Entity() = default; | ||||
|  | ||||
| 	virtual int32_t getIndex() const = 0; | ||||
| 	virtual int32_t getIconIndex() const = 0; | ||||
| 	virtual const std::string & getJsonKey() const = 0; | ||||
| 	virtual const std::string & getName() const = 0; | ||||
|  | ||||
| 	virtual void registerIcons(const IconRegistar & cb) const = 0; | ||||
| }; | ||||
|  | ||||
| template <typename IdType> | ||||
| class DLL_LINKAGE EntityT : public Entity | ||||
| { | ||||
| public: | ||||
| 	virtual IdType getId() const = 0; | ||||
| }; | ||||
|  | ||||
| template <typename IdType> | ||||
| class DLL_LINKAGE EntityWithBonuses : public EntityT<IdType> | ||||
| { | ||||
| public: | ||||
| 	virtual const IBonusBearer * accessBonuses() const = 0; | ||||
| }; | ||||
							
								
								
									
										32
									
								
								include/vcmi/EntityService.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								include/vcmi/EntityService.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| /* | ||||
|  * EntityService.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| class Entity; | ||||
|  | ||||
| class DLL_LINKAGE EntityService | ||||
| { | ||||
| public: | ||||
| 	virtual ~EntityService() = default; | ||||
|  | ||||
| 	virtual const Entity * getBaseByIndex(const int32_t index) const = 0; | ||||
| 	virtual void forEachBase(const std::function<void(const Entity * entity, bool & stop)> & cb) const = 0; | ||||
| }; | ||||
|  | ||||
| template <typename IdType, typename EntityType> | ||||
| class DLL_LINKAGE EntityServiceT : public EntityService | ||||
| { | ||||
| public: | ||||
| 	virtual const EntityType * getById(const IdType & id) const = 0; | ||||
| 	virtual const EntityType * getByIndex(const int32_t index) const = 0; | ||||
|  | ||||
| 	virtual void forEach(const std::function<void(const EntityType * entity, bool & stop)> & cb) const = 0; | ||||
| }; | ||||
							
								
								
									
										36
									
								
								include/vcmi/Environment.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								include/vcmi/Environment.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| /* | ||||
|  * Environment.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| class Services; | ||||
|  | ||||
| class IGameInfoCallback; | ||||
| class IBattleInfoCallback; | ||||
|  | ||||
| namespace events | ||||
| { | ||||
| 	class EventBus; | ||||
| } | ||||
|  | ||||
| class DLL_LINKAGE Environment | ||||
| { | ||||
| public: | ||||
| 	using BattleCb = ::IBattleInfoCallback; | ||||
| 	using GameCb = ::IGameInfoCallback; | ||||
|  | ||||
| 	virtual ~Environment() = default; | ||||
|  | ||||
| 	virtual const Services * services() const = 0; | ||||
| 	virtual const BattleCb * battle() const = 0; | ||||
| 	virtual const GameCb * game() const = 0; | ||||
| 	virtual vstd::CLoggerBase * logger() const = 0; | ||||
| 	virtual events::EventBus * eventBus() const = 0; | ||||
| }; | ||||
							
								
								
									
										21
									
								
								include/vcmi/Faction.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								include/vcmi/Faction.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| /* | ||||
|  * Faction.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "Entity.h" | ||||
|  | ||||
| class FactionID; | ||||
|  | ||||
| class DLL_LINKAGE Faction : public EntityT<FactionID> | ||||
| { | ||||
| public: | ||||
| 	virtual bool hasTown() const = 0; | ||||
| }; | ||||
							
								
								
									
										21
									
								
								include/vcmi/FactionService.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								include/vcmi/FactionService.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| /* | ||||
|  * FactionService.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "EntityService.h" | ||||
|  | ||||
| class FactionID; | ||||
| class Faction; | ||||
|  | ||||
| class DLL_LINKAGE FactionService : public EntityServiceT<FactionID, Faction> | ||||
| { | ||||
| public: | ||||
| }; | ||||
							
								
								
									
										22
									
								
								include/vcmi/HeroClass.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								include/vcmi/HeroClass.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| /* | ||||
|  * HeroClass.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "Entity.h" | ||||
|  | ||||
| class HeroClassID; | ||||
|  | ||||
| class DLL_LINKAGE HeroClass : public EntityT<HeroClassID> | ||||
| { | ||||
| public: | ||||
|  | ||||
| }; | ||||
|  | ||||
							
								
								
									
										21
									
								
								include/vcmi/HeroClassService.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								include/vcmi/HeroClassService.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| /* | ||||
|  * HeroClassService.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "EntityService.h" | ||||
|  | ||||
| class HeroClassID; | ||||
| class HeroClass; | ||||
|  | ||||
| class DLL_LINKAGE HeroClassService : public EntityServiceT<HeroClassID, HeroClass> | ||||
| { | ||||
| public: | ||||
| }; | ||||
							
								
								
									
										22
									
								
								include/vcmi/HeroType.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								include/vcmi/HeroType.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| /* | ||||
|  * HeroType.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "Entity.h" | ||||
|  | ||||
| class HeroTypeID; | ||||
|  | ||||
| class DLL_LINKAGE HeroType : public EntityT<HeroTypeID> | ||||
| { | ||||
| public: | ||||
|  | ||||
| }; | ||||
|  | ||||
							
								
								
									
										21
									
								
								include/vcmi/HeroTypeService.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								include/vcmi/HeroTypeService.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| /* | ||||
|  * HeroTypeService.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "EntityService.h" | ||||
|  | ||||
| class HeroTypeID; | ||||
| class HeroType; | ||||
|  | ||||
| class DLL_LINKAGE HeroTypeService : public EntityServiceT<HeroTypeID, HeroType> | ||||
| { | ||||
| public: | ||||
| }; | ||||
							
								
								
									
										30
									
								
								include/vcmi/Metatype.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								include/vcmi/Metatype.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| /* | ||||
|  * Metatype.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| enum class Metatype : uint32_t | ||||
| { | ||||
| 	UNKNOWN = 0, | ||||
| 	ARTIFACT, | ||||
| 	ARTIFACT_INSTANCE, | ||||
| 	CREATURE, | ||||
| 	CREATURE_INSTANCE, | ||||
| 	FACTION, | ||||
| 	HERO_CLASS, | ||||
| 	HERO_TYPE, | ||||
| 	HERO_INSTANCE, | ||||
| 	MAP_OBJECT_GROUP, | ||||
| 	MAP_OBJECT_TYPE, | ||||
| 	MAP_OBJECT_INSTANCE, | ||||
| 	SKILL, | ||||
| 	SPELL | ||||
| }; | ||||
|  | ||||
							
								
								
									
										30
									
								
								include/vcmi/Player.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								include/vcmi/Player.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| /* | ||||
|  * Player.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| class PlayerColor; | ||||
| class TeamID; | ||||
| class IBonusBearer; | ||||
|  | ||||
| class DLL_LINKAGE Player | ||||
| { | ||||
| public: | ||||
| 	virtual PlayerColor getColor() const = 0; | ||||
| 	virtual TeamID getTeam() const = 0; | ||||
| 	virtual bool isHuman() const = 0; | ||||
| 	virtual const IBonusBearer * accessBonuses() const = 0; | ||||
| 	virtual int getResourceAmount(int type) const = 0; | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
							
								
								
									
										44
									
								
								include/vcmi/ServerCallback.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								include/vcmi/ServerCallback.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| /* | ||||
|  * ServerCallback.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| namespace vstd | ||||
| { | ||||
| 	class RNG; | ||||
| } | ||||
|  | ||||
| struct CPackForClient; | ||||
| struct BattleLogMessage; | ||||
| struct BattleStackMoved; | ||||
| struct BattleUnitsChanged; | ||||
| struct SetStackEffect; | ||||
| struct StacksInjured; | ||||
| struct BattleObstaclesChanged; | ||||
| struct CatapultAttack; | ||||
|  | ||||
| class DLL_LINKAGE ServerCallback | ||||
| { | ||||
| public: | ||||
| 	virtual void complain(const std::string & problem) = 0; | ||||
| 	virtual bool describeChanges() const = 0; | ||||
|  | ||||
| 	virtual vstd::RNG * getRNG() = 0; | ||||
|  | ||||
| 	virtual void apply(CPackForClient * pack) = 0; | ||||
|  | ||||
| 	virtual void apply(BattleLogMessage * pack) = 0; | ||||
| 	virtual void apply(BattleStackMoved * pack) = 0; | ||||
| 	virtual void apply(BattleUnitsChanged * pack) = 0; | ||||
| 	virtual void apply(SetStackEffect * pack) = 0; | ||||
| 	virtual void apply(StacksInjured * pack) = 0; | ||||
| 	virtual void apply(BattleObstaclesChanged * pack) = 0; | ||||
| 	virtual void apply(CatapultAttack * pack) = 0; | ||||
| }; | ||||
							
								
								
									
										57
									
								
								include/vcmi/Services.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								include/vcmi/Services.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| /* | ||||
|  * Services.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "Metatype.h" | ||||
|  | ||||
| class ArtifactService; | ||||
| class CreatureService; | ||||
| class FactionService; | ||||
| class HeroClassService; | ||||
| class HeroTypeService; | ||||
| class SkillService; | ||||
| class JsonNode; | ||||
|  | ||||
| namespace spells | ||||
| { | ||||
| 	class Service; | ||||
|  | ||||
| 	namespace effects | ||||
| 	{ | ||||
| 		class Registry; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| namespace scripting | ||||
| { | ||||
| 	class Service; | ||||
| } | ||||
|  | ||||
| class DLL_LINKAGE Services | ||||
| { | ||||
| public: | ||||
| 	virtual ~Services() = default; | ||||
|  | ||||
| 	virtual const ArtifactService * artifacts() const = 0; | ||||
| 	virtual const CreatureService * creatures() const = 0; | ||||
| 	virtual const FactionService * factions() const = 0; | ||||
| 	virtual const HeroClassService * heroClasses() const = 0; | ||||
| 	virtual const HeroTypeService * heroTypes() const = 0; | ||||
| 	virtual const scripting::Service * scripts() const = 0; | ||||
| 	virtual const spells::Service * spells() const = 0; | ||||
| 	virtual const SkillService * skills() const = 0; | ||||
|  | ||||
| 	virtual void updateEntity(Metatype metatype, int32_t index, const JsonNode & data) = 0; | ||||
|  | ||||
| 	virtual const spells::effects::Registry * spellEffects() const = 0; | ||||
| 	virtual spells::effects::Registry * spellEffects() = 0; | ||||
| 	//TODO: put map object types registry access here | ||||
| }; | ||||
							
								
								
									
										22
									
								
								include/vcmi/Skill.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								include/vcmi/Skill.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| /* | ||||
|  * Skill.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "Entity.h" | ||||
|  | ||||
| class SecondarySkill; | ||||
|  | ||||
| class DLL_LINKAGE Skill : public EntityT<SecondarySkill> | ||||
| { | ||||
| public: | ||||
|  | ||||
| }; | ||||
|  | ||||
							
								
								
									
										21
									
								
								include/vcmi/SkillService.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								include/vcmi/SkillService.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| /* | ||||
|  * SkillService.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "EntityService.h" | ||||
|  | ||||
| class SecondarySkill; | ||||
| class Skill; | ||||
|  | ||||
| class DLL_LINKAGE SkillService : public EntityServiceT<SecondarySkill, Skill> | ||||
| { | ||||
| public: | ||||
| }; | ||||
							
								
								
									
										15
									
								
								include/vcmi/Team.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								include/vcmi/Team.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| /* | ||||
|  * Team.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
							
								
								
									
										13
									
								
								include/vcmi/events/AdventureEvents.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								include/vcmi/events/AdventureEvents.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| /* | ||||
|  * AdventureEvents.h, 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 | ||||
|  * | ||||
|  */ | ||||
| #pragma once | ||||
|  | ||||
| #include "ObjectVisitEnded.h" | ||||
| #include "ObjectVisitStarted.h" | ||||
							
								
								
									
										45
									
								
								include/vcmi/events/ApplyDamage.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								include/vcmi/events/ApplyDamage.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| /* | ||||
|  * ApplyDamage.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "Event.h" | ||||
| #include "SubscriptionRegistry.h" | ||||
|  | ||||
| struct BattleStackAttacked; | ||||
|  | ||||
| namespace battle | ||||
| { | ||||
| 	class Unit; | ||||
| } | ||||
|  | ||||
| namespace events | ||||
| { | ||||
|  | ||||
| class DLL_LINKAGE ApplyDamage : public Event | ||||
| { | ||||
| public: | ||||
| 	using Sub = SubscriptionRegistry<ApplyDamage>; | ||||
|  | ||||
| 	using PreHandler = Sub::PreHandler; | ||||
| 	using PostHandler = Sub::PostHandler; | ||||
| 	using ExecHandler = Sub::ExecHandler; | ||||
|  | ||||
| 	static Sub * getRegistry(); | ||||
|  | ||||
| 	virtual int64_t getInitalDamage() const = 0; | ||||
| 	virtual int64_t getDamage() const = 0; | ||||
| 	virtual void setDamage(int64_t value) = 0; | ||||
| 	virtual const battle::Unit * getTarget() const = 0; | ||||
|  | ||||
| 	friend class SubscriptionRegistry<ApplyDamage>; | ||||
| }; | ||||
|  | ||||
| } | ||||
							
								
								
									
										13
									
								
								include/vcmi/events/BattleEvents.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								include/vcmi/events/BattleEvents.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| /* | ||||
|  * BattleEvents.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "ApplyDamage.h" | ||||
							
								
								
									
										29
									
								
								include/vcmi/events/Event.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								include/vcmi/events/Event.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| /* | ||||
|  * Event.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| namespace events | ||||
| { | ||||
|  | ||||
| class EventBus; | ||||
|  | ||||
| template <typename T> | ||||
| class SubscriptionRegistry; | ||||
|  | ||||
| class DLL_LINKAGE Event | ||||
| { | ||||
| public: | ||||
| 	virtual bool isEnabled() const = 0; | ||||
|  | ||||
| }; | ||||
|  | ||||
| } | ||||
|  | ||||
							
								
								
									
										44
									
								
								include/vcmi/events/EventBus.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								include/vcmi/events/EventBus.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| /* | ||||
|  * EventBus.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "SubscriptionRegistry.h" | ||||
|  | ||||
| class Environment; | ||||
|  | ||||
| namespace events | ||||
| { | ||||
|  | ||||
| class DLL_LINKAGE EventBus : public boost::noncopyable | ||||
| { | ||||
| public: | ||||
| 	template <typename E> | ||||
| 	std::unique_ptr<EventSubscription> subscribeBefore(typename E::PreHandler && cb) | ||||
| 	{ | ||||
| 		auto registry = E::getRegistry(); | ||||
| 		return registry->subscribeBefore(this, std::move(cb)); | ||||
| 	} | ||||
|  | ||||
| 	template <typename E> | ||||
| 	std::unique_ptr<EventSubscription> subscribeAfter(typename E::PostHandler && cb) | ||||
| 	{ | ||||
| 		auto registry = E::getRegistry(); | ||||
| 		return registry->subscribeAfter(this, std::move(cb)); | ||||
| 	} | ||||
|  | ||||
| 	template <typename E> | ||||
| 	void executeEvent(E & event, const typename E::ExecHandler & execHandler = typename E::ExecHandler()) const | ||||
| 	{ | ||||
| 		auto registry = E::getRegistry(); | ||||
| 		registry->executeEvent(this, event, execHandler); | ||||
| 	} | ||||
| }; | ||||
| } | ||||
							
								
								
									
										35
									
								
								include/vcmi/events/GameResumed.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								include/vcmi/events/GameResumed.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| /* | ||||
|  * GameResumed.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "Event.h" | ||||
| #include "SubscriptionRegistry.h" | ||||
|  | ||||
| namespace events | ||||
| { | ||||
|  | ||||
| class DLL_LINKAGE GameResumed : public Event | ||||
| { | ||||
| public: | ||||
| 	using Sub = SubscriptionRegistry<GameResumed>; | ||||
|  | ||||
| 	using PreHandler = Sub::PreHandler; | ||||
| 	using PostHandler = Sub::PostHandler; | ||||
| 	using ExecHandler = Sub::ExecHandler; | ||||
|  | ||||
| 	static Sub * getRegistry(); | ||||
|  | ||||
| 	static void defaultExecute(const EventBus * bus); | ||||
|  | ||||
| 	friend class SubscriptionRegistry<GameResumed>; | ||||
| }; | ||||
|  | ||||
| } | ||||
							
								
								
									
										15
									
								
								include/vcmi/events/GenericEvents.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								include/vcmi/events/GenericEvents.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| /* | ||||
|  * GenericEvents.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "GameResumed.h" | ||||
| #include "PlayerGotTurn.h" | ||||
| #include "TurnStarted.h" | ||||
							
								
								
									
										40
									
								
								include/vcmi/events/ObjectVisitEnded.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								include/vcmi/events/ObjectVisitEnded.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| /* | ||||
|  * ObjectVisitEnded.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "Event.h" | ||||
| #include "SubscriptionRegistry.h" | ||||
|  | ||||
| class PlayerColor; | ||||
| class ObjectInstanceID; | ||||
|  | ||||
| namespace events | ||||
| { | ||||
|  | ||||
| class DLL_LINKAGE ObjectVisitEnded : public Event | ||||
| { | ||||
| public: | ||||
| 	using Sub = SubscriptionRegistry<ObjectVisitEnded>; | ||||
| 	using PreHandler = Sub::PreHandler; | ||||
| 	using PostHandler = Sub::PostHandler; | ||||
| 	using ExecHandler = Sub::ExecHandler; | ||||
|  | ||||
| 	virtual PlayerColor getPlayer() const = 0; | ||||
| 	virtual ObjectInstanceID getHero() const = 0; | ||||
|  | ||||
| 	static Sub * getRegistry(); | ||||
| 	static void defaultExecute(const EventBus * bus, const ExecHandler & execHandler, | ||||
| 		const PlayerColor & player, const ObjectInstanceID & heroId); | ||||
|  | ||||
| 	friend class SubscriptionRegistry<ObjectVisitEnded>; | ||||
| }; | ||||
|  | ||||
| } | ||||
							
								
								
									
										43
									
								
								include/vcmi/events/ObjectVisitStarted.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								include/vcmi/events/ObjectVisitStarted.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| /* | ||||
|  * ObjectVisitStarted.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "Event.h" | ||||
| #include "SubscriptionRegistry.h" | ||||
|  | ||||
| class PlayerColor; | ||||
| class ObjectInstanceID; | ||||
|  | ||||
| namespace events | ||||
| { | ||||
|  | ||||
| class DLL_LINKAGE ObjectVisitStarted : public Event | ||||
| { | ||||
| public: | ||||
| 	using Sub = SubscriptionRegistry<ObjectVisitStarted>; | ||||
| 	using PreHandler = Sub::PreHandler; | ||||
| 	using PostHandler = Sub::PostHandler; | ||||
| 	using ExecHandler = Sub::ExecHandler; | ||||
|  | ||||
| 	virtual PlayerColor getPlayer() const = 0; | ||||
| 	virtual ObjectInstanceID getHero() const = 0; | ||||
| 	virtual ObjectInstanceID getObject() const = 0; | ||||
|  | ||||
| 	virtual void setEnabled(bool enable) = 0; | ||||
|  | ||||
| 	static Sub * getRegistry(); | ||||
| 	static void defaultExecute(const EventBus * bus, const ExecHandler & execHandler, | ||||
| 		const PlayerColor & player, const ObjectInstanceID & heroId, const ObjectInstanceID & objId); | ||||
|  | ||||
| 	friend class SubscriptionRegistry<ObjectVisitStarted>; | ||||
| }; | ||||
|  | ||||
| } | ||||
							
								
								
									
										41
									
								
								include/vcmi/events/PlayerGotTurn.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								include/vcmi/events/PlayerGotTurn.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| /* | ||||
|  * PlayerGotTurn.h, 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 | ||||
|  * | ||||
|  */ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "Event.h" | ||||
| #include "SubscriptionRegistry.h" | ||||
|  | ||||
| class PlayerColor; | ||||
|  | ||||
| namespace events | ||||
| { | ||||
|  | ||||
| class DLL_LINKAGE PlayerGotTurn : public Event | ||||
| { | ||||
| public: | ||||
| 	using Sub = SubscriptionRegistry<PlayerGotTurn>; | ||||
| 	using PreHandler = Sub::PreHandler; | ||||
| 	using PostHandler = Sub::PostHandler; | ||||
| 	using ExecHandler = Sub::ExecHandler; | ||||
|  | ||||
| 	static Sub * getRegistry(); | ||||
| 	static void defaultExecute(const EventBus * bus, const ExecHandler & execHandler, PlayerColor & player); | ||||
|  | ||||
| 	virtual PlayerColor getPlayer() const = 0; | ||||
| 	virtual void setPlayer(const PlayerColor & value) = 0; | ||||
|  | ||||
| 	virtual int32_t getPlayerIndex() const = 0; | ||||
| 	virtual void setPlayerIndex(int32_t value) = 0; | ||||
|  | ||||
| 	friend class SubscriptionRegistry<PlayerGotTurn>; | ||||
| }; | ||||
|  | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user