mirror of
https://github.com/4jcraft/4jcraft.git
synced 2026-06-03 17:02:54 +00:00
TU19: merge Minecraft.World/Entities
This commit is contained in:
parent
405a87e078
commit
3d3fa566c7
24
Minecraft.World/Entities/AbsoptionMobEffect.cpp
Normal file
24
Minecraft.World/Entities/AbsoptionMobEffect.cpp
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#include "../Platform/stdafx.h"
|
||||
#include "../Headers/net.minecraft.world.entity.h"
|
||||
#include "../Headers/net.minecraft.world.effect.h"
|
||||
#include "AbsoptionMobEffect.h"
|
||||
|
||||
AbsoptionMobEffect::AbsoptionMobEffect(int id, bool isHarmful,
|
||||
eMinecraftColour color)
|
||||
: MobEffect(id, isHarmful, color) {}
|
||||
|
||||
void AbsoptionMobEffect::removeAttributeModifiers(
|
||||
std::shared_ptr<LivingEntity> entity, BaseAttributeMap* attributes,
|
||||
int amplifier) {
|
||||
entity->setAbsorptionAmount(entity->getAbsorptionAmount() -
|
||||
4 * (amplifier + 1));
|
||||
MobEffect::removeAttributeModifiers(entity, attributes, amplifier);
|
||||
}
|
||||
|
||||
void AbsoptionMobEffect::addAttributeModifiers(
|
||||
std::shared_ptr<LivingEntity> entity, BaseAttributeMap* attributes,
|
||||
int amplifier) {
|
||||
entity->setAbsorptionAmount(entity->getAbsorptionAmount() +
|
||||
4 * (amplifier + 1));
|
||||
MobEffect::addAttributeModifiers(entity, attributes, amplifier);
|
||||
}
|
||||
15
Minecraft.World/Entities/AbsoptionMobEffect.h
Normal file
15
Minecraft.World/Entities/AbsoptionMobEffect.h
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
class LivingEntity;
|
||||
|
||||
#include "MobEffect.h"
|
||||
|
||||
class AbsoptionMobEffect : public MobEffect {
|
||||
public:
|
||||
AbsoptionMobEffect(int id, bool isHarmful, eMinecraftColour color);
|
||||
|
||||
void removeAttributeModifiers(std::shared_ptr<LivingEntity> entity,
|
||||
BaseAttributeMap* attributes, int amplifier);
|
||||
void addAttributeModifiers(std::shared_ptr<LivingEntity> entity,
|
||||
BaseAttributeMap* attributes, int amplifier);
|
||||
};
|
||||
16
Minecraft.World/Entities/AttackDamageMobEffect.cpp
Normal file
16
Minecraft.World/Entities/AttackDamageMobEffect.cpp
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#include "../Platform/stdafx.h"
|
||||
|
||||
#include "AttackDamageMobEffect.h"
|
||||
|
||||
AttackDamageMobEffect::AttackDamageMobEffect(int id, bool isHarmful,
|
||||
eMinecraftColour color)
|
||||
: MobEffect(id, isHarmful, color) {}
|
||||
|
||||
double AttackDamageMobEffect::getAttributeModifierValue(
|
||||
int amplifier, AttributeModifier* original) {
|
||||
if (id == MobEffect::weakness->id) {
|
||||
return -0.5f * (amplifier + 1);
|
||||
} else {
|
||||
return 1.3 * (amplifier + 1);
|
||||
}
|
||||
}
|
||||
13
Minecraft.World/Entities/AttackDamageMobEffect.h
Normal file
13
Minecraft.World/Entities/AttackDamageMobEffect.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "MobEffect.h"
|
||||
|
||||
class AttributeModifier;
|
||||
|
||||
class AttackDamageMobEffect : public MobEffect {
|
||||
public:
|
||||
AttackDamageMobEffect(int id, bool isHarmful, eMinecraftColour color);
|
||||
|
||||
double getAttributeModifierValue(int amplifier,
|
||||
AttributeModifier* original);
|
||||
};
|
||||
|
|
@ -1,31 +0,0 @@
|
|||
#include "../Platform/stdafx.h"
|
||||
#include "Mobs/BossMob.h"
|
||||
#include "BossMobPart.h"
|
||||
|
||||
BossMobPart::BossMobPart(BossMob* bossMob, const std::wstring& id, float w,
|
||||
float h)
|
||||
: Entity(bossMob->level), bossMob(bossMob), id(id) {
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
|
||||
setSize(w, h);
|
||||
}
|
||||
|
||||
void BossMobPart::defineSynchedData() {}
|
||||
|
||||
void BossMobPart::readAdditionalSaveData(CompoundTag* tag) {}
|
||||
|
||||
void BossMobPart::addAdditonalSaveData(CompoundTag* tag) {}
|
||||
|
||||
bool BossMobPart::isPickable() { return true; }
|
||||
|
||||
bool BossMobPart::hurt(DamageSource* source, int damage) {
|
||||
return bossMob->hurt(
|
||||
std::dynamic_pointer_cast<BossMobPart>(shared_from_this()), source,
|
||||
damage);
|
||||
}
|
||||
|
||||
bool BossMobPart::is(std::shared_ptr<Entity> other) {
|
||||
return shared_from_this() == other || bossMob == other.get();
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "Entity.h"
|
||||
|
||||
class Level;
|
||||
class BossMob;
|
||||
|
||||
class BossMobPart : public Entity {
|
||||
public:
|
||||
eINSTANCEOF GetType() { return eTYPE_BOSS_MOB_PART; };
|
||||
|
||||
public:
|
||||
BossMob* bossMob;
|
||||
const std::wstring id;
|
||||
|
||||
BossMobPart(BossMob* bossMob, const std::wstring& id, float w, float h);
|
||||
|
||||
protected:
|
||||
virtual void defineSynchedData();
|
||||
virtual void readAdditionalSaveData(CompoundTag* tag);
|
||||
virtual void addAdditonalSaveData(CompoundTag* tag);
|
||||
|
||||
public:
|
||||
virtual bool isPickable();
|
||||
virtual bool hurt(DamageSource* source, int damage);
|
||||
virtual bool is(std::shared_ptr<Entity> other);
|
||||
};
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
#include "../Platform/stdafx.h"
|
||||
#include "Enemy.h"
|
||||
|
||||
const int Enemy::XP_REWARD_NONE = 0;
|
||||
const int Enemy::XP_REWARD_SMALL = 3;
|
||||
const int Enemy::XP_REWARD_MEDIUM = 5;
|
||||
const int Enemy::XP_REWARD_LARGE = 10;
|
||||
const int Enemy::XP_REWARD_HUGE = 20;
|
||||
EntitySelector* Enemy::ENEMY_SELECTOR = new Enemy::EnemyEntitySelector();
|
||||
|
||||
bool Enemy::EnemyEntitySelector::matches(std::shared_ptr<Entity> entity) const {
|
||||
return (entity != NULL) && entity->instanceof(eTYPE_ENEMY);
|
||||
}
|
||||
|
|
@ -1,13 +1,19 @@
|
|||
#pragma once
|
||||
#include "Mobs/Creature.h"
|
||||
|
||||
class Level;
|
||||
#include "EntitySelector.h"
|
||||
|
||||
class Enemy : public Creature {
|
||||
public:
|
||||
static const int XP_REWARD_NONE;
|
||||
static const int XP_REWARD_SMALL;
|
||||
static const int XP_REWARD_MEDIUM;
|
||||
static const int XP_REWARD_LARGE;
|
||||
static const int XP_REWARD_HUGE;
|
||||
class EnemyEntitySelector : public EntitySelector {
|
||||
bool matches(std::shared_ptr<Entity> entity) const;
|
||||
};
|
||||
|
||||
static const int XP_REWARD_NONE = 0;
|
||||
static const int XP_REWARD_SMALL = 3;
|
||||
static const int XP_REWARD_MEDIUM = 5;
|
||||
static const int XP_REWARD_LARGE = 10;
|
||||
static const int XP_REWARD_HUGE = 20;
|
||||
static const int XP_REWARD_BOSS = 50;
|
||||
|
||||
static EntitySelector* ENEMY_SELECTOR;
|
||||
};
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -10,7 +10,7 @@
|
|||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
class Mob;
|
||||
class LivingEntity;
|
||||
class LightningBolt;
|
||||
class ItemEntity;
|
||||
class EntityPos;
|
||||
|
|
@ -21,6 +21,7 @@ class Random;
|
|||
class Level;
|
||||
class CompoundTag;
|
||||
class DamageSource;
|
||||
class Explosion;
|
||||
|
||||
// 4J Stu Added this mainly to allow is to record telemetry for player deaths
|
||||
enum EEntityDamageType {
|
||||
|
|
@ -48,7 +49,15 @@ public:
|
|||
// 4J-PB - added to replace (e instanceof Type), avoiding dynamic casts
|
||||
virtual eINSTANCEOF GetType() = 0;
|
||||
|
||||
inline bool instanceof(eINSTANCEOF super) {
|
||||
return eTYPE_DERIVED_FROM(super, GetType());
|
||||
}
|
||||
inline static bool instanceof(eINSTANCEOF type, eINSTANCEOF super) {
|
||||
return eTYPE_DERIVED_FROM(super, type);
|
||||
}
|
||||
|
||||
public:
|
||||
static const std::wstring RIDING_TAG;
|
||||
static const short TOTAL_AIR_SUPPLY = 20 * 15;
|
||||
|
||||
private:
|
||||
|
|
@ -63,6 +72,7 @@ public:
|
|||
std::weak_ptr<Entity> rider; // Changed to weak to avoid circular
|
||||
// dependency between rider/riding entity
|
||||
std::shared_ptr<Entity> riding;
|
||||
bool forcedLoading;
|
||||
|
||||
Level* level;
|
||||
double xo, yo, zo;
|
||||
|
|
@ -89,6 +99,7 @@ public:
|
|||
|
||||
float walkDistO;
|
||||
float walkDist;
|
||||
float moveDist;
|
||||
float fallDistance;
|
||||
|
||||
private:
|
||||
|
|
@ -120,10 +131,6 @@ public:
|
|||
private:
|
||||
bool firstTick;
|
||||
|
||||
public:
|
||||
std::wstring customTextureUrl;
|
||||
std::wstring customTextureUrl2;
|
||||
|
||||
protected:
|
||||
bool fireImmune;
|
||||
|
||||
|
|
@ -135,7 +142,7 @@ private:
|
|||
static const int DATA_SHARED_FLAGS_ID = 0;
|
||||
static const int FLAG_ONFIRE = 0;
|
||||
static const int FLAG_SNEAKING = 1;
|
||||
static const int FLAG_RIDING = 2;
|
||||
// static const int FLAG_ = 2;
|
||||
static const int FLAG_SPRINTING = 3;
|
||||
static const int FLAG_USING_ITEM = 4;
|
||||
static const int FLAG_INVISIBLE = 5;
|
||||
|
|
@ -153,12 +160,29 @@ public:
|
|||
int xp, yp, zp, xRotp, yRotp;
|
||||
bool noCulling;
|
||||
bool hasImpulse;
|
||||
int changingDimensionDelay;
|
||||
|
||||
protected:
|
||||
bool isInsidePortal;
|
||||
int portalTime;
|
||||
|
||||
public:
|
||||
int dimension;
|
||||
|
||||
protected:
|
||||
int portalEntranceDir;
|
||||
|
||||
private:
|
||||
bool invulnerable;
|
||||
std::wstring uuid;
|
||||
|
||||
protected:
|
||||
// 4J Added so that client side simulations on the host are not affected by
|
||||
// zero-lag
|
||||
bool m_ignoreVerticalCollisions;
|
||||
|
||||
bool m_ignorePortal;
|
||||
|
||||
public:
|
||||
Entity(Level* level,
|
||||
bool useSmallId = true); // 4J - added useSmallId parameter
|
||||
|
|
@ -166,7 +190,7 @@ public:
|
|||
|
||||
protected:
|
||||
// 4J - added for common ctor code
|
||||
void _init(bool useSmallId);
|
||||
void _init(bool useSmallId, Level* level);
|
||||
|
||||
protected:
|
||||
virtual void defineSynchedData() = 0;
|
||||
|
|
@ -204,6 +228,7 @@ public:
|
|||
void interpolateTurn(float xo, float yo);
|
||||
virtual void tick();
|
||||
virtual void baseTick();
|
||||
virtual int getPortalWaitTime();
|
||||
|
||||
protected:
|
||||
void lavaHurt();
|
||||
|
|
@ -272,7 +297,7 @@ protected:
|
|||
|
||||
public:
|
||||
// 4J Added damageSource param to enable telemetry on player deaths
|
||||
virtual bool hurt(DamageSource* source, int damage);
|
||||
virtual bool hurt(DamageSource* source, float damage);
|
||||
bool intersects(double x0, double y0, double z0, double x1, double y1,
|
||||
double z1);
|
||||
virtual bool isPickable();
|
||||
|
|
@ -281,18 +306,24 @@ public:
|
|||
virtual void awardKillScore(std::shared_ptr<Entity> victim, int score);
|
||||
virtual bool shouldRender(Vec3* c);
|
||||
virtual bool shouldRenderAtSqrDistance(double distance);
|
||||
virtual int getTexture(); // 4J - changed from std::wstring to int
|
||||
virtual bool isCreativeModeAllowed();
|
||||
bool saveAsMount(CompoundTag* entityTag);
|
||||
bool save(CompoundTag* entityTag);
|
||||
void saveWithoutId(CompoundTag* entityTag);
|
||||
virtual void load(CompoundTag* tag);
|
||||
|
||||
protected:
|
||||
virtual bool repositionEntityAfterLoad();
|
||||
const std::wstring getEncodeId();
|
||||
|
||||
public:
|
||||
virtual void readAdditionalSaveData(CompoundTag* tag) = 0;
|
||||
virtual void addAdditonalSaveData(CompoundTag* tag) = 0;
|
||||
/**
|
||||
* Called after load() has finished and the entity has been added to the
|
||||
* world
|
||||
*/
|
||||
virtual void onLoadedFromSave();
|
||||
|
||||
protected:
|
||||
ListTag<DoubleTag>* newDoubleList(unsigned int number, double firstValue,
|
||||
|
|
@ -317,20 +348,15 @@ public:
|
|||
virtual double getRidingHeight();
|
||||
virtual double getRideHeight();
|
||||
virtual void ride(std::shared_ptr<Entity> e);
|
||||
virtual void findStandUpPosition(
|
||||
std::shared_ptr<Entity>
|
||||
vehicle); // 4J Stu - Brought forward from 12w36 to fix #46282 -
|
||||
// TU5: Gameplay: Exiting the minecart in a tight
|
||||
// corridor damages the player
|
||||
virtual void lerpTo(double x, double y, double z, float yRot, float xRot,
|
||||
int steps);
|
||||
virtual float getPickRadius();
|
||||
virtual Vec3* getLookAngle();
|
||||
virtual void handleInsidePortal();
|
||||
virtual int getDimensionChangingDelay();
|
||||
virtual void lerpMotion(double xd, double yd, double zd);
|
||||
virtual void handleEntityEvent(uint8_t eventId);
|
||||
virtual void animateHurt();
|
||||
virtual void prepareCustomTextures();
|
||||
virtual ItemInstanceArray getEquipmentSlots(); // ItemInstance[]
|
||||
virtual void setEquippedSlot(
|
||||
int slot, std::shared_ptr<ItemInstance>
|
||||
|
|
@ -369,7 +395,7 @@ public:
|
|||
void setAirSupply(int supply);
|
||||
|
||||
virtual void thunderHit(const LightningBolt* lightningBolt);
|
||||
virtual void killed(std::shared_ptr<Mob> mob);
|
||||
virtual void killed(std::shared_ptr<LivingEntity> mob);
|
||||
|
||||
protected:
|
||||
bool checkInTile(double x, double y, double z);
|
||||
|
|
@ -379,9 +405,6 @@ public:
|
|||
|
||||
virtual std::wstring getAName();
|
||||
|
||||
// TU9
|
||||
bool skipAttackInteraction(std::shared_ptr<Entity> source) { return false; }
|
||||
|
||||
// 4J - added to manage allocation of small ids
|
||||
private:
|
||||
// Things also added here to be able to manage the concept of a number of
|
||||
|
|
@ -423,8 +446,25 @@ public:
|
|||
virtual float getYHeadRot();
|
||||
virtual void setYHeadRot(float yHeadRot);
|
||||
virtual bool isAttackable();
|
||||
virtual bool skipAttackInteraction(std::shared_ptr<Entity> source);
|
||||
virtual bool isInvulnerable();
|
||||
virtual void copyPosition(std::shared_ptr<Entity> target);
|
||||
virtual void restoreFrom(std::shared_ptr<Entity> oldEntity,
|
||||
bool teleporting);
|
||||
virtual void changeDimension(int i);
|
||||
virtual float getTileExplosionResistance(Explosion* explosion, Level* level,
|
||||
int x, int y, int z, Tile* tile);
|
||||
virtual bool shouldTileExplode(Explosion* explosion, Level* level, int x,
|
||||
int y, int z, int id, float power);
|
||||
virtual int getMaxFallDistance();
|
||||
virtual int getPortalEntranceDir();
|
||||
virtual bool isIgnoringTileTriggers();
|
||||
virtual bool displayFireAnimation();
|
||||
virtual void setUUID(const std::wstring& UUID);
|
||||
virtual std::wstring getUUID();
|
||||
virtual bool isPushedByWater();
|
||||
virtual std::wstring getDisplayName();
|
||||
virtual std::wstring getNetworkName(); // 4J: Added
|
||||
|
||||
private:
|
||||
unsigned int m_uiAnimOverrideBitmask;
|
||||
|
|
|
|||
|
|
@ -4,36 +4,58 @@
|
|||
#include "../Headers/net.minecraft.world.damagesource.h"
|
||||
#include "../Headers/net.minecraft.network.packet.h"
|
||||
|
||||
// EntityDamageSource::EntityDamageSource(const std::wstring &msgId,
|
||||
// std::shared_ptr<Entity> entity) : DamageSource(msgId)
|
||||
EntityDamageSource::EntityDamageSource(ChatPacket::EChatPacketMessage msgId,
|
||||
std::shared_ptr<Entity> entity)
|
||||
: DamageSource(msgId) {
|
||||
// EntityDamageSource::EntityDamageSource(const wstring &msgId,
|
||||
// shared_ptr<Entity> entity) : DamageSource(msgId)
|
||||
EntityDamageSource::EntityDamageSource(
|
||||
ChatPacket::EChatPacketMessage msgId,
|
||||
ChatPacket::EChatPacketMessage msgWithItemId,
|
||||
std::shared_ptr<Entity> entity)
|
||||
: DamageSource(msgId, msgWithItemId) {
|
||||
this->entity = entity;
|
||||
}
|
||||
|
||||
std::shared_ptr<Entity> EntityDamageSource::getEntity() { return entity; }
|
||||
|
||||
// std::wstring
|
||||
// EntityDamageSource::getLocalizedDeathMessage(std::shared_ptr<Player> player)
|
||||
// wstring EntityDamageSource::getLocalizedDeathMessage(shared_ptr<Player>
|
||||
// player)
|
||||
//{
|
||||
// return L"death." + msgId + player->name + entity->getAName();
|
||||
// //return I18n.get("death." + msgId, player.name, entity.getAName());
|
||||
// }
|
||||
|
||||
std::shared_ptr<ChatPacket> EntityDamageSource::getDeathMessagePacket(
|
||||
std::shared_ptr<Player> player) {
|
||||
std::shared_ptr<LivingEntity> player) {
|
||||
std::shared_ptr<ItemInstance> held =
|
||||
(entity != NULL) && entity->instanceof(eTYPE_LIVINGENTITY)
|
||||
? std::dynamic_pointer_cast<LivingEntity>(entity)->getCarriedItem()
|
||||
: nullptr;
|
||||
std::wstring additional = L"";
|
||||
if (entity->GetType() == eTYPE_SERVERPLAYER) {
|
||||
std::shared_ptr<Player> sourcePlayer =
|
||||
std::dynamic_pointer_cast<Player>(entity);
|
||||
if (sourcePlayer != NULL) additional = sourcePlayer->name;
|
||||
|
||||
if (entity->instanceof(eTYPE_SERVERPLAYER)) {
|
||||
additional = std::dynamic_pointer_cast<Player>(entity)->name;
|
||||
} else if (entity->instanceof(eTYPE_MOB)) {
|
||||
std::shared_ptr<Mob> mob = std::dynamic_pointer_cast<Mob>(entity);
|
||||
if (mob->hasCustomName()) {
|
||||
additional = mob->getCustomName();
|
||||
}
|
||||
}
|
||||
|
||||
if ((held != NULL) && held->hasCustomHoverName()) {
|
||||
return std::shared_ptr<ChatPacket>(new ChatPacket(
|
||||
player->getNetworkName(), m_msgWithItemId, entity->GetType(),
|
||||
additional, held->getHoverName()));
|
||||
} else {
|
||||
return std::shared_ptr<ChatPacket>(new ChatPacket(
|
||||
player->getNetworkName(), m_msgId, entity->GetType(), additional));
|
||||
}
|
||||
return std::shared_ptr<ChatPacket>(
|
||||
new ChatPacket(player->name, m_msgId, entity->GetType(), additional));
|
||||
}
|
||||
|
||||
bool EntityDamageSource::scalesWithDifficulty() {
|
||||
return entity != NULL && std::dynamic_pointer_cast<Mob>(entity) &&
|
||||
!(std::dynamic_pointer_cast<Player>(entity));
|
||||
return (entity != NULL) && entity->instanceof(eTYPE_LIVINGENTITY) &&
|
||||
!entity->instanceof(eTYPE_PLAYER);
|
||||
}
|
||||
|
||||
// 4J: Copy function
|
||||
DamageSource* EntityDamageSource::copy() {
|
||||
return new EntityDamageSource(*this);
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ public:
|
|||
// EntityDamageSource(const std::wstring &msgId, std::shared_ptr<Entity>
|
||||
// entity);
|
||||
EntityDamageSource(ChatPacket::EChatPacketMessage msgId,
|
||||
ChatPacket::EChatPacketMessage msgWithItemId,
|
||||
std::shared_ptr<Entity> entity);
|
||||
virtual ~EntityDamageSource() {}
|
||||
|
||||
|
|
@ -22,7 +23,9 @@ public:
|
|||
// virtual std::wstring getLocalizedDeathMessage(std::shared_ptr<Player>
|
||||
// player);
|
||||
virtual std::shared_ptr<ChatPacket> getDeathMessagePacket(
|
||||
std::shared_ptr<Player> player);
|
||||
std::shared_ptr<LivingEntity> player);
|
||||
|
||||
virtual bool scalesWithDifficulty();
|
||||
|
||||
virtual DamageSource* copy();
|
||||
};
|
||||
42
Minecraft.World/Entities/EntitySelector.cpp
Normal file
42
Minecraft.World/Entities/EntitySelector.cpp
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
#include "../Platform/stdafx.h"
|
||||
#include "../Containers/Container.h"
|
||||
#include "EntitySelector.h"
|
||||
|
||||
const EntitySelector* EntitySelector::ENTITY_STILL_ALIVE =
|
||||
new AliveEntitySelector();
|
||||
const EntitySelector* EntitySelector::CONTAINER_ENTITY_SELECTOR =
|
||||
new ContainerEntitySelector();
|
||||
|
||||
bool AliveEntitySelector::matches(std::shared_ptr<Entity> entity) const {
|
||||
return entity->isAlive();
|
||||
}
|
||||
|
||||
bool ContainerEntitySelector::matches(std::shared_ptr<Entity> entity) const {
|
||||
return (std::dynamic_pointer_cast<Container>(entity) != NULL) &&
|
||||
entity->isAlive();
|
||||
}
|
||||
|
||||
MobCanWearArmourEntitySelector::MobCanWearArmourEntitySelector(
|
||||
std::shared_ptr<ItemInstance> item) {
|
||||
this->item = item;
|
||||
}
|
||||
|
||||
bool MobCanWearArmourEntitySelector::matches(
|
||||
std::shared_ptr<Entity> entity) const {
|
||||
if (!entity->isAlive()) return false;
|
||||
if (!entity->instanceof(eTYPE_LIVINGENTITY)) return false;
|
||||
|
||||
std::shared_ptr<LivingEntity> mob =
|
||||
std::dynamic_pointer_cast<LivingEntity>(entity);
|
||||
|
||||
if (mob->getCarried(Mob::getEquipmentSlotForItem(item)) != NULL)
|
||||
return false;
|
||||
|
||||
if (mob->instanceof(eTYPE_MOB)) {
|
||||
return std::dynamic_pointer_cast<Mob>(mob)->canPickUpLoot();
|
||||
} else if (mob->instanceof(eTYPE_PLAYER)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
28
Minecraft.World/Entities/EntitySelector.h
Normal file
28
Minecraft.World/Entities/EntitySelector.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
class EntitySelector {
|
||||
public:
|
||||
static const EntitySelector* ENTITY_STILL_ALIVE;
|
||||
static const EntitySelector* CONTAINER_ENTITY_SELECTOR;
|
||||
|
||||
virtual bool matches(std::shared_ptr<Entity> entity) const = 0;
|
||||
};
|
||||
|
||||
class AliveEntitySelector : public EntitySelector {
|
||||
public:
|
||||
bool matches(std::shared_ptr<Entity> entity) const;
|
||||
};
|
||||
|
||||
class ContainerEntitySelector : public EntitySelector {
|
||||
public:
|
||||
bool matches(std::shared_ptr<Entity> entity) const;
|
||||
};
|
||||
|
||||
class MobCanWearArmourEntitySelector : public EntitySelector {
|
||||
private:
|
||||
std::shared_ptr<ItemInstance> item;
|
||||
|
||||
public:
|
||||
MobCanWearArmourEntitySelector(std::shared_ptr<ItemInstance> item);
|
||||
bool matches(std::shared_ptr<Entity> entity) const;
|
||||
};
|
||||
158
Minecraft.World/Entities/FireworksRocketEntity.cpp
Normal file
158
Minecraft.World/Entities/FireworksRocketEntity.cpp
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
#include "../Platform/stdafx.h"
|
||||
#include "../Headers/net.minecraft.world.entity.h"
|
||||
#include "../Headers/net.minecraft.world.item.h"
|
||||
#include "../Headers/net.minecraft.world.level.h"
|
||||
#include "FireworksRocketEntity.h"
|
||||
|
||||
FireworksRocketEntity::FireworksRocketEntity(Level* level) : Entity(level) {
|
||||
defineSynchedData();
|
||||
|
||||
life = 0;
|
||||
lifetime = 0;
|
||||
setSize(0.25f, 0.25f);
|
||||
}
|
||||
|
||||
void FireworksRocketEntity::defineSynchedData() {
|
||||
entityData->defineNULL(DATA_ID_FIREWORKS_ITEM, NULL);
|
||||
}
|
||||
|
||||
bool FireworksRocketEntity::shouldRenderAtSqrDistance(double distance) {
|
||||
return distance < 64 * 64;
|
||||
}
|
||||
|
||||
FireworksRocketEntity::FireworksRocketEntity(
|
||||
Level* level, double x, double y, double z,
|
||||
std::shared_ptr<ItemInstance> sourceItem)
|
||||
: Entity(level) {
|
||||
defineSynchedData();
|
||||
|
||||
life = 0;
|
||||
|
||||
setSize(0.25f, 0.25f);
|
||||
|
||||
setPos(x, y, z);
|
||||
heightOffset = 0;
|
||||
|
||||
int flightCount = 1;
|
||||
if (sourceItem != NULL && sourceItem->hasTag()) {
|
||||
entityData->set(DATA_ID_FIREWORKS_ITEM, sourceItem);
|
||||
|
||||
CompoundTag* tag = sourceItem->getTag();
|
||||
CompoundTag* compound = tag->getCompound(FireworksItem::TAG_FIREWORKS);
|
||||
if (compound != NULL) {
|
||||
flightCount += compound->getByte(FireworksItem::TAG_FLIGHT);
|
||||
}
|
||||
}
|
||||
xd = random->nextGaussian() * .001;
|
||||
zd = random->nextGaussian() * .001;
|
||||
yd = 0.05;
|
||||
|
||||
lifetime = (SharedConstants::TICKS_PER_SECOND / 2) * flightCount +
|
||||
random->nextInt(6) + random->nextInt(7);
|
||||
}
|
||||
|
||||
void FireworksRocketEntity::lerpMotion(double xd, double yd, double zd) {
|
||||
xd = xd;
|
||||
yd = yd;
|
||||
zd = zd;
|
||||
if (xRotO == 0 && yRotO == 0) {
|
||||
double sd = Mth::sqrt(xd * xd + zd * zd);
|
||||
yRotO = yRot = (float)(atan2(xd, zd) * 180 / PI);
|
||||
xRotO = xRot = (float)(atan2(yd, sd) * 180 / PI);
|
||||
}
|
||||
}
|
||||
|
||||
void FireworksRocketEntity::tick() {
|
||||
xOld = x;
|
||||
yOld = y;
|
||||
zOld = z;
|
||||
Entity::tick();
|
||||
|
||||
xd *= 1.15;
|
||||
zd *= 1.15;
|
||||
yd += .04;
|
||||
move(xd, yd, zd);
|
||||
|
||||
double sd = Mth::sqrt(xd * xd + zd * zd);
|
||||
yRot = (float)(atan2(xd, zd) * 180 / PI);
|
||||
xRot = (float)(atan2(yd, sd) * 180 / PI);
|
||||
|
||||
while (xRot - xRotO < -180) xRotO -= 360;
|
||||
while (xRot - xRotO >= 180) xRotO += 360;
|
||||
|
||||
while (yRot - yRotO < -180) yRotO -= 360;
|
||||
while (yRot - yRotO >= 180) yRotO += 360;
|
||||
|
||||
xRot = xRotO + (xRot - xRotO) * 0.2f;
|
||||
yRot = yRotO + (yRot - yRotO) * 0.2f;
|
||||
|
||||
if (!level->isClientSide) {
|
||||
if (life == 0) {
|
||||
level->playEntitySound(shared_from_this(),
|
||||
eSoundType_FIREWORKS_LAUNCH, 3, 1);
|
||||
}
|
||||
}
|
||||
|
||||
life++;
|
||||
if (level->isClientSide && (life % 2) < 2) {
|
||||
level->addParticle(eParticleType_fireworksspark, x, y - .3, z,
|
||||
random->nextGaussian() * .05, -yd * .5,
|
||||
random->nextGaussian() * .05);
|
||||
}
|
||||
if (!level->isClientSide && life > lifetime) {
|
||||
level->broadcastEntityEvent(shared_from_this(),
|
||||
EntityEvent::FIREWORKS_EXPLODE);
|
||||
remove();
|
||||
}
|
||||
}
|
||||
|
||||
void FireworksRocketEntity::handleEntityEvent(uint8_t eventId) {
|
||||
if (eventId == EntityEvent::FIREWORKS_EXPLODE && level->isClientSide) {
|
||||
std::shared_ptr<ItemInstance> sourceItem =
|
||||
entityData->getItemInstance(DATA_ID_FIREWORKS_ITEM);
|
||||
CompoundTag* tag = NULL;
|
||||
if (sourceItem != NULL && sourceItem->hasTag()) {
|
||||
tag =
|
||||
sourceItem->getTag()->getCompound(FireworksItem::TAG_FIREWORKS);
|
||||
}
|
||||
level->createFireworks(x, y, z, xd, yd, zd, tag);
|
||||
}
|
||||
Entity::handleEntityEvent(eventId);
|
||||
}
|
||||
|
||||
void FireworksRocketEntity::addAdditonalSaveData(CompoundTag* tag) {
|
||||
tag->putInt(L"Life", life);
|
||||
tag->putInt(L"LifeTime", lifetime);
|
||||
std::shared_ptr<ItemInstance> itemInstance =
|
||||
entityData->getItemInstance(DATA_ID_FIREWORKS_ITEM);
|
||||
if (itemInstance != NULL) {
|
||||
CompoundTag* itemTag = new CompoundTag();
|
||||
itemInstance->save(itemTag);
|
||||
tag->putCompound(L"FireworksItem", itemTag);
|
||||
}
|
||||
}
|
||||
|
||||
void FireworksRocketEntity::readAdditionalSaveData(CompoundTag* tag) {
|
||||
life = tag->getInt(L"Life");
|
||||
lifetime = tag->getInt(L"LifeTime");
|
||||
|
||||
CompoundTag* itemTag = tag->getCompound(L"FireworksItem");
|
||||
if (itemTag != NULL) {
|
||||
std::shared_ptr<ItemInstance> fromTag = ItemInstance::fromTag(itemTag);
|
||||
if (fromTag != NULL) {
|
||||
entityData->set(DATA_ID_FIREWORKS_ITEM, fromTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float FireworksRocketEntity::getShadowHeightOffs() { return 0; }
|
||||
|
||||
float FireworksRocketEntity::getBrightness(float a) {
|
||||
return Entity::getBrightness(a);
|
||||
}
|
||||
|
||||
int FireworksRocketEntity::getLightColor(float a) {
|
||||
return Entity::getLightColor(a);
|
||||
}
|
||||
|
||||
bool FireworksRocketEntity::isAttackable() { return false; }
|
||||
40
Minecraft.World/Entities/FireworksRocketEntity.h
Normal file
40
Minecraft.World/Entities/FireworksRocketEntity.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
|
||||
#include "Entity.h"
|
||||
|
||||
class FireworksRocketEntity : public Entity {
|
||||
public:
|
||||
eINSTANCEOF GetType() { return eTYPE_FIREWORKS_ROCKET; }
|
||||
static Entity* create(Level* level) {
|
||||
return new FireworksRocketEntity(level);
|
||||
}
|
||||
|
||||
private:
|
||||
static const int DATA_ID_FIREWORKS_ITEM = 8;
|
||||
|
||||
int life;
|
||||
int lifetime;
|
||||
|
||||
// constructor needed for level loader
|
||||
public:
|
||||
FireworksRocketEntity(Level* level);
|
||||
|
||||
protected:
|
||||
virtual void defineSynchedData();
|
||||
|
||||
public:
|
||||
virtual bool shouldRenderAtSqrDistance(double distance);
|
||||
|
||||
FireworksRocketEntity(Level* level, double x, double y, double z,
|
||||
std::shared_ptr<ItemInstance> sourceItem);
|
||||
|
||||
virtual void lerpMotion(double xd, double yd, double zd);
|
||||
virtual void tick();
|
||||
virtual void handleEntityEvent(uint8_t eventId);
|
||||
virtual void addAdditonalSaveData(CompoundTag* tag);
|
||||
virtual void readAdditionalSaveData(CompoundTag* tag);
|
||||
virtual float getShadowHeightOffs();
|
||||
virtual float getBrightness(float a);
|
||||
virtual int getLightColor(float a);
|
||||
virtual bool isAttackable();
|
||||
};
|
||||
|
|
@ -11,6 +11,11 @@ void FlyingMob::causeFallDamage(float distance) {
|
|||
// not trigger the "fallOn" tile calls (such as trampling crops)
|
||||
}
|
||||
|
||||
void FlyingMob::checkFallDamage(double ya, bool onGround) {
|
||||
// this method is empty because flying creatures should
|
||||
// not trigger the "fallOn" tile calls (such as trampling crops)
|
||||
}
|
||||
|
||||
void FlyingMob::travel(float xa, float ya) {
|
||||
if (isInWater()) {
|
||||
moveRelative(xa, ya, 0.02f);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ public:
|
|||
|
||||
protected:
|
||||
virtual void causeFallDamage(float distance);
|
||||
virtual void checkFallDamage(double ya, bool onGround);
|
||||
|
||||
public:
|
||||
virtual void travel(float xa, float ya);
|
||||
|
|
|
|||
|
|
@ -11,22 +11,16 @@ void HangingEntity::_init(Level* level) {
|
|||
checkInterval = 0;
|
||||
dir = 0;
|
||||
xTile = yTile = zTile = 0;
|
||||
}
|
||||
|
||||
HangingEntity::HangingEntity(Level* level) : Entity(level) {
|
||||
_init(level);
|
||||
|
||||
this->heightOffset = 0;
|
||||
this->setSize(0.5f, 0.5f);
|
||||
}
|
||||
|
||||
HangingEntity::HangingEntity(Level* level) : Entity(level) { _init(level); }
|
||||
|
||||
HangingEntity::HangingEntity(Level* level, int xTile, int yTile, int zTile,
|
||||
int dir)
|
||||
: Entity(level) {
|
||||
_init(level);
|
||||
// motive = NULL;
|
||||
this->heightOffset = 0;
|
||||
this->setSize(0.5f, 0.5f);
|
||||
this->xTile = xTile;
|
||||
this->yTile = yTile;
|
||||
this->zTile = zTile;
|
||||
|
|
@ -34,7 +28,7 @@ HangingEntity::HangingEntity(Level* level, int xTile, int yTile, int zTile,
|
|||
|
||||
void HangingEntity::setDir(int dir) {
|
||||
this->dir = dir;
|
||||
this->yRotO = this->yRot = (float)(dir * 90);
|
||||
yRotO = yRot = (float)(dir * 90);
|
||||
|
||||
float w = (float)getWidth();
|
||||
float h = (float)getHeight();
|
||||
|
|
@ -68,7 +62,7 @@ void HangingEntity::setDir(int dir) {
|
|||
if (dir == Direction::EAST) z -= offs(getWidth());
|
||||
y += offs(getHeight());
|
||||
|
||||
this->setPos(x, y, z);
|
||||
setPos(x, y, z);
|
||||
|
||||
float ss = -(0.5f / 16.0f);
|
||||
|
||||
|
|
@ -91,12 +85,14 @@ float HangingEntity::offs(int w) {
|
|||
}
|
||||
|
||||
void HangingEntity::tick() {
|
||||
if (checkInterval++ == 20 * 5 && !level->isClientSide) // isClientSide)
|
||||
{
|
||||
xo = x;
|
||||
yo = y;
|
||||
zo = z;
|
||||
if (checkInterval++ == 20 * 5 && !level->isClientSide) {
|
||||
checkInterval = 0;
|
||||
if (!removed && !survives()) {
|
||||
remove();
|
||||
dropItem();
|
||||
dropItem(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -138,7 +134,7 @@ bool HangingEntity::survives() {
|
|||
AUTO_VAR(itEnd, entities->end());
|
||||
for (AUTO_VAR(it, entities->begin()); it != itEnd; it++) {
|
||||
std::shared_ptr<Entity> e = (*it);
|
||||
if (std::dynamic_pointer_cast<HangingEntity>(e) != NULL) {
|
||||
if (e->instanceof(eTYPE_HANGING_ENTITY)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -159,12 +155,14 @@ bool HangingEntity::skipAttackInteraction(std::shared_ptr<Entity> source) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool HangingEntity::hurt(DamageSource* source, int damage) {
|
||||
bool HangingEntity::hurt(DamageSource* source, float damage) {
|
||||
if (isInvulnerable()) return false;
|
||||
if (!removed && !level->isClientSide) {
|
||||
if (dynamic_cast<EntityDamageSource*>(source) != NULL) {
|
||||
std::shared_ptr<Entity> sourceEntity = source->getDirectEntity();
|
||||
|
||||
if (std::dynamic_pointer_cast<Player>(sourceEntity) != NULL &&
|
||||
if ((sourceEntity != NULL) &&
|
||||
sourceEntity->instanceof(eTYPE_PLAYER) &&
|
||||
!std::dynamic_pointer_cast<Player>(sourceEntity)
|
||||
->isAllowedToHurtEntity(shared_from_this())) {
|
||||
return false;
|
||||
|
|
@ -176,8 +174,9 @@ bool HangingEntity::hurt(DamageSource* source, int damage) {
|
|||
|
||||
std::shared_ptr<Player> player = nullptr;
|
||||
std::shared_ptr<Entity> e = source->getEntity();
|
||||
if (e != NULL && ((e->GetType() & eTYPE_PLAYER) !=
|
||||
0)) // check if it's serverplayer or player
|
||||
if ((e != NULL) &&
|
||||
e->instanceof(
|
||||
eTYPE_PLAYER)) // check if it's serverplayer or player
|
||||
{
|
||||
player = std::dynamic_pointer_cast<Player>(e);
|
||||
}
|
||||
|
|
@ -186,7 +185,7 @@ bool HangingEntity::hurt(DamageSource* source, int damage) {
|
|||
return true;
|
||||
}
|
||||
|
||||
dropItem();
|
||||
dropItem(nullptr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -195,14 +194,14 @@ bool HangingEntity::hurt(DamageSource* source, int damage) {
|
|||
void HangingEntity::move(double xa, double ya, double za, bool noEntityCubes) {
|
||||
if (!level->isClientSide && !removed && (xa * xa + ya * ya + za * za) > 0) {
|
||||
remove();
|
||||
dropItem();
|
||||
dropItem(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void HangingEntity::push(double xa, double ya, double za) {
|
||||
if (!level->isClientSide && !removed && (xa * xa + ya * ya + za * za) > 0) {
|
||||
remove();
|
||||
dropItem();
|
||||
dropItem(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -253,3 +252,5 @@ void HangingEntity::readAdditionalSaveData(CompoundTag* tag) {
|
|||
zTile = tag->getInt(L"TileZ");
|
||||
setDir(dir);
|
||||
}
|
||||
|
||||
bool HangingEntity::repositionEntityAfterLoad() { return false; }
|
||||
|
|
@ -9,7 +9,6 @@ public:
|
|||
|
||||
private:
|
||||
void _init(Level* level);
|
||||
float offs(int w);
|
||||
|
||||
int checkInterval;
|
||||
// eINSTANCEOF eType;
|
||||
|
|
@ -24,12 +23,16 @@ public:
|
|||
HangingEntity(Level* level);
|
||||
HangingEntity(Level* level, int xTile, int yTile, int zTile, int dir);
|
||||
void setDir(int dir);
|
||||
bool survives();
|
||||
virtual bool survives();
|
||||
|
||||
private:
|
||||
float offs(int w);
|
||||
|
||||
public:
|
||||
virtual void tick();
|
||||
virtual bool isPickable();
|
||||
virtual bool skipAttackInteraction(std::shared_ptr<Entity> source);
|
||||
virtual bool hurt(DamageSource* source, int damage);
|
||||
virtual bool hurt(DamageSource* source, float damage);
|
||||
virtual void move(
|
||||
double xa, double ya, double za,
|
||||
bool noEntityCubes = false); // 4J - added noEntityCubes parameter
|
||||
|
|
@ -39,5 +42,8 @@ public:
|
|||
|
||||
virtual int getWidth() = 0;
|
||||
virtual int getHeight() = 0;
|
||||
virtual void dropItem() = 0;
|
||||
virtual void dropItem(std::shared_ptr<Entity> causedBy) = 0;
|
||||
|
||||
protected:
|
||||
virtual bool repositionEntityAfterLoad();
|
||||
};
|
||||
|
|
|
|||
16
Minecraft.World/Entities/HealthBoostMobEffect.cpp
Normal file
16
Minecraft.World/Entities/HealthBoostMobEffect.cpp
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#include "../Platform/stdafx.h"
|
||||
#include "../Headers/net.minecraft.world.entity.h"
|
||||
#include "HealthBoostMobEffect.h"
|
||||
|
||||
HealthBoostMobEffect::HealthBoostMobEffect(int id, bool isHarmful,
|
||||
eMinecraftColour color)
|
||||
: MobEffect(id, isHarmful, color) {}
|
||||
|
||||
void HealthBoostMobEffect::removeAttributeModifiers(
|
||||
std::shared_ptr<LivingEntity> entity, BaseAttributeMap* attributes,
|
||||
int amplifier) {
|
||||
MobEffect::removeAttributeModifiers(entity, attributes, amplifier);
|
||||
if (entity->getHealth() > entity->getMaxHealth()) {
|
||||
entity->setHealth(entity->getMaxHealth());
|
||||
}
|
||||
}
|
||||
14
Minecraft.World/Entities/HealthBoostMobEffect.h
Normal file
14
Minecraft.World/Entities/HealthBoostMobEffect.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "MobEffect.h"
|
||||
|
||||
class LivingEntity;
|
||||
class BaseAttributeMap;
|
||||
|
||||
class HealthBoostMobEffect : public MobEffect {
|
||||
public:
|
||||
HealthBoostMobEffect(int id, bool isHarmful, eMinecraftColour color);
|
||||
|
||||
void removeAttributeModifiers(std::shared_ptr<LivingEntity> entity,
|
||||
BaseAttributeMap* attributes, int amplifier);
|
||||
};
|
||||
|
|
@ -4,13 +4,14 @@
|
|||
#include "../Headers/net.minecraft.world.damagesource.h"
|
||||
#include "../Headers/net.minecraft.network.packet.h"
|
||||
|
||||
// IndirectEntityDamageSource::IndirectEntityDamageSource(const std::wstring
|
||||
// &msgId, std::shared_ptr<Entity> entity, std::shared_ptr<Entity> owner) :
|
||||
// IndirectEntityDamageSource::IndirectEntityDamageSource(const wstring &msgId,
|
||||
// shared_ptr<Entity> entity, shared_ptr<Entity> owner) :
|
||||
// EntityDamageSource(msgId, entity)
|
||||
IndirectEntityDamageSource::IndirectEntityDamageSource(
|
||||
ChatPacket::EChatPacketMessage msgId, std::shared_ptr<Entity> entity,
|
||||
std::shared_ptr<Entity> owner)
|
||||
: EntityDamageSource(msgId, entity) {
|
||||
ChatPacket::EChatPacketMessage msgId,
|
||||
ChatPacket::EChatPacketMessage msgWithItemId,
|
||||
std::shared_ptr<Entity> entity, std::shared_ptr<Entity> owner)
|
||||
: EntityDamageSource(msgId, msgWithItemId, entity) {
|
||||
this->owner = owner;
|
||||
}
|
||||
|
||||
|
|
@ -23,8 +24,8 @@ std::shared_ptr<Entity> IndirectEntityDamageSource::getEntity() {
|
|||
return owner;
|
||||
}
|
||||
|
||||
// std::wstring
|
||||
// IndirectEntityDamageSource::getLocalizedDeathMessage(std::shared_ptr<Player>
|
||||
// wstring
|
||||
// IndirectEntityDamageSource::getLocalizedDeathMessage(shared_ptr<Player>
|
||||
// player)
|
||||
//{
|
||||
// return L"death." + msgId + player->name + owner->getAName();
|
||||
|
|
@ -32,7 +33,11 @@ std::shared_ptr<Entity> IndirectEntityDamageSource::getEntity() {
|
|||
// }
|
||||
|
||||
std::shared_ptr<ChatPacket> IndirectEntityDamageSource::getDeathMessagePacket(
|
||||
std::shared_ptr<Player> player) {
|
||||
std::shared_ptr<LivingEntity> player) {
|
||||
std::shared_ptr<ItemInstance> held =
|
||||
entity->instanceof(eTYPE_LIVINGENTITY)
|
||||
? std::dynamic_pointer_cast<LivingEntity>(entity)->getCarriedItem()
|
||||
: nullptr;
|
||||
std::wstring additional = L"";
|
||||
int type;
|
||||
if (owner != NULL) {
|
||||
|
|
@ -45,6 +50,17 @@ std::shared_ptr<ChatPacket> IndirectEntityDamageSource::getDeathMessagePacket(
|
|||
} else {
|
||||
type = entity->GetType();
|
||||
}
|
||||
return std::shared_ptr<ChatPacket>(
|
||||
new ChatPacket(player->name, m_msgId, type, additional));
|
||||
if (held != NULL && held->hasCustomHoverName()) {
|
||||
return std::shared_ptr<ChatPacket>(
|
||||
new ChatPacket(player->getNetworkName(), m_msgWithItemId, type,
|
||||
additional, held->getHoverName()));
|
||||
} else {
|
||||
return std::shared_ptr<ChatPacket>(new ChatPacket(
|
||||
player->getNetworkName(), m_msgId, type, additional));
|
||||
}
|
||||
}
|
||||
|
||||
// 4J: Copy function
|
||||
DamageSource* IndirectEntityDamageSource::copy() {
|
||||
return new IndirectEntityDamageSource(*this);
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ public:
|
|||
// IndirectEntityDamageSource(const std::wstring &msgId,
|
||||
// std::shared_ptr<Entity> entity, std::shared_ptr<Entity> owner);
|
||||
IndirectEntityDamageSource(ChatPacket::EChatPacketMessage msgId,
|
||||
ChatPacket::EChatPacketMessage msgWithItemId,
|
||||
std::shared_ptr<Entity> entity,
|
||||
std::shared_ptr<Entity> owner);
|
||||
virtual ~IndirectEntityDamageSource() {}
|
||||
|
|
@ -25,5 +26,7 @@ public:
|
|||
// virtual std::wstring getLocalizedDeathMessage(std::shared_ptr<Player>
|
||||
// player);
|
||||
virtual std::shared_ptr<ChatPacket> getDeathMessagePacket(
|
||||
std::shared_ptr<Player> player);
|
||||
std::shared_ptr<LivingEntity> player);
|
||||
|
||||
virtual DamageSource* copy();
|
||||
};
|
||||
|
|
@ -83,8 +83,8 @@ void ItemEntity::tick() {
|
|||
xd = (random->nextFloat() - random->nextFloat()) * 0.2f;
|
||||
zd = (random->nextFloat() - random->nextFloat()) * 0.2f;
|
||||
MemSect(31);
|
||||
level->playSound(shared_from_this(), eSoundType_RANDOM_FIZZ, 0.4f,
|
||||
2.0f + random->nextFloat() * 0.4f);
|
||||
playSound(eSoundType_RANDOM_FIZZ, 0.4f,
|
||||
2.0f + random->nextFloat() * 0.4f);
|
||||
MemSect(0);
|
||||
}
|
||||
|
||||
|
|
@ -168,7 +168,7 @@ bool ItemEntity::updateInWaterState() {
|
|||
|
||||
void ItemEntity::burn(int dmg) { hurt(DamageSource::inFire, dmg); }
|
||||
|
||||
bool ItemEntity::hurt(DamageSource* source, int damage) {
|
||||
bool ItemEntity::hurt(DamageSource* source, float damage) {
|
||||
// 4J - added next line: found whilst debugging an issue with item entities
|
||||
// getting into a bad state when being created by a cactus, since entities
|
||||
// insides cactuses get hurt and therefore depending on the timing of things
|
||||
|
|
@ -177,6 +177,10 @@ bool ItemEntity::hurt(DamageSource* source, int damage) {
|
|||
// hurt?
|
||||
if (level->isClientSide) return false;
|
||||
|
||||
if (isInvulnerable()) return false;
|
||||
if (getItem() != NULL && getItem()->id == Item::netherStar_Id &&
|
||||
source->isExplosion())
|
||||
return false;
|
||||
markHurt();
|
||||
health -= damage;
|
||||
if (health <= 0) {
|
||||
|
|
@ -238,8 +242,8 @@ void ItemEntity::playerTouch(std::shared_ptr<Player> player) {
|
|||
player->awardStat(GenericStats::blazeRod(),
|
||||
GenericStats::param_blazeRod());
|
||||
|
||||
level->playSound(
|
||||
shared_from_this(), eSoundType_RANDOM_POP, 0.2f,
|
||||
playSound(
|
||||
eSoundType_RANDOM_POP, 0.2f,
|
||||
((random->nextFloat() - random->nextFloat()) * 0.7f + 1.0f) * 2.0f);
|
||||
player->take(shared_from_this(), orgCount);
|
||||
// System.out.println(item.count + ", " + orgCount);
|
||||
|
|
@ -252,6 +256,12 @@ std::wstring ItemEntity::getAName() {
|
|||
// return I18n.get("item." + item.getDescriptionId());
|
||||
}
|
||||
|
||||
void ItemEntity::changeDimension(int i) {
|
||||
Entity::changeDimension(i);
|
||||
|
||||
if (!level->isClientSide) mergeWithNeighbours();
|
||||
}
|
||||
|
||||
std::shared_ptr<ItemInstance> ItemEntity::getItem() {
|
||||
std::shared_ptr<ItemInstance> result =
|
||||
getEntityData()->getItemInstance(DATA_ITEM);
|
||||
|
|
@ -262,7 +272,7 @@ std::shared_ptr<ItemInstance> ItemEntity::getItem() {
|
|||
// level.getLogger().severe("Item entity " + entityId + " has no
|
||||
// item?!");
|
||||
}
|
||||
return std::shared_ptr<ItemInstance>(new ItemInstance(Tile::rock));
|
||||
return std::shared_ptr<ItemInstance>(new ItemInstance(Tile::stone));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -59,13 +59,13 @@ protected:
|
|||
virtual void burn(int dmg);
|
||||
|
||||
public:
|
||||
virtual bool hurt(DamageSource* source, int damage);
|
||||
virtual bool hurt(DamageSource* source, float damage);
|
||||
virtual void addAdditonalSaveData(CompoundTag* entityTag);
|
||||
virtual void readAdditionalSaveData(CompoundTag* tag);
|
||||
virtual void playerTouch(std::shared_ptr<Player> player);
|
||||
|
||||
virtual std::wstring getAName();
|
||||
|
||||
virtual void changeDimension(int i);
|
||||
std::shared_ptr<ItemInstance> getItem();
|
||||
void setItem(std::shared_ptr<ItemInstance> item);
|
||||
virtual bool isAttackable();
|
||||
|
|
|
|||
47
Minecraft.World/Entities/LargeFireball.cpp
Normal file
47
Minecraft.World/Entities/LargeFireball.cpp
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#include "../Platform/stdafx.h"
|
||||
#include "../Headers/net.minecraft.world.damagesource.h"
|
||||
#include "../Headers/net.minecraft.world.level.h"
|
||||
#include "../Headers/net.minecraft.world.phys.h"
|
||||
#include "LargeFireball.h"
|
||||
|
||||
LargeFireball::LargeFireball(Level* level) : Fireball(level) {
|
||||
explosionPower = 1;
|
||||
}
|
||||
|
||||
LargeFireball::LargeFireball(Level* level, double x, double y, double z,
|
||||
double xa, double ya, double za)
|
||||
: Fireball(level, x, y, z, xa, ya, za) {
|
||||
explosionPower = 1;
|
||||
}
|
||||
|
||||
LargeFireball::LargeFireball(Level* level, std::shared_ptr<LivingEntity> mob,
|
||||
double xa, double ya, double za)
|
||||
: Fireball(level, mob, xa, ya, za) {
|
||||
explosionPower = 1;
|
||||
}
|
||||
|
||||
void LargeFireball::onHit(HitResult* res) {
|
||||
if (!level->isClientSide) {
|
||||
if (res->entity != NULL) {
|
||||
DamageSource* damageSource = DamageSource::fireball(
|
||||
std::dynamic_pointer_cast<Fireball>(shared_from_this()), owner);
|
||||
res->entity->hurt(damageSource, 6);
|
||||
delete damageSource;
|
||||
}
|
||||
level->explode(
|
||||
nullptr, x, y, z, explosionPower, true,
|
||||
level->getGameRules()->getBoolean(GameRules::RULE_MOBGRIEFING));
|
||||
remove();
|
||||
}
|
||||
}
|
||||
|
||||
void LargeFireball::addAdditonalSaveData(CompoundTag* tag) {
|
||||
Fireball::addAdditonalSaveData(tag);
|
||||
tag->putInt(L"ExplosionPower", explosionPower);
|
||||
}
|
||||
|
||||
void LargeFireball::readAdditionalSaveData(CompoundTag* tag) {
|
||||
Fireball::readAdditionalSaveData(tag);
|
||||
if (tag->contains(L"ExplosionPower"))
|
||||
explosionPower = tag->getInt(L"ExplosionPower");
|
||||
}
|
||||
25
Minecraft.World/Entities/LargeFireball.h
Normal file
25
Minecraft.World/Entities/LargeFireball.h
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
|
||||
#include "Mobs/Fireball.h"
|
||||
|
||||
class LargeFireball : public Fireball {
|
||||
public:
|
||||
eINSTANCEOF GetType() { return eTYPE_LARGE_FIREBALL; }
|
||||
static Entity* create(Level* level) { return new LargeFireball(level); }
|
||||
|
||||
public:
|
||||
int explosionPower;
|
||||
|
||||
LargeFireball(Level* level);
|
||||
LargeFireball(Level* level, double x, double y, double z, double xa,
|
||||
double ya, double za);
|
||||
LargeFireball(Level* level, std::shared_ptr<LivingEntity> mob, double xa,
|
||||
double ya, double za);
|
||||
|
||||
protected:
|
||||
void onHit(HitResult* res);
|
||||
|
||||
public:
|
||||
void addAdditonalSaveData(CompoundTag* tag);
|
||||
void readAdditionalSaveData(CompoundTag* tag);
|
||||
};
|
||||
140
Minecraft.World/Entities/LeashFenceKnotEntity.cpp
Normal file
140
Minecraft.World/Entities/LeashFenceKnotEntity.cpp
Normal file
|
|
@ -0,0 +1,140 @@
|
|||
#include "../Platform/stdafx.h"
|
||||
#include "../Headers/net.minecraft.world.entity.player.h"
|
||||
#include "../Headers/net.minecraft.world.item.h"
|
||||
#include "../Headers/net.minecraft.world.level.h"
|
||||
#include "../Headers/net.minecraft.world.phys.h"
|
||||
#include "LeashFenceKnotEntity.h"
|
||||
|
||||
void LeashFenceKnotEntity::_init() { defineSynchedData(); }
|
||||
|
||||
LeashFenceKnotEntity::LeashFenceKnotEntity(Level* level)
|
||||
: HangingEntity(level) {
|
||||
_init();
|
||||
}
|
||||
|
||||
LeashFenceKnotEntity::LeashFenceKnotEntity(Level* level, int xTile, int yTile,
|
||||
int zTile)
|
||||
: HangingEntity(level, xTile, yTile, zTile, 0) {
|
||||
_init();
|
||||
setPos(xTile + .5, yTile + .5, zTile + .5);
|
||||
}
|
||||
|
||||
void LeashFenceKnotEntity::defineSynchedData() {
|
||||
HangingEntity::defineSynchedData();
|
||||
}
|
||||
|
||||
void LeashFenceKnotEntity::setDir(int dir) {
|
||||
// override to do nothing, knots don't have directions
|
||||
}
|
||||
|
||||
int LeashFenceKnotEntity::getWidth() { return 9; }
|
||||
|
||||
int LeashFenceKnotEntity::getHeight() { return 9; }
|
||||
|
||||
bool LeashFenceKnotEntity::shouldRenderAtSqrDistance(double distance) {
|
||||
return distance < 32 * 32;
|
||||
}
|
||||
|
||||
void LeashFenceKnotEntity::dropItem(std::shared_ptr<Entity> causedBy) {}
|
||||
|
||||
bool LeashFenceKnotEntity::save(CompoundTag* entityTag) {
|
||||
// knots are not saved, they are recreated by the entities that are tied
|
||||
return false;
|
||||
}
|
||||
|
||||
void LeashFenceKnotEntity::addAdditonalSaveData(CompoundTag* tag) {}
|
||||
|
||||
void LeashFenceKnotEntity::readAdditionalSaveData(CompoundTag* tag) {}
|
||||
|
||||
bool LeashFenceKnotEntity::interact(std::shared_ptr<Player> player) {
|
||||
std::shared_ptr<ItemInstance> item = player->getCarriedItem();
|
||||
|
||||
bool attachedMob = false;
|
||||
if (item != NULL && item->id == Item::lead_Id) {
|
||||
if (!level->isClientSide) {
|
||||
// look for entities that can be attached to the fence
|
||||
double range = 7;
|
||||
std::vector<std::shared_ptr<Entity> >* mobs =
|
||||
level->getEntitiesOfClass(
|
||||
typeid(Mob),
|
||||
AABB::newTemp(x - range, y - range, z - range, x + range,
|
||||
y + range, z + range));
|
||||
if (mobs != NULL) {
|
||||
for (AUTO_VAR(it, mobs->begin()); it != mobs->end(); ++it) {
|
||||
std::shared_ptr<Mob> mob =
|
||||
std::dynamic_pointer_cast<Mob>(*it);
|
||||
if (mob->isLeashed() && mob->getLeashHolder() == player) {
|
||||
mob->setLeashedTo(shared_from_this(), true);
|
||||
attachedMob = true;
|
||||
}
|
||||
}
|
||||
delete mobs;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!level->isClientSide && !attachedMob) {
|
||||
remove();
|
||||
|
||||
if (player->abilities.instabuild) {
|
||||
// if the player is in creative mode, attempt to remove all leashed
|
||||
// mobs without dropping additional items
|
||||
double range = 7;
|
||||
std::vector<std::shared_ptr<Entity> >* mobs =
|
||||
level->getEntitiesOfClass(
|
||||
typeid(Mob),
|
||||
AABB::newTemp(x - range, y - range, z - range, x + range,
|
||||
y + range, z + range));
|
||||
if (mobs != NULL) {
|
||||
for (AUTO_VAR(it, mobs->begin()); it != mobs->end(); ++it) {
|
||||
std::shared_ptr<Mob> mob =
|
||||
std::dynamic_pointer_cast<Mob>(*it);
|
||||
if (mob->isLeashed() &&
|
||||
mob->getLeashHolder() == shared_from_this()) {
|
||||
mob->dropLeash(true, false);
|
||||
}
|
||||
}
|
||||
delete mobs;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LeashFenceKnotEntity::survives() {
|
||||
// knots are placed on top of fence tiles
|
||||
int tile = level->getTile(xTile, yTile, zTile);
|
||||
if (Tile::tiles[tile] != NULL &&
|
||||
Tile::tiles[tile]->getRenderShape() == Tile::SHAPE_FENCE) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<LeashFenceKnotEntity> LeashFenceKnotEntity::createAndAddKnot(
|
||||
Level* level, int x, int y, int z) {
|
||||
std::shared_ptr<LeashFenceKnotEntity> knot =
|
||||
std::shared_ptr<LeashFenceKnotEntity>(
|
||||
new LeashFenceKnotEntity(level, x, y, z));
|
||||
knot->forcedLoading = true;
|
||||
level->addEntity(knot);
|
||||
return knot;
|
||||
}
|
||||
|
||||
std::shared_ptr<LeashFenceKnotEntity> LeashFenceKnotEntity::findKnotAt(
|
||||
Level* level, int x, int y, int z) {
|
||||
std::vector<std::shared_ptr<Entity> >* knots = level->getEntitiesOfClass(
|
||||
typeid(LeashFenceKnotEntity),
|
||||
AABB::newTemp(x - 1.0, y - 1.0, z - 1.0, x + 1.0, y + 1.0, z + 1.0));
|
||||
if (knots != NULL) {
|
||||
for (AUTO_VAR(it, knots->begin()); it != knots->end(); ++it) {
|
||||
std::shared_ptr<LeashFenceKnotEntity> knot =
|
||||
std::dynamic_pointer_cast<LeashFenceKnotEntity>(*it);
|
||||
if (knot->xTile == x && knot->yTile == y && knot->zTile == z) {
|
||||
delete knots;
|
||||
return knot;
|
||||
}
|
||||
}
|
||||
delete knots;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
38
Minecraft.World/Entities/LeashFenceKnotEntity.h
Normal file
38
Minecraft.World/Entities/LeashFenceKnotEntity.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#pragma once
|
||||
|
||||
#include "HangingEntity.h"
|
||||
|
||||
class LeashFenceKnotEntity : public HangingEntity {
|
||||
public:
|
||||
eINSTANCEOF GetType() { return eTYPE_LEASHFENCEKNOT; };
|
||||
static Entity* create(Level* level) {
|
||||
return new LeashFenceKnotEntity(level);
|
||||
}
|
||||
|
||||
private:
|
||||
void _init();
|
||||
|
||||
public:
|
||||
LeashFenceKnotEntity(Level* level);
|
||||
LeashFenceKnotEntity(Level* level, int xTile, int yTile, int zTile);
|
||||
|
||||
protected:
|
||||
void defineSynchedData();
|
||||
|
||||
public:
|
||||
void setDir(int dir);
|
||||
int getWidth();
|
||||
int getHeight();
|
||||
bool shouldRenderAtSqrDistance(double distance);
|
||||
void dropItem(std::shared_ptr<Entity> causedBy);
|
||||
bool save(CompoundTag* entityTag);
|
||||
void addAdditonalSaveData(CompoundTag* tag);
|
||||
void readAdditionalSaveData(CompoundTag* tag);
|
||||
bool interact(std::shared_ptr<Player> player);
|
||||
virtual bool survives();
|
||||
static std::shared_ptr<LeashFenceKnotEntity> createAndAddKnot(Level* level,
|
||||
int x, int y,
|
||||
int z);
|
||||
static std::shared_ptr<LeashFenceKnotEntity> findKnotAt(Level* level, int x,
|
||||
int y, int z);
|
||||
};
|
||||
1735
Minecraft.World/Entities/LivingEntity.cpp
Normal file
1735
Minecraft.World/Entities/LivingEntity.cpp
Normal file
File diff suppressed because it is too large
Load diff
330
Minecraft.World/Entities/LivingEntity.h
Normal file
330
Minecraft.World/Entities/LivingEntity.h
Normal file
|
|
@ -0,0 +1,330 @@
|
|||
#pragma once
|
||||
|
||||
#include "Entity.h"
|
||||
#include "MobType.h"
|
||||
#include "../AI/Goals/GoalSelector.h"
|
||||
#include "../Util/SharedConstants.h"
|
||||
|
||||
class CombatTracker;
|
||||
class AttributeInstance;
|
||||
class AttributeModifier;
|
||||
class MobEffectInstance;
|
||||
class BaseAttributeMap;
|
||||
class Team;
|
||||
class Attribute;
|
||||
class MobEffect;
|
||||
class HitResult;
|
||||
class Vec3;
|
||||
|
||||
class LivingEntity : public Entity {
|
||||
friend class MobSpawner;
|
||||
|
||||
protected:
|
||||
// 4J - added for common ctor code
|
||||
void _init();
|
||||
|
||||
public:
|
||||
// 4J-PB - added to replace (e instanceof Type), avoiding dynamic casts
|
||||
eINSTANCEOF GetType() { return eTYPE_LIVINGENTITY; }
|
||||
static Entity* create(Level* level) { return NULL; }
|
||||
|
||||
private:
|
||||
static AttributeModifier* SPEED_MODIFIER_SPRINTING;
|
||||
|
||||
public:
|
||||
static const int SLOT_WEAPON = 0;
|
||||
static const int SLOT_BOOTS = 1;
|
||||
static const int SLOT_LEGGINGS = 2;
|
||||
static const int SLOT_CHEST = 3;
|
||||
static const int SLOT_HELM = 4;
|
||||
|
||||
static const int SWING_DURATION = 6;
|
||||
static const int PLAYER_HURT_EXPERIENCE_TIME =
|
||||
SharedConstants::TICKS_PER_SECOND * 5;
|
||||
|
||||
private:
|
||||
static const double MIN_MOVEMENT_DISTANCE;
|
||||
|
||||
public:
|
||||
static const int DATA_HEALTH_ID = 6;
|
||||
static const int DATA_EFFECT_COLOR_ID = 7;
|
||||
static const int DATA_EFFECT_AMBIENCE_ID = 8;
|
||||
static const int DATA_ARROW_COUNT_ID = 9;
|
||||
|
||||
private:
|
||||
BaseAttributeMap* attributes;
|
||||
CombatTracker* combatTracker;
|
||||
std::unordered_map<int, MobEffectInstance*> activeEffects;
|
||||
ItemInstanceArray lastEquipment;
|
||||
|
||||
public:
|
||||
bool swinging;
|
||||
int swingTime;
|
||||
int removeArrowTime;
|
||||
float lastHealth;
|
||||
|
||||
int hurtTime;
|
||||
int hurtDuration;
|
||||
float hurtDir;
|
||||
int deathTime;
|
||||
int attackTime;
|
||||
float oAttackAnim, attackAnim;
|
||||
|
||||
float walkAnimSpeedO;
|
||||
float walkAnimSpeed;
|
||||
float walkAnimPos;
|
||||
int invulnerableDuration;
|
||||
float oTilt, tilt;
|
||||
float timeOffs;
|
||||
float rotA;
|
||||
float yBodyRot, yBodyRotO;
|
||||
float yHeadRot, yHeadRotO;
|
||||
float flyingSpeed;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Player> lastHurtByPlayer;
|
||||
int lastHurtByPlayerTime;
|
||||
bool dead;
|
||||
int noActionTime;
|
||||
float oRun, run;
|
||||
float animStep, animStepO;
|
||||
float rotOffs;
|
||||
int deathScore;
|
||||
float lastHurt;
|
||||
bool jumping;
|
||||
|
||||
public:
|
||||
float xxa;
|
||||
float yya;
|
||||
|
||||
protected:
|
||||
float yRotA;
|
||||
int lSteps;
|
||||
double lx, ly, lz, lyr, lxr;
|
||||
|
||||
private:
|
||||
bool effectsDirty;
|
||||
|
||||
std::shared_ptr<LivingEntity> lastHurtByMob;
|
||||
int lastHurtByMobTimestamp;
|
||||
std::shared_ptr<LivingEntity> lastHurtMob;
|
||||
int lastHurtMobTimestamp;
|
||||
|
||||
float speed;
|
||||
|
||||
protected:
|
||||
int noJumpDelay;
|
||||
|
||||
private:
|
||||
float absorptionAmount;
|
||||
|
||||
public:
|
||||
LivingEntity(Level* level);
|
||||
virtual ~LivingEntity();
|
||||
|
||||
protected:
|
||||
virtual void defineSynchedData();
|
||||
virtual void registerAttributes();
|
||||
virtual void checkFallDamage(double ya, bool onGround);
|
||||
|
||||
public:
|
||||
virtual bool isWaterMob();
|
||||
virtual void baseTick();
|
||||
virtual bool isBaby();
|
||||
|
||||
protected:
|
||||
virtual void tickDeath();
|
||||
virtual int decreaseAirSupply(int currentSupply);
|
||||
virtual int getExperienceReward(std::shared_ptr<Player> killedBy);
|
||||
virtual bool isAlwaysExperienceDropper();
|
||||
|
||||
public:
|
||||
virtual Random* getRandom();
|
||||
virtual std::shared_ptr<LivingEntity> getLastHurtByMob();
|
||||
virtual int getLastHurtByMobTimestamp();
|
||||
virtual void setLastHurtByMob(std::shared_ptr<LivingEntity> hurtBy);
|
||||
virtual std::shared_ptr<LivingEntity> getLastHurtMob();
|
||||
virtual int getLastHurtMobTimestamp();
|
||||
virtual void setLastHurtMob(std::shared_ptr<Entity> target);
|
||||
virtual int getNoActionTime();
|
||||
virtual void addAdditonalSaveData(CompoundTag* entityTag);
|
||||
virtual void readAdditionalSaveData(CompoundTag* tag);
|
||||
|
||||
protected:
|
||||
virtual void tickEffects();
|
||||
|
||||
public:
|
||||
virtual void removeAllEffects();
|
||||
virtual std::vector<MobEffectInstance*>* getActiveEffects();
|
||||
virtual bool hasEffect(int id);
|
||||
virtual bool hasEffect(MobEffect* effect);
|
||||
virtual MobEffectInstance* getEffect(MobEffect* effect);
|
||||
virtual void addEffect(MobEffectInstance* newEffect);
|
||||
virtual void addEffectNoUpdate(MobEffectInstance* newEffect); // 4J added
|
||||
virtual bool canBeAffected(MobEffectInstance* newEffect);
|
||||
virtual bool isInvertedHealAndHarm();
|
||||
virtual void removeEffectNoUpdate(int effectId);
|
||||
virtual void removeEffect(int effectId);
|
||||
|
||||
protected:
|
||||
virtual void onEffectAdded(MobEffectInstance* effect);
|
||||
virtual void onEffectUpdated(MobEffectInstance* effect,
|
||||
bool doRefreshAttributes);
|
||||
virtual void onEffectRemoved(MobEffectInstance* effect);
|
||||
|
||||
public:
|
||||
virtual void heal(float heal);
|
||||
virtual float getHealth();
|
||||
virtual void setHealth(float health);
|
||||
virtual bool hurt(DamageSource* source, float dmg);
|
||||
virtual void breakItem(std::shared_ptr<ItemInstance> itemInstance);
|
||||
virtual void die(DamageSource* source);
|
||||
|
||||
protected:
|
||||
virtual void dropEquipment(bool byPlayer, int playerBonusLevel);
|
||||
|
||||
public:
|
||||
virtual void knockback(std::shared_ptr<Entity> source, float dmg, double xd,
|
||||
double zd);
|
||||
|
||||
protected:
|
||||
virtual int getHurtSound();
|
||||
virtual int getDeathSound();
|
||||
|
||||
protected:
|
||||
virtual void dropRareDeathLoot(int rareLootLevel);
|
||||
virtual void dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel);
|
||||
|
||||
public:
|
||||
virtual bool onLadder();
|
||||
virtual bool isShootable();
|
||||
virtual bool isAlive();
|
||||
virtual void causeFallDamage(float distance);
|
||||
virtual void animateHurt();
|
||||
virtual int getArmorValue();
|
||||
|
||||
protected:
|
||||
virtual void hurtArmor(float damage);
|
||||
virtual float getDamageAfterArmorAbsorb(DamageSource* damageSource,
|
||||
float damage);
|
||||
virtual float getDamageAfterMagicAbsorb(DamageSource* damageSource,
|
||||
float damage);
|
||||
virtual void actuallyHurt(DamageSource* source, float dmg);
|
||||
|
||||
public:
|
||||
virtual CombatTracker* getCombatTracker();
|
||||
virtual std::shared_ptr<LivingEntity> getKillCredit();
|
||||
virtual float getMaxHealth();
|
||||
virtual int getArrowCount();
|
||||
virtual void setArrowCount(int count);
|
||||
|
||||
private:
|
||||
int getCurrentSwingDuration();
|
||||
|
||||
public:
|
||||
virtual void swing();
|
||||
virtual void handleEntityEvent(uint8_t id);
|
||||
|
||||
protected:
|
||||
virtual void outOfWorld();
|
||||
virtual void updateSwingTime();
|
||||
|
||||
public:
|
||||
virtual AttributeInstance* getAttribute(Attribute* attribute);
|
||||
virtual BaseAttributeMap* getAttributes();
|
||||
virtual MobType getMobType();
|
||||
|
||||
virtual std::shared_ptr<ItemInstance> getCarriedItem() = 0;
|
||||
virtual std::shared_ptr<ItemInstance> getCarried(int slot) = 0;
|
||||
virtual std::shared_ptr<ItemInstance> getArmor(int pos) = 0;
|
||||
virtual void setEquippedSlot(int slot,
|
||||
std::shared_ptr<ItemInstance> item) = 0;
|
||||
virtual void setSprinting(bool value);
|
||||
|
||||
virtual ItemInstanceArray getEquipmentSlots() = 0;
|
||||
|
||||
virtual Icon* getItemInHandIcon(std::shared_ptr<ItemInstance> item,
|
||||
int layer);
|
||||
|
||||
protected:
|
||||
virtual float getSoundVolume();
|
||||
virtual float getVoicePitch();
|
||||
virtual bool isImmobile();
|
||||
|
||||
public:
|
||||
virtual void teleportTo(double x, double y, double z);
|
||||
|
||||
protected:
|
||||
virtual void findStandUpPosition(std::shared_ptr<Entity> vehicle);
|
||||
|
||||
public:
|
||||
virtual bool shouldShowName();
|
||||
|
||||
protected:
|
||||
virtual void jumpFromGround();
|
||||
|
||||
public:
|
||||
virtual void travel(float xa, float ya);
|
||||
|
||||
virtual int getLightColor(float a); // 4J - added
|
||||
|
||||
protected:
|
||||
virtual bool useNewAi();
|
||||
|
||||
public:
|
||||
virtual float getSpeed();
|
||||
virtual void setSpeed(float speed);
|
||||
virtual bool doHurtTarget(std::shared_ptr<Entity> target);
|
||||
virtual bool isSleeping();
|
||||
virtual void tick();
|
||||
|
||||
protected:
|
||||
virtual float tickHeadTurn(float yBodyRotT, float walkSpeed);
|
||||
|
||||
public:
|
||||
virtual void aiStep();
|
||||
|
||||
protected:
|
||||
virtual void newServerAiStep();
|
||||
virtual void pushEntities();
|
||||
virtual void doPush(std::shared_ptr<Entity> e);
|
||||
|
||||
public:
|
||||
virtual void rideTick();
|
||||
virtual void lerpTo(double x, double y, double z, float yRot, float xRot,
|
||||
int steps);
|
||||
|
||||
protected:
|
||||
virtual void serverAiMobStep();
|
||||
virtual void serverAiStep();
|
||||
|
||||
public:
|
||||
virtual void setJumping(bool jump);
|
||||
virtual void take(std::shared_ptr<Entity> e, int orgCount);
|
||||
virtual bool canSee(std::shared_ptr<Entity> target);
|
||||
|
||||
public:
|
||||
virtual Vec3* getLookAngle();
|
||||
virtual Vec3* getViewVector(float a);
|
||||
virtual float getAttackAnim(float a);
|
||||
virtual Vec3* getPos(float a);
|
||||
virtual HitResult* pick(double range, float a);
|
||||
virtual bool isEffectiveAi();
|
||||
|
||||
virtual bool isPickable();
|
||||
virtual bool isPushable();
|
||||
virtual float getHeadHeight();
|
||||
|
||||
protected:
|
||||
virtual void markHurt();
|
||||
|
||||
public:
|
||||
virtual float getYHeadRot();
|
||||
virtual void setYHeadRot(float yHeadRot);
|
||||
|
||||
virtual float getAbsorptionAmount();
|
||||
virtual void setAbsorptionAmount(float absorptionAmount);
|
||||
virtual Team* getTeam();
|
||||
virtual bool isAlliedTo(std::shared_ptr<LivingEntity> other);
|
||||
virtual bool isAlliedTo(Team* other);
|
||||
};
|
||||
36
Minecraft.World/Entities/MinecartChest.cpp
Normal file
36
Minecraft.World/Entities/MinecartChest.cpp
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
#include "../Platform/stdafx.h"
|
||||
#include "../Headers/net.minecraft.world.level.tile.h"
|
||||
#include "../Headers/net.minecraft.network.packet.h"
|
||||
#include "MinecartChest.h"
|
||||
|
||||
MinecartChest::MinecartChest(Level* level) : MinecartContainer(level) {
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
}
|
||||
|
||||
MinecartChest::MinecartChest(Level* level, double x, double y, double z)
|
||||
: MinecartContainer(level, x, y, z) {
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
}
|
||||
|
||||
// 4J Added
|
||||
int MinecartChest::getContainerType() {
|
||||
return ContainerOpenPacket::MINECART_CHEST;
|
||||
}
|
||||
|
||||
void MinecartChest::destroy(DamageSource* source) {
|
||||
MinecartContainer::destroy(source);
|
||||
|
||||
spawnAtLocation(Tile::chest_Id, 1, 0);
|
||||
}
|
||||
|
||||
unsigned int MinecartChest::getContainerSize() { return 9 * 3; }
|
||||
|
||||
int MinecartChest::getType() { return TYPE_CHEST; }
|
||||
|
||||
Tile* MinecartChest::getDefaultDisplayTile() { return Tile::chest; }
|
||||
|
||||
int MinecartChest::getDefaultDisplayOffset() { return 8; }
|
||||
22
Minecraft.World/Entities/MinecartChest.h
Normal file
22
Minecraft.World/Entities/MinecartChest.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#pragma once
|
||||
|
||||
#include "MinecartContainer.h"
|
||||
|
||||
class MinecartChest : public MinecartContainer {
|
||||
public:
|
||||
eINSTANCEOF GetType() { return eTYPE_MINECART_CHEST; };
|
||||
static Entity* create(Level* level) { return new MinecartChest(level); }
|
||||
|
||||
public:
|
||||
MinecartChest(Level* level);
|
||||
MinecartChest(Level* level, double x, double y, double z);
|
||||
|
||||
// 4J added
|
||||
virtual int getContainerType();
|
||||
|
||||
virtual void destroy(DamageSource* source);
|
||||
virtual unsigned int getContainerSize();
|
||||
virtual int getType();
|
||||
virtual Tile* getDefaultDisplayTile();
|
||||
virtual int getDefaultDisplayOffset();
|
||||
};
|
||||
213
Minecraft.World/Entities/MinecartContainer.cpp
Normal file
213
Minecraft.World/Entities/MinecartContainer.cpp
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
#include "../Platform/stdafx.h"
|
||||
#include "../Headers/net.minecraft.world.entity.item.h"
|
||||
#include "../Headers/net.minecraft.world.item.h"
|
||||
#include "../Headers/net.minecraft.world.inventory.h"
|
||||
#include "../Headers/net.minecraft.world.level.h"
|
||||
#include "../Headers/net.minecraft.world.level.redstone.h"
|
||||
#include "MinecartContainer.h"
|
||||
|
||||
void MinecartContainer::_init() {
|
||||
items = ItemInstanceArray(9 * 4);
|
||||
dropEquipment = true;
|
||||
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
}
|
||||
|
||||
MinecartContainer::MinecartContainer(Level* level) : Minecart(level) {
|
||||
_init();
|
||||
}
|
||||
|
||||
MinecartContainer::MinecartContainer(Level* level, double x, double y, double z)
|
||||
: Minecart(level, x, y, z) {
|
||||
_init();
|
||||
}
|
||||
|
||||
void MinecartContainer::destroy(DamageSource* source) {
|
||||
Minecart::destroy(source);
|
||||
|
||||
for (int i = 0; i < getContainerSize(); i++) {
|
||||
std::shared_ptr<ItemInstance> item = getItem(i);
|
||||
if (item != NULL) {
|
||||
float xo = random->nextFloat() * 0.8f + 0.1f;
|
||||
float yo = random->nextFloat() * 0.8f + 0.1f;
|
||||
float zo = random->nextFloat() * 0.8f + 0.1f;
|
||||
|
||||
while (item->count > 0) {
|
||||
int count = random->nextInt(21) + 10;
|
||||
if (count > item->count) count = item->count;
|
||||
item->count -= count;
|
||||
|
||||
std::shared_ptr<ItemEntity> itemEntity =
|
||||
std::shared_ptr<ItemEntity>(new ItemEntity(
|
||||
level, x + xo, y + yo, z + zo,
|
||||
std::shared_ptr<ItemInstance>(new ItemInstance(
|
||||
item->id, count, item->getAuxValue()))));
|
||||
float pow = 0.05f;
|
||||
itemEntity->xd = (float)random->nextGaussian() * pow;
|
||||
itemEntity->yd = (float)random->nextGaussian() * pow + 0.2f;
|
||||
itemEntity->zd = (float)random->nextGaussian() * pow;
|
||||
level->addEntity(itemEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<ItemInstance> MinecartContainer::getItem(unsigned int slot) {
|
||||
return items[slot];
|
||||
}
|
||||
|
||||
std::shared_ptr<ItemInstance> MinecartContainer::removeItem(unsigned int slot,
|
||||
int count) {
|
||||
if (items[slot] != NULL) {
|
||||
if (items[slot]->count <= count) {
|
||||
std::shared_ptr<ItemInstance> item = items[slot];
|
||||
items[slot] = nullptr;
|
||||
return item;
|
||||
} else {
|
||||
std::shared_ptr<ItemInstance> i = items[slot]->remove(count);
|
||||
if (items[slot]->count == 0) items[slot] = nullptr;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::shared_ptr<ItemInstance> MinecartContainer::removeItemNoUpdate(int slot) {
|
||||
if (items[slot] != NULL) {
|
||||
std::shared_ptr<ItemInstance> item = items[slot];
|
||||
items[slot] = nullptr;
|
||||
return item;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MinecartContainer::setItem(unsigned int slot,
|
||||
std::shared_ptr<ItemInstance> item) {
|
||||
items[slot] = item;
|
||||
if (item != NULL && item->count > getMaxStackSize())
|
||||
item->count = getMaxStackSize();
|
||||
}
|
||||
|
||||
void MinecartContainer::setChanged() {}
|
||||
|
||||
bool MinecartContainer::stillValid(std::shared_ptr<Player> player) {
|
||||
if (removed) return false;
|
||||
if (player->distanceToSqr(shared_from_this()) > 8 * 8) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void MinecartContainer::startOpen() {}
|
||||
|
||||
void MinecartContainer::stopOpen() {}
|
||||
|
||||
bool MinecartContainer::canPlaceItem(int slot,
|
||||
std::shared_ptr<ItemInstance> item) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::wstring MinecartContainer::getName() {
|
||||
return hasCustomName() ? getCustomName()
|
||||
: app.GetString(IDS_CONTAINER_MINECART);
|
||||
}
|
||||
|
||||
int MinecartContainer::getMaxStackSize() {
|
||||
return Container::LARGE_MAX_STACK_SIZE;
|
||||
}
|
||||
|
||||
void MinecartContainer::changeDimension(int i) {
|
||||
dropEquipment = false;
|
||||
Minecart::changeDimension(i);
|
||||
}
|
||||
|
||||
void MinecartContainer::remove() {
|
||||
if (dropEquipment) {
|
||||
for (int i = 0; i < getContainerSize(); i++) {
|
||||
std::shared_ptr<ItemInstance> item = getItem(i);
|
||||
if (item != NULL) {
|
||||
float xo = random->nextFloat() * 0.8f + 0.1f;
|
||||
float yo = random->nextFloat() * 0.8f + 0.1f;
|
||||
float zo = random->nextFloat() * 0.8f + 0.1f;
|
||||
|
||||
while (item->count > 0) {
|
||||
int count = random->nextInt(21) + 10;
|
||||
if (count > item->count) count = item->count;
|
||||
item->count -= count;
|
||||
|
||||
std::shared_ptr<ItemEntity> itemEntity =
|
||||
std::shared_ptr<ItemEntity>(new ItemEntity(
|
||||
level, x + xo, y + yo, z + zo,
|
||||
std::shared_ptr<ItemInstance>(new ItemInstance(
|
||||
item->id, count, item->getAuxValue()))));
|
||||
|
||||
if (item->hasTag()) {
|
||||
itemEntity->getItem()->setTag(
|
||||
(CompoundTag*)item->getTag()->copy());
|
||||
}
|
||||
|
||||
float pow = 0.05f;
|
||||
itemEntity->xd = (float)random->nextGaussian() * pow;
|
||||
itemEntity->yd = (float)random->nextGaussian() * pow + 0.2f;
|
||||
itemEntity->zd = (float)random->nextGaussian() * pow;
|
||||
level->addEntity(itemEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Minecart::remove();
|
||||
}
|
||||
|
||||
void MinecartContainer::addAdditonalSaveData(CompoundTag* base) {
|
||||
Minecart::addAdditonalSaveData(base);
|
||||
|
||||
ListTag<CompoundTag>* listTag = new ListTag<CompoundTag>();
|
||||
|
||||
for (int i = 0; i < items.length; i++) {
|
||||
if (items[i] != NULL) {
|
||||
CompoundTag* tag = new CompoundTag();
|
||||
tag->putByte(L"Slot", (uint8_t)i);
|
||||
items[i]->save(tag);
|
||||
listTag->add(tag);
|
||||
}
|
||||
}
|
||||
base->put(L"Items", listTag);
|
||||
}
|
||||
|
||||
void MinecartContainer::readAdditionalSaveData(CompoundTag* base) {
|
||||
Minecart::readAdditionalSaveData(base);
|
||||
|
||||
ListTag<CompoundTag>* inventoryList =
|
||||
(ListTag<CompoundTag>*)base->getList(L"Items");
|
||||
delete[] items.data;
|
||||
items = ItemInstanceArray(getContainerSize());
|
||||
for (int i = 0; i < inventoryList->size(); i++) {
|
||||
CompoundTag* tag = inventoryList->get(i);
|
||||
int slot = tag->getByte(L"Slot") & 0xff;
|
||||
if (slot >= 0 && slot < items.length)
|
||||
items[slot] = ItemInstance::fromTag(tag);
|
||||
}
|
||||
}
|
||||
|
||||
bool MinecartContainer::interact(std::shared_ptr<Player> player) {
|
||||
if (!level->isClientSide) {
|
||||
player->openContainer(
|
||||
std::dynamic_pointer_cast<Container>(shared_from_this()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MinecartContainer::applyNaturalSlowdown() {
|
||||
std::shared_ptr<Container> container =
|
||||
std::dynamic_pointer_cast<Container>(shared_from_this());
|
||||
int emptiness =
|
||||
Redstone::SIGNAL_MAX -
|
||||
AbstractContainerMenu::getRedstoneSignalFromContainer(container);
|
||||
float keep = 0.98f + (emptiness * 0.001f);
|
||||
|
||||
xd *= keep;
|
||||
yd *= 0;
|
||||
zd *= keep;
|
||||
}
|
||||
47
Minecraft.World/Entities/MinecartContainer.h
Normal file
47
Minecraft.World/Entities/MinecartContainer.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
|
||||
#include "Mobs/Minecart.h"
|
||||
#include "../Containers/Container.h"
|
||||
|
||||
class MinecartContainer : public Minecart, public virtual Container {
|
||||
private:
|
||||
ItemInstanceArray items;
|
||||
bool dropEquipment;
|
||||
|
||||
void _init();
|
||||
|
||||
public:
|
||||
MinecartContainer(Level* level);
|
||||
MinecartContainer(Level* level, double x, double y, double z);
|
||||
|
||||
virtual void destroy(DamageSource* source);
|
||||
virtual std::shared_ptr<ItemInstance> getItem(unsigned int slot);
|
||||
virtual std::shared_ptr<ItemInstance> removeItem(unsigned int slot,
|
||||
int count);
|
||||
virtual std::shared_ptr<ItemInstance> removeItemNoUpdate(int slot);
|
||||
virtual void setItem(unsigned int slot, std::shared_ptr<ItemInstance> item);
|
||||
virtual void setChanged();
|
||||
virtual bool stillValid(std::shared_ptr<Player> player);
|
||||
virtual void startOpen();
|
||||
virtual void stopOpen();
|
||||
virtual bool canPlaceItem(int slot, std::shared_ptr<ItemInstance> item);
|
||||
virtual std::wstring getName();
|
||||
virtual int getMaxStackSize();
|
||||
virtual void changeDimension(int i);
|
||||
virtual void remove();
|
||||
|
||||
protected:
|
||||
virtual void addAdditonalSaveData(CompoundTag* base);
|
||||
virtual void readAdditionalSaveData(CompoundTag* base);
|
||||
|
||||
public:
|
||||
virtual bool interact(std::shared_ptr<Player> player);
|
||||
|
||||
protected:
|
||||
virtual void applyNaturalSlowdown();
|
||||
|
||||
public:
|
||||
// 4J Stu - For container
|
||||
virtual bool hasCustomName() { return Minecart::hasCustomName(); }
|
||||
virtual std::wstring getCustomName() { return Minecart::getCustomName(); }
|
||||
};
|
||||
148
Minecraft.World/Entities/MinecartFurnace.cpp
Normal file
148
Minecraft.World/Entities/MinecartFurnace.cpp
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
#include "../Platform/stdafx.h"
|
||||
#include "../Headers/net.minecraft.world.damagesource.h"
|
||||
#include "../Headers/net.minecraft.world.entity.h"
|
||||
#include "../Headers/net.minecraft.world.entity.player.h"
|
||||
#include "../Headers/net.minecraft.world.level.h"
|
||||
#include "../Headers/net.minecraft.world.item.h"
|
||||
#include "../Headers/net.minecraft.network.packet.h"
|
||||
#include "MinecartFurnace.h"
|
||||
|
||||
MinecartFurnace::MinecartFurnace(Level* level) : Minecart(level) {
|
||||
defineSynchedData();
|
||||
|
||||
fuel = 0;
|
||||
xPush = zPush = 0.0f;
|
||||
}
|
||||
|
||||
MinecartFurnace::MinecartFurnace(Level* level, double x, double y, double z)
|
||||
: Minecart(level, x, y, z) {
|
||||
defineSynchedData();
|
||||
|
||||
fuel = 0;
|
||||
xPush = zPush = 0.0f;
|
||||
}
|
||||
|
||||
// 4J Added
|
||||
int MinecartFurnace::getContainerType() {
|
||||
return ContainerOpenPacket::MINECART_HOPPER;
|
||||
}
|
||||
|
||||
int MinecartFurnace::getType() { return TYPE_FURNACE; }
|
||||
|
||||
void MinecartFurnace::defineSynchedData() {
|
||||
Minecart::defineSynchedData();
|
||||
entityData->define(DATA_ID_FUEL, (uint8_t)0);
|
||||
}
|
||||
|
||||
void MinecartFurnace::tick() {
|
||||
Minecart::tick();
|
||||
|
||||
if (fuel > 0) {
|
||||
fuel--;
|
||||
}
|
||||
if (fuel <= 0) {
|
||||
xPush = zPush = 0;
|
||||
}
|
||||
setHasFuel(fuel > 0);
|
||||
|
||||
if (hasFuel() && random->nextInt(4) == 0) {
|
||||
level->addParticle(eParticleType_largesmoke, x, y + 0.8, z, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void MinecartFurnace::destroy(DamageSource* source) {
|
||||
Minecart::destroy(source);
|
||||
|
||||
if (!source->isExplosion()) {
|
||||
spawnAtLocation(
|
||||
std::shared_ptr<ItemInstance>(new ItemInstance(Tile::furnace, 1)),
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
void MinecartFurnace::moveAlongTrack(int xt, int yt, int zt, double maxSpeed,
|
||||
double slideSpeed, int tile, int data) {
|
||||
Minecart::moveAlongTrack(xt, yt, zt, maxSpeed, slideSpeed, tile, data);
|
||||
|
||||
double sd = xPush * xPush + zPush * zPush;
|
||||
if (sd > 0.01 * 0.01 && xd * xd + zd * zd > 0.001) {
|
||||
sd = Mth::sqrt(sd);
|
||||
xPush /= sd;
|
||||
zPush /= sd;
|
||||
|
||||
if (xPush * xd + zPush * zd < 0) {
|
||||
xPush = 0;
|
||||
zPush = 0;
|
||||
} else {
|
||||
xPush = xd;
|
||||
zPush = zd;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MinecartFurnace::applyNaturalSlowdown() {
|
||||
double sd = xPush * xPush + zPush * zPush;
|
||||
|
||||
if (sd > 0.01 * 0.01) {
|
||||
sd = Mth::sqrt(sd);
|
||||
xPush /= sd;
|
||||
zPush /= sd;
|
||||
double speed = 0.05;
|
||||
xd *= 0.8f;
|
||||
yd *= 0;
|
||||
zd *= 0.8f;
|
||||
xd += xPush * speed;
|
||||
zd += zPush * speed;
|
||||
} else {
|
||||
xd *= 0.98f;
|
||||
yd *= 0;
|
||||
zd *= 0.98f;
|
||||
}
|
||||
|
||||
Minecart::applyNaturalSlowdown();
|
||||
}
|
||||
|
||||
bool MinecartFurnace::interact(std::shared_ptr<Player> player) {
|
||||
std::shared_ptr<ItemInstance> selected = player->inventory->getSelected();
|
||||
if (selected != NULL && selected->id == Item::coal_Id) {
|
||||
if (!player->abilities.instabuild && --selected->count == 0)
|
||||
player->inventory->setItem(player->inventory->selected, nullptr);
|
||||
fuel += SharedConstants::TICKS_PER_SECOND * 180;
|
||||
}
|
||||
xPush = x - player->x;
|
||||
zPush = z - player->z;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MinecartFurnace::addAdditonalSaveData(CompoundTag* base) {
|
||||
Minecart::addAdditonalSaveData(base);
|
||||
base->putDouble(L"PushX", xPush);
|
||||
base->putDouble(L"PushZ", zPush);
|
||||
base->putShort(L"Fuel", (short)fuel);
|
||||
}
|
||||
|
||||
void MinecartFurnace::readAdditionalSaveData(CompoundTag* base) {
|
||||
Minecart::readAdditionalSaveData(base);
|
||||
xPush = base->getDouble(L"PushX");
|
||||
zPush = base->getDouble(L"PushZ");
|
||||
fuel = base->getShort(L"Fuel");
|
||||
}
|
||||
|
||||
bool MinecartFurnace::hasFuel() {
|
||||
return (entityData->getByte(DATA_ID_FUEL) & 1) != 0;
|
||||
}
|
||||
|
||||
void MinecartFurnace::setHasFuel(bool fuel) {
|
||||
if (fuel) {
|
||||
entityData->set(DATA_ID_FUEL,
|
||||
(uint8_t)(entityData->getByte(DATA_ID_FUEL) | 1));
|
||||
} else {
|
||||
entityData->set(DATA_ID_FUEL,
|
||||
(uint8_t)(entityData->getByte(DATA_ID_FUEL) & ~1));
|
||||
}
|
||||
}
|
||||
|
||||
Tile* MinecartFurnace::getDefaultDisplayTile() { return Tile::furnace_lit; }
|
||||
|
||||
int MinecartFurnace::getDefaultDisplayData() { return 2; }
|
||||
51
Minecraft.World/Entities/MinecartFurnace.h
Normal file
51
Minecraft.World/Entities/MinecartFurnace.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#pragma once
|
||||
|
||||
#include "Mobs/Minecart.h"
|
||||
|
||||
class MinecartFurnace : public Minecart {
|
||||
public:
|
||||
eINSTANCEOF GetType() { return eTYPE_MINECART_FURNACE; };
|
||||
static Entity* create(Level* level) { return new MinecartFurnace(level); }
|
||||
|
||||
private:
|
||||
static const int DATA_ID_FUEL = 16;
|
||||
|
||||
private:
|
||||
int fuel;
|
||||
|
||||
public:
|
||||
double xPush, zPush;
|
||||
|
||||
MinecartFurnace(Level* level);
|
||||
MinecartFurnace(Level* level, double x, double y, double z);
|
||||
|
||||
// 4J added
|
||||
virtual int getContainerType();
|
||||
|
||||
int getType();
|
||||
|
||||
protected:
|
||||
void defineSynchedData();
|
||||
|
||||
public:
|
||||
void tick();
|
||||
void destroy(DamageSource* source);
|
||||
|
||||
protected:
|
||||
void moveAlongTrack(int xt, int yt, int zt, double maxSpeed,
|
||||
double slideSpeed, int tile, int data);
|
||||
void applyNaturalSlowdown();
|
||||
|
||||
public:
|
||||
bool interact(std::shared_ptr<Player> player);
|
||||
|
||||
protected:
|
||||
void addAdditonalSaveData(CompoundTag* base);
|
||||
void readAdditionalSaveData(CompoundTag* base);
|
||||
bool hasFuel();
|
||||
void setHasFuel(bool fuel);
|
||||
|
||||
public:
|
||||
Tile* getDefaultDisplayTile();
|
||||
int getDefaultDisplayData();
|
||||
};
|
||||
119
Minecraft.World/Entities/MinecartHopper.cpp
Normal file
119
Minecraft.World/Entities/MinecartHopper.cpp
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
#include "../Platform/stdafx.h"
|
||||
#include "../Headers/net.minecraft.world.entity.h"
|
||||
#include "../Headers/net.minecraft.world.entity.player.h"
|
||||
#include "../Headers/net.minecraft.world.level.h"
|
||||
#include "../Headers/net.minecraft.world.level.tile.h"
|
||||
#include "../Headers/net.minecraft.world.level.tile.entity.h"
|
||||
#include "../Headers/net.minecraft.world.entity.item.h"
|
||||
#include "../Headers/net.minecraft.world.phys.h"
|
||||
#include "MinecartHopper.h"
|
||||
|
||||
const int MinecartHopper::MOVE_ITEM_SPEED =
|
||||
HopperTileEntity::MOVE_ITEM_SPEED / 2;
|
||||
|
||||
void MinecartHopper::_init() {
|
||||
enabled = true;
|
||||
cooldownTime = -1;
|
||||
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
}
|
||||
|
||||
MinecartHopper::MinecartHopper(Level* level) : MinecartContainer(level) {
|
||||
_init();
|
||||
}
|
||||
|
||||
MinecartHopper::MinecartHopper(Level* level, double x, double y, double z)
|
||||
: MinecartContainer(level, x, y, z) {
|
||||
_init();
|
||||
}
|
||||
|
||||
int MinecartHopper::getType() { return TYPE_HOPPER; }
|
||||
|
||||
Tile* MinecartHopper::getDefaultDisplayTile() { return Tile::hopper; }
|
||||
|
||||
int MinecartHopper::getDefaultDisplayOffset() { return 1; }
|
||||
|
||||
unsigned int MinecartHopper::getContainerSize() { return 5; }
|
||||
|
||||
bool MinecartHopper::interact(std::shared_ptr<Player> player) {
|
||||
if (!level->isClientSide) {
|
||||
player->openHopper(
|
||||
std::dynamic_pointer_cast<MinecartHopper>(shared_from_this()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MinecartHopper::activateMinecart(int xt, int yt, int zt, bool state) {
|
||||
bool newEnabled = !state;
|
||||
|
||||
if (newEnabled != isEnabled()) {
|
||||
setEnabled(newEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
bool MinecartHopper::isEnabled() { return enabled; }
|
||||
|
||||
void MinecartHopper::setEnabled(bool enabled) { this->enabled = enabled; }
|
||||
|
||||
Level* MinecartHopper::getLevel() { return level; }
|
||||
|
||||
double MinecartHopper::getLevelX() { return x; }
|
||||
|
||||
double MinecartHopper::getLevelY() { return y; }
|
||||
|
||||
double MinecartHopper::getLevelZ() { return z; }
|
||||
|
||||
void MinecartHopper::tick() {
|
||||
MinecartContainer::tick();
|
||||
|
||||
if (!level->isClientSide && isAlive() && isEnabled()) {
|
||||
cooldownTime--;
|
||||
if (!isOnCooldown()) {
|
||||
setCooldown(0);
|
||||
|
||||
if (suckInItems()) {
|
||||
setCooldown(MOVE_ITEM_SPEED);
|
||||
MinecartContainer::setChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MinecartHopper::suckInItems() {
|
||||
if (HopperTileEntity::suckInItems(this)) return true;
|
||||
|
||||
std::vector<std::shared_ptr<Entity> >* items =
|
||||
level->getEntitiesOfClass(typeid(ItemEntity), bb->grow(0.25f, 0, 0.25f),
|
||||
EntitySelector::ENTITY_STILL_ALIVE);
|
||||
|
||||
if (items->size() > 0) {
|
||||
HopperTileEntity::addItem(
|
||||
this, std::dynamic_pointer_cast<ItemEntity>(items->at(0)));
|
||||
}
|
||||
delete items;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MinecartHopper::destroy(DamageSource* source) {
|
||||
MinecartContainer::destroy(source);
|
||||
|
||||
spawnAtLocation(Tile::hopper_Id, 1, 0);
|
||||
}
|
||||
|
||||
void MinecartHopper::addAdditonalSaveData(CompoundTag* base) {
|
||||
MinecartContainer::addAdditonalSaveData(base);
|
||||
base->putInt(L"TransferCooldown", cooldownTime);
|
||||
}
|
||||
|
||||
void MinecartHopper::readAdditionalSaveData(CompoundTag* base) {
|
||||
MinecartContainer::readAdditionalSaveData(base);
|
||||
cooldownTime = base->getInt(L"TransferCooldown");
|
||||
}
|
||||
|
||||
void MinecartHopper::setCooldown(int time) { cooldownTime = time; }
|
||||
|
||||
bool MinecartHopper::isOnCooldown() { return cooldownTime > 0; }
|
||||
81
Minecraft.World/Entities/MinecartHopper.h
Normal file
81
Minecraft.World/Entities/MinecartHopper.h
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
#pragma once
|
||||
|
||||
#include "MinecartContainer.h"
|
||||
#include "../Blocks/TileEntities/Hopper.h"
|
||||
|
||||
class MinecartHopper : public MinecartContainer, public Hopper {
|
||||
public:
|
||||
eINSTANCEOF GetType() { return eTYPE_MINECART_HOPPER; };
|
||||
static Entity* create(Level* level) { return new MinecartHopper(level); }
|
||||
|
||||
public:
|
||||
static const int MOVE_ITEM_SPEED;
|
||||
|
||||
private:
|
||||
bool enabled;
|
||||
int cooldownTime;
|
||||
|
||||
void _init();
|
||||
|
||||
public:
|
||||
MinecartHopper(Level* level);
|
||||
MinecartHopper(Level* level, double x, double y, double z);
|
||||
|
||||
virtual int getType();
|
||||
virtual Tile* getDefaultDisplayTile();
|
||||
virtual int getDefaultDisplayOffset();
|
||||
virtual unsigned int getContainerSize();
|
||||
virtual bool interact(std::shared_ptr<Player> player);
|
||||
virtual void activateMinecart(int xt, int yt, int zt, bool state);
|
||||
virtual bool isEnabled();
|
||||
virtual void setEnabled(bool enabled);
|
||||
virtual Level* getLevel();
|
||||
virtual double getLevelX();
|
||||
virtual double getLevelY();
|
||||
virtual double getLevelZ();
|
||||
virtual void tick();
|
||||
virtual bool suckInItems();
|
||||
virtual void destroy(DamageSource* source);
|
||||
|
||||
protected:
|
||||
virtual void addAdditonalSaveData(CompoundTag* base);
|
||||
virtual void readAdditionalSaveData(CompoundTag* base);
|
||||
|
||||
public:
|
||||
void setCooldown(int time);
|
||||
bool isOnCooldown();
|
||||
|
||||
// 4J For Hopper
|
||||
virtual std::shared_ptr<ItemInstance> getItem(unsigned int slot) {
|
||||
return MinecartContainer::getItem(slot);
|
||||
}
|
||||
virtual std::shared_ptr<ItemInstance> removeItem(unsigned int slot,
|
||||
int count) {
|
||||
return MinecartContainer::removeItem(slot, count);
|
||||
}
|
||||
virtual std::shared_ptr<ItemInstance> removeItemNoUpdate(int slot) {
|
||||
return MinecartContainer::removeItemNoUpdate(slot);
|
||||
}
|
||||
virtual void setItem(unsigned int slot,
|
||||
std::shared_ptr<ItemInstance> item) {
|
||||
MinecartContainer::setItem(slot, item);
|
||||
}
|
||||
virtual std::wstring getName() { return MinecartContainer::getName(); }
|
||||
virtual std::wstring getCustomName() {
|
||||
return MinecartContainer::getCustomName();
|
||||
}
|
||||
virtual bool hasCustomName() { return MinecartContainer::hasCustomName(); }
|
||||
virtual int getMaxStackSize() {
|
||||
return MinecartContainer::getMaxStackSize();
|
||||
}
|
||||
|
||||
virtual void setChanged() { MinecartContainer::setChanged(); }
|
||||
virtual bool stillValid(std::shared_ptr<Player> player) {
|
||||
return MinecartContainer::stillValid(player);
|
||||
}
|
||||
virtual void startOpen() { MinecartContainer::startOpen(); }
|
||||
virtual void stopOpen() { MinecartContainer::stopOpen(); }
|
||||
virtual bool canPlaceItem(int slot, std::shared_ptr<ItemInstance> item) {
|
||||
return MinecartContainer::canPlaceItem(slot, item);
|
||||
}
|
||||
};
|
||||
32
Minecraft.World/Entities/MinecartRideable.cpp
Normal file
32
Minecraft.World/Entities/MinecartRideable.cpp
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
#include "../Platform/stdafx.h"
|
||||
#include "../Headers/net.minecraft.world.entity.h"
|
||||
#include "../Headers/net.minecraft.world.entity.player.h"
|
||||
#include "../Headers/net.minecraft.world.level.h"
|
||||
#include "MinecartRideable.h"
|
||||
|
||||
MinecartRideable::MinecartRideable(Level* level) : Minecart(level) {
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
}
|
||||
|
||||
MinecartRideable::MinecartRideable(Level* level, double x, double y, double z)
|
||||
: Minecart(level, x, y, z) {
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
}
|
||||
|
||||
bool MinecartRideable::interact(std::shared_ptr<Player> player) {
|
||||
if (rider.lock() != NULL && rider.lock()->instanceof(eTYPE_PLAYER) &&
|
||||
rider.lock() != player)
|
||||
return true;
|
||||
if (rider.lock() != NULL && rider.lock() != player) return false;
|
||||
if (!level->isClientSide) {
|
||||
player->ride(shared_from_this());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int MinecartRideable::getType() { return TYPE_RIDEABLE; }
|
||||
16
Minecraft.World/Entities/MinecartRideable.h
Normal file
16
Minecraft.World/Entities/MinecartRideable.h
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include "Mobs/Minecart.h"
|
||||
|
||||
class MinecartRideable : public Minecart {
|
||||
public:
|
||||
eINSTANCEOF GetType() { return eTYPE_MINECART_RIDEABLE; };
|
||||
static Entity* create(Level* level) { return new MinecartRideable(level); }
|
||||
|
||||
public:
|
||||
MinecartRideable(Level* level);
|
||||
MinecartRideable(Level* level, double x, double y, double z);
|
||||
|
||||
virtual bool interact(std::shared_ptr<Player> player);
|
||||
virtual int getType();
|
||||
};
|
||||
74
Minecraft.World/Entities/MinecartSpawner.cpp
Normal file
74
Minecraft.World/Entities/MinecartSpawner.cpp
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#include "../Platform/stdafx.h"
|
||||
#include "../Headers/net.minecraft.world.level.h"
|
||||
#include "../Headers/net.minecraft.world.level.tile.h"
|
||||
#include "MinecartSpawner.h"
|
||||
|
||||
MinecartSpawner::MinecartMobSpawner::MinecartMobSpawner(
|
||||
MinecartSpawner* parent) {
|
||||
m_parent = parent;
|
||||
}
|
||||
|
||||
void MinecartSpawner::MinecartMobSpawner::broadcastEvent(int id) {
|
||||
m_parent->level->broadcastEntityEvent(m_parent->shared_from_this(),
|
||||
(uint8_t)id);
|
||||
}
|
||||
|
||||
Level* MinecartSpawner::MinecartMobSpawner::getLevel() {
|
||||
return m_parent->level;
|
||||
}
|
||||
|
||||
int MinecartSpawner::MinecartMobSpawner::getX() {
|
||||
return Mth::floor(m_parent->x);
|
||||
}
|
||||
|
||||
int MinecartSpawner::MinecartMobSpawner::getY() {
|
||||
return Mth::floor(m_parent->y);
|
||||
}
|
||||
|
||||
int MinecartSpawner::MinecartMobSpawner::getZ() {
|
||||
return Mth::floor(m_parent->z);
|
||||
}
|
||||
|
||||
MinecartSpawner::MinecartSpawner(Level* level) : Minecart(level) {
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
|
||||
spawner = new MinecartMobSpawner(this);
|
||||
}
|
||||
|
||||
MinecartSpawner::MinecartSpawner(Level* level, double x, double y, double z)
|
||||
: Minecart(level, x, y, z) {
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
|
||||
spawner = new MinecartMobSpawner(this);
|
||||
}
|
||||
|
||||
MinecartSpawner::~MinecartSpawner() { delete spawner; }
|
||||
|
||||
int MinecartSpawner::getType() { return TYPE_SPAWNER; }
|
||||
|
||||
Tile* MinecartSpawner::getDefaultDisplayTile() { return Tile::mobSpawner; }
|
||||
|
||||
void MinecartSpawner::readAdditionalSaveData(CompoundTag* tag) {
|
||||
Minecart::readAdditionalSaveData(tag);
|
||||
spawner->load(tag);
|
||||
}
|
||||
|
||||
void MinecartSpawner::addAdditonalSaveData(CompoundTag* tag) {
|
||||
Minecart::addAdditonalSaveData(tag);
|
||||
spawner->save(tag);
|
||||
}
|
||||
|
||||
void MinecartSpawner::handleEntityEvent(uint8_t eventId) {
|
||||
spawner->onEventTriggered(eventId);
|
||||
}
|
||||
|
||||
void MinecartSpawner::tick() {
|
||||
Minecart::tick();
|
||||
spawner->tick();
|
||||
}
|
||||
|
||||
BaseMobSpawner* MinecartSpawner::getSpawner() { return spawner; }
|
||||
43
Minecraft.World/Entities/MinecartSpawner.h
Normal file
43
Minecraft.World/Entities/MinecartSpawner.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#pragma once
|
||||
|
||||
#include "Mobs/Minecart.h"
|
||||
#include "../Level/BaseMobSpawner.h"
|
||||
|
||||
class MinecartSpawner : public Minecart {
|
||||
public:
|
||||
eINSTANCEOF GetType() { return eTYPE_MINECART_SPAWNER; };
|
||||
static Entity* create(Level* level) { return new MinecartSpawner(level); }
|
||||
|
||||
private:
|
||||
BaseMobSpawner* spawner;
|
||||
|
||||
class MinecartMobSpawner : public BaseMobSpawner {
|
||||
private:
|
||||
MinecartSpawner* m_parent;
|
||||
|
||||
public:
|
||||
MinecartMobSpawner(MinecartSpawner* parent);
|
||||
void broadcastEvent(int id);
|
||||
Level* getLevel();
|
||||
int getX();
|
||||
int getY();
|
||||
int getZ();
|
||||
};
|
||||
|
||||
public:
|
||||
MinecartSpawner(Level* level);
|
||||
MinecartSpawner(Level* level, double x, double y, double z);
|
||||
virtual ~MinecartSpawner();
|
||||
|
||||
virtual int getType();
|
||||
virtual Tile* getDefaultDisplayTile();
|
||||
|
||||
protected:
|
||||
virtual void readAdditionalSaveData(CompoundTag* tag);
|
||||
virtual void addAdditonalSaveData(CompoundTag* tag);
|
||||
|
||||
public:
|
||||
virtual void handleEntityEvent(uint8_t eventId);
|
||||
virtual void tick();
|
||||
virtual BaseMobSpawner* getSpawner();
|
||||
};
|
||||
136
Minecraft.World/Entities/MinecartTNT.cpp
Normal file
136
Minecraft.World/Entities/MinecartTNT.cpp
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
#include "../Platform/stdafx.h"
|
||||
#include "../Headers/net.minecraft.world.damagesource.h"
|
||||
#include "../Headers/net.minecraft.world.level.h"
|
||||
#include "../Headers/net.minecraft.world.level.tile.h"
|
||||
#include "MinecartTNT.h"
|
||||
|
||||
void MinecartTNT::_init() {
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
|
||||
fuse = -1;
|
||||
}
|
||||
|
||||
MinecartTNT::MinecartTNT(Level* level) : Minecart(level) { _init(); }
|
||||
|
||||
MinecartTNT::MinecartTNT(Level* level, double x, double y, double z)
|
||||
: Minecart(level, x, y, z) {
|
||||
_init();
|
||||
}
|
||||
|
||||
int MinecartTNT::getType() { return TYPE_TNT; }
|
||||
|
||||
Tile* MinecartTNT::getDefaultDisplayTile() { return Tile::tnt; }
|
||||
|
||||
void MinecartTNT::tick() {
|
||||
Minecart::tick();
|
||||
|
||||
if (fuse > 0) {
|
||||
fuse--;
|
||||
level->addParticle(eParticleType_smoke, x, y + 0.5f, z, 0, 0, 0);
|
||||
} else if (fuse == 0) {
|
||||
explode(xd * xd + zd * zd);
|
||||
}
|
||||
|
||||
if (horizontalCollision) {
|
||||
double speedSqr = xd * xd + zd * zd;
|
||||
|
||||
if (speedSqr >= 0.01f) {
|
||||
explode(speedSqr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MinecartTNT::destroy(DamageSource* source) {
|
||||
Minecart::destroy(source);
|
||||
|
||||
double speedSqr = xd * xd + zd * zd;
|
||||
|
||||
if (!source->isExplosion()) {
|
||||
spawnAtLocation(
|
||||
std::shared_ptr<ItemInstance>(new ItemInstance(Tile::tnt, 1)), 0);
|
||||
}
|
||||
|
||||
if (source->isFire() || source->isExplosion() || speedSqr >= 0.01f) {
|
||||
explode(speedSqr);
|
||||
}
|
||||
}
|
||||
|
||||
void MinecartTNT::explode(double speedSqr) {
|
||||
if (!level->isClientSide) {
|
||||
double speed = sqrt(speedSqr);
|
||||
if (speed > 5) speed = 5;
|
||||
level->explode(shared_from_this(), x, y, z,
|
||||
(float)(4 + random->nextDouble() * 1.5f * speed), true);
|
||||
remove();
|
||||
}
|
||||
}
|
||||
|
||||
void MinecartTNT::causeFallDamage(float distance) {
|
||||
if (distance >= 3) {
|
||||
float power = distance / 10;
|
||||
explode(power * power);
|
||||
}
|
||||
|
||||
Minecart::causeFallDamage(distance);
|
||||
}
|
||||
|
||||
void MinecartTNT::activateMinecart(int xt, int yt, int zt, bool state) {
|
||||
if (state && fuse < 0) {
|
||||
primeFuse();
|
||||
}
|
||||
}
|
||||
|
||||
void MinecartTNT::handleEntityEvent(uint8_t eventId) {
|
||||
if (eventId == EVENT_PRIME) {
|
||||
primeFuse();
|
||||
} else {
|
||||
Minecart::handleEntityEvent(eventId);
|
||||
}
|
||||
}
|
||||
|
||||
void MinecartTNT::primeFuse() {
|
||||
fuse = 80;
|
||||
|
||||
if (!level->isClientSide) {
|
||||
level->broadcastEntityEvent(shared_from_this(), EVENT_PRIME);
|
||||
level->playEntitySound(shared_from_this(), eSoundType_RANDOM_FUSE, 1,
|
||||
1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
int MinecartTNT::getFuse() { return fuse; }
|
||||
|
||||
bool MinecartTNT::isPrimed() { return fuse > -1; }
|
||||
|
||||
float MinecartTNT::getTileExplosionResistance(Explosion* explosion,
|
||||
Level* level, int x, int y, int z,
|
||||
Tile* tile) {
|
||||
if (isPrimed() && (BaseRailTile::isRail(tile->id) ||
|
||||
BaseRailTile::isRail(level, x, y + 1, z))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return Minecart::getTileExplosionResistance(explosion, level, x, y, z,
|
||||
tile);
|
||||
}
|
||||
|
||||
bool MinecartTNT::shouldTileExplode(Explosion* explosion, Level* level, int x,
|
||||
int y, int z, int id, float power) {
|
||||
if (isPrimed() &&
|
||||
(BaseRailTile::isRail(id) || BaseRailTile::isRail(level, x, y + 1, z)))
|
||||
return false;
|
||||
|
||||
return Minecart::shouldTileExplode(explosion, level, x, y, z, id, power);
|
||||
}
|
||||
|
||||
void MinecartTNT::readAdditionalSaveData(CompoundTag* tag) {
|
||||
Minecart::readAdditionalSaveData(tag);
|
||||
if (tag->contains(L"TNTFuse")) fuse = tag->getInt(L"TNTFuse");
|
||||
}
|
||||
|
||||
void MinecartTNT::addAdditonalSaveData(CompoundTag* tag) {
|
||||
Minecart::addAdditonalSaveData(tag);
|
||||
tag->putInt(L"TNTFuse", fuse);
|
||||
}
|
||||
44
Minecraft.World/Entities/MinecartTNT.h
Normal file
44
Minecraft.World/Entities/MinecartTNT.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
#pragma once
|
||||
|
||||
#include "Mobs/Minecart.h"
|
||||
|
||||
class MinecartTNT : public Minecart {
|
||||
public:
|
||||
eINSTANCEOF GetType() { return eTYPE_MINECART_TNT; };
|
||||
static Entity* create(Level* level) { return new MinecartTNT(level); }
|
||||
|
||||
private:
|
||||
static const uint8_t EVENT_PRIME = 10;
|
||||
|
||||
int fuse;
|
||||
|
||||
void _init();
|
||||
|
||||
public:
|
||||
MinecartTNT(Level* level);
|
||||
MinecartTNT(Level* level, double x, double y, double z);
|
||||
|
||||
virtual int getType();
|
||||
virtual Tile* getDefaultDisplayTile();
|
||||
virtual void tick();
|
||||
virtual void destroy(DamageSource* source);
|
||||
|
||||
protected:
|
||||
virtual void explode(double speedSqr);
|
||||
virtual void causeFallDamage(float distance);
|
||||
|
||||
public:
|
||||
virtual void activateMinecart(int xt, int yt, int zt, bool state);
|
||||
virtual void handleEntityEvent(uint8_t eventId);
|
||||
virtual void primeFuse();
|
||||
virtual int getFuse();
|
||||
virtual bool isPrimed();
|
||||
virtual float getTileExplosionResistance(Explosion* explosion, Level* level,
|
||||
int x, int y, int z, Tile* tile);
|
||||
virtual bool shouldTileExplode(Explosion* explosion, Level* level, int x,
|
||||
int y, int z, int id, float power);
|
||||
|
||||
protected:
|
||||
virtual void readAdditionalSaveData(CompoundTag* tag);
|
||||
virtual void addAdditonalSaveData(CompoundTag* tag);
|
||||
};
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "Entity.h"
|
||||
#include "LivingEntity.h"
|
||||
#include "MobType.h"
|
||||
#include "../AI/Goals/GoalSelector.h"
|
||||
|
||||
|
|
@ -18,106 +18,33 @@ class PathNavigation;
|
|||
class Sensing;
|
||||
class Icon;
|
||||
class Pos;
|
||||
class MobGroupData;
|
||||
|
||||
class Mob : public Entity {
|
||||
class Mob : public LivingEntity {
|
||||
friend class MobSpawner;
|
||||
|
||||
protected:
|
||||
// 4J - added for common ctor code
|
||||
void _init();
|
||||
|
||||
public:
|
||||
Mob(Level* level);
|
||||
virtual ~Mob();
|
||||
|
||||
// 4J-PB - added to replace (e instanceof Type), avoiding dynamic casts
|
||||
eINSTANCEOF GetType() { return eTYPE_MOB; }
|
||||
static Entity* create(Level* level) { return NULL; }
|
||||
|
||||
public:
|
||||
static const int ATTACK_DURATION = 5;
|
||||
static const int PLAYER_HURT_EXPERIENCE_TIME = 20 * 3;
|
||||
|
||||
public: // 4J Stu - Made public
|
||||
static const int DATA_EFFECT_COLOR_ID = 8;
|
||||
static const float MAX_WEARING_ARMOR_CHANCE;
|
||||
static const float MAX_PICKUP_LOOT_CHANCE;
|
||||
static const float MAX_ENCHANTED_ARMOR_CHANCE;
|
||||
static const float MAX_ENCHANTED_WEAPON_CHANCE;
|
||||
|
||||
private:
|
||||
static const double MIN_MOVEMENT_DISTANCE;
|
||||
|
||||
public:
|
||||
int invulnerableDuration;
|
||||
float timeOffs;
|
||||
float rotA;
|
||||
float yBodyRot, yBodyRotO;
|
||||
float yHeadRot, yHeadRotO;
|
||||
|
||||
protected:
|
||||
float oRun, run;
|
||||
float animStep, animStepO;
|
||||
bool hasHair;
|
||||
// std::wstring textureName;
|
||||
int textureIdx; // 4J changed from std::wstring textureName
|
||||
bool allowAlpha;
|
||||
float rotOffs;
|
||||
std::wstring modelName;
|
||||
float bobStrength;
|
||||
int deathScore;
|
||||
float renderOffset;
|
||||
|
||||
public:
|
||||
float walkingSpeed;
|
||||
float flyingSpeed;
|
||||
float oAttackAnim, attackAnim;
|
||||
|
||||
protected:
|
||||
int health;
|
||||
|
||||
public:
|
||||
int lastHealth;
|
||||
|
||||
protected:
|
||||
int dmgSpill;
|
||||
static const int DATA_CUSTOM_NAME = 10;
|
||||
static const int DATA_CUSTOM_NAME_VISIBLE = 11;
|
||||
|
||||
public:
|
||||
int ambientSoundTime;
|
||||
int hurtTime;
|
||||
int hurtDuration;
|
||||
float hurtDir;
|
||||
int deathTime;
|
||||
int attackTime;
|
||||
float oTilt, tilt;
|
||||
|
||||
protected:
|
||||
bool dead;
|
||||
int xpReward;
|
||||
|
||||
public:
|
||||
int modelNum;
|
||||
float animSpeed;
|
||||
float walkAnimSpeedO;
|
||||
float walkAnimSpeed;
|
||||
float walkAnimPos;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<Player> lastHurtByPlayer;
|
||||
int lastHurtByPlayerTime;
|
||||
|
||||
private:
|
||||
std::shared_ptr<Mob> lastHurtByMob;
|
||||
int lastHurtByMobTime;
|
||||
std::shared_ptr<Mob> lastHurtMob;
|
||||
|
||||
public:
|
||||
int arrowCount;
|
||||
int removeArrowTime;
|
||||
|
||||
protected:
|
||||
std::map<int, MobEffectInstance*> activeEffects;
|
||||
|
||||
private:
|
||||
bool effectsDirty;
|
||||
int effectColor;
|
||||
|
||||
LookControl* lookControl;
|
||||
MoveControl* moveControl;
|
||||
JumpControl* jumpControl;
|
||||
|
|
@ -129,12 +56,28 @@ protected:
|
|||
GoalSelector targetSelector;
|
||||
|
||||
private:
|
||||
std::shared_ptr<Mob> target;
|
||||
std::shared_ptr<LivingEntity> target;
|
||||
Sensing* sensing;
|
||||
float speed;
|
||||
|
||||
Pos* restrictCenter;
|
||||
float restrictRadius;
|
||||
ItemInstanceArray equipment;
|
||||
|
||||
protected:
|
||||
floatArray dropChances;
|
||||
|
||||
private:
|
||||
bool _canPickUpLoot;
|
||||
bool persistenceRequired;
|
||||
|
||||
protected:
|
||||
// 4J - added for common ctor code
|
||||
void _init();
|
||||
|
||||
public:
|
||||
Mob(Level* level);
|
||||
virtual ~Mob();
|
||||
|
||||
protected:
|
||||
void registerAttributes();
|
||||
|
||||
public:
|
||||
virtual LookControl* getLookControl();
|
||||
|
|
@ -142,152 +85,46 @@ public:
|
|||
virtual JumpControl* getJumpControl();
|
||||
virtual PathNavigation* getNavigation();
|
||||
virtual Sensing* getSensing();
|
||||
virtual Random* getRandom();
|
||||
virtual std::shared_ptr<Mob> getLastHurtByMob();
|
||||
virtual std::shared_ptr<Mob> getLastHurtMob();
|
||||
void setLastHurtMob(std::shared_ptr<Entity> target);
|
||||
virtual int getNoActionTime();
|
||||
float getYHeadRot();
|
||||
void setYHeadRot(float yHeadRot);
|
||||
float getSpeed();
|
||||
void setSpeed(float speed);
|
||||
virtual bool doHurtTarget(std::shared_ptr<Entity> target);
|
||||
std::shared_ptr<Mob> getTarget();
|
||||
virtual void setTarget(std::shared_ptr<Mob> target);
|
||||
std::shared_ptr<LivingEntity> getTarget();
|
||||
virtual void setTarget(std::shared_ptr<LivingEntity> target);
|
||||
virtual bool canAttackType(eINSTANCEOF targetType);
|
||||
virtual void ate();
|
||||
|
||||
bool isWithinRestriction();
|
||||
bool isWithinRestriction(int x, int y, int z);
|
||||
void restrictTo(int x, int y, int z, int radius);
|
||||
Pos* getRestrictCenter();
|
||||
float getRestrictRadius();
|
||||
void clearRestriction();
|
||||
bool hasRestriction();
|
||||
|
||||
virtual void setLastHurtByMob(std::shared_ptr<Mob> hurtBy);
|
||||
|
||||
protected:
|
||||
virtual void defineSynchedData();
|
||||
|
||||
public:
|
||||
bool canSee(std::shared_ptr<Entity> target);
|
||||
virtual int getTexture(); // 4J - changed from std::wstring to int
|
||||
virtual bool isPickable();
|
||||
virtual bool isPushable();
|
||||
virtual float getHeadHeight();
|
||||
virtual int getAmbientSoundInterval();
|
||||
void playAmbientSound();
|
||||
virtual void baseTick();
|
||||
|
||||
protected:
|
||||
virtual void tickDeath();
|
||||
virtual int decreaseAirSupply(int currentSupply);
|
||||
virtual int getExperienceReward(std::shared_ptr<Player> killedBy);
|
||||
virtual bool isAlwaysExperienceDropper();
|
||||
|
||||
public:
|
||||
void spawnAnim();
|
||||
virtual void rideTick();
|
||||
|
||||
protected:
|
||||
int lSteps;
|
||||
double lx, ly, lz, lyr, lxr;
|
||||
|
||||
public:
|
||||
virtual void lerpTo(double x, double y, double z, float yRot, float xRot,
|
||||
int steps);
|
||||
|
||||
private:
|
||||
float fallTime;
|
||||
|
||||
public:
|
||||
void superTick();
|
||||
virtual void spawnAnim();
|
||||
virtual void tick();
|
||||
virtual void heal(int heal);
|
||||
virtual int getMaxHealth() = 0;
|
||||
virtual int getHealth();
|
||||
virtual void setHealth(int health);
|
||||
|
||||
protected:
|
||||
int lastHurt;
|
||||
|
||||
public:
|
||||
virtual bool hurt(DamageSource* source, int dmg);
|
||||
|
||||
protected:
|
||||
float getVoicePitch();
|
||||
|
||||
public:
|
||||
virtual void animateHurt();
|
||||
|
||||
/**
|
||||
* Fetches the mob's armor value, from 0 (no armor) to 20 (full armor)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
virtual int getArmorValue();
|
||||
|
||||
protected:
|
||||
virtual void hurtArmor(int damage);
|
||||
virtual int getDamageAfterArmorAbsorb(DamageSource* damageSource,
|
||||
int damage);
|
||||
virtual int getDamageAfterMagicAbsorb(DamageSource* damageSource,
|
||||
int damage);
|
||||
|
||||
virtual void actuallyHurt(DamageSource* source, int dmg);
|
||||
virtual float getSoundVolume();
|
||||
virtual float tickHeadTurn(float yBodyRotT, float walkSpeed);
|
||||
virtual int getAmbientSound();
|
||||
virtual int getHurtSound();
|
||||
virtual int getDeathSound();
|
||||
|
||||
public:
|
||||
void knockback(std::shared_ptr<Entity> source, int dmg, double xd,
|
||||
double zd);
|
||||
virtual void die(DamageSource* source);
|
||||
|
||||
protected:
|
||||
virtual void dropRareDeathLoot(int rareLootLevel);
|
||||
virtual void dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel);
|
||||
virtual int getDeathLoot();
|
||||
virtual void causeFallDamage(float distance);
|
||||
virtual void dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel);
|
||||
|
||||
public:
|
||||
virtual void travel(float xa, float ya);
|
||||
virtual bool onLadder();
|
||||
virtual bool isShootable();
|
||||
virtual void addAdditonalSaveData(CompoundTag* entityTag);
|
||||
virtual void readAdditionalSaveData(CompoundTag* tag);
|
||||
virtual bool isAlive();
|
||||
virtual bool isWaterMob();
|
||||
virtual int getLightColor(float a); // 4J - added
|
||||
|
||||
protected:
|
||||
int noActionTime;
|
||||
float xxa, yya, yRotA;
|
||||
bool jumping;
|
||||
float defaultLookAngle;
|
||||
float runSpeed;
|
||||
|
||||
protected:
|
||||
int noJumpDelay;
|
||||
|
||||
public:
|
||||
virtual void setYya(float yya);
|
||||
virtual void setJumping(bool jump);
|
||||
|
||||
virtual void setSpeed(float speed);
|
||||
virtual void aiStep();
|
||||
|
||||
protected:
|
||||
virtual bool useNewAi();
|
||||
virtual bool isEffectiveAI();
|
||||
virtual bool isImmobile();
|
||||
|
||||
public:
|
||||
virtual bool isBlocking();
|
||||
|
||||
protected:
|
||||
virtual void jumpFromGround();
|
||||
virtual bool removeWhenFarAway();
|
||||
|
||||
private:
|
||||
|
|
@ -298,7 +135,6 @@ protected:
|
|||
|
||||
virtual void checkDespawn();
|
||||
virtual void newServerAiStep();
|
||||
virtual void serverAiMobStep();
|
||||
virtual void serverAiStep();
|
||||
|
||||
public:
|
||||
|
|
@ -314,62 +150,80 @@ private:
|
|||
|
||||
public:
|
||||
virtual bool canSpawn();
|
||||
|
||||
protected:
|
||||
virtual void outOfWorld();
|
||||
|
||||
public:
|
||||
float getAttackAnim(float a);
|
||||
virtual Vec3* getPos(float a);
|
||||
virtual Vec3* getLookAngle();
|
||||
Vec3* getViewVector(float a);
|
||||
virtual float getSizeScale();
|
||||
virtual float getHeadSizeScale();
|
||||
HitResult* pick(double range, float a);
|
||||
virtual int getMaxSpawnClusterSize();
|
||||
virtual int getMaxFallDistance();
|
||||
virtual std::shared_ptr<ItemInstance> getCarriedItem();
|
||||
virtual std::shared_ptr<ItemInstance> getCarried(int slot);
|
||||
virtual std::shared_ptr<ItemInstance> getArmor(int pos);
|
||||
virtual void handleEntityEvent(uint8_t id);
|
||||
virtual bool isSleeping();
|
||||
virtual Icon* getItemInHandIcon(std::shared_ptr<ItemInstance> item,
|
||||
int layer);
|
||||
virtual void setEquippedSlot(int slot, std::shared_ptr<ItemInstance> item);
|
||||
virtual ItemInstanceArray getEquipmentSlots();
|
||||
|
||||
protected:
|
||||
virtual void dropEquipment(bool byPlayer, int playerBonusLevel);
|
||||
virtual void populateDefaultEquipmentSlots();
|
||||
|
||||
public:
|
||||
static int getEquipmentSlotForItem(std::shared_ptr<ItemInstance> item);
|
||||
static Item* getEquipmentForSlot(int slot, int type);
|
||||
|
||||
protected:
|
||||
virtual void populateDefaultEquipmentEnchantments();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Added this method so mobs can handle their own spawn settings instead of
|
||||
* hacking MobSpawner.java
|
||||
*
|
||||
* @param groupData
|
||||
* TODO
|
||||
* @return TODO
|
||||
*/
|
||||
virtual MobGroupData* finalizeMobSpawn(
|
||||
MobGroupData* groupData,
|
||||
int extraData = 0); // 4J Added extraData param
|
||||
virtual void finalizeSpawnEggSpawn(int extraData); // 4J Added
|
||||
virtual bool canBeControlledByRider();
|
||||
virtual std::wstring getAName();
|
||||
virtual void setPersistenceRequired();
|
||||
virtual void setCustomName(const std::wstring& name);
|
||||
virtual std::wstring getCustomName();
|
||||
virtual bool hasCustomName();
|
||||
virtual void setCustomNameVisible(bool visible);
|
||||
virtual bool isCustomNameVisible();
|
||||
virtual bool shouldShowName();
|
||||
virtual void setDropChance(int slot, float pct);
|
||||
virtual bool canPickUpLoot();
|
||||
virtual void setCanPickUpLoot(bool canPickUpLoot);
|
||||
virtual bool isPersistenceRequired();
|
||||
virtual bool interact(std::shared_ptr<Player> player);
|
||||
|
||||
protected:
|
||||
virtual bool mobInteract(std::shared_ptr<Player> player);
|
||||
|
||||
// roper / leash methods
|
||||
|
||||
private:
|
||||
bool _isLeashed;
|
||||
std::shared_ptr<Entity> leashHolder;
|
||||
CompoundTag* leashInfoTag;
|
||||
|
||||
protected:
|
||||
virtual void tickLeash();
|
||||
|
||||
public:
|
||||
virtual void dropLeash(bool synch, bool createItemDrop);
|
||||
virtual bool canBeLeashed();
|
||||
virtual bool isLeashed();
|
||||
virtual std::shared_ptr<Entity> getLeashHolder();
|
||||
virtual void setLeashedTo(std::shared_ptr<Entity> holder, bool synch);
|
||||
|
||||
private:
|
||||
virtual void restoreLeashFromSave();
|
||||
virtual bool shouldRender(Vec3* c);
|
||||
|
||||
protected:
|
||||
void tickEffects();
|
||||
|
||||
public:
|
||||
void removeAllEffects();
|
||||
std::vector<MobEffectInstance*>* getActiveEffects();
|
||||
bool hasEffect(int id);
|
||||
bool hasEffect(MobEffect* effect);
|
||||
MobEffectInstance* getEffect(MobEffect* effect);
|
||||
void addEffect(MobEffectInstance* newEffect);
|
||||
void addEffectNoUpdate(MobEffectInstance* newEffect); // 4J Added
|
||||
virtual bool canBeAffected(MobEffectInstance* newEffect);
|
||||
virtual bool isInvertedHealAndHarm();
|
||||
void removeEffectNoUpdate(int effectId);
|
||||
void removeEffect(int effectId);
|
||||
|
||||
protected:
|
||||
virtual void onEffectAdded(MobEffectInstance* effect);
|
||||
virtual void onEffectUpdated(MobEffectInstance* effect);
|
||||
virtual void onEffectRemoved(MobEffectInstance* effect);
|
||||
|
||||
public:
|
||||
virtual float getWalkingSpeedModifier();
|
||||
|
||||
// 4J-Pb added (from 1.2.3)
|
||||
virtual void teleportTo(double x, double y, double z);
|
||||
virtual bool isBaby();
|
||||
virtual MobType getMobType();
|
||||
virtual void breakItem(std::shared_ptr<ItemInstance> itemInstance);
|
||||
|
||||
virtual bool isInvulnerable();
|
||||
|
||||
virtual void finalizeMobSpawn();
|
||||
virtual bool canBeControlledByRider();
|
||||
|
||||
// 4J Added override to update ai elements when loading entity from
|
||||
// schematics
|
||||
virtual void setLevel(Level* level);
|
||||
|
|
|
|||
|
|
@ -7,47 +7,54 @@
|
|||
|
||||
MobCategory* MobCategory::monster = NULL;
|
||||
MobCategory* MobCategory::creature = NULL;
|
||||
MobCategory* MobCategory::ambient = NULL;
|
||||
MobCategory* MobCategory::waterCreature = NULL;
|
||||
// 4J - added these extra categories
|
||||
MobCategory* MobCategory::creature_wolf = NULL;
|
||||
MobCategory* MobCategory::creature_chicken = NULL;
|
||||
MobCategory* MobCategory::creature_mushroomcow = NULL;
|
||||
|
||||
MobCategoryArray MobCategory::values = MobCategoryArray(6);
|
||||
MobCategoryArray MobCategory::values = MobCategoryArray(7);
|
||||
|
||||
void MobCategory::staticCtor() {
|
||||
// 4J - adjusted the max levels here for the xbox version, which now
|
||||
// represent the max levels in the whole world
|
||||
monster = new MobCategory(70, Material::air, false, eTYPE_MONSTER, false,
|
||||
CONSOLE_MONSTERS_HARD_LIMIT);
|
||||
creature = new MobCategory(10, Material::air, true,
|
||||
monster = new MobCategory(70, Material::air, false, false, eTYPE_MONSTER,
|
||||
false, CONSOLE_MONSTERS_HARD_LIMIT);
|
||||
creature = new MobCategory(10, Material::air, true, true,
|
||||
eTYPE_ANIMALS_SPAWN_LIMIT_CHECK, false,
|
||||
CONSOLE_ANIMALS_HARD_LIMIT);
|
||||
waterCreature = new MobCategory(5, Material::water, true, eTYPE_WATERANIMAL,
|
||||
false, CONSOLE_SQUID_HARD_LIMIT);
|
||||
ambient = new MobCategory(15, Material::air, true, false, eTYPE_AMBIENT,
|
||||
false, CONSOLE_AMBIENT_HARD_LIMIT),
|
||||
waterCreature =
|
||||
new MobCategory(5, Material::water, true, false, eTYPE_WATERANIMAL,
|
||||
false, CONSOLE_SQUID_HARD_LIMIT);
|
||||
|
||||
values[0] = monster;
|
||||
values[1] = creature;
|
||||
values[2] = waterCreature;
|
||||
values[2] = ambient;
|
||||
values[3] = waterCreature;
|
||||
// 4J - added 2 new categories to give us better control over spawning
|
||||
// wolves & chickens
|
||||
creature_wolf = new MobCategory(3, Material::air, true, eTYPE_WOLF, true,
|
||||
MAX_XBOX_WOLVES);
|
||||
creature_chicken = new MobCategory(2, Material::air, true, eTYPE_CHICKEN,
|
||||
true, MAX_XBOX_CHICKENS);
|
||||
creature_mushroomcow = new MobCategory(
|
||||
2, Material::air, true, eTYPE_MUSHROOMCOW, true, MAX_XBOX_MUSHROOMCOWS);
|
||||
values[3] = creature_wolf;
|
||||
values[4] = creature_chicken;
|
||||
values[5] = creature_mushroomcow;
|
||||
creature_wolf = new MobCategory(3, Material::air, true, true, eTYPE_WOLF,
|
||||
true, MAX_XBOX_WOLVES);
|
||||
creature_chicken = new MobCategory(2, Material::air, true, true,
|
||||
eTYPE_CHICKEN, true, MAX_XBOX_CHICKENS);
|
||||
creature_mushroomcow =
|
||||
new MobCategory(2, Material::air, true, true, eTYPE_MUSHROOMCOW, true,
|
||||
MAX_XBOX_MUSHROOMCOWS);
|
||||
values[4] = creature_wolf;
|
||||
values[5] = creature_chicken;
|
||||
values[6] = creature_mushroomcow;
|
||||
}
|
||||
|
||||
MobCategory::MobCategory(int maxVar, Material* spawnPositionMaterial,
|
||||
bool isFriendly, eINSTANCEOF eBase, bool isSingleType,
|
||||
int maxPerLevel)
|
||||
bool isFriendly, bool isPersistent, eINSTANCEOF eBase,
|
||||
bool isSingleType, int maxPerLevel)
|
||||
: m_max(maxVar),
|
||||
spawnPositionMaterial(spawnPositionMaterial),
|
||||
m_isFriendly(isFriendly),
|
||||
m_isPersistent(isPersistent),
|
||||
m_eBase(eBase),
|
||||
m_isSingleType(isSingleType),
|
||||
m_maxPerLevel(maxPerLevel) {}
|
||||
|
|
@ -69,3 +76,5 @@ Material* MobCategory::getSpawnPositionMaterial() {
|
|||
bool MobCategory::isFriendly() { return m_isFriendly; }
|
||||
|
||||
bool MobCategory::isSingleType() { return m_isSingleType; }
|
||||
|
||||
bool MobCategory::isPersistent() { return m_isPersistent; }
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ public:
|
|||
static const int CONSOLE_ANIMALS_HARD_LIMIT =
|
||||
50; // Max number of animals (cows, sheep, pigs) that the mob spawner
|
||||
// will produce
|
||||
static const int CONSOLE_AMBIENT_HARD_LIMIT = 20; // Ambient mobs
|
||||
|
||||
static const int MAX_XBOX_CHICKENS =
|
||||
8; // Max number of chickens that the mob spawner will produce
|
||||
|
|
@ -26,6 +27,8 @@ public:
|
|||
16; // Max number of iron golems that can be created by placing blocks
|
||||
// - 4J-PB increased limit due to player requests
|
||||
static const int CONSOLE_SQUID_HARD_LIMIT = 5;
|
||||
static const int MAX_CONSOLE_BOSS =
|
||||
1; // Max number of bosses (enderdragon/wither)
|
||||
|
||||
static const int MAX_XBOX_ANIMALS_WITH_BREEDING =
|
||||
CONSOLE_ANIMALS_HARD_LIMIT + 20; // Max number of animals that we can
|
||||
|
|
@ -56,6 +59,8 @@ public:
|
|||
MAX_XBOX_MUSHROOMCOWS_WITH_BREEDING + 8;
|
||||
static const int MAX_XBOX_SQUIDS_WITH_SPAWN_EGG =
|
||||
CONSOLE_SQUID_HARD_LIMIT + 8;
|
||||
static const int MAX_AMBIENT_WITH_SPAWN_EGG =
|
||||
CONSOLE_AMBIENT_HARD_LIMIT + 8;
|
||||
|
||||
/*
|
||||
Maximum animals = 50 + 20 + 20 = 90
|
||||
|
|
@ -74,6 +79,7 @@ public:
|
|||
|
||||
static MobCategory* monster;
|
||||
static MobCategory* creature;
|
||||
static MobCategory* ambient;
|
||||
static MobCategory* waterCreature;
|
||||
// 4J added extra categories, to break these out of general creatures & give
|
||||
// us more control of levels
|
||||
|
|
@ -91,11 +97,13 @@ private:
|
|||
const int m_maxPerLevel;
|
||||
const Material* spawnPositionMaterial;
|
||||
const bool m_isFriendly;
|
||||
const bool m_isPersistent;
|
||||
const bool m_isSingleType; // 4J Added
|
||||
const eINSTANCEOF m_eBase; // 4J added
|
||||
|
||||
MobCategory(int maxVar, Material* spawnPositionMaterial, bool isFriendly,
|
||||
eINSTANCEOF eBase, bool isSingleType, int maxPerLevel);
|
||||
bool isPersistent, eINSTANCEOF eBase, bool isSingleType,
|
||||
int maxPerLevel);
|
||||
|
||||
public:
|
||||
const std::type_info getBaseClass();
|
||||
|
|
@ -105,6 +113,7 @@ public:
|
|||
Material* getSpawnPositionMaterial();
|
||||
bool isFriendly();
|
||||
bool isSingleType();
|
||||
bool isPersistent();
|
||||
|
||||
public:
|
||||
static void staticCtor();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
#include "../Platform/stdafx.h"
|
||||
#include "../Headers/net.minecraft.world.entity.ai.attributes.h"
|
||||
#include "../Headers/net.minecraft.world.entity.player.h"
|
||||
#include "../Headers/net.minecraft.world.entity.monster.h"
|
||||
#include "../Headers/net.minecraft.world.entity.h"
|
||||
#include "../Headers/net.minecraft.world.level.h"
|
||||
#include "../Headers/net.minecraft.world.damagesource.h"
|
||||
#include "../Headers/net.minecraft.world.food.h"
|
||||
#include "../Headers/net.minecraft.world.effect.h"
|
||||
|
|
@ -7,119 +11,195 @@
|
|||
|
||||
MobEffect* MobEffect::effects[NUM_EFFECTS];
|
||||
|
||||
MobEffect* MobEffect::voidEffect = NULL;
|
||||
MobEffect* MobEffect::movementSpeed =
|
||||
(new MobEffect(1, false, eMinecraftColour_Effect_MovementSpeed))
|
||||
->setDescriptionId(IDS_POTION_MOVESPEED)
|
||||
->setPostfixDescriptionId(IDS_POTION_MOVESPEED_POSTFIX)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Speed); // setIcon(0, 0);
|
||||
MobEffect* MobEffect::movementSlowdown =
|
||||
(new MobEffect(2, true, eMinecraftColour_Effect_MovementSlowDown))
|
||||
->setDescriptionId(IDS_POTION_MOVESLOWDOWN)
|
||||
->setPostfixDescriptionId(IDS_POTION_MOVESLOWDOWN_POSTFIX)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Slowness); //->setIcon(1, 0);
|
||||
MobEffect* MobEffect::digSpeed =
|
||||
(new MobEffect(3, false, eMinecraftColour_Effect_DigSpeed))
|
||||
->setDescriptionId(IDS_POTION_DIGSPEED)
|
||||
->setPostfixDescriptionId(IDS_POTION_DIGSPEED_POSTFIX)
|
||||
->setDurationModifier(1.5)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Haste); //->setIcon(2, 0);
|
||||
MobEffect* MobEffect::digSlowdown =
|
||||
(new MobEffect(4, true, eMinecraftColour_Effect_DigSlowdown))
|
||||
->setDescriptionId(IDS_POTION_DIGSLOWDOWN)
|
||||
->setPostfixDescriptionId(IDS_POTION_DIGSLOWDOWN_POSTFIX)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_MiningFatigue); //->setIcon(3, 0);
|
||||
MobEffect* MobEffect::damageBoost =
|
||||
(new MobEffect(5, false, eMinecraftColour_Effect_DamageBoost))
|
||||
->setDescriptionId(IDS_POTION_DAMAGEBOOST)
|
||||
->setPostfixDescriptionId(IDS_POTION_DAMAGEBOOST_POSTFIX)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Strength); //->setIcon(4, 0);
|
||||
MobEffect* MobEffect::heal =
|
||||
(new InstantenousMobEffect(6, false, eMinecraftColour_Effect_Heal))
|
||||
->setDescriptionId(IDS_POTION_HEAL)
|
||||
->setPostfixDescriptionId(IDS_POTION_HEAL_POSTFIX);
|
||||
MobEffect* MobEffect::harm =
|
||||
(new InstantenousMobEffect(7, true, eMinecraftColour_Effect_Harm))
|
||||
->setDescriptionId(IDS_POTION_HARM)
|
||||
->setPostfixDescriptionId(IDS_POTION_HARM_POSTFIX);
|
||||
MobEffect* MobEffect::jump =
|
||||
(new MobEffect(8, false, eMinecraftColour_Effect_Jump))
|
||||
->setDescriptionId(IDS_POTION_JUMP)
|
||||
->setPostfixDescriptionId(IDS_POTION_JUMP_POSTFIX)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_JumpBoost); //->setIcon(2, 1);
|
||||
MobEffect* MobEffect::confusion =
|
||||
(new MobEffect(9, true, eMinecraftColour_Effect_Confusion))
|
||||
->setDescriptionId(IDS_POTION_CONFUSION)
|
||||
->setPostfixDescriptionId(IDS_POTION_CONFUSION_POSTFIX)
|
||||
->setDurationModifier(.25)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Nausea); //->setIcon(3, 1);
|
||||
MobEffect* MobEffect::regeneration =
|
||||
(new MobEffect(10, false, eMinecraftColour_Effect_Regeneration))
|
||||
->setDescriptionId(IDS_POTION_REGENERATION)
|
||||
->setPostfixDescriptionId(IDS_POTION_REGENERATION_POSTFIX)
|
||||
->setDurationModifier(.25)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Regeneration); //->setIcon(7, 0);
|
||||
MobEffect* MobEffect::damageResistance =
|
||||
(new MobEffect(11, false, eMinecraftColour_Effect_DamageResistance))
|
||||
->setDescriptionId(IDS_POTION_RESISTANCE)
|
||||
->setPostfixDescriptionId(IDS_POTION_RESISTANCE_POSTFIX)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Resistance); //->setIcon(6, 1);
|
||||
MobEffect* MobEffect::fireResistance =
|
||||
(new MobEffect(12, false, eMinecraftColour_Effect_FireResistance))
|
||||
->setDescriptionId(IDS_POTION_FIRERESISTANCE)
|
||||
->setPostfixDescriptionId(IDS_POTION_FIRERESISTANCE_POSTFIX)
|
||||
->setIcon(
|
||||
MobEffect::e_MobEffectIcon_FireResistance); //->setIcon(7, 1);
|
||||
MobEffect* MobEffect::waterBreathing =
|
||||
(new MobEffect(13, false, eMinecraftColour_Effect_WaterBreathing))
|
||||
->setDescriptionId(IDS_POTION_WATERBREATHING)
|
||||
->setPostfixDescriptionId(IDS_POTION_WATERBREATHING_POSTFIX)
|
||||
->setIcon(
|
||||
MobEffect::e_MobEffectIcon_WaterBreathing); //->setIcon(0, 2);
|
||||
MobEffect* MobEffect::invisibility =
|
||||
(new MobEffect(14, false, eMinecraftColour_Effect_Invisiblity))
|
||||
->setDescriptionId(IDS_POTION_INVISIBILITY)
|
||||
->setPostfixDescriptionId(IDS_POTION_INVISIBILITY_POSTFIX)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Invisiblity); //->setIcon(0, 1);
|
||||
MobEffect* MobEffect::blindness =
|
||||
(new MobEffect(15, true, eMinecraftColour_Effect_Blindness))
|
||||
->setDescriptionId(IDS_POTION_BLINDNESS)
|
||||
->setPostfixDescriptionId(IDS_POTION_BLINDNESS_POSTFIX)
|
||||
->setDurationModifier(.25)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Blindness); //->setIcon(5, 1);
|
||||
MobEffect* MobEffect::nightVision =
|
||||
(new MobEffect(16, false, eMinecraftColour_Effect_NightVision))
|
||||
->setDescriptionId(IDS_POTION_NIGHTVISION)
|
||||
->setPostfixDescriptionId(IDS_POTION_NIGHTVISION_POSTFIX)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_NightVision); //->setIcon(4, 1);
|
||||
MobEffect* MobEffect::hunger =
|
||||
(new MobEffect(17, true, eMinecraftColour_Effect_Hunger))
|
||||
->setDescriptionId(IDS_POTION_HUNGER)
|
||||
->setPostfixDescriptionId(IDS_POTION_HUNGER_POSTFIX)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Hunger); //->setIcon(1, 1);
|
||||
MobEffect* MobEffect::weakness =
|
||||
(new MobEffect(18, true, eMinecraftColour_Effect_Weakness))
|
||||
->setDescriptionId(IDS_POTION_WEAKNESS)
|
||||
->setPostfixDescriptionId(IDS_POTION_WEAKNESS_POSTFIX)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Weakness); //->setIcon(5, 0);
|
||||
MobEffect* MobEffect::poison =
|
||||
(new MobEffect(19, true, eMinecraftColour_Effect_Poison))
|
||||
->setDescriptionId(IDS_POTION_POISON)
|
||||
->setPostfixDescriptionId(IDS_POTION_POISON_POSTFIX)
|
||||
->setDurationModifier(.25)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Poison); //->setIcon(6, 0);
|
||||
MobEffect* MobEffect::reserved_20 = NULL;
|
||||
MobEffect* MobEffect::reserved_21 = NULL;
|
||||
MobEffect* MobEffect::reserved_22 = NULL;
|
||||
MobEffect* MobEffect::reserved_23 = NULL;
|
||||
MobEffect* MobEffect::reserved_24 = NULL;
|
||||
MobEffect* MobEffect::reserved_25 = NULL;
|
||||
MobEffect* MobEffect::reserved_26 = NULL;
|
||||
MobEffect* MobEffect::reserved_27 = NULL;
|
||||
MobEffect* MobEffect::reserved_28 = NULL;
|
||||
MobEffect* MobEffect::reserved_29 = NULL;
|
||||
MobEffect* MobEffect::reserved_30 = NULL;
|
||||
MobEffect* MobEffect::reserved_31 = NULL;
|
||||
MobEffect* MobEffect::voidEffect;
|
||||
MobEffect* MobEffect::movementSpeed;
|
||||
MobEffect* MobEffect::movementSlowdown;
|
||||
MobEffect* MobEffect::digSpeed;
|
||||
MobEffect* MobEffect::digSlowdown;
|
||||
MobEffect* MobEffect::damageBoost;
|
||||
MobEffect* MobEffect::heal;
|
||||
MobEffect* MobEffect::harm;
|
||||
MobEffect* MobEffect::jump;
|
||||
MobEffect* MobEffect::confusion;
|
||||
MobEffect* MobEffect::regeneration;
|
||||
MobEffect* MobEffect::damageResistance;
|
||||
MobEffect* MobEffect::fireResistance;
|
||||
MobEffect* MobEffect::waterBreathing;
|
||||
MobEffect* MobEffect::invisibility;
|
||||
MobEffect* MobEffect::blindness;
|
||||
MobEffect* MobEffect::nightVision;
|
||||
MobEffect* MobEffect::hunger;
|
||||
MobEffect* MobEffect::weakness;
|
||||
MobEffect* MobEffect::poison;
|
||||
MobEffect* MobEffect::wither;
|
||||
MobEffect* MobEffect::healthBoost;
|
||||
MobEffect* MobEffect::absorption;
|
||||
MobEffect* MobEffect::saturation;
|
||||
MobEffect* MobEffect::reserved_24;
|
||||
MobEffect* MobEffect::reserved_25;
|
||||
MobEffect* MobEffect::reserved_26;
|
||||
MobEffect* MobEffect::reserved_27;
|
||||
MobEffect* MobEffect::reserved_28;
|
||||
MobEffect* MobEffect::reserved_29;
|
||||
MobEffect* MobEffect::reserved_30;
|
||||
MobEffect* MobEffect::reserved_31;
|
||||
|
||||
void MobEffect::staticCtor() {
|
||||
voidEffect = NULL;
|
||||
movementSpeed =
|
||||
(new MobEffect(1, false, eMinecraftColour_Effect_MovementSpeed))
|
||||
->setDescriptionId(IDS_POTION_MOVESPEED)
|
||||
->setPostfixDescriptionId(IDS_POTION_MOVESPEED_POSTFIX)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Speed)
|
||||
->addAttributeModifier(
|
||||
SharedMonsterAttributes::MOVEMENT_SPEED,
|
||||
eModifierId_POTION_MOVESPEED, 0.2f,
|
||||
AttributeModifier::OPERATION_MULTIPLY_TOTAL); // setIcon(0, 0);
|
||||
movementSlowdown =
|
||||
(new MobEffect(2, true, eMinecraftColour_Effect_MovementSlowDown))
|
||||
->setDescriptionId(IDS_POTION_MOVESLOWDOWN)
|
||||
->setPostfixDescriptionId(IDS_POTION_MOVESLOWDOWN_POSTFIX)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Slowness)
|
||||
->addAttributeModifier(
|
||||
SharedMonsterAttributes::MOVEMENT_SPEED,
|
||||
eModifierId_POTION_MOVESLOWDOWN, -0.15f,
|
||||
AttributeModifier::OPERATION_MULTIPLY_TOTAL); //->setIcon(1,
|
||||
// 0);
|
||||
digSpeed =
|
||||
(new MobEffect(3, false, eMinecraftColour_Effect_DigSpeed))
|
||||
->setDescriptionId(IDS_POTION_DIGSPEED)
|
||||
->setPostfixDescriptionId(IDS_POTION_DIGSPEED_POSTFIX)
|
||||
->setDurationModifier(1.5)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Haste); //->setIcon(2, 0);
|
||||
digSlowdown =
|
||||
(new MobEffect(4, true, eMinecraftColour_Effect_DigSlowdown))
|
||||
->setDescriptionId(IDS_POTION_DIGSLOWDOWN)
|
||||
->setPostfixDescriptionId(IDS_POTION_DIGSLOWDOWN_POSTFIX)
|
||||
->setIcon(
|
||||
MobEffect::e_MobEffectIcon_MiningFatigue); //->setIcon(3, 0);
|
||||
damageBoost =
|
||||
(new AttackDamageMobEffect(5, false,
|
||||
eMinecraftColour_Effect_DamageBoost))
|
||||
->setDescriptionId(IDS_POTION_DAMAGEBOOST)
|
||||
->setPostfixDescriptionId(IDS_POTION_DAMAGEBOOST_POSTFIX)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Strength)
|
||||
->addAttributeModifier(
|
||||
SharedMonsterAttributes::ATTACK_DAMAGE,
|
||||
eModifierId_POTION_DAMAGEBOOST, 3,
|
||||
AttributeModifier::OPERATION_MULTIPLY_TOTAL); //->setIcon(4,
|
||||
// 0);
|
||||
heal = (new InstantenousMobEffect(6, false, eMinecraftColour_Effect_Heal))
|
||||
->setDescriptionId(IDS_POTION_HEAL)
|
||||
->setPostfixDescriptionId(IDS_POTION_HEAL_POSTFIX);
|
||||
harm = (new InstantenousMobEffect(7, true, eMinecraftColour_Effect_Harm))
|
||||
->setDescriptionId(IDS_POTION_HARM)
|
||||
->setPostfixDescriptionId(IDS_POTION_HARM_POSTFIX);
|
||||
jump =
|
||||
(new MobEffect(8, false, eMinecraftColour_Effect_Jump))
|
||||
->setDescriptionId(IDS_POTION_JUMP)
|
||||
->setPostfixDescriptionId(IDS_POTION_JUMP_POSTFIX)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_JumpBoost); //->setIcon(2, 1);
|
||||
confusion =
|
||||
(new MobEffect(9, true, eMinecraftColour_Effect_Confusion))
|
||||
->setDescriptionId(IDS_POTION_CONFUSION)
|
||||
->setPostfixDescriptionId(IDS_POTION_CONFUSION_POSTFIX)
|
||||
->setDurationModifier(.25)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Nausea); //->setIcon(3, 1);
|
||||
regeneration =
|
||||
(new MobEffect(10, false, eMinecraftColour_Effect_Regeneration))
|
||||
->setDescriptionId(IDS_POTION_REGENERATION)
|
||||
->setPostfixDescriptionId(IDS_POTION_REGENERATION_POSTFIX)
|
||||
->setDurationModifier(.25)
|
||||
->setIcon(
|
||||
MobEffect::e_MobEffectIcon_Regeneration); //->setIcon(7, 0);
|
||||
damageResistance =
|
||||
(new MobEffect(11, false, eMinecraftColour_Effect_DamageResistance))
|
||||
->setDescriptionId(IDS_POTION_RESISTANCE)
|
||||
->setPostfixDescriptionId(IDS_POTION_RESISTANCE_POSTFIX)
|
||||
->setIcon(
|
||||
MobEffect::e_MobEffectIcon_Resistance); //->setIcon(6, 1);
|
||||
fireResistance =
|
||||
(new MobEffect(12, false, eMinecraftColour_Effect_FireResistance))
|
||||
->setDescriptionId(IDS_POTION_FIRERESISTANCE)
|
||||
->setPostfixDescriptionId(IDS_POTION_FIRERESISTANCE_POSTFIX)
|
||||
->setIcon(
|
||||
MobEffect::e_MobEffectIcon_FireResistance); //->setIcon(7, 1);
|
||||
waterBreathing =
|
||||
(new MobEffect(13, false, eMinecraftColour_Effect_WaterBreathing))
|
||||
->setDescriptionId(IDS_POTION_WATERBREATHING)
|
||||
->setPostfixDescriptionId(IDS_POTION_WATERBREATHING_POSTFIX)
|
||||
->setIcon(
|
||||
MobEffect::e_MobEffectIcon_WaterBreathing); //->setIcon(0, 2);
|
||||
invisibility =
|
||||
(new MobEffect(14, false, eMinecraftColour_Effect_Invisiblity))
|
||||
->setDescriptionId(IDS_POTION_INVISIBILITY)
|
||||
->setPostfixDescriptionId(IDS_POTION_INVISIBILITY_POSTFIX)
|
||||
->setIcon(
|
||||
MobEffect::e_MobEffectIcon_Invisiblity); //->setIcon(0, 1);
|
||||
blindness =
|
||||
(new MobEffect(15, true, eMinecraftColour_Effect_Blindness))
|
||||
->setDescriptionId(IDS_POTION_BLINDNESS)
|
||||
->setPostfixDescriptionId(IDS_POTION_BLINDNESS_POSTFIX)
|
||||
->setDurationModifier(.25)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Blindness); //->setIcon(5, 1);
|
||||
nightVision =
|
||||
(new MobEffect(16, false, eMinecraftColour_Effect_NightVision))
|
||||
->setDescriptionId(IDS_POTION_NIGHTVISION)
|
||||
->setPostfixDescriptionId(IDS_POTION_NIGHTVISION_POSTFIX)
|
||||
->setIcon(
|
||||
MobEffect::e_MobEffectIcon_NightVision); //->setIcon(4, 1);
|
||||
hunger =
|
||||
(new MobEffect(17, true, eMinecraftColour_Effect_Hunger))
|
||||
->setDescriptionId(IDS_POTION_HUNGER)
|
||||
->setPostfixDescriptionId(IDS_POTION_HUNGER_POSTFIX)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Hunger); //->setIcon(1, 1);
|
||||
weakness =
|
||||
(new AttackDamageMobEffect(18, true, eMinecraftColour_Effect_Weakness))
|
||||
->setDescriptionId(IDS_POTION_WEAKNESS)
|
||||
->setPostfixDescriptionId(IDS_POTION_WEAKNESS_POSTFIX)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Weakness)
|
||||
->addAttributeModifier(
|
||||
SharedMonsterAttributes::ATTACK_DAMAGE,
|
||||
eModifierId_POTION_WEAKNESS, 2,
|
||||
AttributeModifier::OPERATION_ADDITION); //->setIcon(5, 0);
|
||||
poison =
|
||||
(new MobEffect(19, true, eMinecraftColour_Effect_Poison))
|
||||
->setDescriptionId(IDS_POTION_POISON)
|
||||
->setPostfixDescriptionId(IDS_POTION_POISON_POSTFIX)
|
||||
->setDurationModifier(.25)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Poison); //->setIcon(6, 0);
|
||||
wither = (new MobEffect(20, true, eMinecraftColour_Effect_Wither))
|
||||
->setDescriptionId(IDS_POTION_WITHER)
|
||||
->setPostfixDescriptionId(IDS_POTION_WITHER_POSTFIX)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Wither)
|
||||
->setDurationModifier(.25);
|
||||
healthBoost =
|
||||
(new HealthBoostMobEffect(21, false,
|
||||
eMinecraftColour_Effect_HealthBoost))
|
||||
->setDescriptionId(IDS_POTION_HEALTHBOOST)
|
||||
->setPostfixDescriptionId(IDS_POTION_HEALTHBOOST_POSTFIX)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_HealthBoost)
|
||||
->addAttributeModifier(SharedMonsterAttributes::MAX_HEALTH,
|
||||
eModifierId_POTION_HEALTHBOOST, 4,
|
||||
AttributeModifier::OPERATION_ADDITION);
|
||||
absorption =
|
||||
(new AbsoptionMobEffect(22, false, eMinecraftColour_Effect_Absoprtion))
|
||||
->setDescriptionId(IDS_POTION_ABSORPTION)
|
||||
->setPostfixDescriptionId(IDS_POTION_ABSORPTION_POSTFIX)
|
||||
->setIcon(MobEffect::e_MobEffectIcon_Absorption);
|
||||
saturation = (new InstantenousMobEffect(23, false,
|
||||
eMinecraftColour_Effect_Saturation))
|
||||
->setDescriptionId(IDS_POTION_SATURATION)
|
||||
->setPostfixDescriptionId(IDS_POTION_SATURATION_POSTFIX);
|
||||
reserved_24 = NULL;
|
||||
reserved_25 = NULL;
|
||||
reserved_26 = NULL;
|
||||
reserved_27 = NULL;
|
||||
reserved_28 = NULL;
|
||||
reserved_29 = NULL;
|
||||
reserved_30 = NULL;
|
||||
reserved_31 = NULL;
|
||||
}
|
||||
|
||||
MobEffect::MobEffect(int id, bool isHarmful, eMinecraftColour color)
|
||||
: id(id), _isHarmful(isHarmful), color(color) {
|
||||
|
|
@ -159,7 +239,8 @@ int MobEffect::getId() { return id; }
|
|||
* @param mob
|
||||
* @param amplification
|
||||
*/
|
||||
void MobEffect::applyEffectTick(std::shared_ptr<Mob> mob, int amplification) {
|
||||
void MobEffect::applyEffectTick(std::shared_ptr<LivingEntity> mob,
|
||||
int amplification) {
|
||||
// Maybe move this to separate class implementations in the future?
|
||||
if (id == regeneration->id) {
|
||||
if (mob->getHealth() < mob->getMaxHealth()) {
|
||||
|
|
@ -169,27 +250,33 @@ void MobEffect::applyEffectTick(std::shared_ptr<Mob> mob, int amplification) {
|
|||
if (mob->getHealth() > 1) {
|
||||
mob->hurt(DamageSource::magic, 1);
|
||||
}
|
||||
} else if (id == hunger->id &&
|
||||
std::dynamic_pointer_cast<Player>(mob) != NULL) {
|
||||
} else if (id == wither->id) {
|
||||
mob->hurt(DamageSource::wither, 1);
|
||||
} else if ((id == hunger->id) && mob->instanceof(eTYPE_PLAYER)) {
|
||||
// every tick, cause the same amount of exhaustion as when removing
|
||||
// a block, times amplification
|
||||
std::dynamic_pointer_cast<Player>(mob)->causeFoodExhaustion(
|
||||
FoodConstants::EXHAUSTION_MINE * (amplification + 1));
|
||||
} else if ((id == saturation->id) && mob->instanceof(eTYPE_PLAYER)) {
|
||||
if (!mob->level->isClientSide) {
|
||||
std::dynamic_pointer_cast<Player>(mob)->getFoodData()->eat(
|
||||
amplification + 1, FoodConstants::FOOD_SATURATION_MAX);
|
||||
}
|
||||
} else if ((id == heal->id && !mob->isInvertedHealAndHarm()) ||
|
||||
(id == harm->id && mob->isInvertedHealAndHarm())) {
|
||||
mob->heal(6 << amplification);
|
||||
mob->heal(std::max(4 << amplification, 0));
|
||||
} else if ((id == harm->id && !mob->isInvertedHealAndHarm()) ||
|
||||
(id == heal->id && mob->isInvertedHealAndHarm())) {
|
||||
mob->hurt(DamageSource::magic, 6 << amplification);
|
||||
}
|
||||
}
|
||||
|
||||
void MobEffect::applyInstantenousEffect(std::shared_ptr<Mob> source,
|
||||
std::shared_ptr<Mob> mob,
|
||||
void MobEffect::applyInstantenousEffect(std::shared_ptr<LivingEntity> source,
|
||||
std::shared_ptr<LivingEntity> mob,
|
||||
int amplification, double scale) {
|
||||
if ((id == heal->id && !mob->isInvertedHealAndHarm()) ||
|
||||
(id == harm->id && mob->isInvertedHealAndHarm())) {
|
||||
int amount = (int)(scale * (double)(6 << amplification) + .5);
|
||||
int amount = (int)(scale * (double)(4 << amplification) + .5);
|
||||
mob->heal(amount);
|
||||
} else if ((id == harm->id && !mob->isInvertedHealAndHarm()) ||
|
||||
(id == heal->id && mob->isInvertedHealAndHarm())) {
|
||||
|
|
@ -219,13 +306,26 @@ bool MobEffect::isInstantenous() { return false; }
|
|||
*/
|
||||
bool MobEffect::isDurationEffectTick(int remainingDuration, int amplification) {
|
||||
// Maybe move this to separate class implementations in the future?
|
||||
if (id == regeneration->id || id == poison->id) {
|
||||
if (id == regeneration->id) {
|
||||
// tick intervals are 50, 25, 12, 6..
|
||||
int interval = 50 >> amplification;
|
||||
if (interval > 0) {
|
||||
return (remainingDuration % interval) == 0;
|
||||
}
|
||||
return true;
|
||||
} else if (id == poison->id) {
|
||||
// tick intervals are 25, 12, 6..
|
||||
int interval = 25 >> amplification;
|
||||
if (interval > 0) {
|
||||
return (remainingDuration % interval) == 0;
|
||||
}
|
||||
return true;
|
||||
} else if (id == wither->id) {
|
||||
int interval = 40 >> amplification;
|
||||
if (interval > 0) {
|
||||
return (remainingDuration % interval) == 0;
|
||||
}
|
||||
return true;
|
||||
} else if (id == hunger->id) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -256,6 +356,9 @@ MobEffect::EMobEffectIcon MobEffect::getIcon() { return icon; }
|
|||
bool MobEffect::isHarmful() { return _isHarmful; }
|
||||
|
||||
std::wstring MobEffect::formatDuration(MobEffectInstance* instance) {
|
||||
if (instance->isNoCounter()) {
|
||||
return L"**:**";
|
||||
}
|
||||
int duration = instance->getDuration();
|
||||
|
||||
int seconds = duration / SharedConstants::TICKS_PER_SECOND;
|
||||
|
|
@ -284,10 +387,60 @@ MobEffect* MobEffect::setDurationModifier(double durationModifier) {
|
|||
double MobEffect::getDurationModifier() { return durationModifier; }
|
||||
|
||||
MobEffect* MobEffect::setDisabled() {
|
||||
this->_isDisabled = true;
|
||||
_isDisabled = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
bool MobEffect::isDisabled() { return _isDisabled; }
|
||||
|
||||
eMinecraftColour MobEffect::getColor() { return color; }
|
||||
|
||||
MobEffect* MobEffect::addAttributeModifier(Attribute* attribute,
|
||||
eMODIFIER_ID id, double amount,
|
||||
int operation) {
|
||||
AttributeModifier* effect = new AttributeModifier(id, amount, operation);
|
||||
attributeModifiers.insert(
|
||||
std::pair<Attribute*, AttributeModifier*>(attribute, effect));
|
||||
return this;
|
||||
}
|
||||
|
||||
std::unordered_map<Attribute*, AttributeModifier*>*
|
||||
MobEffect::getAttributeModifiers() {
|
||||
return &attributeModifiers;
|
||||
}
|
||||
|
||||
void MobEffect::removeAttributeModifiers(std::shared_ptr<LivingEntity> entity,
|
||||
BaseAttributeMap* attributes,
|
||||
int amplifier) {
|
||||
for (AUTO_VAR(it, attributeModifiers.begin());
|
||||
it != attributeModifiers.end(); ++it) {
|
||||
AttributeInstance* attribute = attributes->getInstance(it->first);
|
||||
|
||||
if (attribute != NULL) {
|
||||
attribute->removeModifier(it->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MobEffect::addAttributeModifiers(std::shared_ptr<LivingEntity> entity,
|
||||
BaseAttributeMap* attributes,
|
||||
int amplifier) {
|
||||
for (AUTO_VAR(it, attributeModifiers.begin());
|
||||
it != attributeModifiers.end(); ++it) {
|
||||
AttributeInstance* attribute = attributes->getInstance(it->first);
|
||||
|
||||
if (attribute != NULL) {
|
||||
AttributeModifier* original = it->second;
|
||||
attribute->removeModifier(original);
|
||||
attribute->addModifier(new AttributeModifier(
|
||||
original->getId(),
|
||||
getAttributeModifierValue(amplifier, original),
|
||||
original->getOperation()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double MobEffect::getAttributeModifierValue(int amplifier,
|
||||
AttributeModifier* original) {
|
||||
return original->getAmount() * (amplifier + 1);
|
||||
}
|
||||
|
|
@ -1,7 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include "../AI/Attributes/AttributeModifier.h"
|
||||
|
||||
class Mob;
|
||||
class MobEffectInstance;
|
||||
class Attribute;
|
||||
|
||||
class MobEffect {
|
||||
public:
|
||||
|
|
@ -24,6 +27,9 @@ public:
|
|||
e_MobEffectIcon_Strength,
|
||||
e_MobEffectIcon_WaterBreathing,
|
||||
e_MobEffectIcon_Weakness,
|
||||
e_MobEffectIcon_Wither,
|
||||
e_MobEffectIcon_HealthBoost,
|
||||
e_MobEffectIcon_Absorption,
|
||||
|
||||
e_MobEffectIcon_COUNT,
|
||||
};
|
||||
|
|
@ -51,10 +57,10 @@ public:
|
|||
static MobEffect* hunger;
|
||||
static MobEffect* weakness;
|
||||
static MobEffect* poison;
|
||||
static MobEffect* reserved_20;
|
||||
static MobEffect* reserved_21;
|
||||
static MobEffect* reserved_22;
|
||||
static MobEffect* reserved_23;
|
||||
static MobEffect* wither;
|
||||
static MobEffect* healthBoost;
|
||||
static MobEffect* absorption;
|
||||
static MobEffect* saturation;
|
||||
static MobEffect* reserved_24;
|
||||
static MobEffect* reserved_25;
|
||||
static MobEffect* reserved_26;
|
||||
|
|
@ -66,7 +72,10 @@ public:
|
|||
|
||||
const int id;
|
||||
|
||||
static void staticCtor();
|
||||
|
||||
private:
|
||||
std::unordered_map<Attribute*, AttributeModifier*> attributeModifiers;
|
||||
int descriptionId;
|
||||
int m_postfixDescriptionId; // 4J added
|
||||
EMobEffectIcon icon; // 4J changed type
|
||||
|
|
@ -82,11 +91,12 @@ protected:
|
|||
MobEffect* setIcon(EMobEffectIcon icon);
|
||||
|
||||
public:
|
||||
int getId();
|
||||
void applyEffectTick(std::shared_ptr<Mob> mob, int amplification);
|
||||
void applyInstantenousEffect(std::shared_ptr<Mob> source,
|
||||
std::shared_ptr<Mob> mob, int amplification,
|
||||
double scale);
|
||||
virtual int getId();
|
||||
virtual void applyEffectTick(std::shared_ptr<LivingEntity> mob,
|
||||
int amplification);
|
||||
virtual void applyInstantenousEffect(std::shared_ptr<LivingEntity> source,
|
||||
std::shared_ptr<LivingEntity> mob,
|
||||
int amplification, double scale);
|
||||
virtual bool isInstantenous();
|
||||
virtual bool isDurationEffectTick(int remainingDuration, int amplification);
|
||||
|
||||
|
|
@ -106,8 +116,22 @@ protected:
|
|||
MobEffect* setDurationModifier(double durationModifier);
|
||||
|
||||
public:
|
||||
double getDurationModifier();
|
||||
MobEffect* setDisabled();
|
||||
bool isDisabled();
|
||||
eMinecraftColour getColor();
|
||||
virtual double getDurationModifier();
|
||||
virtual MobEffect* setDisabled();
|
||||
virtual bool isDisabled();
|
||||
virtual eMinecraftColour getColor();
|
||||
|
||||
virtual MobEffect* addAttributeModifier(Attribute* attribute,
|
||||
eMODIFIER_ID id, double amount,
|
||||
int operation);
|
||||
virtual std::unordered_map<Attribute*, AttributeModifier*>*
|
||||
getAttributeModifiers();
|
||||
virtual void removeAttributeModifiers(std::shared_ptr<LivingEntity> entity,
|
||||
BaseAttributeMap* attributes,
|
||||
int amplifier);
|
||||
virtual void addAttributeModifiers(std::shared_ptr<LivingEntity> entity,
|
||||
BaseAttributeMap* attributes,
|
||||
int amplifier);
|
||||
virtual double getAttributeModifierValue(int amplifier,
|
||||
AttributeModifier* original);
|
||||
};
|
||||
|
|
@ -5,6 +5,10 @@ void MobEffectInstance::_init(int id, int duration, int amplifier) {
|
|||
this->id = id;
|
||||
this->duration = duration;
|
||||
this->amplifier = amplifier;
|
||||
|
||||
splash = false;
|
||||
ambient = false;
|
||||
noCounter = false;
|
||||
}
|
||||
|
||||
MobEffectInstance::MobEffectInstance(int id) { _init(id, 0, 0); }
|
||||
|
|
@ -17,23 +21,34 @@ MobEffectInstance::MobEffectInstance(int id, int duration, int amplifier) {
|
|||
_init(id, duration, amplifier);
|
||||
}
|
||||
|
||||
MobEffectInstance::MobEffectInstance(int id, int duration, int amplifier,
|
||||
bool ambient) {
|
||||
_init(id, duration, amplifier);
|
||||
this->ambient = ambient;
|
||||
}
|
||||
|
||||
MobEffectInstance::MobEffectInstance(MobEffectInstance* copy) {
|
||||
this->id = copy->id;
|
||||
this->duration = copy->duration;
|
||||
this->amplifier = copy->amplifier;
|
||||
this->splash = copy->splash;
|
||||
this->ambient = copy->ambient;
|
||||
this->noCounter = copy->noCounter;
|
||||
}
|
||||
|
||||
void MobEffectInstance::update(MobEffectInstance* takeOver) {
|
||||
if (this->id != takeOver->id) {
|
||||
if (id != takeOver->id) {
|
||||
app.DebugPrintf(
|
||||
"This method should only be called for matching effects!");
|
||||
}
|
||||
if (takeOver->amplifier > this->amplifier) {
|
||||
this->amplifier = takeOver->amplifier;
|
||||
this->duration = takeOver->duration;
|
||||
} else if (takeOver->amplifier == this->amplifier &&
|
||||
this->duration < takeOver->duration) {
|
||||
this->duration = takeOver->duration;
|
||||
if (takeOver->amplifier > amplifier) {
|
||||
amplifier = takeOver->amplifier;
|
||||
duration = takeOver->duration;
|
||||
} else if (takeOver->amplifier == amplifier &&
|
||||
duration < takeOver->duration) {
|
||||
duration = takeOver->duration;
|
||||
} else if (!takeOver->ambient && ambient) {
|
||||
ambient = takeOver->ambient;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -43,13 +58,19 @@ int MobEffectInstance::getDuration() { return duration; }
|
|||
|
||||
int MobEffectInstance::getAmplifier() { return amplifier; }
|
||||
|
||||
bool MobEffectInstance::isSplash() { return splash; }
|
||||
|
||||
void MobEffectInstance::setSplash(bool splash) { this->splash = splash; }
|
||||
|
||||
bool MobEffectInstance::isAmbient() { return ambient; }
|
||||
|
||||
/**
|
||||
* Runs the effect on a Mob target.
|
||||
*
|
||||
* @param target
|
||||
* @return True if the effect is still active.
|
||||
*/
|
||||
bool MobEffectInstance::tick(std::shared_ptr<Mob> target) {
|
||||
bool MobEffectInstance::tick(std::shared_ptr<LivingEntity> target) {
|
||||
if (duration > 0) {
|
||||
if (MobEffect::effects[id]->isDurationEffectTick(duration, amplifier)) {
|
||||
applyEffect(target);
|
||||
|
|
@ -61,7 +82,7 @@ bool MobEffectInstance::tick(std::shared_ptr<Mob> target) {
|
|||
|
||||
int MobEffectInstance::tickDownDuration() { return --duration; }
|
||||
|
||||
void MobEffectInstance::applyEffect(std::shared_ptr<Mob> mob) {
|
||||
void MobEffectInstance::applyEffect(std::shared_ptr<LivingEntity> mob) {
|
||||
if (duration > 0) {
|
||||
MobEffect::effects[id]->applyEffectTick(mob, amplifier);
|
||||
}
|
||||
|
|
@ -88,11 +109,11 @@ int MobEffectInstance::hashCode() {
|
|||
std::wstring MobEffectInstance::toString() {
|
||||
std::wstring result =
|
||||
L"MobEffectInstance::toString - NON IMPLEMENTED OR LOCALISED FUNCTION";
|
||||
// std::wstring result = "";
|
||||
// wstring result = "";
|
||||
// if (getAmplifier() > 0)
|
||||
//{
|
||||
// result = getDescriptionId() + " x " + (getAmplifier() + 1) + ",
|
||||
//Duration: " + getDuration();
|
||||
// Duration: " + getDuration();
|
||||
// }
|
||||
// else
|
||||
//{
|
||||
|
|
@ -106,7 +127,30 @@ std::wstring MobEffectInstance::toString() {
|
|||
}
|
||||
|
||||
// Was bool equals(Object obj)
|
||||
bool MobEffectInstance::equals(MobEffectInstance* obj) {
|
||||
return this->id == obj->id && this->amplifier == obj->amplifier &&
|
||||
this->duration == obj->duration;
|
||||
bool MobEffectInstance::equals(MobEffectInstance* instance) {
|
||||
return id == instance->id && amplifier == instance->amplifier &&
|
||||
duration == instance->duration && splash == instance->splash &&
|
||||
ambient == instance->ambient;
|
||||
}
|
||||
|
||||
CompoundTag* MobEffectInstance::save(CompoundTag* tag) {
|
||||
tag->putByte(L"Id", (uint8_t)getId());
|
||||
tag->putByte(L"Amplifier", (uint8_t)getAmplifier());
|
||||
tag->putInt(L"Duration", getDuration());
|
||||
tag->putBoolean(L"Ambient", isAmbient());
|
||||
return tag;
|
||||
}
|
||||
|
||||
MobEffectInstance* MobEffectInstance::load(CompoundTag* tag) {
|
||||
int id = tag->getByte(L"Id");
|
||||
int amplifier = tag->getByte(L"Amplifier");
|
||||
int duration = tag->getInt(L"Duration");
|
||||
boolean ambient = tag->getBoolean(L"Ambient");
|
||||
return new MobEffectInstance(id, duration, amplifier, ambient);
|
||||
}
|
||||
|
||||
void MobEffectInstance::setNoCounter(bool noCounter) {
|
||||
this->noCounter = noCounter;
|
||||
}
|
||||
|
||||
bool MobEffectInstance::isNoCounter() { return noCounter; }
|
||||
|
|
@ -10,6 +10,9 @@ private:
|
|||
int duration;
|
||||
// sent as byte
|
||||
int amplifier;
|
||||
bool splash;
|
||||
bool ambient;
|
||||
bool noCounter;
|
||||
|
||||
void _init(int id, int duration, int amplifier);
|
||||
|
||||
|
|
@ -17,19 +20,25 @@ public:
|
|||
MobEffectInstance(int id);
|
||||
MobEffectInstance(int id, int duration);
|
||||
MobEffectInstance(int id, int duration, int amplifier);
|
||||
MobEffectInstance(int id, int duration, int amplifier, bool ambient);
|
||||
MobEffectInstance(MobEffectInstance* copy);
|
||||
|
||||
void update(MobEffectInstance* takeOver);
|
||||
int getId();
|
||||
int getDuration();
|
||||
int getAmplifier();
|
||||
bool tick(std::shared_ptr<Mob> target);
|
||||
|
||||
bool isSplash();
|
||||
void setSplash(bool splash);
|
||||
bool isAmbient();
|
||||
|
||||
bool tick(std::shared_ptr<LivingEntity> target);
|
||||
|
||||
private:
|
||||
int tickDownDuration();
|
||||
|
||||
public:
|
||||
void applyEffect(std::shared_ptr<Mob> mob);
|
||||
void applyEffect(std::shared_ptr<LivingEntity> mob);
|
||||
int getDescriptionId();
|
||||
int getPostfixDescriptionId(); // 4J Added
|
||||
int hashCode();
|
||||
|
|
@ -38,4 +47,9 @@ public:
|
|||
|
||||
// Was bool equals(Object obj)
|
||||
bool equals(MobEffectInstance* obj);
|
||||
|
||||
CompoundTag* save(CompoundTag* tag);
|
||||
static MobEffectInstance* load(CompoundTag* tag);
|
||||
void setNoCounter(bool noCounter);
|
||||
bool isNoCounter();
|
||||
};
|
||||
|
|
@ -12,10 +12,10 @@ AgableMob::AgableMob(Level* level) : PathfinderMob(level) {
|
|||
registeredBBHeight = 0;
|
||||
}
|
||||
|
||||
bool AgableMob::interact(std::shared_ptr<Player> player) {
|
||||
bool AgableMob::mobInteract(std::shared_ptr<Player> player) {
|
||||
std::shared_ptr<ItemInstance> item = player->inventory->getSelected();
|
||||
|
||||
if (item != NULL && item->id == Item::monsterPlacer_Id) {
|
||||
if (item != NULL && item->id == Item::spawnEgg_Id) {
|
||||
if (!level->isClientSide) {
|
||||
eINSTANCEOF classToSpawn = EntityIO::getClass(item->getAuxValue());
|
||||
if (classToSpawn != eTYPE_NOTSET &&
|
||||
|
|
@ -23,28 +23,38 @@ bool AgableMob::interact(std::shared_ptr<Player> player) {
|
|||
classToSpawn == GetType()) // 4J Added GetType() check to only
|
||||
// spawn same type
|
||||
{
|
||||
std::shared_ptr<AgableMob> offspring = getBreedOffspring(
|
||||
std::dynamic_pointer_cast<AgableMob>(shared_from_this()));
|
||||
if (offspring != NULL) {
|
||||
offspring->setAge(-20 * 60 * 20);
|
||||
offspring->moveTo(x, y, z, 0, 0);
|
||||
int error;
|
||||
std::shared_ptr<Entity> result =
|
||||
SpawnEggItem::canSpawn(item->getAuxValue(), level, &error);
|
||||
|
||||
level->addEntity(offspring);
|
||||
if (result != NULL) {
|
||||
std::shared_ptr<AgableMob> offspring =
|
||||
getBreedOffspring(std::dynamic_pointer_cast<AgableMob>(
|
||||
shared_from_this()));
|
||||
if (offspring != NULL) {
|
||||
offspring->setAge(BABY_START_AGE);
|
||||
offspring->moveTo(x, y, z, 0, 0);
|
||||
|
||||
if (!player->abilities.instabuild) {
|
||||
item->count--;
|
||||
level->addEntity(offspring);
|
||||
|
||||
if (item->count <= 0) {
|
||||
player->inventory->setItem(
|
||||
player->inventory->selected, nullptr);
|
||||
if (!player->abilities.instabuild) {
|
||||
item->count--;
|
||||
|
||||
if (item->count <= 0) {
|
||||
player->inventory->setItem(
|
||||
player->inventory->selected, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SpawnEggItem::DisplaySpawnError(player, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return PathfinderMob::interact(player);
|
||||
return false;
|
||||
}
|
||||
|
||||
void AgableMob::defineSynchedData() {
|
||||
|
|
@ -54,6 +64,15 @@ void AgableMob::defineSynchedData() {
|
|||
|
||||
int AgableMob::getAge() { return entityData->getInteger(DATA_AGE_ID); }
|
||||
|
||||
void AgableMob::ageUp(int seconds) {
|
||||
int age = getAge();
|
||||
age += seconds * SharedConstants::TICKS_PER_SECOND;
|
||||
if (age > 0) {
|
||||
age = 0;
|
||||
}
|
||||
setAge(age);
|
||||
}
|
||||
|
||||
void AgableMob::setAge(int age) {
|
||||
entityData->set(DATA_AGE_ID, age);
|
||||
updateSize(isBaby());
|
||||
|
|
|
|||
|
|
@ -6,13 +6,17 @@ class AgableMob : public PathfinderMob {
|
|||
private:
|
||||
static const int DATA_AGE_ID = 12;
|
||||
|
||||
public:
|
||||
static const int BABY_START_AGE = -20 * 60 * 20;
|
||||
|
||||
private:
|
||||
float registeredBBWidth;
|
||||
float registeredBBHeight;
|
||||
|
||||
public:
|
||||
AgableMob(Level* level);
|
||||
|
||||
virtual bool interact(std::shared_ptr<Player> player);
|
||||
virtual bool mobInteract(std::shared_ptr<Player> player);
|
||||
|
||||
protected:
|
||||
virtual void defineSynchedData();
|
||||
|
|
@ -21,6 +25,7 @@ public:
|
|||
virtual std::shared_ptr<AgableMob> getBreedOffspring(
|
||||
std::shared_ptr<AgableMob> target) = 0;
|
||||
virtual int getAge();
|
||||
virtual void ageUp(int seconds);
|
||||
virtual void setAge(int age);
|
||||
virtual void addAdditonalSaveData(CompoundTag* tag);
|
||||
virtual void readAdditionalSaveData(CompoundTag* tag);
|
||||
|
|
|
|||
11
Minecraft.World/Entities/Mobs/AmbientCreature.cpp
Normal file
11
Minecraft.World/Entities/Mobs/AmbientCreature.cpp
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#include "../../Platform/stdafx.h"
|
||||
|
||||
#include "AmbientCreature.h"
|
||||
|
||||
AmbientCreature::AmbientCreature(Level* level) : Mob(level) {}
|
||||
|
||||
bool AmbientCreature::canBeLeashed() { return false; }
|
||||
|
||||
bool AmbientCreature::mobInteract(std::shared_ptr<Player> player) {
|
||||
return false;
|
||||
}
|
||||
14
Minecraft.World/Entities/Mobs/AmbientCreature.h
Normal file
14
Minecraft.World/Entities/Mobs/AmbientCreature.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Mob.h"
|
||||
#include "Creature.h"
|
||||
|
||||
class AmbientCreature : public Mob, public Creature {
|
||||
public:
|
||||
AmbientCreature(Level* level);
|
||||
|
||||
virtual bool canBeLeashed();
|
||||
|
||||
protected:
|
||||
virtual bool mobInteract(std::shared_ptr<Player> player);
|
||||
};
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
#include "../../Platform/stdafx.h"
|
||||
|
||||
#include "../../Headers/com.mojang.nbt.h"
|
||||
#include "../../Headers/net.minecraft.world.level.tile.h"
|
||||
#include "../../Headers/net.minecraft.world.item.h"
|
||||
|
|
@ -9,6 +10,8 @@
|
|||
#include "../../Headers/net.minecraft.world.entity.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.projectile.h"
|
||||
#include "../../Headers/net.minecraft.world.damagesource.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.monster.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.attributes.h"
|
||||
#include "../../Util/Random.h"
|
||||
#include "Animal.h"
|
||||
|
||||
|
|
@ -57,7 +60,8 @@ void Animal::aiStep() {
|
|||
}
|
||||
|
||||
void Animal::checkHurtTarget(std::shared_ptr<Entity> target, float d) {
|
||||
if (std::dynamic_pointer_cast<Player>(target) != NULL) {
|
||||
// 4J-JEV: Changed from dynamic cast to use eINSTANCEOF
|
||||
if (target->instanceof(eTYPE_PLAYER)) {
|
||||
if (d < 3) {
|
||||
double xd = target->x - x;
|
||||
double zd = target->z - z;
|
||||
|
|
@ -67,13 +71,13 @@ void Animal::checkHurtTarget(std::shared_ptr<Entity> target, float d) {
|
|||
}
|
||||
|
||||
std::shared_ptr<Player> p = std::dynamic_pointer_cast<Player>(target);
|
||||
if (p->getSelectedItem() != NULL &&
|
||||
this->isFood(p->getSelectedItem())) {
|
||||
} else {
|
||||
if (p->getSelectedItem() == NULL || !isFood(p->getSelectedItem())) {
|
||||
attackTarget = nullptr;
|
||||
}
|
||||
|
||||
} else if (std::dynamic_pointer_cast<Animal>(target) != NULL) {
|
||||
}
|
||||
// 4J-JEV: Changed from dynamic cast to use eINSTANCEOF
|
||||
else if (target->instanceof(eTYPE_ANIMAL)) {
|
||||
std::shared_ptr<Animal> a = std::dynamic_pointer_cast<Animal>(target);
|
||||
if (getAge() > 0 && a->getAge() < 0) {
|
||||
if (d < 2.5) {
|
||||
|
|
@ -152,20 +156,26 @@ float Animal::getWalkTargetValue(int x, int y, int z) {
|
|||
return level->getBrightness(x, y, z) - 0.5f;
|
||||
}
|
||||
|
||||
bool Animal::hurt(DamageSource* dmgSource, int dmg) {
|
||||
bool Animal::hurt(DamageSource* dmgSource, float dmg) {
|
||||
if (isInvulnerable()) return false;
|
||||
if (dynamic_cast<EntityDamageSource*>(dmgSource) != NULL) {
|
||||
std::shared_ptr<Entity> source = dmgSource->getDirectEntity();
|
||||
|
||||
if (std::dynamic_pointer_cast<Player>(source) != NULL &&
|
||||
// 4J-JEV: Changed from dynamic cast to use eINSTANCEOF
|
||||
if (source->instanceof(eTYPE_PLAYER) &&
|
||||
!std::dynamic_pointer_cast<Player>(source)
|
||||
->isAllowedToAttackAnimals()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (source != NULL && source->GetType() == eTYPE_ARROW) {
|
||||
if ((source != NULL) && source->instanceof(eTYPE_ARROW)) {
|
||||
std::shared_ptr<Arrow> arrow =
|
||||
std::dynamic_pointer_cast<Arrow>(source);
|
||||
if (std::dynamic_pointer_cast<Player>(arrow->owner) != NULL &&
|
||||
|
||||
// 4J: Check that the arrow's owner can attack animals (dispenser
|
||||
// arrows are not owned)
|
||||
if (arrow->owner != NULL &&
|
||||
arrow->owner->instanceof(eTYPE_PLAYER) &&
|
||||
!std::dynamic_pointer_cast<Player>(arrow->owner)
|
||||
->isAllowedToAttackAnimals()) {
|
||||
return false;
|
||||
|
|
@ -174,6 +184,16 @@ bool Animal::hurt(DamageSource* dmgSource, int dmg) {
|
|||
}
|
||||
|
||||
fleeTime = 20 * 3;
|
||||
|
||||
if (!useNewAi()) {
|
||||
AttributeInstance* speed =
|
||||
getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED);
|
||||
if (speed->getModifier(eModifierId_MOB_FLEEING) == NULL) {
|
||||
speed->addModifier(
|
||||
new AttributeModifier(*Animal::SPEED_MODIFIER_FLEEING));
|
||||
}
|
||||
}
|
||||
|
||||
attackTarget = nullptr;
|
||||
setInLoveValue(0);
|
||||
|
||||
|
|
@ -265,9 +285,10 @@ bool Animal::isFood(std::shared_ptr<ItemInstance> itemInstance) {
|
|||
return itemInstance->id == Item::wheat_Id;
|
||||
}
|
||||
|
||||
bool Animal::interact(std::shared_ptr<Player> player) {
|
||||
bool Animal::mobInteract(std::shared_ptr<Player> player) {
|
||||
std::shared_ptr<ItemInstance> item = player->inventory->getSelected();
|
||||
if (item != NULL && isFood(item) && getAge() == 0) {
|
||||
if (item != NULL && isFood(item) && getAge() == 0 &&
|
||||
getInLoveValue() <= 0) {
|
||||
if (!player->abilities.instabuild) {
|
||||
item->count--;
|
||||
if (item->count <= 0) {
|
||||
|
|
@ -311,28 +332,17 @@ bool Animal::interact(std::shared_ptr<Player> player) {
|
|||
|
||||
return false;
|
||||
}
|
||||
} else if ((GetType() & eTYPE_MONSTER) == eTYPE_MONSTER) {
|
||||
} else if (instanceof(eTYPE_MONSTER)) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
setInLove(player);
|
||||
}
|
||||
|
||||
attackTarget = nullptr;
|
||||
for (int i = 0; i < 7; i++) {
|
||||
double xa = random->nextGaussian() * 0.02;
|
||||
double ya = random->nextGaussian() * 0.02;
|
||||
double za = random->nextGaussian() * 0.02;
|
||||
level->addParticle(eParticleType_heart,
|
||||
x + random->nextFloat() * bbWidth * 2 - bbWidth,
|
||||
y + .5f + random->nextFloat() * bbHeight,
|
||||
z + random->nextFloat() * bbWidth * 2 - bbWidth,
|
||||
xa, ya, za);
|
||||
}
|
||||
setInLove();
|
||||
|
||||
return true;
|
||||
}
|
||||
return AgableMob::interact(player);
|
||||
return AgableMob::mobInteract(player);
|
||||
}
|
||||
|
||||
// 4J added
|
||||
|
|
@ -348,18 +358,41 @@ void Animal::setInLove(std::shared_ptr<Player> player) {
|
|||
|
||||
std::shared_ptr<Player> Animal::getLoveCause() { return loveCause.lock(); }
|
||||
|
||||
void Animal::setInLove() {
|
||||
entityData->set(DATA_IN_LOVE, 20 * 30);
|
||||
|
||||
attackTarget = nullptr;
|
||||
level->broadcastEntityEvent(shared_from_this(),
|
||||
EntityEvent::IN_LOVE_HEARTS);
|
||||
}
|
||||
|
||||
bool Animal::isInLove() { return entityData->getInteger(DATA_IN_LOVE) > 0; }
|
||||
|
||||
void Animal::resetLove() { entityData->set(DATA_IN_LOVE, 0); }
|
||||
|
||||
bool Animal::canMate(std::shared_ptr<Animal> partner) {
|
||||
if (partner == shared_from_this()) return false;
|
||||
Animal* partnerPtr = partner.get();
|
||||
if (partnerPtr == NULL || typeid(*partnerPtr) != typeid(*this))
|
||||
return false;
|
||||
if (typeid(*partner) != typeid(*this)) return false;
|
||||
return isInLove() && partner->isInLove();
|
||||
}
|
||||
|
||||
void Animal::handleEntityEvent(uint8_t id) {
|
||||
if (id == EntityEvent::IN_LOVE_HEARTS) {
|
||||
for (int i = 0; i < 7; i++) {
|
||||
double xa = random->nextGaussian() * 0.02;
|
||||
double ya = random->nextGaussian() * 0.02;
|
||||
double za = random->nextGaussian() * 0.02;
|
||||
level->addParticle(eParticleType_heart,
|
||||
x + random->nextFloat() * bbWidth * 2 - bbWidth,
|
||||
y + .5f + random->nextFloat() * bbHeight,
|
||||
z + random->nextFloat() * bbWidth * 2 - bbWidth,
|
||||
xa, ya, za);
|
||||
}
|
||||
} else {
|
||||
AgableMob::handleEntityEvent(id);
|
||||
}
|
||||
}
|
||||
|
||||
void Animal::updateDespawnProtectedState() {
|
||||
if (level->isClientSide) return;
|
||||
|
||||
|
|
@ -375,7 +408,7 @@ void Animal::updateDespawnProtectedState() {
|
|||
if (((m_maxWanderX - m_minWanderX) > MAX_WANDER_DISTANCE) ||
|
||||
((m_maxWanderZ - m_minWanderZ) > MAX_WANDER_DISTANCE)) {
|
||||
// printf("Unprotecting : %d to %d, %d to %d\n",
|
||||
//m_minWanderX, m_maxWanderX, m_minWanderZ, m_maxWanderZ );
|
||||
// m_minWanderX, m_maxWanderX, m_minWanderZ, m_maxWanderZ );
|
||||
m_isDespawnProtected = false;
|
||||
}
|
||||
|
||||
|
|
@ -403,4 +436,4 @@ void Animal::setDespawnProtected() {
|
|||
m_maxWanderZ = zt;
|
||||
|
||||
m_isDespawnProtected = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ private:
|
|||
static const int DATA_IN_LOVE = 13; // 4J added
|
||||
|
||||
// int inLove; // 4J
|
||||
//removed - now synched data
|
||||
// removed - now synched data
|
||||
int loveTime;
|
||||
std::weak_ptr<Player> loveCause;
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ public:
|
|||
virtual float getWalkTargetValue(int x, int y, int z);
|
||||
|
||||
public:
|
||||
virtual bool hurt(DamageSource* source, int dmg);
|
||||
virtual bool hurt(DamageSource* source, float dmg);
|
||||
virtual void addAdditonalSaveData(CompoundTag* tag);
|
||||
virtual void readAdditionalSaveData(CompoundTag* tag);
|
||||
|
||||
|
|
@ -52,7 +52,7 @@ protected:
|
|||
|
||||
public:
|
||||
virtual bool isFood(std::shared_ptr<ItemInstance> itemInstance);
|
||||
virtual bool interact(std::shared_ptr<Player> player);
|
||||
virtual bool mobInteract(std::shared_ptr<Player> player);
|
||||
|
||||
protected:
|
||||
int getInLoveValue(); // 4J added
|
||||
|
|
@ -62,10 +62,12 @@ public:
|
|||
void setInLove(std::shared_ptr<Player>
|
||||
player); // 4J added, then modified to match latest Java
|
||||
// for XboxOne achievements
|
||||
virtual void setInLove();
|
||||
std::shared_ptr<Player> getLoveCause();
|
||||
bool isInLove();
|
||||
void resetLove();
|
||||
virtual bool canMate(std::shared_ptr<Animal> partner);
|
||||
virtual void handleEntityEvent(uint8_t id);
|
||||
|
||||
// 4J added for determining whether animals are enclosed or not
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@
|
|||
#include "../../Headers/net.minecraft.world.item.h"
|
||||
#include "../../Headers/net.minecraft.world.damagesource.h"
|
||||
#include "../../Headers/net.minecraft.world.item.enchantment.h"
|
||||
#include "../../Headers/net.minecraft.network.packet.h"
|
||||
#include "../../../Minecraft.Client/Player/ServerPlayer.h"
|
||||
#include "../../../Minecraft.Client/Network/PlayerConnection.h"
|
||||
#include "../../Headers/com.mojang.nbt.h"
|
||||
#include "Arrow.h"
|
||||
|
||||
|
|
@ -44,16 +47,19 @@ void Arrow::_init() {
|
|||
Arrow::Arrow(Level* level) : Entity(level) {
|
||||
_init();
|
||||
|
||||
this->setSize(0.5f, 0.5f);
|
||||
viewScale = 10;
|
||||
setSize(0.5f, 0.5f);
|
||||
}
|
||||
|
||||
Arrow::Arrow(Level* level, std::shared_ptr<Mob> mob,
|
||||
std::shared_ptr<Mob> target, float power, float uncertainty)
|
||||
Arrow::Arrow(Level* level, std::shared_ptr<LivingEntity> mob,
|
||||
std::shared_ptr<LivingEntity> target, float power,
|
||||
float uncertainty)
|
||||
: Entity(level) {
|
||||
_init();
|
||||
|
||||
this->owner = mob;
|
||||
if (std::dynamic_pointer_cast<Player>(mob) != NULL) pickup = PICKUP_ALLOWED;
|
||||
viewScale = 10;
|
||||
owner = mob;
|
||||
if (mob->instanceof(eTYPE_PLAYER)) pickup = PICKUP_ALLOWED;
|
||||
|
||||
y = mob->y + mob->getHeadHeight() - 0.1f;
|
||||
|
||||
|
|
@ -78,29 +84,30 @@ Arrow::Arrow(Level* level, std::shared_ptr<Mob> mob,
|
|||
Arrow::Arrow(Level* level, double x, double y, double z) : Entity(level) {
|
||||
_init();
|
||||
|
||||
this->setSize(0.5f, 0.5f);
|
||||
viewScale = 10;
|
||||
setSize(0.5f, 0.5f);
|
||||
|
||||
this->setPos(x, y, z);
|
||||
this->heightOffset = 0;
|
||||
setPos(x, y, z);
|
||||
heightOffset = 0;
|
||||
}
|
||||
|
||||
Arrow::Arrow(Level* level, std::shared_ptr<Mob> mob, float power)
|
||||
Arrow::Arrow(Level* level, std::shared_ptr<LivingEntity> mob, float power)
|
||||
: Entity(level) {
|
||||
_init();
|
||||
|
||||
this->owner = mob;
|
||||
if (std::dynamic_pointer_cast<Player>(mob) != NULL) pickup = PICKUP_ALLOWED;
|
||||
viewScale = 10;
|
||||
owner = mob;
|
||||
if (mob->instanceof(eTYPE_PLAYER)) pickup = PICKUP_ALLOWED;
|
||||
|
||||
setSize(0.5f, 0.5f);
|
||||
|
||||
this->moveTo(mob->x, mob->y + mob->getHeadHeight(), mob->z, mob->yRot,
|
||||
mob->xRot);
|
||||
moveTo(mob->x, mob->y + mob->getHeadHeight(), mob->z, mob->yRot, mob->xRot);
|
||||
|
||||
x -= Mth::cos(yRot / 180 * PI) * 0.16f;
|
||||
y -= 0.1f;
|
||||
z -= Mth::sin(yRot / 180 * PI) * 0.16f;
|
||||
this->setPos(x, y, z);
|
||||
this->heightOffset = 0;
|
||||
setPos(x, y, z);
|
||||
heightOffset = 0;
|
||||
|
||||
xd = -Mth::sin(yRot / 180 * PI) * Mth::cos(xRot / 180 * PI);
|
||||
zd = Mth::cos(yRot / 180 * PI) * Mth::cos(xRot / 180 * PI);
|
||||
|
|
@ -119,9 +126,12 @@ void Arrow::shoot(double xd, double yd, double zd, float pow,
|
|||
yd /= dist;
|
||||
zd /= dist;
|
||||
|
||||
xd += (random->nextGaussian()) * 0.0075f * uncertainty;
|
||||
yd += (random->nextGaussian()) * 0.0075f * uncertainty;
|
||||
zd += (random->nextGaussian()) * 0.0075f * uncertainty;
|
||||
xd += (random->nextGaussian() * (random->nextBoolean() ? -1 : 1)) *
|
||||
0.0075f * uncertainty;
|
||||
yd += (random->nextGaussian() * (random->nextBoolean() ? -1 : 1)) *
|
||||
0.0075f * uncertainty;
|
||||
zd += (random->nextGaussian() * (random->nextBoolean() ? -1 : 1)) *
|
||||
0.0075f * uncertainty;
|
||||
|
||||
xd *= pow;
|
||||
yd *= pow;
|
||||
|
|
@ -133,8 +143,8 @@ void Arrow::shoot(double xd, double yd, double zd, float pow,
|
|||
|
||||
double sd = sqrt(xd * xd + zd * zd);
|
||||
|
||||
yRotO = this->yRot = (float)(atan2(xd, zd) * 180 / PI);
|
||||
xRotO = this->xRot = (float)(atan2(yd, sd) * 180 / PI);
|
||||
yRotO = yRot = (float)(atan2(xd, zd) * 180 / PI);
|
||||
xRotO = xRot = (float)(atan2(yd, sd) * 180 / PI);
|
||||
life = 0;
|
||||
}
|
||||
|
||||
|
|
@ -150,8 +160,8 @@ void Arrow::lerpMotion(double xd, double yd, double zd) {
|
|||
this->zd = zd;
|
||||
if (xRotO == 0 && yRotO == 0) {
|
||||
double sd = sqrt(xd * xd + zd * zd);
|
||||
yRotO = this->yRot = (float)(atan2(xd, zd) * 180 / PI);
|
||||
xRotO = this->xRot = (float)(atan2(yd, sd) * 180 / PI);
|
||||
yRotO = yRot = (float)(atan2(xd, zd) * 180 / PI);
|
||||
xRotO = xRot = (float)(atan2(yd, sd) * 180 / PI);
|
||||
xRotO = xRot;
|
||||
yRotO = yRot;
|
||||
app.DebugPrintf("%f %f : 0x%x\n", xRot, yRot, &yRot);
|
||||
|
|
@ -165,8 +175,8 @@ void Arrow::tick() {
|
|||
|
||||
if (xRotO == 0 && yRotO == 0) {
|
||||
double sd = sqrt(xd * xd + zd * zd);
|
||||
yRotO = this->yRot = (float)(atan2(xd, zd) * 180 / PI);
|
||||
xRotO = this->xRot = (float)(atan2(yd, sd) * 180 / PI);
|
||||
yRotO = yRot = (float)(atan2(xd, zd) * 180 / PI);
|
||||
xRotO = xRot = (float)(atan2(yd, sd) * 180 / PI);
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -243,6 +253,20 @@ void Arrow::tick() {
|
|||
res = new HitResult(hitEntity);
|
||||
}
|
||||
|
||||
if ((res != NULL) && (res->entity != NULL) &&
|
||||
res->entity->instanceof(eTYPE_PLAYER)) {
|
||||
std::shared_ptr<Player> player =
|
||||
std::dynamic_pointer_cast<Player>(res->entity);
|
||||
// 4J: Check for owner being null
|
||||
if (player->abilities.invulnerable ||
|
||||
((owner != NULL) &&
|
||||
(owner->instanceof(eTYPE_PLAYER) &&
|
||||
!std::dynamic_pointer_cast<Player>(owner)->canHarmPlayer(
|
||||
player)))) {
|
||||
res = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (res != NULL) {
|
||||
if (res->entity != NULL) {
|
||||
float pow = Mth::sqrt(xd * xd + yd * yd + zd * zd);
|
||||
|
|
@ -268,14 +292,17 @@ void Arrow::tick() {
|
|||
// unless we can cause some damage (this doesn't necessarily
|
||||
// mean that the arrow hit lowered their health) set targets on
|
||||
// fire first because we want cooked pork/chicken/steak
|
||||
if (this->isOnFire()) {
|
||||
if (isOnFire() && res->entity->GetType() != eTYPE_ENDERMAN) {
|
||||
res->entity->setOnFire(5);
|
||||
}
|
||||
|
||||
std::shared_ptr<Mob> mob =
|
||||
std::dynamic_pointer_cast<Mob>(res->entity);
|
||||
if (mob != NULL) {
|
||||
mob->arrowCount++;
|
||||
if (res->entity->instanceof(eTYPE_LIVINGENTITY)) {
|
||||
std::shared_ptr<LivingEntity> mob =
|
||||
std::dynamic_pointer_cast<LivingEntity>(res->entity);
|
||||
|
||||
if (!level->isClientSide) {
|
||||
mob->setArrowCount(mob->getArrowCount() + 1);
|
||||
}
|
||||
if (knockback > 0) {
|
||||
float pushLen = sqrt(xd * xd + zd * zd);
|
||||
if (pushLen > 0) {
|
||||
|
|
@ -289,15 +316,23 @@ void Arrow::tick() {
|
|||
ThornsEnchantment::doThornsAfterAttack(owner, mob,
|
||||
random);
|
||||
}
|
||||
|
||||
if (owner != NULL && res->entity != owner &&
|
||||
owner->GetType() == eTYPE_SERVERPLAYER) {
|
||||
std::dynamic_pointer_cast<ServerPlayer>(owner)
|
||||
->connection->send(std::shared_ptr<GameEventPacket>(
|
||||
new GameEventPacket(
|
||||
GameEventPacket::SUCCESSFUL_BOW_HIT, 0)));
|
||||
}
|
||||
}
|
||||
|
||||
// 4J : WESTY : For award, need to track if creeper was killed
|
||||
// by arrow from the player.
|
||||
if ((std::dynamic_pointer_cast<Player>(owner) !=
|
||||
NULL) && // arrow owner is a player
|
||||
(res->entity->isAlive() == false) && // target is now dead
|
||||
(std::dynamic_pointer_cast<Creeper>(res->entity) !=
|
||||
NULL)) // target is a creeper
|
||||
if (owner != NULL &&
|
||||
owner->instanceof(eTYPE_PLAYER) // arrow owner is a player
|
||||
&& !res->entity->isAlive() // target is now dead
|
||||
&& (res->entity->GetType() ==
|
||||
eTYPE_CREEPER)) // target is a creeper
|
||||
|
||||
{
|
||||
std::dynamic_pointer_cast<Player>(owner)->awardStat(
|
||||
|
|
@ -305,11 +340,9 @@ void Arrow::tick() {
|
|||
GenericStats::param_arrowKillCreeper());
|
||||
}
|
||||
|
||||
// 4J - sound change brought forward from 1.2.3
|
||||
level->playSound(shared_from_this(), eSoundType_RANDOM_BOW_HIT,
|
||||
1.0f,
|
||||
1.2f / (random->nextFloat() * 0.2f + 0.9f));
|
||||
remove();
|
||||
playSound(eSoundType_RANDOM_BOW_HIT, 1.0f,
|
||||
1.2f / (random->nextFloat() * 0.2f + 0.9f));
|
||||
if (res->entity->GetType() != eTYPE_ENDERDRAGON) remove();
|
||||
} else {
|
||||
xd *= -0.1f;
|
||||
yd *= -0.1f;
|
||||
|
|
@ -337,12 +370,16 @@ void Arrow::tick() {
|
|||
z -= (zd / dd) * 0.05f;
|
||||
}
|
||||
|
||||
// 4J - sound change brought forward from 1.2.3
|
||||
level->playSound(shared_from_this(), eSoundType_RANDOM_BOW_HIT,
|
||||
1.0f, 1.2f / (random->nextFloat() * 0.2f + 0.9f));
|
||||
playSound(eSoundType_RANDOM_BOW_HIT, 1.0f,
|
||||
1.2f / (random->nextFloat() * 0.2f + 0.9f));
|
||||
inGround = true;
|
||||
shakeTime = 7;
|
||||
setCritArrow(false);
|
||||
|
||||
if (lastTile != 0) {
|
||||
Tile::tiles[lastTile]->entityInside(level, xTile, yTile, zTile,
|
||||
shared_from_this());
|
||||
}
|
||||
}
|
||||
}
|
||||
delete res;
|
||||
|
|
@ -441,14 +478,16 @@ void Arrow::playerTouch(std::shared_ptr<Player> player) {
|
|||
}
|
||||
|
||||
if (bRemove) {
|
||||
level->playSound(
|
||||
shared_from_this(), eSoundType_RANDOM_POP, 0.2f,
|
||||
playSound(
|
||||
eSoundType_RANDOM_POP, 0.2f,
|
||||
((random->nextFloat() - random->nextFloat()) * 0.7f + 1.0f) * 2.0f);
|
||||
player->take(shared_from_this(), 1);
|
||||
remove();
|
||||
}
|
||||
}
|
||||
|
||||
bool Arrow::makeStepSound() { return false; }
|
||||
|
||||
float Arrow::getShadowHeightOffs() { return 0; }
|
||||
|
||||
void Arrow::setBaseDamage(double baseDamage) { this->baseDamage = baseDamage; }
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Entity.h"
|
||||
#include "../Projectile.h"
|
||||
|
||||
class Level;
|
||||
class CompoundTag;
|
||||
|
||||
class Arrow : public Entity {
|
||||
class Arrow : public Entity, public Projectile {
|
||||
public:
|
||||
eINSTANCEOF GetType() { return eTYPE_ARROW; }
|
||||
static Entity* create(Level* level) { return new Arrow(level); }
|
||||
|
|
@ -50,10 +51,10 @@ private:
|
|||
|
||||
public:
|
||||
Arrow(Level* level);
|
||||
Arrow(Level* level, std::shared_ptr<Mob> mob, std::shared_ptr<Mob> target,
|
||||
float power, float uncertainty);
|
||||
Arrow(Level* level, std::shared_ptr<LivingEntity> mob,
|
||||
std::shared_ptr<LivingEntity> target, float power, float uncertainty);
|
||||
Arrow(Level* level, double x, double y, double z);
|
||||
Arrow(Level* level, std::shared_ptr<Mob> mob, float power);
|
||||
Arrow(Level* level, std::shared_ptr<LivingEntity> mob, float power);
|
||||
|
||||
protected:
|
||||
virtual void defineSynchedData();
|
||||
|
|
@ -67,6 +68,11 @@ public:
|
|||
virtual void addAdditonalSaveData(CompoundTag* tag);
|
||||
virtual void readAdditionalSaveData(CompoundTag* tag);
|
||||
virtual void playerTouch(std::shared_ptr<Player> player);
|
||||
|
||||
protected:
|
||||
virtual bool makeStepSound();
|
||||
|
||||
public:
|
||||
virtual float getShadowHeightOffs();
|
||||
|
||||
void setBaseDamage(double baseDamage);
|
||||
|
|
|
|||
208
Minecraft.World/Entities/Mobs/Bat.cpp
Normal file
208
Minecraft.World/Entities/Mobs/Bat.cpp
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
#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.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 "Bat.h"
|
||||
|
||||
Bat::Bat(Level* level) : AmbientCreature(level) {
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
registerAttributes();
|
||||
setHealth(getMaxHealth());
|
||||
|
||||
targetPosition = NULL;
|
||||
|
||||
setSize(.5f, .9f);
|
||||
setResting(true);
|
||||
}
|
||||
|
||||
void Bat::defineSynchedData() {
|
||||
AmbientCreature::defineSynchedData();
|
||||
|
||||
entityData->define(DATA_ID_FLAGS, (char)0);
|
||||
}
|
||||
|
||||
float Bat::getSoundVolume() { return 0.1f; }
|
||||
|
||||
float Bat::getVoicePitch() { return AmbientCreature::getVoicePitch() * .95f; }
|
||||
|
||||
int Bat::getAmbientSound() {
|
||||
if (isResting() && random->nextInt(4) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return eSoundType_MOB_BAT_IDLE; //"mob.bat.idle";
|
||||
}
|
||||
|
||||
int Bat::getHurtSound() {
|
||||
return eSoundType_MOB_BAT_HURT; //"mob.bat.hurt";
|
||||
}
|
||||
|
||||
int Bat::getDeathSound() {
|
||||
return eSoundType_MOB_BAT_DEATH; //"mob.bat.death";
|
||||
}
|
||||
|
||||
bool Bat::isPushable() {
|
||||
// bats can't be pushed by other mobs
|
||||
return false;
|
||||
}
|
||||
|
||||
void Bat::doPush(std::shared_ptr<Entity> e) {
|
||||
// bats don't push other mobs
|
||||
}
|
||||
|
||||
void Bat::pushEntities() {
|
||||
// bats don't push other mobs
|
||||
}
|
||||
|
||||
void Bat::registerAttributes() {
|
||||
AmbientCreature::registerAttributes();
|
||||
|
||||
getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(6);
|
||||
}
|
||||
|
||||
bool Bat::isResting() {
|
||||
return (entityData->getByte(DATA_ID_FLAGS) & FLAG_RESTING) != 0;
|
||||
}
|
||||
|
||||
void Bat::setResting(bool value) {
|
||||
char current = entityData->getByte(DATA_ID_FLAGS);
|
||||
if (value) {
|
||||
entityData->set(DATA_ID_FLAGS, (char)(current | FLAG_RESTING));
|
||||
} else {
|
||||
entityData->set(DATA_ID_FLAGS, (char)(current & ~FLAG_RESTING));
|
||||
}
|
||||
}
|
||||
|
||||
bool Bat::useNewAi() { return true; }
|
||||
|
||||
void Bat::tick() {
|
||||
AmbientCreature::tick();
|
||||
|
||||
if (isResting()) {
|
||||
xd = yd = zd = 0;
|
||||
y = Mth::floor(y) + 1.0 - bbHeight;
|
||||
} else {
|
||||
yd *= .6f;
|
||||
}
|
||||
}
|
||||
|
||||
inline int signum(double x) { return (x > 0) - (x < 0); }
|
||||
|
||||
void Bat::newServerAiStep() {
|
||||
AmbientCreature::newServerAiStep();
|
||||
|
||||
if (isResting()) {
|
||||
if (!level->isSolidBlockingTile(Mth::floor(x), (int)y + 1,
|
||||
Mth::floor(z))) {
|
||||
setResting(false);
|
||||
level->levelEvent(nullptr, LevelEvent::SOUND_BAT_LIFTOFF, (int)x,
|
||||
(int)y, (int)z, 0);
|
||||
} else {
|
||||
if (random->nextInt(200) == 0) {
|
||||
yHeadRot = random->nextInt(360);
|
||||
}
|
||||
|
||||
if (level->getNearestPlayer(shared_from_this(), 4.0f) != NULL) {
|
||||
setResting(false);
|
||||
level->levelEvent(nullptr, LevelEvent::SOUND_BAT_LIFTOFF,
|
||||
(int)x, (int)y, (int)z, 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (targetPosition != NULL &&
|
||||
(!level->isEmptyTile(targetPosition->x, targetPosition->y,
|
||||
targetPosition->z) ||
|
||||
targetPosition->y < 1)) {
|
||||
delete targetPosition;
|
||||
targetPosition = NULL;
|
||||
}
|
||||
if (targetPosition == NULL || random->nextInt(30) == 0 ||
|
||||
targetPosition->distSqr((int)x, (int)y, (int)z) < 4) {
|
||||
delete targetPosition;
|
||||
targetPosition =
|
||||
new Pos((int)x + random->nextInt(7) - random->nextInt(7),
|
||||
(int)y + random->nextInt(6) - 2,
|
||||
(int)z + random->nextInt(7) - random->nextInt(7));
|
||||
}
|
||||
|
||||
double dx = (targetPosition->x + .5) - x;
|
||||
double dy = (targetPosition->y + .1) - y;
|
||||
double dz = (targetPosition->z + .5) - z;
|
||||
|
||||
xd = xd + (signum(dx) * .5f - xd) * .1f;
|
||||
yd = yd + (signum(dy) * .7f - yd) * .1f;
|
||||
zd = zd + (signum(dz) * .5f - zd) * .1f;
|
||||
|
||||
float yRotD = (float)(atan2(zd, xd) * 180 / PI) - 90;
|
||||
float rotDiff = Mth::wrapDegrees(yRotD - yRot);
|
||||
yya = .5f;
|
||||
yRot += rotDiff;
|
||||
|
||||
if (random->nextInt(100) == 0 &&
|
||||
level->isSolidBlockingTile(Mth::floor(x), (int)y + 1,
|
||||
Mth::floor(z))) {
|
||||
setResting(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Bat::makeStepSound() { return false; }
|
||||
|
||||
void Bat::causeFallDamage(float distance) {}
|
||||
|
||||
void Bat::checkFallDamage(double ya, bool onGround) {
|
||||
// this method is empty because flying creatures should
|
||||
// not trigger the "fallOn" tile calls (such as trampling crops)
|
||||
}
|
||||
|
||||
bool Bat::isIgnoringTileTriggers() { return true; }
|
||||
|
||||
bool Bat::hurt(DamageSource* source, float dmg) {
|
||||
if (isInvulnerable()) return false;
|
||||
if (!level->isClientSide) {
|
||||
if (isResting()) {
|
||||
setResting(false);
|
||||
}
|
||||
}
|
||||
|
||||
return AmbientCreature::hurt(source, dmg);
|
||||
}
|
||||
|
||||
void Bat::readAdditionalSaveData(CompoundTag* tag) {
|
||||
AmbientCreature::readAdditionalSaveData(tag);
|
||||
|
||||
entityData->set(DATA_ID_FLAGS, tag->getByte(L"BatFlags"));
|
||||
}
|
||||
|
||||
void Bat::addAdditonalSaveData(CompoundTag* entityTag) {
|
||||
AmbientCreature::addAdditonalSaveData(entityTag);
|
||||
|
||||
entityTag->putByte(L"BatFlags", entityData->getByte(DATA_ID_FLAGS));
|
||||
}
|
||||
|
||||
bool Bat::canSpawn() {
|
||||
int yt = Mth::floor(bb->y0);
|
||||
if (yt >= level->seaLevel) return false;
|
||||
|
||||
int xt = Mth::floor(x);
|
||||
int zt = Mth::floor(z);
|
||||
|
||||
int br = level->getRawBrightness(xt, yt, zt);
|
||||
int maxLight = 4;
|
||||
|
||||
if ((Calendar::GetDayOfMonth() + 1 == 10 &&
|
||||
Calendar::GetDayOfMonth() >= 20) ||
|
||||
(Calendar::GetMonth() + 1 == 11 && Calendar::GetMonth() <= 3)) {
|
||||
maxLight = 7;
|
||||
} else if (random->nextBoolean()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (br > random->nextInt(maxLight)) return false;
|
||||
|
||||
return AmbientCreature::canSpawn();
|
||||
}
|
||||
57
Minecraft.World/Entities/Mobs/Bat.h
Normal file
57
Minecraft.World/Entities/Mobs/Bat.h
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#pragma once
|
||||
|
||||
#include "AmbientCreature.h"
|
||||
|
||||
class Bat : public AmbientCreature {
|
||||
public:
|
||||
eINSTANCEOF GetType() { return eTYPE_BAT; }
|
||||
static Entity* create(Level* level) { return new Bat(level); }
|
||||
|
||||
private:
|
||||
static const int DATA_ID_FLAGS = 16;
|
||||
static const int FLAG_RESTING = 1;
|
||||
|
||||
Pos* targetPosition;
|
||||
|
||||
public:
|
||||
Bat(Level* level);
|
||||
|
||||
protected:
|
||||
virtual void defineSynchedData();
|
||||
virtual float getSoundVolume();
|
||||
virtual float getVoicePitch();
|
||||
virtual int getAmbientSound();
|
||||
virtual int getHurtSound();
|
||||
virtual int getDeathSound();
|
||||
|
||||
public:
|
||||
virtual bool isPushable();
|
||||
|
||||
protected:
|
||||
virtual void doPush(std::shared_ptr<Entity> e);
|
||||
virtual void pushEntities();
|
||||
virtual void registerAttributes();
|
||||
|
||||
public:
|
||||
virtual bool isResting();
|
||||
virtual void setResting(bool value);
|
||||
|
||||
protected:
|
||||
virtual bool useNewAi();
|
||||
|
||||
public:
|
||||
virtual void tick();
|
||||
|
||||
protected:
|
||||
virtual void newServerAiStep();
|
||||
virtual bool makeStepSound();
|
||||
virtual void causeFallDamage(float distance);
|
||||
virtual void checkFallDamage(double ya, bool onGround);
|
||||
virtual bool isIgnoringTileTriggers();
|
||||
|
||||
public:
|
||||
virtual bool hurt(DamageSource* source, float dmg);
|
||||
virtual void readAdditionalSaveData(CompoundTag* tag);
|
||||
virtual void addAdditonalSaveData(CompoundTag* entityTag);
|
||||
virtual bool canSpawn();
|
||||
};
|
||||
|
|
@ -5,6 +5,8 @@
|
|||
#include "../../Headers/net.minecraft.world.phys.h"
|
||||
#include "../../Headers/net.minecraft.world.item.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.attributes.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.monster.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.projectile.h"
|
||||
#include "../../Util/SharedConstants.h"
|
||||
#include "../../../Minecraft.Client/Textures/Textures.h"
|
||||
|
|
@ -15,17 +17,11 @@ Blaze::Blaze(Level* level) : Monster(level) {
|
|||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
health = getMaxHealth();
|
||||
|
||||
this->textureIdx = TN_MOB_BLAZE; // 4J Was "/mob/fire.png";
|
||||
registerAttributes();
|
||||
setHealth(getMaxHealth());
|
||||
|
||||
fireImmune = true;
|
||||
attackDamage = 6;
|
||||
xpReward = XP_REWARD_LARGE;
|
||||
// this.setSize(1.2f, 1.8f);
|
||||
|
||||
// 4J Default inits
|
||||
allowedHeightOffset = 0.5f;
|
||||
|
|
@ -33,7 +29,10 @@ Blaze::Blaze(Level* level) : Monster(level) {
|
|||
attackCounter = 0;
|
||||
}
|
||||
|
||||
int Blaze::getMaxHealth() { return 20; }
|
||||
void Blaze::registerAttributes() {
|
||||
Monster::registerAttributes();
|
||||
getAttribute(SharedMonsterAttributes::ATTACK_DAMAGE)->setBaseValue(6);
|
||||
}
|
||||
|
||||
void Blaze::defineSynchedData() {
|
||||
Monster::defineSynchedData();
|
||||
|
|
@ -67,7 +66,7 @@ void Blaze::aiStep() {
|
|||
|
||||
if (getAttackTarget() != NULL &&
|
||||
(getAttackTarget()->y + getAttackTarget()->getHeadHeight()) >
|
||||
(this->y + getHeadHeight() + allowedHeightOffset)) {
|
||||
(y + getHeadHeight() + allowedHeightOffset)) {
|
||||
yd = yd + (.3f - yd) * .3f;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,9 @@ private:
|
|||
|
||||
public:
|
||||
Blaze(Level* level);
|
||||
virtual int getMaxHealth();
|
||||
|
||||
protected:
|
||||
virtual void registerAttributes();
|
||||
virtual void defineSynchedData();
|
||||
virtual int getAmbientSound();
|
||||
virtual int getHurtSound();
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ bool Boat::makeStepSound() { return false; }
|
|||
void Boat::defineSynchedData() {
|
||||
entityData->define(DATA_ID_HURT, 0);
|
||||
entityData->define(DATA_ID_HURTDIR, 1);
|
||||
entityData->define(DATA_ID_DAMAGE, 0);
|
||||
entityData->define(DATA_ID_DAMAGE, 0.0f);
|
||||
}
|
||||
|
||||
AABB* Boat::getCollideAgainstBox(std::shared_ptr<Entity> entity) {
|
||||
|
|
@ -66,7 +66,8 @@ Boat::Boat(Level* level, double x, double y, double z) : Entity(level) {
|
|||
|
||||
double Boat::getRideHeight() { return bbHeight * 0.0f - 0.3f; }
|
||||
|
||||
bool Boat::hurt(DamageSource* source, int hurtDamage) {
|
||||
bool Boat::hurt(DamageSource* source, float hurtDamage) {
|
||||
if (isInvulnerable()) return false;
|
||||
if (level->isClientSide || removed) return true;
|
||||
|
||||
// 4J-JEV: Fix for #88212,
|
||||
|
|
@ -74,10 +75,11 @@ bool Boat::hurt(DamageSource* source, int hurtDamage) {
|
|||
if (dynamic_cast<EntityDamageSource*>(source) != NULL) {
|
||||
std::shared_ptr<Entity> attacker = source->getDirectEntity();
|
||||
|
||||
if (std::dynamic_pointer_cast<Player>(attacker) != NULL &&
|
||||
if (attacker->instanceof(eTYPE_PLAYER) &&
|
||||
!std::dynamic_pointer_cast<Player>(attacker)->isAllowedToHurtEntity(
|
||||
shared_from_this()))
|
||||
shared_from_this())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
setHurtDir(-getHurtDir());
|
||||
|
|
@ -95,14 +97,16 @@ bool Boat::hurt(DamageSource* source, int hurtDamage) {
|
|||
|
||||
// 4J Stu - Brought froward from 12w36 to fix #46611 - TU5: Gameplay:
|
||||
// Minecarts and boat requires more hits than one to be destroyed in
|
||||
// creative mode
|
||||
std::shared_ptr<Player> player =
|
||||
std::dynamic_pointer_cast<Player>(source->getEntity());
|
||||
if (player != NULL && player->abilities.instabuild) setDamage(100);
|
||||
// creative mode 4J-PB - Fix for XB1 #175735 - [CRASH] [Multi-Plat]: Code:
|
||||
// Gameplay: Placing a boat on harmful surfaces causes the game to crash
|
||||
bool creativePlayer = (source->getEntity() != NULL) &&
|
||||
source->getEntity()->instanceof(eTYPE_PLAYER) &&
|
||||
std::dynamic_pointer_cast<Player>(source->getEntity())
|
||||
->abilities.instabuild;
|
||||
|
||||
if (getDamage() > 20 * 2) {
|
||||
if (creativePlayer || getDamage() > 20 * 2) {
|
||||
if (rider.lock() != NULL) rider.lock()->ride(shared_from_this());
|
||||
spawnAtLocation(Item::boat_Id, 1, 0);
|
||||
if (!creativePlayer) spawnAtLocation(Item::boat_Id, 1, 0);
|
||||
remove();
|
||||
}
|
||||
return true;
|
||||
|
|
@ -139,9 +143,9 @@ void Boat::lerpTo(double x, double y, double z, float yRot, float xRot,
|
|||
lyr = yRot;
|
||||
lxr = xRot;
|
||||
|
||||
this->xd = lxd;
|
||||
this->yd = lyd;
|
||||
this->zd = lzd;
|
||||
xd = lxd;
|
||||
yd = lyd;
|
||||
zd = lzd;
|
||||
}
|
||||
|
||||
void Boat::lerpMotion(double xd, double yd, double zd) {
|
||||
|
|
@ -204,8 +208,8 @@ void Boat::tick() {
|
|||
xRot += (float)((lxr - xRot) / lSteps);
|
||||
|
||||
lSteps--;
|
||||
this->setPos(xt, yt, zt);
|
||||
this->setRot(yRot, xRot);
|
||||
setPos(xt, yt, zt);
|
||||
setRot(yRot, xRot);
|
||||
} else {
|
||||
#if 1
|
||||
// Original
|
||||
|
|
@ -216,7 +220,7 @@ void Boat::tick() {
|
|||
|
||||
// 4J Stu - Fix for various boat bugs, ensure that we check
|
||||
// collision on client-side movement
|
||||
this->move(xd, yd, zd);
|
||||
move(xd, yd, zd);
|
||||
|
||||
if (onGround) {
|
||||
xd *= 0.5f;
|
||||
|
|
@ -269,9 +273,17 @@ void Boat::tick() {
|
|||
yd += 0.007f;
|
||||
}
|
||||
|
||||
if (rider.lock() != NULL) {
|
||||
xd += rider.lock()->xd * acceleration;
|
||||
zd += rider.lock()->zd * acceleration;
|
||||
if (rider.lock() != NULL && rider.lock()->instanceof(eTYPE_LIVINGENTITY)) {
|
||||
std::shared_ptr<LivingEntity> livingRider =
|
||||
std::dynamic_pointer_cast<LivingEntity>(rider.lock());
|
||||
double std::forward = livingRider->yya;
|
||||
|
||||
if (std::forward > 0) {
|
||||
double riderXd = -sin(livingRider->yRot * PI / 180);
|
||||
double riderZd = cos(livingRider->yRot * PI / 180);
|
||||
xd += riderXd * acceleration * 0.05f;
|
||||
zd += riderZd * acceleration * 0.05f;
|
||||
}
|
||||
}
|
||||
|
||||
double curSpeed = sqrt(xd * xd + zd * zd);
|
||||
|
|
@ -300,7 +312,7 @@ void Boat::tick() {
|
|||
move(xd, yd, zd);
|
||||
|
||||
if ((horizontalCollision && lastSpeed > 0.20)) {
|
||||
if (!level->isClientSide) {
|
||||
if (!level->isClientSide && !removed) {
|
||||
remove();
|
||||
for (int i = 0; i < 3; i++) {
|
||||
spawnAtLocation(Tile::wood_Id, 1, 0);
|
||||
|
|
@ -334,7 +346,7 @@ void Boat::tick() {
|
|||
if (level->isClientSide) return;
|
||||
|
||||
std::vector<std::shared_ptr<Entity> >* entities =
|
||||
level->getEntities(shared_from_this(), this->bb->grow(0.2f, 0, 0.2f));
|
||||
level->getEntities(shared_from_this(), bb->grow(0.2f, 0, 0.2f));
|
||||
if (entities != NULL && !entities->empty()) {
|
||||
AUTO_VAR(itEnd, entities->end());
|
||||
for (AUTO_VAR(it, entities->begin()); it != itEnd; it++) {
|
||||
|
|
@ -353,14 +365,11 @@ void Boat::tick() {
|
|||
for (int j = 0; j < 2; j++) {
|
||||
int yy = Mth::floor(y) + j;
|
||||
int tile = level->getTile(xx, yy, zz);
|
||||
int data = level->getData(xx, yy, zz);
|
||||
|
||||
if (tile == Tile::topSnow_Id) {
|
||||
level->setTile(xx, yy, zz, 0);
|
||||
level->removeTile(xx, yy, zz);
|
||||
} else if (tile == Tile::waterLily_Id) {
|
||||
Tile::waterLily->spawnResources(level, xx, yy, zz, data, 0.3f,
|
||||
0);
|
||||
level->setTile(xx, yy, zz, 0);
|
||||
level->destroyTile(xx, yy, zz, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -388,9 +397,8 @@ float Boat::getShadowHeightOffs() { return 0; }
|
|||
std::wstring Boat::getName() { return L"Boat"; }
|
||||
|
||||
bool Boat::interact(std::shared_ptr<Player> player) {
|
||||
if (rider.lock() != NULL &&
|
||||
std::dynamic_pointer_cast<Player>(rider.lock()) != NULL &&
|
||||
rider.lock() != player)
|
||||
if ((rider.lock() != NULL) && rider.lock()->instanceof(eTYPE_PLAYER) &&
|
||||
(rider.lock() != player))
|
||||
return true;
|
||||
if (!level->isClientSide) {
|
||||
// 4J HEG - Fixed issue with player not being able to dismount boat
|
||||
|
|
@ -400,9 +408,9 @@ bool Boat::interact(std::shared_ptr<Player> player) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void Boat::setDamage(int damage) { entityData->set(DATA_ID_DAMAGE, damage); }
|
||||
void Boat::setDamage(float damage) { entityData->set(DATA_ID_DAMAGE, damage); }
|
||||
|
||||
int Boat::getDamage() { return entityData->getInteger(DATA_ID_DAMAGE); }
|
||||
float Boat::getDamage() { return entityData->getFloat(DATA_ID_DAMAGE); }
|
||||
|
||||
void Boat::setHurtTime(int hurtTime) {
|
||||
entityData->set(DATA_ID_HURT, hurtTime);
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ public:
|
|||
Boat(Level* level, double x, double y, double z);
|
||||
|
||||
virtual double getRideHeight();
|
||||
virtual bool hurt(DamageSource* source, int damage);
|
||||
virtual bool hurt(DamageSource* source, float damage);
|
||||
virtual void animateHurt();
|
||||
virtual bool isPickable();
|
||||
|
||||
|
|
@ -71,8 +71,8 @@ public:
|
|||
std::wstring getName();
|
||||
virtual bool interact(std::shared_ptr<Player> player);
|
||||
|
||||
virtual void setDamage(int damage);
|
||||
virtual int getDamage();
|
||||
virtual void setDamage(float damage);
|
||||
virtual float getDamage();
|
||||
virtual void setHurtTime(int hurtTime);
|
||||
virtual int getHurtTime();
|
||||
virtual void setHurtDir(int hurtDir);
|
||||
|
|
|
|||
|
|
@ -1,24 +0,0 @@
|
|||
#include "../../Platform/stdafx.h"
|
||||
#include "../BossMobPart.h"
|
||||
#include "BossMob.h"
|
||||
|
||||
BossMob::BossMob(Level* level) : Mob(level) {
|
||||
maxHealth = 100;
|
||||
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
health = getMaxHealth();
|
||||
}
|
||||
|
||||
int BossMob::getMaxHealth() { return maxHealth; }
|
||||
|
||||
bool BossMob::hurt(std::shared_ptr<BossMobPart> bossMobPart,
|
||||
DamageSource* source, int damage) {
|
||||
return hurt(source, damage);
|
||||
}
|
||||
|
||||
bool BossMob::hurt(DamageSource* source, int damage) { return false; }
|
||||
|
||||
bool BossMob::reallyHurt(DamageSource* source, int damage) {
|
||||
return Mob::hurt(source, damage);
|
||||
}
|
||||
|
|
@ -1,22 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include "../Mob.h"
|
||||
|
||||
class Level;
|
||||
class BossMobPart;
|
||||
|
||||
class BossMob : public Mob {
|
||||
protected:
|
||||
int maxHealth;
|
||||
|
||||
class BossMob {
|
||||
public:
|
||||
BossMob(Level* level);
|
||||
|
||||
virtual int getMaxHealth();
|
||||
virtual bool hurt(std::shared_ptr<BossMobPart> bossMobPart,
|
||||
DamageSource* source, int damage);
|
||||
virtual bool hurt(DamageSource* source, int damage);
|
||||
|
||||
protected:
|
||||
virtual bool reallyHurt(DamageSource* source, int damage);
|
||||
virtual float getMaxHealth() = 0;
|
||||
virtual float getHealth() = 0;
|
||||
virtual std::wstring getAName() = 0;
|
||||
};
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
#include "../../Platform/stdafx.h"
|
||||
#include "../../Util/SharedConstants.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.attributes.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.monster.h"
|
||||
#include "../../Headers/net.minecraft.world.effect.h"
|
||||
#include "../../Headers/net.minecraft.world.level.h"
|
||||
#include "../../Headers/net.minecraft.world.h"
|
||||
|
|
@ -9,19 +11,20 @@
|
|||
CaveSpider::CaveSpider(Level* level) : Spider(level) {
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
health = getMaxHealth();
|
||||
registerAttributes();
|
||||
|
||||
this->textureIdx = TN_MOB_CAVE_SPIDER; // 4J was "/mob/cavespider.png";
|
||||
this->setSize(0.7f, 0.5f);
|
||||
}
|
||||
|
||||
int CaveSpider::getMaxHealth() { return 12; }
|
||||
void CaveSpider::registerAttributes() {
|
||||
Spider::registerAttributes();
|
||||
|
||||
float CaveSpider::getModelScale() { return .7f; }
|
||||
getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(12);
|
||||
}
|
||||
|
||||
bool CaveSpider::doHurtTarget(std::shared_ptr<Entity> target) {
|
||||
if (Spider::doHurtTarget(target)) {
|
||||
if (std::dynamic_pointer_cast<Mob>(target) != NULL) {
|
||||
if (target->instanceof(eTYPE_LIVINGENTITY)) {
|
||||
int poisonTime = 0;
|
||||
if (level->difficulty <= Difficulty::EASY) {
|
||||
// No poison!
|
||||
|
|
@ -32,7 +35,7 @@ bool CaveSpider::doHurtTarget(std::shared_ptr<Entity> target) {
|
|||
}
|
||||
|
||||
if (poisonTime > 0) {
|
||||
std::dynamic_pointer_cast<Mob>(target)->addEffect(
|
||||
std::dynamic_pointer_cast<LivingEntity>(target)->addEffect(
|
||||
new MobEffectInstance(
|
||||
MobEffect::poison->id,
|
||||
poisonTime * SharedConstants::TICKS_PER_SECOND, 0));
|
||||
|
|
@ -44,6 +47,9 @@ bool CaveSpider::doHurtTarget(std::shared_ptr<Entity> target) {
|
|||
return false;
|
||||
}
|
||||
|
||||
void CaveSpider::finalizeMobSpawn() {
|
||||
MobGroupData* CaveSpider::finalizeMobSpawn(
|
||||
MobGroupData* groupData, int extraData /*= 0*/) // 4J Added extraData param
|
||||
{
|
||||
// do nothing
|
||||
return groupData;
|
||||
}
|
||||
|
|
@ -10,8 +10,12 @@ public:
|
|||
public:
|
||||
CaveSpider(Level* level);
|
||||
|
||||
virtual int getMaxHealth();
|
||||
virtual float getModelScale();
|
||||
protected:
|
||||
void registerAttributes();
|
||||
|
||||
public:
|
||||
virtual bool doHurtTarget(std::shared_ptr<Entity> target);
|
||||
void finalizeMobSpawn();
|
||||
MobGroupData* finalizeMobSpawn(
|
||||
MobGroupData* groupData,
|
||||
int extraData = 0); // 4J Added extraData param
|
||||
};
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
#include "../../Platform/stdafx.h"
|
||||
#include "../../Headers/com.mojang.nbt.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.attributes.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.goal.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.monster.h"
|
||||
#include "../../Headers/net.minecraft.world.level.tile.h"
|
||||
#include "../../Headers/net.minecraft.world.phys.h"
|
||||
#include "../../Headers/net.minecraft.world.level.h"
|
||||
|
|
@ -23,31 +25,32 @@ Chicken::Chicken(Level* level) : Animal(level) {
|
|||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
health = getMaxHealth();
|
||||
registerAttributes();
|
||||
setHealth(getMaxHealth());
|
||||
|
||||
_init();
|
||||
this->textureIdx = TN_MOB_CHICKEN; // 4J - was L"/mob/chicken.png";
|
||||
this->setSize(0.3f, 0.7f); // 4J Changed from 0.4 to 0.7 in 1.8.2
|
||||
setSize(0.3f, 0.7f); // 4J Changed from 0.4 to 0.7 in 1.8.2
|
||||
eggTime = random->nextInt(20 * 60 * 5) + 20 * 60 * 5;
|
||||
|
||||
float walkSpeed = 0.25f;
|
||||
goalSelector.addGoal(0, new FloatGoal(this));
|
||||
goalSelector.addGoal(1, new PanicGoal(this, 0.38f));
|
||||
goalSelector.addGoal(2, new BreedGoal(this, walkSpeed));
|
||||
goalSelector.addGoal(
|
||||
3, new TemptGoal(this, 0.25f, Item::seeds_wheat_Id, false));
|
||||
goalSelector.addGoal(4, new FollowParentGoal(this, 0.28f));
|
||||
goalSelector.addGoal(5, new RandomStrollGoal(this, walkSpeed));
|
||||
goalSelector.addGoal(1, new PanicGoal(this, 1.4));
|
||||
goalSelector.addGoal(2, new BreedGoal(this, 1.0));
|
||||
goalSelector.addGoal(3,
|
||||
new TemptGoal(this, 1.0, Item::seeds_wheat_Id, false));
|
||||
goalSelector.addGoal(4, new FollowParentGoal(this, 1.1));
|
||||
goalSelector.addGoal(5, new RandomStrollGoal(this, 1.0));
|
||||
goalSelector.addGoal(6, new LookAtPlayerGoal(this, typeid(Player), 6));
|
||||
goalSelector.addGoal(7, new RandomLookAroundGoal(this));
|
||||
}
|
||||
|
||||
bool Chicken::useNewAi() { return true; }
|
||||
|
||||
int Chicken::getMaxHealth() { return 4; }
|
||||
void Chicken::registerAttributes() {
|
||||
Animal::registerAttributes();
|
||||
|
||||
getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(4);
|
||||
getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED)->setBaseValue(0.25f);
|
||||
}
|
||||
|
||||
void Chicken::aiStep() {
|
||||
Animal::aiStep();
|
||||
|
|
@ -70,8 +73,8 @@ void Chicken::aiStep() {
|
|||
|
||||
if (!isBaby()) {
|
||||
if (!level->isClientSide && --eggTime <= 0) {
|
||||
level->playSound(
|
||||
shared_from_this(), eSoundType_MOB_CHICKENPLOP, 1.0f,
|
||||
playSound(
|
||||
eSoundType_MOB_CHICKENPLOP, 1.0f,
|
||||
(random->nextFloat() - random->nextFloat()) * 0.2f + 1.0f);
|
||||
spawnAtLocation(Item::egg->id, 1);
|
||||
eggTime = random->nextInt(20 * 60 * 5) + 20 * 60 * 5;
|
||||
|
|
@ -87,6 +90,10 @@ int Chicken::getHurtSound() { return eSoundType_MOB_CHICKEN_HURT; }
|
|||
|
||||
int Chicken::getDeathSound() { return eSoundType_MOB_CHICKEN_HURT; }
|
||||
|
||||
void Chicken::playStepSound(int xt, int yt, int zt, int t) {
|
||||
playSound(eSoundType_MOB_CHICKEN_STEP, 0.15f, 1);
|
||||
}
|
||||
|
||||
int Chicken::getDeathLoot() { return Item::feather->id; }
|
||||
|
||||
void Chicken::dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel) {
|
||||
|
|
@ -115,7 +122,7 @@ std::shared_ptr<AgableMob> Chicken::getBreedOffspring(
|
|||
|
||||
bool Chicken::isFood(std::shared_ptr<ItemInstance> itemInstance) {
|
||||
return (itemInstance->id == Item::seeds_wheat_Id) ||
|
||||
(itemInstance->id == Item::netherStalkSeeds_Id) ||
|
||||
(itemInstance->id == Item::netherwart_seeds_Id) ||
|
||||
(itemInstance->id == Item::seeds_melon_Id) ||
|
||||
(itemInstance->id == Item::seeds_pumpkin_Id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,11 @@ private:
|
|||
public:
|
||||
Chicken(Level* level);
|
||||
virtual bool useNewAi();
|
||||
virtual int getMaxHealth();
|
||||
|
||||
protected:
|
||||
void registerAttributes();
|
||||
|
||||
public:
|
||||
virtual void aiStep();
|
||||
|
||||
protected:
|
||||
|
|
@ -30,6 +34,7 @@ protected:
|
|||
virtual int getAmbientSound();
|
||||
virtual int getHurtSound();
|
||||
virtual int getDeathSound();
|
||||
virtual void playStepSound(int xt, int yt, int zt, int t);
|
||||
virtual int getDeathLoot();
|
||||
virtual void dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "../../Platform/stdafx.h"
|
||||
#include "../../Headers/com.mojang.nbt.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.goal.h"
|
||||
#include "../../Headers/net.minecraft.world.level.tile.h"
|
||||
|
|
@ -7,6 +8,7 @@
|
|||
#include "../../Headers/net.minecraft.world.level.h"
|
||||
#include "../../Headers/net.minecraft.world.item.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.player.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.monster.h"
|
||||
#include "../../Headers/net.minecraft.stats.h"
|
||||
#include "Cow.h"
|
||||
#include "../../../Minecraft.Client/Textures/Textures.h"
|
||||
|
|
@ -16,28 +18,30 @@ Cow::Cow(Level* level) : Animal(level) {
|
|||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
registerAttributes();
|
||||
setHealth(getMaxHealth());
|
||||
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
health = getMaxHealth();
|
||||
|
||||
this->textureIdx = TN_MOB_COW; // 4J was L"/mob/cow.png";
|
||||
this->setSize(0.9f, 1.3f);
|
||||
|
||||
getNavigation()->setAvoidWater(true);
|
||||
goalSelector.addGoal(0, new FloatGoal(this));
|
||||
goalSelector.addGoal(1, new PanicGoal(this, 0.38f));
|
||||
goalSelector.addGoal(2, new BreedGoal(this, 0.2f));
|
||||
goalSelector.addGoal(3, new TemptGoal(this, 0.25f, Item::wheat_Id, false));
|
||||
goalSelector.addGoal(4, new FollowParentGoal(this, 0.25f));
|
||||
goalSelector.addGoal(5, new RandomStrollGoal(this, 0.2f));
|
||||
goalSelector.addGoal(1, new PanicGoal(this, 2.0f));
|
||||
goalSelector.addGoal(2, new BreedGoal(this, 1.0f));
|
||||
goalSelector.addGoal(3, new TemptGoal(this, 1.25f, Item::wheat_Id, false));
|
||||
goalSelector.addGoal(4, new FollowParentGoal(this, 1.25f));
|
||||
goalSelector.addGoal(5, new RandomStrollGoal(this, 1.0f));
|
||||
goalSelector.addGoal(6, new LookAtPlayerGoal(this, typeid(Player), 6));
|
||||
goalSelector.addGoal(7, new RandomLookAroundGoal(this));
|
||||
}
|
||||
|
||||
bool Cow::useNewAi() { return true; }
|
||||
|
||||
int Cow::getMaxHealth() { return 10; }
|
||||
void Cow::registerAttributes() {
|
||||
Animal::registerAttributes();
|
||||
|
||||
getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(10);
|
||||
getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED)->setBaseValue(0.2f);
|
||||
}
|
||||
|
||||
int Cow::getAmbientSound() { return eSoundType_MOB_COW_AMBIENT; }
|
||||
|
||||
|
|
@ -45,6 +49,10 @@ int Cow::getHurtSound() { return eSoundType_MOB_COW_HURT; }
|
|||
|
||||
int Cow::getDeathSound() { return eSoundType_MOB_COW_HURT; }
|
||||
|
||||
void Cow::playStepSound(int xt, int yt, int zt, int t) {
|
||||
playSound(eSoundType_MOB_COW_STEP, 0.15f, 1);
|
||||
}
|
||||
|
||||
float Cow::getSoundVolume() { return 0.4f; }
|
||||
|
||||
int Cow::getDeathLoot() { return Item::leather->id; }
|
||||
|
|
@ -66,25 +74,27 @@ void Cow::dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel) {
|
|||
}
|
||||
}
|
||||
|
||||
bool Cow::interact(std::shared_ptr<Player> player) {
|
||||
bool Cow::mobInteract(std::shared_ptr<Player> player) {
|
||||
std::shared_ptr<ItemInstance> item = player->inventory->getSelected();
|
||||
if (item != NULL && item->id == Item::bucket_empty->id) {
|
||||
if (item != NULL && item->id == Item::bucket_empty->id &&
|
||||
!player->abilities.instabuild) {
|
||||
player->awardStat(GenericStats::cowsMilked(),
|
||||
GenericStats::param_cowsMilked());
|
||||
|
||||
if (--item->count <= 0) {
|
||||
if (item->count-- == 0) {
|
||||
player->inventory->setItem(
|
||||
player->inventory->selected,
|
||||
std::shared_ptr<ItemInstance>(new ItemInstance(Item::milk)));
|
||||
std::shared_ptr<ItemInstance>(
|
||||
new ItemInstance(Item::bucket_milk)));
|
||||
} else if (!player->inventory->add(std::shared_ptr<ItemInstance>(
|
||||
new ItemInstance(Item::milk)))) {
|
||||
player->drop(
|
||||
std::shared_ptr<ItemInstance>(new ItemInstance(Item::milk)));
|
||||
new ItemInstance(Item::bucket_milk)))) {
|
||||
player->drop(std::shared_ptr<ItemInstance>(
|
||||
new ItemInstance(Item::bucket_milk)));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
return Animal::interact(player);
|
||||
return Animal::mobInteract(player);
|
||||
}
|
||||
|
||||
std::shared_ptr<AgableMob> Cow::getBreedOffspring(
|
||||
|
|
|
|||
|
|
@ -13,18 +13,19 @@ public:
|
|||
public:
|
||||
Cow(Level* level);
|
||||
virtual bool useNewAi();
|
||||
virtual int getMaxHealth();
|
||||
|
||||
protected:
|
||||
virtual void registerAttributes();
|
||||
virtual int getAmbientSound();
|
||||
virtual int getHurtSound();
|
||||
virtual int getDeathSound();
|
||||
virtual float getSoundVolume();
|
||||
virtual int getDeathLoot();
|
||||
virtual void playStepSound(int xt, int yt, int zt, int t);
|
||||
virtual void dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel);
|
||||
|
||||
public:
|
||||
virtual bool interact(std::shared_ptr<Player> player);
|
||||
virtual bool mobInteract(std::shared_ptr<Player> player);
|
||||
virtual std::shared_ptr<AgableMob> getBreedOffspring(
|
||||
std::shared_ptr<AgableMob> target);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,11 +3,13 @@
|
|||
#include "../../Headers/net.minecraft.world.level.tile.h"
|
||||
#include "../../Headers/net.minecraft.world.item.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.attributes.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.goal.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.goal.target.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.navigation.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.animal.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.player.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.monster.h"
|
||||
#include "../../Headers/net.minecraft.world.damagesource.h"
|
||||
#include "../../Stats/GeneralStat.h"
|
||||
#include "Skeleton.h"
|
||||
|
|
@ -19,38 +21,53 @@
|
|||
void Creeper::_init() {
|
||||
swell = 0;
|
||||
oldSwell = 0;
|
||||
maxSwell = 30;
|
||||
explosionRadius = 3;
|
||||
}
|
||||
|
||||
Creeper::Creeper(Level* level) : Monster(level) {
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
health = getMaxHealth();
|
||||
registerAttributes();
|
||||
setHealth(getMaxHealth());
|
||||
|
||||
_init();
|
||||
|
||||
this->textureIdx = TN_MOB_CREEPER; // 4J was L"/mob/creeper.png";
|
||||
|
||||
goalSelector.addGoal(1, new FloatGoal(this));
|
||||
goalSelector.addGoal(2, new SwellGoal(this));
|
||||
goalSelector.addGoal(
|
||||
3, new AvoidPlayerGoal(this, typeid(Ozelot), 6, 0.25f, 0.30f));
|
||||
goalSelector.addGoal(4, new MeleeAttackGoal(this, 0.25f, false));
|
||||
goalSelector.addGoal(5, new RandomStrollGoal(this, 0.20f));
|
||||
3, new AvoidPlayerGoal(this, typeid(Ocelot), 6, 1.0, 1.2));
|
||||
goalSelector.addGoal(4, new MeleeAttackGoal(this, 1.0, false));
|
||||
goalSelector.addGoal(5, new RandomStrollGoal(this, 0.8));
|
||||
goalSelector.addGoal(6, new LookAtPlayerGoal(this, typeid(Player), 8));
|
||||
goalSelector.addGoal(6, new RandomLookAroundGoal(this));
|
||||
|
||||
targetSelector.addGoal(
|
||||
1, new NearestAttackableTargetGoal(this, typeid(Player), 16, 0, true));
|
||||
1, new NearestAttackableTargetGoal(this, typeid(Player), 0, true));
|
||||
targetSelector.addGoal(2, new HurtByTargetGoal(this, false));
|
||||
}
|
||||
|
||||
void Creeper::registerAttributes() {
|
||||
Monster::registerAttributes();
|
||||
|
||||
getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED)->setBaseValue(0.25f);
|
||||
}
|
||||
|
||||
bool Creeper::useNewAi() { return true; }
|
||||
|
||||
int Creeper::getMaxHealth() { return 20; }
|
||||
int Creeper::getMaxFallDistance() {
|
||||
if (getTarget() == NULL) return 3;
|
||||
// As long as they survive the fall they should try.
|
||||
return 3 + (int)(getHealth() - 1);
|
||||
}
|
||||
|
||||
void Creeper::causeFallDamage(float distance) {
|
||||
Monster::causeFallDamage(distance);
|
||||
|
||||
swell += distance * 1.5f;
|
||||
if (swell > maxSwell - 5) swell = maxSwell - 5;
|
||||
}
|
||||
|
||||
void Creeper::defineSynchedData() {
|
||||
Monster::defineSynchedData();
|
||||
|
|
@ -63,12 +80,17 @@ void Creeper::addAdditonalSaveData(CompoundTag* entityTag) {
|
|||
Monster::addAdditonalSaveData(entityTag);
|
||||
if (entityData->getByte(DATA_IS_POWERED) == 1)
|
||||
entityTag->putBoolean(L"powered", true);
|
||||
entityTag->putShort(L"Fuse", (short)maxSwell);
|
||||
entityTag->putByte(L"ExplosionRadius", (uint8_t)explosionRadius);
|
||||
}
|
||||
|
||||
void Creeper::readAdditionalSaveData(CompoundTag* tag) {
|
||||
Monster::readAdditionalSaveData(tag);
|
||||
entityData->set(DATA_IS_POWERED,
|
||||
(uint8_t)(tag->getBoolean(L"powered") ? 1 : 0));
|
||||
if (tag->contains(L"Fuse")) maxSwell = tag->getShort(L"Fuse");
|
||||
if (tag->contains(L"ExplosionRadius"))
|
||||
explosionRadius = tag->getByte(L"ExplosionRadius");
|
||||
}
|
||||
|
||||
void Creeper::tick() {
|
||||
|
|
@ -76,21 +98,20 @@ void Creeper::tick() {
|
|||
if (isAlive()) {
|
||||
int swellDir = getSwellDir();
|
||||
if (swellDir > 0 && swell == 0) {
|
||||
level->playSound(shared_from_this(), eSoundType_RANDOM_FUSE, 1,
|
||||
0.5f);
|
||||
playSound(eSoundType_RANDOM_FUSE, 1, 0.5f);
|
||||
}
|
||||
swell += swellDir;
|
||||
if (swell < 0) swell = 0;
|
||||
if (swell >= MAX_SWELL) {
|
||||
swell = MAX_SWELL;
|
||||
if (swell >= maxSwell) {
|
||||
swell = maxSwell;
|
||||
if (!level->isClientSide) {
|
||||
bool destroyBlocks =
|
||||
true; // level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING);
|
||||
bool destroyBlocks = level->getGameRules()->getBoolean(
|
||||
GameRules::RULE_MOBGRIEFING);
|
||||
if (isPowered())
|
||||
level->explode(shared_from_this(), x, y, z, 6,
|
||||
destroyBlocks);
|
||||
level->explode(shared_from_this(), x, y, z,
|
||||
explosionRadius * 2, destroyBlocks);
|
||||
else
|
||||
level->explode(shared_from_this(), x, y, z, 3,
|
||||
level->explode(shared_from_this(), x, y, z, explosionRadius,
|
||||
destroyBlocks);
|
||||
remove();
|
||||
}
|
||||
|
|
@ -106,14 +127,20 @@ int Creeper::getDeathSound() { return eSoundType_MOB_CREEPER_DEATH; }
|
|||
void Creeper::die(DamageSource* source) {
|
||||
Monster::die(source);
|
||||
|
||||
if (std::dynamic_pointer_cast<Skeleton>(source->getEntity()) != NULL) {
|
||||
spawnAtLocation(Item::record_01_Id + random->nextInt(12), 1);
|
||||
if (source->getEntity() != NULL &&
|
||||
source->getEntity()->instanceof(eTYPE_SKELETON)) {
|
||||
int recordId =
|
||||
Item::record_01_Id +
|
||||
random->nextInt(Item::record_12_Id - Item::record_01_Id + 1);
|
||||
spawnAtLocation(recordId, 1);
|
||||
}
|
||||
|
||||
std::shared_ptr<Player> player =
|
||||
std::dynamic_pointer_cast<Player>(source->getEntity());
|
||||
if ((std::dynamic_pointer_cast<Arrow>(source->getDirectEntity()) != NULL) &&
|
||||
(player != NULL)) {
|
||||
if (source->getDirectEntity() != NULL &&
|
||||
source->getDirectEntity()->instanceof(eTYPE_ARROW) &&
|
||||
source->getEntity() != NULL &&
|
||||
source->getEntity()->instanceof(eTYPE_PLAYER)) {
|
||||
std::shared_ptr<Player> player =
|
||||
std::dynamic_pointer_cast<Player>(source->getEntity());
|
||||
player->awardStat(GenericStats::archer(), GenericStats::param_archer());
|
||||
}
|
||||
}
|
||||
|
|
@ -123,10 +150,10 @@ bool Creeper::doHurtTarget(std::shared_ptr<Entity> target) { return true; }
|
|||
bool Creeper::isPowered() { return entityData->getByte(DATA_IS_POWERED) == 1; }
|
||||
|
||||
float Creeper::getSwelling(float a) {
|
||||
return (oldSwell + (swell - oldSwell) * a) / (MAX_SWELL - 2);
|
||||
return (oldSwell + (swell - oldSwell) * a) / (maxSwell - 2);
|
||||
}
|
||||
|
||||
int Creeper::getDeathLoot() { return Item::sulphur->id; }
|
||||
int Creeper::getDeathLoot() { return Item::gunpowder_Id; }
|
||||
|
||||
int Creeper::getSwellDir() {
|
||||
return (int)(char)entityData->getByte(DATA_SWELL_DIR);
|
||||
|
|
|
|||
|
|
@ -14,20 +14,26 @@ private:
|
|||
static const int DATA_SWELL_DIR = 16;
|
||||
static const int DATA_IS_POWERED = 17;
|
||||
|
||||
int swell;
|
||||
int oldSwell;
|
||||
|
||||
static const int MAX_SWELL = 30;
|
||||
int swell;
|
||||
int maxSwell;
|
||||
int explosionRadius;
|
||||
|
||||
void _init();
|
||||
|
||||
public:
|
||||
Creeper(Level* level);
|
||||
|
||||
protected:
|
||||
void registerAttributes();
|
||||
|
||||
public:
|
||||
virtual bool useNewAi();
|
||||
virtual int getMaxHealth();
|
||||
|
||||
virtual int getMaxFallDistance();
|
||||
|
||||
protected:
|
||||
virtual void causeFallDamage(float distance);
|
||||
virtual void defineSynchedData();
|
||||
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ DragonFireball::DragonFireball(Level* level) : Fireball(level) {
|
|||
setSize(5 / 16.0f, 5 / 16.0f);
|
||||
}
|
||||
|
||||
DragonFireball::DragonFireball(Level* level, std::shared_ptr<Mob> mob,
|
||||
DragonFireball::DragonFireball(Level* level, std::shared_ptr<LivingEntity> mob,
|
||||
double xa, double ya, double za)
|
||||
: Fireball(level, mob, xa, ya, za) {
|
||||
setSize(5 / 16.0f, 5 / 16.0f);
|
||||
|
|
@ -31,14 +31,15 @@ void DragonFireball::onHit(HitResult* res) {
|
|||
if (!level->isClientSide) {
|
||||
AABB* aoe = bb->grow(SPLASH_RANGE, SPLASH_RANGE / 2, SPLASH_RANGE);
|
||||
std::vector<std::shared_ptr<Entity> >* entitiesOfClass =
|
||||
level->getEntitiesOfClass(typeid(Mob), aoe);
|
||||
level->getEntitiesOfClass(typeid(LivingEntity), aoe);
|
||||
|
||||
if (entitiesOfClass != NULL && !entitiesOfClass->empty()) {
|
||||
// for (Entity e : entitiesOfClass)
|
||||
for (AUTO_VAR(it, entitiesOfClass->begin());
|
||||
it != entitiesOfClass->end(); ++it) {
|
||||
// std::shared_ptr<Entity> e = *it;
|
||||
std::shared_ptr<Mob> e = std::dynamic_pointer_cast<Mob>(*it);
|
||||
// shared_ptr<Entity> e = *it;
|
||||
std::shared_ptr<LivingEntity> e =
|
||||
std::dynamic_pointer_cast<LivingEntity>(*it);
|
||||
double dist = distanceToSqr(e);
|
||||
if (dist < SPLASH_RANGE_SQ) {
|
||||
double scale = 1.0 - (sqrt(dist) / SPLASH_RANGE);
|
||||
|
|
@ -60,12 +61,10 @@ void DragonFireball::onHit(HitResult* res) {
|
|||
|
||||
bool DragonFireball::isPickable() { return false; }
|
||||
|
||||
bool DragonFireball::hurt(DamageSource* source, int damage) { return false; }
|
||||
|
||||
bool DragonFireball::shouldBurn() { return false; }
|
||||
|
||||
int DragonFireball::getIcon() { return 15 + 14 * 16; }
|
||||
bool DragonFireball::hurt(DamageSource* source, float damage) { return false; }
|
||||
|
||||
ePARTICLE_TYPE DragonFireball::getTrailParticleType() {
|
||||
return eParticleType_dragonbreath;
|
||||
}
|
||||
}
|
||||
|
||||
bool DragonFireball::shouldBurn() { return false; }
|
||||
|
|
@ -17,8 +17,8 @@ private:
|
|||
|
||||
public:
|
||||
DragonFireball(Level* level);
|
||||
DragonFireball(Level* level, std::shared_ptr<Mob> mob, double xa, double ya,
|
||||
double za);
|
||||
DragonFireball(Level* level, std::shared_ptr<LivingEntity> mob, double xa,
|
||||
double ya, double za);
|
||||
DragonFireball(Level* level, double x, double y, double z, double xa,
|
||||
double ya, double za);
|
||||
|
||||
|
|
@ -27,12 +27,11 @@ protected:
|
|||
|
||||
public:
|
||||
virtual bool isPickable();
|
||||
virtual bool hurt(DamageSource* source, int damage);
|
||||
|
||||
virtual bool shouldBurn();
|
||||
virtual int getIcon();
|
||||
virtual bool hurt(DamageSource* source, float damage);
|
||||
|
||||
protected:
|
||||
// 4J Added TU9
|
||||
virtual ePARTICLE_TYPE getTrailParticleType();
|
||||
|
||||
virtual bool shouldBurn();
|
||||
};
|
||||
|
|
@ -50,7 +50,7 @@ void EnderCrystal::tick() {
|
|||
int yt = Mth::floor(y);
|
||||
int zt = Mth::floor(z);
|
||||
if (level->getTile(xt, yt, zt) != Tile::fire_Id) {
|
||||
level->setTile(xt, yt, zt, Tile::fire_Id);
|
||||
level->setTileAndUpdate(xt, yt, zt, Tile::fire_Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -63,13 +63,13 @@ float EnderCrystal::getShadowHeightOffs() { return 0; }
|
|||
|
||||
bool EnderCrystal::isPickable() { return true; }
|
||||
|
||||
bool EnderCrystal::hurt(DamageSource* source, int damage) {
|
||||
bool EnderCrystal::hurt(DamageSource* source, float damage) {
|
||||
if (isInvulnerable()) return false;
|
||||
|
||||
// 4J-PB - if the owner of the source is the enderdragon, then ignore it
|
||||
// (where the dragon's fireball hits an endercrystal)
|
||||
std::shared_ptr<EnderDragon> sourceIsDragon =
|
||||
std::dynamic_pointer_cast<EnderDragon>(source->getEntity());
|
||||
|
||||
if (sourceIsDragon != NULL) {
|
||||
if (source->getEntity() != NULL &&
|
||||
source->getEntity()->instanceof(eTYPE_ENDERDRAGON)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,5 +38,5 @@ protected:
|
|||
public:
|
||||
virtual float getShadowHeightOffs();
|
||||
virtual bool isPickable();
|
||||
virtual bool hurt(DamageSource* source, int damage);
|
||||
virtual bool hurt(DamageSource* source, float damage);
|
||||
};
|
||||
|
|
@ -2,7 +2,9 @@
|
|||
#include "../../Headers/net.minecraft.world.level.h"
|
||||
#include "../../Headers/net.minecraft.world.level.tile.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.attributes.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.boss.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.monster.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.projectile.h"
|
||||
#include "../../Headers/net.minecraft.world.phys.h"
|
||||
#include "../../Headers/net.minecraft.world.damagesource.h"
|
||||
|
|
@ -48,10 +50,8 @@ void EnderDragon::_init() {
|
|||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
health = getMaxHealth();
|
||||
registerAttributes();
|
||||
setHealth(getMaxHealth());
|
||||
|
||||
xTarget = yTarget = zTarget = 0.0;
|
||||
posPointer = -1;
|
||||
|
|
@ -86,33 +86,9 @@ void EnderDragon::_init() {
|
|||
m_currentPath = NULL;
|
||||
}
|
||||
|
||||
EnderDragon::EnderDragon(Level* level) : BossMob(level) {
|
||||
EnderDragon::EnderDragon(Level* level) : Mob(level) {
|
||||
_init();
|
||||
|
||||
head = std::shared_ptr<BossMobPart>(new BossMobPart(this, L"head", 6, 6));
|
||||
neck = std::shared_ptr<BossMobPart>(
|
||||
new BossMobPart(this, L"neck", 6, 6)); // 4J Added
|
||||
body = std::shared_ptr<BossMobPart>(new BossMobPart(this, L"body", 8, 8));
|
||||
tail1 = std::shared_ptr<BossMobPart>(new BossMobPart(this, L"tail", 4, 4));
|
||||
tail2 = std::shared_ptr<BossMobPart>(new BossMobPart(this, L"tail", 4, 4));
|
||||
tail3 = std::shared_ptr<BossMobPart>(new BossMobPart(this, L"tail", 4, 4));
|
||||
wing1 = std::shared_ptr<BossMobPart>(new BossMobPart(this, L"wing", 4, 4));
|
||||
wing2 = std::shared_ptr<BossMobPart>(new BossMobPart(this, L"wing", 4, 4));
|
||||
|
||||
subEntities.push_back(head);
|
||||
subEntities.push_back(neck); // 4J Added
|
||||
subEntities.push_back(body);
|
||||
subEntities.push_back(tail1);
|
||||
subEntities.push_back(tail2);
|
||||
subEntities.push_back(tail3);
|
||||
subEntities.push_back(wing1);
|
||||
subEntities.push_back(wing2);
|
||||
|
||||
maxHealth = 200;
|
||||
setHealth(maxHealth);
|
||||
|
||||
this->textureIdx =
|
||||
TN_MOB_ENDERDRAGON; // 4J was "/mob/enderdragon/ender.png";
|
||||
setSize(16, 8);
|
||||
|
||||
noPhysics = true;
|
||||
|
|
@ -125,6 +101,44 @@ EnderDragon::EnderDragon(Level* level) : BossMob(level) {
|
|||
noCulling = true;
|
||||
}
|
||||
|
||||
// 4J - split off from ctor so we can use shared_from_this()
|
||||
void EnderDragon::AddParts() {
|
||||
head = std::shared_ptr<MultiEntityMobPart>(new MultiEntityMobPart(
|
||||
std::dynamic_pointer_cast<MultiEntityMob>(shared_from_this()), L"head",
|
||||
6, 6));
|
||||
neck = std::shared_ptr<MultiEntityMobPart>(new MultiEntityMobPart(
|
||||
std::dynamic_pointer_cast<MultiEntityMob>(shared_from_this()), L"neck",
|
||||
6,
|
||||
6)); // 4J Added
|
||||
body = std::shared_ptr<MultiEntityMobPart>(new MultiEntityMobPart(
|
||||
std::dynamic_pointer_cast<MultiEntityMob>(shared_from_this()), L"body",
|
||||
8, 8));
|
||||
tail1 = std::shared_ptr<MultiEntityMobPart>(new MultiEntityMobPart(
|
||||
std::dynamic_pointer_cast<MultiEntityMob>(shared_from_this()), L"tail",
|
||||
4, 4));
|
||||
tail2 = std::shared_ptr<MultiEntityMobPart>(new MultiEntityMobPart(
|
||||
std::dynamic_pointer_cast<MultiEntityMob>(shared_from_this()), L"tail",
|
||||
4, 4));
|
||||
tail3 = std::shared_ptr<MultiEntityMobPart>(new MultiEntityMobPart(
|
||||
std::dynamic_pointer_cast<MultiEntityMob>(shared_from_this()), L"tail",
|
||||
4, 4));
|
||||
wing1 = std::shared_ptr<MultiEntityMobPart>(new MultiEntityMobPart(
|
||||
std::dynamic_pointer_cast<MultiEntityMob>(shared_from_this()), L"wing",
|
||||
4, 4));
|
||||
wing2 = std::shared_ptr<MultiEntityMobPart>(new MultiEntityMobPart(
|
||||
std::dynamic_pointer_cast<MultiEntityMob>(shared_from_this()), L"wing",
|
||||
4, 4));
|
||||
|
||||
subEntities.push_back(head);
|
||||
subEntities.push_back(neck); // 4J Added
|
||||
subEntities.push_back(body);
|
||||
subEntities.push_back(tail1);
|
||||
subEntities.push_back(tail2);
|
||||
subEntities.push_back(tail3);
|
||||
subEntities.push_back(wing1);
|
||||
subEntities.push_back(wing2);
|
||||
}
|
||||
|
||||
EnderDragon::~EnderDragon() {
|
||||
if (m_nodes->data != NULL) {
|
||||
for (unsigned int i = 0; i < m_nodes->length; ++i) {
|
||||
|
|
@ -136,10 +150,14 @@ EnderDragon::~EnderDragon() {
|
|||
if (m_currentPath != NULL) delete m_currentPath;
|
||||
}
|
||||
|
||||
void EnderDragon::defineSynchedData() {
|
||||
BossMob::defineSynchedData();
|
||||
void EnderDragon::registerAttributes() {
|
||||
Mob::registerAttributes();
|
||||
|
||||
entityData->define(DATA_ID_SYNCHED_HEALTH, maxHealth);
|
||||
getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(200);
|
||||
}
|
||||
|
||||
void EnderDragon::defineSynchedData() {
|
||||
Mob::defineSynchedData();
|
||||
|
||||
// 4J Added for new dragon behaviour
|
||||
entityData->define(DATA_ID_SYNCHED_ACTION,
|
||||
|
|
@ -147,7 +165,7 @@ void EnderDragon::defineSynchedData() {
|
|||
}
|
||||
|
||||
void EnderDragon::getLatencyPos(doubleArray result, int step, float a) {
|
||||
if (health <= 0) {
|
||||
if (getHealth() <= 0) {
|
||||
a = 0;
|
||||
}
|
||||
|
||||
|
|
@ -173,21 +191,20 @@ void EnderDragon::getLatencyPos(doubleArray result, int step, float a) {
|
|||
}
|
||||
|
||||
void EnderDragon::aiStep() {
|
||||
if (!level->isClientSide) {
|
||||
entityData->set(DATA_ID_SYNCHED_HEALTH, health);
|
||||
} else {
|
||||
if (level->isClientSide) {
|
||||
// 4J Stu - If saved when dead we need to make sure that the actual
|
||||
// health is updated correctly on the client Fix for TU9: Content:
|
||||
// Gameplay: Enderdragon respawns after loading game which was
|
||||
// previously saved at point of hes death
|
||||
health = getSynchedHealth();
|
||||
setHealth(getHealth());
|
||||
|
||||
float flap = Mth::cos(flapTime * PI * 2);
|
||||
float oldFlap = Mth::cos(oFlapTime * PI * 2);
|
||||
|
||||
if (oldFlap <= -0.3f && flap >= -0.3f) {
|
||||
level->playLocalSound(x, y, z, eSoundType_MOB_ENDERDRAGON_MOVE, 1,
|
||||
0.8f + random->nextFloat() * .3f, 100.0f);
|
||||
0.8f + random->nextFloat() * .3f, false,
|
||||
100.0f);
|
||||
}
|
||||
// play a growl every now and then
|
||||
if (!(getSynchedAction() == e_EnderdragonAction_Sitting_Flaming ||
|
||||
|
|
@ -197,7 +214,7 @@ void EnderDragon::aiStep() {
|
|||
if (m_iGrowlTimer < 0) {
|
||||
level->playLocalSound(x, y, z, eSoundType_MOB_ENDERDRAGON_GROWL,
|
||||
0.5f, 0.8f + random->nextFloat() * .3f,
|
||||
100.0f);
|
||||
false, 100.0f);
|
||||
m_iGrowlTimer = 200 + (random->nextInt(200));
|
||||
}
|
||||
}
|
||||
|
|
@ -205,7 +222,7 @@ void EnderDragon::aiStep() {
|
|||
|
||||
oFlapTime = flapTime;
|
||||
|
||||
if (health <= 0) {
|
||||
if (getHealth() <= 0) {
|
||||
// level.addParticle("explode", x + random.nextFloat() *
|
||||
// bbWidth * 2 - bbWidth, y + random.nextFloat() * bbHeight,
|
||||
// z + random.nextFloat() * bbWidth * 2 - bbWidth, 0, 0, 0);
|
||||
|
|
@ -352,7 +369,7 @@ void EnderDragon::aiStep() {
|
|||
// AP - changed this to use playLocalSound because no sound could be
|
||||
// heard with playSound (cos it's a stub function)
|
||||
level->playLocalSound(x, y, z, eSoundType_MOB_ENDERDRAGON_GROWL,
|
||||
0.5f, 0.8f + random->nextFloat() * .3f,
|
||||
0.5f, 0.8f + random->nextFloat() * .3f, false,
|
||||
100.0f);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -447,10 +464,10 @@ void EnderDragon::aiStep() {
|
|||
|
||||
for (AUTO_VAR(it, targets->begin()); it != targets->end();
|
||||
++it) {
|
||||
std::shared_ptr<Mob> e =
|
||||
std::dynamic_pointer_cast<Mob>(*it);
|
||||
if (e != NULL) {
|
||||
if ((*it)->instanceof(eTYPE_LIVINGENTITY)) {
|
||||
// app.DebugPrintf("Attacking entity with acid\n");
|
||||
std::shared_ptr<LivingEntity> e =
|
||||
std::dynamic_pointer_cast<LivingEntity>(*it);
|
||||
e->hurt(DamageSource::dragonbreath, 2);
|
||||
}
|
||||
}
|
||||
|
|
@ -685,7 +702,7 @@ void EnderDragon::aiStep() {
|
|||
|
||||
// Curls/straightens the tail
|
||||
for (int i = 0; i < 3; i++) {
|
||||
std::shared_ptr<BossMobPart> part = nullptr;
|
||||
std::shared_ptr<MultiEntityMobPart> part = nullptr;
|
||||
|
||||
if (i == 0) part = tail1;
|
||||
if (i == 1) part = tail2;
|
||||
|
|
@ -782,12 +799,12 @@ void EnderDragon::checkCrystals() {
|
|||
if (nearestCrystal != NULL) {
|
||||
if (nearestCrystal->removed) {
|
||||
if (!level->isClientSide) {
|
||||
hurt(head, DamageSource::explosion, 10);
|
||||
hurt(head, DamageSource::explosion(NULL), 10);
|
||||
}
|
||||
|
||||
nearestCrystal = nullptr;
|
||||
} else if (tickCount % 10 == 0) {
|
||||
if (health < maxHealth) health++;
|
||||
if (getHealth() < getMaxHealth()) setHealth(getHealth() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -836,9 +853,10 @@ void EnderDragon::knockBack(std::vector<std::shared_ptr<Entity> >* entities) {
|
|||
|
||||
// for (Entity e : entities)
|
||||
for (AUTO_VAR(it, entities->begin()); it != entities->end(); ++it) {
|
||||
std::shared_ptr<Mob> e = std::dynamic_pointer_cast<Mob>(*it);
|
||||
if (e != NULL) //(e instanceof Mob)
|
||||
if ((*it)->instanceof(eTYPE_LIVINGENTITY)) //(e instanceof Mob)
|
||||
{
|
||||
std::shared_ptr<LivingEntity> e =
|
||||
std::dynamic_pointer_cast<LivingEntity>(*it);
|
||||
double xd = e->x - xm;
|
||||
double zd = e->z - zm;
|
||||
double dd = xd * xd + zd * zd;
|
||||
|
|
@ -850,12 +868,13 @@ void EnderDragon::knockBack(std::vector<std::shared_ptr<Entity> >* entities) {
|
|||
void EnderDragon::hurt(std::vector<std::shared_ptr<Entity> >* entities) {
|
||||
// for (int i = 0; i < entities->size(); i++)
|
||||
for (AUTO_VAR(it, entities->begin()); it != entities->end(); ++it) {
|
||||
std::shared_ptr<Mob> e =
|
||||
std::dynamic_pointer_cast<Mob>(*it); // entities.get(i);
|
||||
if (e != NULL) //(e instanceof Mob)
|
||||
if ((*it)->instanceof(eTYPE_LIVINGENTITY)) //(e instanceof Mob)
|
||||
{
|
||||
std::shared_ptr<LivingEntity> e =
|
||||
std::dynamic_pointer_cast<LivingEntity>(
|
||||
*it); // entities.get(i);
|
||||
DamageSource* damageSource = DamageSource::mobAttack(
|
||||
std::dynamic_pointer_cast<Mob>(shared_from_this()));
|
||||
std::dynamic_pointer_cast<LivingEntity>(shared_from_this()));
|
||||
e->hurt(damageSource, 10);
|
||||
delete damageSource;
|
||||
}
|
||||
|
|
@ -919,7 +938,8 @@ void EnderDragon::findNewTarget() {
|
|||
// setSynchedAction(e_EnderdragonAction_Sitting_Flaming);
|
||||
// #if PRINT_DRAGON_STATE_CHANGE_MESSAGES
|
||||
// app.DebugPrintf("Dragon action is now:
|
||||
//SittingFlaming\n"); #endif m_actionTicks = FLAME_TICKS;
|
||||
// SittingFlaming\n"); #endif m_actionTicks =
|
||||
// FLAME_TICKS;
|
||||
|
||||
m_flameAttacks = 0;
|
||||
setSynchedAction(e_EnderdragonAction_Sitting_Scanning);
|
||||
|
|
@ -1066,12 +1086,13 @@ bool EnderDragon::checkWalls(AABB* bb) {
|
|||
int t = level->getTile(x, y, z);
|
||||
// 4J Stu - Don't remove fire
|
||||
if (t == 0 || t == Tile::fire_Id) {
|
||||
} else if (t == Tile::obsidian_Id || t == Tile::whiteStone_Id ||
|
||||
t == Tile::unbreakable_Id) {
|
||||
} else if (t == Tile::obsidian_Id || t == Tile::endStone_Id ||
|
||||
t == Tile::unbreakable_Id ||
|
||||
!level->getGameRules()->getBoolean(
|
||||
GameRules::RULE_MOBGRIEFING)) {
|
||||
hitWall = true;
|
||||
} else {
|
||||
destroyedTile = true;
|
||||
level->setTile(x, y, z, 0);
|
||||
destroyedTile = level->removeTile(x, y, z) || destroyedTile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1087,9 +1108,9 @@ bool EnderDragon::checkWalls(AABB* bb) {
|
|||
return hitWall;
|
||||
}
|
||||
|
||||
bool EnderDragon::hurt(std::shared_ptr<BossMobPart> bossMobPart,
|
||||
DamageSource* source, int damage) {
|
||||
if (bossMobPart != head) {
|
||||
bool EnderDragon::hurt(std::shared_ptr<MultiEntityMobPart> MultiEntityMobPart,
|
||||
DamageSource* source, float damage) {
|
||||
if (MultiEntityMobPart != head) {
|
||||
damage = damage / 4 + 1;
|
||||
}
|
||||
|
||||
|
|
@ -1102,18 +1123,19 @@ bool EnderDragon::hurt(std::shared_ptr<BossMobPart> bossMobPart,
|
|||
// zTarget = z - cc1 * 5 + (random->nextFloat() - 0.5f) * 2;
|
||||
// attackTarget = NULL;
|
||||
|
||||
if (source == DamageSource::explosion ||
|
||||
(std::dynamic_pointer_cast<Player>(source->getEntity()) != NULL)) {
|
||||
int healthBefore = health;
|
||||
if (source->getEntity() != NULL &&
|
||||
source->getEntity()->instanceof(eTYPE_PLAYER) ||
|
||||
source->isExplosion()) {
|
||||
int healthBefore = getHealth();
|
||||
reallyHurt(source, damage);
|
||||
|
||||
// if(!level->isClientSide) app.DebugPrintf("Health is now %d\n",
|
||||
// health);
|
||||
if (health <= 0 &&
|
||||
if (getHealth() <= 0 &&
|
||||
!(getSynchedAction() == e_EnderdragonAction_Sitting_Flaming ||
|
||||
getSynchedAction() == e_EnderdragonAction_Sitting_Scanning ||
|
||||
getSynchedAction() == e_EnderdragonAction_Sitting_Attacking)) {
|
||||
health = 1;
|
||||
setHealth(1);
|
||||
|
||||
if (setSynchedAction(e_EnderdragonAction_LandingApproach)) {
|
||||
if (m_currentPath != NULL) {
|
||||
|
|
@ -1132,7 +1154,7 @@ bool EnderDragon::hurt(std::shared_ptr<BossMobPart> bossMobPart,
|
|||
if (getSynchedAction() == e_EnderdragonAction_Sitting_Flaming ||
|
||||
getSynchedAction() == e_EnderdragonAction_Sitting_Scanning ||
|
||||
getSynchedAction() == e_EnderdragonAction_Sitting_Attacking) {
|
||||
m_sittingDamageReceived += healthBefore - health;
|
||||
m_sittingDamageReceived += healthBefore - getHealth();
|
||||
|
||||
if (m_sittingDamageReceived >
|
||||
(SITTING_ALLOWED_DAMAGE_PERCENTAGE * getMaxHealth())) {
|
||||
|
|
@ -1148,11 +1170,17 @@ bool EnderDragon::hurt(std::shared_ptr<BossMobPart> bossMobPart,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool EnderDragon::hurt(DamageSource* source, float damage) { return false; }
|
||||
|
||||
bool EnderDragon::reallyHurt(DamageSource* source, float damage) {
|
||||
return Mob::hurt(source, damage);
|
||||
}
|
||||
|
||||
void EnderDragon::tickDeath() {
|
||||
if (getSynchedAction() != e_EnderdragonAction_Sitting_Flaming &&
|
||||
getSynchedAction() != e_EnderdragonAction_Sitting_Scanning &&
|
||||
getSynchedAction() != e_EnderdragonAction_Sitting_Attacking) {
|
||||
if (!level->isClientSide) health = 1;
|
||||
if (!level->isClientSide) setHealth(1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1175,10 +1203,8 @@ void EnderDragon::tickDeath() {
|
|||
}
|
||||
}
|
||||
if (dragonDeathTime == 1) {
|
||||
// level->globalLevelEvent(LevelEvent::SOUND_DRAGON_DEATH, (int) x,
|
||||
// (int) y, (int) z, 0);
|
||||
level->levelEvent(LevelEvent::SOUND_DRAGON_DEATH, (int)x, (int)y,
|
||||
(int)z, 0);
|
||||
level->globalLevelEvent(LevelEvent::SOUND_DRAGON_DEATH, (int)x,
|
||||
(int)y, (int)z, 0);
|
||||
}
|
||||
}
|
||||
move(0, 0.1f, 0);
|
||||
|
|
@ -1224,15 +1250,18 @@ void EnderDragon::spawnExitPortal(int x, int z) {
|
|||
if (yy < y) {
|
||||
if (d > r - 1 - 0.5) {
|
||||
} else {
|
||||
level->setTile(xx, yy, zz, Tile::unbreakable_Id);
|
||||
level->setTileAndUpdate(xx, yy, zz,
|
||||
Tile::unbreakable_Id);
|
||||
}
|
||||
} else if (yy > y) {
|
||||
level->setTile(xx, yy, zz, 0);
|
||||
level->setTileAndUpdate(xx, yy, zz, 0);
|
||||
} else {
|
||||
if (d > r - 1 - 0.5) {
|
||||
level->setTile(xx, yy, zz, Tile::unbreakable_Id);
|
||||
level->setTileAndUpdate(xx, yy, zz,
|
||||
Tile::unbreakable_Id);
|
||||
} else {
|
||||
level->setTile(xx, yy, zz, Tile::endPortalTile_Id);
|
||||
level->setTileAndUpdate(xx, yy, zz,
|
||||
Tile::endPortalTile_Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1240,15 +1269,15 @@ void EnderDragon::spawnExitPortal(int x, int z) {
|
|||
}
|
||||
}
|
||||
|
||||
level->setTile(x, y + 0, z, Tile::unbreakable_Id);
|
||||
level->setTile(x, y + 1, z, Tile::unbreakable_Id);
|
||||
level->setTile(x, y + 2, z, Tile::unbreakable_Id);
|
||||
level->setTile(x - 1, y + 2, z, Tile::torch_Id);
|
||||
level->setTile(x + 1, y + 2, z, Tile::torch_Id);
|
||||
level->setTile(x, y + 2, z - 1, Tile::torch_Id);
|
||||
level->setTile(x, y + 2, z + 1, Tile::torch_Id);
|
||||
level->setTile(x, y + 3, z, Tile::unbreakable_Id);
|
||||
level->setTile(x, y + 4, z, Tile::dragonEgg_Id);
|
||||
level->setTileAndUpdate(x, y + 0, z, Tile::unbreakable_Id);
|
||||
level->setTileAndUpdate(x, y + 1, z, Tile::unbreakable_Id);
|
||||
level->setTileAndUpdate(x, y + 2, z, Tile::unbreakable_Id);
|
||||
level->setTileAndUpdate(x - 1, y + 2, z, Tile::torch_Id);
|
||||
level->setTileAndUpdate(x + 1, y + 2, z, Tile::torch_Id);
|
||||
level->setTileAndUpdate(x, y + 2, z - 1, Tile::torch_Id);
|
||||
level->setTileAndUpdate(x, y + 2, z + 1, Tile::torch_Id);
|
||||
level->setTileAndUpdate(x, y + 3, z, Tile::unbreakable_Id);
|
||||
level->setTileAndUpdate(x, y + 4, z, Tile::dragonEgg_Id);
|
||||
|
||||
// 4J-PB - The podium can be floating with nothing under it, so put some
|
||||
// whiteStone under it if this is the case
|
||||
|
|
@ -1256,7 +1285,7 @@ void EnderDragon::spawnExitPortal(int x, int z) {
|
|||
for (int xx = x - (r - 1); xx <= x + (r - 1); xx++) {
|
||||
for (int zz = z - (r - 1); zz <= z + (r - 1); zz++) {
|
||||
if (level->isEmptyTile(xx, yy, zz)) {
|
||||
level->setTile(xx, yy, zz, Tile::whiteStone_Id);
|
||||
level->setTileAndUpdate(xx, yy, zz, Tile::endStone_Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1273,14 +1302,18 @@ std::vector<std::shared_ptr<Entity> >* EnderDragon::getSubEntities() {
|
|||
|
||||
bool EnderDragon::isPickable() { return false; }
|
||||
|
||||
// Fix for TU9 Enderdragon sound hits being the player sound hits - moved this
|
||||
// forward from later version
|
||||
int EnderDragon::getHurtSound() { return eSoundType_MOB_ENDERDRAGON_HIT; }
|
||||
Level* EnderDragon::getLevel() { return level; }
|
||||
|
||||
int EnderDragon::getSynchedHealth() {
|
||||
return entityData->getInteger(DATA_ID_SYNCHED_HEALTH);
|
||||
int EnderDragon::getAmbientSound() {
|
||||
return eSoundType_MOB_ENDERDRAGON_GROWL; //"mob.enderdragon.growl";
|
||||
}
|
||||
|
||||
int EnderDragon::getHurtSound() {
|
||||
return eSoundType_MOB_ENDERDRAGON_HIT; //"mob.enderdragon.hit";
|
||||
}
|
||||
|
||||
float EnderDragon::getSoundVolume() { return 5; }
|
||||
|
||||
// 4J Added for new dragon behaviour
|
||||
bool EnderDragon::setSynchedAction(EEnderdragonAction action,
|
||||
bool force /*= false*/) {
|
||||
|
|
@ -1411,7 +1444,8 @@ void EnderDragon::handleCrystalDestroyed(DamageSource* source) {
|
|||
app.DebugPrintf("Dragon action is now: LandingApproach\n");
|
||||
#endif
|
||||
}
|
||||
} else if (std::dynamic_pointer_cast<Player>(source->getEntity()) != NULL) {
|
||||
} else if (source->getEntity() != NULL &&
|
||||
source->getEntity()->instanceof(eTYPE_PLAYER)) {
|
||||
if (setSynchedAction(e_EnderdragonAction_StrafePlayer)) {
|
||||
attackTarget =
|
||||
std::dynamic_pointer_cast<Player>(source->getEntity());
|
||||
|
|
@ -1696,7 +1730,7 @@ void EnderDragon::addAdditonalSaveData(CompoundTag* entityTag) {
|
|||
entityTag->putShort(L"RemainingCrystals", m_remainingCrystalsCount);
|
||||
entityTag->putInt(L"DragonState", (int)getSynchedAction());
|
||||
|
||||
BossMob::addAdditonalSaveData(entityTag);
|
||||
Mob::addAdditonalSaveData(entityTag);
|
||||
}
|
||||
|
||||
void EnderDragon::readAdditionalSaveData(CompoundTag* tag) {
|
||||
|
|
@ -1708,7 +1742,7 @@ void EnderDragon::readAdditionalSaveData(CompoundTag* tag) {
|
|||
if (tag->contains(L"DragonState"))
|
||||
setSynchedAction((EEnderdragonAction)tag->getInt(L"DragonState"), true);
|
||||
|
||||
BossMob::readAdditionalSaveData(tag);
|
||||
Mob::readAdditionalSaveData(tag);
|
||||
}
|
||||
|
||||
float EnderDragon::getTilt(float a) {
|
||||
|
|
|
|||
|
|
@ -1,21 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
#include "BossMob.h"
|
||||
#include "MultiEntityMob.h"
|
||||
#include "../Enemy.h"
|
||||
|
||||
class BossMobPart;
|
||||
class MultiEntityMobPart;
|
||||
class EnderCrystal;
|
||||
class Node;
|
||||
class BinaryHeap;
|
||||
class Path;
|
||||
|
||||
class EnderDragon : public BossMob {
|
||||
class EnderDragon : public Mob,
|
||||
public BossMob,
|
||||
public MultiEntityMob,
|
||||
public Enemy {
|
||||
public:
|
||||
eINSTANCEOF GetType() { return eTYPE_ENDERDRAGON; };
|
||||
static Entity* create(Level* level) { return new EnderDragon(level); }
|
||||
|
||||
private:
|
||||
static const int DATA_ID_SYNCHED_HEALTH = 16;
|
||||
|
||||
// 4J Added for new behaviours
|
||||
static const int DATA_ID_SYNCHED_ACTION = 17;
|
||||
|
||||
|
|
@ -28,16 +30,16 @@ public:
|
|||
double positions[positionsLength][3];
|
||||
int posPointer;
|
||||
|
||||
// BossMobPart[] subEntities;
|
||||
// MultiEntityMobPart[] subEntities;
|
||||
std::vector<std::shared_ptr<Entity> > subEntities;
|
||||
std::shared_ptr<BossMobPart> head;
|
||||
std::shared_ptr<BossMobPart> neck; // 4J Added
|
||||
std::shared_ptr<BossMobPart> body;
|
||||
std::shared_ptr<BossMobPart> tail1;
|
||||
std::shared_ptr<BossMobPart> tail2;
|
||||
std::shared_ptr<BossMobPart> tail3;
|
||||
std::shared_ptr<BossMobPart> wing1;
|
||||
std::shared_ptr<BossMobPart> wing2;
|
||||
std::shared_ptr<MultiEntityMobPart> head;
|
||||
std::shared_ptr<MultiEntityMobPart> neck; // 4J Added
|
||||
std::shared_ptr<MultiEntityMobPart> body;
|
||||
std::shared_ptr<MultiEntityMobPart> tail1;
|
||||
std::shared_ptr<MultiEntityMobPart> tail2;
|
||||
std::shared_ptr<MultiEntityMobPart> tail3;
|
||||
std::shared_ptr<MultiEntityMobPart> wing1;
|
||||
std::shared_ptr<MultiEntityMobPart> wing2;
|
||||
|
||||
float oFlapTime;
|
||||
float flapTime;
|
||||
|
|
@ -113,9 +115,11 @@ private:
|
|||
|
||||
public:
|
||||
EnderDragon(Level* level);
|
||||
void AddParts();
|
||||
virtual ~EnderDragon();
|
||||
|
||||
protected:
|
||||
virtual void registerAttributes();
|
||||
virtual void defineSynchedData();
|
||||
|
||||
public:
|
||||
|
|
@ -123,7 +127,7 @@ public:
|
|||
virtual void aiStep();
|
||||
|
||||
private:
|
||||
using BossMob::hurt;
|
||||
using MultiEntityMob::hurt;
|
||||
|
||||
void checkCrystals();
|
||||
void checkAttack();
|
||||
|
|
@ -134,10 +138,12 @@ private:
|
|||
bool checkWalls(AABB* bb);
|
||||
|
||||
public:
|
||||
virtual bool hurt(std::shared_ptr<BossMobPart> bossMobPart,
|
||||
DamageSource* source, int damage);
|
||||
virtual bool hurt(std::shared_ptr<MultiEntityMobPart> MultiEntityMobPart,
|
||||
DamageSource* source, float damage);
|
||||
virtual bool hurt(DamageSource* source, float damage);
|
||||
|
||||
protected:
|
||||
virtual bool reallyHurt(DamageSource* source, float damage);
|
||||
virtual void tickDeath();
|
||||
|
||||
private:
|
||||
|
|
@ -145,12 +151,16 @@ private:
|
|||
|
||||
protected:
|
||||
virtual void checkDespawn();
|
||||
virtual int getHurtSound();
|
||||
|
||||
public:
|
||||
virtual std::vector<std::shared_ptr<Entity> >* getSubEntities();
|
||||
virtual bool isPickable();
|
||||
virtual int getSynchedHealth();
|
||||
Level* getLevel();
|
||||
|
||||
protected:
|
||||
int getAmbientSound();
|
||||
int getHurtSound();
|
||||
float getSoundVolume();
|
||||
|
||||
private:
|
||||
// 4J added for new dragon behaviour
|
||||
|
|
@ -179,4 +189,8 @@ public:
|
|||
double getHeadPartYRotDiff(int partIndex, doubleArray bodyPos,
|
||||
doubleArray partPos);
|
||||
Vec3* getHeadLookVector(float a);
|
||||
|
||||
virtual std::wstring getAName() { return app.GetString(IDS_ENDERDRAGON); };
|
||||
virtual float getHealth() { return LivingEntity::getHealth(); };
|
||||
virtual float getMaxHealth() { return LivingEntity::getMaxHealth(); };
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#include "../../Platform/stdafx.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.player.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.attributes.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.monster.h"
|
||||
#include "../../Headers/net.minecraft.world.item.h"
|
||||
#include "../../Headers/net.minecraft.world.level.h"
|
||||
#include "../../Headers/net.minecraft.world.level.tile.h"
|
||||
|
|
@ -10,6 +12,11 @@
|
|||
#include "../../../Minecraft.Client/Textures/Textures.h"
|
||||
#include "EnderMan.h"
|
||||
|
||||
AttributeModifier* EnderMan::SPEED_MODIFIER_ATTACKING =
|
||||
(new AttributeModifier(eModifierId_MOB_ENDERMAN_ATTACKSPEED, 6.2f,
|
||||
AttributeModifier::OPERATION_ADDITION))
|
||||
->setSerialize(false);
|
||||
|
||||
bool EnderMan::MAY_TAKE[256];
|
||||
|
||||
void EnderMan::staticCtor() {
|
||||
|
|
@ -20,8 +27,8 @@ void EnderMan::staticCtor() {
|
|||
MAY_TAKE[Tile::gravel_Id] = true;
|
||||
MAY_TAKE[Tile::flower_Id] = true;
|
||||
MAY_TAKE[Tile::rose_Id] = true;
|
||||
MAY_TAKE[Tile::mushroom1_Id] = true;
|
||||
MAY_TAKE[Tile::mushroom2_Id] = true;
|
||||
MAY_TAKE[Tile::mushroom_brown_Id] = true;
|
||||
MAY_TAKE[Tile::mushroom_red_Id] = true;
|
||||
MAY_TAKE[Tile::tnt_Id] = true;
|
||||
MAY_TAKE[Tile::cactus_Id] = true;
|
||||
MAY_TAKE[Tile::clay_Id] = true;
|
||||
|
|
@ -35,25 +42,27 @@ EnderMan::EnderMan(Level* level) : Monster(level) {
|
|||
// ensure that the derived version of the function is called Brought forward
|
||||
// from 1.2.3
|
||||
this->defineSynchedData();
|
||||
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
health = getMaxHealth();
|
||||
registerAttributes();
|
||||
setHealth(getMaxHealth());
|
||||
|
||||
// 4J initialisors
|
||||
teleportTime = 0;
|
||||
aggroTime = 0;
|
||||
lastAttackTarget = nullptr;
|
||||
aggroedByPlayer = false;
|
||||
|
||||
this->textureIdx = TN_MOB_ENDERMAN; // 4J was "/mob/enderman.png";
|
||||
runSpeed = 0.2f;
|
||||
attackDamage = 7;
|
||||
setSize(0.6f, 2.9f);
|
||||
footSize = 1;
|
||||
}
|
||||
|
||||
int EnderMan::getMaxHealth() { return 40; }
|
||||
void EnderMan::registerAttributes() {
|
||||
Monster::registerAttributes();
|
||||
|
||||
getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(40);
|
||||
getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED)->setBaseValue(0.3f);
|
||||
getAttribute(SharedMonsterAttributes::ATTACK_DAMAGE)->setBaseValue(7);
|
||||
}
|
||||
|
||||
// Brought forward from 1.2.3
|
||||
void EnderMan::defineSynchedData() {
|
||||
Monster::defineSynchedData();
|
||||
|
||||
|
|
@ -85,6 +94,10 @@ std::shared_ptr<Entity> EnderMan::findAttackTarget() {
|
|||
level->getNearestAttackablePlayer(shared_from_this(), 64);
|
||||
if (player != NULL) {
|
||||
if (isLookingAtMe(player)) {
|
||||
aggroedByPlayer = true;
|
||||
if (aggroTime == 0)
|
||||
level->playEntitySound(player, eSoundType_MOB_ENDERMAN_STARE, 1,
|
||||
1);
|
||||
if (aggroTime++ == 5) {
|
||||
aggroTime = 0;
|
||||
setCreepy(true);
|
||||
|
|
@ -116,42 +129,53 @@ bool EnderMan::isLookingAtMe(std::shared_ptr<Player> player) {
|
|||
}
|
||||
|
||||
void EnderMan::aiStep() {
|
||||
if (this->isInWaterOrRain()) hurt(DamageSource::drown, 1);
|
||||
if (isInWaterOrRain()) hurt(DamageSource::drown, 1);
|
||||
|
||||
runSpeed = attackTarget != NULL ? 6.5f : 0.3f;
|
||||
if (lastAttackTarget != attackTarget) {
|
||||
AttributeInstance* speed =
|
||||
getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED);
|
||||
speed->removeModifier(SPEED_MODIFIER_ATTACKING);
|
||||
|
||||
if (attackTarget != NULL) {
|
||||
speed->addModifier(
|
||||
new AttributeModifier(*SPEED_MODIFIER_ATTACKING));
|
||||
}
|
||||
}
|
||||
|
||||
lastAttackTarget = attackTarget;
|
||||
|
||||
if (!level->isClientSide) {
|
||||
if (getCarryingTile() == 0) {
|
||||
if (random->nextInt(20) == 0) {
|
||||
int xt = Mth::floor(x - 2 + random->nextDouble() * 4);
|
||||
int yt = Mth::floor(y + random->nextDouble() * 3);
|
||||
int zt = Mth::floor(z - 2 + random->nextDouble() * 4);
|
||||
int t = level->getTile(xt, yt, zt);
|
||||
// if (t > 0 && Tile::tiles[t]->isCubeShaped())
|
||||
if (EnderMan::MAY_TAKE[t]) // 4J - Brought forward from 1.2.3
|
||||
{
|
||||
setCarryingTile(level->getTile(xt, yt, zt));
|
||||
setCarryingData(level->getData(xt, yt, zt));
|
||||
level->setTile(xt, yt, zt, 0);
|
||||
if (level->getGameRules()->getBoolean(GameRules::RULE_MOBGRIEFING)) {
|
||||
if (getCarryingTile() == 0) {
|
||||
if (random->nextInt(20) == 0) {
|
||||
int xt = Mth::floor(x - 2 + random->nextDouble() * 4);
|
||||
int yt = Mth::floor(y + random->nextDouble() * 3);
|
||||
int zt = Mth::floor(z - 2 + random->nextDouble() * 4);
|
||||
int t = level->getTile(xt, yt, zt);
|
||||
if (MAY_TAKE[t]) {
|
||||
setCarryingTile(level->getTile(xt, yt, zt));
|
||||
setCarryingData(level->getData(xt, yt, zt));
|
||||
level->setTileAndUpdate(xt, yt, zt, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (random->nextInt(2000) == 0) {
|
||||
int xt = Mth::floor(x - 1 + random->nextDouble() * 2);
|
||||
int yt = Mth::floor(y + random->nextDouble() * 2);
|
||||
int zt = Mth::floor(z - 1 + random->nextDouble() * 2);
|
||||
int t = level->getTile(xt, yt, zt);
|
||||
int bt = level->getTile(xt, yt - 1, zt);
|
||||
if (t == 0 && bt > 0 && Tile::tiles[bt]->isCubeShaped()) {
|
||||
level->setTileAndData(xt, yt, zt, getCarryingTile(),
|
||||
getCarryingData());
|
||||
setCarryingTile(0);
|
||||
} else {
|
||||
if (random->nextInt(2000) == 0) {
|
||||
int xt = Mth::floor(x - 1 + random->nextDouble() * 2);
|
||||
int yt = Mth::floor(y + random->nextDouble() * 2);
|
||||
int zt = Mth::floor(z - 1 + random->nextDouble() * 2);
|
||||
int t = level->getTile(xt, yt, zt);
|
||||
int bt = level->getTile(xt, yt - 1, zt);
|
||||
if (t == 0 && bt > 0 && Tile::tiles[bt]->isCubeShaped()) {
|
||||
level->setTileAndData(xt, yt, zt, getCarryingTile(),
|
||||
getCarryingData(),
|
||||
Tile::UPDATE_ALL);
|
||||
setCarryingTile(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4J - Brought forward particles from 1.2.3
|
||||
for (int i = 0; i < 2; i++) {
|
||||
level->addParticle(
|
||||
eParticleType_ender, x + (random->nextDouble() - 0.5) * bbWidth,
|
||||
|
|
@ -164,34 +188,38 @@ void EnderMan::aiStep() {
|
|||
if (level->isDay() && !level->isClientSide) {
|
||||
float br = getBrightness(1);
|
||||
if (br > 0.5f) {
|
||||
if (level->canSeeSky(Mth::floor(x), Mth::floor(y), Mth::floor(z)) &&
|
||||
if (level->canSeeSky(Mth::floor(x), (int)floor(y + 0.5),
|
||||
Mth::floor(z)) &&
|
||||
random->nextFloat() * 30 < (br - 0.4f) * 2) {
|
||||
// 4J - Brought forward behaviour change from 1.2.3
|
||||
// onFire = 20 * 15;
|
||||
attackTarget = nullptr;
|
||||
setCreepy(false);
|
||||
aggroedByPlayer = false;
|
||||
teleport();
|
||||
}
|
||||
}
|
||||
}
|
||||
// 4J Brought forward behaviour change from 1.2.3
|
||||
|
||||
if (isInWaterOrRain() || isOnFire()) {
|
||||
attackTarget = nullptr;
|
||||
setCreepy(false);
|
||||
aggroedByPlayer = false;
|
||||
teleport();
|
||||
}
|
||||
|
||||
if (isCreepy() && !aggroedByPlayer && random->nextInt(100) == 0) {
|
||||
setCreepy(false);
|
||||
}
|
||||
|
||||
jumping = false;
|
||||
if (attackTarget != NULL) {
|
||||
this->lookAt(attackTarget, 100, 100);
|
||||
lookAt(attackTarget, 100, 100);
|
||||
}
|
||||
|
||||
if (!level->isClientSide && isAlive()) {
|
||||
if (attackTarget != NULL) {
|
||||
if (std::dynamic_pointer_cast<Player>(attackTarget) != NULL &&
|
||||
if (attackTarget->instanceof(eTYPE_PLAYER) &&
|
||||
isLookingAtMe(
|
||||
std::dynamic_pointer_cast<Player>(attackTarget))) {
|
||||
xxa = yya = 0;
|
||||
runSpeed = 0;
|
||||
if (attackTarget->distanceToSqr(shared_from_this()) < 4 * 4) {
|
||||
teleport();
|
||||
}
|
||||
|
|
@ -278,15 +306,10 @@ bool EnderMan::teleport(double xx, double yy, double zz) {
|
|||
double _z =
|
||||
zo + (z - zo) * d + (random->nextDouble() - 0.5) * bbWidth * 2;
|
||||
|
||||
// 4J - Brought forward particle change from 1.2.3
|
||||
// level->addParticle(eParticleType_largesmoke, _x, _y, _z, xa, ya,
|
||||
// za);
|
||||
level->addParticle(eParticleType_ender, _x, _y, _z, xa, ya, za);
|
||||
}
|
||||
// 4J - moved sounds forward from 1.2.3
|
||||
level->playSound(xo, yo, zo, eSoundType_MOB_ENDERMEN_PORTAL, 1, 1);
|
||||
level->playSound(shared_from_this(), eSoundType_MOB_ENDERMEN_PORTAL, 1,
|
||||
1);
|
||||
playSound(eSoundType_MOB_ENDERMEN_PORTAL, 1, 1);
|
||||
return true;
|
||||
} else {
|
||||
setPos(xo, yo, zo);
|
||||
|
|
@ -295,19 +318,13 @@ bool EnderMan::teleport(double xx, double yy, double zz) {
|
|||
}
|
||||
|
||||
int EnderMan::getAmbientSound() {
|
||||
// 4J - brought sound change forward from 1.2.3
|
||||
return eSoundType_MOB_ENDERMEN_IDLE;
|
||||
return isCreepy() ? eSoundType_MOB_ENDERMAN_SCREAM
|
||||
: eSoundType_MOB_ENDERMEN_IDLE;
|
||||
}
|
||||
|
||||
int EnderMan::getHurtSound() {
|
||||
// 4J - brought sound change forward from 1.2.3
|
||||
return eSoundType_MOB_ENDERMEN_HIT;
|
||||
}
|
||||
int EnderMan::getHurtSound() { return eSoundType_MOB_ENDERMEN_HIT; }
|
||||
|
||||
int EnderMan::getDeathSound() {
|
||||
// 4J - brought sound change forward from 1.2.3
|
||||
return eSoundType_MOB_ENDERMEN_DEATH;
|
||||
}
|
||||
int EnderMan::getDeathSound() { return eSoundType_MOB_ENDERMEN_DEATH; }
|
||||
|
||||
int EnderMan::getDeathLoot() { return Item::enderPearl_Id; }
|
||||
|
||||
|
|
@ -336,10 +353,21 @@ int EnderMan::getCarryingData() {
|
|||
return entityData->getByte(DATA_CARRY_ITEM_DATA);
|
||||
}
|
||||
|
||||
bool EnderMan::hurt(DamageSource* source, int damage) {
|
||||
bool EnderMan::hurt(DamageSource* source, float damage) {
|
||||
if (isInvulnerable()) return false;
|
||||
setCreepy(true);
|
||||
|
||||
if (dynamic_cast<EntityDamageSource*>(source) != NULL &&
|
||||
source->getEntity()->instanceof(eTYPE_PLAYER)) {
|
||||
aggroedByPlayer = true;
|
||||
}
|
||||
|
||||
if (dynamic_cast<IndirectEntityDamageSource*>(source) != NULL) {
|
||||
aggroedByPlayer = false;
|
||||
for (int i = 0; i < 64; i++) {
|
||||
if (teleport()) return true;
|
||||
if (teleport()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -350,4 +378,4 @@ bool EnderMan::isCreepy() { return entityData->getByte(DATA_CREEPY) > 0; }
|
|||
|
||||
void EnderMan::setCreepy(bool creepy) {
|
||||
entityData->set(DATA_CREEPY, (uint8_t)(creepy ? 1 : 0));
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,8 @@ public:
|
|||
static void staticCtor();
|
||||
|
||||
private:
|
||||
static AttributeModifier* SPEED_MODIFIER_ATTACKING;
|
||||
|
||||
static bool MAY_TAKE[256];
|
||||
|
||||
static const int DATA_CARRY_ITEM_ID = 16;
|
||||
|
|
@ -20,13 +22,14 @@ private:
|
|||
private:
|
||||
int teleportTime;
|
||||
int aggroTime;
|
||||
std::shared_ptr<Entity> lastAttackTarget;
|
||||
bool aggroedByPlayer;
|
||||
|
||||
public:
|
||||
EnderMan(Level* level);
|
||||
|
||||
virtual int getMaxHealth();
|
||||
|
||||
protected:
|
||||
virtual void registerAttributes();
|
||||
virtual void defineSynchedData();
|
||||
|
||||
public:
|
||||
|
|
@ -54,12 +57,11 @@ protected:
|
|||
virtual void dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel);
|
||||
|
||||
public:
|
||||
// 4J Brought forward from 1.2.3 to help fix Enderman behaviour
|
||||
void setCarryingTile(int carryingTile);
|
||||
int getCarryingTile();
|
||||
void setCarryingData(int carryingData);
|
||||
int getCarryingData();
|
||||
virtual bool hurt(DamageSource* source, int damage);
|
||||
virtual bool hurt(DamageSource* source, float damage);
|
||||
bool isCreepy();
|
||||
void setCreepy(bool creepy);
|
||||
};
|
||||
1520
Minecraft.World/Entities/Mobs/EntityHorse.cpp
Normal file
1520
Minecraft.World/Entities/Mobs/EntityHorse.cpp
Normal file
File diff suppressed because it is too large
Load diff
343
Minecraft.World/Entities/Mobs/EntityHorse.h
Normal file
343
Minecraft.World/Entities/Mobs/EntityHorse.h
Normal file
|
|
@ -0,0 +1,343 @@
|
|||
#pragma once
|
||||
|
||||
#include "Animal.h"
|
||||
#include "../../Headers/net.minecraft.world.ContainerListener.h"
|
||||
#include "MobGroupData.h"
|
||||
#include "../EntitySelector.h"
|
||||
|
||||
class Attribute;
|
||||
class AnimalChest;
|
||||
|
||||
class HorseEntitySelector : public EntitySelector {
|
||||
public:
|
||||
bool matches(std::shared_ptr<Entity> entity) const;
|
||||
};
|
||||
|
||||
class EntityHorse : public Animal,
|
||||
public net_minecraft_world::ContainerListener {
|
||||
public:
|
||||
eINSTANCEOF GetType() { return eTYPE_HORSE; }
|
||||
static Entity* create(Level* level) { return new EntityHorse(level); }
|
||||
|
||||
private:
|
||||
static const std::wstring TEX_FOLDER;
|
||||
|
||||
static const EntitySelector* PARENT_HORSE_SELECTOR;
|
||||
|
||||
static Attribute* JUMP_STRENGTH;
|
||||
|
||||
static const int DATA_ID_HORSE_FLAGS = 16;
|
||||
static const int DATA_ID_TYPE = 19;
|
||||
static const int DATA_ID_TYPE_VARIANT = 20;
|
||||
static const int DATA_ID_OWNER_NAME = 21;
|
||||
static const int DATA_ID_ARMOR = 22;
|
||||
|
||||
static const int FLAG_TAME = 1 << 1;
|
||||
static const int FLAG_SADDLE = 1 << 2;
|
||||
static const int FLAG_CHESTED = 1 << 3;
|
||||
static const int FLAG_BRED = 1 << 4;
|
||||
static const int FLAG_EATING = 1 << 5;
|
||||
static const int FLAG_STANDING = 1 << 6;
|
||||
static const int FLAG_OPEN_MOUTH = 1 << 7;
|
||||
|
||||
public:
|
||||
static const int INV_SLOT_SADDLE = 0;
|
||||
static const int INV_SLOT_ARMOR = 1;
|
||||
static const int INV_BASE_COUNT = 2;
|
||||
static const int INV_DONKEY_CHEST_COUNT = 15;
|
||||
|
||||
// TODO: USE ENUMS! // Original comment
|
||||
static const int ARMOR_NONE = 0;
|
||||
static const int ARMOR_IRON = 1;
|
||||
static const int ARMOR_GOLD = 2;
|
||||
static const int ARMOR_DIAMOND = 3;
|
||||
|
||||
private:
|
||||
static const int ARMORS = 4;
|
||||
static std::wstring ARMOR_TEXTURES[ARMORS];
|
||||
static int ARMOR_TEXTURES_ID[ARMORS];
|
||||
static std::wstring ARMOR_HASHES[ARMORS];
|
||||
static int ARMOR_PROTECTION[ARMORS];
|
||||
|
||||
public:
|
||||
static const int TYPE_HORSE = 0;
|
||||
static const int TYPE_DONKEY = 1;
|
||||
static const int TYPE_MULE = 2;
|
||||
static const int TYPE_UNDEAD = 3;
|
||||
static const int TYPE_SKELETON = 4;
|
||||
|
||||
static const int VARIANT_WHITE = 0;
|
||||
static const int VARIANT_CREAMY = 1;
|
||||
static const int VARIANT_CHESTNUT = 2;
|
||||
static const int VARIANT_BROWN = 3;
|
||||
static const int VARIANT_BLACK = 4;
|
||||
static const int VARIANT_GRAY = 5;
|
||||
static const int VARIANT_DARKBROWN = 6;
|
||||
|
||||
private:
|
||||
static const int VARIANTS = 7;
|
||||
static std::wstring VARIANT_TEXTURES[VARIANTS];
|
||||
static int VARIANT_TEXTURES_ID[VARIANTS];
|
||||
static std::wstring VARIANT_HASHES[VARIANTS];
|
||||
|
||||
public:
|
||||
static const int MARKING_NONE = 0;
|
||||
static const int MARKING_WHITE_DETAILS = 1;
|
||||
static const int MARKING_WHITE_FIELDS = 2;
|
||||
static const int MARKING_WHITE_DOTS = 3;
|
||||
static const int MARKING_BLACK_DOTS = 4;
|
||||
|
||||
private:
|
||||
static const int MARKINGS = 5;
|
||||
static std::wstring MARKING_TEXTURES[MARKINGS];
|
||||
static int MARKING_TEXTURES_ID[MARKINGS];
|
||||
static std::wstring MARKING_HASHES[MARKINGS];
|
||||
|
||||
private:
|
||||
int countEating; // eating timer
|
||||
int mouthCounter;
|
||||
int standCounter;
|
||||
|
||||
public:
|
||||
int tailCounter;
|
||||
int sprintCounter;
|
||||
|
||||
protected:
|
||||
bool isEntityJumping;
|
||||
|
||||
private:
|
||||
std::shared_ptr<AnimalChest> inventory;
|
||||
bool hasReproduced;
|
||||
|
||||
protected:
|
||||
int temper;
|
||||
float playerJumpPendingScale;
|
||||
|
||||
private:
|
||||
bool allowStandSliding;
|
||||
|
||||
// animation data
|
||||
float eatAnim, eatAnimO;
|
||||
float standAnim, standAnimO;
|
||||
float mouthAnim, mouthAnimO;
|
||||
|
||||
public:
|
||||
EntityHorse(Level* world);
|
||||
~EntityHorse();
|
||||
|
||||
protected:
|
||||
virtual void defineSynchedData();
|
||||
|
||||
public:
|
||||
virtual void setType(int i);
|
||||
virtual int getType();
|
||||
virtual void setVariant(int i);
|
||||
virtual int getVariant();
|
||||
virtual std::wstring getAName();
|
||||
|
||||
private:
|
||||
virtual bool getHorseFlag(int flag);
|
||||
virtual void setHorseFlag(int flag, bool value);
|
||||
|
||||
public:
|
||||
virtual bool isAdult();
|
||||
virtual bool isTamed();
|
||||
virtual bool isRidable();
|
||||
virtual std::wstring getOwnerName();
|
||||
virtual void setOwner(const std::wstring& par1Str);
|
||||
virtual float getFoalScale();
|
||||
virtual void updateSize(bool isBaby);
|
||||
virtual bool getIsJumping();
|
||||
virtual void setTamed(bool flag);
|
||||
virtual void setIsJumping(bool flag);
|
||||
virtual bool canBeLeashed();
|
||||
|
||||
protected:
|
||||
virtual void onLeashDistance(float distanceToLeashHolder);
|
||||
|
||||
public:
|
||||
virtual bool isChestedHorse();
|
||||
virtual int getArmorType();
|
||||
virtual int getArmorTypeForItem(std::shared_ptr<ItemInstance> armorItem);
|
||||
virtual bool isEating();
|
||||
virtual bool isStanding();
|
||||
virtual bool isBred();
|
||||
virtual bool getHasReproduced();
|
||||
virtual void setArmorType(int i);
|
||||
virtual void setBred(bool flag);
|
||||
virtual void setChestedHorse(bool flag);
|
||||
virtual void setReproduced(bool flag);
|
||||
virtual void setSaddled(bool flag);
|
||||
virtual int getTemper();
|
||||
virtual void setTemper(int temper);
|
||||
virtual int modifyTemper(int amount);
|
||||
virtual bool hurt(DamageSource* damagesource, float dmg);
|
||||
virtual int getArmorValue();
|
||||
virtual bool isPushable();
|
||||
virtual bool checkSpawningBiome();
|
||||
virtual void dropBags();
|
||||
|
||||
private:
|
||||
virtual void eatingHorse();
|
||||
|
||||
protected:
|
||||
virtual void causeFallDamage(float fallDistance);
|
||||
|
||||
private:
|
||||
virtual int getInventorySize();
|
||||
virtual void createInventory();
|
||||
virtual void updateEquipment();
|
||||
|
||||
public:
|
||||
virtual void containerChanged();
|
||||
virtual bool canSpawn();
|
||||
|
||||
protected:
|
||||
virtual std::shared_ptr<EntityHorse> getClosestMommy(
|
||||
std::shared_ptr<Entity> baby, double searchRadius);
|
||||
|
||||
public:
|
||||
virtual double getCustomJump();
|
||||
|
||||
protected:
|
||||
virtual int getDeathSound();
|
||||
virtual int getDeathLoot();
|
||||
virtual int getHurtSound();
|
||||
|
||||
public:
|
||||
virtual bool isSaddled();
|
||||
|
||||
protected:
|
||||
virtual int getAmbientSound();
|
||||
virtual int getMadSound();
|
||||
|
||||
private:
|
||||
int gallopSoundCounter;
|
||||
|
||||
protected:
|
||||
virtual void playStepSound(int xt, int yt, int zt, int t);
|
||||
virtual void registerAttributes();
|
||||
|
||||
public:
|
||||
virtual int getMaxSpawnClusterSize();
|
||||
virtual int getMaxTemper();
|
||||
|
||||
protected:
|
||||
virtual float getSoundVolume();
|
||||
|
||||
public:
|
||||
virtual int getAmbientSoundInterval();
|
||||
virtual bool hasLayeredTextures();
|
||||
|
||||
private:
|
||||
std::wstring layerTextureHashName;
|
||||
intArray layerTextureLayers;
|
||||
|
||||
private:
|
||||
virtual void clearLayeredTextureInfo();
|
||||
virtual void rebuildLayeredTextureInfo();
|
||||
|
||||
public:
|
||||
virtual std::wstring getLayeredTextureHashName();
|
||||
virtual intArray getLayeredTextureLayers();
|
||||
virtual void openInventory(std::shared_ptr<Player> player);
|
||||
virtual bool mobInteract(std::shared_ptr<Player> player);
|
||||
|
||||
private:
|
||||
virtual void doPlayerRide(std::shared_ptr<Player> player);
|
||||
|
||||
public:
|
||||
virtual bool isAmuletHorse();
|
||||
virtual bool canWearArmor();
|
||||
virtual bool canWearBags();
|
||||
|
||||
protected:
|
||||
virtual bool isImmobile();
|
||||
|
||||
public:
|
||||
virtual bool isPureBreed();
|
||||
virtual bool isUndead();
|
||||
virtual bool isSterile();
|
||||
virtual bool isFood(std::shared_ptr<ItemInstance> itemInstance);
|
||||
|
||||
private:
|
||||
virtual void moveTail();
|
||||
|
||||
public:
|
||||
virtual int nameYOffset();
|
||||
virtual void die(DamageSource* damagesource);
|
||||
virtual void aiStep();
|
||||
virtual void tick();
|
||||
|
||||
private:
|
||||
virtual void openMouth();
|
||||
|
||||
public:
|
||||
// 4J-JEV: Made public for tooltip code, doesn't change state anyway.
|
||||
virtual bool isReadyForParenting();
|
||||
|
||||
public:
|
||||
virtual bool renderName();
|
||||
virtual bool rideableEntity();
|
||||
virtual void setUsingItemFlag(bool flag);
|
||||
virtual void setEating(bool state);
|
||||
virtual void setStanding(bool state);
|
||||
|
||||
private:
|
||||
virtual void stand();
|
||||
|
||||
public:
|
||||
virtual void makeMad();
|
||||
virtual void dropMyStuff();
|
||||
|
||||
private:
|
||||
virtual void dropInventory(std::shared_ptr<Entity> entity,
|
||||
std::shared_ptr<AnimalChest> animalchest);
|
||||
|
||||
public:
|
||||
virtual bool tameWithName(std::shared_ptr<Player> player);
|
||||
virtual void travel(float xa, float ya);
|
||||
virtual void addAdditonalSaveData(CompoundTag* tag);
|
||||
virtual void readAdditionalSaveData(CompoundTag* tag);
|
||||
virtual bool canMate(std::shared_ptr<Animal> partner);
|
||||
virtual std::shared_ptr<AgableMob> getBreedOffspring(
|
||||
std::shared_ptr<AgableMob> partner);
|
||||
virtual MobGroupData* finalizeMobSpawn(
|
||||
MobGroupData* groupData,
|
||||
int extraData = 0); // 4J Added extraData param
|
||||
virtual float getEatAnim(float a);
|
||||
virtual float getStandAnim(float a);
|
||||
virtual float getMouthAnim(float a);
|
||||
|
||||
protected:
|
||||
virtual bool useNewAi();
|
||||
|
||||
public:
|
||||
virtual void onPlayerJump(int jumpAmount);
|
||||
|
||||
protected:
|
||||
virtual void spawnTamingParticles(bool success);
|
||||
|
||||
public:
|
||||
virtual void handleEntityEvent(uint8_t id);
|
||||
virtual void positionRider();
|
||||
|
||||
private:
|
||||
virtual float generateRandomMaxHealth();
|
||||
virtual double generateRandomJumpStrength();
|
||||
virtual double generateRandomSpeed();
|
||||
|
||||
std::shared_ptr<Player> getOwner();
|
||||
|
||||
public:
|
||||
class HorseGroupData : public MobGroupData {
|
||||
public:
|
||||
int horseType;
|
||||
int horseVariant;
|
||||
|
||||
HorseGroupData(int type, int variant);
|
||||
};
|
||||
|
||||
static bool isHorseArmor(int itemId);
|
||||
virtual bool onLadder();
|
||||
};
|
||||
|
|
@ -81,8 +81,8 @@ void ExperienceOrb::tick() {
|
|||
yd = 0.2f;
|
||||
xd = (random->nextFloat() - random->nextFloat()) * 0.2f;
|
||||
zd = (random->nextFloat() - random->nextFloat()) * 0.2f;
|
||||
level->playSound(shared_from_this(), eSoundType_RANDOM_FIZZ, 0.4f,
|
||||
2.0f + random->nextFloat() * 0.4f);
|
||||
playSound(eSoundType_RANDOM_FIZZ, 0.4f,
|
||||
2.0f + random->nextFloat() * 0.4f);
|
||||
}
|
||||
checkInTile(x, (bb->y0 + bb->y1) / 2, z);
|
||||
|
||||
|
|
@ -150,7 +150,8 @@ bool ExperienceOrb::updateInWaterState() {
|
|||
|
||||
void ExperienceOrb::burn(int dmg) { hurt(DamageSource::inFire, dmg); }
|
||||
|
||||
bool ExperienceOrb::hurt(DamageSource* source, int damage) {
|
||||
bool ExperienceOrb::hurt(DamageSource* source, float damage) {
|
||||
if (isInvulnerable()) return false;
|
||||
markHurt();
|
||||
health -= damage;
|
||||
if (health <= 0) {
|
||||
|
|
@ -177,8 +178,8 @@ void ExperienceOrb::playerTouch(std::shared_ptr<Player> player) {
|
|||
if (throwTime == 0 && player->takeXpDelay == 0) {
|
||||
player->takeXpDelay = 2;
|
||||
// 4J - sound change brought forward from 1.2.3
|
||||
level->playSound(
|
||||
shared_from_this(), eSoundType_RANDOM_ORB, 0.1f,
|
||||
playSound(
|
||||
eSoundType_RANDOM_ORB, 0.1f,
|
||||
0.5f * ((random->nextFloat() - random->nextFloat()) * 0.7f + 1.8f));
|
||||
player->take(shared_from_this(), 1);
|
||||
player->increaseXp(value);
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ protected:
|
|||
virtual void burn(int dmg);
|
||||
|
||||
public:
|
||||
virtual bool hurt(DamageSource* source, int damage);
|
||||
virtual bool hurt(DamageSource* source, float damage);
|
||||
virtual void addAdditonalSaveData(CompoundTag* entityTag);
|
||||
virtual void readAdditionalSaveData(CompoundTag* tag);
|
||||
virtual void playerTouch(std::shared_ptr<Player> player);
|
||||
|
|
|
|||
|
|
@ -40,8 +40,8 @@ EyeOfEnderSignal::EyeOfEnderSignal(Level* level, double x, double y, double z)
|
|||
|
||||
setSize(0.25f, 0.25f);
|
||||
|
||||
this->setPos(x, y, z);
|
||||
this->heightOffset = 0;
|
||||
setPos(x, y, z);
|
||||
heightOffset = 0;
|
||||
}
|
||||
|
||||
void EyeOfEnderSignal::signalTo(double tx, int ty, double tz) {
|
||||
|
|
@ -68,8 +68,8 @@ void EyeOfEnderSignal::lerpMotion(double xd, double yd, double zd) {
|
|||
this->zd = zd;
|
||||
if (xRotO == 0 && yRotO == 0) {
|
||||
float sd = (float)sqrt(xd * xd + zd * zd);
|
||||
yRotO = this->yRot = (float)(atan2(xd, zd) * 180 / PI);
|
||||
xRotO = this->xRot = (float)(atan2(yd, (double)sd) * 180 / PI);
|
||||
yRotO = yRot = (float)(atan2(xd, zd) * 180 / PI);
|
||||
xRotO = xRot = (float)(atan2(yd, (double)sd) * 180 / PI);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,8 +55,8 @@ Fireball::Fireball(Level* level, double x, double y, double z, double xa,
|
|||
|
||||
setSize(16 / 16.0f, 16 / 16.0f);
|
||||
|
||||
this->moveTo(x, y, z, yRot, xRot);
|
||||
this->setPos(x, y, z);
|
||||
moveTo(x, y, z, yRot, xRot);
|
||||
setPos(x, y, z);
|
||||
|
||||
double dd = sqrt(xa * xa + ya * ya + za * za);
|
||||
|
||||
|
|
@ -74,8 +74,8 @@ Fireball::Fireball(Level* level, double x, double y, double z, double xa,
|
|||
}
|
||||
}
|
||||
|
||||
Fireball::Fireball(Level* level, std::shared_ptr<Mob> mob, double xa, double ya,
|
||||
double za)
|
||||
Fireball::Fireball(Level* level, std::shared_ptr<LivingEntity> mob, double xa,
|
||||
double ya, double za)
|
||||
: Entity(level) {
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
|
|
@ -83,13 +83,13 @@ Fireball::Fireball(Level* level, std::shared_ptr<Mob> mob, double xa, double ya,
|
|||
|
||||
_init();
|
||||
|
||||
this->owner = mob;
|
||||
owner = mob;
|
||||
|
||||
setSize(16 / 16.0f, 16 / 16.0f);
|
||||
|
||||
this->moveTo(mob->x, mob->y, mob->z, mob->yRot, mob->xRot);
|
||||
this->setPos(x, y, z);
|
||||
this->heightOffset = 0;
|
||||
moveTo(mob->x, mob->y, mob->z, mob->yRot, mob->xRot);
|
||||
setPos(x, y, z);
|
||||
heightOffset = 0;
|
||||
|
||||
xd = yd = zd = 0.0;
|
||||
|
||||
|
|
@ -177,7 +177,7 @@ void Fireball::tick() {
|
|||
}
|
||||
std::shared_ptr<Entity> hitEntity = nullptr;
|
||||
std::vector<std::shared_ptr<Entity> >* objects = level->getEntities(
|
||||
shared_from_this(), this->bb->expand(xd, yd, zd)->grow(1, 1, 1));
|
||||
shared_from_this(), bb->expand(xd, yd, zd)->grow(1, 1, 1));
|
||||
double nearest = 0;
|
||||
AUTO_VAR(itEnd, objects->end());
|
||||
for (AUTO_VAR(it, objects->begin()); it != itEnd; it++) {
|
||||
|
|
@ -214,8 +214,8 @@ void Fireball::tick() {
|
|||
z += zd;
|
||||
|
||||
double sd = sqrt(xd * xd + zd * zd);
|
||||
yRot = (float)(atan2(xd, zd) * 180 / PI);
|
||||
xRot = (float)(atan2(yd, sd) * 180 / PI);
|
||||
yRot = (float)(atan2(zd, xd) * 180 / PI) + 90;
|
||||
xRot = (float)(atan2(sd, yd) * 180 / PI) - 90;
|
||||
|
||||
while (xRot - xRotO < -180) xRotO -= 360;
|
||||
while (xRot - xRotO >= 180) xRotO += 360;
|
||||
|
|
@ -226,7 +226,7 @@ void Fireball::tick() {
|
|||
xRot = xRotO + (xRot - xRotO) * 0.2f;
|
||||
yRot = yRotO + (yRot - yRotO) * 0.2f;
|
||||
|
||||
float inertia = 0.95f;
|
||||
float inertia = getInertia();
|
||||
if (isInWater()) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
float s = 1 / 4.0f;
|
||||
|
|
@ -260,24 +260,7 @@ void Fireball::tick() {
|
|||
setPos(x, y, z);
|
||||
}
|
||||
|
||||
void Fireball::onHit(HitResult* res) {
|
||||
if (!level->isClientSide) {
|
||||
if (res->entity != NULL) {
|
||||
DamageSource* damageSource = DamageSource::fireball(
|
||||
std::dynamic_pointer_cast<Fireball>(shared_from_this()), owner);
|
||||
if (res->entity->hurt(damageSource, 6)) {
|
||||
} else {
|
||||
}
|
||||
delete damageSource;
|
||||
}
|
||||
|
||||
bool destroyBlocks =
|
||||
true; // level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING);
|
||||
level->explode(nullptr, x, y, z, 1, true, destroyBlocks);
|
||||
|
||||
remove();
|
||||
}
|
||||
}
|
||||
float Fireball::getInertia() { return 0.95f; }
|
||||
|
||||
void Fireball::addAdditonalSaveData(CompoundTag* tag) {
|
||||
tag->putShort(L"xTile", (short)xTile);
|
||||
|
|
@ -285,8 +268,7 @@ void Fireball::addAdditonalSaveData(CompoundTag* tag) {
|
|||
tag->putShort(L"zTile", (short)zTile);
|
||||
tag->putByte(L"inTile", (uint8_t)lastTile);
|
||||
tag->putByte(L"inGround", (uint8_t)(inGround ? 1 : 0));
|
||||
tag->put(L"direction",
|
||||
this->newDoubleList(3, this->xd, this->yd, this->zd));
|
||||
tag->put(L"direction", newDoubleList(3, xd, yd, zd));
|
||||
}
|
||||
|
||||
void Fireball::readAdditionalSaveData(CompoundTag* tag) {
|
||||
|
|
@ -301,11 +283,11 @@ void Fireball::readAdditionalSaveData(CompoundTag* tag) {
|
|||
if (tag->contains(L"direction")) {
|
||||
ListTag<DoubleTag>* listTag =
|
||||
(ListTag<DoubleTag>*)tag->getList(L"direction");
|
||||
this->xd = ((DoubleTag*)listTag->get(0))->data;
|
||||
this->yd = ((DoubleTag*)listTag->get(1))->data;
|
||||
this->zd = ((DoubleTag*)listTag->get(2))->data;
|
||||
xd = ((DoubleTag*)listTag->get(0))->data;
|
||||
yd = ((DoubleTag*)listTag->get(1))->data;
|
||||
zd = ((DoubleTag*)listTag->get(2))->data;
|
||||
} else {
|
||||
this->remove();
|
||||
remove();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -313,7 +295,8 @@ bool Fireball::isPickable() { return true; }
|
|||
|
||||
float Fireball::getPickRadius() { return 1; }
|
||||
|
||||
bool Fireball::hurt(DamageSource* source, int damage) {
|
||||
bool Fireball::hurt(DamageSource* source, float damage) {
|
||||
if (isInvulnerable()) return false;
|
||||
markHurt();
|
||||
|
||||
if (source->getEntity() != NULL) {
|
||||
|
|
@ -326,10 +309,9 @@ bool Fireball::hurt(DamageSource* source, int damage) {
|
|||
yPower = yd * 0.1;
|
||||
zPower = zd * 0.1;
|
||||
}
|
||||
std::shared_ptr<Mob> mob =
|
||||
std::dynamic_pointer_cast<Mob>(source->getEntity());
|
||||
if (mob != NULL) {
|
||||
owner = mob;
|
||||
if (source->getEntity()->instanceof(eTYPE_LIVINGENTITY)) {
|
||||
owner =
|
||||
std::dynamic_pointer_cast<LivingEntity>(source->getEntity());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -342,8 +324,6 @@ float Fireball::getBrightness(float a) { return 1.0f; }
|
|||
|
||||
int Fireball::getLightColor(float a) { return 15 << 20 | 15 << 4; }
|
||||
|
||||
bool Fireball::shouldBurn() { return true; }
|
||||
|
||||
int Fireball::getIcon() { return 14 + 2 * 16; }
|
||||
|
||||
ePARTICLE_TYPE Fireball::getTrailParticleType() { return eParticleType_smoke; }
|
||||
|
||||
bool Fireball::shouldBurn() { return true; }
|
||||
|
|
@ -8,7 +8,6 @@ class HitResult;
|
|||
class Fireball : public Entity {
|
||||
public:
|
||||
eINSTANCEOF GetType() { return eTYPE_FIREBALL; }
|
||||
static Entity* create(Level* level) { return new Fireball(level); }
|
||||
|
||||
private:
|
||||
int xTile;
|
||||
|
|
@ -20,7 +19,7 @@ private:
|
|||
bool inGround;
|
||||
|
||||
public:
|
||||
std::shared_ptr<Mob> owner;
|
||||
std::shared_ptr<LivingEntity> owner;
|
||||
|
||||
private:
|
||||
int life;
|
||||
|
|
@ -42,30 +41,29 @@ public:
|
|||
|
||||
Fireball(Level* level, double x, double y, double z, double xa, double ya,
|
||||
double za);
|
||||
Fireball(Level* level, std::shared_ptr<Mob> mob, double xa, double ya,
|
||||
double za);
|
||||
Fireball(Level* level, std::shared_ptr<LivingEntity> mob, double xa,
|
||||
double ya, double za);
|
||||
|
||||
public:
|
||||
virtual void tick();
|
||||
|
||||
protected:
|
||||
virtual void onHit(HitResult* res);
|
||||
virtual float getInertia();
|
||||
virtual void onHit(HitResult* res) = 0;
|
||||
|
||||
public:
|
||||
virtual void addAdditonalSaveData(CompoundTag* tag);
|
||||
virtual void readAdditionalSaveData(CompoundTag* tag);
|
||||
virtual bool isPickable();
|
||||
virtual float getPickRadius();
|
||||
virtual bool hurt(DamageSource* source, int damage);
|
||||
virtual bool hurt(DamageSource* source, float damage);
|
||||
virtual float getShadowHeightOffs();
|
||||
virtual float getBrightness(float a);
|
||||
virtual int getLightColor(float a);
|
||||
|
||||
// 4J Added TU9
|
||||
virtual bool shouldBurn();
|
||||
virtual int getIcon();
|
||||
|
||||
protected:
|
||||
// 4J Added TU9
|
||||
virtual ePARTICLE_TYPE getTrailParticleType();
|
||||
|
||||
virtual bool shouldBurn();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -63,19 +63,19 @@ FishingHook::FishingHook(Level* level, std::shared_ptr<Player> mob)
|
|||
: Entity(level) {
|
||||
_init();
|
||||
|
||||
this->owner = mob;
|
||||
owner = mob;
|
||||
// 4J Stu - Moved this outside the ctor
|
||||
// owner->fishing = std::dynamic_pointer_cast<FishingHook>(
|
||||
// shared_from_this() );
|
||||
|
||||
this->moveTo(mob->x, mob->y + 1.62 - mob->heightOffset, mob->z, mob->yRot,
|
||||
mob->xRot);
|
||||
moveTo(mob->x, mob->y + 1.62 - mob->heightOffset, mob->z, mob->yRot,
|
||||
mob->xRot);
|
||||
|
||||
x -= Mth::cos(yRot / 180 * PI) * 0.16f;
|
||||
y -= 0.1f;
|
||||
z -= Mth::sin(yRot / 180 * PI) * 0.16f;
|
||||
this->setPos(x, y, z);
|
||||
this->heightOffset = 0;
|
||||
setPos(x, y, z);
|
||||
heightOffset = 0;
|
||||
|
||||
float speed = 0.4f;
|
||||
xd = (-Mth::sin(yRot / 180 * PI) * Mth::cos(xRot / 180 * PI)) * speed;
|
||||
|
|
@ -115,8 +115,8 @@ void FishingHook::shoot(double xd, double yd, double zd, float pow,
|
|||
|
||||
double sd = sqrt(xd * xd + zd * zd);
|
||||
|
||||
yRotO = this->yRot = (float)(atan2(xd, zd) * 180 / PI);
|
||||
xRotO = this->xRot = (float)(atan2(yd, sd) * 180 / PI);
|
||||
yRotO = yRot = (float)(atan2(xd, zd) * 180 / PI);
|
||||
xRotO = xRot = (float)(atan2(yd, sd) * 180 / PI);
|
||||
life = 0;
|
||||
}
|
||||
|
||||
|
|
@ -130,9 +130,9 @@ void FishingHook::lerpTo(double x, double y, double z, float yRot, float xRot,
|
|||
|
||||
lSteps = steps;
|
||||
|
||||
this->xd = lxd;
|
||||
this->yd = lyd;
|
||||
this->zd = lzd;
|
||||
xd = lxd;
|
||||
yd = lyd;
|
||||
zd = lzd;
|
||||
}
|
||||
|
||||
void FishingHook::lerpMotion(double xd, double yd, double zd) {
|
||||
|
|
@ -155,8 +155,8 @@ void FishingHook::tick() {
|
|||
xRot += (float)((lxr - xRot) / lSteps);
|
||||
|
||||
lSteps--;
|
||||
this->setPos(xt, yt, zt);
|
||||
this->setRot(yRot, xRot);
|
||||
setPos(xt, yt, zt);
|
||||
setRot(yRot, xRot);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -164,7 +164,7 @@ void FishingHook::tick() {
|
|||
std::shared_ptr<ItemInstance> selectedItem = owner->getSelectedItem();
|
||||
if (owner->removed || !owner->isAlive() || selectedItem == NULL ||
|
||||
selectedItem->getItem() != Item::fishingRod ||
|
||||
this->distanceToSqr(owner) > 32 * 32) {
|
||||
distanceToSqr(owner) > 32 * 32) {
|
||||
remove();
|
||||
owner->fishing = nullptr;
|
||||
return;
|
||||
|
|
@ -214,7 +214,7 @@ void FishingHook::tick() {
|
|||
}
|
||||
std::shared_ptr<Entity> hitEntity = nullptr;
|
||||
std::vector<std::shared_ptr<Entity> >* objects = level->getEntities(
|
||||
shared_from_this(), this->bb->expand(xd, yd, zd)->grow(1, 1, 1));
|
||||
shared_from_this(), bb->expand(xd, yd, zd)->grow(1, 1, 1));
|
||||
double nearest = 0;
|
||||
AUTO_VAR(itEnd, objects->end());
|
||||
for (AUTO_VAR(it, objects->begin()); it != itEnd; it++) {
|
||||
|
|
@ -243,8 +243,8 @@ void FishingHook::tick() {
|
|||
if (res->entity != NULL) {
|
||||
// 4J Stu Move fix for : fix for #48587 - CRASH: Code: Gameplay:
|
||||
// Hitting another player with the fishing bobber crashes the game.
|
||||
// [Fishing pole, line] Incorrect std::dynamic_pointer_cast used
|
||||
// around the shared_from_this()
|
||||
// [Fishing pole, line] Incorrect dynamic_pointer_cast used around
|
||||
// the shared_from_this()
|
||||
DamageSource* damageSource =
|
||||
DamageSource::thrown(shared_from_this(), owner);
|
||||
if (res->entity->hurt(damageSource, 0)) {
|
||||
|
|
@ -305,8 +305,8 @@ void FishingHook::tick() {
|
|||
if (random->nextInt(nibbleOdds) == 0) {
|
||||
nibble = random->nextInt(30) + 10;
|
||||
yd -= 0.2f;
|
||||
level->playSound(
|
||||
shared_from_this(), eSoundType_RANDOM_SPLASH, 0.25f,
|
||||
playSound(
|
||||
eSoundType_RANDOM_SPLASH, 0.25f,
|
||||
1 + (random->nextFloat() - random->nextFloat()) * 0.4f);
|
||||
float yt = (float)Mth::floor(bb->y0);
|
||||
for (int i = 0; i < 1 + bbWidth * 20; i++) {
|
||||
|
|
@ -398,7 +398,7 @@ int FishingHook::retrieve() {
|
|||
owner->level->addEntity(
|
||||
std::shared_ptr<ExperienceOrb>(new ExperienceOrb(
|
||||
owner->level, owner->x, owner->y + 0.5f, owner->z + 0.5f,
|
||||
random->nextInt(3) + 1))); // 4J Stu brought forward from 1.4
|
||||
random->nextInt(6) + 1))); // 4J Stu brought forward from 1.4
|
||||
dmg = 1;
|
||||
}
|
||||
if (inGround) dmg = 2;
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@
|
|||
#include "../../Headers/net.minecraft.world.phys.h"
|
||||
#include "../../Headers/net.minecraft.world.level.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.attributes.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.projectile.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.player.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.monster.h"
|
||||
#include "../../Headers/net.minecraft.world.item.h"
|
||||
#include "../../Headers/net.minecraft.world.damagesource.h"
|
||||
#include "../../Headers/net.minecraft.stats.h"
|
||||
|
|
@ -14,6 +16,7 @@
|
|||
#include "../../Util/SoundTypes.h"
|
||||
|
||||
void Ghast::_init() {
|
||||
explosionPower = 1;
|
||||
floatDuration = 0;
|
||||
target = nullptr;
|
||||
retargetTime = 0;
|
||||
|
|
@ -29,28 +32,27 @@ Ghast::Ghast(Level* level) : FlyingMob(level) {
|
|||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
health = getMaxHealth();
|
||||
registerAttributes();
|
||||
setHealth(getMaxHealth());
|
||||
|
||||
_init();
|
||||
|
||||
this->textureIdx = TN_MOB_GHAST; // 4J was L"/mob/ghast.png";
|
||||
this->setSize(4, 4);
|
||||
this->fireImmune = true;
|
||||
setSize(4, 4);
|
||||
fireImmune = true;
|
||||
xpReward = Enemy::XP_REWARD_MEDIUM;
|
||||
}
|
||||
|
||||
bool Ghast::hurt(DamageSource* source, int dmg) {
|
||||
bool Ghast::isCharging() { return entityData->getByte(DATA_IS_CHARGING) != 0; }
|
||||
|
||||
bool Ghast::hurt(DamageSource* source, float dmg) {
|
||||
if (isInvulnerable()) return false;
|
||||
if (source->getMsgId() == ChatPacket::e_ChatDeathFireball) {
|
||||
std::shared_ptr<Player> player =
|
||||
std::dynamic_pointer_cast<Player>(source->getEntity());
|
||||
if (player != NULL) {
|
||||
if ((source->getEntity() != NULL) &&
|
||||
source->getEntity()->instanceof(eTYPE_PLAYER)) {
|
||||
// reflected fireball, kill the ghast
|
||||
FlyingMob::hurt(source, 1000);
|
||||
player->awardStat(GenericStats::ghast(),
|
||||
GenericStats::param_ghast());
|
||||
std::dynamic_pointer_cast<Player>(source->getEntity())
|
||||
->awardStat(GenericStats::ghast(), GenericStats::param_ghast());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -64,14 +66,10 @@ void Ghast::defineSynchedData() {
|
|||
entityData->define(DATA_IS_CHARGING, (uint8_t)0);
|
||||
}
|
||||
|
||||
int Ghast::getMaxHealth() { return 10; }
|
||||
void Ghast::registerAttributes() {
|
||||
FlyingMob::registerAttributes();
|
||||
|
||||
void Ghast::tick() {
|
||||
FlyingMob::tick();
|
||||
uint8_t current = entityData->getByte(DATA_IS_CHARGING);
|
||||
// this->textureName = current == 1 ? L"/mob/ghast_fire.png" :
|
||||
// L"/mob/ghast.png"; // 4J replaced with following line
|
||||
this->textureIdx = current == 1 ? TN_MOB_GHAST_FIRE : TN_MOB_GHAST;
|
||||
getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(10);
|
||||
}
|
||||
|
||||
void Ghast::serverAiStep() {
|
||||
|
|
@ -125,7 +123,7 @@ void Ghast::serverAiStep() {
|
|||
double zdd = target->z - z;
|
||||
yBodyRot = yRot = -(float)atan2(xdd, zdd) * 180 / PI;
|
||||
|
||||
if (this->canSee(target)) {
|
||||
if (canSee(target)) {
|
||||
if (charge == 10) {
|
||||
// 4J - change brought forward from 1.2.3
|
||||
level->levelEvent(nullptr, LevelEvent::SOUND_GHAST_WARNING,
|
||||
|
|
@ -136,11 +134,12 @@ void Ghast::serverAiStep() {
|
|||
// 4J - change brought forward from 1.2.3
|
||||
level->levelEvent(nullptr, LevelEvent::SOUND_GHAST_FIREBALL,
|
||||
(int)x, (int)y, (int)z, 0);
|
||||
std::shared_ptr<Fireball> ie =
|
||||
std::shared_ptr<Fireball>(new Fireball(
|
||||
std::shared_ptr<LargeFireball> ie =
|
||||
std::shared_ptr<LargeFireball>(new LargeFireball(
|
||||
level,
|
||||
std::dynamic_pointer_cast<Mob>(shared_from_this()), xdd,
|
||||
ydd, zdd));
|
||||
ie->explosionPower = explosionPower;
|
||||
double d = 4;
|
||||
Vec3* v = getViewVector(1);
|
||||
ie->x = x + v->x * d;
|
||||
|
|
@ -186,7 +185,7 @@ int Ghast::getHurtSound() { return eSoundType_MOB_GHAST_SCREAM; }
|
|||
|
||||
int Ghast::getDeathSound() { return eSoundType_MOB_GHAST_DEATH; }
|
||||
|
||||
int Ghast::getDeathLoot() { return Item::sulphur->id; }
|
||||
int Ghast::getDeathLoot() { return Item::gunpowder_Id; }
|
||||
|
||||
void Ghast::dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel) {
|
||||
int count = random->nextInt(2) + random->nextInt(1 + playerBonusLevel);
|
||||
|
|
@ -195,7 +194,7 @@ void Ghast::dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel) {
|
|||
}
|
||||
count = random->nextInt(3) + random->nextInt(1 + playerBonusLevel);
|
||||
for (int i = 0; i < count; i++) {
|
||||
spawnAtLocation(Item::sulphur_Id, 1);
|
||||
spawnAtLocation(Item::gunpowder_Id, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -209,3 +208,13 @@ bool Ghast::canSpawn() {
|
|||
}
|
||||
|
||||
int Ghast::getMaxSpawnClusterSize() { return 1; }
|
||||
void Ghast::addAdditonalSaveData(CompoundTag* tag) {
|
||||
FlyingMob::addAdditonalSaveData(tag);
|
||||
tag->putInt(L"ExplosionPower", explosionPower);
|
||||
}
|
||||
|
||||
void Ghast::readAdditionalSaveData(CompoundTag* tag) {
|
||||
FlyingMob::readAdditionalSaveData(tag);
|
||||
if (tag->contains(L"ExplosionPower"))
|
||||
explosionPower = tag->getInt(L"ExplosionPower");
|
||||
}
|
||||
|
|
@ -27,21 +27,19 @@ public:
|
|||
int charge;
|
||||
|
||||
private:
|
||||
int explosionPower;
|
||||
|
||||
void _init();
|
||||
|
||||
public:
|
||||
Ghast(Level* level);
|
||||
|
||||
virtual bool hurt(DamageSource* source, int dmg);
|
||||
virtual bool isCharging();
|
||||
virtual bool hurt(DamageSource* source, float dmg);
|
||||
|
||||
protected:
|
||||
virtual void defineSynchedData();
|
||||
|
||||
public:
|
||||
int getMaxHealth();
|
||||
|
||||
public:
|
||||
virtual void tick();
|
||||
virtual void registerAttributes();
|
||||
|
||||
protected:
|
||||
virtual void serverAiStep();
|
||||
|
|
@ -60,4 +58,6 @@ protected:
|
|||
public:
|
||||
virtual bool canSpawn();
|
||||
virtual int getMaxSpawnClusterSize();
|
||||
virtual void addAdditonalSaveData(CompoundTag* tag);
|
||||
virtual void readAdditionalSaveData(CompoundTag* tag);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#include "../../Platform/stdafx.h"
|
||||
#include "../../Headers/net.minecraft.world.level.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.ai.attributes.h"
|
||||
#include "../../Headers/net.minecraft.world.entity.monster.h"
|
||||
#include "Giant.h"
|
||||
#include "../../../Minecraft.Client/Textures/Textures.h"
|
||||
|
||||
|
|
@ -7,19 +9,19 @@ Giant::Giant(Level* level) : Monster(level) {
|
|||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
registerAttributes();
|
||||
|
||||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
health = getMaxHealth();
|
||||
|
||||
this->textureIdx = TN_MOB_ZOMBIE; // 4J was L"/mob/zombie.png";
|
||||
runSpeed = 0.5f;
|
||||
attackDamage = 50;
|
||||
this->heightOffset *= 6;
|
||||
this->setSize(bbWidth * 6, bbHeight * 6);
|
||||
heightOffset *= 6;
|
||||
setSize(bbWidth * 6, bbHeight * 6);
|
||||
}
|
||||
|
||||
int Giant::getMaxHealth() { return 100; }
|
||||
void Giant::registerAttributes() {
|
||||
Monster::registerAttributes();
|
||||
|
||||
getAttribute(SharedMonsterAttributes::MAX_HEALTH)->setBaseValue(100);
|
||||
getAttribute(SharedMonsterAttributes::MOVEMENT_SPEED)->setBaseValue(0.5f);
|
||||
getAttribute(SharedMonsterAttributes::ATTACK_DAMAGE)->setBaseValue(50);
|
||||
}
|
||||
|
||||
float Giant::getWalkTargetValue(int x, int y, int z) {
|
||||
return level->getBrightness(x, y, z) - 0.5f;
|
||||
|
|
|
|||
|
|
@ -11,6 +11,9 @@ public:
|
|||
|
||||
Giant(Level* level);
|
||||
|
||||
int getMaxHealth();
|
||||
protected:
|
||||
virtual void registerAttributes();
|
||||
|
||||
public:
|
||||
virtual float getWalkTargetValue(int x, int y, int z);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ void ItemFrame::_init() {
|
|||
// 4J Stu - This function call had to be moved here from the Entity ctor to
|
||||
// ensure that the derived version of the function is called
|
||||
this->defineSynchedData();
|
||||
|
||||
dropChance = 1;
|
||||
}
|
||||
|
||||
ItemFrame::ItemFrame(Level* level) : HangingEntity(level) { _init(); }
|
||||
|
|
@ -31,19 +33,40 @@ void ItemFrame::defineSynchedData() {
|
|||
getEntityData()->define(DATA_ROTATION, (uint8_t)0);
|
||||
}
|
||||
|
||||
void ItemFrame::dropItem() {
|
||||
spawnAtLocation(
|
||||
std::shared_ptr<ItemInstance>(new ItemInstance(Item::frame)), 0.0f);
|
||||
std::shared_ptr<ItemInstance> item = getItem();
|
||||
if (item != NULL) {
|
||||
std::shared_ptr<MapItemSavedData> data =
|
||||
Item::map->getSavedData(item, level);
|
||||
data->removeItemFrameDecoration(item);
|
||||
bool ItemFrame::shouldRenderAtSqrDistance(double distance) {
|
||||
double size = 16;
|
||||
size *= 64.0f * viewScale;
|
||||
return distance < size * size;
|
||||
}
|
||||
|
||||
std::shared_ptr<ItemInstance> itemToDrop = item->copy();
|
||||
itemToDrop->setFramed(nullptr);
|
||||
spawnAtLocation(itemToDrop, 0.0f);
|
||||
void ItemFrame::dropItem(std::shared_ptr<Entity> causedBy) {
|
||||
std::shared_ptr<ItemInstance> item = getItem();
|
||||
|
||||
if (causedBy != NULL && causedBy->instanceof(eTYPE_PLAYER)) {
|
||||
if (std::dynamic_pointer_cast<Player>(causedBy)->abilities.instabuild) {
|
||||
removeFramedMap(item);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
spawnAtLocation(
|
||||
std::shared_ptr<ItemInstance>(new ItemInstance(Item::frame)), 0);
|
||||
if ((item != NULL) && (random->nextFloat() < dropChance)) {
|
||||
item = item->copy();
|
||||
removeFramedMap(item);
|
||||
spawnAtLocation(item, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void ItemFrame::removeFramedMap(std::shared_ptr<ItemInstance> item) {
|
||||
if (item == NULL) return;
|
||||
if (item->id == Item::map_Id) {
|
||||
std::shared_ptr<MapItemSavedData> mapItemSavedData =
|
||||
Item::map->getSavedData(item, level);
|
||||
mapItemSavedData->removeItemFrameDecoration(item);
|
||||
// mapItemSavedData.decorations.remove("frame-" + entityId);
|
||||
}
|
||||
item->setFramed(nullptr);
|
||||
}
|
||||
|
||||
std::shared_ptr<ItemInstance> ItemFrame::getItem() {
|
||||
|
|
@ -72,7 +95,7 @@ void ItemFrame::addAdditonalSaveData(CompoundTag* tag) {
|
|||
if (getItem() != NULL) {
|
||||
tag->putCompound(L"Item", getItem()->save(new CompoundTag()));
|
||||
tag->putByte(L"ItemRotation", (uint8_t)getRotation());
|
||||
// tag->putFloat(L"ItemDropChance", dropChance);
|
||||
tag->putFloat(L"ItemDropChance", dropChance);
|
||||
}
|
||||
HangingEntity::addAdditonalSaveData(tag);
|
||||
}
|
||||
|
|
@ -83,8 +106,8 @@ void ItemFrame::readAdditionalSaveData(CompoundTag* tag) {
|
|||
setItem(ItemInstance::fromTag(itemTag));
|
||||
setRotation(tag->getByte(L"ItemRotation"));
|
||||
|
||||
// if (tag->contains(L"ItemDropChance")) dropChance =
|
||||
// tag->getFloat(L"ItemDropChance");
|
||||
if (tag->contains(L"ItemDropChance"))
|
||||
dropChance = tag->getFloat(L"ItemDropChance");
|
||||
}
|
||||
HangingEntity::readAdditionalSaveData(tag);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ private:
|
|||
static const int DATA_ITEM = 2;
|
||||
static const int DATA_ROTATION = 3;
|
||||
|
||||
float dropChance;
|
||||
|
||||
private:
|
||||
void _init();
|
||||
|
||||
|
|
@ -23,9 +25,15 @@ public:
|
|||
|
||||
protected:
|
||||
virtual void defineSynchedData();
|
||||
|
||||
public:
|
||||
virtual int getWidth() { return 9; }
|
||||
virtual int getHeight() { return 9; }
|
||||
virtual void dropItem();
|
||||
virtual bool shouldRenderAtSqrDistance(double distance);
|
||||
virtual void dropItem(std::shared_ptr<Entity> causedBy);
|
||||
|
||||
private:
|
||||
void removeFramedMap(std::shared_ptr<ItemInstance> item);
|
||||
|
||||
public:
|
||||
std::shared_ptr<ItemInstance> getItem();
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue