diff --git a/src/activeobject.h b/src/activeobject.h index 782b9a5..9d8a484 100644 --- a/src/activeobject.h +++ b/src/activeobject.h @@ -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 diff --git a/src/client.cpp b/src/client.cpp index 6e573e1..6dc115b 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -2131,7 +2131,7 @@ ClientActiveObject * Client::getSelectedActiveObject( objects.sort(); for (u32 i=0; i *selection_box = obj->getSelectionBox(); if (selection_box == NULL) diff --git a/src/clientobject.h b/src/clientobject.h index c6539e0..9c73d82 100644 --- a/src/clientobject.h +++ b/src/clientobject.h @@ -94,22 +94,5 @@ private: static core::map 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 diff --git a/src/content_mob.cpp b/src/content_mob.cpp index 331d2cd..50151ea 100644 --- a/src/content_mob.cpp +++ b/src/content_mob.cpp @@ -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.)); diff --git a/src/content_mob.h b/src/content_mob.h index 2a98f1e..58e2a0a 100644 --- a/src/content_mob.h +++ b/src/content_mob.h @@ -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; diff --git a/src/content_sao.cpp b/src/content_sao.cpp index 0b3cb96..cbd99ce 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -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="< 0) { + core::array 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; igetId() == 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 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; dxsecond; } +void ServerEnvironment::getActiveObjects(v3f origin, f32 max_d, core::array &dest) +{ + for (std::map::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); diff --git a/src/environment.h b/src/environment.h index 28d0d4d..96d2861 100644 --- a/src/environment.h +++ b/src/environment.h @@ -177,6 +177,9 @@ public: ServerActiveObject* getActiveObject(u16 id); + // Get all nearby objects + void getActiveObjects(v3f origin, f32 max_d, core::array &dest); + /* Add an active object to the environment. Environment handles deletion of object. diff --git a/src/servercommand.cpp b/src/servercommand.cpp index 30a94ba..8c62467 100644 --- a/src/servercommand.cpp +++ b/src/servercommand.cpp @@ -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")";