3 Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "content_cao.h"
22 #include "environment.h"
23 #include "collision.h"
25 #include <ICameraSceneNode.h>
26 #include <ITextSceneNode.h>
27 #include <IBillboardSceneNode.h>
28 #include "serialization.h" // For decompressZlib
30 #include "clientobject.h"
31 #include "content_object.h"
33 #include "utility.h" // For IntervalLimiter
36 core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
42 struct SmoothTranslator
49 f32 anim_time_counter;
69 anim_time_counter = 0;
78 void update(v3f vect_new, bool is_end_position=false, float update_interval=-1)
80 aim_is_end = is_end_position;
83 if(update_interval > 0){
84 anim_time = update_interval;
86 if(anim_time < 0.001 || anim_time > 1.0)
87 anim_time = anim_time_counter;
89 anim_time = anim_time * 0.9 + anim_time_counter * 0.1;
91 anim_time_counter = 0;
95 void translate(f32 dtime)
97 anim_time_counter = anim_time_counter + dtime;
98 anim_counter = anim_counter + dtime;
99 v3f vect_move = vect_aim - vect_old;
101 if(anim_time > 0.001)
102 moveratio = anim_time_counter / anim_time;
103 // Move a bit less than should, to avoid oscillation
104 moveratio = moveratio * 0.8;
105 float move_end = 1.5;
108 if(moveratio > move_end)
109 moveratio = move_end;
110 vect_show = vect_old + vect_move * moveratio;
115 return ((anim_time_counter / anim_time) < 1.4);
124 class TestCAO : public ClientActiveObject
127 TestCAO(IGameDef *gamedef, ClientEnvironment *env);
132 return ACTIVEOBJECT_TYPE_TEST;
135 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
137 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
138 IrrlichtDevice *irr);
139 void removeFromScene();
140 void updateLight(u8 light_at_pos);
141 v3s16 getLightPosition();
142 void updateNodePos();
144 void step(float dtime, ClientEnvironment *env);
146 void processMessage(const std::string &data);
149 scene::IMeshSceneNode *m_node;
157 class ItemCAO : public ClientActiveObject
160 ItemCAO(IGameDef *gamedef, ClientEnvironment *env);
165 return ACTIVEOBJECT_TYPE_ITEM;
168 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
170 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
171 IrrlichtDevice *irr);
172 void removeFromScene();
173 void updateLight(u8 light_at_pos);
174 v3s16 getLightPosition();
175 void updateNodePos();
176 void updateInfoText();
177 void updateTexture();
179 void step(float dtime, ClientEnvironment *env);
181 void processMessage(const std::string &data);
183 void initialize(const std::string &data);
185 core::aabbox3d<f32>* getSelectionBox()
186 {return &m_selection_box;}
190 std::string infoText()
194 core::aabbox3d<f32> m_selection_box;
195 scene::IMeshSceneNode *m_node;
197 std::string m_itemstring;
198 std::string m_infotext;
205 class RatCAO : public ClientActiveObject
208 RatCAO(IGameDef *gamedef, ClientEnvironment *env);
213 return ACTIVEOBJECT_TYPE_RAT;
216 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
218 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
219 IrrlichtDevice *irr);
220 void removeFromScene();
221 void updateLight(u8 light_at_pos);
222 v3s16 getLightPosition();
223 void updateNodePos();
225 void step(float dtime, ClientEnvironment *env);
227 void processMessage(const std::string &data);
229 void initialize(const std::string &data);
231 core::aabbox3d<f32>* getSelectionBox()
232 {return &m_selection_box;}
234 {return pos_translator.vect_show;}
235 //{return m_position;}
238 core::aabbox3d<f32> m_selection_box;
239 scene::IMeshSceneNode *m_node;
242 SmoothTranslator pos_translator;
249 class Oerkki1CAO : public ClientActiveObject
252 Oerkki1CAO(IGameDef *gamedef, ClientEnvironment *env);
253 virtual ~Oerkki1CAO();
257 return ACTIVEOBJECT_TYPE_OERKKI1;
260 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
262 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
263 IrrlichtDevice *irr);
264 void removeFromScene();
265 void updateLight(u8 light_at_pos);
266 v3s16 getLightPosition();
267 void updateNodePos();
269 void step(float dtime, ClientEnvironment *env);
271 void processMessage(const std::string &data);
273 void initialize(const std::string &data);
275 core::aabbox3d<f32>* getSelectionBox()
276 {return &m_selection_box;}
278 {return pos_translator.vect_show;}
279 //{return m_position;}
281 // If returns true, punch will not be sent to the server
282 bool directReportPunch(const std::string &toolname, v3f dir);
285 IntervalLimiter m_attack_interval;
286 core::aabbox3d<f32> m_selection_box;
287 scene::IMeshSceneNode *m_node;
290 SmoothTranslator pos_translator;
291 float m_damage_visual_timer;
292 bool m_damage_texture_enabled;
299 class FireflyCAO : public ClientActiveObject
302 FireflyCAO(IGameDef *gamedef, ClientEnvironment *env);
303 virtual ~FireflyCAO();
307 return ACTIVEOBJECT_TYPE_FIREFLY;
310 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
312 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
313 IrrlichtDevice *irr);
314 void removeFromScene();
315 void updateLight(u8 light_at_pos);
316 v3s16 getLightPosition();
317 void updateNodePos();
319 void step(float dtime, ClientEnvironment *env);
321 void processMessage(const std::string &data);
323 void initialize(const std::string &data);
325 core::aabbox3d<f32>* getSelectionBox()
326 {return &m_selection_box;}
331 core::aabbox3d<f32> m_selection_box;
332 scene::IMeshSceneNode *m_node;
335 SmoothTranslator pos_translator;
338 static void setBillboardTextureMatrix(scene::IBillboardSceneNode *bill,
339 float txs, float tys, int col, int row)
341 video::SMaterial& material = bill->getMaterial(0);
342 core::matrix4& matrix = material.getTextureMatrix(0);
343 matrix.setTextureTranslate(txs*col, tys*row);
344 matrix.setTextureScale(txs, tys);
351 class MobV2CAO : public ClientActiveObject
354 MobV2CAO(IGameDef *gamedef, ClientEnvironment *env);
359 return ACTIVEOBJECT_TYPE_MOBV2;
362 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
364 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
365 IrrlichtDevice *irr);
366 void removeFromScene();
367 void updateLight(u8 light_at_pos);
368 v3s16 getLightPosition();
369 void updateNodePos();
371 void step(float dtime, ClientEnvironment *env);
373 void processMessage(const std::string &data);
375 void initialize(const std::string &data);
377 core::aabbox3d<f32>* getSelectionBox()
378 {return &m_selection_box;}
380 {return pos_translator.vect_show;}
381 //{return m_position;}
382 bool doShowSelectionBox(){return false;}
384 // If returns true, punch will not be sent to the server
385 bool directReportPunch(const std::string &toolname, v3f dir);
388 void setLooks(const std::string &looks);
390 IntervalLimiter m_attack_interval;
391 core::aabbox3d<f32> m_selection_box;
392 scene::IBillboardSceneNode *m_node;
394 std::string m_texture_name;
396 SmoothTranslator pos_translator;
398 float m_walking_unset_timer;
401 float m_damage_visual_timer;
404 float m_shooting_unset_timer;
407 bool m_bright_shooting;
408 std::string m_sprite_type;
409 int m_simple_anim_frames;
410 float m_simple_anim_frametime;
411 bool m_lock_full_brightness;
412 int m_player_hit_damage;
413 float m_player_hit_distance;
414 float m_player_hit_interval;
415 float m_player_hit_timer;
417 Settings *m_properties;
425 TestCAO proto_TestCAO(NULL, NULL);
427 TestCAO::TestCAO(IGameDef *gamedef, ClientEnvironment *env):
428 ClientActiveObject(0, gamedef, env),
430 m_position(v3f(0,10*BS,0))
432 ClientActiveObject::registerType(getType(), create);
439 ClientActiveObject* TestCAO::create(IGameDef *gamedef, ClientEnvironment *env)
441 return new TestCAO(gamedef, env);
444 void TestCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
450 //video::IVideoDriver* driver = smgr->getVideoDriver();
452 scene::SMesh *mesh = new scene::SMesh();
453 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
454 video::SColor c(255,255,255,255);
455 video::S3DVertex vertices[4] =
457 video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
458 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
459 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
460 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),
462 u16 indices[] = {0,1,2,2,3,0};
463 buf->append(vertices, 4, indices, 6);
465 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
466 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
467 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("rat.png"));
468 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
469 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
470 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
472 mesh->addMeshBuffer(buf);
474 m_node = smgr->addMeshSceneNode(mesh, NULL);
479 void TestCAO::removeFromScene()
488 void TestCAO::updateLight(u8 light_at_pos)
492 v3s16 TestCAO::getLightPosition()
494 return floatToInt(m_position, BS);
497 void TestCAO::updateNodePos()
502 m_node->setPosition(m_position);
503 //m_node->setRotation(v3f(0, 45, 0));
506 void TestCAO::step(float dtime, ClientEnvironment *env)
510 v3f rot = m_node->getRotation();
511 //infostream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
512 rot.Y += dtime * 180;
513 m_node->setRotation(rot);
517 void TestCAO::processMessage(const std::string &data)
519 infostream<<"TestCAO: Got data: "<<data<<std::endl;
520 std::istringstream is(data, std::ios::binary);
538 #include "inventory.h"
541 ItemCAO proto_ItemCAO(NULL, NULL);
543 ItemCAO::ItemCAO(IGameDef *gamedef, ClientEnvironment *env):
544 ClientActiveObject(0, gamedef, env),
545 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.),
547 m_position(v3f(0,10*BS,0))
551 ClientActiveObject::registerType(getType(), create);
559 ClientActiveObject* ItemCAO::create(IGameDef *gamedef, ClientEnvironment *env)
561 return new ItemCAO(gamedef, env);
564 void ItemCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
570 //video::IVideoDriver* driver = smgr->getVideoDriver();
572 scene::SMesh *mesh = new scene::SMesh();
573 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
574 video::SColor c(255,255,255,255);
575 video::S3DVertex vertices[4] =
577 /*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
578 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
579 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
580 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/
581 video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1),
582 video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1),
583 video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0),
584 video::S3DVertex(BS/3.,0+BS*2./3.,0, 0,0,0, c, 0,0),
586 u16 indices[] = {0,1,2,2,3,0};
587 buf->append(vertices, 4, indices, 6);
589 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
590 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
591 // Initialize with a generated placeholder texture
592 buf->getMaterial().setTexture(0, tsrc->getTextureRaw(""));
593 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
594 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
595 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
597 mesh->addMeshBuffer(buf);
599 m_node = smgr->addMeshSceneNode(mesh, NULL);
610 void ItemCAO::removeFromScene()
619 void ItemCAO::updateLight(u8 light_at_pos)
624 u8 li = decode_light(light_at_pos);
625 video::SColor color(255,li,li,li);
626 setMeshColor(m_node->getMesh(), color);
629 v3s16 ItemCAO::getLightPosition()
631 return floatToInt(m_position, BS);
634 void ItemCAO::updateNodePos()
639 m_node->setPosition(m_position);
642 void ItemCAO::updateInfoText()
645 IItemDefManager *idef = m_gamedef->idef();
647 item.deSerialize(m_itemstring, idef);
648 if(item.isKnown(idef))
649 m_infotext = item.getDefinition(idef).description;
651 m_infotext = "Unknown item: '" + m_itemstring + "'";
653 m_infotext += " (" + itos(item.count) + ")";
655 catch(SerializationError &e)
657 m_infotext = "Unknown item: '" + m_itemstring + "'";
661 void ItemCAO::updateTexture()
666 // Create an inventory item to see what is its image
667 std::istringstream is(m_itemstring, std::ios_base::binary);
668 video::ITexture *texture = NULL;
670 IItemDefManager *idef = m_gamedef->idef();
672 item.deSerialize(is, idef);
673 texture = item.getDefinition(idef).inventory_texture;
675 catch(SerializationError &e)
677 infostream<<"WARNING: "<<__FUNCTION_NAME
678 <<": error deSerializing itemstring \""
679 <<m_itemstring<<std::endl;
682 // Set meshbuffer texture
683 m_node->getMaterial(0).setTexture(0, texture);
687 void ItemCAO::step(float dtime, ClientEnvironment *env)
691 /*v3f rot = m_node->getRotation();
692 rot.Y += dtime * 120;
693 m_node->setRotation(rot);*/
694 LocalPlayer *player = env->getLocalPlayer();
696 v3f rot = m_node->getRotation();
697 rot.Y = 180.0 - (player->getYaw());
698 m_node->setRotation(rot);
702 void ItemCAO::processMessage(const std::string &data)
704 //infostream<<"ItemCAO: Got message"<<std::endl;
705 std::istringstream is(data, std::ios::binary);
711 m_position = readV3F1000(is);
717 m_itemstring = deSerializeString(is);
723 void ItemCAO::initialize(const std::string &data)
725 infostream<<"ItemCAO: Got init data"<<std::endl;
728 std::istringstream is(data, std::ios::binary);
730 u8 version = readU8(is);
735 m_position = readV3F1000(is);
737 m_itemstring = deSerializeString(is);
748 #include "inventory.h"
751 RatCAO proto_RatCAO(NULL, NULL);
753 RatCAO::RatCAO(IGameDef *gamedef, ClientEnvironment *env):
754 ClientActiveObject(0, gamedef, env),
755 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
757 m_position(v3f(0,10*BS,0)),
760 ClientActiveObject::registerType(getType(), create);
767 ClientActiveObject* RatCAO::create(IGameDef *gamedef, ClientEnvironment *env)
769 return new RatCAO(gamedef, env);
772 void RatCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
778 //video::IVideoDriver* driver = smgr->getVideoDriver();
780 scene::SMesh *mesh = new scene::SMesh();
781 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
782 video::SColor c(255,255,255,255);
783 video::S3DVertex vertices[4] =
785 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
786 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
787 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
788 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
790 u16 indices[] = {0,1,2,2,3,0};
791 buf->append(vertices, 4, indices, 6);
793 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
794 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
795 //buf->getMaterial().setTexture(0, NULL);
796 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("rat.png"));
797 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
798 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
799 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
801 mesh->addMeshBuffer(buf);
803 m_node = smgr->addMeshSceneNode(mesh, NULL);
805 // Set it to use the materials of the meshbuffers directly.
806 // This is needed for changing the texture in the future
807 m_node->setReadOnlyMaterials(true);
811 void RatCAO::removeFromScene()
820 void RatCAO::updateLight(u8 light_at_pos)
825 u8 li = decode_light(light_at_pos);
826 video::SColor color(255,li,li,li);
827 setMeshColor(m_node->getMesh(), color);
830 v3s16 RatCAO::getLightPosition()
832 return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
835 void RatCAO::updateNodePos()
840 //m_node->setPosition(m_position);
841 m_node->setPosition(pos_translator.vect_show);
843 v3f rot = m_node->getRotation();
844 rot.Y = 180.0 - m_yaw;
845 m_node->setRotation(rot);
848 void RatCAO::step(float dtime, ClientEnvironment *env)
850 pos_translator.translate(dtime);
854 void RatCAO::processMessage(const std::string &data)
856 //infostream<<"RatCAO: Got message"<<std::endl;
857 std::istringstream is(data, std::ios::binary);
863 m_position = readV3F1000(is);
864 pos_translator.update(m_position);
866 m_yaw = readF1000(is);
871 void RatCAO::initialize(const std::string &data)
873 //infostream<<"RatCAO: Got init data"<<std::endl;
876 std::istringstream is(data, std::ios::binary);
878 u8 version = readU8(is);
883 m_position = readV3F1000(is);
884 pos_translator.init(m_position);
894 #include "inventory.h"
897 Oerkki1CAO proto_Oerkki1CAO(NULL, NULL);
899 Oerkki1CAO::Oerkki1CAO(IGameDef *gamedef, ClientEnvironment *env):
900 ClientActiveObject(0, gamedef, env),
901 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.),
903 m_position(v3f(0,10*BS,0)),
905 m_damage_visual_timer(0),
906 m_damage_texture_enabled(false)
908 ClientActiveObject::registerType(getType(), create);
911 Oerkki1CAO::~Oerkki1CAO()
915 ClientActiveObject* Oerkki1CAO::create(IGameDef *gamedef, ClientEnvironment *env)
917 return new Oerkki1CAO(gamedef, env);
920 void Oerkki1CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
926 //video::IVideoDriver* driver = smgr->getVideoDriver();
928 scene::SMesh *mesh = new scene::SMesh();
929 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
930 video::SColor c(255,255,255,255);
931 video::S3DVertex vertices[4] =
933 video::S3DVertex(-BS/2-BS,0,0, 0,0,0, c, 0,1),
934 video::S3DVertex(BS/2+BS,0,0, 0,0,0, c, 1,1),
935 video::S3DVertex(BS/2+BS,BS*2,0, 0,0,0, c, 1,0),
936 video::S3DVertex(-BS/2-BS,BS*2,0, 0,0,0, c, 0,0),
938 u16 indices[] = {0,1,2,2,3,0};
939 buf->append(vertices, 4, indices, 6);
941 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
942 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
943 //buf->getMaterial().setTexture(0, NULL);
944 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("oerkki1.png"));
945 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
946 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
947 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
949 mesh->addMeshBuffer(buf);
951 m_node = smgr->addMeshSceneNode(mesh, NULL);
953 // Set it to use the materials of the meshbuffers directly.
954 // This is needed for changing the texture in the future
955 m_node->setReadOnlyMaterials(true);
959 void Oerkki1CAO::removeFromScene()
968 void Oerkki1CAO::updateLight(u8 light_at_pos)
973 if(light_at_pos <= 2)
975 m_node->setVisible(false);
979 m_node->setVisible(true);
981 u8 li = decode_light(light_at_pos);
982 video::SColor color(255,li,li,li);
983 setMeshColor(m_node->getMesh(), color);
986 v3s16 Oerkki1CAO::getLightPosition()
988 return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
991 void Oerkki1CAO::updateNodePos()
996 //m_node->setPosition(m_position);
997 m_node->setPosition(pos_translator.vect_show);
999 v3f rot = m_node->getRotation();
1000 rot.Y = 180.0 - m_yaw + 90.0;
1001 m_node->setRotation(rot);
1004 void Oerkki1CAO::step(float dtime, ClientEnvironment *env)
1006 ITextureSource *tsrc = m_gamedef->tsrc();
1008 pos_translator.translate(dtime);
1011 LocalPlayer *player = env->getLocalPlayer();
1014 v3f playerpos = player->getPosition();
1015 v2f playerpos_2d(playerpos.X,playerpos.Z);
1016 v2f objectpos_2d(m_position.X,m_position.Z);
1018 if(fabs(m_position.Y - playerpos.Y) < 1.5*BS &&
1019 objectpos_2d.getDistanceFrom(playerpos_2d) < 1.5*BS)
1021 if(m_attack_interval.step(dtime, 0.5))
1023 env->damageLocalPlayer(2);
1027 if(m_damage_visual_timer > 0)
1029 if(!m_damage_texture_enabled)
1031 // Enable damage texture
1034 /*video::IVideoDriver* driver =
1035 m_node->getSceneManager()->getVideoDriver();*/
1037 scene::IMesh *mesh = m_node->getMesh();
1041 u16 mc = mesh->getMeshBufferCount();
1042 for(u16 j=0; j<mc; j++)
1044 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
1045 buf->getMaterial().setTexture(0,
1046 tsrc->getTextureRaw("oerkki1_damaged.png"));
1049 m_damage_texture_enabled = true;
1051 m_damage_visual_timer -= dtime;
1055 if(m_damage_texture_enabled)
1057 // Disable damage texture
1060 /*video::IVideoDriver* driver =
1061 m_node->getSceneManager()->getVideoDriver();*/
1063 scene::IMesh *mesh = m_node->getMesh();
1067 u16 mc = mesh->getMeshBufferCount();
1068 for(u16 j=0; j<mc; j++)
1070 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
1071 buf->getMaterial().setTexture(0,
1072 tsrc->getTextureRaw("oerkki1.png"));
1075 m_damage_texture_enabled = false;
1080 void Oerkki1CAO::processMessage(const std::string &data)
1082 //infostream<<"Oerkki1CAO: Got message"<<std::endl;
1083 std::istringstream is(data, std::ios::binary);
1085 u8 cmd = readU8(is);
1089 m_position = readV3F1000(is);
1090 pos_translator.update(m_position);
1092 m_yaw = readF1000(is);
1097 //u16 damage = readU8(is);
1098 m_damage_visual_timer = 1.0;
1102 void Oerkki1CAO::initialize(const std::string &data)
1104 //infostream<<"Oerkki1CAO: Got init data"<<std::endl;
1107 std::istringstream is(data, std::ios::binary);
1109 u8 version = readU8(is);
1114 m_position = readV3F1000(is);
1115 pos_translator.init(m_position);
1121 bool Oerkki1CAO::directReportPunch(const std::string &toolname, v3f dir)
1123 m_damage_visual_timer = 1.0;
1125 m_position += dir * BS;
1126 pos_translator.sharpen();
1127 pos_translator.update(m_position);
1138 FireflyCAO proto_FireflyCAO(NULL, NULL);
1140 FireflyCAO::FireflyCAO(IGameDef *gamedef, ClientEnvironment *env):
1141 ClientActiveObject(0, gamedef, env),
1142 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
1144 m_position(v3f(0,10*BS,0)),
1147 ClientActiveObject::registerType(getType(), create);
1150 FireflyCAO::~FireflyCAO()
1154 ClientActiveObject* FireflyCAO::create(IGameDef *gamedef, ClientEnvironment *env)
1156 return new FireflyCAO(gamedef, env);
1159 void FireflyCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
1160 IrrlichtDevice *irr)
1165 //video::IVideoDriver* driver = smgr->getVideoDriver();
1167 scene::SMesh *mesh = new scene::SMesh();
1168 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
1169 video::SColor c(255,255,255,255);
1170 video::S3DVertex vertices[4] =
1172 video::S3DVertex(0,0,0, 0,0,0, c, 0,1),
1173 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
1174 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
1175 video::S3DVertex(0,BS/2,0, 0,0,0, c, 0,0),
1177 u16 indices[] = {0,1,2,2,3,0};
1178 buf->append(vertices, 4, indices, 6);
1180 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
1181 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
1182 //buf->getMaterial().setTexture(0, NULL);
1183 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("firefly.png"));
1184 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
1185 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
1186 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
1188 mesh->addMeshBuffer(buf);
1190 m_node = smgr->addMeshSceneNode(mesh, NULL);
1192 // Set it to use the materials of the meshbuffers directly.
1193 // This is needed for changing the texture in the future
1194 m_node->setReadOnlyMaterials(true);
1198 void FireflyCAO::removeFromScene()
1207 void FireflyCAO::updateLight(u8 light_at_pos)
1213 video::SColor color(255,li,li,li);
1214 setMeshColor(m_node->getMesh(), color);
1217 v3s16 FireflyCAO::getLightPosition()
1219 return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
1222 void FireflyCAO::updateNodePos()
1227 //m_node->setPosition(m_position);
1228 m_node->setPosition(pos_translator.vect_show);
1230 v3f rot = m_node->getRotation();
1231 rot.Y = 180.0 - m_yaw;
1232 m_node->setRotation(rot);
1235 void FireflyCAO::step(float dtime, ClientEnvironment *env)
1237 pos_translator.translate(dtime);
1241 void FireflyCAO::processMessage(const std::string &data)
1243 //infostream<<"FireflyCAO: Got message"<<std::endl;
1244 std::istringstream is(data, std::ios::binary);
1246 u8 cmd = readU8(is);
1250 m_position = readV3F1000(is);
1251 pos_translator.update(m_position);
1253 m_yaw = readF1000(is);
1258 void FireflyCAO::initialize(const std::string &data)
1260 //infostream<<"FireflyCAO: Got init data"<<std::endl;
1263 std::istringstream is(data, std::ios::binary);
1265 u8 version = readU8(is);
1270 m_position = readV3F1000(is);
1271 pos_translator.init(m_position);
1282 MobV2CAO proto_MobV2CAO(NULL, NULL);
1284 MobV2CAO::MobV2CAO(IGameDef *gamedef, ClientEnvironment *env):
1285 ClientActiveObject(0, gamedef, env),
1286 m_selection_box(-0.4*BS,-0.4*BS,-0.4*BS, 0.4*BS,0.8*BS,0.4*BS),
1288 m_position(v3f(0,10*BS,0)),
1291 m_walking_unset_timer(0),
1294 m_damage_visual_timer(0),
1297 m_shooting_unset_timer(0),
1298 m_sprite_size(BS,BS),
1300 m_bright_shooting(false),
1301 m_lock_full_brightness(false),
1302 m_player_hit_timer(0)
1304 ClientActiveObject::registerType(getType(), create);
1306 m_properties = new Settings;
1309 MobV2CAO::~MobV2CAO()
1311 delete m_properties;
1314 ClientActiveObject* MobV2CAO::create(IGameDef *gamedef, ClientEnvironment *env)
1316 return new MobV2CAO(gamedef, env);
1319 void MobV2CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
1320 IrrlichtDevice *irr)
1325 /*infostream<<"MobV2CAO::addToScene using texture_name="<<
1326 m_texture_name<<std::endl;*/
1327 std::string texture_string = m_texture_name +
1328 "^[makealpha:128,0,0^[makealpha:128,128,0";
1330 scene::IBillboardSceneNode *bill = smgr->addBillboardSceneNode(
1331 NULL, v2f(1, 1), v3f(0,0,0), -1);
1332 bill->setMaterialTexture(0, tsrc->getTextureRaw(texture_string));
1333 bill->setMaterialFlag(video::EMF_LIGHTING, false);
1334 bill->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
1335 bill->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
1336 bill->setMaterialFlag(video::EMF_FOG_ENABLE, true);
1337 bill->setColor(video::SColor(255,0,0,0));
1338 bill->setVisible(false); /* Set visible when brightness is known */
1339 bill->setSize(m_sprite_size);
1340 if(m_sprite_type == "humanoid_1"){
1341 const float txp = 1./192;
1342 const float txs = txp*32;
1343 const float typ = 1./240;
1344 const float tys = typ*48;
1345 setBillboardTextureMatrix(bill, txs, tys, 0, 0);
1346 } else if(m_sprite_type == "simple"){
1347 const float txs = 1.0;
1348 const float tys = 1.0 / m_simple_anim_frames;
1349 setBillboardTextureMatrix(bill, txs, tys, 0, 0);
1351 infostream<<"MobV2CAO: Unknown sprite type \""<<m_sprite_type<<"\""
1360 void MobV2CAO::removeFromScene()
1369 void MobV2CAO::updateLight(u8 light_at_pos)
1371 if(m_lock_full_brightness)
1374 m_last_light = light_at_pos;
1379 if(m_damage_visual_timer > 0)
1382 if(m_shooting && m_bright_shooting)
1385 /*if(light_at_pos <= 2){
1386 m_node->setVisible(false);
1390 m_node->setVisible(true);
1392 u8 li = decode_light(light_at_pos);
1393 video::SColor color(255,li,li,li);
1394 m_node->setColor(color);
1397 v3s16 MobV2CAO::getLightPosition()
1399 return floatToInt(m_position+v3f(0,0,0), BS);
1402 void MobV2CAO::updateNodePos()
1407 m_node->setPosition(pos_translator.vect_show + v3f(0,m_sprite_y,0));
1410 void MobV2CAO::step(float dtime, ClientEnvironment *env)
1412 scene::IBillboardSceneNode *bill = m_node;
1416 pos_translator.translate(dtime);
1418 if(m_sprite_type == "humanoid_1"){
1419 scene::ICameraSceneNode* camera = m_node->getSceneManager()->getActiveCamera();
1422 v3f cam_to_mob = m_node->getAbsolutePosition() - camera->getAbsolutePosition();
1423 cam_to_mob.normalize();
1425 if(cam_to_mob.Y > 0.75)
1427 else if(cam_to_mob.Y < -0.75)
1430 float mob_dir = atan2(cam_to_mob.Z, cam_to_mob.X) / PI * 180.;
1431 float dir = mob_dir - m_yaw;
1432 dir = wrapDegrees_180(dir);
1433 //infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
1434 if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
1436 else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
1438 else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
1440 else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
1449 } else if(m_walking){
1450 m_walk_timer += dtime;
1451 if(m_walk_timer >= 0.5){
1452 m_walk_frame = (m_walk_frame + 1) % 2;
1455 if(m_walk_frame == 0)
1461 const float txp = 1./192;
1462 const float txs = txp*32;
1463 const float typ = 1./240;
1464 const float tys = typ*48;
1465 setBillboardTextureMatrix(bill, txs, tys, col, row);
1466 } else if(m_sprite_type == "simple"){
1467 m_walk_timer += dtime;
1468 if(m_walk_timer >= m_simple_anim_frametime){
1469 m_walk_frame = (m_walk_frame + 1) % m_simple_anim_frames;
1473 int row = m_walk_frame;
1474 const float txs = 1.0;
1475 const float tys = 1.0 / m_simple_anim_frames;
1476 setBillboardTextureMatrix(bill, txs, tys, col, row);
1478 infostream<<"MobV2CAO::step(): Unknown sprite type \""
1479 <<m_sprite_type<<"\""<<std::endl;
1484 /* Damage local player */
1485 if(m_player_hit_damage && m_player_hit_timer <= 0.0){
1486 LocalPlayer *player = env->getLocalPlayer();
1489 v3f playerpos = player->getPosition();
1490 v2f playerpos_2d(playerpos.X,playerpos.Z);
1491 v2f objectpos_2d(m_position.X,m_position.Z);
1493 if(fabs(m_position.Y - playerpos.Y) < m_player_hit_distance*BS &&
1494 objectpos_2d.getDistanceFrom(playerpos_2d) < m_player_hit_distance*BS)
1496 env->damageLocalPlayer(m_player_hit_damage);
1497 m_player_hit_timer = m_player_hit_interval;
1503 m_player_hit_timer -= dtime;
1505 if(m_damage_visual_timer >= 0){
1506 m_damage_visual_timer -= dtime;
1507 if(m_damage_visual_timer <= 0){
1508 infostream<<"id="<<m_id<<" damage visual ended"<<std::endl;
1512 m_walking_unset_timer += dtime;
1513 if(m_walking_unset_timer >= 1.0){
1517 m_shooting_unset_timer -= dtime;
1518 if(m_shooting_unset_timer <= 0.0){
1519 if(m_bright_shooting){
1520 u8 li = decode_light(m_last_light);
1521 video::SColor color(255,li,li,li);
1522 bill->setColor(color);
1523 m_bright_shooting = false;
1530 void MobV2CAO::processMessage(const std::string &data)
1532 //infostream<<"MobV2CAO: Got message"<<std::endl;
1533 std::istringstream is(data, std::ios::binary);
1535 u8 cmd = readU8(is);
1541 m_position = readV3F1000(is);
1542 pos_translator.update(m_position);
1544 m_yaw = readF1000(is);
1547 m_walking_unset_timer = 0;
1554 //u16 damage = readU16(is);
1556 /*u8 li = decode_light(m_last_light);
1562 /*video::SColor color(255,255,0,0);
1563 m_node->setColor(color);
1565 m_damage_visual_timer = 0.2;*/
1571 m_shooting_unset_timer = readF1000(is);
1573 m_bright_shooting = readU8(is);
1574 if(m_bright_shooting){
1576 video::SColor color(255,li,li,li);
1577 m_node->setColor(color);
1584 void MobV2CAO::initialize(const std::string &data)
1586 //infostream<<"MobV2CAO: Got init data"<<std::endl;
1589 std::istringstream is(data, std::ios::binary);
1591 u8 version = readU8(is);
1594 infostream<<__FUNCTION_NAME<<": Invalid version"<<std::endl;
1598 std::ostringstream tmp_os(std::ios::binary);
1599 decompressZlib(is, tmp_os);
1600 std::istringstream tmp_is(tmp_os.str(), std::ios::binary);
1601 m_properties->parseConfigLines(tmp_is, "MobArgsEnd");
1603 infostream<<"MobV2CAO::initialize(): got properties:"<<std::endl;
1604 m_properties->writeLines(infostream);
1606 m_properties->setDefault("looks", "dummy_default");
1607 m_properties->setDefault("yaw", "0");
1608 m_properties->setDefault("pos", "(0,0,0)");
1609 m_properties->setDefault("player_hit_damage", "0");
1610 m_properties->setDefault("player_hit_distance", "1.5");
1611 m_properties->setDefault("player_hit_interval", "1.5");
1613 setLooks(m_properties->get("looks"));
1614 m_yaw = m_properties->getFloat("yaw");
1615 m_position = m_properties->getV3F("pos");
1616 m_player_hit_damage = m_properties->getS32("player_hit_damage");
1617 m_player_hit_distance = m_properties->getFloat("player_hit_distance");
1618 m_player_hit_interval = m_properties->getFloat("player_hit_interval");
1620 pos_translator.init(m_position);
1626 bool MobV2CAO::directReportPunch(const std::string &toolname, v3f dir)
1628 video::SColor color(255,255,0,0);
1629 m_node->setColor(color);
1631 m_damage_visual_timer = 0.05;
1633 m_position += dir * BS;
1634 pos_translator.sharpen();
1635 pos_translator.update(m_position);
1641 void MobV2CAO::setLooks(const std::string &looks)
1643 v2f selection_size = v2f(0.4, 0.4) * BS;
1644 float selection_y = 0 * BS;
1646 if(looks == "dungeon_master"){
1647 m_texture_name = "dungeon_master.png";
1648 m_sprite_type = "humanoid_1";
1649 m_sprite_size = v2f(2, 3) * BS;
1650 m_sprite_y = 0.85 * BS;
1651 selection_size = v2f(0.4, 2.6) * BS;
1652 selection_y = -0.4 * BS;
1654 else if(looks == "fireball"){
1655 m_texture_name = "fireball.png";
1656 m_sprite_type = "simple";
1657 m_sprite_size = v2f(1, 1) * BS;
1658 m_simple_anim_frames = 3;
1659 m_simple_anim_frametime = 0.1;
1660 m_lock_full_brightness = true;
1663 m_texture_name = "stone.png";
1664 m_sprite_type = "simple";
1665 m_sprite_size = v2f(1, 1) * BS;
1666 m_simple_anim_frames = 3;
1667 m_simple_anim_frametime = 0.333;
1668 selection_size = v2f(0.4, 0.4) * BS;
1669 selection_y = 0 * BS;
1672 m_selection_box = core::aabbox3d<f32>(
1673 -selection_size.X, selection_y, -selection_size.X,
1674 selection_size.X, selection_y+selection_size.Y,
1682 #include "luaentity_common.h"
1684 class LuaEntityCAO : public ClientActiveObject
1687 core::aabbox3d<f32> m_selection_box;
1688 scene::IMeshSceneNode *m_meshnode;
1689 scene::IBillboardSceneNode *m_spritenode;
1694 struct LuaEntityProperties *m_prop;
1695 SmoothTranslator pos_translator;
1696 // Spritesheet/animation stuff
1699 bool m_tx_select_horiz_by_yawpitch;
1701 int m_anim_num_frames;
1702 float m_anim_framelength;
1706 LuaEntityCAO(IGameDef *gamedef, ClientEnvironment *env):
1707 ClientActiveObject(0, gamedef, env),
1708 m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.),
1711 m_position(v3f(0,10*BS,0)),
1712 m_velocity(v3f(0,0,0)),
1713 m_acceleration(v3f(0,0,0)),
1715 m_prop(new LuaEntityProperties),
1718 m_tx_select_horiz_by_yawpitch(false),
1720 m_anim_num_frames(1),
1721 m_anim_framelength(0.2),
1725 ClientActiveObject::registerType(getType(), create);
1728 void initialize(const std::string &data)
1730 infostream<<"LuaEntityCAO: Got init data"<<std::endl;
1732 std::istringstream is(data, std::ios::binary);
1734 u8 version = readU8(is);
1739 m_position = readV3F1000(is);
1741 m_yaw = readF1000(is);
1743 std::istringstream prop_is(deSerializeLongString(is), std::ios::binary);
1744 m_prop->deSerialize(prop_is);
1746 infostream<<"m_prop: "<<m_prop->dump()<<std::endl;
1748 m_selection_box = m_prop->collisionbox;
1749 m_selection_box.MinEdge *= BS;
1750 m_selection_box.MaxEdge *= BS;
1752 pos_translator.init(m_position);
1754 m_tx_size.X = 1.0 / m_prop->spritediv.X;
1755 m_tx_size.Y = 1.0 / m_prop->spritediv.Y;
1756 m_tx_basepos.X = m_tx_size.X * m_prop->initial_sprite_basepos.X;
1757 m_tx_basepos.Y = m_tx_size.Y * m_prop->initial_sprite_basepos.Y;
1767 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
1769 return new LuaEntityCAO(gamedef, env);
1774 return ACTIVEOBJECT_TYPE_LUAENTITY;
1776 core::aabbox3d<f32>* getSelectionBox()
1778 return &m_selection_box;
1782 return pos_translator.vect_show;
1785 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
1786 IrrlichtDevice *irr)
1788 if(m_meshnode != NULL || m_spritenode != NULL)
1791 //video::IVideoDriver* driver = smgr->getVideoDriver();
1793 if(m_prop->visual == "sprite"){
1794 infostream<<"LuaEntityCAO::addToScene(): single_sprite"<<std::endl;
1795 m_spritenode = smgr->addBillboardSceneNode(
1796 NULL, v2f(1, 1), v3f(0,0,0), -1);
1797 m_spritenode->setMaterialTexture(0,
1798 tsrc->getTextureRaw("unknown_block.png"));
1799 m_spritenode->setMaterialFlag(video::EMF_LIGHTING, false);
1800 m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
1801 m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
1802 m_spritenode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
1803 m_spritenode->setColor(video::SColor(255,0,0,0));
1804 m_spritenode->setVisible(false); /* Set visible when brightness is known */
1805 m_spritenode->setSize(m_prop->visual_size*BS);
1807 const float txs = 1.0 / 1;
1808 const float tys = 1.0 / 1;
1809 setBillboardTextureMatrix(m_spritenode,
1812 } else if(m_prop->visual == "cube"){
1813 infostream<<"LuaEntityCAO::addToScene(): cube"<<std::endl;
1814 scene::IMesh *mesh = createCubeMesh(v3f(BS,BS,BS));
1815 m_meshnode = smgr->addMeshSceneNode(mesh, NULL);
1818 m_meshnode->setScale(v3f(1));
1819 // Will be shown when we know the brightness
1820 m_meshnode->setVisible(false);
1822 infostream<<"LuaEntityCAO::addToScene(): \""<<m_prop->visual
1823 <<"\" not supported"<<std::endl;
1829 void removeFromScene()
1832 m_meshnode->remove();
1836 m_spritenode->remove();
1837 m_spritenode = NULL;
1841 void updateLight(u8 light_at_pos)
1843 u8 li = decode_light(light_at_pos);
1844 video::SColor color(255,li,li,li);
1846 setMeshColor(m_meshnode->getMesh(), color);
1847 m_meshnode->setVisible(true);
1850 m_spritenode->setColor(color);
1851 m_spritenode->setVisible(true);
1855 v3s16 getLightPosition()
1857 return floatToInt(m_position, BS);
1860 void updateNodePos()
1863 m_meshnode->setPosition(pos_translator.vect_show);
1866 m_spritenode->setPosition(pos_translator.vect_show);
1870 void step(float dtime, ClientEnvironment *env)
1872 if(m_prop->physical){
1873 core::aabbox3d<f32> box = m_prop->collisionbox;
1876 collisionMoveResult moveresult;
1877 f32 pos_max_d = BS*0.25; // Distance per iteration
1878 v3f p_pos = m_position;
1879 v3f p_velocity = m_velocity;
1880 IGameDef *gamedef = env->getGameDef();
1881 moveresult = collisionMovePrecise(&env->getMap(), gamedef,
1882 pos_max_d, box, dtime, p_pos, p_velocity);
1885 m_velocity = p_velocity;
1887 bool is_end_position = moveresult.collides;
1888 pos_translator.update(m_position, is_end_position, dtime);
1889 pos_translator.translate(dtime);
1892 m_velocity += dtime * m_acceleration;
1894 m_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration;
1895 m_velocity += dtime * m_acceleration;
1896 pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time);
1897 pos_translator.translate(dtime);
1901 m_anim_timer += dtime;
1902 if(m_anim_timer >= m_anim_framelength){
1903 m_anim_timer -= m_anim_framelength;
1905 if(m_anim_frame >= m_anim_num_frames)
1912 void updateTexturePos()
1915 scene::ICameraSceneNode* camera =
1916 m_spritenode->getSceneManager()->getActiveCamera();
1919 v3f cam_to_entity = m_spritenode->getAbsolutePosition()
1920 - camera->getAbsolutePosition();
1921 cam_to_entity.normalize();
1923 int row = m_tx_basepos.Y;
1924 int col = m_tx_basepos.X;
1926 if(m_tx_select_horiz_by_yawpitch)
1928 if(cam_to_entity.Y > 0.75)
1930 else if(cam_to_entity.Y < -0.75)
1933 float mob_dir = atan2(cam_to_entity.Z, cam_to_entity.X) / PI * 180.;
1934 float dir = mob_dir - m_yaw;
1935 dir = wrapDegrees_180(dir);
1936 //infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
1937 if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
1939 else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
1941 else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
1943 else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
1950 // Animation goes downwards
1951 row += m_anim_frame;
1953 float txs = m_tx_size.X;
1954 float tys = m_tx_size.Y;
1955 setBillboardTextureMatrix(m_spritenode,
1956 txs, tys, col, row);
1960 void updateTextures(const std::string &mod)
1962 ITextureSource *tsrc = m_gamedef->tsrc();
1965 std::string texturestring = "unknown_block.png";
1966 if(m_prop->textures.size() >= 1)
1967 texturestring = m_prop->textures[0];
1968 texturestring += mod;
1969 m_spritenode->setMaterialTexture(0,
1970 tsrc->getTextureRaw(texturestring));
1973 for (u32 i = 0; i < 6; ++i)
1975 std::string texturestring = "unknown_block.png";
1976 if(m_prop->textures.size() > i)
1977 texturestring = m_prop->textures[i];
1978 texturestring += mod;
1979 AtlasPointer ap = tsrc->getTexture(texturestring);
1981 // Get the tile texture and atlas transformation
1982 video::ITexture* atlas = ap.atlas;
1986 // Set material flags and texture
1987 video::SMaterial& material = m_meshnode->getMaterial(i);
1988 material.setFlag(video::EMF_LIGHTING, false);
1989 material.setFlag(video::EMF_BILINEAR_FILTER, false);
1990 material.setTexture(0, atlas);
1991 material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
1992 material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
1997 void processMessage(const std::string &data)
1999 //infostream<<"LuaEntityCAO: Got message"<<std::endl;
2000 std::istringstream is(data, std::ios::binary);
2002 u8 cmd = readU8(is);
2003 if(cmd == 0) // update position
2006 bool do_interpolate = readU8(is);
2008 m_position = readV3F1000(is);
2010 m_velocity = readV3F1000(is);
2012 m_acceleration = readV3F1000(is);
2014 m_yaw = readF1000(is);
2015 // is_end_position (for interpolation)
2016 bool is_end_position = readU8(is);
2018 float update_interval = readF1000(is);
2021 if(!m_prop->physical)
2022 pos_translator.update(m_position, is_end_position, update_interval);
2024 pos_translator.init(m_position);
2028 else if(cmd == 1) // set texture modification
2030 std::string mod = deSerializeString(is);
2031 updateTextures(mod);
2033 else if(cmd == 2) // set sprite
2035 v2s16 p = readV2S16(is);
2036 int num_frames = readU16(is);
2037 float framelength = readF1000(is);
2038 bool select_horiz_by_yawpitch = readU8(is);
2041 m_anim_num_frames = num_frames;
2042 m_anim_framelength = framelength;
2043 m_tx_select_horiz_by_yawpitch = select_horiz_by_yawpitch;
2051 LuaEntityCAO proto_LuaEntityCAO(NULL, NULL);
2057 class PlayerCAO : public ClientActiveObject
2060 core::aabbox3d<f32> m_selection_box;
2061 scene::IMeshSceneNode *m_node;
2062 scene::ITextSceneNode* m_text;
2066 SmoothTranslator pos_translator;
2067 bool m_is_local_player;
2068 LocalPlayer *m_local_player;
2069 float m_damage_visual_timer;
2073 PlayerCAO(IGameDef *gamedef, ClientEnvironment *env):
2074 ClientActiveObject(0, gamedef, env),
2075 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.0,BS/3.),
2078 m_position(v3f(0,10*BS,0)),
2080 m_is_local_player(false),
2081 m_local_player(NULL),
2082 m_damage_visual_timer(0),
2086 ClientActiveObject::registerType(getType(), create);
2089 void initialize(const std::string &data)
2091 infostream<<"PlayerCAO: Got init data"<<std::endl;
2093 std::istringstream is(data, std::ios::binary);
2095 u8 version = readU8(is);
2100 m_name = deSerializeString(is);
2102 m_position = readV3F1000(is);
2104 m_yaw = readF1000(is);
2106 m_dead = readU8(is);
2108 pos_translator.init(m_position);
2110 Player *player = m_env->getPlayer(m_name.c_str());
2111 if(player && player->isLocal()){
2112 m_is_local_player = true;
2113 m_local_player = (LocalPlayer*)player;
2123 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
2125 return new PlayerCAO(gamedef, env);
2130 return ACTIVEOBJECT_TYPE_PLAYER;
2132 core::aabbox3d<f32>* getSelectionBox()
2134 if(m_is_local_player)
2138 return &m_selection_box;
2142 return pos_translator.vect_show;
2145 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
2146 IrrlichtDevice *irr)
2150 if(m_is_local_player)
2153 //video::IVideoDriver* driver = smgr->getVideoDriver();
2154 gui::IGUIEnvironment* gui = irr->getGUIEnvironment();
2156 scene::SMesh *mesh = new scene::SMesh();
2158 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
2159 video::SColor c(255,255,255,255);
2160 video::S3DVertex vertices[4] =
2162 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
2163 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
2164 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
2165 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
2167 u16 indices[] = {0,1,2,2,3,0};
2168 buf->append(vertices, 4, indices, 6);
2170 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
2171 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
2172 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
2173 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
2175 mesh->addMeshBuffer(buf);
2179 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
2180 video::SColor c(255,255,255,255);
2181 video::S3DVertex vertices[4] =
2183 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
2184 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
2185 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
2186 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
2188 u16 indices[] = {0,1,2,2,3,0};
2189 buf->append(vertices, 4, indices, 6);
2191 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
2192 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
2193 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
2194 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
2196 mesh->addMeshBuffer(buf);
2199 m_node = smgr->addMeshSceneNode(mesh, NULL);
2201 // Set it to use the materials of the meshbuffers directly.
2202 // This is needed for changing the texture in the future
2203 m_node->setReadOnlyMaterials(true);
2206 // Add a text node for showing the name
2207 std::wstring wname = narrow_to_wide(m_name);
2208 m_text = smgr->addTextSceneNode(gui->getBuiltInFont(),
2209 wname.c_str(), video::SColor(255,255,255,255), m_node);
2210 m_text->setPosition(v3f(0, (f32)BS*2.1, 0));
2217 void removeFromScene()
2226 void updateLight(u8 light_at_pos)
2231 u8 li = decode_light(light_at_pos);
2232 video::SColor color(255,li,li,li);
2233 setMeshColor(m_node->getMesh(), color);
2238 v3s16 getLightPosition()
2240 return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
2243 void updateVisibility()
2248 m_node->setVisible(!m_dead);
2251 void updateNodePos()
2256 m_node->setPosition(pos_translator.vect_show);
2258 v3f rot = m_node->getRotation();
2260 m_node->setRotation(rot);
2263 void step(float dtime, ClientEnvironment *env)
2265 pos_translator.translate(dtime);
2269 if(m_damage_visual_timer > 0){
2270 m_damage_visual_timer -= dtime;
2271 if(m_damage_visual_timer <= 0){
2277 void processMessage(const std::string &data)
2279 //infostream<<"PlayerCAO: Got message"<<std::endl;
2280 std::istringstream is(data, std::ios::binary);
2282 u8 cmd = readU8(is);
2283 if(cmd == 0) // update position
2286 m_position = readV3F1000(is);
2288 m_yaw = readF1000(is);
2290 pos_translator.update(m_position, false);
2294 else if(cmd == 1) // punched
2297 s16 damage = readS16(is);
2298 m_damage_visual_timer = 0.05;
2300 m_damage_visual_timer += 0.05 * damage;
2301 updateTextures("^[brighten");
2303 else if(cmd == 2) // died or respawned
2305 m_dead = readU8(is);
2310 void updateTextures(const std::string &mod)
2314 ITextureSource *tsrc = m_gamedef->tsrc();
2315 scene::IMesh *mesh = m_node->getMesh();
2318 std::string tname = "player.png";
2320 scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
2321 buf->getMaterial().setTexture(0,
2322 tsrc->getTextureRaw(tname));
2325 std::string tname = "player_back.png";
2327 scene::IMeshBuffer *buf = mesh->getMeshBuffer(1);
2328 buf->getMaterial().setTexture(0,
2329 tsrc->getTextureRaw(tname));
2336 PlayerCAO proto_PlayerCAO(NULL, NULL);