m_is_visible = false;
player->setCAO(this);
}
- if (m_client->getProtoVersion() < 33)
- m_env->addPlayerName(m_name);
}
}
m_yaw = readF1000(is);
m_hp = readS16(is);
num_messages = readU8(is);
- } else if (version == 0) { // In PROTOCOL_VERSION 13
- m_name = deSerializeString(is);
- m_is_player = readU8(is);
- m_position = readV3F1000(is);
- m_yaw = readF1000(is);
- m_hp = readS16(is);
- num_messages = readU8(is);
} else {
errorstream<<"GenericCAO: Unsupported init data version"
<<std::endl;
GenericCAO::~GenericCAO()
{
- if (m_is_player && m_client->getProtoVersion() < 33) {
- m_env->removePlayerName(m_name);
- }
removeFromScene(true);
}
bool GenericCAO::getSelectionBox(aabb3f *toset) const
{
if (!m_prop.is_visible || !m_is_visible || m_is_local_player
- || getParent() != NULL){
+ || !m_prop.pointable || getParent() != NULL) {
return false;
}
*toset = m_selection_box;
}
else if(m_prop.visual == "mesh") {
infostream<<"GenericCAO::addToScene(): mesh"<<std::endl;
- scene::IAnimatedMesh *mesh = m_client->getMesh(m_prop.mesh);
+ scene::IAnimatedMesh *mesh = m_client->getMesh(m_prop.mesh, true);
if(mesh)
{
m_animated_meshnode = RenderingEngine::get_scene_manager()->
m_prop.visual_size.Y,
m_prop.visual_size.X));
u8 li = m_last_light;
+
+ // set vertex colors to ensure alpha is set
setMeshColor(m_animated_meshnode->getMesh(), video::SColor(255,li,li,li));
+ setAnimatedMeshColor(m_animated_meshnode, video::SColor(255,li,li,li));
+
bool backface_culling = m_prop.backface_culling;
if (m_is_player)
backface_culling = false;
- m_animated_meshnode->setMaterialFlag(video::EMF_LIGHTING, false);
+ m_animated_meshnode->setMaterialFlag(video::EMF_LIGHTING, true);
m_animated_meshnode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
m_animated_meshnode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
m_animated_meshnode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
void GenericCAO::updateLightNoCheck(u8 light_at_pos)
{
- u8 li = decode_light(light_at_pos);
+ if (m_glow < 0)
+ return;
+
+ u8 li = decode_light(light_at_pos + m_glow);
if (li != m_last_light) {
m_last_light = li;
video::SColor color(255,li,li,li);
if (m_meshnode) {
setMeshColor(m_meshnode->getMesh(), color);
} else if (m_animated_meshnode) {
- setMeshColor(m_animated_meshnode->getMesh(), color);
+ setAnimatedMeshColor(m_animated_meshnode, color);
} else if (m_wield_meshnode) {
m_wield_meshnode->setColor(color);
} else if (m_spritenode) {
v3s16 GenericCAO::getLightPosition()
{
- return floatToInt(m_position + v3f(0, 0.5 * BS, 0), BS);
+ if (m_is_player)
+ return floatToInt(m_position + v3f(0, 0.5 * BS, 0), BS);
+
+ return floatToInt(m_position, BS);
}
void GenericCAO::updateNodePos()
float moved = lastpos.getDistanceFrom(pos_translator.vect_show);
m_step_distance_counter += moved;
- if(m_step_distance_counter > 1.5*BS)
- {
- m_step_distance_counter = 0;
- if(!m_is_local_player && m_prop.makes_footstep_sound)
- {
+ if (m_step_distance_counter > 1.5f * BS) {
+ m_step_distance_counter = 0.0f;
+ if (!m_is_local_player && m_prop.makes_footstep_sound) {
INodeDefManager *ndef = m_client->ndef();
- v3s16 p = floatToInt(getPosition() + v3f(0,
- (m_prop.collisionbox.MinEdge.Y-0.5)*BS, 0), BS);
+ v3s16 p = floatToInt(getPosition() +
+ v3f(0.0f, (m_prop.collisionbox.MinEdge.Y - 0.5f) * BS, 0.0f), BS);
MapNode n = m_env->getMap().getNodeNoEx(p);
SimpleSoundSpec spec = ndef->get(n).sound_footstep;
+ // Reduce footstep gain, as non-local-player footsteps are
+ // somehow louder.
+ spec.gain *= 0.6f;
m_client->sound()->playSoundAt(spec, false, getPosition());
}
}
}
if (!getParent() && m_prop.automatic_face_movement_dir &&
- (fabs(m_velocity.Z) > 0.001 || fabs(m_velocity.X) > 0.001))
- {
- float optimal_yaw = atan2(m_velocity.Z,m_velocity.X) * 180 / M_PI
+ (fabs(m_velocity.Z) > 0.001 || fabs(m_velocity.X) > 0.001)) {
+
+ float target_yaw = atan2(m_velocity.Z, m_velocity.X) * 180 / M_PI
+ m_prop.automatic_face_movement_dir_offset;
float max_rotation_delta =
dtime * m_prop.automatic_face_movement_max_rotation_per_sec;
+ float delta = wrapDegrees_0_360(target_yaw - m_yaw);
- if ((m_prop.automatic_face_movement_max_rotation_per_sec > 0) &&
- (fabs(m_yaw - optimal_yaw) > max_rotation_delta)) {
-
- m_yaw = optimal_yaw < m_yaw ? m_yaw - max_rotation_delta : m_yaw + max_rotation_delta;
+ if (delta > max_rotation_delta && 360 - delta > max_rotation_delta) {
+ m_yaw += (delta < 180) ? max_rotation_delta : -max_rotation_delta;
+ m_yaw = wrapDegrees_0_360(m_yaw);
} else {
- m_yaw = optimal_yaw;
+ m_yaw = target_yaw;
}
updateNodePos();
}
m_previous_texture_modifier = m_current_texture_modifier;
m_current_texture_modifier = mod;
+ m_glow = m_prop.glow;
if (m_spritenode) {
if (m_prop.visual == "sprite") {
// Set material flags and texture
video::SMaterial& material = m_animated_meshnode->getMaterial(i);
material.TextureLayer[0].Texture = texture;
- material.setFlag(video::EMF_LIGHTING, false);
+ material.setFlag(video::EMF_LIGHTING, true);
material.setFlag(video::EMF_BILINEAR_FILTER, false);
+ // don't filter low-res textures, makes them look blurry
+ // player models have a res of 64
+ const core::dimension2d<u32> &size = texture->getOriginalSize();
+ const u32 res = std::min(size.Height, size.Width);
+ use_trilinear_filter &= res > 64;
+ use_bilinear_filter &= res > 64;
+
m_animated_meshnode->getMaterial(i)
.setFlag(video::EMF_TRILINEAR_FILTER, use_trilinear_filter);
m_animated_meshnode->getMaterial(i)
buf->getMaterial().AmbientColor = m_prop.colors[1];
buf->getMaterial().DiffuseColor = m_prop.colors[1];
buf->getMaterial().SpecularColor = m_prop.colors[1];
+ setMeshColor(mesh, m_prop.colors[1]);
} else if (!m_prop.colors.empty()) {
buf->getMaterial().AmbientColor = m_prop.colors[0];
buf->getMaterial().DiffuseColor = m_prop.colors[0];
buf->getMaterial().SpecularColor = m_prop.colors[0];
+ setMeshColor(mesh, m_prop.colors[0]);
}
buf->getMaterial().setFlag(video::EMF_TRILINEAR_FILTER, use_trilinear_filter);
#endif
}
+void GenericCAO::updateAnimationSpeed()
+{
+ if (!m_animated_meshnode)
+ return;
+
+ m_animated_meshnode->setAnimationSpeed(m_animation_speed);
+}
+
void GenericCAO::updateBonePosition()
{
- if(m_bone_position.empty() || !m_animated_meshnode)
+ if (m_bone_position.empty() || !m_animated_meshnode)
return;
m_animated_meshnode->setJointMode(irr::scene::EJUOR_CONTROL); // To write positions to the mesh on render
if (cmd == GENERIC_CMD_SET_PROPERTIES) {
m_prop = gob_read_set_properties(is);
- m_selection_box = m_prop.collisionbox;
+ m_selection_box = m_prop.selectionbox;
m_selection_box.MinEdge *= BS;
m_selection_box.MaxEdge *= BS;
if (m_is_local_player) {
LocalPlayer *player = m_env->getLocalPlayer();
player->makes_footstep_sound = m_prop.makes_footstep_sound;
- player->setCollisionbox(m_selection_box);
+ aabb3f collision_box = m_prop.collisionbox;
+ collision_box.MinEdge *= BS;
+ collision_box.MaxEdge *= BS;
+ player->setCollisionbox(collision_box);
+ player->setEyeHeight(m_prop.eye_height);
+ player->setZoomFOV(m_prop.zoom_fov);
}
if ((m_is_player && !m_is_local_player) && m_prop.nametag.empty())
updateAnimation();
}
}
+ } else if (cmd == GENERIC_CMD_SET_ANIMATION_SPEED) {
+ m_animation_speed = readF1000(is);
+ updateAnimationSpeed();
} else if (cmd == GENERIC_CMD_SET_BONE_POSITION) {
std::string bone = deSerializeString(is);
v3f position = readV3F1000(is);