File: RemoveObstacle.cpp

package info (click to toggle)
vcmi 0.99%2Bdfsg%2Bgit20190113.f06c8a87-1
  • links: PTS, VCS
  • area: contrib
  • in suites: buster
  • size: 11,096 kB
  • sloc: cpp: 142,605; sh: 315; objc: 248; makefile: 32; ansic: 28; python: 13
file content (114 lines) | stat: -rw-r--r-- 3,083 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*
 * RemoveObstacle.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 "RemoveObstacle.h"

#include "Registry.h"
#include "../ISpellMechanics.h"

#include "../../NetPacks.h"
#include "../../battle/IBattleState.h"
#include "../../battle/CBattleInfoCallback.h"
#include "../../battle/CObstacleInstance.h"
#include "../../serializer/JsonSerializeFormat.h"

static const std::string EFFECT_NAME = "core:removeObstacle";

namespace spells
{
namespace effects
{

VCMI_REGISTER_SPELL_EFFECT(RemoveObstacle, EFFECT_NAME);

RemoveObstacle::RemoveObstacle()
	: LocationEffect(),
	removeAbsolute(false),
	removeUsual(false),
	removeAllSpells(false)
{
}

RemoveObstacle::~RemoveObstacle() = default;

bool RemoveObstacle::applicable(Problem & problem, const Mechanics * m) const
{
	return !getTargets(m, EffectTarget(), true).empty();
}

bool RemoveObstacle::applicable(Problem & problem, const Mechanics * m, const EffectTarget & target) const
{
	return !getTargets(m, target, false).empty();
}

void RemoveObstacle::apply(BattleStateProxy * battleState, RNG & rng, const Mechanics * m, const EffectTarget & target) const
{
	BattleObstaclesChanged pack;

	for(const auto & obstacle : getTargets(m, target, false))
		pack.changes.emplace_back(obstacle->uniqueID, BattleChanges::EOperation::REMOVE);

	if(!pack.changes.empty())
		battleState->apply(&pack);
}

void RemoveObstacle::serializeJsonEffect(JsonSerializeFormat & handler)
{
	handler.serializeBool("removeAbsolute", removeAbsolute, false);
	handler.serializeBool("removeUsual", removeUsual, false);
	handler.serializeBool("removeAllSpells", removeAllSpells, false);
	handler.serializeIdArray("removeSpells", removeSpells);
}

bool RemoveObstacle::canRemove(const CObstacleInstance * obstacle) const
{
	if(removeAbsolute && obstacle->obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE)
		return true;
	if(removeUsual && obstacle->obstacleType == CObstacleInstance::USUAL)
		return true;
	auto spellObstacle = dynamic_cast<const SpellCreatedObstacle *>(obstacle);

	if(removeAllSpells && spellObstacle)
		return true;

	if(spellObstacle && !removeSpells.empty())
	{
		if(vstd::contains(removeSpells, SpellID(spellObstacle->ID)))
			return true;
	}

	return false;
}

std::set<const CObstacleInstance *> RemoveObstacle::getTargets(const Mechanics * m, const EffectTarget & target, bool alwaysMassive) const
{
	std::set<const CObstacleInstance *> possibleTargets;
	if(m->isMassive() || alwaysMassive)
	{
		for(const auto & obstacle : m->cb->battleGetAllObstacles())
			if(canRemove(obstacle.get()))
				possibleTargets.insert(obstacle.get());
	}
	else
	{
		for(const auto & destination : target)
			if(destination.hexValue.isValid())
				for(const auto & obstacle : m->cb->battleGetAllObstaclesOnPos(destination.hexValue, false))
					if(canRemove(obstacle.get()))
						possibleTargets.insert(obstacle.get());
	}

	return possibleTargets;
}


}
}