aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.World/TargetGoal.cpp
blob: 8f6eaa47e4484bf7a22c34c4a51427d6e707275a (plain)
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
#include "stdafx.h"
#include "net.minecraft.world.entity.ai.navigation.h"
#include "net.minecraft.world.entity.ai.sensing.h"
#include "net.minecraft.world.entity.h"
#include "net.minecraft.world.entity.animal.h"
#include "net.minecraft.world.entity.player.h"
#include "net.minecraft.world.level.pathfinder.h"
#include "net.minecraft.world.phys.h"
#include "TargetGoal.h"

void TargetGoal::_init(Mob *mob, float within, bool mustSee, bool mustReach)
{
	reachCache = EmptyReachCache;
	reachCacheTime = 0;
	unseenTicks = 0;

	this->mob = mob;
	this->within = within;
	this->mustSee = mustSee;
	this->mustReach = mustReach;
}

TargetGoal::TargetGoal(Mob *mob, float within, bool mustSee)
{
	_init(mob, within, mustSee, false);
}

TargetGoal::TargetGoal(Mob *mob, float within, bool mustSee, bool mustReach)
{
	_init(mob,within,mustSee,mustReach);
}

bool TargetGoal::canContinueToUse()
{
	std::shared_ptr<Mob> target = mob->getTarget();
	if (target == NULL) return false;
	if (!target->isAlive()) return false;
	if (mob->distanceToSqr(target) > within * within) return false;
	if (mustSee)
	{
		if (mob->getSensing()->canSee(target))
		{
			unseenTicks = 0;
		}
		else
		{
			if (++unseenTicks > UnseenMemoryTicks) return false;
		}
	}
	return true;
}

void TargetGoal::start()
{
	reachCache = EmptyReachCache;
	reachCacheTime = 0;
	unseenTicks = 0;
}

void TargetGoal::stop()
{
	mob->setTarget(nullptr);
}

bool TargetGoal::canAttack(std::shared_ptr<Mob> target, bool allowInvulnerable)
{
	if (target == NULL) return false;
	if (target == mob->shared_from_this()) return false;
	if (!target->isAlive()) return false;
	if (!mob->canAttackType(target->GetType())) return false;

	std::shared_ptr<TamableAnimal> tamableAnimal = std::dynamic_pointer_cast<TamableAnimal>(mob->shared_from_this());
	if (tamableAnimal != NULL && tamableAnimal->isTame())
	{
		std::shared_ptr<TamableAnimal> tamableTarget = std::dynamic_pointer_cast<TamableAnimal>(target);
		if (tamableTarget != NULL && tamableTarget->isTame()) return false;
		if (target == tamableAnimal->getOwner()) return false;
	}
	else if (std::dynamic_pointer_cast<Player>(target) != NULL)
	{
		if (!allowInvulnerable && (std::dynamic_pointer_cast<Player>(target))->abilities.invulnerable) return false;
	}

	if (!mob->isWithinRestriction(Mth::floor(target->x), Mth::floor(target->y), Mth::floor(target->z))) return false;

	if (mustSee && !mob->getSensing()->canSee(target)) return false;

	if (mustReach)
	{
		if (--reachCacheTime <= 0) reachCache = EmptyReachCache;
		if (reachCache == EmptyReachCache) reachCache = canReach(target) ? CanReachCache : CantReachCache;
		if (reachCache == CantReachCache) return false;
	}

	return true;
}

bool TargetGoal::canReach(std::shared_ptr<Mob> target)
{
	reachCacheTime = 10 + mob->getRandom()->nextInt(5);
	Path *path = mob->getNavigation()->createPath(target);
	if (path == NULL) return false;
	Node *last = path->last();
	if (last == NULL)
	{
		delete path;
		return false;
	}
	int xx = last->x - Mth::floor(target->x);
	int zz = last->z - Mth::floor(target->z);
	delete path;
	return xx * xx + zz * zz <= 1.5 * 1.5;
}