forked from Kolyah35/minecraft-pe-0.6.1
the whole game
This commit is contained in:
114
src/world/entity/monster/Creeper.cpp
Executable file
114
src/world/entity/monster/Creeper.cpp
Executable file
@@ -0,0 +1,114 @@
|
||||
#include "Creeper.h"
|
||||
#include "../Entity.h"
|
||||
#include "../../item/Item.h"
|
||||
#include "../../level/Level.h"
|
||||
#include "../../../nbt/CompoundTag.h"
|
||||
|
||||
Creeper::Creeper( Level* level )
|
||||
: super(level),
|
||||
swell(0),
|
||||
oldSwell(0),
|
||||
swellDir(-1)
|
||||
{
|
||||
entityRendererId = ER_CREEPER_RENDERER;
|
||||
this->textureName = "mob/creeper.png";
|
||||
|
||||
entityData.define(DATA_SWELL_DIR, (SynchedEntityData::TypeChar) -1);
|
||||
}
|
||||
|
||||
int Creeper::getMaxHealth() {
|
||||
return 16;
|
||||
}
|
||||
|
||||
void Creeper::tick() {
|
||||
oldSwell = swell;
|
||||
if (level->isClientSide) {
|
||||
int swellDir = getSwellDir();
|
||||
if (swellDir > 0 && swell == 0) {
|
||||
level->playSound(this, "random.fuse", 1, 0.5f);
|
||||
}
|
||||
swell += swellDir;
|
||||
if (swell < 0) swell = 0;
|
||||
if (swell >= MAX_SWELL) swell = MAX_SWELL;
|
||||
}
|
||||
super::tick();
|
||||
|
||||
if (!level->isClientSide && attackTargetId == 0) {
|
||||
if (swell > 0) {
|
||||
setSwellDir(-1);
|
||||
swell--;
|
||||
if (swell < 0) {
|
||||
swell = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float Creeper::getSwelling( float a ) {
|
||||
return (oldSwell + (swell - oldSwell) * a) / (MAX_SWELL - 2);
|
||||
}
|
||||
|
||||
int Creeper::getEntityTypeId() const {
|
||||
return MobTypes::Creeper;
|
||||
}
|
||||
|
||||
int Creeper::getDeathLoot() {
|
||||
return Item::sulphur->id;
|
||||
}
|
||||
|
||||
void Creeper::checkCantSeeTarget( Entity* target, float d ) {
|
||||
if (level->isClientSide) return;
|
||||
if (swell > 0) {
|
||||
setSwellDir(-1);
|
||||
swell--;
|
||||
if (swell < 0) {
|
||||
swell = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string Creeper::getHurtSound() {
|
||||
return "mob.creeper";
|
||||
}
|
||||
|
||||
std::string Creeper::getDeathSound() {
|
||||
return "mob.creeperdeath";
|
||||
}
|
||||
|
||||
void Creeper::checkHurtTarget( Entity* target, float d ) {
|
||||
if (level->isClientSide) return;
|
||||
const int swellDir = getSwellDir();
|
||||
if ((swellDir <= 0 && d < 3) || (swellDir > 0 && d < 7)) {
|
||||
if (swell == 0) {
|
||||
level->playSound(this, "random.fuse", 1, 0.5f);
|
||||
}
|
||||
setSwellDir(1);
|
||||
|
||||
if (++swell >= MAX_SWELL) {
|
||||
level->explode(this, x, y, z, 2.4f);
|
||||
remove();
|
||||
}
|
||||
holdGround = true;
|
||||
} else {
|
||||
setSwellDir(-1);
|
||||
if (--swell < 0)
|
||||
swell = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int Creeper::getSwellDir() {
|
||||
return (int) entityData.getByte(DATA_SWELL_DIR);
|
||||
}
|
||||
|
||||
void Creeper::setSwellDir( int dir ) {
|
||||
entityData.set(DATA_SWELL_DIR, (SynchedEntityData::TypeChar) dir);
|
||||
}
|
||||
|
||||
//@todo
|
||||
//void die(DamageSource* source) {
|
||||
// super::die(source);
|
||||
|
||||
// if (source.getEntity() instanceof Skeleton) {
|
||||
// spawnAtLocation(Item::record_01->id + random.nextInt(2), 1);
|
||||
// }
|
||||
//}
|
||||
46
src/world/entity/monster/Creeper.h
Executable file
46
src/world/entity/monster/Creeper.h
Executable file
@@ -0,0 +1,46 @@
|
||||
#ifndef NET_MINECRAFT_WORLD_ENTITY_MONSTER__Creeper_H__
|
||||
#define NET_MINECRAFT_WORLD_ENTITY_MONSTER__Creeper_H__
|
||||
|
||||
//package net.minecraft.world.entity.monster;
|
||||
|
||||
#include "Monster.h"
|
||||
#include <string>
|
||||
|
||||
class Entity;
|
||||
|
||||
class Creeper: public Monster
|
||||
{
|
||||
typedef Monster super;
|
||||
public:
|
||||
Creeper(Level* level);
|
||||
|
||||
/*@Override*/
|
||||
int getMaxHealth();
|
||||
|
||||
void tick();
|
||||
|
||||
float getSwelling(float a);
|
||||
|
||||
virtual int getEntityTypeId() const;
|
||||
protected:
|
||||
int getDeathLoot();
|
||||
|
||||
void checkCantSeeTarget(Entity* target, float d);
|
||||
void checkHurtTarget(Entity* target, float d);
|
||||
|
||||
std::string getHurtSound();
|
||||
std::string getDeathSound();
|
||||
private:
|
||||
int getSwellDir();
|
||||
void setSwellDir(int dir);
|
||||
|
||||
int swell;
|
||||
int oldSwell;
|
||||
|
||||
int swellDir;
|
||||
|
||||
static const int DATA_SWELL_DIR = 16;
|
||||
static const int MAX_SWELL = 30;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_WORLD_ENTITY_MONSTER__Creeper_H__*/
|
||||
144
src/world/entity/monster/Monster.cpp
Executable file
144
src/world/entity/monster/Monster.cpp
Executable file
@@ -0,0 +1,144 @@
|
||||
#include "Monster.h"
|
||||
|
||||
#include "../player/Player.h"
|
||||
#include "../../level/Level.h"
|
||||
#include "../../Difficulty.h"
|
||||
#include "../../../util/Mth.h"
|
||||
//#include "../../effect/MobEffect.h"
|
||||
|
||||
Monster::Monster(Level* level)
|
||||
: super(level),
|
||||
attackDamage(2),
|
||||
targetId(0),
|
||||
lastHurtByMobId(0)
|
||||
{
|
||||
entityRendererId = ER_HUMANOID_RENDERER;
|
||||
//xpReward = Enemy.XP_REWARD_MEDIUM;
|
||||
}
|
||||
|
||||
void Monster::aiStep()
|
||||
{
|
||||
updateAttackAnim();
|
||||
|
||||
float br = getBrightness(1);
|
||||
if (br > 0.5f) {
|
||||
noActionTime += 2;
|
||||
}
|
||||
super::aiStep();
|
||||
}
|
||||
|
||||
void Monster::tick()
|
||||
{
|
||||
super::tick();
|
||||
if (!level->isClientSide && level->difficulty == Difficulty::PEACEFUL) remove();
|
||||
}
|
||||
|
||||
bool Monster::hurt( Entity* sourceEntity, int dmg )
|
||||
{
|
||||
if (super::hurt(sourceEntity, dmg)) {
|
||||
if (sourceEntity != this) {
|
||||
attackTargetId = 0;
|
||||
if (sourceEntity != NULL) {
|
||||
attackTargetId = sourceEntity->entityId;
|
||||
if (sourceEntity->isMob())
|
||||
lastHurtByMobId = sourceEntity->entityId;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Monster::canSpawn()
|
||||
{
|
||||
return isDarkEnoughToSpawn() && super::canSpawn();
|
||||
}
|
||||
|
||||
Entity* Monster::findAttackTarget()
|
||||
{
|
||||
//Player* player = level->getNearestAttackablePlayer(this, 16);
|
||||
Player* player = level->getNearestPlayer(this, 16);
|
||||
//LOGI("playuer: %p\n", player);
|
||||
if (player != NULL && canSee(player)) return player;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool Monster::isDarkEnoughToSpawn()
|
||||
{
|
||||
//static int st = getTimeMs();
|
||||
//return getTimeMs() - st > 10000;
|
||||
|
||||
int xt = Mth::floor(x);
|
||||
int yt = Mth::floor(bb.y0);
|
||||
int zt = Mth::floor(z);
|
||||
if (level->getBrightness(LightLayer::Sky, xt, yt, zt) > random.nextInt(32)) return false;
|
||||
|
||||
int br = level->getRawBrightness(xt, yt, zt);
|
||||
|
||||
//if (level->isThundering()) {
|
||||
// int tmp = level->skyDarken;
|
||||
// level->skyDarken = 10;
|
||||
// br = level->getRawBrightness(xt, yt, zt);
|
||||
// level->skyDarken = tmp;
|
||||
//}
|
||||
//LOGI("br: %d\n", br);
|
||||
return br <= random.nextInt(8); // was 8
|
||||
}
|
||||
|
||||
bool Monster::doHurtTarget( Entity* target )
|
||||
{
|
||||
swing();
|
||||
//if (target->isMob()) setLastHurtMob(target);
|
||||
//@todo
|
||||
int dmg = attackDamage;
|
||||
//if (hasEffect(MobEffect.damageBoost)) {
|
||||
// dmg += (3 << getEffect(MobEffect.damageBoost).getAmplifier());
|
||||
//}
|
||||
//if (hasEffect(MobEffect.weakness)) {
|
||||
// dmg -= (2 << getEffect(MobEffect.weakness).getAmplifier());
|
||||
//}
|
||||
|
||||
return target->hurt(this, dmg);
|
||||
}
|
||||
|
||||
void Monster::checkHurtTarget( Entity* target, float distance ) {
|
||||
if (attackTime <= 0 && distance < 2.0f && target->bb.y1 > bb.y0 && target->bb.y0 < bb.y1) {
|
||||
attackTime = getAttackTime();
|
||||
doHurtTarget(target);
|
||||
}
|
||||
}
|
||||
|
||||
float Monster::getWalkTargetValue( int x, int y, int z )
|
||||
{
|
||||
return 0.5f - level->getBrightness(x, y, z);
|
||||
}
|
||||
|
||||
int Monster::getCreatureBaseType() const {
|
||||
return MobTypes::BaseEnemy;
|
||||
}
|
||||
|
||||
Mob* Monster::getTarget() {
|
||||
if (targetId == 0) return NULL;
|
||||
return level->getMob(targetId);
|
||||
}
|
||||
|
||||
void Monster::setTarget(Mob* mob) {
|
||||
targetId = mob? mob->entityId : 0;
|
||||
}
|
||||
|
||||
Mob* Monster::getLastHurtByMob() {
|
||||
if (targetId == 0) return NULL;
|
||||
return level->getMob(lastHurtByMobId);
|
||||
}
|
||||
|
||||
void Monster::setLastHurtByMob(Mob* mob) {
|
||||
lastHurtByMobId = mob? mob->entityId : 0;
|
||||
}
|
||||
|
||||
int Monster::getAttackDamage( Entity* target ) {
|
||||
return attackDamage;
|
||||
}
|
||||
|
||||
int Monster::getAttackTime() {
|
||||
return 20;
|
||||
}
|
||||
57
src/world/entity/monster/Monster.h
Executable file
57
src/world/entity/monster/Monster.h
Executable file
@@ -0,0 +1,57 @@
|
||||
#ifndef NET_MINECRAFT_WORLD_ENTITY_MONSTER__Monster_H__
|
||||
#define NET_MINECRAFT_WORLD_ENTITY_MONSTER__Monster_H__
|
||||
|
||||
//package net.minecraft.world.entity->monster;
|
||||
|
||||
#include "../PathfinderMob.h"
|
||||
|
||||
class Level;
|
||||
class Entity;
|
||||
//class DamageSource;
|
||||
class CompoundTag;
|
||||
|
||||
class Monster: public PathfinderMob//implements Enemy
|
||||
{
|
||||
typedef PathfinderMob super;
|
||||
public:
|
||||
Monster(Level* level);
|
||||
|
||||
void aiStep();
|
||||
void tick();
|
||||
|
||||
//bool hurt(DamageSource* source, int dmg) {
|
||||
bool hurt(Entity* sourceEntity, int dmg);
|
||||
|
||||
/*@Override*/
|
||||
bool canSpawn();
|
||||
|
||||
int getCreatureBaseType() const;
|
||||
|
||||
bool doHurtTarget(Entity* target);
|
||||
void setTarget(Mob* mob);
|
||||
Mob* getTarget();
|
||||
|
||||
Mob* getLastHurtByMob();
|
||||
void setLastHurtByMob(Mob* mob);
|
||||
virtual int getAttackDamage(Entity* target);
|
||||
protected:
|
||||
Entity* findAttackTarget();
|
||||
|
||||
bool isDarkEnoughToSpawn();
|
||||
/**
|
||||
* Performs hurt action, returns if successful
|
||||
*
|
||||
* @param target
|
||||
* @return
|
||||
*/
|
||||
void checkHurtTarget(Entity* target, float distance);
|
||||
|
||||
float getWalkTargetValue(int x, int y, int z);
|
||||
virtual int getAttackTime();
|
||||
int attackDamage;
|
||||
int targetId;
|
||||
|
||||
int lastHurtByMobId;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_WORLD_ENTITY_MONSTER__Monster_H__*/
|
||||
10
src/world/entity/monster/MonsterInclude.h
Executable file
10
src/world/entity/monster/MonsterInclude.h
Executable file
@@ -0,0 +1,10 @@
|
||||
#ifndef NET_MINECRAFT_WORLD_ENTITY_MONSTER__MonsterInclude_H__
|
||||
#define NET_MINECRAFT_WORLD_ENTITY_MONSTER__MonsterInclude_H__
|
||||
|
||||
#include "Creeper.h"
|
||||
#include "Monster.h"
|
||||
#include "Skeleton.h"
|
||||
#include "Spider.h"
|
||||
#include "Zombie.h"
|
||||
#include "PigZombie.h"
|
||||
#endif /*NET_MINECRAFT_WORLD_ENTITY_MONSTER__MonsterInclude_H__*/
|
||||
138
src/world/entity/monster/PigZombie.cpp
Executable file
138
src/world/entity/monster/PigZombie.cpp
Executable file
@@ -0,0 +1,138 @@
|
||||
#include "PigZombie.h"
|
||||
#include "../../item/Item.h"
|
||||
#include "../../level/Level.h"
|
||||
#include "../../Difficulty.h"
|
||||
#include "../Entity.h"
|
||||
#include "../projectile/Arrow.h"
|
||||
PigZombie::PigZombie( Level* level )
|
||||
: super(level)
|
||||
, angerTime(0)
|
||||
, playAngrySoundIn(0)
|
||||
, weapon(Item::sword_gold)
|
||||
, stunedTime(SharedConstants::TicksPerSecond * 3){
|
||||
textureName = "mob/pigzombie.png";
|
||||
runSpeed = 0.7f;
|
||||
fireImmune = true;
|
||||
attackDamage = 5;
|
||||
}
|
||||
|
||||
bool PigZombie::useNewAi() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void PigZombie::tick() {
|
||||
//runSpeed = attackTargetId != 0 ? 0.95f : 0.5f;
|
||||
if(stunedTime > 0)
|
||||
stunedTime--;
|
||||
if(playAngrySoundIn > 0) {
|
||||
if(--playAngrySoundIn == 0) {
|
||||
level->playSound(x, y, z, "mob.zombiepig.zpigangry", getSoundVolume() * 2, ((random.nextFloat() - random.nextFloat()) * 0.2f + 1.0f) * 1.8f);
|
||||
}
|
||||
}
|
||||
super::tick();
|
||||
}
|
||||
|
||||
std::string PigZombie::getTexture() {
|
||||
return "mob/pigzombie.png";
|
||||
}
|
||||
|
||||
bool PigZombie::canSpawn() {
|
||||
return level->difficulty > Difficulty::PEACEFUL && level->isUnobstructed(bb) && level->getCubes(this, bb).empty();
|
||||
}
|
||||
|
||||
void PigZombie::addAdditonalSaveData( CompoundTag* entityTag ) {
|
||||
super::addAdditonalSaveData(entityTag);
|
||||
entityTag->putShort("Anger", (short)angerTime);
|
||||
}
|
||||
|
||||
void PigZombie::readAdditionalSaveData( CompoundTag* tag ) {
|
||||
super::readAdditionalSaveData(tag);
|
||||
angerTime = tag->getShort("Anger");
|
||||
}
|
||||
|
||||
Entity* PigZombie::findAttackTarget() {
|
||||
if(stunedTime != 0)
|
||||
return NULL;
|
||||
if(angerTime == 0) {
|
||||
Entity* potentialTarget = super::findAttackTarget();
|
||||
if(potentialTarget != NULL && potentialTarget->distanceTo(x, y, z) < 5) {
|
||||
return potentialTarget;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
return super::findAttackTarget();
|
||||
}
|
||||
|
||||
bool PigZombie::hurt( Entity* sourceEntity, int dmg ) {
|
||||
Entity* attacker = NULL;
|
||||
if(sourceEntity != NULL) {
|
||||
if(sourceEntity->isPlayer()) {
|
||||
attacker = sourceEntity;
|
||||
}
|
||||
else if(sourceEntity->isEntityType(EntityTypes::IdArrow)) {
|
||||
Arrow* arrow = (Arrow*)sourceEntity;
|
||||
if(arrow->ownerId != 0) {
|
||||
attacker = level->getEntity(arrow->ownerId);
|
||||
if(!attacker->isPlayer())
|
||||
attacker = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(attacker != NULL) {
|
||||
EntityList nearby = level->getEntities(this, bb.grow(12, 12, 12));
|
||||
for(EntityList::iterator it = nearby.begin(); it != nearby.end(); ++it) {
|
||||
if((*it)->isEntityType(MobTypes::PigZombie)) {
|
||||
PigZombie* pigZombie = (PigZombie*)(*it);
|
||||
pigZombie->alert(sourceEntity);
|
||||
}
|
||||
}
|
||||
}
|
||||
return super::hurt(sourceEntity, dmg);
|
||||
}
|
||||
|
||||
void PigZombie::alert( Entity* target ) {
|
||||
attackTargetId = target->entityId;
|
||||
angerTime = 20 * 20 * random.nextInt(20 * 20);
|
||||
playAngrySoundIn = random.nextInt(20 * 2);
|
||||
}
|
||||
|
||||
const char* PigZombie::getAmbientSound() {
|
||||
return "mob.zombiepig.zpig";
|
||||
}
|
||||
|
||||
std::string PigZombie::getHurtSound() {
|
||||
return "mob.zombiepig.zpighurt";
|
||||
}
|
||||
|
||||
std::string PigZombie::getDeathSound() {
|
||||
return "mob.zombiepig.zpigdeath";
|
||||
}
|
||||
|
||||
void PigZombie::dropDeathLoot() {
|
||||
int count = random.nextInt(2);
|
||||
for(int i = 0; i < count; ++i) {
|
||||
// We really should spawn gold nuggets instead of ingots.
|
||||
spawnAtLocation(Item::goldIngot->id, 1);
|
||||
}
|
||||
}
|
||||
|
||||
bool PigZombie::interact( Player* player ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int PigZombie::getDeathLoot() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ItemInstance* PigZombie::getCarriedItem() {
|
||||
return &weapon;
|
||||
}
|
||||
|
||||
int PigZombie::getEntityTypeId() const {
|
||||
return MobTypes::PigZombie;
|
||||
}
|
||||
|
||||
int PigZombie::getAttackTime() {
|
||||
return 40;
|
||||
}
|
||||
38
src/world/entity/monster/PigZombie.h
Executable file
38
src/world/entity/monster/PigZombie.h
Executable file
@@ -0,0 +1,38 @@
|
||||
#ifndef NET_MINECRAFT_WORLD_ENTITY_MONSTER__PigZombie_H__
|
||||
#define NET_MINECRAFT_WORLD_ENTITY_MONSTER__PigZombie_H__
|
||||
|
||||
#include "Zombie.h"
|
||||
class ItemInstance;
|
||||
class PigZombie : public Zombie {
|
||||
typedef Zombie super;
|
||||
public:
|
||||
PigZombie(Level* level);
|
||||
bool useNewAi();
|
||||
void tick();
|
||||
std::string getTexture();
|
||||
bool canSpawn();
|
||||
void addAdditonalSaveData(CompoundTag* entityTag);
|
||||
void readAdditionalSaveData(CompoundTag* tag);
|
||||
bool hurt(Entity* sourceEntity, int dmg);
|
||||
bool interact(Player* player);
|
||||
int getEntityTypeId() const;
|
||||
virtual int getAttackTime();
|
||||
ItemInstance* getCarriedItem();
|
||||
protected:
|
||||
Entity* findAttackTarget();
|
||||
const char* getAmbientSound();
|
||||
std::string getHurtSound();
|
||||
std::string getDeathSound();
|
||||
void dropDeathLoot();
|
||||
int getDeathLoot();
|
||||
private:
|
||||
void alert(Entity* target);
|
||||
|
||||
private:
|
||||
int angerTime;
|
||||
int playAngrySoundIn;
|
||||
int stunedTime;
|
||||
ItemInstance weapon;
|
||||
};
|
||||
|
||||
#endif /* NET_MINECRAFT_WORLD_ENTITY_MONSTER__PigZombie_H__ */
|
||||
107
src/world/entity/monster/Skeleton.cpp
Executable file
107
src/world/entity/monster/Skeleton.cpp
Executable file
@@ -0,0 +1,107 @@
|
||||
#include "Skeleton.h"
|
||||
#include "../projectile/Arrow.h"
|
||||
|
||||
Skeleton::Skeleton( Level* level )
|
||||
: super(level),
|
||||
bow(Item::bow, 1),
|
||||
fireCheckTick(0)
|
||||
{
|
||||
entityRendererId = ER_SKELETON_RENDERER;
|
||||
this->textureName = "mob/skeleton.png";
|
||||
}
|
||||
|
||||
int Skeleton::getMaxHealth() {
|
||||
return 10; // 15
|
||||
}
|
||||
|
||||
void Skeleton::aiStep() {
|
||||
if ((++fireCheckTick & 1) && level->isDay() && !level->isClientSide) {
|
||||
float br = getBrightness(1);
|
||||
if (br > 0.5f) {
|
||||
if (level->canSeeSky(Mth::floor(x), Mth::floor(y), Mth::floor(z)) && random.nextFloat() * 3.5f < (br - 0.4f)) {
|
||||
hurt(NULL, 1);
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
float xa = (2.0f * random.nextFloat() - 1.0f) * (2.0f * random.nextFloat() - 1.0f) * 0.02f;
|
||||
float ya = (2.0f * random.nextFloat() - 1.0f) * (2.0f * random.nextFloat() - 1.0f) * 0.02f;
|
||||
float za = (2.0f * random.nextFloat() - 1.0f) * (2.0f * random.nextFloat() - 1.0f) * 0.02f;
|
||||
level->addParticle(PARTICLETYPE(explode), x + random.nextFloat() * bbWidth * 2 - bbWidth, y + random.nextFloat() * bbHeight, z + random.nextFloat() * bbWidth * 2 - bbWidth, xa, ya, za);
|
||||
}
|
||||
//setOnFire(8); //@todo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super::aiStep();
|
||||
}
|
||||
|
||||
int Skeleton::getDeathLoot() {
|
||||
return Item::arrow->id;
|
||||
}
|
||||
|
||||
ItemInstance* Skeleton::getCarriedItem() {
|
||||
return &bow;
|
||||
}
|
||||
|
||||
int Skeleton::getEntityTypeId() const {
|
||||
return MobTypes::Skeleton;
|
||||
}
|
||||
|
||||
const char* Skeleton::getAmbientSound() {
|
||||
return "mob.skeleton";
|
||||
}
|
||||
|
||||
std::string Skeleton::getHurtSound() {
|
||||
return "mob.skeletonhurt";
|
||||
}
|
||||
|
||||
std::string Skeleton::getDeathSound() {
|
||||
return "mob.skeletonhurt";
|
||||
}
|
||||
|
||||
void Skeleton::checkHurtTarget( Entity* target, float d ) {
|
||||
if (d < 10) {
|
||||
float xd = target->x - x;
|
||||
float zd = target->z - z;
|
||||
|
||||
if (attackTime == 0) {
|
||||
Arrow* arrow = new Arrow(level, this, 1);
|
||||
// arrow.y += 1.4f;
|
||||
|
||||
float yd = (target->y + target->getHeadHeight() - 0.7f) - arrow->y;
|
||||
|
||||
float yo = Mth::sqrt(xd * xd + zd * zd) * 0.2f;
|
||||
|
||||
level->playSound(this, "random.bow", 1.0f, 1 / (random.nextFloat() * 0.4f + 0.8f));
|
||||
level->addEntity(arrow);
|
||||
|
||||
arrow->shoot(xd, yd + yo, zd, 1.60f, 32);
|
||||
attackTime = SharedConstants::TicksPerSecond * 3;
|
||||
}
|
||||
yRot = (float) (std::atan2(zd, xd) * Mth::RADDEG) - 90;
|
||||
|
||||
holdGround = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Skeleton::dropDeathLoot( /*bool wasKilledByPlayer, int playerBonusLevel*/ ) {
|
||||
// drop some arrows
|
||||
int count = random.nextInt(3 /*+ playerBonusLevel*/);
|
||||
for (int i = 0; i < count; i++) {
|
||||
spawnAtLocation(Item::arrow->id, 1);
|
||||
}
|
||||
// and some bones
|
||||
count = random.nextInt(3 /*+ playerBonusLevel*/);
|
||||
for (int i = 0; i < count; i++) {
|
||||
spawnAtLocation(Item::bone->id, 1);
|
||||
}
|
||||
}
|
||||
|
||||
int Skeleton::getUseDuration() {
|
||||
return attackTime;
|
||||
}
|
||||
|
||||
/*@Override*/
|
||||
// MobType getMobType() {
|
||||
// return MobType.UNDEAD;
|
||||
// }
|
||||
43
src/world/entity/monster/Skeleton.h
Executable file
43
src/world/entity/monster/Skeleton.h
Executable file
@@ -0,0 +1,43 @@
|
||||
#ifndef NET_MINECRAFT_WORLD_ENTITY_MONSTER__Skeleton_H__
|
||||
#define NET_MINECRAFT_WORLD_ENTITY_MONSTER__Skeleton_H__
|
||||
|
||||
//package net.minecraft.world.entity->monster;
|
||||
|
||||
#include "Monster.h"
|
||||
#include <string>
|
||||
#include "../../item/ItemInstance.h"
|
||||
|
||||
class Level;
|
||||
class Entity;
|
||||
|
||||
class Skeleton: public Monster
|
||||
{
|
||||
typedef Monster super;
|
||||
public:
|
||||
Skeleton(Level* level);
|
||||
|
||||
/*@Override*/
|
||||
int getMaxHealth();
|
||||
|
||||
void aiStep();
|
||||
|
||||
int getDeathLoot();
|
||||
|
||||
ItemInstance* getCarriedItem();
|
||||
|
||||
virtual int getEntityTypeId() const;
|
||||
protected:
|
||||
const char* getAmbientSound();
|
||||
std::string getHurtSound();
|
||||
std::string getDeathSound();
|
||||
|
||||
void checkHurtTarget(Entity* target, float d);
|
||||
/*@Override*/
|
||||
void dropDeathLoot(/*bool wasKilledByPlayer, int playerBonusLevel*/);
|
||||
virtual int getUseDuration();
|
||||
private:
|
||||
ItemInstance bow;
|
||||
int fireCheckTick;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_WORLD_ENTITY_MONSTER__Skeleton_H__*/
|
||||
137
src/world/entity/monster/Spider.cpp
Executable file
137
src/world/entity/monster/Spider.cpp
Executable file
@@ -0,0 +1,137 @@
|
||||
#include "Spider.h"
|
||||
#include "../../item/Item.h"
|
||||
#include "../../level/Level.h"
|
||||
#include "../../../util/Mth.h"
|
||||
|
||||
Spider::Spider( Level* level )
|
||||
: super(level),
|
||||
fireCheckTick(0)
|
||||
{
|
||||
entityRendererId = ER_SPIDER_RENDERER;
|
||||
this->textureName = "mob/spider.png";
|
||||
|
||||
this->setSize(1.4f, 0.9f);
|
||||
runSpeed = 0.5f;
|
||||
|
||||
entityData.define(DATA_FLAGS_ID, (DataFlagIdType) 0);
|
||||
}
|
||||
|
||||
void Spider::aiStep() {
|
||||
super::aiStep();
|
||||
}
|
||||
|
||||
void Spider::tick() {
|
||||
super::tick();
|
||||
|
||||
if (!level->isClientSide) {
|
||||
// this is to synchronize the spiders' climb state
|
||||
// in multiplayer (to stop them from "flashing")
|
||||
setClimbing(horizontalCollision);
|
||||
}
|
||||
}
|
||||
|
||||
int Spider::getMaxHealth() {
|
||||
return 8; // 12
|
||||
}
|
||||
|
||||
bool Spider::onLadder() {
|
||||
return isClimbing();
|
||||
}
|
||||
|
||||
void Spider::makeStuckInWeb() {
|
||||
// do nothing - spiders don't get stuck in web
|
||||
}
|
||||
|
||||
float Spider::getModelScale() {
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
bool Spider::isClimbing() {
|
||||
return entityData.getFlag<DataFlagIdType>(DATA_FLAGS_ID, 0);
|
||||
}
|
||||
|
||||
void Spider::setClimbing( bool value ) {
|
||||
if (value)
|
||||
return entityData.setFlag<DataFlagIdType>(DATA_FLAGS_ID, 0);
|
||||
else
|
||||
return entityData.clearFlag<DataFlagIdType>(DATA_FLAGS_ID, 0);
|
||||
}
|
||||
|
||||
int Spider::getEntityTypeId() const {
|
||||
return MobTypes::Spider;
|
||||
}
|
||||
|
||||
bool Spider::makeStepSound() {
|
||||
return false;
|
||||
}
|
||||
|
||||
Entity* Spider::findAttackTarget() {
|
||||
float br = getBrightness(1);
|
||||
if (br < 0.5f) {
|
||||
return level->getNearestPlayer(this, 16);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* Spider::getAmbientSound() {
|
||||
return "mob.spider";
|
||||
}
|
||||
|
||||
std::string Spider::getHurtSound() {
|
||||
return "mob.spider";
|
||||
}
|
||||
|
||||
std::string Spider::getDeathSound() {
|
||||
return "mob.spiderdeath";
|
||||
}
|
||||
|
||||
void Spider::checkHurtTarget( Entity* target, float d ) {
|
||||
float br = getBrightness(1);
|
||||
if (br > 0.5f && random.nextInt(100) == 0) {
|
||||
attackTargetId = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (d > 2 && d < 6 && random.nextInt(10) == 0) {
|
||||
if (onGround) {
|
||||
float xdd = target->x - x;
|
||||
float zdd = target->z - z;
|
||||
float dd = Mth::sqrt(xdd * xdd + zdd * zdd);
|
||||
xd = (xdd / dd * 0.5f) * 0.8f + xd * 0.2f;
|
||||
zd = (zdd / dd * 0.5f) * 0.8f + zd * 0.2f;
|
||||
yd = 0.4f;
|
||||
}
|
||||
} else {
|
||||
super::checkHurtTarget(target, d);
|
||||
}
|
||||
}
|
||||
|
||||
int Spider::getDeathLoot() {
|
||||
return Item::string->id;
|
||||
}
|
||||
|
||||
//void dropDeathLoot(/*bool wasKilledByPlayer, int playerBonusLevel*/) {
|
||||
// super::dropDeathLoot(/*wasKilledByPlayer, playerBonusLevel*/);
|
||||
|
||||
//// if (wasKilledByPlayer && (random.nextInt(3) == 0 || random.nextInt(1 + playerBonusLevel) > 0)) {
|
||||
//// spawnAtLocation(Item::spiderEye->id, 1);
|
||||
//// }
|
||||
//}
|
||||
|
||||
//float getRideHeight() {
|
||||
// return bbHeight * .75f - 0.5f;
|
||||
//}
|
||||
|
||||
/*@Override*/
|
||||
// MobType getMobType() {
|
||||
// return MobType.ARTHROPOD;
|
||||
// }
|
||||
|
||||
/*@Override*/ //@todo
|
||||
// bool canBeAffected(MobEffectInstance newEffect) {
|
||||
// if (newEffect.getId() == MobEffect.poison.id) {
|
||||
// return false;
|
||||
// }
|
||||
// return super::canBeAffected(newEffect);
|
||||
// }
|
||||
//
|
||||
62
src/world/entity/monster/Spider.h
Executable file
62
src/world/entity/monster/Spider.h
Executable file
@@ -0,0 +1,62 @@
|
||||
#ifndef NET_MINECRAFT_WORLD_ENTITY_MONSTER__Spider_H__
|
||||
#define NET_MINECRAFT_WORLD_ENTITY_MONSTER__Spider_H__
|
||||
|
||||
//package net.minecraft.world.entity->monster;
|
||||
|
||||
#include "Monster.h"
|
||||
#include <string>
|
||||
|
||||
class Level;
|
||||
class Entity;
|
||||
|
||||
class Spider: public Monster
|
||||
{
|
||||
typedef Monster super;
|
||||
typedef SynchedEntityData::TypeChar DataFlagIdType;
|
||||
static const int DATA_FLAGS_ID = 16;
|
||||
public:
|
||||
Spider(Level* level);
|
||||
|
||||
/*@Override*/
|
||||
void aiStep();
|
||||
/*@Override*/
|
||||
void tick();
|
||||
|
||||
/*@Override*/
|
||||
int getMaxHealth();
|
||||
|
||||
/**
|
||||
* The the spiders act as if they're always on a ladder, which enables them
|
||||
* to climb walls.
|
||||
*/
|
||||
/*@Override*/ //@todo
|
||||
bool onLadder();
|
||||
|
||||
/*@Override*/
|
||||
void makeStuckInWeb();
|
||||
|
||||
float getModelScale();
|
||||
|
||||
bool isClimbing();
|
||||
void setClimbing(bool value);
|
||||
|
||||
virtual int getEntityTypeId() const;
|
||||
|
||||
protected:
|
||||
/*@Override*/
|
||||
bool makeStepSound();
|
||||
|
||||
Entity* findAttackTarget();
|
||||
|
||||
const char* getAmbientSound();
|
||||
std::string getHurtSound();
|
||||
std::string getDeathSound();
|
||||
|
||||
void checkHurtTarget(Entity* target, float d);
|
||||
int fireCheckTick;
|
||||
int getDeathLoot();
|
||||
/*@Override*/
|
||||
//void dropDeathLoot();
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_WORLD_ENTITY_MONSTER__Spider_H__*/
|
||||
129
src/world/entity/monster/Zombie.cpp
Executable file
129
src/world/entity/monster/Zombie.cpp
Executable file
@@ -0,0 +1,129 @@
|
||||
#include "Zombie.h"
|
||||
|
||||
#include "../../item/Item.h"
|
||||
#include "../../level/Level.h"
|
||||
#include "../../../util/Mth.h"
|
||||
//#include "../MobType.h"
|
||||
#include "../ai/goal/GoalSelector.h"
|
||||
#include "../ai/control/JumpControl.h"
|
||||
#include "../ai/goal/RandomStrollGoal.h"
|
||||
#include "../ai/goal/MeleeAttackGoal.h"
|
||||
#include "../ai/goal/target/NearestAttackableTargetGoal.h"
|
||||
#include "../ai/goal/target/HurtByTargetGoal.h"
|
||||
#include "../ai/goal/BreakDoorGoal.h"
|
||||
|
||||
Zombie::Zombie( Level* level )
|
||||
: super(level),
|
||||
fireCheckTick(0),
|
||||
_useNewAi(false)
|
||||
{
|
||||
entityRendererId = ER_ZOMBIE_RENDERER;
|
||||
this->textureName = "mob/zombie.png";
|
||||
//pathfinderMask |= CAN_OPEN_DOORS;
|
||||
//navigation->canOpenDoors = true;
|
||||
|
||||
runSpeed = 0.5f;
|
||||
attackDamage = 4;
|
||||
|
||||
targetSelector = new GoalSelector();
|
||||
targetSelector->addGoal(1, new HurtByTargetGoal(this, false));
|
||||
targetSelector->addGoal(2, new NearestAttackableTargetGoal(this, 1, 16, 0, true));
|
||||
|
||||
goalSelector = new GoalSelector();
|
||||
//goalSelector->addGoal(1, new BreakDoorGoal(this));
|
||||
goalSelector->addGoal(2, new MeleeAttackGoal(this, runSpeed, false, 0));
|
||||
goalSelector->addGoal(7, new RandomStrollGoal(this, runSpeed) );
|
||||
|
||||
moveControl = new MoveControl(this);
|
||||
jumpControl = new JumpControl(this);
|
||||
}
|
||||
|
||||
Zombie::~Zombie() {
|
||||
delete goalSelector;
|
||||
delete targetSelector;
|
||||
|
||||
delete moveControl;
|
||||
delete jumpControl;
|
||||
}
|
||||
|
||||
int Zombie::getMaxHealth() {
|
||||
return 12; // 16
|
||||
}
|
||||
|
||||
void Zombie::aiStep() {
|
||||
if ((++fireCheckTick & 1) && level->isDay() && !level->isClientSide) {
|
||||
float br = getBrightness(1);
|
||||
if (br > 0.5f) {
|
||||
if (level->canSeeSky(Mth::floor(x), Mth::floor(y), Mth::floor(z)) && random.nextFloat() * 3.5f < (br - 0.4f)) {
|
||||
hurt(NULL, 1);
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
float xa = (2.0f * random.nextFloat() - 1.0f) * (2.0f * random.nextFloat() - 1.0f) * 0.02f;
|
||||
float ya = (2.0f * random.nextFloat() - 1.0f) * (2.0f * random.nextFloat() - 1.0f) * 0.02f;
|
||||
float za = (2.0f * random.nextFloat() - 1.0f) * (2.0f * random.nextFloat() - 1.0f) * 0.02f;
|
||||
level->addParticle(PARTICLETYPE(explode), x + random.nextFloat() * bbWidth * 2 - bbWidth, y + random.nextFloat() * bbHeight, z + random.nextFloat() * bbWidth * 2 - bbWidth, xa, ya, za);
|
||||
}
|
||||
//setOnFire(8); //@todo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
super::aiStep();
|
||||
}
|
||||
|
||||
int Zombie::getEntityTypeId() const {
|
||||
return MobTypes::Zombie;
|
||||
}
|
||||
|
||||
void Zombie::setUseNewAi( bool use ) {
|
||||
_useNewAi = use;
|
||||
}
|
||||
|
||||
int Zombie::getArmorValue() {
|
||||
int armor = super::getArmorValue() + 2;
|
||||
if (armor > 20) armor = 20;
|
||||
return armor;
|
||||
}
|
||||
|
||||
const char* Zombie::getAmbientSound() {
|
||||
return "mob.zombie";
|
||||
}
|
||||
|
||||
std::string Zombie::getHurtSound() {
|
||||
return "mob.zombiehurt";
|
||||
}
|
||||
|
||||
std::string Zombie::getDeathSound() {
|
||||
return "mob.zombiedeath";
|
||||
}
|
||||
|
||||
int Zombie::getDeathLoot() {
|
||||
return 0; //@todo
|
||||
//return Item::rotten_flesh->id;
|
||||
}
|
||||
|
||||
bool Zombie::useNewAi() {
|
||||
return _useNewAi;
|
||||
}
|
||||
|
||||
void Zombie::die( Entity* source ) {
|
||||
super::die(source);
|
||||
if(!level->isClientSide) {
|
||||
if(random.nextInt(4) == 0) {
|
||||
spawnAtLocation(Item::feather->id, random.nextInt(1) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int Zombie::getAttackDamage( Entity* target ) {
|
||||
ItemInstance* weapon = getCarriedItem();
|
||||
int damage = attackDamage;
|
||||
if(weapon != NULL) damage += weapon->getAttackDamage(this);
|
||||
return damage;
|
||||
}
|
||||
|
||||
/*@Override*/ //@todo?
|
||||
//MobType getMobType() {
|
||||
// return MobType::UNDEAD;
|
||||
//}
|
||||
|
||||
44
src/world/entity/monster/Zombie.h
Executable file
44
src/world/entity/monster/Zombie.h
Executable file
@@ -0,0 +1,44 @@
|
||||
#ifndef NET_MINECRAFT_WORLD_ENTITY_MONSTER__Zombie_H__
|
||||
#define NET_MINECRAFT_WORLD_ENTITY_MONSTER__Zombie_H__
|
||||
|
||||
//package net.minecraft.world.entity->monster;
|
||||
|
||||
#include "Monster.h"
|
||||
#include <string>
|
||||
|
||||
class Level;
|
||||
|
||||
class Zombie: public Monster
|
||||
{
|
||||
typedef Monster super;
|
||||
public:
|
||||
Zombie(Level* level);
|
||||
|
||||
~Zombie();
|
||||
|
||||
/*@Override*/
|
||||
int getMaxHealth();
|
||||
|
||||
void aiStep();
|
||||
virtual int getEntityTypeId() const;
|
||||
void setUseNewAi(bool use);
|
||||
virtual void die(Entity* source);
|
||||
virtual int getAttackDamage(Entity* target);
|
||||
protected:
|
||||
/*@Override*/
|
||||
int getArmorValue();
|
||||
|
||||
const char* getAmbientSound();
|
||||
std::string getHurtSound();
|
||||
std::string getDeathSound();
|
||||
|
||||
//@todo
|
||||
int getDeathLoot();
|
||||
|
||||
virtual bool useNewAi();
|
||||
|
||||
int fireCheckTick;
|
||||
bool _useNewAi;
|
||||
};
|
||||
|
||||
#endif /*NET_MINECRAFT_WORLD_ENTITY_MONSTER__Zombie_H__*/
|
||||
Reference in New Issue
Block a user