allow objects to damage other objects

This commit is contained in:
darkrose 2014-12-07 18:27:58 +10:00
parent f592e2620e
commit 675e9f3aa3
10 changed files with 87 additions and 25 deletions

View File

@ -73,5 +73,22 @@ protected:
u16 m_id; // 0 is invalid, "no id"
};
struct DistanceSortedActiveObject
{
ActiveObject *obj;
f32 d;
DistanceSortedActiveObject(ActiveObject *a_obj, f32 a_d)
{
obj = a_obj;
d = a_d;
}
bool operator < (DistanceSortedActiveObject &other)
{
return d < other.d;
}
};
#endif

View File

@ -2131,7 +2131,7 @@ ClientActiveObject * Client::getSelectedActiveObject(
objects.sort();
for (u32 i=0; i<objects.size(); i++) {
ClientActiveObject *obj = objects[i].obj;
ClientActiveObject *obj = (ClientActiveObject*)objects[i].obj;
core::aabbox3d<f32> *selection_box = obj->getSelectionBox();
if (selection_box == NULL)

View File

@ -94,22 +94,5 @@ private:
static core::map<u16, Factory> m_types;
};
struct DistanceSortedActiveObject
{
ClientActiveObject *obj;
f32 d;
DistanceSortedActiveObject(ClientActiveObject *a_obj, f32 a_d)
{
obj = a_obj;
d = a_d;
}
bool operator < (DistanceSortedActiveObject &other)
{
return d < other.d;
}
};
#endif

View File

@ -105,6 +105,8 @@ bool content_mob_spawn(ServerEnvironment *env, v3s16 pos, u32 active_object_coun
if (active_object_count > 20)
return false;
int rand = myrand();
if (pos.Y < 0 && rand%2 == 0)
return false;
assert(env);
Map *map = &env->getMap();
@ -321,7 +323,7 @@ void content_mob_init()
f->spawn_on = CONTENT_WILDGRASS_SHORT;
f->spawn_in = CONTENT_AIR;
f->spawn_min_height = -5;
f->spawn_max_height = 30;
f->spawn_max_height = 40;
f->spawn_min_light = LIGHT_MAX/2;
f->spawn_max_nearby_mobs = 3;
f->lifetime = 900.0;
@ -349,7 +351,7 @@ void content_mob_init()
f->spawn_on = CONTENT_WILDGRASS_SHORT;
f->spawn_in = CONTENT_AIR;
f->spawn_min_height = -5;
f->spawn_max_height = 30;
f->spawn_max_height = 40;
f->spawn_min_light = LIGHT_MAX/2;
f->spawn_max_nearby_mobs = 3;
f->spawn_chance = 2;
@ -454,7 +456,7 @@ void content_mob_init()
f->spawn_on = CONTENT_WILDGRASS_LONG;
f->spawn_in = CONTENT_AIR;
f->spawn_min_height = 0;
f->spawn_max_height = 30;
f->spawn_max_height = 40;
f->spawn_max_light = LIGHT_MAX/2;
f->spawn_max_nearby_mobs = 3;
f->notices_player = true;
@ -481,6 +483,8 @@ void content_mob_init()
f->motion = MM_SEEKER;
f->motion_type = MMT_WALK;
f->notices_player = true;
f->attack_mob_damage = 5;
f->attack_mob_range = v3f(1,1,1);
f->lifetime = 900.0;
f->setCollisionBox(aabb3f(-0.5*BS, 0., -0.5*BS, 0.5*BS, 1.*BS, 0.5*BS));
@ -508,7 +512,7 @@ void content_mob_init()
f->spawn_on = CONTENT_WILDGRASS_SHORT;
f->spawn_in = CONTENT_AIR;
f->spawn_min_height = 2;
f->spawn_max_height = 20;
f->spawn_max_height = 50;
f->spawn_min_light = LIGHT_MAX/2;
f->spawn_max_nearby_mobs = 3;
f->lifetime = 900.0;
@ -526,6 +530,8 @@ void content_mob_init()
f->notices_player = true;
f->attack_player_damage = 1;
f->attack_player_range = v3f(1,1,1);
f->attack_mob_damage = 5;
f->attack_mob_range = v3f(1,1,1);
f->lifetime = 10.0;
f->contact_place_node = CONTENT_SNOW;
f->contact_drop_item = CONTENT_CRAFTITEM_SNOW_BALL;
@ -544,6 +550,8 @@ void content_mob_init()
f->notices_player = true;
f->attack_player_damage = 1;
f->attack_player_range = v3f(1,1,1);
f->attack_mob_damage = 20;
f->attack_mob_range = v3f(1,1,1);
f->lifetime = 20.0;
f->contact_drop_item = CONTENT_CRAFTITEM_ARROW;
f->setCollisionBox(aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.));

View File

@ -118,6 +118,8 @@ struct MobFeatures {
v3f attack_throw_offset;
u8 attack_player_damage;
v3f attack_player_range;
u8 attack_mob_damage;
v3f attack_mob_range;
u8 glow_light;
u8 attack_glow_light;
u16 hp;
@ -242,6 +244,8 @@ struct MobFeatures {
attack_throw_offset = v3f(0,0,0);
attack_player_damage = 0;
attack_player_range = v3f(0,0,0);
attack_mob_damage = 0;
attack_mob_range = v3f(0,0,0);
glow_light = 0;
attack_glow_light = 0;
hp = 20;

View File

@ -450,7 +450,7 @@ void MobSAO::step(float dtime, bool send_recommended)
v3f playerpos = player->getPosition();
f32 dist = m_base_position.getDistanceFrom(playerpos);
if (dist < BS*16) {
if (dist < BS*3 || myrand_range(0,3) == 0) {
if (dist < BS*8 || myrand_range(0,2) == 0) {
actionstream<<"Mob id="<<m_id<<" at "
<<PP(m_base_position/BS)
<<" got randomly disturbed by "
@ -536,6 +536,32 @@ void MobSAO::step(float dtime, bool send_recommended)
}
}
if (m.attack_mob_damage > 0) {
core::array<DistanceSortedActiveObject> objects;
f32 range = m.attack_mob_range.X;
if (m.attack_mob_range.Y > range)
range = m.attack_mob_range.Y;
if (m.attack_mob_range.Z > range)
range = m.attack_mob_range.Z;
m_env->getActiveObjects(m_base_position, range*BS, objects);
// Sort them.
// After this, the closest object is the first in the array.
objects.sort();
for (u32 i=0; i<objects.size(); i++) {
ServerActiveObject *obj = (ServerActiveObject*)objects[i].obj;
if (obj->getId() == m_id)
continue;
if (obj->getType() == ACTIVEOBJECT_TYPE_MOB) {
((MobSAO*)obj)->doDamage(m.attack_mob_damage);
}else if (obj->getType() == ACTIVEOBJECT_TYPE_ITEM) {
((ItemSAO*)obj)->m_removed = true;
}
}
}
MobMotion mot = getMotion();
if (mot != MM_CONSTANT && mot != MM_STATIC) {
@ -1188,6 +1214,11 @@ void MobSAO::explodeSquare(v3s16 p0, v3s16 size)
Map *map = &m_env->getMap();
core::map<v3s16, MapBlock*> modified_blocks;
if (content_mob_features(m_content).level != MOB_DESTRUCTIVE) {
if (m_env->searchNear(p0,size+v3s16(5,5,5),CONTENT_BORDERSTONE,NULL))
return;
}
for (int dx=0; dx<size.X; dx++)
for (int dy=0; dy<size.Y; dy++)
for (int dz=0; dz<size.Z; dz++) {

View File

@ -72,9 +72,9 @@ public:
u16 punch(content_t punch_item, v3f dir, const std::string &playername);
bool rightClick(Player *player);
u8 level();
void doDamage(u16 d);
private:
void sendPosition();
void doDamage(u16 d);
MobMotion getMotion()
{

View File

@ -2824,6 +2824,22 @@ ServerActiveObject* ServerEnvironment::getActiveObject(u16 id)
return i->second;
}
void ServerEnvironment::getActiveObjects(v3f origin, f32 max_d, core::array<DistanceSortedActiveObject> &dest)
{
for (std::map<u16, ServerActiveObject*>::iterator i = m_active_objects.begin(); i != m_active_objects.end(); i++) {
ServerActiveObject* obj = i->second;
f32 d = (obj->getBasePosition() - origin).getLength();
if (d > max_d)
continue;
DistanceSortedActiveObject dso(obj, d);
dest.push_back(dso);
}
}
bool ServerEnvironment::propogateEnergy(u8 level, v3s16 powersrc, v3s16 signalsrc, v3s16 pos)
{
MapNode n = m_map->getNodeNoEx(pos);

View File

@ -177,6 +177,9 @@ public:
ServerActiveObject* getActiveObject(u16 id);
// Get all nearby objects
void getActiveObjects(v3f origin, f32 max_d, core::array<DistanceSortedActiveObject> &dest);
/*
Add an active object to the environment.
Environment handles deletion of object.

View File

@ -312,7 +312,7 @@ void cmd_clearobjects(std::wostringstream &os,
{
std::wstring msg;
msg += L"Clearing all objects. This may take long.";
msg += L"Clearing all objects. This may take a long time.";
msg += L" You may experience a timeout. (by ";
msg += narrow_to_wide(ctx->player->getName());
msg += L")";