mirror of
https://github.com/4jcraft/4jcraft.git
synced 2026-07-14 11:37:04 +00:00
TU19: merge Minecraft.World/AI
This commit is contained in:
parent
4c30ef1e62
commit
7973172ae8
14
Minecraft.World/AI/Attributes/Attribute.cpp
Normal file
14
Minecraft.World/AI/Attributes/Attribute.cpp
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#include "../../Platform/stdafx.h"
|
||||
#include "Attribute.h"
|
||||
|
||||
const int Attribute::AttributeNames[] = {
|
||||
IDS_ATTRIBUTE_NAME_GENERIC_MAXHEALTH,
|
||||
IDS_ATTRIBUTE_NAME_GENERIC_FOLLOWRANGE,
|
||||
IDS_ATTRIBUTE_NAME_GENERIC_KNOCKBACKRESISTANCE,
|
||||
IDS_ATTRIBUTE_NAME_GENERIC_MOVEMENTSPEED,
|
||||
IDS_ATTRIBUTE_NAME_GENERIC_ATTACKDAMAGE,
|
||||
IDS_ATTRIBUTE_NAME_HORSE_JUMPSTRENGTH,
|
||||
IDS_ATTRIBUTE_NAME_ZOMBIE_SPAWNREINFORCEMENTS,
|
||||
};
|
||||
|
||||
int Attribute::getName(eATTRIBUTE_ID id) { return AttributeNames[id]; }
|
||||
73
Minecraft.World/AI/Attributes/Attribute.h
Normal file
73
Minecraft.World/AI/Attributes/Attribute.h
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
#pragma once
|
||||
class AttributeModifier;
|
||||
|
||||
// 4J: This ID is serialised into save data so new attributes must always be
|
||||
// added after existing ones
|
||||
enum eATTRIBUTE_ID {
|
||||
// 1.6.4
|
||||
eAttributeId_GENERIC_MAXHEALTH,
|
||||
eAttributeId_GENERIC_FOLLOWRANGE,
|
||||
eAttributeId_GENERIC_KNOCKBACKRESISTANCE,
|
||||
eAttributeId_GENERIC_MOVEMENTSPEED,
|
||||
eAttributeId_GENERIC_ATTACKDAMAGE,
|
||||
eAttributeId_HORSE_JUMPSTRENGTH,
|
||||
eAttributeId_ZOMBIE_SPAWNREINFORCEMENTS,
|
||||
|
||||
// 1.8+
|
||||
// New attributes go here
|
||||
|
||||
eAttributeId_COUNT
|
||||
};
|
||||
|
||||
class Attribute {
|
||||
public:
|
||||
static const int MAX_NAME_LENGTH = 64;
|
||||
|
||||
/**
|
||||
* 4J: Changed this from a std::string name to an ID
|
||||
* Gets the ID of this attribute, for serialization.
|
||||
*
|
||||
* @return Name of this attribute.
|
||||
*/
|
||||
virtual eATTRIBUTE_ID getId() = 0;
|
||||
|
||||
/**
|
||||
* Sanitizes an attribute value, making sure it's not out of range and is an
|
||||
* acceptable amount.
|
||||
*
|
||||
*
|
||||
* @param value Value to sanitize.
|
||||
* @return Sanitized value, safe for use.
|
||||
*/
|
||||
virtual double sanitizeValue(double value) = 0;
|
||||
|
||||
/**
|
||||
* Get the default value of this attribute, to be used upon creation.
|
||||
*
|
||||
* @return Default value.
|
||||
*/
|
||||
virtual double getDefaultValue() = 0;
|
||||
|
||||
/**
|
||||
* Checks if this attribute should be synced to the client.
|
||||
*
|
||||
* Attributes should be serverside only unless the client needs to know
|
||||
* about it.
|
||||
*
|
||||
* @return True if the client should know about this attribute.
|
||||
*/
|
||||
virtual bool isClientSyncable() = 0;
|
||||
|
||||
// 4J: Added to retrieve std::string ID for attribute
|
||||
static int getName(eATTRIBUTE_ID id);
|
||||
|
||||
protected:
|
||||
static const int AttributeNames[];
|
||||
};
|
||||
|
||||
#ifdef __ORBIS__
|
||||
typedef std::unordered_map<eATTRIBUTE_ID, AttributeModifier*, std::hash<int>>
|
||||
attrAttrModMap;
|
||||
#else
|
||||
typedef std::unordered_map<eATTRIBUTE_ID, AttributeModifier*> attrAttrModMap;
|
||||
#endif
|
||||
24
Minecraft.World/AI/Attributes/AttributeInstance.h
Normal file
24
Minecraft.World/AI/Attributes/AttributeInstance.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
#include "AttributeModifier.h"
|
||||
|
||||
class AttributeInstance {
|
||||
public:
|
||||
virtual ~AttributeInstance() {}
|
||||
|
||||
virtual Attribute* getAttribute() = 0;
|
||||
virtual double getBaseValue() = 0;
|
||||
virtual void setBaseValue(double baseValue) = 0;
|
||||
virtual double getValue() = 0;
|
||||
|
||||
virtual std::unordered_set<AttributeModifier*>* getModifiers(
|
||||
int operation) = 0;
|
||||
virtual void getModifiers(
|
||||
std::unordered_set<AttributeModifier*>& result) = 0;
|
||||
virtual AttributeModifier* getModifier(eMODIFIER_ID id) = 0;
|
||||
virtual void addModifiers(
|
||||
std::unordered_set<AttributeModifier*>* modifiers) = 0;
|
||||
virtual void addModifier(AttributeModifier* modifier) = 0;
|
||||
virtual void removeModifier(AttributeModifier* modifier) = 0;
|
||||
virtual void removeModifier(eMODIFIER_ID id) = 0;
|
||||
virtual void removeModifiers() = 0;
|
||||
};
|
||||
107
Minecraft.World/AI/Attributes/AttributeModifier.cpp
Normal file
107
Minecraft.World/AI/Attributes/AttributeModifier.cpp
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
#include "../../Platform/stdafx.h"
|
||||
|
||||
#include "AttributeModifier.h"
|
||||
#include "../../Util/HtmlString.h"
|
||||
|
||||
void AttributeModifier::_init(eMODIFIER_ID id, const std::wstring name,
|
||||
double amount, int operation) {
|
||||
assert(operation < TOTAL_OPERATIONS);
|
||||
this->amount = amount;
|
||||
this->operation = operation;
|
||||
this->name = name;
|
||||
this->id = id;
|
||||
this->serialize = true;
|
||||
}
|
||||
|
||||
AttributeModifier::AttributeModifier(double amount, int operation) {
|
||||
// Create an anonymous attribute
|
||||
_init(eModifierId_ANONYMOUS, name, amount, operation);
|
||||
}
|
||||
|
||||
AttributeModifier::AttributeModifier(eMODIFIER_ID id, double amount,
|
||||
int operation) {
|
||||
_init(id, name, amount, operation);
|
||||
|
||||
// Validate.notEmpty(name, "Modifier name cannot be empty");
|
||||
// Validate.inclusiveBetween(0, TOTAL_OPERATIONS - 1, operation, "Invalid
|
||||
// operation");
|
||||
}
|
||||
|
||||
eMODIFIER_ID AttributeModifier::getId() { return id; }
|
||||
|
||||
std::wstring AttributeModifier::getName() { return name; }
|
||||
|
||||
int AttributeModifier::getOperation() { return operation; }
|
||||
|
||||
double AttributeModifier::getAmount() { return amount; }
|
||||
|
||||
bool AttributeModifier::isSerializable() { return serialize; }
|
||||
|
||||
AttributeModifier* AttributeModifier::setSerialize(bool serialize) {
|
||||
this->serialize = serialize;
|
||||
return this;
|
||||
}
|
||||
|
||||
bool AttributeModifier::equals(AttributeModifier* modifier) {
|
||||
if (this == modifier) return true;
|
||||
if (modifier == NULL)
|
||||
return false; //|| getClass() != o.getClass()) return false;
|
||||
|
||||
if (id != modifier->id) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::wstring AttributeModifier::toString() {
|
||||
return L"";
|
||||
|
||||
/*return L"AttributeModifier{" +
|
||||
L"amount=" + amount +
|
||||
L", operation=" + operation +
|
||||
L", name='" + name + '\'' +
|
||||
L", id=" + id +
|
||||
L", serialize=" + serialize +
|
||||
L'}';*/
|
||||
}
|
||||
|
||||
HtmlString AttributeModifier::getHoverText(eATTRIBUTE_ID attribute) {
|
||||
double amount = getAmount();
|
||||
double displayAmount;
|
||||
|
||||
if (getOperation() == AttributeModifier::OPERATION_MULTIPLY_BASE ||
|
||||
getOperation() == AttributeModifier::OPERATION_MULTIPLY_TOTAL) {
|
||||
displayAmount = getAmount() * 100.0f;
|
||||
} else {
|
||||
displayAmount = getAmount();
|
||||
}
|
||||
|
||||
eMinecraftColour color;
|
||||
|
||||
if (amount > 0) {
|
||||
color = eHTMLColor_9;
|
||||
} else if (amount < 0) {
|
||||
displayAmount *= -1;
|
||||
color = eHTMLColor_c;
|
||||
}
|
||||
|
||||
bool percentage = false;
|
||||
switch (getOperation()) {
|
||||
case AttributeModifier::OPERATION_ADDITION:
|
||||
percentage = false;
|
||||
break;
|
||||
case AttributeModifier::OPERATION_MULTIPLY_BASE:
|
||||
case AttributeModifier::OPERATION_MULTIPLY_TOTAL:
|
||||
percentage = true;
|
||||
break;
|
||||
default:
|
||||
// No other operations
|
||||
assert(0);
|
||||
}
|
||||
|
||||
wchar_t formatted[256];
|
||||
swprintf(formatted, 256, L"%ls%d%ls %ls", (amount > 0 ? L"+" : L"-"),
|
||||
(int)displayAmount, (percentage ? L"%" : L""),
|
||||
app.GetString(Attribute::getName(attribute)));
|
||||
|
||||
return HtmlString(formatted, color);
|
||||
}
|
||||
74
Minecraft.World/AI/Attributes/AttributeModifier.h
Normal file
74
Minecraft.World/AI/Attributes/AttributeModifier.h
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
4J - Both modifier uuid and name have been replaced by an id enum. Note that we
|
||||
have special value "eModifierId_ANONYMOUS" for attribute modifiers that
|
||||
previously didn't have a fixed UUID and are never removed.
|
||||
|
||||
To all intents and purposes anonymous modifiers don't have an ID and so are
|
||||
handled differently in some cases, for instance:
|
||||
1. You can have multiple modifiers with the anonymous ID on a single
|
||||
attribute instance
|
||||
2. Anonymous modifiers can't be removed from attribute instance by ID
|
||||
|
||||
IMPORTANT: Saved out to file so don't change order. All new values should be
|
||||
added at the end.
|
||||
*/
|
||||
|
||||
class HtmlString;
|
||||
|
||||
enum eMODIFIER_ID {
|
||||
eModifierId_ANONYMOUS = 0,
|
||||
|
||||
eModifierId_ITEM_BASEDAMAGE,
|
||||
|
||||
eModifierId_MOB_FLEEING,
|
||||
eModifierId_MOB_SPRINTING,
|
||||
|
||||
eModifierId_MOB_ENDERMAN_ATTACKSPEED,
|
||||
eModifierId_MOB_PIG_ATTACKSPEED,
|
||||
eModifierId_MOB_WITCH_DRINKSPEED,
|
||||
eModifierId_MOB_ZOMBIE_BABYSPEED,
|
||||
|
||||
eModifierId_POTION_DAMAGEBOOST,
|
||||
eModifierId_POTION_HEALTHBOOST,
|
||||
eModifierId_POTION_MOVESPEED,
|
||||
eModifierId_POTION_MOVESLOWDOWN,
|
||||
eModifierId_POTION_WEAKNESS,
|
||||
|
||||
eModifierId_COUNT,
|
||||
};
|
||||
|
||||
class AttributeModifier {
|
||||
public:
|
||||
static const int OPERATION_ADDITION = 0;
|
||||
static const int OPERATION_MULTIPLY_BASE = 1;
|
||||
static const int OPERATION_MULTIPLY_TOTAL = 2;
|
||||
static const int TOTAL_OPERATIONS = 3;
|
||||
|
||||
private:
|
||||
double amount;
|
||||
int operation;
|
||||
std::wstring name;
|
||||
eMODIFIER_ID id;
|
||||
bool serialize;
|
||||
|
||||
void _init(eMODIFIER_ID id, const std::wstring name, double amount,
|
||||
int operation);
|
||||
|
||||
public:
|
||||
AttributeModifier(double amount, int operation);
|
||||
AttributeModifier(eMODIFIER_ID id, double amount, int operation);
|
||||
|
||||
eMODIFIER_ID getId();
|
||||
std::wstring getName();
|
||||
int getOperation();
|
||||
double getAmount();
|
||||
bool isSerializable();
|
||||
AttributeModifier* setSerialize(bool serialize);
|
||||
bool equals(AttributeModifier* modifier);
|
||||
std::wstring toString();
|
||||
HtmlString getHoverText(
|
||||
eATTRIBUTE_ID attribute); // 4J: Added to keep modifier readable
|
||||
// std::string creation in one place
|
||||
};
|
||||
20
Minecraft.World/AI/Attributes/BaseAttribute.cpp
Normal file
20
Minecraft.World/AI/Attributes/BaseAttribute.cpp
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#include "../../Platform/stdafx.h"
|
||||
|
||||
#include "BaseAttribute.h"
|
||||
|
||||
BaseAttribute::BaseAttribute(eATTRIBUTE_ID id, double defaultValue) {
|
||||
this->id = id;
|
||||
this->defaultValue = defaultValue;
|
||||
syncable = false;
|
||||
}
|
||||
|
||||
eATTRIBUTE_ID BaseAttribute::getId() { return id; }
|
||||
|
||||
double BaseAttribute::getDefaultValue() { return defaultValue; }
|
||||
|
||||
bool BaseAttribute::isClientSyncable() { return syncable; }
|
||||
|
||||
BaseAttribute* BaseAttribute::setSyncable(bool syncable) {
|
||||
this->syncable = syncable;
|
||||
return this;
|
||||
}
|
||||
19
Minecraft.World/AI/Attributes/BaseAttribute.h
Normal file
19
Minecraft.World/AI/Attributes/BaseAttribute.h
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include "Attribute.h"
|
||||
|
||||
class BaseAttribute : public Attribute {
|
||||
private:
|
||||
eATTRIBUTE_ID id;
|
||||
double defaultValue;
|
||||
bool syncable;
|
||||
|
||||
protected:
|
||||
BaseAttribute(eATTRIBUTE_ID id, double defaultValue);
|
||||
|
||||
public:
|
||||
virtual eATTRIBUTE_ID getId();
|
||||
virtual double getDefaultValue();
|
||||
virtual bool isClientSyncable();
|
||||
virtual BaseAttribute* setSyncable(bool syncable);
|
||||
};
|
||||
68
Minecraft.World/AI/Attributes/BaseAttributeMap.cpp
Normal file
68
Minecraft.World/AI/Attributes/BaseAttributeMap.cpp
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
#include "../../Platform/stdafx.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.attributes.h"
|
||||
#include "BaseAttributeMap.h"
|
||||
|
||||
BaseAttributeMap::~BaseAttributeMap() {
|
||||
for (AUTO_VAR(it, attributesById.begin()); it != attributesById.end();
|
||||
++it) {
|
||||
delete it->second;
|
||||
}
|
||||
}
|
||||
|
||||
AttributeInstance* BaseAttributeMap::getInstance(Attribute* attribute) {
|
||||
return getInstance(attribute->getId());
|
||||
}
|
||||
|
||||
AttributeInstance* BaseAttributeMap::getInstance(eATTRIBUTE_ID id) {
|
||||
AUTO_VAR(it, attributesById.find(id));
|
||||
if (it != attributesById.end()) {
|
||||
return it->second;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void BaseAttributeMap::getAttributes(std::vector<AttributeInstance*>& atts) {
|
||||
for (AUTO_VAR(it, attributesById.begin()); it != attributesById.end();
|
||||
++it) {
|
||||
atts.push_back(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
void BaseAttributeMap::onAttributeModified(
|
||||
ModifiableAttributeInstance* attributeInstance) {}
|
||||
|
||||
void BaseAttributeMap::removeItemModifiers(std::shared_ptr<ItemInstance> item) {
|
||||
attrAttrModMap* modifiers = item->getAttributeModifiers();
|
||||
|
||||
for (AUTO_VAR(it, modifiers->begin()); it != modifiers->end(); ++it) {
|
||||
AttributeInstance* attribute = getInstance(it->first);
|
||||
AttributeModifier* modifier = it->second;
|
||||
|
||||
if (attribute != NULL) {
|
||||
attribute->removeModifier(modifier);
|
||||
}
|
||||
|
||||
delete modifier;
|
||||
}
|
||||
|
||||
delete modifiers;
|
||||
}
|
||||
|
||||
void BaseAttributeMap::addItemModifiers(std::shared_ptr<ItemInstance> item) {
|
||||
attrAttrModMap* modifiers = item->getAttributeModifiers();
|
||||
|
||||
for (AUTO_VAR(it, modifiers->begin()); it != modifiers->end(); ++it) {
|
||||
AttributeInstance* attribute = getInstance(it->first);
|
||||
AttributeModifier* modifier = it->second;
|
||||
|
||||
if (attribute != NULL) {
|
||||
attribute->removeModifier(modifier);
|
||||
attribute->addModifier(new AttributeModifier(*modifier));
|
||||
}
|
||||
|
||||
delete modifier;
|
||||
}
|
||||
|
||||
delete modifiers;
|
||||
}
|
||||
31
Minecraft.World/AI/Attributes/BaseAttributeMap.h
Normal file
31
Minecraft.World/AI/Attributes/BaseAttributeMap.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
class ModifiableAttributeInstance;
|
||||
|
||||
class BaseAttributeMap {
|
||||
protected:
|
||||
// unordered_map<Attribute *, AttributeInstance *> attributesByObject;
|
||||
#ifdef __ORBIS__
|
||||
std::unordered_map<eATTRIBUTE_ID, AttributeInstance*, std::hash<int> >
|
||||
attributesById;
|
||||
#else
|
||||
std::unordered_map<eATTRIBUTE_ID, AttributeInstance*> attributesById;
|
||||
#endif
|
||||
|
||||
public:
|
||||
virtual ~BaseAttributeMap();
|
||||
|
||||
virtual AttributeInstance* getInstance(Attribute* attribute);
|
||||
virtual AttributeInstance* getInstance(eATTRIBUTE_ID name);
|
||||
|
||||
virtual AttributeInstance* registerAttribute(Attribute* attribute) = 0;
|
||||
|
||||
virtual void getAttributes(std::vector<AttributeInstance*>& atts);
|
||||
virtual void onAttributeModified(
|
||||
ModifiableAttributeInstance* attributeInstance);
|
||||
|
||||
// 4J: Changed these into specialised functions for adding/removing the
|
||||
// modifiers of an item (it's cleaner)
|
||||
virtual void removeItemModifiers(std::shared_ptr<ItemInstance> item);
|
||||
virtual void addItemModifiers(std::shared_ptr<ItemInstance> item);
|
||||
};
|
||||
160
Minecraft.World/AI/Attributes/ModifiableAttributeInstance.cpp
Normal file
160
Minecraft.World/AI/Attributes/ModifiableAttributeInstance.cpp
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
#include "../../Platform/stdafx.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.attributes.h"
|
||||
#include "ModifiableAttributeInstance.h"
|
||||
|
||||
ModifiableAttributeInstance::ModifiableAttributeInstance(
|
||||
BaseAttributeMap* attributeMap, Attribute* attribute) {
|
||||
this->attributeMap = attributeMap;
|
||||
this->attribute = attribute;
|
||||
|
||||
dirty = true;
|
||||
cachedValue = 0.0;
|
||||
|
||||
baseValue = attribute->getDefaultValue();
|
||||
}
|
||||
|
||||
ModifiableAttributeInstance::~ModifiableAttributeInstance() {
|
||||
for (int i = 0; i < AttributeModifier::TOTAL_OPERATIONS; i++) {
|
||||
for (AUTO_VAR(it, modifiers[i].begin()); it != modifiers[i].end();
|
||||
++it) {
|
||||
// Delete all modifiers
|
||||
delete *it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Attribute* ModifiableAttributeInstance::getAttribute() { return attribute; }
|
||||
|
||||
double ModifiableAttributeInstance::getBaseValue() { return baseValue; }
|
||||
|
||||
void ModifiableAttributeInstance::setBaseValue(double baseValue) {
|
||||
if (baseValue == this->getBaseValue()) return;
|
||||
this->baseValue = baseValue;
|
||||
setDirty();
|
||||
}
|
||||
|
||||
// Returns a pointer to an internally managed vector of modifers by operation
|
||||
std::unordered_set<AttributeModifier*>*
|
||||
ModifiableAttributeInstance::getModifiers(int operation) {
|
||||
return &modifiers[operation];
|
||||
}
|
||||
|
||||
// Returns a pointer to a new vector of all modifiers
|
||||
void ModifiableAttributeInstance::getModifiers(
|
||||
std::unordered_set<AttributeModifier*>& result) {
|
||||
for (int i = 0; i < AttributeModifier::TOTAL_OPERATIONS; i++) {
|
||||
std::unordered_set<AttributeModifier*>* opModifiers = &modifiers[i];
|
||||
|
||||
for (AUTO_VAR(it, opModifiers->begin()); it != opModifiers->end();
|
||||
++it) {
|
||||
result.insert(*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AttributeModifier* ModifiableAttributeInstance::getModifier(eMODIFIER_ID id) {
|
||||
AttributeModifier* modifier = NULL;
|
||||
|
||||
AUTO_VAR(it, modifierById.find(id));
|
||||
if (it != modifierById.end()) {
|
||||
modifier = it->second;
|
||||
}
|
||||
|
||||
return modifier;
|
||||
}
|
||||
|
||||
void ModifiableAttributeInstance::addModifiers(
|
||||
std::unordered_set<AttributeModifier*>* modifiers) {
|
||||
for (AUTO_VAR(it, modifiers->begin()); it != modifiers->end(); ++it) {
|
||||
addModifier(*it);
|
||||
}
|
||||
}
|
||||
|
||||
// Add new modifier to attribute instance (takes ownership of modifier)
|
||||
void ModifiableAttributeInstance::addModifier(AttributeModifier* modifier) {
|
||||
// Can't add modifiers with the same ID (unless the modifier is anonymous)
|
||||
if (modifier->getId() != eModifierId_ANONYMOUS &&
|
||||
getModifier(modifier->getId()) != NULL) {
|
||||
assert(0);
|
||||
// throw new IllegalArgumentException("Modifier is already applied on
|
||||
// this attribute!");
|
||||
return;
|
||||
}
|
||||
|
||||
modifiers[modifier->getOperation()].insert(modifier);
|
||||
modifierById[modifier->getId()] = modifier;
|
||||
|
||||
setDirty();
|
||||
}
|
||||
|
||||
void ModifiableAttributeInstance::setDirty() {
|
||||
dirty = true;
|
||||
attributeMap->onAttributeModified(this);
|
||||
}
|
||||
|
||||
void ModifiableAttributeInstance::removeModifier(AttributeModifier* modifier) {
|
||||
for (int i = 0; i < AttributeModifier::TOTAL_OPERATIONS; i++) {
|
||||
for (AUTO_VAR(it, modifiers[i].begin()); it != modifiers[i].end();
|
||||
++it) {
|
||||
if (modifier->equals(*it)) {
|
||||
modifiers[i].erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
modifierById.erase(modifier->getId());
|
||||
|
||||
setDirty();
|
||||
}
|
||||
|
||||
void ModifiableAttributeInstance::removeModifier(eMODIFIER_ID id) {
|
||||
AttributeModifier* modifier = getModifier(id);
|
||||
if (modifier != NULL) removeModifier(modifier);
|
||||
}
|
||||
|
||||
void ModifiableAttributeInstance::removeModifiers() {
|
||||
std::unordered_set<AttributeModifier*> removingModifiers;
|
||||
getModifiers(removingModifiers);
|
||||
|
||||
for (AUTO_VAR(it, removingModifiers.begin()); it != removingModifiers.end();
|
||||
++it) {
|
||||
removeModifier(*it);
|
||||
}
|
||||
}
|
||||
|
||||
double ModifiableAttributeInstance::getValue() {
|
||||
if (dirty) {
|
||||
cachedValue = calculateValue();
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
return cachedValue;
|
||||
}
|
||||
|
||||
double ModifiableAttributeInstance::calculateValue() {
|
||||
double base = getBaseValue();
|
||||
std::unordered_set<AttributeModifier*>* modifiers;
|
||||
|
||||
modifiers = getModifiers(AttributeModifier::OPERATION_ADDITION);
|
||||
for (AUTO_VAR(it, modifiers->begin()); it != modifiers->end(); ++it) {
|
||||
AttributeModifier* modifier = *it;
|
||||
base += modifier->getAmount();
|
||||
}
|
||||
|
||||
double result = base;
|
||||
|
||||
modifiers = getModifiers(AttributeModifier::OPERATION_MULTIPLY_BASE);
|
||||
for (AUTO_VAR(it, modifiers->begin()); it != modifiers->end(); ++it) {
|
||||
AttributeModifier* modifier = *it;
|
||||
result += base * modifier->getAmount();
|
||||
}
|
||||
|
||||
modifiers = getModifiers(AttributeModifier::OPERATION_MULTIPLY_TOTAL);
|
||||
for (AUTO_VAR(it, modifiers->begin()); it != modifiers->end(); ++it) {
|
||||
AttributeModifier* modifier = *it;
|
||||
result *= 1 + modifier->getAmount();
|
||||
}
|
||||
|
||||
return attribute->sanitizeValue(result);
|
||||
}
|
||||
41
Minecraft.World/AI/Attributes/ModifiableAttributeInstance.h
Normal file
41
Minecraft.World/AI/Attributes/ModifiableAttributeInstance.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
#pragma once
|
||||
|
||||
#include "AttributeInstance.h"
|
||||
|
||||
class ModifiableAttributeInstance : public AttributeInstance {
|
||||
private:
|
||||
BaseAttributeMap* attributeMap;
|
||||
Attribute* attribute;
|
||||
std::unordered_set<AttributeModifier*>
|
||||
modifiers[AttributeModifier::TOTAL_OPERATIONS];
|
||||
std::unordered_map<unsigned int, AttributeModifier*> modifierById;
|
||||
double baseValue;
|
||||
bool dirty;
|
||||
double cachedValue;
|
||||
|
||||
public:
|
||||
ModifiableAttributeInstance(BaseAttributeMap* attributeMap,
|
||||
Attribute* attribute);
|
||||
~ModifiableAttributeInstance();
|
||||
|
||||
Attribute* getAttribute();
|
||||
double getBaseValue();
|
||||
void setBaseValue(double baseValue);
|
||||
std::unordered_set<AttributeModifier*>* getModifiers(int operation);
|
||||
void getModifiers(std::unordered_set<AttributeModifier*>& result);
|
||||
AttributeModifier* getModifier(eMODIFIER_ID id);
|
||||
void addModifiers(std::unordered_set<AttributeModifier*>* modifiers);
|
||||
void addModifier(AttributeModifier* modifier);
|
||||
|
||||
private:
|
||||
void setDirty();
|
||||
|
||||
public:
|
||||
void removeModifier(AttributeModifier* modifier);
|
||||
void removeModifier(eMODIFIER_ID id);
|
||||
void removeModifiers();
|
||||
double getValue();
|
||||
|
||||
private:
|
||||
double calculateValue();
|
||||
};
|
||||
28
Minecraft.World/AI/Attributes/RangedAttribute.cpp
Normal file
28
Minecraft.World/AI/Attributes/RangedAttribute.cpp
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#include "../../Platform/stdafx.h"
|
||||
|
||||
#include "RangedAttribute.h"
|
||||
|
||||
RangedAttribute::RangedAttribute(eATTRIBUTE_ID id, double defaultValue,
|
||||
double minValue, double maxValue)
|
||||
: BaseAttribute(id, defaultValue) {
|
||||
this->minValue = minValue;
|
||||
this->maxValue = maxValue;
|
||||
|
||||
// if (minValue > maxValue) throw new IllegalArgumentException("Minimum
|
||||
// value cannot be bigger than maximum value!"); if (defaultValue <
|
||||
// minValue) throw new IllegalArgumentException("Default value cannot be
|
||||
// lower than minimum value!"); if (defaultValue > maxValue) throw new
|
||||
// IllegalArgumentException("Default value cannot be bigger than maximum
|
||||
// value!");
|
||||
}
|
||||
|
||||
double RangedAttribute::getMinValue() { return minValue; }
|
||||
|
||||
double RangedAttribute::getMaxValue() { return maxValue; }
|
||||
|
||||
double RangedAttribute::sanitizeValue(double value) {
|
||||
if (value < minValue) value = minValue;
|
||||
if (value > maxValue) value = maxValue;
|
||||
|
||||
return value;
|
||||
}
|
||||
21
Minecraft.World/AI/Attributes/RangedAttribute.h
Normal file
21
Minecraft.World/AI/Attributes/RangedAttribute.h
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include "BaseAttribute.h"
|
||||
|
||||
class RangedAttribute : public BaseAttribute {
|
||||
private:
|
||||
double minValue;
|
||||
double maxValue;
|
||||
|
||||
public:
|
||||
RangedAttribute(eATTRIBUTE_ID id, double defaultValue, double minValue,
|
||||
double maxValue);
|
||||
|
||||
double getMinValue();
|
||||
double getMaxValue();
|
||||
double sanitizeValue(double value);
|
||||
|
||||
// 4J: Removed legacy name
|
||||
// RangedAttribute *importLegacyName(const std::wstring &name);
|
||||
// std::wstring getImportLegacyName();
|
||||
};
|
||||
82
Minecraft.World/AI/Attributes/ServersideAttributeMap.cpp
Normal file
82
Minecraft.World/AI/Attributes/ServersideAttributeMap.cpp
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
#include "../../Platform/stdafx.h"
|
||||
|
||||
#include "Attribute.h"
|
||||
#include "RangedAttribute.h"
|
||||
#include "AttributeInstance.h"
|
||||
#include "ModifiableAttributeInstance.h"
|
||||
#include "ServersideAttributeMap.h"
|
||||
|
||||
AttributeInstance* ServersideAttributeMap::getInstance(Attribute* attribute) {
|
||||
return BaseAttributeMap::getInstance(attribute);
|
||||
}
|
||||
|
||||
AttributeInstance* ServersideAttributeMap::getInstance(eATTRIBUTE_ID id) {
|
||||
AttributeInstance* result = BaseAttributeMap::getInstance(id);
|
||||
|
||||
// 4J: Removed legacy name
|
||||
// If we didn't find it, search by legacy name
|
||||
/*if (result == NULL)
|
||||
{
|
||||
AUTO_VAR(it, attributesByLegacy.find(name));
|
||||
if(it != attributesByLegacy.end())
|
||||
{
|
||||
result = it->second;
|
||||
}
|
||||
}*/
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
AttributeInstance* ServersideAttributeMap::registerAttribute(
|
||||
Attribute* attribute) {
|
||||
AUTO_VAR(it, attributesById.find(attribute->getId()));
|
||||
if (it != attributesById.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
AttributeInstance* instance =
|
||||
new ModifiableAttributeInstance(this, attribute);
|
||||
attributesById.insert(std::pair<eATTRIBUTE_ID, AttributeInstance*>(
|
||||
attribute->getId(), instance));
|
||||
|
||||
// 4J: Removed legacy name
|
||||
// If this is a ranged attribute also add to legacy name map
|
||||
/*RangedAttribute *rangedAttribute =
|
||||
dynamic_cast<RangedAttribute*>(attribute); if (rangedAttribute != NULL &&
|
||||
rangedAttribute->getImportLegacyName() != L"")
|
||||
{
|
||||
attributesByLegacy.insert(std::pair<std::wstring,
|
||||
AttributeInstance*>(rangedAttribute->getImportLegacyName(), instance));
|
||||
}*/
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void ServersideAttributeMap::onAttributeModified(
|
||||
ModifiableAttributeInstance* attributeInstance) {
|
||||
if (attributeInstance->getAttribute()->isClientSyncable()) {
|
||||
dirtyAttributes.insert(attributeInstance);
|
||||
}
|
||||
}
|
||||
|
||||
std::unordered_set<AttributeInstance*>*
|
||||
ServersideAttributeMap::getDirtyAttributes() {
|
||||
return &dirtyAttributes;
|
||||
}
|
||||
|
||||
std::unordered_set<AttributeInstance*>*
|
||||
ServersideAttributeMap::getSyncableAttributes() {
|
||||
std::unordered_set<AttributeInstance*>* result =
|
||||
new std::unordered_set<AttributeInstance*>();
|
||||
std::vector<AttributeInstance*> atts;
|
||||
getAttributes(atts);
|
||||
for (int i = 0; i < atts.size(); i++) {
|
||||
AttributeInstance* instance = atts.at(i);
|
||||
|
||||
if (instance->getAttribute()->isClientSyncable()) {
|
||||
result->insert(instance);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
24
Minecraft.World/AI/Attributes/ServersideAttributeMap.h
Normal file
24
Minecraft.World/AI/Attributes/ServersideAttributeMap.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include "BaseAttributeMap.h"
|
||||
|
||||
class ServersideAttributeMap : public BaseAttributeMap {
|
||||
private:
|
||||
std::unordered_set<AttributeInstance*> dirtyAttributes;
|
||||
|
||||
protected:
|
||||
// 4J: Remove legacy name
|
||||
// unordered_map<eATTRIBUTE_ID, AttributeInstance *> attributesByLegacy;
|
||||
|
||||
public:
|
||||
// 4J-JEV: Changed from ModifiableAttributeInstance to AttributeInstance as
|
||||
// they are not 'covariant' on PS4.
|
||||
virtual AttributeInstance* getInstance(Attribute* attribute);
|
||||
virtual AttributeInstance* getInstance(eATTRIBUTE_ID id);
|
||||
|
||||
virtual AttributeInstance* registerAttribute(Attribute* attribute);
|
||||
virtual void onAttributeModified(
|
||||
ModifiableAttributeInstance* attributeInstance);
|
||||
virtual std::unordered_set<AttributeInstance*>* getDirtyAttributes();
|
||||
virtual std::unordered_set<AttributeInstance*>* getSyncableAttributes();
|
||||
};
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
const float BodyControl::maxClampAngle = 75.0f;
|
||||
|
||||
BodyControl::BodyControl(Mob* mob) {
|
||||
BodyControl::BodyControl(LivingEntity* mob) {
|
||||
this->mob = mob;
|
||||
|
||||
timeStill = 0;
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@
|
|||
|
||||
class BodyControl : public Control {
|
||||
private:
|
||||
Mob* mob;
|
||||
LivingEntity* mob;
|
||||
static const float maxClampAngle;
|
||||
int timeStill;
|
||||
float lastHeadY;
|
||||
|
||||
public:
|
||||
BodyControl(Mob* mob);
|
||||
BodyControl(LivingEntity* mob);
|
||||
|
||||
void clientTick();
|
||||
|
||||
|
|
|
|||
|
|
@ -14,13 +14,14 @@ LookControl::LookControl(Mob* mob) {
|
|||
|
||||
void LookControl::setLookAt(std::shared_ptr<Entity> target, float yMax,
|
||||
float xMax) {
|
||||
this->wantedX = target->x;
|
||||
std::shared_ptr<Mob> targetMob = std::dynamic_pointer_cast<Mob>(target);
|
||||
if (targetMob != NULL)
|
||||
this->wantedY = target->y + targetMob->getHeadHeight();
|
||||
wantedX = target->x;
|
||||
if (target->instanceof(eTYPE_LIVINGENTITY))
|
||||
wantedY =
|
||||
target->y +
|
||||
std::dynamic_pointer_cast<LivingEntity>(target)->getHeadHeight();
|
||||
else
|
||||
this->wantedY = (target->bb->y0 + target->bb->y1) / 2;
|
||||
this->wantedZ = target->z;
|
||||
wantedY = (target->bb->y0 + target->bb->y1) / 2;
|
||||
wantedZ = target->z;
|
||||
this->yMax = yMax;
|
||||
this->xMax = xMax;
|
||||
hasWanted = true;
|
||||
|
|
@ -28,9 +29,9 @@ void LookControl::setLookAt(std::shared_ptr<Entity> target, float yMax,
|
|||
|
||||
void LookControl::setLookAt(double x, double y, double z, float yMax,
|
||||
float xMax) {
|
||||
this->wantedX = x;
|
||||
this->wantedY = y;
|
||||
this->wantedZ = z;
|
||||
wantedX = x;
|
||||
wantedY = y;
|
||||
wantedZ = z;
|
||||
this->yMax = yMax;
|
||||
this->xMax = xMax;
|
||||
hasWanted = true;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#include "../../Platform/stdafx.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.control.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.attributes.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.control.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.monster.h"
|
||||
#include "../../Headers/net.minecraft.world.phys.h"
|
||||
#include "MoveControl.h"
|
||||
|
||||
|
|
@ -13,20 +15,21 @@ MoveControl::MoveControl(Mob* mob) {
|
|||
wantedY = mob->y;
|
||||
wantedZ = mob->z;
|
||||
|
||||
speed = 0.0f;
|
||||
speedModifier = 0.0;
|
||||
|
||||
_hasWanted = false;
|
||||
}
|
||||
|
||||
bool MoveControl::hasWanted() { return _hasWanted; }
|
||||
|
||||
float MoveControl::getSpeed() { return speed; }
|
||||
double MoveControl::getSpeedModifier() { return speedModifier; }
|
||||
|
||||
void MoveControl::setWantedPosition(double x, double y, double z, float speed) {
|
||||
void MoveControl::setWantedPosition(double x, double y, double z,
|
||||
double speedModifier) {
|
||||
wantedX = x;
|
||||
wantedY = y;
|
||||
wantedZ = z;
|
||||
this->speed = speed;
|
||||
this->speedModifier = speedModifier;
|
||||
_hasWanted = true;
|
||||
}
|
||||
|
||||
|
|
@ -46,7 +49,10 @@ void MoveControl::tick() {
|
|||
float yRotD = (float)(atan2(zd, xd) * 180 / PI) - 90;
|
||||
|
||||
mob->yRot = rotlerp(mob->yRot, yRotD, MAX_TURN);
|
||||
mob->setSpeed(speed * mob->getWalkingSpeedModifier());
|
||||
mob->setSpeed(
|
||||
(float)(speedModifier *
|
||||
mob->getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED)
|
||||
->getValue()));
|
||||
|
||||
if (yd > 0 && xd * xd + zd * zd < 1) mob->getJumpControl()->jump();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,19 +16,18 @@ private:
|
|||
double wantedX;
|
||||
double wantedY;
|
||||
double wantedZ;
|
||||
float speed;
|
||||
double speedModifier;
|
||||
bool _hasWanted;
|
||||
|
||||
public:
|
||||
MoveControl(Mob* mob);
|
||||
virtual ~MoveControl() {}
|
||||
|
||||
bool hasWanted();
|
||||
float getSpeed();
|
||||
void setWantedPosition(double x, double y, double z, float speed);
|
||||
double getSpeedModifier();
|
||||
void setWantedPosition(double x, double y, double z, double speedModifier);
|
||||
void setSpeed(float speed);
|
||||
virtual void tick();
|
||||
|
||||
private:
|
||||
float rotlerp(float a, float b, float max);
|
||||
};
|
||||
};
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
#include "../../Platform/stdafx.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.control.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.navigation.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.sensing.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.projectile.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.h"
|
||||
#include "../../Headers/net.minecraft.world.level.h"
|
||||
#include "../../Headers/net.minecraft.world.phys.h"
|
||||
#include "../../Util/SoundTypes.h"
|
||||
#include "ArrowAttackGoal.h"
|
||||
|
||||
ArrowAttackGoal::ArrowAttackGoal(Mob* mob, float speed, int projectileType,
|
||||
int attackInterval) {
|
||||
// 4J Init
|
||||
target = std::weak_ptr<Mob>();
|
||||
attackTime = 0;
|
||||
seeTime = 0;
|
||||
|
||||
this->mob = mob;
|
||||
this->level = mob->level;
|
||||
this->speed = speed;
|
||||
this->projectileType = projectileType;
|
||||
this->attackInterval = attackInterval;
|
||||
setRequiredControlFlags(Control::MoveControlFlag |
|
||||
Control::LookControlFlag);
|
||||
}
|
||||
|
||||
bool ArrowAttackGoal::canUse() {
|
||||
std::shared_ptr<Mob> bestTarget = mob->getTarget();
|
||||
if (bestTarget == NULL) return false;
|
||||
target = std::weak_ptr<Mob>(bestTarget);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ArrowAttackGoal::canContinueToUse() {
|
||||
return target.lock() != NULL &&
|
||||
(canUse() || !mob->getNavigation()->isDone());
|
||||
}
|
||||
|
||||
void ArrowAttackGoal::stop() { target = std::weak_ptr<Mob>(); }
|
||||
|
||||
void ArrowAttackGoal::tick() {
|
||||
double attackRadiusSqr = 10 * 10;
|
||||
std::shared_ptr<Mob> tar = target.lock();
|
||||
double targetDistSqr = mob->distanceToSqr(tar->x, tar->bb->y0, tar->z);
|
||||
bool canSee = mob->getSensing()->canSee(tar);
|
||||
|
||||
if (canSee) {
|
||||
++seeTime;
|
||||
} else
|
||||
seeTime = 0;
|
||||
|
||||
if (targetDistSqr > attackRadiusSqr || seeTime < 20)
|
||||
mob->getNavigation()->moveTo(tar, speed);
|
||||
else
|
||||
mob->getNavigation()->stop();
|
||||
|
||||
mob->getLookControl()->setLookAt(tar, 30, 30);
|
||||
|
||||
attackTime = std::max(attackTime - 1, 0);
|
||||
if (attackTime > 0) return;
|
||||
if (targetDistSqr > attackRadiusSqr || !canSee) return;
|
||||
fireAtTarget();
|
||||
attackTime = attackInterval;
|
||||
}
|
||||
|
||||
void ArrowAttackGoal::fireAtTarget() {
|
||||
std::shared_ptr<Mob> tar = target.lock();
|
||||
if (projectileType == ArrowType) {
|
||||
std::shared_ptr<Arrow> arrow = std::shared_ptr<Arrow>(new Arrow(
|
||||
level, std::dynamic_pointer_cast<Mob>(mob->shared_from_this()), tar,
|
||||
1.60f, 12));
|
||||
level->playSound(mob->shared_from_this(), eSoundType_RANDOM_BOW, 1.0f,
|
||||
1 / (mob->getRandom()->nextFloat() * 0.4f + 0.8f));
|
||||
level->addEntity(arrow);
|
||||
} else if (projectileType == SnowballType) {
|
||||
std::shared_ptr<Snowball> snowball = std::shared_ptr<Snowball>(
|
||||
new Snowball(level, std::dynamic_pointer_cast<Mob>(
|
||||
mob->shared_from_this())));
|
||||
double xd = tar->x - mob->x;
|
||||
double yd = (tar->y + tar->getHeadHeight() - 1.1f) - snowball->y;
|
||||
double zd = tar->z - mob->z;
|
||||
float yo = sqrt(xd * xd + zd * zd) * 0.2f;
|
||||
snowball->shoot(xd, yd + yo, zd, 1.60f, 12);
|
||||
|
||||
level->playSound(mob->shared_from_this(), eSoundType_RANDOM_BOW, 1.0f,
|
||||
1 / (mob->getRandom()->nextFloat() * 0.4f + 0.8f));
|
||||
level->addEntity(snowball);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "Goal.h"
|
||||
|
||||
class ArrowAttackGoal : public Goal {
|
||||
public:
|
||||
static const int ArrowType = 1;
|
||||
static const int SnowballType = 2;
|
||||
|
||||
Level* level;
|
||||
Mob* mob; // Owner of this goal
|
||||
std::weak_ptr<Mob> target;
|
||||
int attackTime;
|
||||
float speed;
|
||||
int seeTime;
|
||||
int projectileType;
|
||||
int attackInterval;
|
||||
|
||||
ArrowAttackGoal(Mob* mob, float speed, int projectileType,
|
||||
int attackInterval);
|
||||
|
||||
virtual bool canUse();
|
||||
virtual bool canContinueToUse();
|
||||
virtual void stop();
|
||||
virtual void tick();
|
||||
|
||||
private:
|
||||
void fireAtTarget();
|
||||
|
||||
public:
|
||||
// 4J Added override to update ai elements when loading entity from
|
||||
// schematics
|
||||
virtual void setLevel(Level* level) { this->level = level; }
|
||||
};
|
||||
|
|
@ -10,24 +10,38 @@
|
|||
#include "../../Headers/net.minecraft.world.phys.h"
|
||||
#include "AvoidPlayerGoal.h"
|
||||
|
||||
AvoidPlayerGoalEntitySelector::AvoidPlayerGoalEntitySelector(
|
||||
AvoidPlayerGoal* parent) {
|
||||
m_parent = parent;
|
||||
}
|
||||
|
||||
bool AvoidPlayerGoalEntitySelector::matches(
|
||||
std::shared_ptr<Entity> entity) const {
|
||||
return entity->isAlive() && m_parent->mob->getSensing()->canSee(entity);
|
||||
}
|
||||
|
||||
AvoidPlayerGoal::AvoidPlayerGoal(PathfinderMob* mob,
|
||||
const std::type_info& avoidType, float maxDist,
|
||||
float walkSpeed, float sprintSpeed)
|
||||
double walkSpeedModifier,
|
||||
double sprintSpeedModifier)
|
||||
: avoidType(avoidType) {
|
||||
this->mob = mob;
|
||||
// this->avoidType = avoidType;
|
||||
this->maxDist = maxDist;
|
||||
this->walkSpeed = walkSpeed;
|
||||
this->sprintSpeed = sprintSpeed;
|
||||
this->walkSpeedModifier = walkSpeedModifier;
|
||||
this->sprintSpeedModifier = sprintSpeedModifier;
|
||||
this->pathNav = mob->getNavigation();
|
||||
setRequiredControlFlags(Control::MoveControlFlag);
|
||||
|
||||
entitySelector = new AvoidPlayerGoalEntitySelector(this);
|
||||
|
||||
toAvoid = std::weak_ptr<Entity>();
|
||||
path = NULL;
|
||||
}
|
||||
|
||||
AvoidPlayerGoal::~AvoidPlayerGoal() {
|
||||
if (path != NULL) delete path;
|
||||
delete entitySelector;
|
||||
}
|
||||
|
||||
bool AvoidPlayerGoal::canUse() {
|
||||
|
|
@ -40,8 +54,8 @@ bool AvoidPlayerGoal::canUse() {
|
|||
if (toAvoid.lock() == NULL) return false;
|
||||
} else {
|
||||
std::vector<std::shared_ptr<Entity> >* entities =
|
||||
mob->level->getEntitiesOfClass(avoidType,
|
||||
mob->bb->grow(maxDist, 3, maxDist));
|
||||
mob->level->getEntitiesOfClass(
|
||||
avoidType, mob->bb->grow(maxDist, 3, maxDist), entitySelector);
|
||||
if (entities->empty()) {
|
||||
delete entities;
|
||||
return false;
|
||||
|
|
@ -50,8 +64,6 @@ bool AvoidPlayerGoal::canUse() {
|
|||
delete entities;
|
||||
}
|
||||
|
||||
if (!mob->getSensing()->canSee(toAvoid.lock())) return false;
|
||||
|
||||
Vec3* pos = RandomPos::getPosAvoid(
|
||||
std::dynamic_pointer_cast<PathfinderMob>(mob->shared_from_this()), 16,
|
||||
7,
|
||||
|
|
@ -72,7 +84,7 @@ bool AvoidPlayerGoal::canContinueToUse() {
|
|||
}
|
||||
|
||||
void AvoidPlayerGoal::start() {
|
||||
pathNav->moveTo(path, walkSpeed);
|
||||
pathNav->moveTo(path, walkSpeedModifier);
|
||||
path = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -80,7 +92,7 @@ void AvoidPlayerGoal::stop() { toAvoid = std::weak_ptr<Entity>(); }
|
|||
|
||||
void AvoidPlayerGoal::tick() {
|
||||
if (mob->distanceToSqr(toAvoid.lock()) < 7 * 7)
|
||||
mob->getNavigation()->setSpeed(sprintSpeed);
|
||||
mob->getNavigation()->setSpeedModifier(sprintSpeedModifier);
|
||||
else
|
||||
mob->getNavigation()->setSpeed(walkSpeed);
|
||||
mob->getNavigation()->setSpeedModifier(walkSpeedModifier);
|
||||
}
|
||||
|
|
@ -1,24 +1,39 @@
|
|||
#pragma once
|
||||
|
||||
#include "Goal.h"
|
||||
#include "../../Entities/EntitySelector.h"
|
||||
|
||||
class PathNavigation;
|
||||
class PathfinderMob;
|
||||
class Path;
|
||||
class AvoidPlayerGoal;
|
||||
|
||||
class AvoidPlayerGoalEntitySelector : public EntitySelector {
|
||||
private:
|
||||
AvoidPlayerGoal* m_parent;
|
||||
|
||||
public:
|
||||
AvoidPlayerGoalEntitySelector(AvoidPlayerGoal* parent);
|
||||
bool matches(std::shared_ptr<Entity> entity) const;
|
||||
};
|
||||
|
||||
class AvoidPlayerGoal : public Goal {
|
||||
friend class AvoidPlayerGoalEntitySelector;
|
||||
|
||||
private:
|
||||
PathfinderMob* mob; // Owner of this goal
|
||||
float walkSpeed, sprintSpeed;
|
||||
double walkSpeedModifier, sprintSpeedModifier;
|
||||
std::weak_ptr<Entity> toAvoid;
|
||||
float maxDist;
|
||||
Path* path;
|
||||
PathNavigation* pathNav;
|
||||
const std::type_info& avoidType;
|
||||
EntitySelector* entitySelector;
|
||||
|
||||
public:
|
||||
AvoidPlayerGoal(PathfinderMob* mob, const std::type_info& avoidType,
|
||||
float maxDist, float walkSpeed, float sprintSpeed);
|
||||
float maxDist, double walkSpeedModifier,
|
||||
double sprintSpeedModifier);
|
||||
~AvoidPlayerGoal();
|
||||
|
||||
virtual bool canUse();
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ BreakDoorGoal::BreakDoorGoal(Mob* mob) : DoorInteractGoal(mob) {
|
|||
|
||||
bool BreakDoorGoal::canUse() {
|
||||
if (!DoorInteractGoal::canUse()) return false;
|
||||
if (!mob->level->getGameRules()->getBoolean(GameRules::RULE_MOBGRIEFING))
|
||||
return false;
|
||||
return !doorTile->isOpen(mob->level, doorX, doorY, doorZ);
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +52,7 @@ void BreakDoorGoal::tick() {
|
|||
|
||||
if (breakTime == DOOR_BREAK_TIME) {
|
||||
if (mob->level->difficulty == Difficulty::HARD) {
|
||||
mob->level->setTile(doorX, doorY, doorZ, 0);
|
||||
mob->level->removeTile(doorX, doorY, doorZ);
|
||||
mob->level->levelEvent(LevelEvent::SOUND_ZOMBIE_DOOR_CRASH, doorX,
|
||||
doorY, doorZ, 0);
|
||||
mob->level->levelEvent(LevelEvent::PARTICLES_DESTROY_BLOCK, doorX,
|
||||
|
|
|
|||
|
|
@ -4,18 +4,19 @@
|
|||
#include "../../Headers/net.minecraft.world.entity.animal.h"
|
||||
#include "../../Headers/net.minecraft.world.level.h"
|
||||
#include "../../Headers/net.minecraft.world.phys.h"
|
||||
#include "../../Util/BasicTypeContainers.h"
|
||||
#include "BreedGoal.h"
|
||||
#include "../../Entities/Mobs/ExperienceOrb.h"
|
||||
|
||||
#include "../../Stats/GenericStats.h"
|
||||
|
||||
BreedGoal::BreedGoal(Animal* animal, float speed) {
|
||||
BreedGoal::BreedGoal(Animal* animal, double speedModifier) {
|
||||
partner = std::weak_ptr<Animal>();
|
||||
loveTime = 0;
|
||||
|
||||
this->animal = animal;
|
||||
this->level = animal->level;
|
||||
this->speed = speed;
|
||||
this->speedModifier = speedModifier;
|
||||
setRequiredControlFlags(Control::MoveControlFlag |
|
||||
Control::LookControlFlag);
|
||||
}
|
||||
|
|
@ -39,24 +40,27 @@ void BreedGoal::stop() {
|
|||
void BreedGoal::tick() {
|
||||
animal->getLookControl()->setLookAt(partner.lock(), 10,
|
||||
animal->getMaxHeadXRot());
|
||||
animal->getNavigation()->moveTo(partner.lock(), speed);
|
||||
animal->getNavigation()->moveTo(partner.lock(), speedModifier);
|
||||
++loveTime;
|
||||
if (loveTime == 20 * 3) breed();
|
||||
if (loveTime >= 20 * 3 && animal->distanceToSqr(partner.lock()) < 3 * 3)
|
||||
breed();
|
||||
}
|
||||
|
||||
std::shared_ptr<Animal> BreedGoal::getFreePartner() {
|
||||
float r = 8;
|
||||
std::vector<std::shared_ptr<Entity> >* others =
|
||||
level->getEntitiesOfClass(typeid(*animal), animal->bb->grow(r, r, r));
|
||||
double dist = Double::MAX_VALUE;
|
||||
std::shared_ptr<Animal> partner = nullptr;
|
||||
for (AUTO_VAR(it, others->begin()); it != others->end(); ++it) {
|
||||
std::shared_ptr<Animal> p = std::dynamic_pointer_cast<Animal>(*it);
|
||||
if (animal->canMate(p)) {
|
||||
delete others;
|
||||
return p;
|
||||
if (animal->canMate(p) && animal->distanceToSqr(p) < dist) {
|
||||
partner = p;
|
||||
dist = animal->distanceToSqr(p);
|
||||
}
|
||||
}
|
||||
delete others;
|
||||
return nullptr;
|
||||
return partner;
|
||||
}
|
||||
|
||||
void BreedGoal::breed() {
|
||||
|
|
@ -93,7 +97,7 @@ void BreedGoal::breed() {
|
|||
partner.lock()->setAge(5 * 60 * 20);
|
||||
animal->resetLove();
|
||||
partner.lock()->resetLove();
|
||||
offspring->setAge(-20 * 60 * 20);
|
||||
offspring->setAge(AgableMob::BABY_START_AGE);
|
||||
offspring->moveTo(animal->x, animal->y, animal->z, 0, 0);
|
||||
offspring->setDespawnProtected();
|
||||
level->addEntity(offspring);
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@ private:
|
|||
Level* level;
|
||||
std::weak_ptr<Animal> partner;
|
||||
int loveTime;
|
||||
float speed;
|
||||
double speedModifier;
|
||||
|
||||
public:
|
||||
BreedGoal(Animal* animal, float speed);
|
||||
BreedGoal(Animal* animal, double speedModifier);
|
||||
|
||||
virtual bool canUse();
|
||||
virtual bool canContinueToUse();
|
||||
|
|
|
|||
|
|
@ -36,9 +36,8 @@ void ControlledByPlayerGoal::stop() {
|
|||
}
|
||||
|
||||
bool ControlledByPlayerGoal::canUse() {
|
||||
std::shared_ptr<Player> player =
|
||||
std::dynamic_pointer_cast<Player>(mob->rider.lock());
|
||||
return mob->isAlive() && player &&
|
||||
return mob->isAlive() && mob->rider.lock() != NULL &&
|
||||
mob->rider.lock()->instanceof(eTYPE_PLAYER) &&
|
||||
(boosting || mob->canBeControlledByRider());
|
||||
}
|
||||
|
||||
|
|
@ -119,7 +118,7 @@ void ControlledByPlayerGoal::tick() {
|
|||
std::shared_ptr<ItemInstance> carriedItem = player->getCarriedItem();
|
||||
|
||||
if (carriedItem != NULL && carriedItem->id == Item::carrotOnAStick_Id) {
|
||||
carriedItem->hurt(1, player);
|
||||
carriedItem->hurtAndBreak(1, player);
|
||||
|
||||
if (carriedItem->count == 0) {
|
||||
std::shared_ptr<ItemInstance> replacement =
|
||||
|
|
@ -135,6 +134,12 @@ void ControlledByPlayerGoal::tick() {
|
|||
mob->travel(0, moveSpeed);
|
||||
}
|
||||
|
||||
bool ControlledByPlayerGoal::isNoJumpTile(int tile) {
|
||||
return Tile::tiles[tile] != NULL &&
|
||||
(Tile::tiles[tile]->getRenderShape() == Tile::SHAPE_STAIRS ||
|
||||
(dynamic_cast<HalfSlabTile*>(Tile::tiles[tile]) != NULL));
|
||||
}
|
||||
|
||||
bool ControlledByPlayerGoal::isBoosting() { return boosting; }
|
||||
|
||||
void ControlledByPlayerGoal::boost() {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "Goal.h"
|
||||
#include "../../Util/SharedConstants.h"
|
||||
#include "../Minecraft.World/SharedConstants.h"
|
||||
|
||||
class Mob;
|
||||
|
||||
|
|
@ -26,7 +26,12 @@ public:
|
|||
void stop();
|
||||
bool canUse();
|
||||
void tick();
|
||||
|
||||
private:
|
||||
bool isNoJumpTile(int tile);
|
||||
|
||||
public:
|
||||
bool isBoosting();
|
||||
void boost();
|
||||
bool canBoost();
|
||||
};
|
||||
};
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
#include "DefendVillageTargetGoal.h"
|
||||
|
||||
DefendVillageTargetGoal::DefendVillageTargetGoal(VillagerGolem* golem)
|
||||
: TargetGoal(golem, 16, false, true) {
|
||||
: TargetGoal(golem, false, true) {
|
||||
this->golem = golem;
|
||||
setRequiredControlFlags(TargetGoal::TargetFlag);
|
||||
}
|
||||
|
|
@ -12,9 +12,21 @@ DefendVillageTargetGoal::DefendVillageTargetGoal(VillagerGolem* golem)
|
|||
bool DefendVillageTargetGoal::canUse() {
|
||||
std::shared_ptr<Village> village = golem->getVillage();
|
||||
if (village == NULL) return false;
|
||||
potentialTarget = std::weak_ptr<Mob>(village->getClosestAggressor(
|
||||
std::dynamic_pointer_cast<Mob>(golem->shared_from_this())));
|
||||
return canAttack(potentialTarget.lock(), false);
|
||||
potentialTarget = std::weak_ptr<LivingEntity>(village->getClosestAggressor(
|
||||
std::dynamic_pointer_cast<LivingEntity>(golem->shared_from_this())));
|
||||
std::shared_ptr<LivingEntity> potTarget = potentialTarget.lock();
|
||||
if (!canAttack(potTarget, false)) {
|
||||
// look for bad players
|
||||
if (mob->getRandom()->nextInt(20) == 0) {
|
||||
potentialTarget = village->getClosestBadStandingPlayer(
|
||||
std::dynamic_pointer_cast<LivingEntity>(
|
||||
golem->shared_from_this()));
|
||||
return canAttack(potTarget, false);
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void DefendVillageTargetGoal::start() {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ class VillagerGolem;
|
|||
class DefendVillageTargetGoal : public TargetGoal {
|
||||
private:
|
||||
VillagerGolem* golem; // Owner of this goal
|
||||
std::weak_ptr<Mob> potentialTarget;
|
||||
std::weak_ptr<LivingEntity> potentialTarget;
|
||||
|
||||
public:
|
||||
DefendVillageTargetGoal(VillagerGolem* golem);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ EatTileGoal::EatTileGoal(Mob* mob) {
|
|||
eatAnimationTick = 0;
|
||||
|
||||
this->mob = mob;
|
||||
this->level = mob->level;
|
||||
level = mob->level;
|
||||
setRequiredControlFlags(Control::MoveControlFlag |
|
||||
Control::LookControlFlag |
|
||||
Control::JumpControlFlag);
|
||||
|
|
@ -51,15 +51,13 @@ void EatTileGoal::tick() {
|
|||
int zz = Mth::floor(mob->z);
|
||||
|
||||
if (level->getTile(xx, yy, zz) == Tile::tallgrass_Id) {
|
||||
level->levelEvent(LevelEvent::PARTICLES_DESTROY_BLOCK, xx, yy, zz,
|
||||
Tile::tallgrass_Id +
|
||||
(TallGrass::TALL_GRASS << Tile::TILE_NUM_SHIFT));
|
||||
level->setTile(xx, yy, zz, 0);
|
||||
level->destroyTile(xx, yy, zz, false);
|
||||
mob->ate();
|
||||
} else if (level->getTile(xx, yy - 1, zz) == Tile::grass_Id) {
|
||||
level->levelEvent(LevelEvent::PARTICLES_DESTROY_BLOCK, xx, yy - 1, zz,
|
||||
Tile::grass_Id);
|
||||
level->setTile(xx, yy - 1, zz, Tile::dirt_Id);
|
||||
level->setTileAndData(xx, yy - 1, zz, Tile::dirt_Id, 0,
|
||||
Tile::UPDATE_CLIENTS);
|
||||
mob->ate();
|
||||
}
|
||||
}
|
||||
|
|
@ -6,9 +6,9 @@
|
|||
#include "../../Headers/net.minecraft.world.phys.h"
|
||||
#include "FleeSunGoal.h"
|
||||
|
||||
FleeSunGoal::FleeSunGoal(PathfinderMob* mob, float speed) {
|
||||
FleeSunGoal::FleeSunGoal(PathfinderMob* mob, double speedModifier) {
|
||||
this->mob = mob;
|
||||
this->speed = speed;
|
||||
this->speedModifier = speedModifier;
|
||||
this->level = mob->level;
|
||||
setRequiredControlFlags(Control::MoveControlFlag);
|
||||
}
|
||||
|
|
@ -31,7 +31,7 @@ bool FleeSunGoal::canUse() {
|
|||
bool FleeSunGoal::canContinueToUse() { return !mob->getNavigation()->isDone(); }
|
||||
|
||||
void FleeSunGoal::start() {
|
||||
mob->getNavigation()->moveTo(wantedX, wantedY, wantedZ, speed);
|
||||
mob->getNavigation()->moveTo(wantedX, wantedY, wantedZ, speedModifier);
|
||||
}
|
||||
|
||||
Vec3* FleeSunGoal::getHidePos() {
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ class FleeSunGoal : public Goal {
|
|||
private:
|
||||
PathfinderMob* mob; // Owner of this goal
|
||||
double wantedX, wantedY, wantedZ;
|
||||
float speed;
|
||||
double speedModifier;
|
||||
Level* level;
|
||||
|
||||
public:
|
||||
FleeSunGoal(PathfinderMob* mob, float speed);
|
||||
FleeSunGoal(PathfinderMob* mob, double speedModifier);
|
||||
|
||||
virtual bool canUse();
|
||||
virtual bool canContinueToUse();
|
||||
|
|
|
|||
|
|
@ -7,16 +7,16 @@
|
|||
#include "../../Headers/net.minecraft.world.phys.h"
|
||||
#include "FollowOwnerGoal.h"
|
||||
|
||||
FollowOwnerGoal::FollowOwnerGoal(TamableAnimal* tamable, float speed,
|
||||
FollowOwnerGoal::FollowOwnerGoal(TamableAnimal* tamable, double speedModifier,
|
||||
float startDistance, float stopDistance) {
|
||||
owner = std::weak_ptr<Mob>();
|
||||
timeToRecalcPath = 0;
|
||||
oldAvoidWater = false;
|
||||
|
||||
this->tamable = tamable;
|
||||
this->level = tamable->level;
|
||||
this->speed = speed;
|
||||
this->navigation = tamable->getNavigation();
|
||||
level = tamable->level;
|
||||
this->speedModifier = speedModifier;
|
||||
navigation = tamable->getNavigation();
|
||||
this->startDistance = startDistance;
|
||||
this->stopDistance = stopDistance;
|
||||
setRequiredControlFlags(Control::MoveControlFlag |
|
||||
|
|
@ -24,12 +24,13 @@ FollowOwnerGoal::FollowOwnerGoal(TamableAnimal* tamable, float speed,
|
|||
}
|
||||
|
||||
bool FollowOwnerGoal::canUse() {
|
||||
std::shared_ptr<Mob> owner = tamable->getOwner();
|
||||
std::shared_ptr<LivingEntity> owner =
|
||||
std::dynamic_pointer_cast<LivingEntity>(tamable->getOwner());
|
||||
if (owner == NULL) return false;
|
||||
if (tamable->isSitting()) return false;
|
||||
if (tamable->distanceToSqr(owner) < startDistance * startDistance)
|
||||
return false;
|
||||
this->owner = std::weak_ptr<Mob>(owner);
|
||||
this->owner = std::weak_ptr<LivingEntity>(owner);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -59,7 +60,8 @@ void FollowOwnerGoal::tick() {
|
|||
if (--timeToRecalcPath > 0) return;
|
||||
timeToRecalcPath = 10;
|
||||
|
||||
if (navigation->moveTo(owner.lock(), speed)) return;
|
||||
if (navigation->moveTo(owner.lock(), speedModifier)) return;
|
||||
if (tamable->isLeashed()) return;
|
||||
if (tamable->distanceToSqr(owner.lock()) <
|
||||
TeleportDistance * TeleportDistance)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -11,17 +11,17 @@ public:
|
|||
|
||||
private:
|
||||
TamableAnimal* tamable; // Owner of this goal
|
||||
std::weak_ptr<Mob> owner;
|
||||
std::weak_ptr<LivingEntity> owner;
|
||||
Level* level;
|
||||
float speed;
|
||||
double speedModifier;
|
||||
PathNavigation* navigation;
|
||||
int timeToRecalcPath;
|
||||
float stopDistance, startDistance;
|
||||
bool oldAvoidWater;
|
||||
|
||||
public:
|
||||
FollowOwnerGoal(TamableAnimal* tamable, float speed, float startDistance,
|
||||
float stopDistance);
|
||||
FollowOwnerGoal(TamableAnimal* tamable, double speedModifier,
|
||||
float startDistance, float stopDistance);
|
||||
|
||||
virtual bool canUse();
|
||||
virtual bool canContinueToUse();
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@
|
|||
#include "../../Util/BasicTypeContainers.h"
|
||||
#include "FollowParentGoal.h"
|
||||
|
||||
FollowParentGoal::FollowParentGoal(Animal* animal, float speed) {
|
||||
FollowParentGoal::FollowParentGoal(Animal* animal, double speedModifier) {
|
||||
timeToRecalcPath = 0;
|
||||
|
||||
this->animal = animal;
|
||||
this->speed = speed;
|
||||
this->speedModifier = speedModifier;
|
||||
}
|
||||
|
||||
bool FollowParentGoal::canUse() {
|
||||
|
|
@ -52,5 +52,5 @@ void FollowParentGoal::stop() { parent = std::weak_ptr<Animal>(); }
|
|||
void FollowParentGoal::tick() {
|
||||
if (--timeToRecalcPath > 0) return;
|
||||
timeToRecalcPath = 10;
|
||||
animal->getNavigation()->moveTo(parent.lock(), speed);
|
||||
animal->getNavigation()->moveTo(parent.lock(), speedModifier);
|
||||
}
|
||||
|
|
@ -8,11 +8,11 @@ class FollowParentGoal : public Goal {
|
|||
private:
|
||||
Animal* animal; // Owner of this goal
|
||||
std::weak_ptr<Animal> parent;
|
||||
float speed;
|
||||
double speedModifier;
|
||||
int timeToRecalcPath;
|
||||
|
||||
public:
|
||||
FollowParentGoal(Animal* animal, float speed);
|
||||
FollowParentGoal(Animal* animal, double speedModifier);
|
||||
|
||||
virtual bool canUse();
|
||||
virtual bool canContinueToUse();
|
||||
|
|
|
|||
|
|
@ -28,6 +28,27 @@ void GoalSelector::addGoal(
|
|||
goals.push_back(new InternalGoal(prio, goal, canDeletePointer));
|
||||
}
|
||||
|
||||
void GoalSelector::removeGoal(Goal* toRemove) {
|
||||
for (AUTO_VAR(it, goals.begin()); it != goals.end();) {
|
||||
InternalGoal* ig = *it;
|
||||
Goal* goal = ig->goal;
|
||||
|
||||
if (goal == toRemove) {
|
||||
AUTO_VAR(it2, find(usingGoals.begin(), usingGoals.end(), ig));
|
||||
if (it2 != usingGoals.end()) {
|
||||
goal->stop();
|
||||
usingGoals.erase(it2);
|
||||
}
|
||||
|
||||
if (ig->canDeletePointer) delete ig->goal;
|
||||
delete ig;
|
||||
it = goals.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GoalSelector::tick() {
|
||||
std::vector<InternalGoal*> toStart;
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ public:
|
|||
|
||||
// 4J Added canDelete param
|
||||
void addGoal(int prio, Goal* goal, bool canDeletePointer = true);
|
||||
void removeGoal(Goal* toRemove);
|
||||
void tick();
|
||||
std::vector<InternalGoal*>* getRunningGoals();
|
||||
|
||||
|
|
|
|||
|
|
@ -4,41 +4,40 @@
|
|||
#include "../../Headers/net.minecraft.world.level.h"
|
||||
#include "HurtByTargetGoal.h"
|
||||
|
||||
HurtByTargetGoal::HurtByTargetGoal(Mob* mob, bool alertSameType)
|
||||
: TargetGoal(mob, 16, false) {
|
||||
HurtByTargetGoal::HurtByTargetGoal(PathfinderMob* mob, bool alertSameType)
|
||||
: TargetGoal(mob, false) {
|
||||
this->alertSameType = alertSameType;
|
||||
setRequiredControlFlags(TargetGoal::TargetFlag);
|
||||
timestamp = 0;
|
||||
}
|
||||
|
||||
bool HurtByTargetGoal::canUse() {
|
||||
return canAttack(mob->getLastHurtByMob(), false);
|
||||
int ts = mob->getLastHurtByMobTimestamp();
|
||||
return ts != timestamp && canAttack(mob->getLastHurtByMob(), false);
|
||||
}
|
||||
|
||||
void HurtByTargetGoal::start() {
|
||||
mob->setTarget(mob->getLastHurtByMob());
|
||||
oldHurtByMob = mob->getLastHurtByMob();
|
||||
timestamp = mob->getLastHurtByMobTimestamp();
|
||||
|
||||
if (alertSameType) {
|
||||
double within = getFollowDistance();
|
||||
std::vector<std::shared_ptr<Entity> >* nearby =
|
||||
mob->level->getEntitiesOfClass(
|
||||
typeid(*mob), AABB::newTemp(mob->x, mob->y, mob->z, mob->x + 1,
|
||||
mob->y + 1, mob->z + 1)
|
||||
->grow(within, 4, within));
|
||||
for (AUTO_VAR(it, nearby->begin()); it != nearby->end(); ++it) {
|
||||
std::shared_ptr<Mob> other = std::dynamic_pointer_cast<Mob>(*it);
|
||||
std::shared_ptr<PathfinderMob> other =
|
||||
std::dynamic_pointer_cast<PathfinderMob>(*it);
|
||||
if (this->mob->shared_from_this() == other) continue;
|
||||
if (other->getTarget() != NULL) continue;
|
||||
if (other->isAlliedTo(mob->getLastHurtByMob()))
|
||||
continue; // don't target allies
|
||||
other->setTarget(mob->getLastHurtByMob());
|
||||
}
|
||||
delete nearby;
|
||||
}
|
||||
|
||||
TargetGoal::start();
|
||||
}
|
||||
|
||||
void HurtByTargetGoal::tick() {
|
||||
if (mob->getLastHurtByMob() != NULL &&
|
||||
mob->getLastHurtByMob() != oldHurtByMob) {
|
||||
this->start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,12 +5,11 @@
|
|||
class HurtByTargetGoal : public TargetGoal {
|
||||
private:
|
||||
bool alertSameType;
|
||||
std::shared_ptr<Mob> oldHurtByMob;
|
||||
int timestamp;
|
||||
|
||||
public:
|
||||
HurtByTargetGoal(Mob* mob, bool alertSameType);
|
||||
HurtByTargetGoal(PathfinderMob* mob, bool alertSameType);
|
||||
|
||||
bool canUse();
|
||||
void start();
|
||||
void tick();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
#include "LeapAtTargetGoal.h"
|
||||
|
||||
LeapAtTargetGoal::LeapAtTargetGoal(Mob* mob, float yd) {
|
||||
target = std::weak_ptr<Mob>();
|
||||
target = std::weak_ptr<LivingEntity>();
|
||||
|
||||
this->mob = mob;
|
||||
this->yd = yd;
|
||||
|
|
@ -13,7 +13,7 @@ LeapAtTargetGoal::LeapAtTargetGoal(Mob* mob, float yd) {
|
|||
}
|
||||
|
||||
bool LeapAtTargetGoal::canUse() {
|
||||
target = std::weak_ptr<Mob>(mob->getTarget());
|
||||
target = std::weak_ptr<LivingEntity>(mob->getTarget());
|
||||
if (target.lock() == NULL) return false;
|
||||
double d = mob->distanceToSqr(target.lock());
|
||||
if (d < 2 * 2 || d > 4 * 4) return false;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
class LeapAtTargetGoal : public Goal {
|
||||
private:
|
||||
Mob* mob; // Owner of this goal
|
||||
std::weak_ptr<Mob> target;
|
||||
std::weak_ptr<LivingEntity> target;
|
||||
float yd;
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ LookAtPlayerGoal::LookAtPlayerGoal(Mob* mob, const std::type_info& lookAtType,
|
|||
: lookAtType(lookAtType) {
|
||||
this->mob = mob;
|
||||
this->lookDistance = lookDistance;
|
||||
this->probability = 0.02f;
|
||||
probability = 0.02f;
|
||||
setRequiredControlFlags(Control::LookControlFlag);
|
||||
|
||||
lookTime = 0;
|
||||
|
|
@ -29,13 +29,18 @@ LookAtPlayerGoal::LookAtPlayerGoal(Mob* mob, const std::type_info& lookAtType,
|
|||
|
||||
bool LookAtPlayerGoal::canUse() {
|
||||
if (mob->getRandom()->nextFloat() >= probability) return false;
|
||||
if (lookAtType == typeid(Player))
|
||||
|
||||
if (mob->getTarget() != NULL) {
|
||||
lookAt = mob->getTarget();
|
||||
}
|
||||
if (lookAtType == typeid(Player)) {
|
||||
lookAt =
|
||||
mob->level->getNearestPlayer(mob->shared_from_this(), lookDistance);
|
||||
else
|
||||
} else {
|
||||
lookAt = std::weak_ptr<Entity>(mob->level->getClosestEntityOfClass(
|
||||
lookAtType, mob->bb->grow(lookDistance, 3, lookDistance),
|
||||
mob->shared_from_this()));
|
||||
}
|
||||
return lookAt.lock() != NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -76,6 +76,10 @@ bool MakeLoveGoal::villageNeedsMoreVillagers() {
|
|||
std::shared_ptr<Village> _village = village.lock();
|
||||
if (_village == NULL) return false;
|
||||
|
||||
if (!_village->isBreedTimerOk()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int idealSize = (int)((float)_village->getDoorCount() * 0.35);
|
||||
// System.out.println("idealSize: " + idealSize + " pop: " +
|
||||
// village.getPopulationSize());
|
||||
|
|
@ -90,11 +94,9 @@ void MakeLoveGoal::breed() {
|
|||
villager->setAge(5 * 60 * 20);
|
||||
// 4J - added limit to number of animals that can be bred
|
||||
if (level->canCreateMore(eTYPE_VILLAGER, Level::eSpawnType_Breed)) {
|
||||
std::shared_ptr<Villager> child =
|
||||
std::shared_ptr<Villager>(new Villager(level));
|
||||
std::shared_ptr<Villager> child = std::dynamic_pointer_cast<Villager>(
|
||||
villager->getBreedOffspring(partner.lock()));
|
||||
child->setAge(-20 * 60 * 20);
|
||||
child->setProfession(
|
||||
villager->getRandom()->nextInt(Villager::PROFESSION_MAX));
|
||||
child->moveTo(villager->x, villager->y, villager->z, 0, 0);
|
||||
level->addEntity(child);
|
||||
level->broadcastEntityEvent(child, EntityEvent::LOVE_HEARTS);
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@
|
|||
#include "../../Headers/net.minecraft.world.entity.ai.sensing.h"
|
||||
#include "../../Headers/net.minecraft.world.phys.h"
|
||||
#include "MeleeAttackGoal.h"
|
||||
#include "../Navigation/Path.h"
|
||||
|
||||
void MeleeAttackGoal::_init(Mob* mob, float speed, bool trackTarget) {
|
||||
void MeleeAttackGoal::_init(PathfinderMob* mob, double speedModifier,
|
||||
bool trackTarget) {
|
||||
this->attackType = eTYPE_NOTSET;
|
||||
this->mob = mob;
|
||||
this->level = mob->level;
|
||||
this->speed = speed;
|
||||
level = mob->level;
|
||||
this->speedModifier = speedModifier;
|
||||
this->trackTarget = trackTarget;
|
||||
setRequiredControlFlags(Control::MoveControlFlag |
|
||||
Control::LookControlFlag);
|
||||
|
|
@ -23,14 +23,15 @@ void MeleeAttackGoal::_init(Mob* mob, float speed, bool trackTarget) {
|
|||
timeToRecalcPath = 0;
|
||||
}
|
||||
|
||||
MeleeAttackGoal::MeleeAttackGoal(Mob* mob, eINSTANCEOF attackType, float speed,
|
||||
bool trackTarget) {
|
||||
_init(mob, speed, trackTarget);
|
||||
MeleeAttackGoal::MeleeAttackGoal(PathfinderMob* mob, eINSTANCEOF attackType,
|
||||
double speedModifier, bool trackTarget) {
|
||||
_init(mob, speedModifier, trackTarget);
|
||||
this->attackType = attackType;
|
||||
}
|
||||
|
||||
MeleeAttackGoal::MeleeAttackGoal(Mob* mob, float speed, bool trackTarget) {
|
||||
_init(mob, speed, trackTarget);
|
||||
MeleeAttackGoal::MeleeAttackGoal(PathfinderMob* mob, double speedModifier,
|
||||
bool trackTarget) {
|
||||
_init(mob, speedModifier, trackTarget);
|
||||
}
|
||||
|
||||
MeleeAttackGoal::~MeleeAttackGoal() {
|
||||
|
|
@ -38,57 +39,53 @@ MeleeAttackGoal::~MeleeAttackGoal() {
|
|||
}
|
||||
|
||||
bool MeleeAttackGoal::canUse() {
|
||||
std::shared_ptr<Mob> bestTarget = mob->getTarget();
|
||||
if (bestTarget == NULL) return false;
|
||||
if (!bestTarget->isAlive()) return false;
|
||||
if (attackType != eTYPE_NOTSET &&
|
||||
(attackType & bestTarget->GetType()) != attackType)
|
||||
return false;
|
||||
target = std::weak_ptr<Mob>(bestTarget);
|
||||
std::shared_ptr<LivingEntity> target = mob->getTarget();
|
||||
if (target == NULL) return false;
|
||||
if (!target->isAlive()) return false;
|
||||
if (attackType != NULL && !target->instanceof(attackType)) return false;
|
||||
delete path;
|
||||
path = mob->getNavigation()->createPath(target.lock());
|
||||
path = mob->getNavigation()->createPath(target);
|
||||
return path != NULL;
|
||||
}
|
||||
|
||||
bool MeleeAttackGoal::canContinueToUse() {
|
||||
std::shared_ptr<Mob> bestTarget = mob->getTarget();
|
||||
if (bestTarget == NULL) return false;
|
||||
if (target.lock() == NULL || !target.lock()->isAlive()) return false;
|
||||
std::shared_ptr<LivingEntity> target = mob->getTarget();
|
||||
if (target == NULL) return false;
|
||||
if (!target->isAlive()) return false;
|
||||
if (!trackTarget) return !mob->getNavigation()->isDone();
|
||||
if (!mob->isWithinRestriction(Mth::floor(target.lock()->x),
|
||||
Mth::floor(target.lock()->y),
|
||||
Mth::floor(target.lock()->z)))
|
||||
if (!mob->isWithinRestriction(Mth::floor(target->x), Mth::floor(target->y),
|
||||
Mth::floor(target->z)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void MeleeAttackGoal::start() {
|
||||
mob->getNavigation()->moveTo(path, speed);
|
||||
mob->getNavigation()->moveTo(path, speedModifier);
|
||||
path = NULL;
|
||||
timeToRecalcPath = 0;
|
||||
}
|
||||
|
||||
void MeleeAttackGoal::stop() {
|
||||
target = std::weak_ptr<Mob>();
|
||||
mob->getNavigation()->stop();
|
||||
}
|
||||
void MeleeAttackGoal::stop() { mob->getNavigation()->stop(); }
|
||||
|
||||
void MeleeAttackGoal::tick() {
|
||||
mob->getLookControl()->setLookAt(target.lock(), 30, 30);
|
||||
if (trackTarget || mob->getSensing()->canSee(target.lock())) {
|
||||
std::shared_ptr<LivingEntity> target = mob->getTarget();
|
||||
mob->getLookControl()->setLookAt(target, 30, 30);
|
||||
if (trackTarget || mob->getSensing()->canSee(target)) {
|
||||
if (--timeToRecalcPath <= 0) {
|
||||
timeToRecalcPath = 4 + mob->getRandom()->nextInt(7);
|
||||
mob->getNavigation()->moveTo(target.lock(), speed);
|
||||
mob->getNavigation()->moveTo(target, speedModifier);
|
||||
}
|
||||
}
|
||||
|
||||
attackTime = std::max(attackTime - 1, 0);
|
||||
|
||||
double meleeRadiusSqr = (mob->bbWidth * 2) * (mob->bbWidth * 2);
|
||||
if (mob->distanceToSqr(target.lock()->x, target.lock()->bb->y0,
|
||||
target.lock()->z) > meleeRadiusSqr)
|
||||
double meleeRadiusSqr =
|
||||
(mob->bbWidth * 2) * (mob->bbWidth * 2) + target->bbWidth;
|
||||
if (mob->distanceToSqr(target->x, target->bb->y0, target->z) >
|
||||
meleeRadiusSqr)
|
||||
return;
|
||||
if (attackTime > 0) return;
|
||||
attackTime = 20;
|
||||
mob->doHurtTarget(target.lock());
|
||||
if (mob->getCarriedItem() != NULL) mob->swing();
|
||||
mob->doHurtTarget(target);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,28 +3,26 @@
|
|||
#include "Goal.h"
|
||||
|
||||
class Level;
|
||||
class Mob;
|
||||
class PathfinderMob;
|
||||
class Path;
|
||||
|
||||
class MeleeAttackGoal : public Goal {
|
||||
private:
|
||||
Level* level;
|
||||
Mob* mob; // Owner of this goal
|
||||
std::weak_ptr<Mob> target;
|
||||
|
||||
PathfinderMob* mob; // Owner of this goal
|
||||
int attackTime;
|
||||
float speed;
|
||||
double speedModifier;
|
||||
bool trackTarget;
|
||||
Path* path;
|
||||
eINSTANCEOF attackType;
|
||||
int timeToRecalcPath;
|
||||
|
||||
void _init(Mob* mob, float speed, bool trackTarget);
|
||||
void _init(PathfinderMob* mob, double speedModifier, bool trackTarget);
|
||||
|
||||
public:
|
||||
MeleeAttackGoal(Mob* mob, eINSTANCEOF attackType, float speed,
|
||||
bool trackTarget);
|
||||
MeleeAttackGoal(Mob* mob, float speed, bool trackTarget);
|
||||
MeleeAttackGoal(PathfinderMob* mob, eINSTANCEOF attackType,
|
||||
double speedModifier, bool trackTarget);
|
||||
MeleeAttackGoal(PathfinderMob* mob, double speedModifier, bool trackTarget);
|
||||
~MeleeAttackGoal();
|
||||
|
||||
virtual bool canUse();
|
||||
|
|
|
|||
|
|
@ -51,11 +51,11 @@ void MoveIndoorsGoal::start() {
|
|||
_doorInfo->getIndoorY(),
|
||||
_doorInfo->getIndoorZ() + 0.5));
|
||||
if (pos != NULL)
|
||||
mob->getNavigation()->moveTo(pos->x, pos->y, pos->z, 0.3f);
|
||||
mob->getNavigation()->moveTo(pos->x, pos->y, pos->z, 1.0f);
|
||||
} else
|
||||
mob->getNavigation()->moveTo(_doorInfo->getIndoorX() + 0.5,
|
||||
_doorInfo->getIndoorY(),
|
||||
_doorInfo->getIndoorZ() + 0.5, 0.3f);
|
||||
_doorInfo->getIndoorZ() + 0.5, 1.0f);
|
||||
}
|
||||
|
||||
void MoveIndoorsGoal::stop() {
|
||||
|
|
|
|||
|
|
@ -9,13 +9,14 @@
|
|||
#include "MoveThroughVillageGoal.h"
|
||||
#include "../Navigation/Path.h"
|
||||
|
||||
MoveThroughVillageGoal::MoveThroughVillageGoal(PathfinderMob* mob, float speed,
|
||||
MoveThroughVillageGoal::MoveThroughVillageGoal(PathfinderMob* mob,
|
||||
double speedModifier,
|
||||
bool onlyAtNight) {
|
||||
path = NULL;
|
||||
doorInfo = std::weak_ptr<DoorInfo>();
|
||||
|
||||
this->mob = mob;
|
||||
this->speed = speed;
|
||||
this->speedModifier = speedModifier;
|
||||
this->onlyAtNight = onlyAtNight;
|
||||
setRequiredControlFlags(Control::MoveControlFlag);
|
||||
}
|
||||
|
|
@ -68,7 +69,7 @@ bool MoveThroughVillageGoal::canContinueToUse() {
|
|||
}
|
||||
|
||||
void MoveThroughVillageGoal::start() {
|
||||
mob->getNavigation()->moveTo(path, speed);
|
||||
mob->getNavigation()->moveTo(path, speedModifier);
|
||||
path = NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,14 +9,15 @@ class DoorInfo;
|
|||
class MoveThroughVillageGoal : public Goal {
|
||||
private:
|
||||
PathfinderMob* mob;
|
||||
float speed;
|
||||
double speedModifier;
|
||||
Path* path;
|
||||
std::weak_ptr<DoorInfo> doorInfo;
|
||||
bool onlyAtNight;
|
||||
std::vector<std::weak_ptr<DoorInfo> > visited;
|
||||
|
||||
public:
|
||||
MoveThroughVillageGoal(PathfinderMob* mob, float speed, bool onlyAtNight);
|
||||
MoveThroughVillageGoal(PathfinderMob* mob, double speedModifier,
|
||||
bool onlyAtNight);
|
||||
~MoveThroughVillageGoal();
|
||||
|
||||
virtual bool canUse();
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@
|
|||
#include "MoveTowardsRestrictionGoal.h"
|
||||
|
||||
MoveTowardsRestrictionGoal::MoveTowardsRestrictionGoal(PathfinderMob* mob,
|
||||
float speed) {
|
||||
double speedModifier) {
|
||||
wantedX = wantedY = wantedZ = 0.0;
|
||||
|
||||
this->mob = mob;
|
||||
this->speed = speed;
|
||||
this->speedModifier = speedModifier;
|
||||
setRequiredControlFlags(Control::MoveControlFlag);
|
||||
}
|
||||
|
||||
|
|
@ -33,5 +33,5 @@ bool MoveTowardsRestrictionGoal::canContinueToUse() {
|
|||
}
|
||||
|
||||
void MoveTowardsRestrictionGoal::start() {
|
||||
mob->getNavigation()->moveTo(wantedX, wantedY, wantedZ, speed);
|
||||
mob->getNavigation()->moveTo(wantedX, wantedY, wantedZ, speedModifier);
|
||||
}
|
||||
|
|
@ -6,10 +6,10 @@ class MoveTowardsRestrictionGoal : public Goal {
|
|||
private:
|
||||
PathfinderMob* mob;
|
||||
double wantedX, wantedY, wantedZ;
|
||||
float speed;
|
||||
double speedModifier;
|
||||
|
||||
public:
|
||||
MoveTowardsRestrictionGoal(PathfinderMob* mob, float speed);
|
||||
MoveTowardsRestrictionGoal(PathfinderMob* mob, double speedModifier);
|
||||
|
||||
bool canUse();
|
||||
bool canContinueToUse();
|
||||
|
|
|
|||
|
|
@ -6,16 +6,17 @@
|
|||
#include "../../Headers/net.minecraft.world.phys.h"
|
||||
#include "MoveTowardsTargetGoal.h"
|
||||
|
||||
MoveTowardsTargetGoal::MoveTowardsTargetGoal(PathfinderMob* mob, float speed,
|
||||
MoveTowardsTargetGoal::MoveTowardsTargetGoal(PathfinderMob* mob,
|
||||
double speedModifier,
|
||||
float within) {
|
||||
this->mob = mob;
|
||||
this->speed = speed;
|
||||
this->speedModifier = speedModifier;
|
||||
this->within = within;
|
||||
setRequiredControlFlags(Control::MoveControlFlag);
|
||||
}
|
||||
|
||||
bool MoveTowardsTargetGoal::canUse() {
|
||||
target = std::weak_ptr<Mob>(mob->getTarget());
|
||||
target = std::weak_ptr<LivingEntity>(mob->getTarget());
|
||||
if (target.lock() == NULL) return false;
|
||||
if (target.lock()->distanceToSqr(mob->shared_from_this()) > within * within)
|
||||
return false;
|
||||
|
|
@ -39,5 +40,5 @@ bool MoveTowardsTargetGoal::canContinueToUse() {
|
|||
void MoveTowardsTargetGoal::stop() { target = std::weak_ptr<Mob>(); }
|
||||
|
||||
void MoveTowardsTargetGoal::start() {
|
||||
mob->getNavigation()->moveTo(wantedX, wantedY, wantedZ, speed);
|
||||
mob->getNavigation()->moveTo(wantedX, wantedY, wantedZ, speedModifier);
|
||||
}
|
||||
|
|
@ -5,12 +5,14 @@
|
|||
class MoveTowardsTargetGoal : public Goal {
|
||||
private:
|
||||
PathfinderMob* mob;
|
||||
std::weak_ptr<Mob> target;
|
||||
std::weak_ptr<LivingEntity> target;
|
||||
double wantedX, wantedY, wantedZ;
|
||||
float speed, within;
|
||||
double speedModifier;
|
||||
float within;
|
||||
|
||||
public:
|
||||
MoveTowardsTargetGoal(PathfinderMob* mob, float speed, float within);
|
||||
MoveTowardsTargetGoal(PathfinderMob* mob, double speedModifier,
|
||||
float within);
|
||||
|
||||
bool canUse();
|
||||
bool canContinueToUse();
|
||||
|
|
|
|||
|
|
@ -4,6 +4,21 @@
|
|||
#include "../../Headers/net.minecraft.world.phys.h"
|
||||
#include "NearestAttackableTargetGoal.h"
|
||||
|
||||
SubselectEntitySelector::SubselectEntitySelector(
|
||||
NearestAttackableTargetGoal* parent, EntitySelector* subselector) {
|
||||
m_parent = parent;
|
||||
m_subselector = subselector;
|
||||
}
|
||||
|
||||
SubselectEntitySelector::~SubselectEntitySelector() { delete m_subselector; }
|
||||
|
||||
bool SubselectEntitySelector::matches(std::shared_ptr<Entity> entity) const {
|
||||
if (!entity->instanceof(eTYPE_LIVINGENTITY)) return false;
|
||||
if (m_subselector != NULL && !m_subselector->matches(entity)) return false;
|
||||
return m_parent->canAttack(std::dynamic_pointer_cast<LivingEntity>(entity),
|
||||
false);
|
||||
}
|
||||
|
||||
NearestAttackableTargetGoal::DistComp::DistComp(Entity* source) {
|
||||
this->source = source;
|
||||
}
|
||||
|
|
@ -19,46 +34,41 @@ bool NearestAttackableTargetGoal::DistComp::operator()(
|
|||
}
|
||||
|
||||
NearestAttackableTargetGoal::NearestAttackableTargetGoal(
|
||||
Mob* mob, const std::type_info& targetType, float within,
|
||||
int randomInterval, bool mustSee, bool mustReach /*= false*/)
|
||||
: TargetGoal(mob, within, mustSee, mustReach), targetType(targetType) {
|
||||
// this->targetType = targetType;
|
||||
this->within = within;
|
||||
PathfinderMob* mob, const std::type_info& targetType, int randomInterval,
|
||||
bool mustSee, bool mustReach /*= false*/,
|
||||
EntitySelector* entitySelector /* =NULL */)
|
||||
: TargetGoal(mob, mustSee, mustReach), targetType(targetType) {
|
||||
this->randomInterval = randomInterval;
|
||||
this->distComp = new DistComp(mob);
|
||||
setRequiredControlFlags(TargetGoal::TargetFlag);
|
||||
|
||||
this->selector = new SubselectEntitySelector(this, entitySelector);
|
||||
}
|
||||
|
||||
NearestAttackableTargetGoal::~NearestAttackableTargetGoal() { delete distComp; }
|
||||
NearestAttackableTargetGoal::~NearestAttackableTargetGoal() {
|
||||
delete distComp;
|
||||
delete selector;
|
||||
}
|
||||
|
||||
bool NearestAttackableTargetGoal::canUse() {
|
||||
if (randomInterval > 0 && mob->getRandom()->nextInt(randomInterval) != 0)
|
||||
return false;
|
||||
if (targetType == typeid(Player)) {
|
||||
std::shared_ptr<Mob> potentialTarget =
|
||||
mob->level->getNearestAttackablePlayer(mob->shared_from_this(),
|
||||
within);
|
||||
if (canAttack(potentialTarget, false)) {
|
||||
target = std::weak_ptr<Mob>(potentialTarget);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
std::vector<std::shared_ptr<Entity> >* entities =
|
||||
mob->level->getEntitiesOfClass(targetType,
|
||||
mob->bb->grow(within, 4, within));
|
||||
// Collections.sort(entities, distComp);
|
||||
double within = getFollowDistance();
|
||||
|
||||
std::vector<std::shared_ptr<Entity> >* entities =
|
||||
mob->level->getEntitiesOfClass(
|
||||
targetType, mob->bb->grow(within, 4, within), selector);
|
||||
|
||||
bool result = false;
|
||||
if (entities != NULL && !entities->empty()) {
|
||||
std::sort(entities->begin(), entities->end(), *distComp);
|
||||
for (AUTO_VAR(it, entities->begin()); it != entities->end(); ++it) {
|
||||
std::shared_ptr<Mob> potTarget =
|
||||
std::dynamic_pointer_cast<Mob>(*it);
|
||||
if (canAttack(potTarget, false)) {
|
||||
target = std::weak_ptr<Mob>(potTarget);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
delete entities;
|
||||
target = std::weak_ptr<LivingEntity>(
|
||||
std::dynamic_pointer_cast<LivingEntity>(entities->at(0)));
|
||||
result = true;
|
||||
}
|
||||
return false;
|
||||
|
||||
delete entities;
|
||||
return result;
|
||||
}
|
||||
|
||||
void NearestAttackableTargetGoal::start() {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
#include "TargetGoal.h"
|
||||
#include "../../Entities/EntitySelector.h"
|
||||
|
||||
class NearestAttackableTargetGoal;
|
||||
|
||||
// Anonymous class from NearestAttackableTargetGoal
|
||||
class SubselectEntitySelector : public EntitySelector {
|
||||
private:
|
||||
EntitySelector* m_subselector;
|
||||
NearestAttackableTargetGoal* m_parent;
|
||||
|
||||
public:
|
||||
SubselectEntitySelector(NearestAttackableTargetGoal* parent,
|
||||
EntitySelector* subselector);
|
||||
~SubselectEntitySelector();
|
||||
bool matches(std::shared_ptr<Entity> entity) const;
|
||||
};
|
||||
|
||||
class NearestAttackableTargetGoal : public TargetGoal {
|
||||
friend class SubselectEntitySelector;
|
||||
|
||||
public:
|
||||
class DistComp {
|
||||
private:
|
||||
|
|
@ -15,21 +33,19 @@ public:
|
|||
};
|
||||
|
||||
private:
|
||||
std::weak_ptr<Mob> target;
|
||||
const std::type_info& targetType;
|
||||
int randomInterval;
|
||||
DistComp* distComp;
|
||||
EntitySelector* selector;
|
||||
std::weak_ptr<LivingEntity> target;
|
||||
|
||||
public:
|
||||
// public NearestAttackableTargetGoal(Mob mob, const std::type_info&
|
||||
// targetType, float within, int randomInterval, bool mustSee)
|
||||
//{
|
||||
// this(mob, targetType, within, randomInterval, mustSee, false);
|
||||
// }
|
||||
NearestAttackableTargetGoal(PathfinderMob* mob,
|
||||
const std::type_info& targetType,
|
||||
int randomInterval, bool mustSee,
|
||||
bool mustReach = false,
|
||||
EntitySelector* entitySelector = NULL);
|
||||
|
||||
NearestAttackableTargetGoal(Mob* mob, const std::type_info& targetType,
|
||||
float within, int randomInterval, bool mustSee,
|
||||
bool mustReach = false);
|
||||
virtual ~NearestAttackableTargetGoal();
|
||||
|
||||
virtual bool canUse();
|
||||
|
|
|
|||
|
|
@ -3,14 +3,12 @@
|
|||
#include "NonTameRandomTargetGoal.h"
|
||||
|
||||
NonTameRandomTargetGoal::NonTameRandomTargetGoal(
|
||||
TamableAnimal* mob, const std::type_info& targetType, float within,
|
||||
int randomInterval, bool mustSee)
|
||||
: NearestAttackableTargetGoal(mob, targetType, within, randomInterval,
|
||||
mustSee) {
|
||||
this->tamableMob = mob;
|
||||
TamableAnimal* mob, const std::type_info& targetType, int randomInterval,
|
||||
bool mustSee)
|
||||
: NearestAttackableTargetGoal(mob, targetType, randomInterval, mustSee) {
|
||||
tamableMob = mob;
|
||||
}
|
||||
|
||||
bool NonTameRandomTargetGoal::canUse() {
|
||||
if (tamableMob->isTame()) return false;
|
||||
return NearestAttackableTargetGoal::canUse();
|
||||
return !tamableMob->isTame() && NearestAttackableTargetGoal::canUse();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ private:
|
|||
|
||||
public:
|
||||
NonTameRandomTargetGoal(TamableAnimal* mob,
|
||||
const std::type_info& targetType, float within,
|
||||
const std::type_info& targetType,
|
||||
int randomInterval, bool mustSee);
|
||||
|
||||
bool canUse();
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@
|
|||
#include "../../Headers/net.minecraft.world.phys.h"
|
||||
#include "OcelotAttackGoal.h"
|
||||
|
||||
OzelotAttackGoal::OzelotAttackGoal(Mob* mob) {
|
||||
target = std::weak_ptr<Mob>();
|
||||
OcelotAttackGoal::OcelotAttackGoal(Mob* mob) {
|
||||
target = std::weak_ptr<LivingEntity>();
|
||||
attackTime = 0;
|
||||
speed = 0;
|
||||
trackTarget = false;
|
||||
|
|
@ -18,38 +18,38 @@ OzelotAttackGoal::OzelotAttackGoal(Mob* mob) {
|
|||
Control::LookControlFlag);
|
||||
}
|
||||
|
||||
bool OzelotAttackGoal::canUse() {
|
||||
std::shared_ptr<Mob> bestTarget = mob->getTarget();
|
||||
bool OcelotAttackGoal::canUse() {
|
||||
std::shared_ptr<LivingEntity> bestTarget = mob->getTarget();
|
||||
if (bestTarget == NULL) return false;
|
||||
target = std::weak_ptr<Mob>(bestTarget);
|
||||
target = std::weak_ptr<LivingEntity>(bestTarget);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OzelotAttackGoal::canContinueToUse() {
|
||||
bool OcelotAttackGoal::canContinueToUse() {
|
||||
if (target.lock() == NULL || !target.lock()->isAlive()) return false;
|
||||
if (mob->distanceToSqr(target.lock()) > 15 * 15) return false;
|
||||
return !mob->getNavigation()->isDone() || canUse();
|
||||
}
|
||||
|
||||
void OzelotAttackGoal::stop() {
|
||||
void OcelotAttackGoal::stop() {
|
||||
target = std::weak_ptr<Mob>();
|
||||
mob->getNavigation()->stop();
|
||||
}
|
||||
|
||||
void OzelotAttackGoal::tick() {
|
||||
void OcelotAttackGoal::tick() {
|
||||
mob->getLookControl()->setLookAt(target.lock(), 30, 30);
|
||||
|
||||
double meleeRadiusSqr = (mob->bbWidth * 2) * (mob->bbWidth * 2);
|
||||
double distSqr = mob->distanceToSqr(target.lock()->x, target.lock()->bb->y0,
|
||||
target.lock()->z);
|
||||
|
||||
float speed = Ozelot::WALK_SPEED;
|
||||
double speedModifier = Ocelot::WALK_SPEED_MOD;
|
||||
if (distSqr > meleeRadiusSqr && distSqr < 4 * 4)
|
||||
speed = Ozelot::SPRINT_SPEED;
|
||||
speedModifier = Ocelot::SPRINT_SPEED_MOD;
|
||||
else if (distSqr < 15 * 15)
|
||||
speed = Ozelot::SNEAK_SPEED;
|
||||
speedModifier = Ocelot::SNEAK_SPEED_MOD;
|
||||
|
||||
mob->getNavigation()->moveTo(target.lock(), speed);
|
||||
mob->getNavigation()->moveTo(target.lock(), speedModifier);
|
||||
|
||||
attackTime = std::max(attackTime - 1, 0);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,17 +2,17 @@
|
|||
|
||||
#include "Goal.h"
|
||||
|
||||
class OzelotAttackGoal : public Goal {
|
||||
class OcelotAttackGoal : public Goal {
|
||||
private:
|
||||
Level* level;
|
||||
Mob* mob;
|
||||
std::weak_ptr<Mob> target;
|
||||
std::weak_ptr<LivingEntity> target;
|
||||
int attackTime;
|
||||
float speed;
|
||||
bool trackTarget;
|
||||
|
||||
public:
|
||||
OzelotAttackGoal(Mob* mob);
|
||||
OcelotAttackGoal(Mob* mob);
|
||||
|
||||
virtual bool canUse();
|
||||
virtual bool canContinueToUse();
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ const int OcelotSitOnTileGoal::SIT_TICKS =
|
|||
const int OcelotSitOnTileGoal::SEARCH_RANGE = 8;
|
||||
const double OcelotSitOnTileGoal::SIT_CHANCE = 0.0065f;
|
||||
|
||||
OcelotSitOnTileGoal::OcelotSitOnTileGoal(Ozelot* ocelot, float speed) {
|
||||
OcelotSitOnTileGoal::OcelotSitOnTileGoal(Ocelot* ocelot, double speedModifier) {
|
||||
_tick = 0;
|
||||
tryTicks = 0;
|
||||
maxTicks = 0;
|
||||
|
|
@ -26,7 +26,7 @@ OcelotSitOnTileGoal::OcelotSitOnTileGoal(Ozelot* ocelot, float speed) {
|
|||
tileZ = 0;
|
||||
|
||||
this->ocelot = ocelot;
|
||||
this->speed = speed;
|
||||
this->speedModifier = speedModifier;
|
||||
setRequiredControlFlags(Control::MoveControlFlag |
|
||||
Control::JumpControlFlag);
|
||||
}
|
||||
|
|
@ -43,16 +43,22 @@ bool OcelotSitOnTileGoal::canContinueToUse() {
|
|||
|
||||
void OcelotSitOnTileGoal::start() {
|
||||
ocelot->getNavigation()->moveTo((float)tileX + 0.5, tileY + 1,
|
||||
(float)tileZ + 0.5, speed);
|
||||
(float)tileZ + 0.5, speedModifier);
|
||||
_tick = 0;
|
||||
tryTicks = 0;
|
||||
maxTicks = ocelot->getRandom()->nextInt(
|
||||
ocelot->getRandom()->nextInt(SIT_TICKS) + SIT_TICKS) +
|
||||
SIT_TICKS;
|
||||
ocelot->getSitGoal()->wantToSit(false);
|
||||
|
||||
ocelot->setSittingOnTile(true); // 4J-Added.
|
||||
}
|
||||
|
||||
void OcelotSitOnTileGoal::stop() { ocelot->setSitting(false); }
|
||||
void OcelotSitOnTileGoal::stop() {
|
||||
ocelot->setSitting(false);
|
||||
|
||||
ocelot->setSittingOnTile(false); // 4J-Added.
|
||||
}
|
||||
|
||||
void OcelotSitOnTileGoal::tick() {
|
||||
_tick++;
|
||||
|
|
@ -60,7 +66,7 @@ void OcelotSitOnTileGoal::tick() {
|
|||
if (ocelot->distanceToSqr(tileX, tileY + 1, tileZ) > 1) {
|
||||
ocelot->setSitting(false);
|
||||
ocelot->getNavigation()->moveTo((float)tileX + 0.5, tileY + 1,
|
||||
(float)tileZ + 0.5, speed);
|
||||
(float)tileZ + 0.5, speedModifier);
|
||||
tryTicks++;
|
||||
} else if (!ocelot->isSitting()) {
|
||||
ocelot->setSitting(true);
|
||||
|
|
@ -82,9 +88,9 @@ bool OcelotSitOnTileGoal::findNearestTile() {
|
|||
double dist = ocelot->distanceToSqr(x, y, z);
|
||||
|
||||
if (dist < distSqr) {
|
||||
this->tileX = x;
|
||||
this->tileY = y;
|
||||
this->tileZ = z;
|
||||
tileX = x;
|
||||
tileY = y;
|
||||
tileZ = z;
|
||||
distSqr = dist;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "Goal.h"
|
||||
|
||||
class Ozelot;
|
||||
class Ocelot;
|
||||
|
||||
class OcelotSitOnTileGoal : public Goal {
|
||||
private:
|
||||
|
|
@ -12,8 +12,8 @@ private:
|
|||
static const double SIT_CHANCE;
|
||||
|
||||
private:
|
||||
Ozelot* ocelot; // Owner of this goal
|
||||
float speed;
|
||||
Ocelot* ocelot; // Owner of this goal
|
||||
double speedModifier;
|
||||
int _tick;
|
||||
int tryTicks;
|
||||
int maxTicks;
|
||||
|
|
@ -22,7 +22,7 @@ private:
|
|||
int tileZ;
|
||||
|
||||
public:
|
||||
OcelotSitOnTileGoal(Ozelot* ocelot, float speed);
|
||||
OcelotSitOnTileGoal(Ocelot* ocelot, double speedModifier);
|
||||
|
||||
bool canUse();
|
||||
bool canContinueToUse();
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
OpenDoorGoal::OpenDoorGoal(Mob* mob, bool closeDoorAfter)
|
||||
: DoorInteractGoal(mob) {
|
||||
this->mob = mob;
|
||||
this->closeDoor = closeDoorAfter;
|
||||
closeDoor = closeDoorAfter;
|
||||
}
|
||||
|
||||
bool OpenDoorGoal::canContinueToUse() {
|
||||
|
|
|
|||
|
|
@ -6,18 +6,31 @@
|
|||
OwnerHurtByTargetGoal::OwnerHurtByTargetGoal(TamableAnimal* tameAnimal)
|
||||
: TargetGoal(tameAnimal, 32, false) {
|
||||
this->tameAnimal = tameAnimal;
|
||||
timestamp = 0;
|
||||
setRequiredControlFlags(TargetGoal::TargetFlag);
|
||||
}
|
||||
|
||||
bool OwnerHurtByTargetGoal::canUse() {
|
||||
if (!tameAnimal->isTame()) return false;
|
||||
std::shared_ptr<Mob> owner = tameAnimal->getOwner();
|
||||
std::shared_ptr<LivingEntity> owner =
|
||||
std::dynamic_pointer_cast<LivingEntity>(tameAnimal->getOwner());
|
||||
if (owner == NULL) return false;
|
||||
ownerLastHurtBy = std::weak_ptr<Mob>(owner->getLastHurtByMob());
|
||||
return canAttack(ownerLastHurtBy.lock(), false);
|
||||
ownerLastHurtBy = std::weak_ptr<LivingEntity>(owner->getLastHurtByMob());
|
||||
int ts = owner->getLastHurtByMobTimestamp();
|
||||
|
||||
std::shared_ptr<LivingEntity> locked = ownerLastHurtBy.lock();
|
||||
return ts != timestamp && canAttack(locked, false) &&
|
||||
tameAnimal->wantsToAttack(locked, owner);
|
||||
}
|
||||
|
||||
void OwnerHurtByTargetGoal::start() {
|
||||
mob->setTarget(ownerLastHurtBy.lock());
|
||||
|
||||
std::shared_ptr<LivingEntity> owner =
|
||||
std::dynamic_pointer_cast<LivingEntity>(tameAnimal->getOwner());
|
||||
if (owner != NULL) {
|
||||
timestamp = owner->getLastHurtByMobTimestamp();
|
||||
}
|
||||
|
||||
TargetGoal::start();
|
||||
}
|
||||
|
|
@ -7,7 +7,8 @@ class TamableAnimal;
|
|||
class OwnerHurtByTargetGoal : public TargetGoal {
|
||||
private:
|
||||
TamableAnimal* tameAnimal; // Owner of this goal
|
||||
std::weak_ptr<Mob> ownerLastHurtBy;
|
||||
std::weak_ptr<LivingEntity> ownerLastHurtBy;
|
||||
int timestamp;
|
||||
|
||||
public:
|
||||
OwnerHurtByTargetGoal(TamableAnimal* tameAnimal);
|
||||
|
|
|
|||
|
|
@ -7,17 +7,29 @@ OwnerHurtTargetGoal::OwnerHurtTargetGoal(TamableAnimal* tameAnimal)
|
|||
: TargetGoal(tameAnimal, 32, false) {
|
||||
this->tameAnimal = tameAnimal;
|
||||
setRequiredControlFlags(TargetGoal::TargetFlag);
|
||||
timestamp = 0;
|
||||
}
|
||||
|
||||
bool OwnerHurtTargetGoal::canUse() {
|
||||
if (!tameAnimal->isTame()) return false;
|
||||
std::shared_ptr<Mob> owner = tameAnimal->getOwner();
|
||||
std::shared_ptr<LivingEntity> owner =
|
||||
std::dynamic_pointer_cast<LivingEntity>(tameAnimal->getOwner());
|
||||
if (owner == NULL) return false;
|
||||
ownerLastHurt = std::weak_ptr<Mob>(owner->getLastHurtMob());
|
||||
return canAttack(ownerLastHurt.lock(), false);
|
||||
ownerLastHurt = std::weak_ptr<LivingEntity>(owner->getLastHurtMob());
|
||||
int ts = owner->getLastHurtMobTimestamp();
|
||||
std::shared_ptr<LivingEntity> locked = ownerLastHurt.lock();
|
||||
return ts != timestamp && canAttack(locked, false) &&
|
||||
tameAnimal->wantsToAttack(locked, owner);
|
||||
}
|
||||
|
||||
void OwnerHurtTargetGoal::start() {
|
||||
mob->setTarget(ownerLastHurt.lock());
|
||||
TargetGoal::start();
|
||||
|
||||
std::shared_ptr<LivingEntity> owner =
|
||||
std::dynamic_pointer_cast<LivingEntity>(tameAnimal->getOwner());
|
||||
if (owner != NULL) {
|
||||
timestamp = owner->getLastHurtMobTimestamp();
|
||||
|
||||
TargetGoal::start();
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,8 @@ class TamableAnimal;
|
|||
class OwnerHurtTargetGoal : public TargetGoal {
|
||||
private:
|
||||
TamableAnimal* tameAnimal; // Owner of this goal
|
||||
std::weak_ptr<Mob> ownerLastHurt;
|
||||
std::weak_ptr<LivingEntity> ownerLastHurt;
|
||||
int timestamp;
|
||||
|
||||
public:
|
||||
OwnerHurtTargetGoal(TamableAnimal* tameAnimal);
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@
|
|||
#include "../../Headers/net.minecraft.world.phys.h"
|
||||
#include "PanicGoal.h"
|
||||
|
||||
PanicGoal::PanicGoal(PathfinderMob* mob, float speed) {
|
||||
PanicGoal::PanicGoal(PathfinderMob* mob, double speedModifier) {
|
||||
this->mob = mob;
|
||||
this->speed = speed;
|
||||
this->speedModifier = speedModifier;
|
||||
setRequiredControlFlags(Control::MoveControlFlag);
|
||||
}
|
||||
|
||||
bool PanicGoal::canUse() {
|
||||
if (mob->getLastHurtByMob() == NULL) return false;
|
||||
if (mob->getLastHurtByMob() == NULL && !mob->isOnFire()) return false;
|
||||
Vec3* pos = RandomPos::getPos(
|
||||
std::dynamic_pointer_cast<PathfinderMob>(mob->shared_from_this()), 5,
|
||||
4);
|
||||
|
|
@ -25,7 +25,7 @@ bool PanicGoal::canUse() {
|
|||
}
|
||||
|
||||
void PanicGoal::start() {
|
||||
mob->getNavigation()->moveTo(posX, posY, posZ, speed);
|
||||
mob->getNavigation()->moveTo(posX, posY, posZ, speedModifier);
|
||||
}
|
||||
|
||||
bool PanicGoal::canContinueToUse() { return !mob->getNavigation()->isDone(); }
|
||||
|
|
@ -7,11 +7,11 @@ class PathfinderMob;
|
|||
class PanicGoal : public Goal {
|
||||
private:
|
||||
PathfinderMob* mob;
|
||||
float speed;
|
||||
double speedModifier;
|
||||
double posX, posY, posZ;
|
||||
|
||||
public:
|
||||
PanicGoal(PathfinderMob* mob, float speed);
|
||||
PanicGoal(PathfinderMob* mob, double speedModifier);
|
||||
|
||||
virtual bool canUse();
|
||||
virtual void start();
|
||||
|
|
|
|||
|
|
@ -9,13 +9,13 @@
|
|||
#include "../../Util/BasicTypeContainers.h"
|
||||
#include "PlayGoal.h"
|
||||
|
||||
PlayGoal::PlayGoal(Villager* mob, float speed) {
|
||||
followFriend = std::weak_ptr<Mob>();
|
||||
PlayGoal::PlayGoal(Villager* mob, double speedModifier) {
|
||||
followFriend = std::weak_ptr<LivingEntity>();
|
||||
wantedX = wantedY = wantedZ = 0.0;
|
||||
playTime = 0;
|
||||
|
||||
this->mob = mob;
|
||||
this->speed = speed;
|
||||
this->speedModifier = speedModifier;
|
||||
setRequiredControlFlags(Control::MoveControlFlag);
|
||||
}
|
||||
|
||||
|
|
@ -38,7 +38,7 @@ bool PlayGoal::canUse() {
|
|||
double distSqr = friendV->distanceToSqr(mob->shared_from_this());
|
||||
if (distSqr > closestDistSqr) continue;
|
||||
closestDistSqr = distSqr;
|
||||
followFriend = std::weak_ptr<Mob>(friendV);
|
||||
followFriend = std::weak_ptr<LivingEntity>(friendV);
|
||||
}
|
||||
delete children;
|
||||
|
||||
|
|
@ -62,14 +62,14 @@ void PlayGoal::start() {
|
|||
|
||||
void PlayGoal::stop() {
|
||||
mob->setChasing(false);
|
||||
followFriend = std::weak_ptr<Mob>();
|
||||
followFriend = std::weak_ptr<LivingEntity>();
|
||||
}
|
||||
|
||||
void PlayGoal::tick() {
|
||||
--playTime;
|
||||
if (followFriend.lock() != NULL) {
|
||||
if (mob->distanceToSqr(followFriend.lock()) > 2 * 2)
|
||||
mob->getNavigation()->moveTo(followFriend.lock(), speed);
|
||||
mob->getNavigation()->moveTo(followFriend.lock(), speedModifier);
|
||||
} else {
|
||||
if (mob->getNavigation()->isDone()) {
|
||||
Vec3* pos =
|
||||
|
|
@ -77,7 +77,7 @@ void PlayGoal::tick() {
|
|||
mob->shared_from_this()),
|
||||
16, 3);
|
||||
if (pos == NULL) return;
|
||||
mob->getNavigation()->moveTo(pos->x, pos->y, pos->z, speed);
|
||||
mob->getNavigation()->moveTo(pos->x, pos->y, pos->z, speedModifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,13 +5,13 @@
|
|||
class PlayGoal : public Goal {
|
||||
private:
|
||||
Villager* mob;
|
||||
std::weak_ptr<Mob> followFriend;
|
||||
float speed;
|
||||
std::weak_ptr<LivingEntity> followFriend;
|
||||
double speedModifier;
|
||||
double wantedX, wantedY, wantedZ;
|
||||
int playTime;
|
||||
|
||||
public:
|
||||
PlayGoal(Villager* mob, float speed);
|
||||
PlayGoal(Villager* mob, double speedModifier);
|
||||
|
||||
virtual bool canUse();
|
||||
virtual bool canContinueToUse();
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@
|
|||
#include "../../Util/SharedConstants.h"
|
||||
#include "RandomStrollGoal.h"
|
||||
|
||||
RandomStrollGoal::RandomStrollGoal(PathfinderMob* mob, float speed) {
|
||||
RandomStrollGoal::RandomStrollGoal(PathfinderMob* mob, double speedModifier) {
|
||||
this->mob = mob;
|
||||
this->speed = speed;
|
||||
this->speedModifier = speedModifier;
|
||||
setRequiredControlFlags(Control::MoveControlFlag |
|
||||
Control::LookControlFlag);
|
||||
}
|
||||
|
|
@ -57,5 +57,5 @@ bool RandomStrollGoal::canContinueToUse() {
|
|||
}
|
||||
|
||||
void RandomStrollGoal::start() {
|
||||
mob->getNavigation()->moveTo(wantedX, wantedY, wantedZ, speed);
|
||||
mob->getNavigation()->moveTo(wantedX, wantedY, wantedZ, speedModifier);
|
||||
}
|
||||
|
|
@ -8,10 +8,10 @@ class RandomStrollGoal : public Goal {
|
|||
private:
|
||||
PathfinderMob* mob;
|
||||
double wantedX, wantedY, wantedZ;
|
||||
float speed;
|
||||
double speedModifier;
|
||||
|
||||
public:
|
||||
RandomStrollGoal(PathfinderMob* mob, float speed);
|
||||
RandomStrollGoal(PathfinderMob* mob, double speedModifier);
|
||||
|
||||
virtual bool canUse();
|
||||
virtual bool canContinueToUse();
|
||||
|
|
|
|||
103
Minecraft.World/AI/Goals/RangedAttackGoal.cpp
Normal file
103
Minecraft.World/AI/Goals/RangedAttackGoal.cpp
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
#include "../../Platform/stdafx.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.control.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.navigation.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.sensing.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.monster.h"
|
||||
#include "../../Headers/net.minecraft.world.phys.h"
|
||||
#include "RangedAttackGoal.h"
|
||||
|
||||
void RangedAttackGoal::_init(RangedAttackMob* rangedMob, Mob* mob,
|
||||
double speedModifier, int attackIntervalMin,
|
||||
int attackIntervalMax, float attackRadius) {
|
||||
// if (!(mob instanceof LivingEntity))
|
||||
//{
|
||||
// throw new IllegalArgumentException("ArrowAttackGoal requires Mob
|
||||
// implements RangedAttackMob");
|
||||
// }
|
||||
rangedAttackMob = rangedMob;
|
||||
this->mob = mob;
|
||||
this->speedModifier = speedModifier;
|
||||
this->attackIntervalMin = attackIntervalMin;
|
||||
this->attackIntervalMax = attackIntervalMax;
|
||||
this->attackRadius = attackRadius;
|
||||
attackRadiusSqr = attackRadius * attackRadius;
|
||||
setRequiredControlFlags(Control::MoveControlFlag |
|
||||
Control::LookControlFlag);
|
||||
|
||||
target = std::weak_ptr<LivingEntity>();
|
||||
attackTime = -1;
|
||||
seeTime = 0;
|
||||
}
|
||||
|
||||
RangedAttackGoal::RangedAttackGoal(RangedAttackMob* rangedMob, Mob* mob,
|
||||
double speedModifier, int attackInterval,
|
||||
float attackRadius) {
|
||||
_init(rangedMob, mob, speedModifier, attackInterval, attackInterval,
|
||||
attackRadius);
|
||||
}
|
||||
|
||||
RangedAttackGoal::RangedAttackGoal(RangedAttackMob* rangedMob, Mob* mob,
|
||||
double speedModifier, int attackIntervalMin,
|
||||
int attackIntervalMax, float attackRadius) {
|
||||
_init(rangedMob, mob, speedModifier, attackIntervalMin, attackIntervalMax,
|
||||
attackRadius);
|
||||
}
|
||||
|
||||
bool RangedAttackGoal::canUse() {
|
||||
std::shared_ptr<LivingEntity> bestTarget = mob->getTarget();
|
||||
if (bestTarget == NULL) return false;
|
||||
target = std::weak_ptr<LivingEntity>(bestTarget);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RangedAttackGoal::canContinueToUse() {
|
||||
return canUse() || !mob->getNavigation()->isDone();
|
||||
}
|
||||
|
||||
void RangedAttackGoal::stop() {
|
||||
target = std::weak_ptr<LivingEntity>();
|
||||
seeTime = 0;
|
||||
attackTime = -1;
|
||||
}
|
||||
|
||||
void RangedAttackGoal::tick() {
|
||||
// 4J: It's possible the target has gone since canUse selected it, don't do
|
||||
// tick if target is null
|
||||
if (target.lock() == NULL) return;
|
||||
|
||||
double targetDistSqr = mob->distanceToSqr(
|
||||
target.lock()->x, target.lock()->bb->y0, target.lock()->z);
|
||||
bool canSee = mob->getSensing()->canSee(target.lock());
|
||||
|
||||
if (canSee) {
|
||||
seeTime++;
|
||||
} else {
|
||||
seeTime = 0;
|
||||
}
|
||||
|
||||
if (targetDistSqr > attackRadiusSqr || seeTime < 20) {
|
||||
mob->getNavigation()->moveTo(target.lock(), speedModifier);
|
||||
} else {
|
||||
mob->getNavigation()->stop();
|
||||
}
|
||||
|
||||
mob->getLookControl()->setLookAt(target.lock(), 30, 30);
|
||||
|
||||
if (--attackTime == 0) {
|
||||
if (targetDistSqr > attackRadiusSqr || !canSee) return;
|
||||
|
||||
float dist = Mth::sqrt(targetDistSqr) / attackRadius;
|
||||
float power = dist;
|
||||
if (power < 0.1f) power = 0.1f;
|
||||
if (power > 1) power = 1;
|
||||
|
||||
rangedAttackMob->performRangedAttack(target.lock(), power);
|
||||
attackTime = Mth::floor(dist * (attackIntervalMax - attackIntervalMin) +
|
||||
attackIntervalMin);
|
||||
} else if (attackTime < 0) {
|
||||
float dist = Mth::sqrt(targetDistSqr) / attackRadius;
|
||||
attackTime = Mth::floor(dist * (attackIntervalMax - attackIntervalMin) +
|
||||
attackIntervalMin);
|
||||
}
|
||||
}
|
||||
36
Minecraft.World/AI/Goals/RangedAttackGoal.h
Normal file
36
Minecraft.World/AI/Goals/RangedAttackGoal.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include "Goal.h"
|
||||
|
||||
class RangedAttackMob;
|
||||
|
||||
class RangedAttackGoal : public Goal {
|
||||
private:
|
||||
Mob* mob; // Owner
|
||||
RangedAttackMob* rangedAttackMob; // owner
|
||||
std::weak_ptr<LivingEntity> target;
|
||||
int attackTime;
|
||||
double speedModifier;
|
||||
int seeTime;
|
||||
int attackIntervalMin;
|
||||
int attackIntervalMax;
|
||||
float attackRadius;
|
||||
float attackRadiusSqr;
|
||||
|
||||
void _init(RangedAttackMob* rangedMob, Mob* mob, double speedModifier,
|
||||
int attackIntervalMin, int attackIntervalMax,
|
||||
float attackRadius);
|
||||
|
||||
public:
|
||||
// 4J Added extra Mob param to avoid weird type conversion problems
|
||||
RangedAttackGoal(RangedAttackMob* rangedMob, Mob* mob, double speedModifier,
|
||||
int attackInterval, float attackRadius);
|
||||
RangedAttackGoal(RangedAttackMob* rangedMob, Mob* mob, double speedModifier,
|
||||
int attackIntervalMin, int attackIntervalMax,
|
||||
float attackRadius);
|
||||
|
||||
bool canUse();
|
||||
bool canContinueToUse();
|
||||
void stop();
|
||||
void tick();
|
||||
};
|
||||
60
Minecraft.World/AI/Goals/RunAroundLikeCrazyGoal.cpp
Normal file
60
Minecraft.World/AI/Goals/RunAroundLikeCrazyGoal.cpp
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
#include "../../Platform/stdafx.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.control.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.animal.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.navigation.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.player.h"
|
||||
#include "../../Headers/net.minecraft.world.level.h"
|
||||
#include "../Navigation/RandomPos.h"
|
||||
#include "RunAroundLikeCrazyGoal.h"
|
||||
|
||||
RunAroundLikeCrazyGoal::RunAroundLikeCrazyGoal(EntityHorse* mob,
|
||||
double speedModifier) {
|
||||
horse = mob;
|
||||
this->speedModifier = speedModifier;
|
||||
setRequiredControlFlags(Control::MoveControlFlag);
|
||||
}
|
||||
|
||||
bool RunAroundLikeCrazyGoal::canUse() {
|
||||
if (horse->isTamed() || horse->rider.lock() == NULL) return false;
|
||||
Vec3* pos = RandomPos::getPos(
|
||||
std::dynamic_pointer_cast<PathfinderMob>(horse->shared_from_this()), 5,
|
||||
4);
|
||||
if (pos == NULL) return false;
|
||||
posX = pos->x;
|
||||
posY = pos->y;
|
||||
posZ = pos->z;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RunAroundLikeCrazyGoal::start() {
|
||||
horse->getNavigation()->moveTo(posX, posY, posZ, speedModifier);
|
||||
}
|
||||
|
||||
bool RunAroundLikeCrazyGoal::canContinueToUse() {
|
||||
return !horse->getNavigation()->isDone() && horse->rider.lock() != NULL;
|
||||
}
|
||||
|
||||
void RunAroundLikeCrazyGoal::tick() {
|
||||
if (horse->getRandom()->nextInt(50) == 0) {
|
||||
if (horse->rider.lock()->instanceof(eTYPE_PLAYER)) {
|
||||
int temper = horse->getTemper();
|
||||
int maxTemper = horse->getMaxTemper();
|
||||
if (maxTemper > 0 &&
|
||||
horse->getRandom()->nextInt(maxTemper) < temper) {
|
||||
horse->tameWithName(
|
||||
std::dynamic_pointer_cast<Player>(horse->rider.lock()));
|
||||
horse->level->broadcastEntityEvent(
|
||||
horse->shared_from_this(), EntityEvent::TAMING_SUCCEEDED);
|
||||
return;
|
||||
}
|
||||
horse->modifyTemper(5);
|
||||
}
|
||||
|
||||
horse->rider.lock()->ride(nullptr);
|
||||
horse->rider = std::weak_ptr<LivingEntity>();
|
||||
horse->makeMad();
|
||||
horse->level->broadcastEntityEvent(horse->shared_from_this(),
|
||||
EntityEvent::TAMING_FAILED);
|
||||
}
|
||||
}
|
||||
20
Minecraft.World/AI/Goals/RunAroundLikeCrazyGoal.h
Normal file
20
Minecraft.World/AI/Goals/RunAroundLikeCrazyGoal.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
|
||||
#include "Goal.h"
|
||||
|
||||
class EntityHorse;
|
||||
|
||||
class RunAroundLikeCrazyGoal : public Goal {
|
||||
private:
|
||||
EntityHorse* horse; // Owner
|
||||
double speedModifier;
|
||||
double posX, posY, posZ;
|
||||
|
||||
public:
|
||||
RunAroundLikeCrazyGoal(EntityHorse* mob, double speedModifier);
|
||||
|
||||
bool canUse();
|
||||
void start();
|
||||
bool canContinueToUse();
|
||||
void tick();
|
||||
};
|
||||
|
|
@ -19,7 +19,8 @@ bool SitGoal::canUse() {
|
|||
if (mob->isInWater()) return false;
|
||||
if (!mob->onGround) return false;
|
||||
|
||||
std::shared_ptr<Mob> owner = mob->getOwner();
|
||||
std::shared_ptr<LivingEntity> owner =
|
||||
std::dynamic_pointer_cast<LivingEntity>(mob->getOwner());
|
||||
if (owner == NULL) return true; // owner not on level
|
||||
|
||||
if (mob->distanceToSqr(owner) < FollowOwnerGoal::TeleportDistance *
|
||||
|
|
|
|||
|
|
@ -6,24 +6,24 @@
|
|||
#include "SwellGoal.h"
|
||||
|
||||
SwellGoal::SwellGoal(Creeper* creeper) {
|
||||
target = std::weak_ptr<Mob>();
|
||||
target = std::weak_ptr<LivingEntity>();
|
||||
|
||||
this->creeper = creeper;
|
||||
setRequiredControlFlags(Control::MoveControlFlag);
|
||||
}
|
||||
|
||||
bool SwellGoal::canUse() {
|
||||
std::shared_ptr<Mob> target = creeper->getTarget();
|
||||
std::shared_ptr<LivingEntity> target = creeper->getTarget();
|
||||
return creeper->getSwellDir() > 0 ||
|
||||
(target != NULL && (creeper->distanceToSqr(target) < 3 * 3));
|
||||
}
|
||||
|
||||
void SwellGoal::start() {
|
||||
creeper->getNavigation()->stop();
|
||||
target = std::weak_ptr<Mob>(creeper->getTarget());
|
||||
target = std::weak_ptr<LivingEntity>(creeper->getTarget());
|
||||
}
|
||||
|
||||
void SwellGoal::stop() { target = std::weak_ptr<Mob>(); }
|
||||
void SwellGoal::stop() { target = std::weak_ptr<LivingEntity>(); }
|
||||
|
||||
void SwellGoal::tick() {
|
||||
if (target.lock() == NULL) {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ class Creeper;
|
|||
class SwellGoal : public Goal {
|
||||
private:
|
||||
Creeper* creeper;
|
||||
std::weak_ptr<Mob> target;
|
||||
std::weak_ptr<LivingEntity> target;
|
||||
|
||||
public:
|
||||
SwellGoal(Creeper* creeper);
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ void TakeFlowerGoal::stop() {
|
|||
void TakeFlowerGoal::tick() {
|
||||
villager->getLookControl()->setLookAt(golem.lock(), 30, 30);
|
||||
if (golem.lock()->getOfferFlowerTick() == pickupTick) {
|
||||
villager->getNavigation()->moveTo(golem.lock(), 0.15f);
|
||||
villager->getNavigation()->moveTo(golem.lock(), 0.5f);
|
||||
takeFlower = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,36 +1,39 @@
|
|||
#include "../../Platform/stdafx.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.attributes.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.navigation.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.sensing.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.animal.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.monster.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.player.h"
|
||||
#include "../../Headers/net.minecraft.world.level.pathfinder.h"
|
||||
#include "../../Headers/net.minecraft.world.phys.h"
|
||||
#include "TargetGoal.h"
|
||||
|
||||
void TargetGoal::_init(Mob* mob, float within, bool mustSee, bool mustReach) {
|
||||
void TargetGoal::_init(PathfinderMob* mob, 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(PathfinderMob* mob, bool mustSee) {
|
||||
_init(mob, mustSee, false);
|
||||
}
|
||||
|
||||
TargetGoal::TargetGoal(Mob* mob, float within, bool mustSee, bool mustReach) {
|
||||
_init(mob, within, mustSee, mustReach);
|
||||
TargetGoal::TargetGoal(PathfinderMob* mob, bool mustSee, bool mustReach) {
|
||||
_init(mob, mustSee, mustReach);
|
||||
}
|
||||
|
||||
bool TargetGoal::canContinueToUse() {
|
||||
std::shared_ptr<Mob> target = mob->getTarget();
|
||||
std::shared_ptr<LivingEntity> target = mob->getTarget();
|
||||
if (target == NULL) return false;
|
||||
if (!target->isAlive()) return false;
|
||||
|
||||
double within = getFollowDistance();
|
||||
if (mob->distanceToSqr(target) > within * within) return false;
|
||||
if (mustSee) {
|
||||
if (mob->getSensing()->canSee(target)) {
|
||||
|
|
@ -42,6 +45,12 @@ bool TargetGoal::canContinueToUse() {
|
|||
return true;
|
||||
}
|
||||
|
||||
double TargetGoal::getFollowDistance() {
|
||||
AttributeInstance* followRange =
|
||||
mob->getAttribute(SharedMonsterAttributes::FOLLOW_RANGE);
|
||||
return followRange == NULL ? 16 : followRange->getValue();
|
||||
}
|
||||
|
||||
void TargetGoal::start() {
|
||||
reachCache = EmptyReachCache;
|
||||
reachCacheTime = 0;
|
||||
|
|
@ -50,21 +59,28 @@ void TargetGoal::start() {
|
|||
|
||||
void TargetGoal::stop() { mob->setTarget(nullptr); }
|
||||
|
||||
bool TargetGoal::canAttack(std::shared_ptr<Mob> target,
|
||||
bool TargetGoal::canAttack(std::shared_ptr<LivingEntity> 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) {
|
||||
OwnableEntity* ownableMob = dynamic_cast<OwnableEntity*>(mob);
|
||||
if (ownableMob != NULL && !ownableMob->getOwnerUUID().empty()) {
|
||||
std::shared_ptr<OwnableEntity> ownableTarget =
|
||||
std::dynamic_pointer_cast<OwnableEntity>(target);
|
||||
if (ownableTarget != NULL && ownableMob->getOwnerUUID().compare(
|
||||
ownableTarget->getOwnerUUID()) == 0) {
|
||||
// We're attacking something owned by the same person...
|
||||
return false;
|
||||
}
|
||||
|
||||
if (target == ownableMob->getOwner()) {
|
||||
// We're attacking our owner
|
||||
return false;
|
||||
}
|
||||
} else if (target->instanceof(eTYPE_PLAYER)) {
|
||||
if (!allowInvulnerable &&
|
||||
(std::dynamic_pointer_cast<Player>(target))->abilities.invulnerable)
|
||||
return false;
|
||||
|
|
@ -86,7 +102,7 @@ bool TargetGoal::canAttack(std::shared_ptr<Mob> target,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool TargetGoal::canReach(std::shared_ptr<Mob> target) {
|
||||
bool TargetGoal::canReach(std::shared_ptr<LivingEntity> target) {
|
||||
reachCacheTime = 10 + mob->getRandom()->nextInt(5);
|
||||
Path* path = mob->getNavigation()->createPath(target);
|
||||
if (path == NULL) return false;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include "Goal.h"
|
||||
|
||||
class PathfinderMob;
|
||||
|
||||
class TargetGoal : public Goal {
|
||||
public:
|
||||
static const int TargetFlag = 1;
|
||||
|
|
@ -13,8 +15,7 @@ private:
|
|||
static const int UnseenMemoryTicks = 60;
|
||||
|
||||
protected:
|
||||
Mob* mob; // Owner of this goal
|
||||
float within;
|
||||
PathfinderMob* mob; // Owner of this goal
|
||||
bool mustSee;
|
||||
|
||||
private:
|
||||
|
|
@ -23,20 +24,26 @@ private:
|
|||
int reachCacheTime;
|
||||
int unseenTicks;
|
||||
|
||||
void _init(Mob* mob, float within, bool mustSee, bool mustReach);
|
||||
void _init(PathfinderMob* mob, bool mustSee, bool mustReach);
|
||||
|
||||
public:
|
||||
TargetGoal(Mob* mob, float within, bool mustSee);
|
||||
TargetGoal(Mob* mob, float within, bool mustSee, bool mustReach);
|
||||
TargetGoal(PathfinderMob* mob, bool mustSee);
|
||||
TargetGoal(PathfinderMob* mob, bool mustSee, bool mustReach);
|
||||
virtual ~TargetGoal() {}
|
||||
|
||||
virtual bool canContinueToUse();
|
||||
|
||||
protected:
|
||||
virtual double getFollowDistance();
|
||||
|
||||
public:
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
|
||||
protected:
|
||||
virtual bool canAttack(std::shared_ptr<Mob> target, bool allowInvulnerable);
|
||||
virtual bool canAttack(std::shared_ptr<LivingEntity> target,
|
||||
bool allowInvulnerable);
|
||||
|
||||
private:
|
||||
bool canReach(std::shared_ptr<Mob> target);
|
||||
bool canReach(std::shared_ptr<LivingEntity> target);
|
||||
};
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
#include "../../Headers/net.minecraft.world.level.h"
|
||||
#include "TemptGoal.h"
|
||||
|
||||
TemptGoal::TemptGoal(PathfinderMob* mob, float speed, int itemId,
|
||||
TemptGoal::TemptGoal(PathfinderMob* mob, double speedModifier, int itemId,
|
||||
bool canScare) {
|
||||
px = py = pz = pRotX = pRotY = 0.0;
|
||||
player = std::weak_ptr<Player>();
|
||||
|
|
@ -15,7 +15,7 @@ TemptGoal::TemptGoal(PathfinderMob* mob, float speed, int itemId,
|
|||
oldAvoidWater = false;
|
||||
|
||||
this->mob = mob;
|
||||
this->speed = speed;
|
||||
this->speedModifier = speedModifier;
|
||||
this->itemId = itemId;
|
||||
this->canScare = canScare;
|
||||
setRequiredControlFlags(Control::MoveControlFlag |
|
||||
|
|
@ -81,7 +81,7 @@ void TemptGoal::tick() {
|
|||
if (mob->distanceToSqr(player.lock()) < 2.5 * 2.5)
|
||||
mob->getNavigation()->stop();
|
||||
else
|
||||
mob->getNavigation()->moveTo(player.lock(), speed);
|
||||
mob->getNavigation()->moveTo(player.lock(), speedModifier);
|
||||
}
|
||||
|
||||
bool TemptGoal::isRunning() { return _isRunning; }
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
class TemptGoal : public Goal {
|
||||
private:
|
||||
PathfinderMob* mob;
|
||||
float speed;
|
||||
double speedModifier;
|
||||
double px, py, pz, pRotX, pRotY;
|
||||
std::weak_ptr<Player> player;
|
||||
int calmDown;
|
||||
|
|
@ -15,7 +15,8 @@ private:
|
|||
bool oldAvoidWater;
|
||||
|
||||
public:
|
||||
TemptGoal(PathfinderMob* mob, float speed, int itemId, bool canScare);
|
||||
TemptGoal(PathfinderMob* mob, double speedModifier, int itemId,
|
||||
bool canScare);
|
||||
|
||||
bool canUse();
|
||||
bool canContinueToUse();
|
||||
|
|
|
|||
|
|
@ -168,7 +168,12 @@ Node* PathFinder::getNode(Entity* entity, int x, int y, int z, Node* size,
|
|||
if (avoidWater && cost == TYPE_WATER) return NULL;
|
||||
if (cost != TYPE_OPEN) break;
|
||||
// fell too far?
|
||||
if (++drop >= 4) return NULL;
|
||||
if (++drop >= 4)
|
||||
return NULL; // 4J - rolling this back to pre-java 1.6.4
|
||||
// version as we're suspicious of the performance
|
||||
// implications of this
|
||||
// if (drop++ >=
|
||||
// entity->getMaxFallDistance()) return NULL;
|
||||
y--;
|
||||
|
||||
if (y > 0) best = getNode(x, y, z);
|
||||
|
|
@ -221,6 +226,24 @@ int PathFinder::isFree(Entity* entity, int x, int y, int z, Node* size,
|
|||
}
|
||||
|
||||
Tile* tile = Tile::tiles[tileId];
|
||||
|
||||
// 4J Stu - Use new getTileRenderShape passing in the tileId we
|
||||
// have already got
|
||||
if (entity->level->getTileRenderShape(tileId) ==
|
||||
Tile::SHAPE_RAIL) {
|
||||
int xt = Mth::floor(entity->x);
|
||||
int yt = Mth::floor(entity->y);
|
||||
int zt = Mth::floor(entity->z);
|
||||
if (entity->level->getTileRenderShape(xt, yt, zt) ==
|
||||
Tile::SHAPE_RAIL ||
|
||||
entity->level->getTileRenderShape(xt, yt - 1, zt) ==
|
||||
Tile::SHAPE_RAIL) {
|
||||
continue;
|
||||
} else {
|
||||
return TYPE_FENCE;
|
||||
}
|
||||
}
|
||||
|
||||
if (tile->isPathfindable(entity->level, xx, yy, zz)) continue;
|
||||
if (canOpenDoors && tileId == Tile::door_wood_Id) continue;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,19 +2,21 @@
|
|||
#include "../../Headers/net.minecraft.world.level.h"
|
||||
#include "../../Headers/net.minecraft.world.level.pathfinder.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.attributes.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.control.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.monster.h"
|
||||
#include "../../Headers/net.minecraft.world.level.h"
|
||||
#include "../../Headers/net.minecraft.world.level.tile.h"
|
||||
#include "../../Headers/net.minecraft.world.phys.h"
|
||||
#include "PathNavigation.h"
|
||||
|
||||
PathNavigation::PathNavigation(Mob* mob, Level* level, float maxDist) {
|
||||
PathNavigation::PathNavigation(Mob* mob, Level* level) {
|
||||
this->mob = mob;
|
||||
this->level = level;
|
||||
this->maxDist = maxDist;
|
||||
dist = mob->getAttribute(SharedMonsterAttributes::FOLLOW_RANGE);
|
||||
|
||||
path = NULL;
|
||||
speed = 0.0f;
|
||||
speedModifier = 0.0;
|
||||
avoidSun = false;
|
||||
_tick = 0;
|
||||
lastStuckCheck = 0;
|
||||
|
|
@ -48,45 +50,51 @@ bool PathNavigation::canOpenDoors() { return _canOpenDoors; }
|
|||
|
||||
void PathNavigation::setAvoidSun(bool avoidSun) { this->avoidSun = avoidSun; }
|
||||
|
||||
void PathNavigation::setSpeed(float speed) { this->speed = speed; }
|
||||
void PathNavigation::setSpeedModifier(double speedModifier) {
|
||||
this->speedModifier = speedModifier;
|
||||
}
|
||||
|
||||
void PathNavigation::setCanFloat(bool canFloat) { this->canFloat = canFloat; }
|
||||
|
||||
float PathNavigation::getMaxDist() { return (float)dist->getValue(); }
|
||||
|
||||
Path* PathNavigation::createPath(double x, double y, double z) {
|
||||
if (!canUpdatePath()) return NULL;
|
||||
return level->findPath(mob->shared_from_this(), Mth::floor(x), (int)y,
|
||||
Mth::floor(z), maxDist, _canPassDoors, _canOpenDoors,
|
||||
avoidWater, canFloat);
|
||||
Mth::floor(z), getMaxDist(), _canPassDoors,
|
||||
_canOpenDoors, avoidWater, canFloat);
|
||||
}
|
||||
|
||||
bool PathNavigation::moveTo(double x, double y, double z, float speed) {
|
||||
bool PathNavigation::moveTo(double x, double y, double z,
|
||||
double speedModifier) {
|
||||
MemSect(52);
|
||||
Path* newPath = createPath(Mth::floor(x), (int)y, Mth::floor(z));
|
||||
MemSect(0);
|
||||
// No need to delete newPath here as this will be copied into the member
|
||||
// variable path and the class can assume responsibility for it
|
||||
return moveTo(newPath, speed);
|
||||
return moveTo(newPath, speedModifier);
|
||||
}
|
||||
|
||||
Path* PathNavigation::createPath(std::shared_ptr<Mob> target) {
|
||||
Path* PathNavigation::createPath(std::shared_ptr<Entity> target) {
|
||||
if (!canUpdatePath()) return NULL;
|
||||
return level->findPath(mob->shared_from_this(), target, maxDist,
|
||||
return level->findPath(mob->shared_from_this(), target, getMaxDist(),
|
||||
_canPassDoors, _canOpenDoors, avoidWater, canFloat);
|
||||
}
|
||||
|
||||
bool PathNavigation::moveTo(std::shared_ptr<Mob> target, float speed) {
|
||||
bool PathNavigation::moveTo(std::shared_ptr<Entity> target,
|
||||
double speedModifier) {
|
||||
MemSect(53);
|
||||
Path* newPath = createPath(target);
|
||||
MemSect(0);
|
||||
// No need to delete newPath here as this will be copied into the member
|
||||
// variable path and the class can assume responsibility for it
|
||||
if (newPath != NULL)
|
||||
return moveTo(newPath, speed);
|
||||
return moveTo(newPath, speedModifier);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PathNavigation::moveTo(Path* newPath, float speed) {
|
||||
bool PathNavigation::moveTo(Path* newPath, double speedModifier) {
|
||||
if (newPath == NULL) {
|
||||
if (path != NULL) delete path;
|
||||
path = NULL;
|
||||
|
|
@ -101,7 +109,7 @@ bool PathNavigation::moveTo(Path* newPath, float speed) {
|
|||
if (avoidSun) trimPathFromSun();
|
||||
if (path->getSize() == 0) return false;
|
||||
|
||||
this->speed = speed;
|
||||
this->speedModifier = speedModifier;
|
||||
Vec3* mobPos = getTempMobPos();
|
||||
lastStuckCheck = _tick;
|
||||
lastStuckCheckPos->x = mobPos->x;
|
||||
|
|
@ -123,7 +131,7 @@ void PathNavigation::tick() {
|
|||
if (target == NULL) return;
|
||||
|
||||
mob->getMoveControl()->setWantedPosition(target->x, target->y, target->z,
|
||||
speed);
|
||||
speedModifier);
|
||||
}
|
||||
|
||||
void PathNavigation::updatePath() {
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ private:
|
|||
Mob* mob;
|
||||
Level* level;
|
||||
Path* path;
|
||||
float speed;
|
||||
float maxDist;
|
||||
double speedModifier;
|
||||
AttributeInstance* dist;
|
||||
bool avoidSun;
|
||||
int _tick;
|
||||
int lastStuckCheck;
|
||||
|
|
@ -22,7 +22,7 @@ private:
|
|||
bool canFloat;
|
||||
|
||||
public:
|
||||
PathNavigation(Mob* mob, Level* level, float maxDist);
|
||||
PathNavigation(Mob* mob, Level* level);
|
||||
~PathNavigation();
|
||||
|
||||
void setAvoidWater(bool avoidWater);
|
||||
|
|
@ -32,13 +32,14 @@ public:
|
|||
void setCanPassDoors(bool canPass);
|
||||
bool canOpenDoors();
|
||||
void setAvoidSun(bool avoidSun);
|
||||
void setSpeed(float speed);
|
||||
void setSpeedModifier(double speedModifier);
|
||||
void setCanFloat(bool canFloat);
|
||||
float getMaxDist();
|
||||
Path* createPath(double x, double y, double z);
|
||||
bool moveTo(double x, double y, double z, float speed);
|
||||
Path* createPath(std::shared_ptr<Mob> target);
|
||||
bool moveTo(std::shared_ptr<Mob> target, float speed);
|
||||
bool moveTo(Path* newPath, float speed);
|
||||
bool moveTo(double x, double y, double z, double speedModifier);
|
||||
Path* createPath(std::shared_ptr<Entity> target);
|
||||
bool moveTo(std::shared_ptr<Entity> target, double speedModifier);
|
||||
bool moveTo(Path* newPath, double speedModifier);
|
||||
Path* getPath();
|
||||
void tick();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue