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"
24 #include <ICameraSceneNode.h>
25 #include <ITextSceneNode.h>
26 #include "serialization.h" // For decompressZlib
28 #include "clientobject.h"
29 #include "content_object.h"
30 #include "utility.h" // For IntervalLimiter
32 #include "MyBillboardSceneNode.h"
34 core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
40 struct SmoothTranslator
47 f32 anim_time_counter;
67 anim_time_counter = 0;
76 void update(v3f vect_new, bool is_end_position=false, float update_interval=-1)
78 aim_is_end = is_end_position;
81 if(update_interval > 0){
82 anim_time = update_interval;
84 if(anim_time < 0.001 || anim_time > 1.0)
85 anim_time = anim_time_counter;
87 anim_time = anim_time * 0.9 + anim_time_counter * 0.1;
89 anim_time_counter = 0;
93 void translate(f32 dtime)
95 anim_time_counter = anim_time_counter + dtime;
96 anim_counter = anim_counter + dtime;
97 v3f vect_move = vect_aim - vect_old;
100 moveratio = anim_time_counter / anim_time;
101 // Move a bit less than should, to avoid oscillation
102 moveratio = moveratio * 0.8;
103 float move_end = 1.5;
106 if(moveratio > move_end)
107 moveratio = move_end;
108 vect_show = vect_old + vect_move * moveratio;
113 return ((anim_time_counter / anim_time) < 1.4);
122 class TestCAO : public ClientActiveObject
125 TestCAO(IGameDef *gamedef, ClientEnvironment *env);
130 return ACTIVEOBJECT_TYPE_TEST;
133 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
135 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
136 IrrlichtDevice *irr);
137 void removeFromScene();
138 void updateLight(u8 light_at_pos);
139 v3s16 getLightPosition();
140 void updateNodePos();
142 void step(float dtime, ClientEnvironment *env);
144 void processMessage(const std::string &data);
147 scene::IMeshSceneNode *m_node;
155 class ItemCAO : public ClientActiveObject
158 ItemCAO(IGameDef *gamedef, ClientEnvironment *env);
163 return ACTIVEOBJECT_TYPE_ITEM;
166 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
168 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
169 IrrlichtDevice *irr);
170 void removeFromScene();
171 void updateLight(u8 light_at_pos);
172 v3s16 getLightPosition();
173 void updateNodePos();
175 void step(float dtime, ClientEnvironment *env);
177 void processMessage(const std::string &data);
179 void initialize(const std::string &data);
181 core::aabbox3d<f32>* getSelectionBox()
182 {return &m_selection_box;}
187 core::aabbox3d<f32> m_selection_box;
188 scene::IMeshSceneNode *m_node;
190 std::string m_inventorystring;
197 class RatCAO : public ClientActiveObject
200 RatCAO(IGameDef *gamedef, ClientEnvironment *env);
205 return ACTIVEOBJECT_TYPE_RAT;
208 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
210 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
211 IrrlichtDevice *irr);
212 void removeFromScene();
213 void updateLight(u8 light_at_pos);
214 v3s16 getLightPosition();
215 void updateNodePos();
217 void step(float dtime, ClientEnvironment *env);
219 void processMessage(const std::string &data);
221 void initialize(const std::string &data);
223 core::aabbox3d<f32>* getSelectionBox()
224 {return &m_selection_box;}
226 {return pos_translator.vect_show;}
227 //{return m_position;}
230 core::aabbox3d<f32> m_selection_box;
231 scene::IMeshSceneNode *m_node;
234 SmoothTranslator pos_translator;
241 class Oerkki1CAO : public ClientActiveObject
244 Oerkki1CAO(IGameDef *gamedef, ClientEnvironment *env);
245 virtual ~Oerkki1CAO();
249 return ACTIVEOBJECT_TYPE_OERKKI1;
252 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
254 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
255 IrrlichtDevice *irr);
256 void removeFromScene();
257 void updateLight(u8 light_at_pos);
258 v3s16 getLightPosition();
259 void updateNodePos();
261 void step(float dtime, ClientEnvironment *env);
263 void processMessage(const std::string &data);
265 void initialize(const std::string &data);
267 core::aabbox3d<f32>* getSelectionBox()
268 {return &m_selection_box;}
270 {return pos_translator.vect_show;}
271 //{return m_position;}
273 // If returns true, punch will not be sent to the server
274 bool directReportPunch(const std::string &toolname, v3f dir);
277 IntervalLimiter m_attack_interval;
278 core::aabbox3d<f32> m_selection_box;
279 scene::IMeshSceneNode *m_node;
282 SmoothTranslator pos_translator;
283 float m_damage_visual_timer;
284 bool m_damage_texture_enabled;
291 class FireflyCAO : public ClientActiveObject
294 FireflyCAO(IGameDef *gamedef, ClientEnvironment *env);
295 virtual ~FireflyCAO();
299 return ACTIVEOBJECT_TYPE_FIREFLY;
302 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
304 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
305 IrrlichtDevice *irr);
306 void removeFromScene();
307 void updateLight(u8 light_at_pos);
308 v3s16 getLightPosition();
309 void updateNodePos();
311 void step(float dtime, ClientEnvironment *env);
313 void processMessage(const std::string &data);
315 void initialize(const std::string &data);
317 core::aabbox3d<f32>* getSelectionBox()
318 {return &m_selection_box;}
323 core::aabbox3d<f32> m_selection_box;
324 scene::IMeshSceneNode *m_node;
327 SmoothTranslator pos_translator;
334 class MobV2CAO : public ClientActiveObject
337 MobV2CAO(IGameDef *gamedef, ClientEnvironment *env);
342 return ACTIVEOBJECT_TYPE_MOBV2;
345 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
347 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
348 IrrlichtDevice *irr);
349 void removeFromScene();
350 void updateLight(u8 light_at_pos);
351 v3s16 getLightPosition();
352 void updateNodePos();
354 void step(float dtime, ClientEnvironment *env);
356 void processMessage(const std::string &data);
358 void initialize(const std::string &data);
360 core::aabbox3d<f32>* getSelectionBox()
361 {return &m_selection_box;}
363 {return pos_translator.vect_show;}
364 //{return m_position;}
365 bool doShowSelectionBox(){return false;}
367 // If returns true, punch will not be sent to the server
368 bool directReportPunch(const std::string &toolname, v3f dir);
371 void setLooks(const std::string &looks);
373 IntervalLimiter m_attack_interval;
374 core::aabbox3d<f32> m_selection_box;
375 scene::MyBillboardSceneNode *m_node;
377 std::string m_texture_name;
379 SmoothTranslator pos_translator;
381 float m_walking_unset_timer;
384 float m_damage_visual_timer;
387 float m_shooting_unset_timer;
390 bool m_bright_shooting;
391 std::string m_sprite_type;
392 int m_simple_anim_frames;
393 float m_simple_anim_frametime;
394 bool m_lock_full_brightness;
395 int m_player_hit_damage;
396 float m_player_hit_distance;
397 float m_player_hit_interval;
398 float m_player_hit_timer;
400 Settings *m_properties;
408 TestCAO proto_TestCAO(NULL, NULL);
410 TestCAO::TestCAO(IGameDef *gamedef, ClientEnvironment *env):
411 ClientActiveObject(0, gamedef, env),
413 m_position(v3f(0,10*BS,0))
415 ClientActiveObject::registerType(getType(), create);
422 ClientActiveObject* TestCAO::create(IGameDef *gamedef, ClientEnvironment *env)
424 return new TestCAO(gamedef, env);
427 void TestCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
433 //video::IVideoDriver* driver = smgr->getVideoDriver();
435 scene::SMesh *mesh = new scene::SMesh();
436 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
437 video::SColor c(255,255,255,255);
438 video::S3DVertex vertices[4] =
440 video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
441 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
442 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
443 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),
445 u16 indices[] = {0,1,2,2,3,0};
446 buf->append(vertices, 4, indices, 6);
448 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
449 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
450 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("rat.png"));
451 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
452 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
453 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
455 mesh->addMeshBuffer(buf);
457 m_node = smgr->addMeshSceneNode(mesh, NULL);
462 void TestCAO::removeFromScene()
471 void TestCAO::updateLight(u8 light_at_pos)
475 v3s16 TestCAO::getLightPosition()
477 return floatToInt(m_position, BS);
480 void TestCAO::updateNodePos()
485 m_node->setPosition(m_position);
486 //m_node->setRotation(v3f(0, 45, 0));
489 void TestCAO::step(float dtime, ClientEnvironment *env)
493 v3f rot = m_node->getRotation();
494 //infostream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
495 rot.Y += dtime * 180;
496 m_node->setRotation(rot);
500 void TestCAO::processMessage(const std::string &data)
502 infostream<<"TestCAO: Got data: "<<data<<std::endl;
503 std::istringstream is(data, std::ios::binary);
521 #include "inventory.h"
524 ItemCAO proto_ItemCAO(NULL, NULL);
526 ItemCAO::ItemCAO(IGameDef *gamedef, ClientEnvironment *env):
527 ClientActiveObject(0, gamedef, env),
528 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.),
530 m_position(v3f(0,10*BS,0))
532 ClientActiveObject::registerType(getType(), create);
539 ClientActiveObject* ItemCAO::create(IGameDef *gamedef, ClientEnvironment *env)
541 return new ItemCAO(gamedef, env);
544 void ItemCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
550 //video::IVideoDriver* driver = smgr->getVideoDriver();
552 scene::SMesh *mesh = new scene::SMesh();
553 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
554 video::SColor c(255,255,255,255);
555 video::S3DVertex vertices[4] =
557 /*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
558 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
559 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
560 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/
561 video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1),
562 video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1),
563 video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0),
564 video::S3DVertex(BS/3.,0+BS*2./3.,0, 0,0,0, c, 0,0),
566 u16 indices[] = {0,1,2,2,3,0};
567 buf->append(vertices, 4, indices, 6);
569 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
570 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
571 //buf->getMaterial().setTexture(0, NULL);
572 // Initialize with the stick texture
573 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("stick.png"));
574 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
575 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
576 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
578 mesh->addMeshBuffer(buf);
580 m_node = smgr->addMeshSceneNode(mesh, NULL);
582 // Set it to use the materials of the meshbuffers directly.
583 // This is needed for changing the texture in the future
584 m_node->setReadOnlyMaterials(true);
591 // Create an inventory item to see what is its image
592 std::istringstream is(m_inventorystring, std::ios_base::binary);
593 video::ITexture *texture = NULL;
595 InventoryItem *item = NULL;
596 item = InventoryItem::deSerialize(is, m_gamedef);
597 infostream<<__FUNCTION_NAME<<": m_inventorystring=\""
598 <<m_inventorystring<<"\" -> item="<<item
602 texture = item->getImage();
606 catch(SerializationError &e)
608 infostream<<"WARNING: "<<__FUNCTION_NAME
609 <<": error deSerializing inventorystring \""
610 <<m_inventorystring<<"\""<<std::endl;
613 // Set meshbuffer texture
614 buf->getMaterial().setTexture(0, texture);
617 void ItemCAO::removeFromScene()
626 void ItemCAO::updateLight(u8 light_at_pos)
631 u8 li = decode_light(light_at_pos);
632 video::SColor color(255,li,li,li);
633 setMeshVerticesColor(m_node->getMesh(), color);
636 v3s16 ItemCAO::getLightPosition()
638 return floatToInt(m_position, BS);
641 void ItemCAO::updateNodePos()
646 m_node->setPosition(m_position);
649 void ItemCAO::step(float dtime, ClientEnvironment *env)
653 /*v3f rot = m_node->getRotation();
654 rot.Y += dtime * 120;
655 m_node->setRotation(rot);*/
656 LocalPlayer *player = env->getLocalPlayer();
658 v3f rot = m_node->getRotation();
659 rot.Y = 180.0 - (player->getYaw());
660 m_node->setRotation(rot);
664 void ItemCAO::processMessage(const std::string &data)
666 //infostream<<"ItemCAO: Got message"<<std::endl;
667 std::istringstream is(data, std::ios::binary);
673 m_position = readV3F1000(is);
678 void ItemCAO::initialize(const std::string &data)
680 infostream<<"ItemCAO: Got init data"<<std::endl;
683 std::istringstream is(data, std::ios::binary);
685 u8 version = readU8(is);
690 m_position = readV3F1000(is);
692 m_inventorystring = deSerializeString(is);
702 #include "inventory.h"
705 RatCAO proto_RatCAO(NULL, NULL);
707 RatCAO::RatCAO(IGameDef *gamedef, ClientEnvironment *env):
708 ClientActiveObject(0, gamedef, env),
709 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
711 m_position(v3f(0,10*BS,0)),
714 ClientActiveObject::registerType(getType(), create);
721 ClientActiveObject* RatCAO::create(IGameDef *gamedef, ClientEnvironment *env)
723 return new RatCAO(gamedef, env);
726 void RatCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
732 //video::IVideoDriver* driver = smgr->getVideoDriver();
734 scene::SMesh *mesh = new scene::SMesh();
735 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
736 video::SColor c(255,255,255,255);
737 video::S3DVertex vertices[4] =
739 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
740 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
741 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
742 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
744 u16 indices[] = {0,1,2,2,3,0};
745 buf->append(vertices, 4, indices, 6);
747 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
748 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
749 //buf->getMaterial().setTexture(0, NULL);
750 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("rat.png"));
751 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
752 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
753 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
755 mesh->addMeshBuffer(buf);
757 m_node = smgr->addMeshSceneNode(mesh, NULL);
759 // Set it to use the materials of the meshbuffers directly.
760 // This is needed for changing the texture in the future
761 m_node->setReadOnlyMaterials(true);
765 void RatCAO::removeFromScene()
774 void RatCAO::updateLight(u8 light_at_pos)
779 u8 li = decode_light(light_at_pos);
780 video::SColor color(255,li,li,li);
781 setMeshVerticesColor(m_node->getMesh(), color);
784 v3s16 RatCAO::getLightPosition()
786 return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
789 void RatCAO::updateNodePos()
794 //m_node->setPosition(m_position);
795 m_node->setPosition(pos_translator.vect_show);
797 v3f rot = m_node->getRotation();
798 rot.Y = 180.0 - m_yaw;
799 m_node->setRotation(rot);
802 void RatCAO::step(float dtime, ClientEnvironment *env)
804 pos_translator.translate(dtime);
808 void RatCAO::processMessage(const std::string &data)
810 //infostream<<"RatCAO: Got message"<<std::endl;
811 std::istringstream is(data, std::ios::binary);
817 m_position = readV3F1000(is);
818 pos_translator.update(m_position);
820 m_yaw = readF1000(is);
825 void RatCAO::initialize(const std::string &data)
827 //infostream<<"RatCAO: Got init data"<<std::endl;
830 std::istringstream is(data, std::ios::binary);
832 u8 version = readU8(is);
837 m_position = readV3F1000(is);
838 pos_translator.init(m_position);
848 #include "inventory.h"
851 Oerkki1CAO proto_Oerkki1CAO(NULL, NULL);
853 Oerkki1CAO::Oerkki1CAO(IGameDef *gamedef, ClientEnvironment *env):
854 ClientActiveObject(0, gamedef, env),
855 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.),
857 m_position(v3f(0,10*BS,0)),
859 m_damage_visual_timer(0),
860 m_damage_texture_enabled(false)
862 ClientActiveObject::registerType(getType(), create);
865 Oerkki1CAO::~Oerkki1CAO()
869 ClientActiveObject* Oerkki1CAO::create(IGameDef *gamedef, ClientEnvironment *env)
871 return new Oerkki1CAO(gamedef, env);
874 void Oerkki1CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
880 //video::IVideoDriver* driver = smgr->getVideoDriver();
882 scene::SMesh *mesh = new scene::SMesh();
883 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
884 video::SColor c(255,255,255,255);
885 video::S3DVertex vertices[4] =
887 video::S3DVertex(-BS/2-BS,0,0, 0,0,0, c, 0,1),
888 video::S3DVertex(BS/2+BS,0,0, 0,0,0, c, 1,1),
889 video::S3DVertex(BS/2+BS,BS*2,0, 0,0,0, c, 1,0),
890 video::S3DVertex(-BS/2-BS,BS*2,0, 0,0,0, c, 0,0),
892 u16 indices[] = {0,1,2,2,3,0};
893 buf->append(vertices, 4, indices, 6);
895 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
896 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
897 //buf->getMaterial().setTexture(0, NULL);
898 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("oerkki1.png"));
899 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
900 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
901 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
903 mesh->addMeshBuffer(buf);
905 m_node = smgr->addMeshSceneNode(mesh, NULL);
907 // Set it to use the materials of the meshbuffers directly.
908 // This is needed for changing the texture in the future
909 m_node->setReadOnlyMaterials(true);
913 void Oerkki1CAO::removeFromScene()
922 void Oerkki1CAO::updateLight(u8 light_at_pos)
927 if(light_at_pos <= 2)
929 m_node->setVisible(false);
933 m_node->setVisible(true);
935 u8 li = decode_light(light_at_pos);
936 video::SColor color(255,li,li,li);
937 setMeshVerticesColor(m_node->getMesh(), color);
940 v3s16 Oerkki1CAO::getLightPosition()
942 return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
945 void Oerkki1CAO::updateNodePos()
950 //m_node->setPosition(m_position);
951 m_node->setPosition(pos_translator.vect_show);
953 v3f rot = m_node->getRotation();
954 rot.Y = 180.0 - m_yaw + 90.0;
955 m_node->setRotation(rot);
958 void Oerkki1CAO::step(float dtime, ClientEnvironment *env)
960 ITextureSource *tsrc = m_gamedef->tsrc();
962 pos_translator.translate(dtime);
965 LocalPlayer *player = env->getLocalPlayer();
968 v3f playerpos = player->getPosition();
969 v2f playerpos_2d(playerpos.X,playerpos.Z);
970 v2f objectpos_2d(m_position.X,m_position.Z);
972 if(fabs(m_position.Y - playerpos.Y) < 1.5*BS &&
973 objectpos_2d.getDistanceFrom(playerpos_2d) < 1.5*BS)
975 if(m_attack_interval.step(dtime, 0.5))
977 env->damageLocalPlayer(2);
981 if(m_damage_visual_timer > 0)
983 if(!m_damage_texture_enabled)
985 // Enable damage texture
988 /*video::IVideoDriver* driver =
989 m_node->getSceneManager()->getVideoDriver();*/
991 scene::IMesh *mesh = m_node->getMesh();
995 u16 mc = mesh->getMeshBufferCount();
996 for(u16 j=0; j<mc; j++)
998 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
999 buf->getMaterial().setTexture(0,
1000 tsrc->getTextureRaw("oerkki1_damaged.png"));
1003 m_damage_texture_enabled = true;
1005 m_damage_visual_timer -= dtime;
1009 if(m_damage_texture_enabled)
1011 // Disable damage texture
1014 /*video::IVideoDriver* driver =
1015 m_node->getSceneManager()->getVideoDriver();*/
1017 scene::IMesh *mesh = m_node->getMesh();
1021 u16 mc = mesh->getMeshBufferCount();
1022 for(u16 j=0; j<mc; j++)
1024 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
1025 buf->getMaterial().setTexture(0,
1026 tsrc->getTextureRaw("oerkki1.png"));
1029 m_damage_texture_enabled = false;
1034 void Oerkki1CAO::processMessage(const std::string &data)
1036 //infostream<<"Oerkki1CAO: Got message"<<std::endl;
1037 std::istringstream is(data, std::ios::binary);
1039 u8 cmd = readU8(is);
1043 m_position = readV3F1000(is);
1044 pos_translator.update(m_position);
1046 m_yaw = readF1000(is);
1051 //u16 damage = readU8(is);
1052 m_damage_visual_timer = 1.0;
1056 void Oerkki1CAO::initialize(const std::string &data)
1058 //infostream<<"Oerkki1CAO: Got init data"<<std::endl;
1061 std::istringstream is(data, std::ios::binary);
1063 u8 version = readU8(is);
1068 m_position = readV3F1000(is);
1069 pos_translator.init(m_position);
1075 bool Oerkki1CAO::directReportPunch(const std::string &toolname, v3f dir)
1077 m_damage_visual_timer = 1.0;
1079 m_position += dir * BS;
1080 pos_translator.sharpen();
1081 pos_translator.update(m_position);
1092 FireflyCAO proto_FireflyCAO(NULL, NULL);
1094 FireflyCAO::FireflyCAO(IGameDef *gamedef, ClientEnvironment *env):
1095 ClientActiveObject(0, gamedef, env),
1096 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
1098 m_position(v3f(0,10*BS,0)),
1101 ClientActiveObject::registerType(getType(), create);
1104 FireflyCAO::~FireflyCAO()
1108 ClientActiveObject* FireflyCAO::create(IGameDef *gamedef, ClientEnvironment *env)
1110 return new FireflyCAO(gamedef, env);
1113 void FireflyCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
1114 IrrlichtDevice *irr)
1119 //video::IVideoDriver* driver = smgr->getVideoDriver();
1121 scene::SMesh *mesh = new scene::SMesh();
1122 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
1123 video::SColor c(255,255,255,255);
1124 video::S3DVertex vertices[4] =
1126 video::S3DVertex(0,0,0, 0,0,0, c, 0,1),
1127 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
1128 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
1129 video::S3DVertex(0,BS/2,0, 0,0,0, c, 0,0),
1131 u16 indices[] = {0,1,2,2,3,0};
1132 buf->append(vertices, 4, indices, 6);
1134 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
1135 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
1136 //buf->getMaterial().setTexture(0, NULL);
1137 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("firefly.png"));
1138 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
1139 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
1140 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
1142 mesh->addMeshBuffer(buf);
1144 m_node = smgr->addMeshSceneNode(mesh, NULL);
1146 // Set it to use the materials of the meshbuffers directly.
1147 // This is needed for changing the texture in the future
1148 m_node->setReadOnlyMaterials(true);
1152 void FireflyCAO::removeFromScene()
1161 void FireflyCAO::updateLight(u8 light_at_pos)
1167 video::SColor color(255,li,li,li);
1168 setMeshVerticesColor(m_node->getMesh(), color);
1171 v3s16 FireflyCAO::getLightPosition()
1173 return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
1176 void FireflyCAO::updateNodePos()
1181 //m_node->setPosition(m_position);
1182 m_node->setPosition(pos_translator.vect_show);
1184 v3f rot = m_node->getRotation();
1185 rot.Y = 180.0 - m_yaw;
1186 m_node->setRotation(rot);
1189 void FireflyCAO::step(float dtime, ClientEnvironment *env)
1191 pos_translator.translate(dtime);
1195 void FireflyCAO::processMessage(const std::string &data)
1197 //infostream<<"FireflyCAO: Got message"<<std::endl;
1198 std::istringstream is(data, std::ios::binary);
1200 u8 cmd = readU8(is);
1204 m_position = readV3F1000(is);
1205 pos_translator.update(m_position);
1207 m_yaw = readF1000(is);
1212 void FireflyCAO::initialize(const std::string &data)
1214 //infostream<<"FireflyCAO: Got init data"<<std::endl;
1217 std::istringstream is(data, std::ios::binary);
1219 u8 version = readU8(is);
1224 m_position = readV3F1000(is);
1225 pos_translator.init(m_position);
1236 MobV2CAO proto_MobV2CAO(NULL, NULL);
1238 MobV2CAO::MobV2CAO(IGameDef *gamedef, ClientEnvironment *env):
1239 ClientActiveObject(0, gamedef, env),
1240 m_selection_box(-0.4*BS,-0.4*BS,-0.4*BS, 0.4*BS,0.8*BS,0.4*BS),
1242 m_position(v3f(0,10*BS,0)),
1245 m_walking_unset_timer(0),
1248 m_damage_visual_timer(0),
1251 m_shooting_unset_timer(0),
1252 m_sprite_size(BS,BS),
1254 m_bright_shooting(false),
1255 m_lock_full_brightness(false),
1256 m_player_hit_timer(0)
1258 ClientActiveObject::registerType(getType(), create);
1260 m_properties = new Settings;
1263 MobV2CAO::~MobV2CAO()
1265 delete m_properties;
1268 ClientActiveObject* MobV2CAO::create(IGameDef *gamedef, ClientEnvironment *env)
1270 return new MobV2CAO(gamedef, env);
1273 void MobV2CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
1274 IrrlichtDevice *irr)
1279 /*infostream<<"MobV2CAO::addToScene using texture_name="<<
1280 m_texture_name<<std::endl;*/
1281 std::string texture_string = m_texture_name +
1282 "^[makealpha:128,0,0^[makealpha:128,128,0";
1284 scene::MyBillboardSceneNode *bill = new scene::MyBillboardSceneNode(
1285 smgr->getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1));
1286 bill->setMaterialTexture(0, tsrc->getTextureRaw(texture_string));
1287 bill->setMaterialFlag(video::EMF_LIGHTING, false);
1288 bill->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
1289 bill->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
1290 bill->setMaterialFlag(video::EMF_FOG_ENABLE, true);
1291 bill->setColor(video::SColor(255,0,0,0));
1292 bill->setVisible(false); /* Set visible when brightness is known */
1293 bill->setSize(m_sprite_size);
1294 if(m_sprite_type == "humanoid_1"){
1295 const float txp = 1./192;
1296 const float txs = txp*32;
1297 const float typ = 1./240;
1298 const float tys = typ*48;
1299 bill->setTCoords(0, v2f(txs*1, tys*1));
1300 bill->setTCoords(1, v2f(txs*1, tys*0));
1301 bill->setTCoords(2, v2f(txs*0, tys*0));
1302 bill->setTCoords(3, v2f(txs*0, tys*1));
1303 } else if(m_sprite_type == "simple"){
1304 const float txs = 1.0;
1305 const float tys = 1.0 / m_simple_anim_frames;
1306 bill->setTCoords(0, v2f(txs*1, tys*1));
1307 bill->setTCoords(1, v2f(txs*1, tys*0));
1308 bill->setTCoords(2, v2f(txs*0, tys*0));
1309 bill->setTCoords(3, v2f(txs*0, tys*1));
1311 infostream<<"MobV2CAO: Unknown sprite type \""<<m_sprite_type<<"\""
1320 void MobV2CAO::removeFromScene()
1330 void MobV2CAO::updateLight(u8 light_at_pos)
1332 if(m_lock_full_brightness)
1335 m_last_light = light_at_pos;
1340 if(m_damage_visual_timer > 0)
1343 if(m_shooting && m_bright_shooting)
1346 /*if(light_at_pos <= 2){
1347 m_node->setVisible(false);
1351 m_node->setVisible(true);
1353 u8 li = decode_light(light_at_pos);
1354 video::SColor color(255,li,li,li);
1355 m_node->setColor(color);
1358 v3s16 MobV2CAO::getLightPosition()
1360 return floatToInt(m_position+v3f(0,0,0), BS);
1363 void MobV2CAO::updateNodePos()
1368 m_node->setPosition(pos_translator.vect_show + v3f(0,m_sprite_y,0));
1371 void MobV2CAO::step(float dtime, ClientEnvironment *env)
1373 scene::MyBillboardSceneNode *bill = m_node;
1377 pos_translator.translate(dtime);
1379 if(m_sprite_type == "humanoid_1"){
1380 scene::ICameraSceneNode* camera = m_node->getSceneManager()->getActiveCamera();
1383 v3f cam_to_mob = m_node->getAbsolutePosition() - camera->getAbsolutePosition();
1384 cam_to_mob.normalize();
1386 if(cam_to_mob.Y > 0.75)
1388 else if(cam_to_mob.Y < -0.75)
1391 float mob_dir = atan2(cam_to_mob.Z, cam_to_mob.X) / PI * 180.;
1392 float dir = mob_dir - m_yaw;
1393 dir = wrapDegrees_180(dir);
1394 //infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
1395 if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
1397 else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
1399 else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
1401 else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
1410 } else if(m_walking){
1411 m_walk_timer += dtime;
1412 if(m_walk_timer >= 0.5){
1413 m_walk_frame = (m_walk_frame + 1) % 2;
1416 if(m_walk_frame == 0)
1422 const float txp = 1./192;
1423 const float txs = txp*32;
1424 const float typ = 1./240;
1425 const float tys = typ*48;
1426 bill->setTCoords(0, v2f(txs*(1+col), tys*(1+row)));
1427 bill->setTCoords(1, v2f(txs*(1+col), tys*(0+row)));
1428 bill->setTCoords(2, v2f(txs*(0+col), tys*(0+row)));
1429 bill->setTCoords(3, v2f(txs*(0+col), tys*(1+row)));
1430 } else if(m_sprite_type == "simple"){
1431 m_walk_timer += dtime;
1432 if(m_walk_timer >= m_simple_anim_frametime){
1433 m_walk_frame = (m_walk_frame + 1) % m_simple_anim_frames;
1437 int row = m_walk_frame;
1438 const float txs = 1.0;
1439 const float tys = 1.0 / m_simple_anim_frames;
1440 bill->setTCoords(0, v2f(txs*(1+col), tys*(1+row)));
1441 bill->setTCoords(1, v2f(txs*(1+col), tys*(0+row)));
1442 bill->setTCoords(2, v2f(txs*(0+col), tys*(0+row)));
1443 bill->setTCoords(3, v2f(txs*(0+col), tys*(1+row)));
1445 infostream<<"MobV2CAO::step(): Unknown sprite type \""
1446 <<m_sprite_type<<"\""<<std::endl;
1451 /* Damage local player */
1452 if(m_player_hit_damage && m_player_hit_timer <= 0.0){
1453 LocalPlayer *player = env->getLocalPlayer();
1456 v3f playerpos = player->getPosition();
1457 v2f playerpos_2d(playerpos.X,playerpos.Z);
1458 v2f objectpos_2d(m_position.X,m_position.Z);
1460 if(fabs(m_position.Y - playerpos.Y) < m_player_hit_distance*BS &&
1461 objectpos_2d.getDistanceFrom(playerpos_2d) < m_player_hit_distance*BS)
1463 env->damageLocalPlayer(m_player_hit_damage);
1464 m_player_hit_timer = m_player_hit_interval;
1470 m_player_hit_timer -= dtime;
1472 if(m_damage_visual_timer >= 0){
1473 m_damage_visual_timer -= dtime;
1474 if(m_damage_visual_timer <= 0){
1475 infostream<<"id="<<m_id<<" damage visual ended"<<std::endl;
1479 m_walking_unset_timer += dtime;
1480 if(m_walking_unset_timer >= 1.0){
1484 m_shooting_unset_timer -= dtime;
1485 if(m_shooting_unset_timer <= 0.0){
1486 if(m_bright_shooting){
1487 u8 li = decode_light(m_last_light);
1488 video::SColor color(255,li,li,li);
1489 bill->setColor(color);
1490 m_bright_shooting = false;
1497 void MobV2CAO::processMessage(const std::string &data)
1499 //infostream<<"MobV2CAO: Got message"<<std::endl;
1500 std::istringstream is(data, std::ios::binary);
1502 u8 cmd = readU8(is);
1508 m_position = readV3F1000(is);
1509 pos_translator.update(m_position);
1511 m_yaw = readF1000(is);
1514 m_walking_unset_timer = 0;
1521 //u16 damage = readU16(is);
1523 /*u8 li = decode_light(m_last_light);
1529 /*video::SColor color(255,255,0,0);
1530 m_node->setColor(color);
1532 m_damage_visual_timer = 0.2;*/
1538 m_shooting_unset_timer = readF1000(is);
1540 m_bright_shooting = readU8(is);
1541 if(m_bright_shooting){
1543 video::SColor color(255,li,li,li);
1544 m_node->setColor(color);
1551 void MobV2CAO::initialize(const std::string &data)
1553 //infostream<<"MobV2CAO: Got init data"<<std::endl;
1556 std::istringstream is(data, std::ios::binary);
1558 u8 version = readU8(is);
1561 infostream<<__FUNCTION_NAME<<": Invalid version"<<std::endl;
1565 std::ostringstream tmp_os(std::ios::binary);
1566 decompressZlib(is, tmp_os);
1567 std::istringstream tmp_is(tmp_os.str(), std::ios::binary);
1568 m_properties->parseConfigLines(tmp_is, "MobArgsEnd");
1570 infostream<<"MobV2CAO::initialize(): got properties:"<<std::endl;
1571 m_properties->writeLines(infostream);
1573 m_properties->setDefault("looks", "dummy_default");
1574 m_properties->setDefault("yaw", "0");
1575 m_properties->setDefault("pos", "(0,0,0)");
1576 m_properties->setDefault("player_hit_damage", "0");
1577 m_properties->setDefault("player_hit_distance", "1.5");
1578 m_properties->setDefault("player_hit_interval", "1.5");
1580 setLooks(m_properties->get("looks"));
1581 m_yaw = m_properties->getFloat("yaw");
1582 m_position = m_properties->getV3F("pos");
1583 m_player_hit_damage = m_properties->getS32("player_hit_damage");
1584 m_player_hit_distance = m_properties->getFloat("player_hit_distance");
1585 m_player_hit_interval = m_properties->getFloat("player_hit_interval");
1587 pos_translator.init(m_position);
1593 bool MobV2CAO::directReportPunch(const std::string &toolname, v3f dir)
1595 video::SColor color(255,255,0,0);
1596 m_node->setColor(color);
1598 m_damage_visual_timer = 0.05;
1600 m_position += dir * BS;
1601 pos_translator.sharpen();
1602 pos_translator.update(m_position);
1608 void MobV2CAO::setLooks(const std::string &looks)
1610 v2f selection_size = v2f(0.4, 0.4) * BS;
1611 float selection_y = 0 * BS;
1613 if(looks == "dungeon_master"){
1614 m_texture_name = "dungeon_master.png";
1615 m_sprite_type = "humanoid_1";
1616 m_sprite_size = v2f(2, 3) * BS;
1617 m_sprite_y = 0.85 * BS;
1618 selection_size = v2f(0.4, 2.6) * BS;
1619 selection_y = -0.4 * BS;
1621 else if(looks == "fireball"){
1622 m_texture_name = "fireball.png";
1623 m_sprite_type = "simple";
1624 m_sprite_size = v2f(1, 1) * BS;
1625 m_simple_anim_frames = 3;
1626 m_simple_anim_frametime = 0.1;
1627 m_lock_full_brightness = true;
1630 m_texture_name = "stone.png";
1631 m_sprite_type = "simple";
1632 m_sprite_size = v2f(1, 1) * BS;
1633 m_simple_anim_frames = 3;
1634 m_simple_anim_frametime = 0.333;
1635 selection_size = v2f(0.4, 0.4) * BS;
1636 selection_y = 0 * BS;
1639 m_selection_box = core::aabbox3d<f32>(
1640 -selection_size.X, selection_y, -selection_size.X,
1641 selection_size.X, selection_y+selection_size.Y,
1649 #include "luaentity_common.h"
1651 class LuaEntityCAO : public ClientActiveObject
1654 core::aabbox3d<f32> m_selection_box;
1655 scene::IMeshSceneNode *m_meshnode;
1656 scene::MyBillboardSceneNode *m_spritenode;
1661 struct LuaEntityProperties *m_prop;
1662 SmoothTranslator pos_translator;
1663 // Spritesheet/animation stuff
1666 bool m_tx_select_horiz_by_yawpitch;
1668 int m_anim_num_frames;
1669 float m_anim_framelength;
1673 LuaEntityCAO(IGameDef *gamedef, ClientEnvironment *env):
1674 ClientActiveObject(0, gamedef, env),
1675 m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.),
1678 m_position(v3f(0,10*BS,0)),
1679 m_velocity(v3f(0,0,0)),
1680 m_acceleration(v3f(0,0,0)),
1682 m_prop(new LuaEntityProperties),
1685 m_tx_select_horiz_by_yawpitch(false),
1687 m_anim_num_frames(1),
1688 m_anim_framelength(0.2),
1692 ClientActiveObject::registerType(getType(), create);
1695 void initialize(const std::string &data)
1697 infostream<<"LuaEntityCAO: Got init data"<<std::endl;
1699 std::istringstream is(data, std::ios::binary);
1701 u8 version = readU8(is);
1706 m_position = readV3F1000(is);
1708 m_yaw = readF1000(is);
1710 std::istringstream prop_is(deSerializeLongString(is), std::ios::binary);
1711 m_prop->deSerialize(prop_is);
1713 infostream<<"m_prop: "<<m_prop->dump()<<std::endl;
1715 m_selection_box = m_prop->collisionbox;
1716 m_selection_box.MinEdge *= BS;
1717 m_selection_box.MaxEdge *= BS;
1719 pos_translator.init(m_position);
1721 m_tx_size.X = 1.0 / m_prop->spritediv.X;
1722 m_tx_size.Y = 1.0 / m_prop->spritediv.Y;
1723 m_tx_basepos.X = m_tx_size.X * m_prop->initial_sprite_basepos.X;
1724 m_tx_basepos.Y = m_tx_size.Y * m_prop->initial_sprite_basepos.Y;
1734 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
1736 return new LuaEntityCAO(gamedef, env);
1741 return ACTIVEOBJECT_TYPE_LUAENTITY;
1743 core::aabbox3d<f32>* getSelectionBox()
1745 return &m_selection_box;
1749 return pos_translator.vect_show;
1752 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
1753 IrrlichtDevice *irr)
1755 if(m_meshnode != NULL || m_spritenode != NULL)
1758 //video::IVideoDriver* driver = smgr->getVideoDriver();
1760 if(m_prop->visual == "sprite"){
1761 infostream<<"LuaEntityCAO::addToScene(): single_sprite"<<std::endl;
1762 m_spritenode = new scene::MyBillboardSceneNode(
1763 smgr->getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1));
1764 m_spritenode->setMaterialTexture(0,
1765 tsrc->getTextureRaw("unknown_block.png"));
1766 m_spritenode->setMaterialFlag(video::EMF_LIGHTING, false);
1767 m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
1768 m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
1769 m_spritenode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
1770 m_spritenode->setColor(video::SColor(255,0,0,0));
1771 m_spritenode->setVisible(false); /* Set visible when brightness is known */
1772 m_spritenode->setSize(m_prop->visual_size*BS);
1774 const float txs = 1.0 / 1;
1775 const float tys = 1.0 / 1;
1776 m_spritenode->setTCoords(0, v2f(txs*1, tys*1));
1777 m_spritenode->setTCoords(1, v2f(txs*1, tys*0));
1778 m_spritenode->setTCoords(2, v2f(txs*0, tys*0));
1779 m_spritenode->setTCoords(3, v2f(txs*0, tys*1));
1781 } else if(m_prop->visual == "cube"){
1782 infostream<<"LuaEntityCAO::addToScene(): cube"<<std::endl;
1783 video::SColor c(255,255,255,255);
1784 video::S3DVertex vertices[24] =
1787 video::S3DVertex(-0.5,+0.5,-0.5, 0,1,0, c, 0,1),
1788 video::S3DVertex(-0.5,+0.5,+0.5, 0,1,0, c, 0,0),
1789 video::S3DVertex(+0.5,+0.5,+0.5, 0,1,0, c, 1,0),
1790 video::S3DVertex(+0.5,+0.5,-0.5, 0,1,0, c, 1,1),
1792 video::S3DVertex(-0.5,-0.5,-0.5, 0,-1,0, c, 0,0),
1793 video::S3DVertex(+0.5,-0.5,-0.5, 0,-1,0, c, 1,0),
1794 video::S3DVertex(+0.5,-0.5,+0.5, 0,-1,0, c, 1,1),
1795 video::S3DVertex(-0.5,-0.5,+0.5, 0,-1,0, c, 0,1),
1797 video::S3DVertex(+0.5,-0.5,-0.5, 1,0,0, c, 0,1),
1798 video::S3DVertex(+0.5,+0.5,-0.5, 1,0,0, c, 0,0),
1799 video::S3DVertex(+0.5,+0.5,+0.5, 1,0,0, c, 1,0),
1800 video::S3DVertex(+0.5,-0.5,+0.5, 1,0,0, c, 1,1),
1802 video::S3DVertex(-0.5,-0.5,-0.5, -1,0,0, c, 1,1),
1803 video::S3DVertex(-0.5,-0.5,+0.5, -1,0,0, c, 0,1),
1804 video::S3DVertex(-0.5,+0.5,+0.5, -1,0,0, c, 0,0),
1805 video::S3DVertex(-0.5,+0.5,-0.5, -1,0,0, c, 1,0),
1807 video::S3DVertex(-0.5,-0.5,+0.5, 0,0,1, c, 1,1),
1808 video::S3DVertex(+0.5,-0.5,+0.5, 0,0,1, c, 0,1),
1809 video::S3DVertex(+0.5,+0.5,+0.5, 0,0,1, c, 0,0),
1810 video::S3DVertex(-0.5,+0.5,+0.5, 0,0,1, c, 1,0),
1812 video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1),
1813 video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0),
1814 video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0),
1815 video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1),
1818 for(u32 i=0; i<24; ++i){
1819 vertices[i].Pos *= BS;
1820 vertices[i].Pos.Y *= m_prop->visual_size.Y;
1821 vertices[i].Pos.X *= m_prop->visual_size.X;
1822 vertices[i].Pos.Z *= m_prop->visual_size.X;
1825 u16 indices[6] = {0,1,2,2,3,0};
1827 scene::SMesh* mesh = new scene::SMesh();
1828 for (u32 i=0; i<6; ++i)
1830 scene::IMeshBuffer* buf = new scene::SMeshBuffer();
1831 buf->append(vertices + 4 * i, 4, indices, 6);
1832 buf->recalculateBoundingBox();
1833 mesh->addMeshBuffer(buf);
1836 mesh->recalculateBoundingBox();
1838 m_meshnode = smgr->addMeshSceneNode(mesh, NULL);
1840 m_meshnode->setMesh(mesh);
1841 m_meshnode->setScale(v3f(1));
1842 // Will be shown when we know the brightness
1843 m_meshnode->setVisible(false);
1845 infostream<<"LuaEntityCAO::addToScene(): \""<<m_prop->visual
1846 <<"\" not supported"<<std::endl;
1852 void removeFromScene()
1855 m_meshnode->remove();
1859 m_spritenode->remove();
1860 m_spritenode = NULL;
1864 void updateLight(u8 light_at_pos)
1866 u8 li = decode_light(light_at_pos);
1867 video::SColor color(255,li,li,li);
1869 setMeshVerticesColor(m_meshnode->getMesh(), color);
1870 m_meshnode->setVisible(true);
1873 m_spritenode->setColor(color);
1874 m_spritenode->setVisible(true);
1878 v3s16 getLightPosition()
1880 return floatToInt(m_position, BS);
1883 void updateNodePos()
1886 m_meshnode->setPosition(pos_translator.vect_show);
1889 m_spritenode->setPosition(pos_translator.vect_show);
1893 void step(float dtime, ClientEnvironment *env)
1895 if(m_prop->physical){
1896 core::aabbox3d<f32> box = m_prop->collisionbox;
1899 collisionMoveResult moveresult;
1900 f32 pos_max_d = BS*0.25; // Distance per iteration
1901 v3f p_pos = m_position;
1902 v3f p_velocity = m_velocity;
1903 IGameDef *gamedef = env->getGameDef();
1904 moveresult = collisionMovePrecise(&env->getMap(), gamedef,
1905 pos_max_d, box, dtime, p_pos, p_velocity);
1908 m_velocity = p_velocity;
1910 bool is_end_position = moveresult.collides;
1911 pos_translator.update(m_position, is_end_position, dtime);
1912 pos_translator.translate(dtime);
1915 m_velocity += dtime * m_acceleration;
1917 m_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration;
1918 m_velocity += dtime * m_acceleration;
1919 pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time);
1920 pos_translator.translate(dtime);
1924 m_anim_timer += dtime;
1925 if(m_anim_timer >= m_anim_framelength){
1926 m_anim_timer -= m_anim_framelength;
1928 if(m_anim_frame >= m_anim_num_frames)
1935 void updateTexturePos()
1938 scene::ICameraSceneNode* camera =
1939 m_spritenode->getSceneManager()->getActiveCamera();
1942 v3f cam_to_entity = m_spritenode->getAbsolutePosition()
1943 - camera->getAbsolutePosition();
1944 cam_to_entity.normalize();
1946 int row = m_tx_basepos.Y;
1947 int col = m_tx_basepos.X;
1949 if(m_tx_select_horiz_by_yawpitch)
1951 if(cam_to_entity.Y > 0.75)
1953 else if(cam_to_entity.Y < -0.75)
1956 float mob_dir = atan2(cam_to_entity.Z, cam_to_entity.X) / PI * 180.;
1957 float dir = mob_dir - m_yaw;
1958 dir = wrapDegrees_180(dir);
1959 //infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
1960 if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
1962 else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
1964 else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
1966 else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
1973 // Animation goes downwards
1974 row += m_anim_frame;
1976 float txs = m_tx_size.X;
1977 float tys = m_tx_size.Y;
1978 m_spritenode->setTCoords(0, v2f(txs*(1+col), tys*(1+row)));
1979 m_spritenode->setTCoords(1, v2f(txs*(1+col), tys*(0+row)));
1980 m_spritenode->setTCoords(2, v2f(txs*(0+col), tys*(0+row)));
1981 m_spritenode->setTCoords(3, v2f(txs*(0+col), tys*(1+row)));
1985 void updateTextures(const std::string &mod)
1987 ITextureSource *tsrc = m_gamedef->tsrc();
1990 std::string texturestring = "unknown_block.png";
1991 if(m_prop->textures.size() >= 1)
1992 texturestring = m_prop->textures[0];
1993 texturestring += mod;
1994 m_spritenode->setMaterialTexture(0,
1995 tsrc->getTextureRaw(texturestring));
1998 for (u32 i = 0; i < 6; ++i)
2000 std::string texturestring = "unknown_block.png";
2001 if(m_prop->textures.size() > i)
2002 texturestring = m_prop->textures[i];
2003 texturestring += mod;
2004 AtlasPointer ap = tsrc->getTexture(texturestring);
2006 // Get the tile texture and atlas transformation
2007 video::ITexture* atlas = ap.atlas;
2011 // Set material flags and texture
2012 video::SMaterial& material = m_meshnode->getMaterial(i);
2013 material.setFlag(video::EMF_LIGHTING, false);
2014 material.setFlag(video::EMF_BILINEAR_FILTER, false);
2015 material.setTexture(0, atlas);
2016 material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
2017 material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
2022 void processMessage(const std::string &data)
2024 //infostream<<"LuaEntityCAO: Got message"<<std::endl;
2025 std::istringstream is(data, std::ios::binary);
2027 u8 cmd = readU8(is);
2028 if(cmd == 0) // update position
2031 bool do_interpolate = readU8(is);
2033 m_position = readV3F1000(is);
2035 m_velocity = readV3F1000(is);
2037 m_acceleration = readV3F1000(is);
2039 m_yaw = readF1000(is);
2040 // is_end_position (for interpolation)
2041 bool is_end_position = readU8(is);
2043 float update_interval = readF1000(is);
2046 if(!m_prop->physical)
2047 pos_translator.update(m_position, is_end_position, update_interval);
2049 pos_translator.init(m_position);
2053 else if(cmd == 1) // set texture modification
2055 std::string mod = deSerializeString(is);
2056 updateTextures(mod);
2058 else if(cmd == 2) // set sprite
2060 v2s16 p = readV2S16(is);
2061 int num_frames = readU16(is);
2062 float framelength = readF1000(is);
2063 bool select_horiz_by_yawpitch = readU8(is);
2066 m_anim_num_frames = num_frames;
2067 m_anim_framelength = framelength;
2068 m_tx_select_horiz_by_yawpitch = select_horiz_by_yawpitch;
2076 LuaEntityCAO proto_LuaEntityCAO(NULL, NULL);
2082 class PlayerCAO : public ClientActiveObject
2085 core::aabbox3d<f32> m_selection_box;
2086 scene::IMeshSceneNode *m_node;
2087 scene::ITextSceneNode* m_text;
2091 SmoothTranslator pos_translator;
2092 bool m_is_local_player;
2093 LocalPlayer *m_local_player;
2094 float m_damage_visual_timer;
2097 PlayerCAO(IGameDef *gamedef, ClientEnvironment *env):
2098 ClientActiveObject(0, gamedef, env),
2099 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.0,BS/3.),
2102 m_position(v3f(0,10*BS,0)),
2104 m_is_local_player(false),
2105 m_local_player(NULL),
2106 m_damage_visual_timer(0)
2109 ClientActiveObject::registerType(getType(), create);
2112 void initialize(const std::string &data)
2114 infostream<<"PlayerCAO: Got init data"<<std::endl;
2116 std::istringstream is(data, std::ios::binary);
2118 u8 version = readU8(is);
2123 m_name = deSerializeString(is);
2125 m_position = readV3F1000(is);
2127 m_yaw = readF1000(is);
2129 pos_translator.init(m_position);
2131 Player *player = m_env->getPlayer(m_name.c_str());
2132 if(player && player->isLocal()){
2133 m_is_local_player = true;
2134 m_local_player = (LocalPlayer*)player;
2144 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
2146 return new PlayerCAO(gamedef, env);
2151 return ACTIVEOBJECT_TYPE_PLAYER;
2153 core::aabbox3d<f32>* getSelectionBox()
2155 if(m_is_local_player)
2157 return &m_selection_box;
2161 return pos_translator.vect_show;
2164 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
2165 IrrlichtDevice *irr)
2169 if(m_is_local_player)
2172 //video::IVideoDriver* driver = smgr->getVideoDriver();
2173 gui::IGUIEnvironment* gui = irr->getGUIEnvironment();
2175 scene::SMesh *mesh = new scene::SMesh();
2177 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
2178 video::SColor c(255,255,255,255);
2179 video::S3DVertex vertices[4] =
2181 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
2182 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
2183 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
2184 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
2186 u16 indices[] = {0,1,2,2,3,0};
2187 buf->append(vertices, 4, indices, 6);
2189 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
2190 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
2191 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
2192 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
2194 mesh->addMeshBuffer(buf);
2198 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
2199 video::SColor c(255,255,255,255);
2200 video::S3DVertex vertices[4] =
2202 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
2203 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
2204 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
2205 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
2207 u16 indices[] = {0,1,2,2,3,0};
2208 buf->append(vertices, 4, indices, 6);
2210 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
2211 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
2212 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
2213 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
2215 mesh->addMeshBuffer(buf);
2218 m_node = smgr->addMeshSceneNode(mesh, NULL);
2220 // Set it to use the materials of the meshbuffers directly.
2221 // This is needed for changing the texture in the future
2222 m_node->setReadOnlyMaterials(true);
2225 // Add a text node for showing the name
2226 std::wstring wname = narrow_to_wide(m_name);
2227 m_text = smgr->addTextSceneNode(gui->getBuiltInFont(),
2228 wname.c_str(), video::SColor(255,255,255,255), m_node);
2229 m_text->setPosition(v3f(0, (f32)BS*2.1, 0));
2235 void removeFromScene()
2244 void updateLight(u8 light_at_pos)
2249 m_node->setVisible(true);
2251 u8 li = decode_light(light_at_pos);
2252 video::SColor color(255,li,li,li);
2253 setMeshVerticesColor(m_node->getMesh(), color);
2256 v3s16 getLightPosition()
2258 return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
2261 void updateNodePos()
2266 m_node->setPosition(pos_translator.vect_show);
2268 v3f rot = m_node->getRotation();
2270 m_node->setRotation(rot);
2273 void step(float dtime, ClientEnvironment *env)
2275 pos_translator.translate(dtime);
2278 if(m_damage_visual_timer > 0){
2279 m_damage_visual_timer -= dtime;
2280 if(m_damage_visual_timer <= 0){
2286 void processMessage(const std::string &data)
2288 //infostream<<"PlayerCAO: Got message"<<std::endl;
2289 std::istringstream is(data, std::ios::binary);
2291 u8 cmd = readU8(is);
2292 if(cmd == 0) // update position
2295 m_position = readV3F1000(is);
2297 m_yaw = readF1000(is);
2299 pos_translator.update(m_position, false);
2303 else if(cmd == 1) // punched
2306 s16 damage = readS16(is);
2308 if(m_is_local_player)
2309 m_env->damageLocalPlayer(damage, false);
2311 m_damage_visual_timer = 0.5;
2312 updateTextures("^[brighten");
2316 void updateTextures(const std::string &mod)
2320 ITextureSource *tsrc = m_gamedef->tsrc();
2321 scene::IMesh *mesh = m_node->getMesh();
2324 std::string tname = "player.png";
2326 scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
2327 buf->getMaterial().setTexture(0,
2328 tsrc->getTextureRaw(tname));
2331 std::string tname = "player_back.png";
2333 scene::IMeshBuffer *buf = mesh->getMeshBuffer(1);
2334 buf->getMaterial().setTexture(0,
2335 tsrc->getTextureRaw(tname));
2342 PlayerCAO proto_PlayerCAO(NULL, NULL);