diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2558be9cb..4e7ac3152 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -153,6 +153,7 @@ configure_file( ) set(common_SRCS + genericobject.cpp voxelalgorithms.cpp sound.cpp quicktune.cpp diff --git a/src/content_cao.cpp b/src/content_cao.cpp index 11c9ad9c6..da4ab6144 100644 --- a/src/content_cao.cpp +++ b/src/content_cao.cpp @@ -1349,4 +1349,492 @@ public: // Prototype PlayerCAO proto_PlayerCAO(NULL, NULL); +/* + GenericCAO +*/ + +#include "genericobject.h" + +class GenericCAO : public ClientActiveObject +{ +private: + // Property-ish things + s16 m_hp_max; + bool m_physical; + float m_weight; + core::aabbox3d m_collisionbox; + std::string m_visual; + v2f m_visual_size; + core::array m_textures; + v2s16 m_spritediv; + // + scene::ISceneManager *m_smgr; + core::aabbox3d m_selection_box; + scene::IMeshSceneNode *m_meshnode; + scene::IBillboardSceneNode *m_spritenode; + v3f m_position; + v3f m_velocity; + v3f m_acceleration; + float m_yaw; + s16 m_hp; + SmoothTranslator pos_translator; + // Spritesheet/animation stuff + v2f m_tx_size; + v2s16 m_tx_basepos; + bool m_tx_select_horiz_by_yawpitch; + int m_anim_frame; + int m_anim_num_frames; + float m_anim_framelength; + float m_anim_timer; + ItemGroupList m_armor_groups; + float m_reset_textures_timer; + +public: + GenericCAO(IGameDef *gamedef, ClientEnvironment *env): + ClientActiveObject(0, gamedef, env), + // + m_hp_max(1), + m_physical(false), + m_weight(5), + m_collisionbox(-0.5,-0.5,-0.5, 0.5,0.5,0.5), + m_visual("sprite"), + m_visual_size(1,1), + m_spritediv(1,1), + // + m_smgr(NULL), + m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.), + m_meshnode(NULL), + m_spritenode(NULL), + m_position(v3f(0,10*BS,0)), + m_velocity(v3f(0,0,0)), + m_acceleration(v3f(0,0,0)), + m_yaw(0), + m_hp(1), + m_tx_size(1,1), + m_tx_basepos(0,0), + m_tx_select_horiz_by_yawpitch(false), + m_anim_frame(0), + m_anim_num_frames(1), + m_anim_framelength(0.2), + m_anim_timer(0), + m_reset_textures_timer(-1) + { + m_textures.push_back("unknown_object.png"); + if(gamedef == NULL) + ClientActiveObject::registerType(getType(), create); + } + + void initialize(const std::string &data) + { + infostream<<"GenericCAO: Got init data"<* getSelectionBox() + { + return &m_selection_box; + } + v3f getPosition() + { + return pos_translator.vect_show; + } + + void removeFromScene() + { + if(m_meshnode){ + m_meshnode->remove(); + m_meshnode = NULL; + } + if(m_spritenode){ + m_spritenode->remove(); + m_spritenode = NULL; + } + } + + void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, + IrrlichtDevice *irr) + { + m_smgr = smgr; + + if(m_meshnode != NULL || m_spritenode != NULL) + return; + + //video::IVideoDriver* driver = smgr->getVideoDriver(); + + if(m_visual == "sprite"){ + infostream<<"GenericCAO::addToScene(): single_sprite"<addBillboardSceneNode( + NULL, v2f(1, 1), v3f(0,0,0), -1); + m_spritenode->setMaterialTexture(0, + tsrc->getTextureRaw("unknown_block.png")); + m_spritenode->setMaterialFlag(video::EMF_LIGHTING, false); + m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false); + m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF); + m_spritenode->setMaterialFlag(video::EMF_FOG_ENABLE, true); + m_spritenode->setColor(video::SColor(255,0,0,0)); + m_spritenode->setVisible(false); /* Set visible when brightness is known */ + m_spritenode->setSize(m_visual_size*BS); + { + const float txs = 1.0 / 1; + const float tys = 1.0 / 1; + setBillboardTextureMatrix(m_spritenode, + txs, tys, 0, 0); + } + } else if(m_visual == "cube"){ + infostream<<"GenericCAO::addToScene(): cube"<addMeshSceneNode(mesh, NULL); + mesh->drop(); + + m_meshnode->setScale(v3f(1)); + // Will be shown when we know the brightness + m_meshnode->setVisible(false); + } else { + infostream<<"GenericCAO::addToScene(): \""<tsrc(), NULL); + } + + void updateLight(u8 light_at_pos) + { + bool is_visible = (m_hp != 0); + u8 li = decode_light(light_at_pos); + video::SColor color(255,li,li,li); + if(m_meshnode){ + setMeshColor(m_meshnode->getMesh(), color); + m_meshnode->setVisible(is_visible); + } + if(m_spritenode){ + m_spritenode->setColor(color); + m_spritenode->setVisible(is_visible); + } + } + + v3s16 getLightPosition() + { + return floatToInt(m_position, BS); + } + + void updateNodePos() + { + if(m_meshnode){ + m_meshnode->setPosition(pos_translator.vect_show); + } + if(m_spritenode){ + m_spritenode->setPosition(pos_translator.vect_show); + } + } + + void step(float dtime, ClientEnvironment *env) + { + if(m_physical){ + core::aabbox3d box = m_collisionbox; + box.MinEdge *= BS; + box.MaxEdge *= BS; + collisionMoveResult moveresult; + f32 pos_max_d = BS*0.25; // Distance per iteration + v3f p_pos = m_position; + v3f p_velocity = m_velocity; + IGameDef *gamedef = env->getGameDef(); + moveresult = collisionMovePrecise(&env->getMap(), gamedef, + pos_max_d, box, dtime, p_pos, p_velocity); + // Apply results + m_position = p_pos; + m_velocity = p_velocity; + + bool is_end_position = moveresult.collides; + pos_translator.update(m_position, is_end_position, dtime); + pos_translator.translate(dtime); + updateNodePos(); + + m_velocity += dtime * m_acceleration; + } else { + m_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration; + m_velocity += dtime * m_acceleration; + pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time); + pos_translator.translate(dtime); + updateNodePos(); + } + + m_anim_timer += dtime; + if(m_anim_timer >= m_anim_framelength){ + m_anim_timer -= m_anim_framelength; + m_anim_frame++; + if(m_anim_frame >= m_anim_num_frames) + m_anim_frame = 0; + } + + updateTexturePos(); + + if(m_reset_textures_timer >= 0){ + m_reset_textures_timer -= dtime; + if(m_reset_textures_timer <= 0){ + m_reset_textures_timer = -1; + updateTextures(""); + } + } + } + + void updateTexturePos() + { + if(m_spritenode){ + scene::ICameraSceneNode* camera = + m_spritenode->getSceneManager()->getActiveCamera(); + if(!camera) + return; + v3f cam_to_entity = m_spritenode->getAbsolutePosition() + - camera->getAbsolutePosition(); + cam_to_entity.normalize(); + + int row = m_tx_basepos.Y; + int col = m_tx_basepos.X; + + if(m_tx_select_horiz_by_yawpitch) + { + if(cam_to_entity.Y > 0.75) + col += 5; + else if(cam_to_entity.Y < -0.75) + col += 4; + else{ + float mob_dir = atan2(cam_to_entity.Z, cam_to_entity.X) / PI * 180.; + float dir = mob_dir - m_yaw; + dir = wrapDegrees_180(dir); + //infostream<<"id="<= 1) + texturestring = m_textures[0]; + texturestring += mod; + m_spritenode->setMaterialTexture(0, + tsrc->getTextureRaw(texturestring)); + } + if(m_meshnode){ + for (u32 i = 0; i < 6; ++i) + { + std::string texturestring = "unknown_block.png"; + if(m_textures.size() > i) + texturestring = m_textures[i]; + texturestring += mod; + AtlasPointer ap = tsrc->getTexture(texturestring); + + // Get the tile texture and atlas transformation + video::ITexture* atlas = ap.atlas; + v2f pos = ap.pos; + v2f size = ap.size; + + // Set material flags and texture + video::SMaterial& material = m_meshnode->getMaterial(i); + material.setFlag(video::EMF_LIGHTING, false); + material.setFlag(video::EMF_BILINEAR_FILTER, false); + material.setTexture(0, atlas); + material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y); + material.getTextureMatrix(0).setTextureScale(size.X, size.Y); + } + } + } + + void processMessage(const std::string &data) + { + //infostream<<"GenericCAO: Got message"<getToolCapabilities(m_gamedef->idef()); + PunchDamageResult result = getPunchDamage( + m_armor_groups, + toolcap, + punchitem, + time_from_last_punch); + + if(result.did_punch && result.damage != 0) + { + if(result.damage < m_hp){ + m_hp -= result.damage; + } else { + m_hp = 0; + // TODO: Execute defined fast response + // As there is no definition, make a smoke puff + ClientSimpleObject *simple = createSmokePuff( + m_smgr, m_env, m_position, + m_visual_size * BS); + m_env->addSimpleObject(simple); + } + // TODO: Execute defined fast response + // Flashing shall suffice as there is no definition + updateTextures("^[brighten"); + m_reset_textures_timer = 0.1; + } + + return false; + } + + std::string debugInfoText() + { + std::ostringstream os(std::ios::binary); + os<<"GenericCAO hp="<first<<"="<second<<", "; + } + os<<"}"; + return os.str(); + } +}; + +// Prototype +GenericCAO proto_GenericCAO(NULL, NULL); + diff --git a/src/content_object.h b/src/content_object.h index 0b85e3cf1..aa73d107c 100644 --- a/src/content_object.h +++ b/src/content_object.h @@ -32,5 +32,8 @@ with this program; if not, write to the Free Software Foundation, Inc., // Special type, not stored as a static object #define ACTIVEOBJECT_TYPE_PLAYER 100 +// Special type, only exists as CAO +#define ACTIVEOBJECT_TYPE_GENERIC 101 + #endif diff --git a/src/content_sao.cpp b/src/content_sao.cpp index d01b023de..fb8b23fbf 100644 --- a/src/content_sao.cpp +++ b/src/content_sao.cpp @@ -605,17 +605,6 @@ void LuaEntitySAO::rightClick(ServerActiveObject *clicker) scriptapi_luaentity_rightclick(L, m_id, clicker); } -void LuaEntitySAO::setHP(s16 hp) -{ - if(hp < 0) hp = 0; - m_hp = hp; -} - -s16 LuaEntitySAO::getHP() const -{ - return m_hp; -} - void LuaEntitySAO::setPos(v3f pos) { m_base_position = pos; @@ -645,6 +634,23 @@ std::string LuaEntitySAO::getDescription() return os.str(); } +void LuaEntitySAO::setHP(s16 hp) +{ + if(hp < 0) hp = 0; + m_hp = hp; +} + +s16 LuaEntitySAO::getHP() const +{ + return m_hp; +} + +void LuaEntitySAO::setArmorGroups(const ItemGroupList &armor_groups) +{ + m_armor_groups = armor_groups; + m_armor_groups_sent = false; +} + void LuaEntitySAO::setVelocity(v3f velocity) { m_velocity = velocity; @@ -708,12 +714,6 @@ std::string LuaEntitySAO::getName() return m_init_name; } -void LuaEntitySAO::setArmorGroups(const ItemGroupList &armor_groups) -{ - m_armor_groups = armor_groups; - m_armor_groups_sent = false; -} - void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end) { m_last_sent_move_precision = m_base_position.getDistanceFrom( @@ -766,6 +766,7 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_): m_time_from_last_punch(0), m_wield_index(0), m_position_not_sent(false), + m_armor_groups_sent(false), m_teleported(false), m_inventory_not_sent(false), m_hp_not_sent(false), @@ -775,6 +776,8 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_): assert(m_peer_id != 0); setBasePosition(m_player->getPosition()); m_inventory = &m_player->inventory; + m_armor_groups["choppy"] = 2; + m_armor_groups["fleshy"] = 3; } PlayerSAO::~PlayerSAO() @@ -960,12 +963,8 @@ int PlayerSAO::punch(v3f dir, return 0; } - // "Material" groups of the player - ItemGroupList groups; - groups["choppy"] = 2; - groups["fleshy"] = 3; - - HitParams hitparams = getHitParams(groups, toolcap, time_from_last_punch); + HitParams hitparams = getHitParams(m_armor_groups, toolcap, + time_from_last_punch); actionstream<<"Player "<getName()<<" punched by " <getDescription()<<", damage "<getType(); + type = obj->getSendType(); // Add to data buffer for sending writeU16((u8*)buf, id); diff --git a/src/serverobject.h b/src/serverobject.h index 8719267d7..110f67f5b 100644 --- a/src/serverobject.h +++ b/src/serverobject.h @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "activeobject.h" #include "utility.h" #include "inventorymanager.h" +#include "itemgroup.h" /* @@ -56,6 +57,9 @@ public: ServerActiveObject(ServerEnvironment *env, v3f pos); virtual ~ServerActiveObject(); + virtual u8 getSendType() const + { return getType(); } + // Called after id has been set and has been inserted in environment virtual void addedToEnvironment(){}; // Called before removing from environment @@ -146,6 +150,9 @@ public: virtual s16 getHP() const { return 0; } + virtual void setArmorGroups(const ItemGroupList &armor_groups) + {} + // Inventory and wielded item virtual Inventory* getInventory() { return NULL; }