void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end) { // If the object is attached client-side, don't waste bandwidth sending its position to clients if(isAttached()) return; m_last_sent_move_precision = getBasePosition().getDistanceFrom( m_last_sent_position); m_last_sent_position_timer = 0; m_last_sent_yaw = m_yaw; m_last_sent_position = getBasePosition(); m_last_sent_velocity = m_velocity; //m_last_sent_acceleration = m_acceleration; float update_interval = m_env->getSendRecommendedInterval(); std::string str = gob_cmd_update_position( getBasePosition(), m_velocity, m_acceleration, m_yaw, do_interpolate, is_movement_end, update_interval ); // create message and add to list ActiveObjectMessage aom(getId(), false, str); m_messages_out.push(aom); }
bool LuaEntitySAO::getCollisionBox(aabb3f *toset) { if (m_prop.physical) { //update collision box toset->MinEdge = m_prop.collisionbox.MinEdge * BS; toset->MaxEdge = m_prop.collisionbox.MaxEdge * BS; toset->MinEdge += getBasePosition(); toset->MaxEdge += getBasePosition(); return true; } return false; }
void ModelContainer::intersect(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit, G3D::Vector3& /*pOutLocation*/, G3D::Vector3& /*pOutNormal*/) const { IntersectionCallBack<SubModel> intersectCallback; NodeValueAccess<TreeNode, SubModel> vna = NodeValueAccess<TreeNode, SubModel>(getTreeNodes(), iSubModel); Ray relativeRay = Ray::fromOriginAndDirection(pRay.origin - getBasePosition(), pRay.direction); iTreeNodes[0].intersectRay(pRay, intersectCallback, pMaxDist, vna, pStopAtFirstHit, false); }
void step(float dtime, bool send_recommended) { ScopeProfiler sp2(g_profiler, "step avg", SPT_AVG); assert(m_env); const float interval = 0.2; if(m_move_interval.step(dtime, interval)==false) return; dtime = interval; core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.); collisionMoveResult moveresult; // Apply gravity m_speed_f += v3f(0, -dtime*9.81*BS, 0); // Maximum movement without glitches f32 pos_max_d = BS*0.25; // Limit speed if(m_speed_f.getLength()*dtime > pos_max_d) m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime); v3f pos_f = getBasePosition(); v3f pos_f_old = pos_f; v3f accel_f = v3f(0,0,0); f32 stepheight = 0; IGameDef *gamedef = m_env->getGameDef(); moveresult = collisionMoveSimple(&m_env->getMap(), gamedef, pos_max_d, box, stepheight, dtime, pos_f, m_speed_f, accel_f); if(send_recommended == false) return; if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS) { setBasePosition(pos_f); m_last_sent_position = pos_f; std::ostringstream os(std::ios::binary); // command (0 = update position) writeU8(os, 0); // pos writeV3F1000(os, m_base_position); // create message and add to list ActiveObjectMessage aom(getId(), false, os.str()); m_messages_out.push_back(aom); } if(m_itemstring_changed) { m_itemstring_changed = false; std::ostringstream os(std::ios::binary); // command (1 = update itemstring) writeU8(os, 1); // itemstring os<<serializeString(m_itemstring); // create message and add to list ActiveObjectMessage aom(getId(), false, os.str()); m_messages_out.push_back(aom); } }
bool MoveMapBox::operator== (const MoveMapBox& pMM2) const { bool result = false; if (getBounds () == pMM2.getBounds () && getBasePosition () == pMM2.getBasePosition ()) { result = true; } return result; }
RealTime ModelContainer::getIntersectionTime(const Ray& pRay, bool pExitAtFirst, float pMaxDist) const { #ifdef _DEBUG_VMAPS for(unsigned int i=0; i<getNSubModel(); i++) { SubModel model = getSubModel(i); bool insiteOk; Vector3 mynormal; Vector3 location; bool hitval = MyCollisionDetection::collisionLocationForMovingPointFixedAABox( pRay.origin, pRay.direction, model.getAABoxBounds(), location,insiteOk, mynormal); if(hitval) { float len2 = (location - pRay.origin).squaredLength(); int a = 0; // just to be able to set a breakpoint } } TreeNode tn = getTreeNode(0); for(int i=0; i<tn.getNValues(); i++) { SubModel mysm = getSubModel(tn.getStartPosition() + i); AABox testbox = mysm.getAABoxBounds(); gBoxArray.append(AABox(testbox.low(), testbox.high())); } #endif double firstDistance = inf(); Ray relativeRay = Ray::fromOriginAndDirection(pRay.origin - getBasePosition(), pRay.direction); const IT end = endRayIntersection(); IT obj = beginRayIntersection(pRay, pMaxDist); for ( ;obj != end; ++obj) // (preincrement is *much* faster than postincrement!) { /* Call your accurate intersection test here. It is guaranteed that the ray hits the bounding box of obj. (*obj) has type T, so you can call methods directly using the "->" operator. */ SubModel const *model = &(*obj); RealTime t = model->getIntersectionTime(pRay, pExitAtFirst, pMaxDist); if(t > 0 && t < inf()) { obj.markBreakNode(); if(firstDistance > t && pMaxDist >= t) { firstDistance = t; if(pExitAtFirst) { break; } } } } return(firstDistance); }
//========================================================== void SubModel::intersect(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit, G3D::Vector3& /*pOutLocation*/, G3D::Vector3& /*pOutNormal*/) const { NodeValueAccess<TreeNode, TriangleBox> vna = NodeValueAccess<TreeNode, TriangleBox>(getTreeNodes(), getTriangles()); IntersectionCallBack<TriangleBox> intersectCallback; Ray relativeRay = Ray::fromOriginAndDirection(pRay.origin - getBasePosition(), pRay.direction); #ifdef _DEBUG_VMAPS //p6=getBasePosition(); //gBoxArray.push_back(getAABoxBounds()); #endif getTreeNode(0).intersectRay(relativeRay, intersectCallback, pMaxDist, vna, pStopAtFirstHit, false); }
bool ModelContainer::writeFile(const char *filename) { bool result = false; unsigned int flags=0; unsigned int size; FILE *wf =fopen(filename,"wb"); if(wf) { fwrite(VMAP_MAGIC,1,8,wf); result = true; if(result && fwrite("CTREE01",8,1,wf) != 1) result = false; if(result && fwrite(&flags,sizeof(unsigned int),1,wf) != 1) result = false; if(result && fwrite("POS ",4,1,wf) != 1) result = false; size = sizeof(float)*3; if(result && fwrite(&size,4,1,wf) != 1) result = false; Vector3 basePos = getBasePosition(); if(result && fwrite(&basePos,sizeof(float),3,wf) != 3) result = false; if(result && fwrite("BOX ",4,1,wf) != 1) result = false; size = sizeof(float)*6; if(result && fwrite(&size,4,1,wf) != 1) result = false; Vector3 low = iBox.low(); if(result && fwrite(&low,sizeof(float),3,wf) != 3) result = false; Vector3 high = iBox.high(); if(result && fwrite(&high,sizeof(float),3,wf) != 3) result = false; if(result && fwrite("NODE",4,1,wf) != 1) result = false; size = sizeof(unsigned int)+ sizeof(TreeNode)*getNNodes(); if(result && fwrite(&size,4,1,wf) != 1) result = false; unsigned int val = getNNodes(); if(result && fwrite(&val,sizeof(unsigned int),1,wf) != 1) result = false; if(result && fwrite(getTreeNodes(),sizeof(TreeNode),getNNodes(),wf) != getNNodes()) result = false; if(result && fwrite("TRIB",4,1,wf) != 1) result = false; size = sizeof(unsigned int)+ sizeof(TriangleBox)*getNTriangles(); if(result && fwrite(&size,4,1,wf) != 1) result = false; val = getNTriangles(); if(result && fwrite(&val,sizeof(unsigned int),1,wf) != 1) result = false; if(result && fwrite(getTriangles(),sizeof(TriangleBox),getNTriangles(),wf) != getNTriangles()) result = false; if(result && fwrite("SUBM",4,1,wf) != 1) result = false; size = sizeof(unsigned int)+ sizeof(SubModel)*iNSubModel; if(result && fwrite(&size,4,1,wf) != 1) result = false; if(result && fwrite(&iNSubModel,sizeof(unsigned int),1,wf) != 1) result = false; if(result && fwrite(iSubModel,sizeof(SubModel),iNSubModel,wf) != iNSubModel) result = false; fclose(wf); } return(result); }
void MobV2SAO::punch(ServerActiveObject *puncher, float time_from_last_punch) { if(!puncher) return; v3f dir = (getBasePosition() - puncher->getBasePosition()).normalize(); // A quick hack; SAO description is player name for player std::string playername = puncher->getDescription(); Map *map = &m_env->getMap(); actionstream<<playername<<" punches mob id="<<m_id <<" at "<<PP(m_base_position/BS)<<std::endl; m_disturb_timer = 0; m_disturbing_player = playername; m_next_pos_exists = false; // Cancel moving immediately m_yaw = wrapDegrees_180(180./PI*atan2(dir.Z, dir.X) + 180.); v3f new_base_position = m_base_position + dir * BS; { v3s16 pos_i = floatToInt(new_base_position, BS); v3s16 size_blocks = v3s16(m_size.X+0.5,m_size.Y+0.5,m_size.X+0.5); v3s16 pos_size_off(0,0,0); if(m_size.X >= 2.5){ pos_size_off.X = -1; pos_size_off.Y = -1; } bool free = checkFreePosition(map, pos_i + pos_size_off, size_blocks); if(free) m_base_position = new_base_position; } sendPosition(); // "Material" properties of the MobV2 MaterialProperties mp; mp.diggability = DIGGABLE_NORMAL; mp.crackiness = -1.0; mp.cuttability = 1.0; ToolDiggingProperties tp; puncher->getWieldDiggingProperties(&tp); HittingProperties hitprop = getHittingProperties(&mp, &tp, time_from_last_punch); doDamage(hitprop.hp); puncher->damageWieldedItem(hitprop.wear); }
void ItemSAO::step(float dtime, bool send_recommended) { ScopeProfiler sp2(g_profiler, "ItemSAO::step avg", SPT_AVG); assert(m_env); const float interval = 0.2; if(m_move_interval.step(dtime, interval)==false) return; dtime = interval; core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.); collisionMoveResult moveresult; // Apply gravity m_speed_f += v3f(0, -dtime*9.81*BS, 0); // Maximum movement without glitches f32 pos_max_d = BS*0.25; // Limit speed if(m_speed_f.getLength()*dtime > pos_max_d) m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime); v3f pos_f = getBasePosition(); v3f pos_f_old = pos_f; IGameDef *gamedef = m_env->getGameDef(); moveresult = collisionMoveSimple(&m_env->getMap(), gamedef, pos_max_d, box, dtime, pos_f, m_speed_f); if(send_recommended == false) return; if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS) { setBasePosition(pos_f); m_last_sent_position = pos_f; std::ostringstream os(std::ios::binary); char buf[6]; // command (0 = update position) buf[0] = 0; os.write(buf, 1); // pos writeS32((u8*)buf, m_base_position.X*1000); os.write(buf, 4); writeS32((u8*)buf, m_base_position.Y*1000); os.write(buf, 4); writeS32((u8*)buf, m_base_position.Z*1000); os.write(buf, 4); // create message and add to list ActiveObjectMessage aom(getId(), false, os.str()); m_messages_out.push_back(aom); } }
bool SubModel::operator==(const SubModel& pSm2) const { bool result = false; if(getNNodes() == pSm2.getNNodes() && getNTriangles() == pSm2.getNTriangles() && getBasePosition() == pSm2.getBasePosition() && getNodesPos() == pSm2.getNodesPos() && getTrianglesPos() == pSm2.getTrianglesPos()) { result = true; } return result; }
void LuaEntitySAO::step(float dtime, bool send_recommended) { m_last_sent_position_timer += dtime; if(m_prop->physical){ core::aabbox3d<f32> box = m_prop->collisionbox; box.MinEdge *= BS; box.MaxEdge *= BS; collisionMoveResult moveresult; f32 pos_max_d = BS*0.25; // Distance per iteration v3f p_pos = getBasePosition(); v3f p_velocity = m_velocity; IGameDef *gamedef = m_env->getGameDef(); moveresult = collisionMovePrecise(&m_env->getMap(), gamedef, pos_max_d, box, dtime, p_pos, p_velocity); // Apply results setBasePosition(p_pos); m_velocity = p_velocity; m_velocity += dtime * m_acceleration; } else { m_base_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration; m_velocity += dtime * m_acceleration; } if(m_registered){ lua_State *L = m_env->getLua(); scriptapi_luaentity_step(L, m_id, dtime); } if(send_recommended == false) return; // TODO: force send when acceleration changes enough? float minchange = 0.2*BS; if(m_last_sent_position_timer > 1.0){ minchange = 0.01*BS; } else if(m_last_sent_position_timer > 0.2){ minchange = 0.05*BS; } float move_d = m_base_position.getDistanceFrom(m_last_sent_position); move_d += m_last_sent_move_precision; float vel_d = m_velocity.getDistanceFrom(m_last_sent_velocity); if(move_d > minchange || vel_d > minchange || fabs(m_yaw - m_last_sent_yaw) > 1.0){ sendPosition(true, false); } }
void Oerkki1SAO::punch(ServerActiveObject *puncher, float time_from_last_punch) { if(!puncher) return; v3f dir = (getBasePosition() - puncher->getBasePosition()).normalize(); m_speed_f += dir*12*BS; // "Material" properties of an oerkki MaterialProperties mp; mp.diggability = DIGGABLE_NORMAL; mp.crackiness = -1.0; mp.cuttability = 1.0; ToolDiggingProperties tp; puncher->getWieldDiggingProperties(&tp); HittingProperties hitprop = getHittingProperties(&mp, &tp, time_from_last_punch); doDamage(hitprop.hp); puncher->damageWieldedItem(hitprop.wear); }
void step(float dtime, bool send_recommended) { m_age += dtime; if(m_age > 10) { m_removed = true; return; } auto m_base_position = getBasePosition(); m_base_position.Y += dtime * BS * 2; if(m_base_position.Y > 8*BS) m_base_position.Y = 2*BS; setBasePosition(m_base_position); if(send_recommended == false) return; m_timer1 -= dtime; if(m_timer1 < 0.0) { m_timer1 += 0.125; std::string data; data += itos(0); // 0 = position data += " "; data += itos(m_base_position.X); data += " "; data += itos(m_base_position.Y); data += " "; data += itos(m_base_position.Z); ActiveObjectMessage aom(getId(), false, data); m_messages_out.push(aom); } }
RealTime SubModel::getIntersectionTime(const Ray& pRay, bool pExitAtFirst, float pMaxDist) const { TriangleBox const *firstObject; double firstDistance = inf(); #ifdef _DEBUG_VMAPS int debugCount =0; #endif Ray relativeRay = Ray::fromOriginAndDirection(pRay.origin - getBasePosition(), pRay.direction); const IT end = endRayIntersection(); IT obj = beginRayIntersection(relativeRay,pMaxDist,false); Triangle testT; for ( ;obj != end; ++obj) // (preincrement is *much* faster than postincrement!) { /* Call your accurate intersection test here. It is guaranteed that the ray hits the bounding box of obj. (*obj) has type T, so you can call methods directly using the "->" operator. */ const TriangleBox *tri = &(*obj); testT = Triangle(tri->vertex(0).getVector3(),tri->vertex(1).getVector3(),tri->vertex(2).getVector3()); double t = testIntersectionWithTriangle(obj,testT, relativeRay); #ifdef _DEBUG_VMAPS if(debugCount == 5) { firstObject = tri; firstDistance = 1; } ++debugCount; #endif if(t != inf()) { /* Tell the iterator that we've found at least one intersection. It will finish looking at all objects in this node and then terminate. */ obj.markBreakNode(); if(firstDistance > t && pMaxDist >= t) { firstDistance = t; firstObject = tri; if(pExitAtFirst) break; } } else { // This might the wrong side of the triangle... Turn it and test again testT = Triangle(tri->vertex(2).getVector3(),tri->vertex(1).getVector3(),tri->vertex(0).getVector3()); t = testIntersectionWithTriangle(obj, testT,relativeRay); if(t != inf()) { obj.markBreakNode(); if(firstDistance > t && pMaxDist >= t) { firstDistance = t; firstObject = tri; if(pExitAtFirst) break; } } } } #ifdef _DEBUG_VMAPS if(firstDistance < inf()) { myfound = true; p1 = firstObject->vertex(0).getVector3()+ getBasePosition(); p2 = firstObject->vertex(1).getVector3()+ getBasePosition(); p3 = firstObject->vertex(2).getVector3()+ getBasePosition(); p4 = relativeRay.origin + getBasePosition(); p5 = relativeRay.intersection(testT.plane()) + getBasePosition(); float dist1 = (p5-p4).magnitude(); double dist2 = relativeRay.intersectionTime(testT); float dist3 = relativeRay.direction.magnitude(); double dist4 = relativeRay.intersectionTime(testT); } #endif return(firstDistance); }
std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version) { std::ostringstream os(std::ios::binary); auto lock = lock_shared_rec(); try { if(protocol_version >= 14) { writeU8(os, 1); // version os<<serializeString(""); // name writeU8(os, 0); // is_player writeS16(os, getId()); //id writeV3F1000(os, getBasePosition()); writeF1000(os, m_yaw); writeS16(os, m_hp); std::ostringstream msg_os(std::ios::binary); msg_os << serializeLongString(getPropertyPacket()); // message 1 msg_os << serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2 msg_os << serializeLongString(gob_cmd_update_animation( m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop)); // 3 for (UNORDERED_MAP<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii) { msg_os << serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size } msg_os << serializeLongString(gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4 int message_count = 4 + m_bone_position.size(); for (UNORDERED_SET<int>::const_iterator ii = m_attachment_child_ids.begin(); (ii != m_attachment_child_ids.end()); ++ii) { if (ServerActiveObject *obj = m_env->getActiveObject(*ii)) { message_count++; msg_os << serializeLongString(gob_cmd_update_infant(*ii, obj->getSendType(), obj->getClientInitializationData(protocol_version))); } } writeU8(os, message_count); os.write(msg_os.str().c_str(), msg_os.str().size()); } else { writeU8(os, 0); // version os<<serializeString(""); // name writeU8(os, 0); // is_player writeV3F1000(os, getBasePosition()); writeF1000(os, m_yaw); writeS16(os, m_hp); writeU8(os, 2); // number of messages stuffed in here os<<serializeLongString(getPropertyPacket()); // message 1 os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2 } } catch (std::exception &e){ errorstream << "Catn serialize object id="<<getId()<< " pos="<< getBasePosition() << std::endl; return ""; } // return result return os.str(); }
void LuaEntitySAO::step(float dtime, bool send_recommended) { if(!m_properties_sent) { m_properties_sent = true; std::string str = getPropertyPacket(); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push_back(aom); } m_last_sent_position_timer += dtime; if(m_prop.physical){ core::aabbox3d<f32> box = m_prop.collisionbox; box.MinEdge *= BS; box.MaxEdge *= BS; collisionMoveResult moveresult; f32 pos_max_d = BS*0.25; // Distance per iteration v3f p_pos = getBasePosition(); v3f p_velocity = m_velocity; IGameDef *gamedef = m_env->getGameDef(); moveresult = collisionMovePrecise(&m_env->getMap(), gamedef, pos_max_d, box, dtime, p_pos, p_velocity); // Apply results setBasePosition(p_pos); m_velocity = p_velocity; m_velocity += dtime * m_acceleration; } else { m_base_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration; m_velocity += dtime * m_acceleration; } if(m_registered){ lua_State *L = m_env->getLua(); scriptapi_luaentity_step(L, m_id, dtime); } if(send_recommended == false) return; // TODO: force send when acceleration changes enough? float minchange = 0.2*BS; if(m_last_sent_position_timer > 1.0){ minchange = 0.01*BS; } else if(m_last_sent_position_timer > 0.2){ minchange = 0.05*BS; } float move_d = m_base_position.getDistanceFrom(m_last_sent_position); move_d += m_last_sent_move_precision; float vel_d = m_velocity.getDistanceFrom(m_last_sent_velocity); if(move_d > minchange || vel_d > minchange || fabs(m_yaw - m_last_sent_yaw) > 1.0){ sendPosition(true, false); } if(m_armor_groups_sent == false){ m_armor_groups_sent = true; std::string str = gob_cmd_update_armor_groups( m_armor_groups); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push_back(aom); } }
void LuaEntitySAO::step(float dtime, bool send_recommended) { if(!m_properties_sent) { std::string str = getPropertyPacket(); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); m_properties_sent = true; } // If attached, check that our parent is still there. If it isn't, detach. if(m_attachment_parent_id && !isAttached()) { m_attachment_parent_id = 0; m_attachment_bone = ""; m_attachment_position = v3f(0,0,0); m_attachment_rotation = v3f(0,0,0); sendPosition(false, true); } m_last_sent_position_timer += dtime; // Each frame, parent position is copied if the object is attached, otherwise it's calculated normally // If the object gets detached this comes into effect automatically from the last known origin if(isAttached()) { v3f pos = m_env->getActiveObject(m_attachment_parent_id)->getBasePosition(); setBasePosition(pos); m_velocity = v3f(0,0,0); m_acceleration = v3f(0,0,0); } else { if(m_prop.physical){ aabb3f box = m_prop.collisionbox; box.MinEdge *= BS; box.MaxEdge *= BS; collisionMoveResult moveresult; f32 pos_max_d = BS*0.25; // Distance per iteration v3f p_pos = getBasePosition(); v3f p_velocity = m_velocity; v3f p_acceleration = m_acceleration; moveresult = collisionMoveSimple(m_env,m_env->getGameDef(), pos_max_d, box, m_prop.stepheight, dtime, &p_pos, &p_velocity, p_acceleration, this, m_prop.collideWithObjects); // Apply results setBasePosition(p_pos); m_velocity = p_velocity; m_acceleration = p_acceleration; } else { v3f p_pos = getBasePosition(); p_pos += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration; setBasePosition(p_pos); m_velocity += dtime * m_acceleration; } if((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 + m_prop.automatic_face_movement_dir_offset; float max_rotation_delta = dtime * m_prop.automatic_face_movement_max_rotation_per_sec; 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; } else { m_yaw = optimal_yaw; } } } if(m_registered && (getType() < ACTIVEOBJECT_TYPE_LUACREATURE || getType() > ACTIVEOBJECT_TYPE_LUAFALLING)) { m_env->getScriptIface()->luaentity_Step(m_id, dtime); } if(send_recommended == false) return; if(!isAttached()) { // TODO: force send when acceleration changes enough? float minchange = 0.2*BS; if(m_last_sent_position_timer > 1.0){ minchange = 0.01*BS; } else if(m_last_sent_position_timer > 0.2){ minchange = 0.05*BS; } float move_d = getBasePosition().getDistanceFrom(m_last_sent_position); move_d += m_last_sent_move_precision; float vel_d = m_velocity.getDistanceFrom(m_last_sent_velocity); if(move_d > minchange || vel_d > minchange || fabs(m_yaw - m_last_sent_yaw) > 1.0){ sendPosition(true, false); } } if(m_armor_groups_sent == false){ m_armor_groups_sent = true; std::string str = gob_cmd_update_armor_groups( m_armor_groups); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } if(m_animation_sent == false){ m_animation_sent = true; std::string str = gob_cmd_update_animation( m_animation_range, m_animation_speed, m_animation_blend, m_animation_loop); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } if(m_bone_position_sent == false){ m_bone_position_sent = true; for (UNORDERED_MAP<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){ std::string str = gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } } if(m_attachment_sent == false){ m_attachment_sent = true; std::string str = gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } }
void FireflySAO::step(float dtime, bool send_recommended) { ScopeProfiler sp2(g_profiler, "FireflySAO::step avg", SPT_AVG); assert(m_env); if(m_is_active == false) { if(m_inactive_interval.step(dtime, 0.5)==false) return; } /* The AI */ // Apply (less) gravity m_speed_f.Y -= dtime*3*BS; /* Move around if some player is close */ bool player_is_close = false; // Check connected players core::list<Player*> players = m_env->getPlayers(true); core::list<Player*>::Iterator i; for(i = players.begin(); i != players.end(); i++) { Player *player = *i; v3f playerpos = player->getPosition(); if(m_base_position.getDistanceFrom(playerpos) < BS*10.0) { player_is_close = true; break; } } m_is_active = player_is_close; if(player_is_close == false) { m_speed_f.X = 0; m_speed_f.Z = 0; } else { // Move around v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI)); f32 speed = BS/2; m_speed_f.X = speed * dir.X; m_speed_f.Z = speed * dir.Z; if(m_touching_ground && (m_oldpos - m_base_position).getLength() < dtime*speed/2) { m_counter1 -= dtime; if(m_counter1 < 0.0) { m_counter1 += 1.0; m_speed_f.Y = 5.0*BS; } } { m_counter2 -= dtime; if(m_counter2 < 0.0) { m_counter2 += (float)(myrand()%100)/100*3.0; m_yaw += ((float)(myrand()%200)-100)/100*180; m_yaw = wrapDegrees(m_yaw); } } } m_oldpos = m_base_position; /* Move it, with collision detection */ core::aabbox3d<f32> box(-BS/3.,-BS*2/3.0,-BS/3., BS/3.,BS*4./3.,BS/3.); collisionMoveResult moveresult; // Maximum movement without glitches f32 pos_max_d = BS*0.25; // Limit speed if(m_speed_f.getLength()*dtime > pos_max_d) m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime); v3f pos_f = getBasePosition(); v3f pos_f_old = pos_f; IGameDef *gamedef = m_env->getGameDef(); moveresult = collisionMoveSimple(&m_env->getMap(), gamedef, pos_max_d, box, dtime, pos_f, m_speed_f); m_touching_ground = moveresult.touching_ground; setBasePosition(pos_f); if(send_recommended == false) return; if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS) { m_last_sent_position = pos_f; std::ostringstream os(std::ios::binary); // command (0 = update position) writeU8(os, 0); // pos writeV3F1000(os, m_base_position); // yaw writeF1000(os, m_yaw); // create message and add to list ActiveObjectMessage aom(getId(), false, os.str()); m_messages_out.push_back(aom); } }
void Oerkki1SAO::step(float dtime, bool send_recommended) { ScopeProfiler sp2(g_profiler, "Oerkki1SAO::step avg", SPT_AVG); assert(m_env); if(m_is_active == false) { if(m_inactive_interval.step(dtime, 0.5)==false) return; } /* The AI */ m_age += dtime; if(m_age > 120) { // Die m_removed = true; return; } m_after_jump_timer -= dtime; v3f old_speed = m_speed_f; // Apply gravity m_speed_f.Y -= dtime*9.81*BS; /* Move around if some player is close */ bool player_is_close = false; bool player_is_too_close = false; v3f near_player_pos; // Check connected players core::list<Player*> players = m_env->getPlayers(true); core::list<Player*>::Iterator i; for(i = players.begin(); i != players.end(); i++) { Player *player = *i; v3f playerpos = player->getPosition(); f32 dist = m_base_position.getDistanceFrom(playerpos); if(dist < BS*0.6) { m_removed = true; return; player_is_too_close = true; near_player_pos = playerpos; } else if(dist < BS*15.0 && !player_is_too_close) { player_is_close = true; near_player_pos = playerpos; } } m_is_active = player_is_close; v3f target_speed = m_speed_f; if(!player_is_close) { target_speed = v3f(0,0,0); } else { // Move around v3f ndir = near_player_pos - m_base_position; ndir.Y = 0; ndir.normalize(); f32 nyaw = 180./PI*atan2(ndir.Z,ndir.X); if(nyaw < m_yaw - 180) nyaw += 360; else if(nyaw > m_yaw + 180) nyaw -= 360; m_yaw = 0.95*m_yaw + 0.05*nyaw; m_yaw = wrapDegrees(m_yaw); f32 speed = 2*BS; if((m_touching_ground || m_after_jump_timer > 0.0) && !player_is_too_close) { v3f dir(cos(m_yaw/180*PI),0,sin(m_yaw/180*PI)); target_speed.X = speed * dir.X; target_speed.Z = speed * dir.Z; } if(m_touching_ground && (m_oldpos - m_base_position).getLength() < dtime*speed/2) { m_counter1 -= dtime; if(m_counter1 < 0.0) { m_counter1 += 0.2; // Jump target_speed.Y = 5.0*BS; m_after_jump_timer = 1.0; } } { m_counter2 -= dtime; if(m_counter2 < 0.0) { m_counter2 += (float)(myrand()%100)/100*3.0; //m_yaw += ((float)(myrand()%200)-100)/100*180; m_yaw += ((float)(myrand()%200)-100)/100*90; m_yaw = wrapDegrees(m_yaw); } } } if((m_speed_f - target_speed).getLength() > BS*4 || player_is_too_close) accelerate_xz(m_speed_f, target_speed, dtime*BS*8); else accelerate_xz(m_speed_f, target_speed, dtime*BS*4); m_oldpos = m_base_position; /* Move it, with collision detection */ core::aabbox3d<f32> box(-BS/3.,0.0,-BS/3., BS/3.,BS*5./3.,BS/3.); collisionMoveResult moveresult; // Maximum movement without glitches f32 pos_max_d = BS*0.25; /*// Limit speed if(m_speed_f.getLength()*dtime > pos_max_d) m_speed_f *= pos_max_d / (m_speed_f.getLength()*dtime);*/ v3f pos_f = getBasePosition(); v3f pos_f_old = pos_f; IGameDef *gamedef = m_env->getGameDef(); moveresult = collisionMovePrecise(&m_env->getMap(), gamedef, pos_max_d, box, dtime, pos_f, m_speed_f); m_touching_ground = moveresult.touching_ground; // Do collision damage float tolerance = BS*30; float factor = BS*0.5; v3f speed_diff = old_speed - m_speed_f; // Increase effect in X and Z speed_diff.X *= 2; speed_diff.Z *= 2; float vel = speed_diff.getLength(); if(vel > tolerance) { f32 damage_f = (vel - tolerance)/BS*factor; u16 damage = (u16)(damage_f+0.5); doDamage(damage); } setBasePosition(pos_f); if(send_recommended == false && m_speed_f.getLength() < 3.0*BS) return; if(pos_f.getDistanceFrom(m_last_sent_position) > 0.05*BS) { m_last_sent_position = pos_f; std::ostringstream os(std::ios::binary); // command (0 = update position) writeU8(os, 0); // pos writeV3F1000(os, m_base_position); // yaw writeF1000(os, m_yaw); // create message and add to list ActiveObjectMessage aom(getId(), false, os.str()); m_messages_out.push_back(aom); } }