| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 | 
							- /*
 
-  * Clone.cpp, 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
 
-  *
 
-  */
 
- #include "StdInc.h"
 
- #include "Clone.h"
 
- #include "Registry.h"
 
- #include "../ISpellMechanics.h"
 
- #include "../../battle/CBattleInfoCallback.h"
 
- #include "../../battle/IBattleState.h"
 
- #include "../../battle/CUnitState.h"
 
- #include "../../networkPacks/PacksForClientBattle.h"
 
- #include "../../networkPacks/SetStackEffect.h"
 
- #include "../../serializer/JsonSerializeFormat.h"
 
- VCMI_LIB_NAMESPACE_BEGIN
 
- namespace spells
 
- {
 
- namespace effects
 
- {
 
- void Clone::apply(ServerCallback * server, const Mechanics * m, const EffectTarget & target) const
 
- {
 
- 	for(const Destination & dest : target)
 
- 	{
 
- 		const battle::Unit * clonedStack = dest.unitValue;
 
- 		//we shall have all targets to be stacks
 
- 		if(!clonedStack)
 
- 		{
 
- 			server->complain("No target stack to clone! Invalid effect target transformation.");
 
- 			continue;
 
- 		}
 
- 		//should not happen, but in theory we might have stack took damage from other effects
 
- 		if(clonedStack->getCount() < 1)
 
- 			continue;
 
- 		auto hex = m->battle()->getAvailableHex(clonedStack->creatureId(), m->casterSide, clonedStack->getPosition());
 
- 		if(!hex.isValid())
 
- 		{
 
- 			server->complain("No place to put new clone!");
 
- 			break;
 
- 		}
 
- 		auto unitId = m->battle()->battleNextUnitId();
 
- 		battle::UnitInfo info;
 
- 		info.id = unitId;
 
- 		info.count = clonedStack->getCount();
 
- 		info.type = clonedStack->creatureId();
 
- 		info.side = m->casterSide;
 
- 		info.position = hex;
 
- 		info.summoned = true;
 
- 		BattleUnitsChanged pack;
 
- 		pack.battleID = m->battle()->getBattle()->getBattleID();
 
- 		pack.changedStacks.emplace_back(info.id, UnitChanges::EOperation::ADD);
 
- 		info.save(pack.changedStacks.back().data);
 
- 		server->apply(&pack);
 
- 		//TODO: use BattleUnitsChanged with UPDATE operation
 
- 		BattleUnitsChanged cloneFlags;
 
- 		cloneFlags.battleID = m->battle()->getBattle()->getBattleID();
 
- 		const auto *cloneUnit = m->battle()->battleGetUnitByID(unitId);
 
- 		if(!cloneUnit)
 
- 		{
 
- 			server->complain("[Internal error] Cloned unit missing.");
 
- 			continue;
 
- 		}
 
- 		auto cloneState = cloneUnit->acquireState();
 
- 		cloneState->cloned = true;
 
- 		cloneFlags.changedStacks.emplace_back(cloneState->unitId(), UnitChanges::EOperation::RESET_STATE);
 
- 		cloneState->save(cloneFlags.changedStacks.back().data);
 
- 		auto originalState = clonedStack->acquireState();
 
- 		originalState->cloneID = unitId;
 
- 		cloneFlags.changedStacks.emplace_back(originalState->unitId(), UnitChanges::EOperation::RESET_STATE);
 
- 		originalState->save(cloneFlags.changedStacks.back().data);
 
- 		server->apply(&cloneFlags);
 
- 		SetStackEffect sse;
 
- 		sse.battleID = m->battle()->getBattle()->getBattleID();
 
- 		Bonus lifeTimeMarker(BonusDuration::N_TURNS, BonusType::NONE, BonusSource::SPELL_EFFECT, 0, BonusSourceID(SpellID(SpellID::CLONE))); //TODO: use special bonus type
 
- 		lifeTimeMarker.turnsRemain = m->getEffectDuration();
 
- 		std::vector<Bonus> buffer;
 
- 		buffer.push_back(lifeTimeMarker);
 
- 		sse.toAdd.emplace_back(unitId, buffer);
 
- 		server->apply(&sse);
 
- 	}
 
- }
 
- bool Clone::isReceptive(const Mechanics * m, const battle::Unit * s) const
 
- {
 
- 	int creLevel = s->creatureLevel();
 
- 	if(creLevel > maxTier)
 
- 		return false;
 
- 	//use default algorithm only if there is no mechanics-related problem
 
- 	return UnitEffect::isReceptive(m, s);
 
- }
 
- bool Clone::isValidTarget(const Mechanics * m, const battle::Unit * s) const
 
- {
 
- 	//can't clone already cloned creature
 
- 	if(s->isClone())
 
- 		return false;
 
- 	//can`t clone if old clone still alive
 
- 	if(s->hasClone())
 
- 		return false;
 
- 	return UnitEffect::isValidTarget(m, s);
 
- }
 
- void Clone::serializeJsonUnitEffect(JsonSerializeFormat & handler)
 
- {
 
- 	handler.serializeInt("maxTier", maxTier);
 
- }
 
- }
 
- }
 
- VCMI_LIB_NAMESPACE_END
 
 
  |