forked from oerkki/voxelands
improved mob spawning, pt1
This commit is contained in:
parent
18953b1333
commit
70636b3b4a
|
@ -6331,7 +6331,6 @@ Frame Root {
|
||||||
123.529412;
|
123.529412;
|
||||||
0.000000; 0.000000; 0.000000;;
|
0.000000; 0.000000; 0.000000;;
|
||||||
0.000000; 0.000000; 0.000000;;
|
0.000000; 0.000000; 0.000000;;
|
||||||
TextureFilename {"mob_doe.png";}
|
|
||||||
}
|
}
|
||||||
} // End of Cube_002 material list
|
} // End of Cube_002 material list
|
||||||
XSkinMeshHeader {
|
XSkinMeshHeader {
|
||||||
|
|
|
@ -130,46 +130,12 @@ bool content_mob_spawn(ServerEnvironment *env, v3s16 pos, u32 active_object_coun
|
||||||
if ((c1 != CONTENT_AIR && c1 != CONTENT_WATERSOURCE) && c1 != c2)
|
if ((c1 != CONTENT_AIR && c1 != CONTENT_WATERSOURCE) && c1 != c2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
u8 light = a1.getLightBlend(env->getDayNightRatio());
|
|
||||||
u8 level = mobLevelI(g_settings->get("max_mob_level"));
|
|
||||||
v3f pf = intToFloat(pos,BS);
|
|
||||||
Player *nearest = env->getNearestConnectedPlayer(pf);
|
|
||||||
f32 distance = 30000.0;
|
|
||||||
if (nearest)
|
|
||||||
distance = pf.getDistanceFrom(nearest->getPosition());
|
|
||||||
|
|
||||||
for (u16 i=0; i<CONTENT_MOB_COUNT; i++) {
|
for (u16 i=0; i<CONTENT_MOB_COUNT; i++) {
|
||||||
MobFeatures m = g_content_mob_features[i];
|
MobFeatures m = g_content_mob_features[i];
|
||||||
if (m.spawn_in == CONTENT_IGNORE && m.spawn_on == CONTENT_IGNORE)
|
|
||||||
continue;
|
|
||||||
if (m.spawn_max_nearby_mobs < active_object_count)
|
|
||||||
continue;
|
|
||||||
if (m.spawn_min_height > pos.Y)
|
if (m.spawn_min_height > pos.Y)
|
||||||
continue;
|
continue;
|
||||||
if (m.spawn_max_height < pos.Y)
|
if (m.spawn_max_height < pos.Y)
|
||||||
continue;
|
continue;
|
||||||
if (m.spawn_in != CONTENT_IGNORE) {
|
|
||||||
if (m.spawn_in != c1)
|
|
||||||
continue;
|
|
||||||
if (m.spawn_in != c2)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (m.spawn_on != CONTENT_IGNORE) {
|
|
||||||
if (m.spawn_on != c0)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (m.spawn_min_light > light)
|
|
||||||
continue;
|
|
||||||
if (m.spawn_max_light < light)
|
|
||||||
continue;
|
|
||||||
if (m.level > level)
|
|
||||||
continue;
|
|
||||||
if (m.notices_player && m.spawn_nearest_player != m.spawn_farthest_player) {
|
|
||||||
if (m.spawn_nearest_player > distance)
|
|
||||||
continue;
|
|
||||||
if (m.spawn_farthest_player < distance)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (m.spawn_chance > 1 && rand%m.spawn_chance != 0)
|
if (m.spawn_chance > 1 && rand%m.spawn_chance != 0)
|
||||||
continue;
|
continue;
|
||||||
can.push_back(i);
|
can.push_back(i);
|
||||||
|
@ -204,6 +170,196 @@ bool content_mob_spawn(ServerEnvironment *env, v3s16 pos, u32 active_object_coun
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void mob_spawn(v3s16 pos, content_t mob, ServerEnvironment *env)
|
||||||
|
{
|
||||||
|
|
||||||
|
MobFeatures &m = content_mob_features(mob);
|
||||||
|
|
||||||
|
if (m.content == CONTENT_IGNORE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
v3f p = intToFloat(pos+v3s16(0,1,0), BS);
|
||||||
|
actionstream<<"A mob of type "<<m.content<<" spawns at "<<PP(floatToInt(p,BS))<<std::endl;
|
||||||
|
ServerActiveObject *obj = new MobSAO(env, 0, p, m.content);
|
||||||
|
u16 id = env->addActiveObject(obj);
|
||||||
|
if (!id) {
|
||||||
|
actionstream<<"A mob of type "<<m.content<<" didn't spawn at "<<PP(floatToInt(p,BS))<<std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id && m.sound_spawn != "")
|
||||||
|
env->addEnvEvent(ENV_EVENT_SOUND,p,m.sound_spawn);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mob_spawn_passive(v3s16 pos, bool water, ServerEnvironment *env)
|
||||||
|
{
|
||||||
|
std::vector<content_t> can;
|
||||||
|
int rand = myrand();
|
||||||
|
for (u16 i=0; i<CONTENT_MOB_COUNT; i++) {
|
||||||
|
MobFeatures m = g_content_mob_features[i];
|
||||||
|
if (!m.spawn_naturally)
|
||||||
|
continue;
|
||||||
|
if (m.level > MOB_PASSIVE)
|
||||||
|
continue;
|
||||||
|
if (m.spawn_water != water)
|
||||||
|
continue;
|
||||||
|
if (m.spawn_min_height > pos.Y)
|
||||||
|
continue;
|
||||||
|
if (m.spawn_max_height < pos.Y)
|
||||||
|
continue;
|
||||||
|
if (m.spawn_chance > 1 && rand%m.spawn_chance != 0)
|
||||||
|
continue;
|
||||||
|
can.push_back(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (can.size() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MobFeatures m;
|
||||||
|
u32 index = 0;
|
||||||
|
|
||||||
|
if (can.size() > 1)
|
||||||
|
index = myrand_range(0,can.size()-1);
|
||||||
|
|
||||||
|
m = g_content_mob_features[can[index]];
|
||||||
|
|
||||||
|
if (m.content == CONTENT_IGNORE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
v3s16 spots[9] = {
|
||||||
|
v3s16(0,0,0),
|
||||||
|
v3s16(-2,0,0),
|
||||||
|
v3s16(-2,0,2),
|
||||||
|
v3s16(-2,0,-2),
|
||||||
|
v3s16(2,0,0),
|
||||||
|
v3s16(2,0,-2),
|
||||||
|
v3s16(2,0,2),
|
||||||
|
v3s16(0,0,-2),
|
||||||
|
v3s16(0,0,2)
|
||||||
|
};
|
||||||
|
u16 cnt = 0;
|
||||||
|
for (u16 i=0; i<9 && cnt < m.spawn_group; i++) {
|
||||||
|
v3s16 p = pos+spots[i];
|
||||||
|
if (water) {
|
||||||
|
if (env->getMap().getNodeNoEx(p+v3s16(0,1,0)).getContent() != CONTENT_WATERSOURCE)
|
||||||
|
continue;
|
||||||
|
}else{
|
||||||
|
content_t c = env->getMap().getNodeNoEx(pos).getContent();
|
||||||
|
bool have_spot = false;
|
||||||
|
for (s16 x=-1; !have_spot && x<2; x++) {
|
||||||
|
for (s16 y=-1; !have_spot && y<2; y++) {
|
||||||
|
for (s16 z=-1; !have_spot && z<2; z++) {
|
||||||
|
v3s16 pp = p+v3s16(x,y,z);
|
||||||
|
if (env->getMap().getNodeNoEx(pp).getContent() != c)
|
||||||
|
continue;
|
||||||
|
pp.Y++;
|
||||||
|
if (env->getMap().getNodeNoEx(pp).getContent() != CONTENT_AIR)
|
||||||
|
continue;
|
||||||
|
pp.Y++;
|
||||||
|
if (env->getMap().getNodeNoEx(pp).getContent() != CONTENT_AIR)
|
||||||
|
continue;
|
||||||
|
p += v3s16(x,y,z);
|
||||||
|
have_spot = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!have_spot)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mob_spawn(p,m.content,env);
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mob_spawn_hostile(v3s16 pos, bool water, ServerEnvironment *env)
|
||||||
|
{
|
||||||
|
std::vector<content_t> can;
|
||||||
|
int rand = myrand();
|
||||||
|
u8 level = mobLevelI(g_settings->get("max_mob_level"));
|
||||||
|
if (level < MOB_AGGRESSIVE)
|
||||||
|
return;
|
||||||
|
for (u16 i=0; i<CONTENT_MOB_COUNT; i++) {
|
||||||
|
MobFeatures m = g_content_mob_features[i];
|
||||||
|
if (!m.spawn_naturally)
|
||||||
|
continue;
|
||||||
|
if (m.level < MOB_AGGRESSIVE)
|
||||||
|
continue;
|
||||||
|
if (m.level > level)
|
||||||
|
continue;
|
||||||
|
if (m.spawn_water != water)
|
||||||
|
continue;
|
||||||
|
if (m.spawn_min_height > pos.Y)
|
||||||
|
continue;
|
||||||
|
if (m.spawn_max_height < pos.Y)
|
||||||
|
continue;
|
||||||
|
if (m.spawn_chance > 1 && rand%m.spawn_chance != 0)
|
||||||
|
continue;
|
||||||
|
can.push_back(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (can.size() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MobFeatures m;
|
||||||
|
u32 index = 0;
|
||||||
|
|
||||||
|
if (can.size() > 1)
|
||||||
|
index = myrand_range(0,can.size()-1);
|
||||||
|
|
||||||
|
m = g_content_mob_features[can[index]];
|
||||||
|
|
||||||
|
if (m.content == CONTENT_IGNORE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
v3s16 spots[9] = {
|
||||||
|
v3s16(0,0,0),
|
||||||
|
v3s16(-2,0,0),
|
||||||
|
v3s16(-2,0,2),
|
||||||
|
v3s16(-2,0,-2),
|
||||||
|
v3s16(2,0,0),
|
||||||
|
v3s16(2,0,-2),
|
||||||
|
v3s16(2,0,2),
|
||||||
|
v3s16(0,0,-2),
|
||||||
|
v3s16(0,0,2)
|
||||||
|
};
|
||||||
|
u16 cnt = 0;
|
||||||
|
for (u16 i=0; i<9 && cnt < m.spawn_group; i++) {
|
||||||
|
v3s16 p = pos+spots[i];
|
||||||
|
if (water) {
|
||||||
|
if (env->getMap().getNodeNoEx(p+v3s16(0,1,0)).getContent() != CONTENT_WATERSOURCE)
|
||||||
|
continue;
|
||||||
|
}else{
|
||||||
|
content_t c = env->getMap().getNodeNoEx(pos).getContent();
|
||||||
|
bool have_spot = false;
|
||||||
|
for (s16 x=-1; !have_spot && x<2; x++) {
|
||||||
|
for (s16 y=-1; !have_spot && y<2; y++) {
|
||||||
|
for (s16 z=-1; !have_spot && z<2; z++) {
|
||||||
|
v3s16 pp = p+v3s16(x,y,z);
|
||||||
|
if (env->getMap().getNodeNoEx(pp).getContent() != c)
|
||||||
|
continue;
|
||||||
|
pp.Y++;
|
||||||
|
if (env->getMap().getNodeNoEx(pp).getContent() != CONTENT_AIR)
|
||||||
|
continue;
|
||||||
|
pp.Y++;
|
||||||
|
if (env->getMap().getNodeNoEx(pp).getContent() != CONTENT_AIR)
|
||||||
|
continue;
|
||||||
|
p += v3s16(x,y,z);
|
||||||
|
have_spot = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!have_spot)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
mob_spawn(p,m.content,env);
|
||||||
|
cnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void content_mob_init()
|
void content_mob_init()
|
||||||
{
|
{
|
||||||
content_t i;
|
content_t i;
|
||||||
|
@ -220,10 +376,9 @@ void content_mob_init()
|
||||||
f->dropped_item = std::string("CraftItem2 ")+itos(CONTENT_CRAFTITEM_RAT)+" 1";
|
f->dropped_item = std::string("CraftItem2 ")+itos(CONTENT_CRAFTITEM_RAT)+" 1";
|
||||||
f->motion = MM_WANDER;
|
f->motion = MM_WANDER;
|
||||||
f->moves_silently = true;
|
f->moves_silently = true;
|
||||||
f->spawn_on = CONTENT_STONE;
|
|
||||||
f->spawn_in = CONTENT_AIR;
|
|
||||||
f->spawn_max_height = -10;
|
f->spawn_max_height = -10;
|
||||||
f->spawn_max_nearby_mobs = 4;
|
f->spawn_group = 3;
|
||||||
|
f->spawn_naturally = false;
|
||||||
f->lifetime = 900.0;
|
f->lifetime = 900.0;
|
||||||
f->setCollisionBox(aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.));
|
f->setCollisionBox(aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.));
|
||||||
|
|
||||||
|
@ -239,12 +394,9 @@ void content_mob_init()
|
||||||
f->motion_type = MMT_FLYLOW;
|
f->motion_type = MMT_FLYLOW;
|
||||||
f->glow_light = LIGHT_MAX-1;
|
f->glow_light = LIGHT_MAX-1;
|
||||||
f->moves_silently = true;
|
f->moves_silently = true;
|
||||||
f->spawn_on = CONTENT_JUNGLETREE;
|
|
||||||
f->spawn_in = CONTENT_AIR;
|
|
||||||
f->spawn_min_height = -5;
|
f->spawn_min_height = -5;
|
||||||
f->spawn_max_height = 50;
|
f->spawn_max_height = 50;
|
||||||
f->spawn_max_light = LIGHT_MAX/2;
|
f->spawn_naturally = false;
|
||||||
f->spawn_max_nearby_mobs = 5;
|
|
||||||
f->lifetime = 1200.0;
|
f->lifetime = 1200.0;
|
||||||
f->setCollisionBox(aabb3f(-BS/4.,-BS/6.,-BS/4., BS/4.,BS/6.,BS/4.));
|
f->setCollisionBox(aabb3f(-BS/4.,-BS/6.,-BS/4., BS/4.,BS/6.,BS/4.));
|
||||||
|
|
||||||
|
@ -289,11 +441,7 @@ void content_mob_init()
|
||||||
f->dropped_item = std::string("CraftItem2 ")+itos(CONTENT_CRAFTITEM_OERKKI_DUST)+" 2";
|
f->dropped_item = std::string("CraftItem2 ")+itos(CONTENT_CRAFTITEM_OERKKI_DUST)+" 2";
|
||||||
f->motion = MM_SEEKER;
|
f->motion = MM_SEEKER;
|
||||||
f->moves_silently = true;
|
f->moves_silently = true;
|
||||||
f->spawn_on = CONTENT_STONE;
|
|
||||||
f->spawn_in = CONTENT_AIR;
|
|
||||||
f->spawn_max_height = 2;
|
f->spawn_max_height = 2;
|
||||||
f->spawn_max_light = LIGHT_MAX/4;
|
|
||||||
f->spawn_max_nearby_mobs = 2;
|
|
||||||
f->sound_spawn = "mob-oerkki-spawn";
|
f->sound_spawn = "mob-oerkki-spawn";
|
||||||
f->notices_player = true;
|
f->notices_player = true;
|
||||||
f->attack_player_damage = 3;
|
f->attack_player_damage = 3;
|
||||||
|
@ -343,11 +491,6 @@ void content_mob_init()
|
||||||
f->punch_action = MPA_HARM;
|
f->punch_action = MPA_HARM;
|
||||||
f->dropped_item = std::string("CraftItem2 ")+itos(CONTENT_CRAFTITEM_GUNPOWDER)+" 4";
|
f->dropped_item = std::string("CraftItem2 ")+itos(CONTENT_CRAFTITEM_GUNPOWDER)+" 4";
|
||||||
f->motion = MM_SENTRY;
|
f->motion = MM_SENTRY;
|
||||||
f->spawn_on = CONTENT_MOSSYCOBBLE;
|
|
||||||
f->spawn_in = CONTENT_AIR;
|
|
||||||
f->spawn_max_light = LIGHT_MAX/3;
|
|
||||||
f->spawn_max_nearby_mobs = 1;
|
|
||||||
f->spawn_farthest_player = 20.0*BS;
|
|
||||||
f->notices_player = true;
|
f->notices_player = true;
|
||||||
f->attack_throw_object = CONTENT_MOB_FIREBALL;
|
f->attack_throw_object = CONTENT_MOB_FIREBALL;
|
||||||
f->attack_glow_light = LIGHT_MAX-1;
|
f->attack_glow_light = LIGHT_MAX-1;
|
||||||
|
@ -369,6 +512,7 @@ void content_mob_init()
|
||||||
f->attack_player_damage = 3;
|
f->attack_player_damage = 3;
|
||||||
f->attack_player_range = v3f(2,2,2);
|
f->attack_player_range = v3f(2,2,2);
|
||||||
f->contact_explosion_diameter = 3;
|
f->contact_explosion_diameter = 3;
|
||||||
|
f->spawn_naturally = false;
|
||||||
f->setCollisionBox(aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.));
|
f->setCollisionBox(aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.));
|
||||||
|
|
||||||
i = CONTENT_MOB_DOE;
|
i = CONTENT_MOB_DOE;
|
||||||
|
@ -389,12 +533,9 @@ void content_mob_init()
|
||||||
f->motion = MM_SEEKER;
|
f->motion = MM_SEEKER;
|
||||||
f->motion_type = MMT_WALK;
|
f->motion_type = MMT_WALK;
|
||||||
f->sound_random = "mob-deer-env";
|
f->sound_random = "mob-deer-env";
|
||||||
f->spawn_on = CONTENT_WILDGRASS_SHORT;
|
|
||||||
f->spawn_in = CONTENT_AIR;
|
|
||||||
f->spawn_min_height = -5;
|
f->spawn_min_height = -5;
|
||||||
f->spawn_max_height = 40;
|
f->spawn_max_height = 40;
|
||||||
f->spawn_min_light = LIGHT_MAX/2;
|
f->spawn_group = 3;
|
||||||
f->spawn_max_nearby_mobs = 3;
|
|
||||||
f->lifetime = 1200.0;
|
f->lifetime = 1200.0;
|
||||||
f->setCollisionBox(aabb3f(-0.6*BS, 0., -0.6*BS, 0.6*BS, 1.25*BS, 0.6*BS));
|
f->setCollisionBox(aabb3f(-0.6*BS, 0., -0.6*BS, 0.6*BS, 1.25*BS, 0.6*BS));
|
||||||
|
|
||||||
|
@ -418,12 +559,8 @@ void content_mob_init()
|
||||||
f->motion_type = MMT_WALK;
|
f->motion_type = MMT_WALK;
|
||||||
f->angry_motion = MM_SEEKER;
|
f->angry_motion = MM_SEEKER;
|
||||||
f->sound_random = "mob-deer-env";
|
f->sound_random = "mob-deer-env";
|
||||||
f->spawn_on = CONTENT_WILDGRASS_SHORT;
|
|
||||||
f->spawn_in = CONTENT_AIR;
|
|
||||||
f->spawn_min_height = -5;
|
f->spawn_min_height = -5;
|
||||||
f->spawn_max_height = 40;
|
f->spawn_max_height = 40;
|
||||||
f->spawn_min_light = LIGHT_MAX/2;
|
|
||||||
f->spawn_max_nearby_mobs = 3;
|
|
||||||
f->spawn_chance = 2;
|
f->spawn_chance = 2;
|
||||||
f->notices_player = true;
|
f->notices_player = true;
|
||||||
f->attack_player_damage = 3;
|
f->attack_player_damage = 3;
|
||||||
|
@ -451,6 +588,7 @@ void content_mob_init()
|
||||||
f->sound_random = "mob-deer-env";
|
f->sound_random = "mob-deer-env";
|
||||||
f->notices_player = true;
|
f->notices_player = true;
|
||||||
f->lifetime = 1800.0;
|
f->lifetime = 1800.0;
|
||||||
|
f->spawn_naturally = false;
|
||||||
f->setCollisionBox(aabb3f(-0.7*BS, 0., -0.7*BS, 0.7*BS, 1.5*BS, 0.7*BS));
|
f->setCollisionBox(aabb3f(-0.7*BS, 0., -0.7*BS, 0.7*BS, 1.5*BS, 0.7*BS));
|
||||||
|
|
||||||
i = CONTENT_MOB_FISH;
|
i = CONTENT_MOB_FISH;
|
||||||
|
@ -471,11 +609,9 @@ void content_mob_init()
|
||||||
f->motion = MM_WANDER;
|
f->motion = MM_WANDER;
|
||||||
f->motion_type = MMT_SWIM;
|
f->motion_type = MMT_SWIM;
|
||||||
f->moves_silently = true;
|
f->moves_silently = true;
|
||||||
f->spawn_on = CONTENT_SAND;
|
|
||||||
f->spawn_in = CONTENT_WATERSOURCE;
|
|
||||||
f->spawn_min_height = -30;
|
f->spawn_min_height = -30;
|
||||||
f->spawn_max_height = -2;
|
f->spawn_max_height = -2;
|
||||||
f->spawn_max_nearby_mobs = 5;
|
f->spawn_group = 3;
|
||||||
f->hp = 5;
|
f->hp = 5;
|
||||||
f->lifetime = 1200.0;
|
f->lifetime = 1200.0;
|
||||||
f->setCollisionBox(aabb3f(-0.25*BS, 0.25*BS, -0.25*BS, 0.25*BS, 0.75*BS, 0.25*BS));
|
f->setCollisionBox(aabb3f(-0.25*BS, 0.25*BS, -0.25*BS, 0.25*BS, 0.75*BS, 0.25*BS));
|
||||||
|
@ -498,11 +634,8 @@ void content_mob_init()
|
||||||
f->motion = MM_SEEKER;
|
f->motion = MM_SEEKER;
|
||||||
f->motion_type = MMT_SWIM;
|
f->motion_type = MMT_SWIM;
|
||||||
f->moves_silently = true;
|
f->moves_silently = true;
|
||||||
f->spawn_on = CONTENT_SAND;
|
|
||||||
f->spawn_in = CONTENT_WATERSOURCE;
|
|
||||||
f->spawn_min_height = -30;
|
f->spawn_min_height = -30;
|
||||||
f->spawn_max_height = -2;
|
f->spawn_max_height = -2;
|
||||||
f->spawn_max_nearby_mobs = 3;
|
|
||||||
f->notices_player = true;
|
f->notices_player = true;
|
||||||
f->attack_player_damage = 3;
|
f->attack_player_damage = 3;
|
||||||
f->attack_player_range = v3f(1,1,1);
|
f->attack_player_range = v3f(1,1,1);
|
||||||
|
@ -527,12 +660,8 @@ void content_mob_init()
|
||||||
f->tamed_mob = CONTENT_MOB_TAMEWOLF;
|
f->tamed_mob = CONTENT_MOB_TAMEWOLF;
|
||||||
f->motion = MM_SEEKER;
|
f->motion = MM_SEEKER;
|
||||||
f->motion_type = MMT_WALK;
|
f->motion_type = MMT_WALK;
|
||||||
f->spawn_on = CONTENT_WILDGRASS_LONG;
|
|
||||||
f->spawn_in = CONTENT_AIR;
|
|
||||||
f->spawn_min_height = 0;
|
f->spawn_min_height = 0;
|
||||||
f->spawn_max_height = 40;
|
f->spawn_max_height = 40;
|
||||||
f->spawn_max_light = LIGHT_MAX/2;
|
|
||||||
f->spawn_max_nearby_mobs = 3;
|
|
||||||
f->sound_punch = "mob-wolf-hit";
|
f->sound_punch = "mob-wolf-hit";
|
||||||
f->sound_spawn = "mob-wolf-spawn";
|
f->sound_spawn = "mob-wolf-spawn";
|
||||||
f->notices_player = true;
|
f->notices_player = true;
|
||||||
|
@ -563,6 +692,7 @@ void content_mob_init()
|
||||||
f->attack_mob_damage = 5;
|
f->attack_mob_damage = 5;
|
||||||
f->attack_mob_range = v3f(1,1,1);
|
f->attack_mob_range = v3f(1,1,1);
|
||||||
f->lifetime = 1800.0;
|
f->lifetime = 1800.0;
|
||||||
|
f->spawn_naturally = false;
|
||||||
f->setCollisionBox(aabb3f(-0.5*BS, 0., -0.5*BS, 0.5*BS, 1.*BS, 0.5*BS));
|
f->setCollisionBox(aabb3f(-0.5*BS, 0., -0.5*BS, 0.5*BS, 1.*BS, 0.5*BS));
|
||||||
|
|
||||||
i = CONTENT_MOB_SHEEP;
|
i = CONTENT_MOB_SHEEP;
|
||||||
|
@ -588,12 +718,9 @@ void content_mob_init()
|
||||||
f->motion_type = MMT_WALK;
|
f->motion_type = MMT_WALK;
|
||||||
f->sound_random = "mob-sheep-env";
|
f->sound_random = "mob-sheep-env";
|
||||||
f->sound_random_extra = "mob-ducksheep-env";
|
f->sound_random_extra = "mob-ducksheep-env";
|
||||||
f->spawn_on = CONTENT_WILDGRASS_SHORT;
|
|
||||||
f->spawn_in = CONTENT_AIR;
|
|
||||||
f->spawn_min_height = 2;
|
f->spawn_min_height = 2;
|
||||||
f->spawn_max_height = 50;
|
f->spawn_max_height = 50;
|
||||||
f->spawn_min_light = LIGHT_MAX/2;
|
f->spawn_group = 4;
|
||||||
f->spawn_max_nearby_mobs = 3;
|
|
||||||
f->lifetime = 1800.0;
|
f->lifetime = 1800.0;
|
||||||
f->setCollisionBox(aabb3f(-0.4*BS, 0., -0.4*BS, 0.4*BS, 1.*BS, 0.4*BS));
|
f->setCollisionBox(aabb3f(-0.4*BS, 0., -0.4*BS, 0.4*BS, 1.*BS, 0.4*BS));
|
||||||
|
|
||||||
|
@ -613,6 +740,7 @@ void content_mob_init()
|
||||||
f->lifetime = 10.0;
|
f->lifetime = 10.0;
|
||||||
f->contact_place_node = CONTENT_SNOW;
|
f->contact_place_node = CONTENT_SNOW;
|
||||||
f->contact_drop_item = CONTENT_CRAFTITEM_SNOW_BALL;
|
f->contact_drop_item = CONTENT_CRAFTITEM_SNOW_BALL;
|
||||||
|
f->spawn_naturally = false;
|
||||||
f->setCollisionBox(aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.));
|
f->setCollisionBox(aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.));
|
||||||
|
|
||||||
i = CONTENT_MOB_ARROW;
|
i = CONTENT_MOB_ARROW;
|
||||||
|
@ -631,5 +759,6 @@ void content_mob_init()
|
||||||
f->attack_mob_range = v3f(1,1,1);
|
f->attack_mob_range = v3f(1,1,1);
|
||||||
f->lifetime = 20.0;
|
f->lifetime = 20.0;
|
||||||
f->contact_drop_item = CONTENT_CRAFTITEM_ARROW;
|
f->contact_drop_item = CONTENT_CRAFTITEM_ARROW;
|
||||||
|
f->spawn_naturally = false;
|
||||||
f->setCollisionBox(aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.));
|
f->setCollisionBox(aabb3f(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.));
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,8 +110,6 @@ struct MobFeatures {
|
||||||
MobMotionType motion_type;
|
MobMotionType motion_type;
|
||||||
MobMotion angry_motion;
|
MobMotion angry_motion;
|
||||||
f32 static_thrown_speed;
|
f32 static_thrown_speed;
|
||||||
content_t hunted_node;
|
|
||||||
content_t fleed_node;
|
|
||||||
bool notices_player;
|
bool notices_player;
|
||||||
content_t tamed_mob;
|
content_t tamed_mob;
|
||||||
content_t attack_throw_object;
|
content_t attack_throw_object;
|
||||||
|
@ -141,16 +139,13 @@ struct MobFeatures {
|
||||||
std::string sound_random;
|
std::string sound_random;
|
||||||
std::string sound_random_extra;
|
std::string sound_random_extra;
|
||||||
|
|
||||||
content_t spawn_on;
|
|
||||||
content_t spawn_in;
|
|
||||||
u8 spawn_min_light;
|
|
||||||
u8 spawn_max_light;
|
|
||||||
s16 spawn_min_height;
|
s16 spawn_min_height;
|
||||||
s16 spawn_max_height;
|
s16 spawn_max_height;
|
||||||
u8 spawn_max_nearby_mobs;
|
|
||||||
s16 spawn_chance;
|
s16 spawn_chance;
|
||||||
s16 spawn_nearest_player;
|
s16 spawn_group;
|
||||||
s16 spawn_farthest_player;
|
bool spawn_water;
|
||||||
|
|
||||||
|
bool spawn_naturally;
|
||||||
|
|
||||||
MobFeatures()
|
MobFeatures()
|
||||||
{
|
{
|
||||||
|
@ -241,8 +236,6 @@ struct MobFeatures {
|
||||||
motion_type = MMT_WALK;
|
motion_type = MMT_WALK;
|
||||||
angry_motion = MM_STATIC;
|
angry_motion = MM_STATIC;
|
||||||
static_thrown_speed = 20.0;
|
static_thrown_speed = 20.0;
|
||||||
hunted_node = CONTENT_IGNORE;
|
|
||||||
fleed_node = CONTENT_IGNORE;
|
|
||||||
notices_player = false;
|
notices_player = false;
|
||||||
tamed_mob = CONTENT_IGNORE;
|
tamed_mob = CONTENT_IGNORE;
|
||||||
attack_throw_object = CONTENT_IGNORE;
|
attack_throw_object = CONTENT_IGNORE;
|
||||||
|
@ -270,16 +263,12 @@ struct MobFeatures {
|
||||||
sound_punch = "mob-dig";
|
sound_punch = "mob-dig";
|
||||||
sound_random = "";
|
sound_random = "";
|
||||||
sound_random_extra = "";
|
sound_random_extra = "";
|
||||||
spawn_on = CONTENT_IGNORE;
|
|
||||||
spawn_in = CONTENT_IGNORE;
|
|
||||||
spawn_min_light = 0;
|
|
||||||
spawn_max_light = LIGHT_MAX;
|
|
||||||
spawn_min_height = -20000;
|
spawn_min_height = -20000;
|
||||||
spawn_max_height = 100;
|
spawn_max_height = 100;
|
||||||
spawn_max_nearby_mobs = 3;
|
|
||||||
spawn_chance = 1;
|
spawn_chance = 1;
|
||||||
spawn_nearest_player = 0;
|
spawn_group = 1;
|
||||||
spawn_farthest_player = 0;
|
spawn_water = false;
|
||||||
|
spawn_naturally = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -307,6 +296,9 @@ inline std::string mobLevelS(u8 level)
|
||||||
|
|
||||||
class ServerEnvironment;
|
class ServerEnvironment;
|
||||||
bool content_mob_spawn(ServerEnvironment *env, v3s16 pos, u32 active_object_count);
|
bool content_mob_spawn(ServerEnvironment *env, v3s16 pos, u32 active_object_count);
|
||||||
|
void mob_spawn(v3s16 pos, content_t mob, ServerEnvironment *env);
|
||||||
|
void mob_spawn_passive(v3s16 pos, bool water, ServerEnvironment *env);
|
||||||
|
void mob_spawn_hostile(v3s16 pos, bool water, ServerEnvironment *env);
|
||||||
|
|
||||||
MobFeatures & content_mob_features(content_t i);
|
MobFeatures & content_mob_features(content_t i);
|
||||||
void content_mob_init();
|
void content_mob_init();
|
||||||
|
|
|
@ -517,7 +517,6 @@ void MobSAO::step(float dtime, bool send_recommended)
|
||||||
bool dont_move = false;
|
bool dont_move = false;
|
||||||
|
|
||||||
m_age += dtime;
|
m_age += dtime;
|
||||||
m_last_sound += dtime;
|
|
||||||
|
|
||||||
/* die, but not in the middle of attacking someone */
|
/* die, but not in the middle of attacking someone */
|
||||||
if (m.lifetime > 0.0 && m_age >= m.lifetime && (!m.notices_player || m_disturbing_player == "")) {
|
if (m.lifetime > 0.0 && m_age >= m.lifetime && (!m.notices_player || m_disturbing_player == "")) {
|
||||||
|
@ -567,6 +566,8 @@ void MobSAO::step(float dtime, bool send_recommended)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_last_sound += dtime;
|
||||||
|
|
||||||
if (m_last_sound > 30.0) {
|
if (m_last_sound > 30.0) {
|
||||||
m_last_sound -= 5.0;
|
m_last_sound -= 5.0;
|
||||||
if (m.sound_random != "" && myrand_range(0,10) == 0) {
|
if (m.sound_random != "" && myrand_range(0,10) == 0) {
|
||||||
|
@ -729,10 +730,10 @@ void MobSAO::step(float dtime, bool send_recommended)
|
||||||
}else{
|
}else{
|
||||||
m_walk_around = !m_walk_around;
|
m_walk_around = !m_walk_around;
|
||||||
if (m_walk_around) {
|
if (m_walk_around) {
|
||||||
if (!disturbing_player || mot != MM_SEEKER)
|
if ((!m.notices_player && !disturbing_player) || mot != MM_SEEKER)
|
||||||
m_walk_around_timer = 0.1*myrand_range(5,15);
|
m_walk_around_timer = myrand_range(10,20);
|
||||||
}else{
|
}else{
|
||||||
m_walk_around_timer = 0.1*myrand_range(20,40);
|
m_walk_around_timer = myrand_range(10,20);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else if (m_walk_around_timer > 10.0) {
|
}else if (m_walk_around_timer > 10.0) {
|
||||||
|
|
|
@ -988,35 +988,91 @@ void ServerEnvironment::step(float dtime)
|
||||||
active_object_count_wider += wblock->m_active_objects.size();
|
active_object_count_wider += wblock->m_active_objects.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
active_object_count_wider < 2
|
||||||
|
&& block->has_spawn_area
|
||||||
|
&& (
|
||||||
|
block->last_spawn < m_time_of_day-6000
|
||||||
|
|| block->last_spawn > m_time_of_day+6000
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
MapNode n = block->getNodeNoEx(block->spawn_area);
|
||||||
|
MapNode n1 = block->getNodeNoEx(block->spawn_area+v3s16(0,1,0));
|
||||||
|
MapNode n2 = block->getNodeNoEx(block->spawn_area+v3s16(0,2,0));
|
||||||
|
u8 light = n1.getLightBlend(getDayNightRatio());
|
||||||
|
if (block->water_spawn) {
|
||||||
|
if (n1.getContent() != CONTENT_WATERSOURCE || n2.getContent() != CONTENT_WATERSOURCE)
|
||||||
|
block->has_spawn_area = false;
|
||||||
|
}else{
|
||||||
|
if (
|
||||||
|
!content_features(n1.getContent()).air_equivalent
|
||||||
|
|| !content_features(n2.getContent()).air_equivalent
|
||||||
|
)
|
||||||
|
block->has_spawn_area = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block->has_spawn_area) {
|
||||||
|
// dawn, passive mobs spawn
|
||||||
|
if (m_time_of_day > 7000 && m_time_of_day < 8000) {
|
||||||
|
if (
|
||||||
|
(
|
||||||
|
n.getContent() == CONTENT_GRASS
|
||||||
|
|| n.getContent() == CONTENT_GRASS_AUTUMN
|
||||||
|
|| n.getContent() == CONTENT_GRASS_FOOTSTEPS
|
||||||
|
|| n.getContent() == CONTENT_GRASS_FOOTSTEPS_AUTUMN
|
||||||
|
|| n.getContent() == CONTENT_MUDSNOW
|
||||||
|
|| (
|
||||||
|
block->water_spawn
|
||||||
|
&& n.getContent() == CONTENT_SAND
|
||||||
|
)
|
||||||
|
) && (
|
||||||
|
light >= LIGHT_SPAWN_BRIGHT
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
mob_spawn_passive(block->spawn_area+block->getPosRelative(),block->water_spawn,this);
|
||||||
|
}else if (n.getContent() == CONTENT_STONE && light <= LIGHT_SPAWN_DARK && block->getPosRelative().Y < -16) {
|
||||||
|
mob_spawn(block->spawn_area+block->getPosRelative(),CONTENT_MOB_RAT,this);
|
||||||
|
}
|
||||||
|
block->last_spawn = m_time_of_day;
|
||||||
|
// dusk, hostile mobs spawn, or fireflies
|
||||||
|
}else if (m_time_of_day > 19000 && m_time_of_day < 20000) {
|
||||||
|
if (light <= LIGHT_SPAWN_DARK) {
|
||||||
|
if (n.getContent() == CONTENT_STONE || n.getContent() == CONTENT_SAND) {
|
||||||
|
mob_spawn_hostile(block->spawn_area+block->getPosRelative(),block->water_spawn,this);
|
||||||
|
}else if (n1.getContent() == CONTENT_JUNGLEGRASS) {
|
||||||
|
mob_spawn(block->spawn_area+block->getPosRelative(),CONTENT_MOB_FIREFLY,this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
block->last_spawn = m_time_of_day;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
v3s16 p0;
|
v3s16 p0;
|
||||||
bool spawned = false;
|
|
||||||
for (p0.X=0; p0.X<MAP_BLOCKSIZE; p0.X++)
|
for (p0.X=0; p0.X<MAP_BLOCKSIZE; p0.X++)
|
||||||
for (p0.Y=0; p0.Y<MAP_BLOCKSIZE; p0.Y++)
|
for (p0.Y=0; p0.Y<MAP_BLOCKSIZE; p0.Y++)
|
||||||
for (p0.Z=0; p0.Z<MAP_BLOCKSIZE; p0.Z++) {
|
for (p0.Z=0; p0.Z<MAP_BLOCKSIZE; p0.Z++) {
|
||||||
v3s16 p = p0 + block->getPosRelative();
|
v3s16 p = p0 + block->getPosRelative();
|
||||||
block->incNodeTicks(p0);
|
block->incNodeTicks(p0);
|
||||||
MapNode n = block->getNodeNoEx(p0);
|
MapNode n = block->getNodeNoEx(p0);
|
||||||
if (!spawned && active_object_count_wider < 5) {
|
if (!block->has_spawn_area && content_features(n.getContent()).draw_type == CDT_CUBELIKE) {
|
||||||
MapNode n1 = block->getNodeNoEx(p0+v3s16(0,1,0));
|
MapNode n1 = block->getNodeNoEx(p0+v3s16(0,1,0));
|
||||||
bool spawnable = false;
|
MapNode n2 = block->getNodeNoEx(p0+v3s16(0,2,0));
|
||||||
switch (n.getContent()) {
|
if (
|
||||||
case CONTENT_SAND:
|
content_features(n1.getContent()).air_equivalent
|
||||||
if (n1.getContent() == CONTENT_WATERSOURCE)
|
&& content_features(n2.getContent()).air_equivalent
|
||||||
spawnable = true;
|
) {
|
||||||
break;
|
block->spawn_area = p0;
|
||||||
case CONTENT_STONE:
|
block->has_spawn_area = true;
|
||||||
case CONTENT_MOSSYCOBBLE:
|
block->water_spawn = false;
|
||||||
case CONTENT_WILDGRASS_SHORT:
|
}else if (
|
||||||
case CONTENT_WILDGRASS_LONG:
|
n.getContent() == CONTENT_SAND
|
||||||
case CONTENT_JUNGLETREE:
|
&& n1.getContent() == CONTENT_WATERSOURCE
|
||||||
if (n1.getContent() == CONTENT_AIR)
|
&& n2.getContent() == CONTENT_WATERSOURCE
|
||||||
spawnable = true;
|
) {
|
||||||
break;
|
block->spawn_area = p0;
|
||||||
default:;
|
block->has_spawn_area = true;
|
||||||
}
|
block->water_spawn = true;
|
||||||
if (spawnable && content_mob_spawn(this,p,active_object_count_wider)) {
|
|
||||||
spawned = true;
|
|
||||||
active_object_count_wider++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,10 @@ extern u32 daynight_cache_ratios[DAYNIGHT_CACHE_COUNT];*/
|
||||||
// This brightness is reserved for sunlight
|
// This brightness is reserved for sunlight
|
||||||
#define LIGHT_SUN 15
|
#define LIGHT_SUN 15
|
||||||
|
|
||||||
|
// these are used in mob spawning
|
||||||
|
#define LIGHT_SPAWN_BRIGHT 10
|
||||||
|
#define LIGHT_SPAWN_DARK 4
|
||||||
|
|
||||||
inline u8 diminish_light(u8 light)
|
inline u8 diminish_light(u8 light)
|
||||||
{
|
{
|
||||||
if(light == 0)
|
if(light == 0)
|
||||||
|
|
|
@ -38,18 +38,22 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
MapBlock::MapBlock(Map *parent, v3s16 pos, bool dummy):
|
MapBlock::MapBlock(Map *parent, v3s16 pos, bool dummy):
|
||||||
m_parent(parent),
|
has_spawn_area(false),
|
||||||
m_pos(pos),
|
spawn_area(0,0,0),
|
||||||
m_modified(MOD_STATE_WRITE_NEEDED),
|
water_spawn(false),
|
||||||
is_underground(false),
|
last_spawn(0),
|
||||||
m_lighting_expired(true),
|
m_parent(parent),
|
||||||
m_day_night_differs(false),
|
m_pos(pos),
|
||||||
m_generated(false),
|
m_modified(MOD_STATE_WRITE_NEEDED),
|
||||||
m_timestamp(BLOCK_TIMESTAMP_UNDEFINED),
|
is_underground(false),
|
||||||
m_usage_timer(0)
|
m_lighting_expired(true),
|
||||||
|
m_day_night_differs(false),
|
||||||
|
m_generated(false),
|
||||||
|
m_timestamp(BLOCK_TIMESTAMP_UNDEFINED),
|
||||||
|
m_usage_timer(0)
|
||||||
{
|
{
|
||||||
data = NULL;
|
data = NULL;
|
||||||
if(dummy == false)
|
if (dummy == false)
|
||||||
reallocate();
|
reallocate();
|
||||||
|
|
||||||
//m_spawn_timer = -10000;
|
//m_spawn_timer = -10000;
|
||||||
|
|
|
@ -539,6 +539,12 @@ public:
|
||||||
void serializeDiskExtra(std::ostream &os, u8 version);
|
void serializeDiskExtra(std::ostream &os, u8 version);
|
||||||
void deSerializeDiskExtra(std::istream &is, u8 version);
|
void deSerializeDiskExtra(std::istream &is, u8 version);
|
||||||
|
|
||||||
|
// Used by the server env for mob spawning
|
||||||
|
bool has_spawn_area;
|
||||||
|
v3s16 spawn_area;
|
||||||
|
bool water_spawn;
|
||||||
|
u32 last_spawn;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*
|
/*
|
||||||
Private methods
|
Private methods
|
||||||
|
|
Loading…
Reference in New Issue