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"
31 #include "utility.h" // For IntervalLimiter
33 #include "MyBillboardSceneNode.h"
35 core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
41 struct SmoothTranslator
48 f32 anim_time_counter;
68 anim_time_counter = 0;
77 void update(v3f vect_new, bool is_end_position=false, float update_interval=-1)
79 aim_is_end = is_end_position;
82 if(update_interval > 0){
83 anim_time = update_interval;
85 if(anim_time < 0.001 || anim_time > 1.0)
86 anim_time = anim_time_counter;
88 anim_time = anim_time * 0.9 + anim_time_counter * 0.1;
90 anim_time_counter = 0;
94 void translate(f32 dtime)
96 anim_time_counter = anim_time_counter + dtime;
97 anim_counter = anim_counter + dtime;
98 v3f vect_move = vect_aim - vect_old;
100 if(anim_time > 0.001)
101 moveratio = anim_time_counter / anim_time;
102 // Move a bit less than should, to avoid oscillation
103 moveratio = moveratio * 0.8;
104 float move_end = 1.5;
107 if(moveratio > move_end)
108 moveratio = move_end;
109 vect_show = vect_old + vect_move * moveratio;
114 return ((anim_time_counter / anim_time) < 1.4);
123 class TestCAO : public ClientActiveObject
126 TestCAO(IGameDef *gamedef, ClientEnvironment *env);
131 return ACTIVEOBJECT_TYPE_TEST;
134 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
136 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
137 IrrlichtDevice *irr);
138 void removeFromScene();
139 void updateLight(u8 light_at_pos);
140 v3s16 getLightPosition();
141 void updateNodePos();
143 void step(float dtime, ClientEnvironment *env);
145 void processMessage(const std::string &data);
148 scene::IMeshSceneNode *m_node;
156 class ItemCAO : public ClientActiveObject
159 ItemCAO(IGameDef *gamedef, ClientEnvironment *env);
164 return ACTIVEOBJECT_TYPE_ITEM;
167 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
169 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
170 IrrlichtDevice *irr);
171 void removeFromScene();
172 void updateLight(u8 light_at_pos);
173 v3s16 getLightPosition();
174 void updateNodePos();
176 void step(float dtime, ClientEnvironment *env);
178 void processMessage(const std::string &data);
180 void initialize(const std::string &data);
182 core::aabbox3d<f32>* getSelectionBox()
183 {return &m_selection_box;}
188 core::aabbox3d<f32> m_selection_box;
189 scene::IMeshSceneNode *m_node;
191 std::string m_inventorystring;
198 class RatCAO : public ClientActiveObject
201 RatCAO(IGameDef *gamedef, ClientEnvironment *env);
206 return ACTIVEOBJECT_TYPE_RAT;
209 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
211 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
212 IrrlichtDevice *irr);
213 void removeFromScene();
214 void updateLight(u8 light_at_pos);
215 v3s16 getLightPosition();
216 void updateNodePos();
218 void step(float dtime, ClientEnvironment *env);
220 void processMessage(const std::string &data);
222 void initialize(const std::string &data);
224 core::aabbox3d<f32>* getSelectionBox()
225 {return &m_selection_box;}
227 {return pos_translator.vect_show;}
228 //{return m_position;}
231 core::aabbox3d<f32> m_selection_box;
232 scene::IMeshSceneNode *m_node;
235 SmoothTranslator pos_translator;
242 class Oerkki1CAO : public ClientActiveObject
245 Oerkki1CAO(IGameDef *gamedef, ClientEnvironment *env);
246 virtual ~Oerkki1CAO();
250 return ACTIVEOBJECT_TYPE_OERKKI1;
253 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
255 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
256 IrrlichtDevice *irr);
257 void removeFromScene();
258 void updateLight(u8 light_at_pos);
259 v3s16 getLightPosition();
260 void updateNodePos();
262 void step(float dtime, ClientEnvironment *env);
264 void processMessage(const std::string &data);
266 void initialize(const std::string &data);
268 core::aabbox3d<f32>* getSelectionBox()
269 {return &m_selection_box;}
271 {return pos_translator.vect_show;}
272 //{return m_position;}
274 // If returns true, punch will not be sent to the server
275 bool directReportPunch(const std::string &toolname, v3f dir);
278 IntervalLimiter m_attack_interval;
279 core::aabbox3d<f32> m_selection_box;
280 scene::IMeshSceneNode *m_node;
283 SmoothTranslator pos_translator;
284 float m_damage_visual_timer;
285 bool m_damage_texture_enabled;
292 class FireflyCAO : public ClientActiveObject
295 FireflyCAO(IGameDef *gamedef, ClientEnvironment *env);
296 virtual ~FireflyCAO();
300 return ACTIVEOBJECT_TYPE_FIREFLY;
303 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
305 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
306 IrrlichtDevice *irr);
307 void removeFromScene();
308 void updateLight(u8 light_at_pos);
309 v3s16 getLightPosition();
310 void updateNodePos();
312 void step(float dtime, ClientEnvironment *env);
314 void processMessage(const std::string &data);
316 void initialize(const std::string &data);
318 core::aabbox3d<f32>* getSelectionBox()
319 {return &m_selection_box;}
324 core::aabbox3d<f32> m_selection_box;
325 scene::IMeshSceneNode *m_node;
328 SmoothTranslator pos_translator;
335 class MobV2CAO : public ClientActiveObject
338 MobV2CAO(IGameDef *gamedef, ClientEnvironment *env);
343 return ACTIVEOBJECT_TYPE_MOBV2;
346 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
348 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
349 IrrlichtDevice *irr);
350 void removeFromScene();
351 void updateLight(u8 light_at_pos);
352 v3s16 getLightPosition();
353 void updateNodePos();
355 void step(float dtime, ClientEnvironment *env);
357 void processMessage(const std::string &data);
359 void initialize(const std::string &data);
361 core::aabbox3d<f32>* getSelectionBox()
362 {return &m_selection_box;}
364 {return pos_translator.vect_show;}
365 //{return m_position;}
366 bool doShowSelectionBox(){return false;}
368 // If returns true, punch will not be sent to the server
369 bool directReportPunch(const std::string &toolname, v3f dir);
372 void setLooks(const std::string &looks);
374 IntervalLimiter m_attack_interval;
375 core::aabbox3d<f32> m_selection_box;
376 scene::MyBillboardSceneNode *m_node;
378 std::string m_texture_name;
380 SmoothTranslator pos_translator;
382 float m_walking_unset_timer;
385 float m_damage_visual_timer;
388 float m_shooting_unset_timer;
391 bool m_bright_shooting;
392 std::string m_sprite_type;
393 int m_simple_anim_frames;
394 float m_simple_anim_frametime;
395 bool m_lock_full_brightness;
396 int m_player_hit_damage;
397 float m_player_hit_distance;
398 float m_player_hit_interval;
399 float m_player_hit_timer;
401 Settings *m_properties;
409 TestCAO proto_TestCAO(NULL, NULL);
411 TestCAO::TestCAO(IGameDef *gamedef, ClientEnvironment *env):
412 ClientActiveObject(0, gamedef, env),
414 m_position(v3f(0,10*BS,0))
416 ClientActiveObject::registerType(getType(), create);
423 ClientActiveObject* TestCAO::create(IGameDef *gamedef, ClientEnvironment *env)
425 return new TestCAO(gamedef, env);
428 void TestCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
434 //video::IVideoDriver* driver = smgr->getVideoDriver();
436 scene::SMesh *mesh = new scene::SMesh();
437 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
438 video::SColor c(255,255,255,255);
439 video::S3DVertex vertices[4] =
441 video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
442 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
443 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
444 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),
446 u16 indices[] = {0,1,2,2,3,0};
447 buf->append(vertices, 4, indices, 6);
449 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
450 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
451 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("rat.png"));
452 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
453 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
454 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
456 mesh->addMeshBuffer(buf);
458 m_node = smgr->addMeshSceneNode(mesh, NULL);
463 void TestCAO::removeFromScene()
472 void TestCAO::updateLight(u8 light_at_pos)
476 v3s16 TestCAO::getLightPosition()
478 return floatToInt(m_position, BS);
481 void TestCAO::updateNodePos()
486 m_node->setPosition(m_position);
487 //m_node->setRotation(v3f(0, 45, 0));
490 void TestCAO::step(float dtime, ClientEnvironment *env)
494 v3f rot = m_node->getRotation();
495 //infostream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
496 rot.Y += dtime * 180;
497 m_node->setRotation(rot);
501 void TestCAO::processMessage(const std::string &data)
503 infostream<<"TestCAO: Got data: "<<data<<std::endl;
504 std::istringstream is(data, std::ios::binary);
522 #include "inventory.h"
525 ItemCAO proto_ItemCAO(NULL, NULL);
527 ItemCAO::ItemCAO(IGameDef *gamedef, ClientEnvironment *env):
528 ClientActiveObject(0, gamedef, env),
529 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.),
531 m_position(v3f(0,10*BS,0))
533 ClientActiveObject::registerType(getType(), create);
540 ClientActiveObject* ItemCAO::create(IGameDef *gamedef, ClientEnvironment *env)
542 return new ItemCAO(gamedef, env);
545 void ItemCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
551 //video::IVideoDriver* driver = smgr->getVideoDriver();
553 scene::SMesh *mesh = new scene::SMesh();
554 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
555 video::SColor c(255,255,255,255);
556 video::S3DVertex vertices[4] =
558 /*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
559 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
560 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
561 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/
562 video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1),
563 video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1),
564 video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0),
565 video::S3DVertex(BS/3.,0+BS*2./3.,0, 0,0,0, c, 0,0),
567 u16 indices[] = {0,1,2,2,3,0};
568 buf->append(vertices, 4, indices, 6);
570 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
571 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
572 //buf->getMaterial().setTexture(0, NULL);
573 // Initialize with the stick texture
574 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("stick.png"));
575 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
576 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
577 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
579 mesh->addMeshBuffer(buf);
581 m_node = smgr->addMeshSceneNode(mesh, NULL);
583 // Set it to use the materials of the meshbuffers directly.
584 // This is needed for changing the texture in the future
585 m_node->setReadOnlyMaterials(true);
592 // Create an inventory item to see what is its image
593 std::istringstream is(m_inventorystring, std::ios_base::binary);
594 video::ITexture *texture = NULL;
596 InventoryItem *item = NULL;
597 item = InventoryItem::deSerialize(is, m_gamedef);
598 infostream<<__FUNCTION_NAME<<": m_inventorystring=\""
599 <<m_inventorystring<<"\" -> item="<<item
603 texture = item->getImage();
607 catch(SerializationError &e)
609 infostream<<"WARNING: "<<__FUNCTION_NAME
610 <<": error deSerializing inventorystring \""
611 <<m_inventorystring<<"\""<<std::endl;
614 // Set meshbuffer texture
615 buf->getMaterial().setTexture(0, texture);
618 void ItemCAO::removeFromScene()
627 void ItemCAO::updateLight(u8 light_at_pos)
632 u8 li = decode_light(light_at_pos);
633 video::SColor color(255,li,li,li);
634 setMeshColor(m_node->getMesh(), color);
637 v3s16 ItemCAO::getLightPosition()
639 return floatToInt(m_position, BS);
642 void ItemCAO::updateNodePos()
647 m_node->setPosition(m_position);
650 void ItemCAO::step(float dtime, ClientEnvironment *env)
654 /*v3f rot = m_node->getRotation();
655 rot.Y += dtime * 120;
656 m_node->setRotation(rot);*/
657 LocalPlayer *player = env->getLocalPlayer();
659 v3f rot = m_node->getRotation();
660 rot.Y = 180.0 - (player->getYaw());
661 m_node->setRotation(rot);
665 void ItemCAO::processMessage(const std::string &data)
667 //infostream<<"ItemCAO: Got message"<<std::endl;
668 std::istringstream is(data, std::ios::binary);
674 m_position = readV3F1000(is);
679 void ItemCAO::initialize(const std::string &data)
681 infostream<<"ItemCAO: Got init data"<<std::endl;
684 std::istringstream is(data, std::ios::binary);
686 u8 version = readU8(is);
691 m_position = readV3F1000(is);
693 m_inventorystring = deSerializeString(is);
703 #include "inventory.h"
706 RatCAO proto_RatCAO(NULL, NULL);
708 RatCAO::RatCAO(IGameDef *gamedef, ClientEnvironment *env):
709 ClientActiveObject(0, gamedef, env),
710 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
712 m_position(v3f(0,10*BS,0)),
715 ClientActiveObject::registerType(getType(), create);
722 ClientActiveObject* RatCAO::create(IGameDef *gamedef, ClientEnvironment *env)
724 return new RatCAO(gamedef, env);
727 void RatCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
733 //video::IVideoDriver* driver = smgr->getVideoDriver();
735 scene::SMesh *mesh = new scene::SMesh();
736 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
737 video::SColor c(255,255,255,255);
738 video::S3DVertex vertices[4] =
740 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
741 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
742 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
743 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
745 u16 indices[] = {0,1,2,2,3,0};
746 buf->append(vertices, 4, indices, 6);
748 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
749 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
750 //buf->getMaterial().setTexture(0, NULL);
751 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("rat.png"));
752 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
753 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
754 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
756 mesh->addMeshBuffer(buf);
758 m_node = smgr->addMeshSceneNode(mesh, NULL);
760 // Set it to use the materials of the meshbuffers directly.
761 // This is needed for changing the texture in the future
762 m_node->setReadOnlyMaterials(true);
766 void RatCAO::removeFromScene()
775 void RatCAO::updateLight(u8 light_at_pos)
780 u8 li = decode_light(light_at_pos);
781 video::SColor color(255,li,li,li);
782 setMeshColor(m_node->getMesh(), color);
785 v3s16 RatCAO::getLightPosition()
787 return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
790 void RatCAO::updateNodePos()
795 //m_node->setPosition(m_position);
796 m_node->setPosition(pos_translator.vect_show);
798 v3f rot = m_node->getRotation();
799 rot.Y = 180.0 - m_yaw;
800 m_node->setRotation(rot);
803 void RatCAO::step(float dtime, ClientEnvironment *env)
805 pos_translator.translate(dtime);
809 void RatCAO::processMessage(const std::string &data)
811 //infostream<<"RatCAO: Got message"<<std::endl;
812 std::istringstream is(data, std::ios::binary);
818 m_position = readV3F1000(is);
819 pos_translator.update(m_position);
821 m_yaw = readF1000(is);
826 void RatCAO::initialize(const std::string &data)
828 //infostream<<"RatCAO: Got init data"<<std::endl;
831 std::istringstream is(data, std::ios::binary);
833 u8 version = readU8(is);
838 m_position = readV3F1000(is);
839 pos_translator.init(m_position);
849 #include "inventory.h"
852 Oerkki1CAO proto_Oerkki1CAO(NULL, NULL);
854 Oerkki1CAO::Oerkki1CAO(IGameDef *gamedef, ClientEnvironment *env):
855 ClientActiveObject(0, gamedef, env),
856 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.),
858 m_position(v3f(0,10*BS,0)),
860 m_damage_visual_timer(0),
861 m_damage_texture_enabled(false)
863 ClientActiveObject::registerType(getType(), create);
866 Oerkki1CAO::~Oerkki1CAO()
870 ClientActiveObject* Oerkki1CAO::create(IGameDef *gamedef, ClientEnvironment *env)
872 return new Oerkki1CAO(gamedef, env);
875 void Oerkki1CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
881 //video::IVideoDriver* driver = smgr->getVideoDriver();
883 scene::SMesh *mesh = new scene::SMesh();
884 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
885 video::SColor c(255,255,255,255);
886 video::S3DVertex vertices[4] =
888 video::S3DVertex(-BS/2-BS,0,0, 0,0,0, c, 0,1),
889 video::S3DVertex(BS/2+BS,0,0, 0,0,0, c, 1,1),
890 video::S3DVertex(BS/2+BS,BS*2,0, 0,0,0, c, 1,0),
891 video::S3DVertex(-BS/2-BS,BS*2,0, 0,0,0, c, 0,0),
893 u16 indices[] = {0,1,2,2,3,0};
894 buf->append(vertices, 4, indices, 6);
896 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
897 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
898 //buf->getMaterial().setTexture(0, NULL);
899 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("oerkki1.png"));
900 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
901 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
902 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
904 mesh->addMeshBuffer(buf);
906 m_node = smgr->addMeshSceneNode(mesh, NULL);
908 // Set it to use the materials of the meshbuffers directly.
909 // This is needed for changing the texture in the future
910 m_node->setReadOnlyMaterials(true);
914 void Oerkki1CAO::removeFromScene()
923 void Oerkki1CAO::updateLight(u8 light_at_pos)
928 if(light_at_pos <= 2)
930 m_node->setVisible(false);
934 m_node->setVisible(true);
936 u8 li = decode_light(light_at_pos);
937 video::SColor color(255,li,li,li);
938 setMeshColor(m_node->getMesh(), color);
941 v3s16 Oerkki1CAO::getLightPosition()
943 return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
946 void Oerkki1CAO::updateNodePos()
951 //m_node->setPosition(m_position);
952 m_node->setPosition(pos_translator.vect_show);
954 v3f rot = m_node->getRotation();
955 rot.Y = 180.0 - m_yaw + 90.0;
956 m_node->setRotation(rot);
959 void Oerkki1CAO::step(float dtime, ClientEnvironment *env)
961 ITextureSource *tsrc = m_gamedef->tsrc();
963 pos_translator.translate(dtime);
966 LocalPlayer *player = env->getLocalPlayer();
969 v3f playerpos = player->getPosition();
970 v2f playerpos_2d(playerpos.X,playerpos.Z);
971 v2f objectpos_2d(m_position.X,m_position.Z);
973 if(fabs(m_position.Y - playerpos.Y) < 1.5*BS &&
974 objectpos_2d.getDistanceFrom(playerpos_2d) < 1.5*BS)
976 if(m_attack_interval.step(dtime, 0.5))
978 env->damageLocalPlayer(2);
982 if(m_damage_visual_timer > 0)
984 if(!m_damage_texture_enabled)
986 // Enable damage texture
989 /*video::IVideoDriver* driver =
990 m_node->getSceneManager()->getVideoDriver();*/
992 scene::IMesh *mesh = m_node->getMesh();
996 u16 mc = mesh->getMeshBufferCount();
997 for(u16 j=0; j<mc; j++)
999 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
1000 buf->getMaterial().setTexture(0,
1001 tsrc->getTextureRaw("oerkki1_damaged.png"));
1004 m_damage_texture_enabled = true;
1006 m_damage_visual_timer -= dtime;
1010 if(m_damage_texture_enabled)
1012 // Disable damage texture
1015 /*video::IVideoDriver* driver =
1016 m_node->getSceneManager()->getVideoDriver();*/
1018 scene::IMesh *mesh = m_node->getMesh();
1022 u16 mc = mesh->getMeshBufferCount();
1023 for(u16 j=0; j<mc; j++)
1025 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
1026 buf->getMaterial().setTexture(0,
1027 tsrc->getTextureRaw("oerkki1.png"));
1030 m_damage_texture_enabled = false;
1035 void Oerkki1CAO::processMessage(const std::string &data)
1037 //infostream<<"Oerkki1CAO: Got message"<<std::endl;
1038 std::istringstream is(data, std::ios::binary);
1040 u8 cmd = readU8(is);
1044 m_position = readV3F1000(is);
1045 pos_translator.update(m_position);
1047 m_yaw = readF1000(is);
1052 //u16 damage = readU8(is);
1053 m_damage_visual_timer = 1.0;
1057 void Oerkki1CAO::initialize(const std::string &data)
1059 //infostream<<"Oerkki1CAO: Got init data"<<std::endl;
1062 std::istringstream is(data, std::ios::binary);
1064 u8 version = readU8(is);
1069 m_position = readV3F1000(is);
1070 pos_translator.init(m_position);
1076 bool Oerkki1CAO::directReportPunch(const std::string &toolname, v3f dir)
1078 m_damage_visual_timer = 1.0;
1080 m_position += dir * BS;
1081 pos_translator.sharpen();
1082 pos_translator.update(m_position);
1093 FireflyCAO proto_FireflyCAO(NULL, NULL);
1095 FireflyCAO::FireflyCAO(IGameDef *gamedef, ClientEnvironment *env):
1096 ClientActiveObject(0, gamedef, env),
1097 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
1099 m_position(v3f(0,10*BS,0)),
1102 ClientActiveObject::registerType(getType(), create);
1105 FireflyCAO::~FireflyCAO()
1109 ClientActiveObject* FireflyCAO::create(IGameDef *gamedef, ClientEnvironment *env)
1111 return new FireflyCAO(gamedef, env);
1114 void FireflyCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
1115 IrrlichtDevice *irr)
1120 //video::IVideoDriver* driver = smgr->getVideoDriver();
1122 scene::SMesh *mesh = new scene::SMesh();
1123 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
1124 video::SColor c(255,255,255,255);
1125 video::S3DVertex vertices[4] =
1127 video::S3DVertex(0,0,0, 0,0,0, c, 0,1),
1128 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
1129 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
1130 video::S3DVertex(0,BS/2,0, 0,0,0, c, 0,0),
1132 u16 indices[] = {0,1,2,2,3,0};
1133 buf->append(vertices, 4, indices, 6);
1135 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
1136 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
1137 //buf->getMaterial().setTexture(0, NULL);
1138 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("firefly.png"));
1139 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
1140 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
1141 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
1143 mesh->addMeshBuffer(buf);
1145 m_node = smgr->addMeshSceneNode(mesh, NULL);
1147 // Set it to use the materials of the meshbuffers directly.
1148 // This is needed for changing the texture in the future
1149 m_node->setReadOnlyMaterials(true);
1153 void FireflyCAO::removeFromScene()
1162 void FireflyCAO::updateLight(u8 light_at_pos)
1168 video::SColor color(255,li,li,li);
1169 setMeshColor(m_node->getMesh(), color);
1172 v3s16 FireflyCAO::getLightPosition()
1174 return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
1177 void FireflyCAO::updateNodePos()
1182 //m_node->setPosition(m_position);
1183 m_node->setPosition(pos_translator.vect_show);
1185 v3f rot = m_node->getRotation();
1186 rot.Y = 180.0 - m_yaw;
1187 m_node->setRotation(rot);
1190 void FireflyCAO::step(float dtime, ClientEnvironment *env)
1192 pos_translator.translate(dtime);
1196 void FireflyCAO::processMessage(const std::string &data)
1198 //infostream<<"FireflyCAO: Got message"<<std::endl;
1199 std::istringstream is(data, std::ios::binary);
1201 u8 cmd = readU8(is);
1205 m_position = readV3F1000(is);
1206 pos_translator.update(m_position);
1208 m_yaw = readF1000(is);
1213 void FireflyCAO::initialize(const std::string &data)
1215 //infostream<<"FireflyCAO: Got init data"<<std::endl;
1218 std::istringstream is(data, std::ios::binary);
1220 u8 version = readU8(is);
1225 m_position = readV3F1000(is);
1226 pos_translator.init(m_position);
1237 MobV2CAO proto_MobV2CAO(NULL, NULL);
1239 MobV2CAO::MobV2CAO(IGameDef *gamedef, ClientEnvironment *env):
1240 ClientActiveObject(0, gamedef, env),
1241 m_selection_box(-0.4*BS,-0.4*BS,-0.4*BS, 0.4*BS,0.8*BS,0.4*BS),
1243 m_position(v3f(0,10*BS,0)),
1246 m_walking_unset_timer(0),
1249 m_damage_visual_timer(0),
1252 m_shooting_unset_timer(0),
1253 m_sprite_size(BS,BS),
1255 m_bright_shooting(false),
1256 m_lock_full_brightness(false),
1257 m_player_hit_timer(0)
1259 ClientActiveObject::registerType(getType(), create);
1261 m_properties = new Settings;
1264 MobV2CAO::~MobV2CAO()
1266 delete m_properties;
1269 ClientActiveObject* MobV2CAO::create(IGameDef *gamedef, ClientEnvironment *env)
1271 return new MobV2CAO(gamedef, env);
1274 void MobV2CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
1275 IrrlichtDevice *irr)
1280 /*infostream<<"MobV2CAO::addToScene using texture_name="<<
1281 m_texture_name<<std::endl;*/
1282 std::string texture_string = m_texture_name +
1283 "^[makealpha:128,0,0^[makealpha:128,128,0";
1285 scene::MyBillboardSceneNode *bill = new scene::MyBillboardSceneNode(
1286 smgr->getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1));
1287 bill->setMaterialTexture(0, tsrc->getTextureRaw(texture_string));
1288 bill->setMaterialFlag(video::EMF_LIGHTING, false);
1289 bill->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
1290 bill->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
1291 bill->setMaterialFlag(video::EMF_FOG_ENABLE, true);
1292 bill->setColor(video::SColor(255,0,0,0));
1293 bill->setVisible(false); /* Set visible when brightness is known */
1294 bill->setSize(m_sprite_size);
1295 if(m_sprite_type == "humanoid_1"){
1296 const float txp = 1./192;
1297 const float txs = txp*32;
1298 const float typ = 1./240;
1299 const float tys = typ*48;
1300 bill->setTCoords(0, v2f(txs*1, tys*1));
1301 bill->setTCoords(1, v2f(txs*1, tys*0));
1302 bill->setTCoords(2, v2f(txs*0, tys*0));
1303 bill->setTCoords(3, v2f(txs*0, tys*1));
1304 } else if(m_sprite_type == "simple"){
1305 const float txs = 1.0;
1306 const float tys = 1.0 / m_simple_anim_frames;
1307 bill->setTCoords(0, v2f(txs*1, tys*1));
1308 bill->setTCoords(1, v2f(txs*1, tys*0));
1309 bill->setTCoords(2, v2f(txs*0, tys*0));
1310 bill->setTCoords(3, v2f(txs*0, tys*1));
1312 infostream<<"MobV2CAO: Unknown sprite type \""<<m_sprite_type<<"\""
1321 void MobV2CAO::removeFromScene()
1331 void MobV2CAO::updateLight(u8 light_at_pos)
1333 if(m_lock_full_brightness)
1336 m_last_light = light_at_pos;
1341 if(m_damage_visual_timer > 0)
1344 if(m_shooting && m_bright_shooting)
1347 /*if(light_at_pos <= 2){
1348 m_node->setVisible(false);
1352 m_node->setVisible(true);
1354 u8 li = decode_light(light_at_pos);
1355 video::SColor color(255,li,li,li);
1356 m_node->setColor(color);
1359 v3s16 MobV2CAO::getLightPosition()
1361 return floatToInt(m_position+v3f(0,0,0), BS);
1364 void MobV2CAO::updateNodePos()
1369 m_node->setPosition(pos_translator.vect_show + v3f(0,m_sprite_y,0));
1372 void MobV2CAO::step(float dtime, ClientEnvironment *env)
1374 scene::MyBillboardSceneNode *bill = m_node;
1378 pos_translator.translate(dtime);
1380 if(m_sprite_type == "humanoid_1"){
1381 scene::ICameraSceneNode* camera = m_node->getSceneManager()->getActiveCamera();
1384 v3f cam_to_mob = m_node->getAbsolutePosition() - camera->getAbsolutePosition();
1385 cam_to_mob.normalize();
1387 if(cam_to_mob.Y > 0.75)
1389 else if(cam_to_mob.Y < -0.75)
1392 float mob_dir = atan2(cam_to_mob.Z, cam_to_mob.X) / PI * 180.;
1393 float dir = mob_dir - m_yaw;
1394 dir = wrapDegrees_180(dir);
1395 //infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
1396 if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
1398 else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
1400 else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
1402 else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
1411 } else if(m_walking){
1412 m_walk_timer += dtime;
1413 if(m_walk_timer >= 0.5){
1414 m_walk_frame = (m_walk_frame + 1) % 2;
1417 if(m_walk_frame == 0)
1423 const float txp = 1./192;
1424 const float txs = txp*32;
1425 const float typ = 1./240;
1426 const float tys = typ*48;
1427 bill->setTCoords(0, v2f(txs*(1+col), tys*(1+row)));
1428 bill->setTCoords(1, v2f(txs*(1+col), tys*(0+row)));
1429 bill->setTCoords(2, v2f(txs*(0+col), tys*(0+row)));
1430 bill->setTCoords(3, v2f(txs*(0+col), tys*(1+row)));
1431 } else if(m_sprite_type == "simple"){
1432 m_walk_timer += dtime;
1433 if(m_walk_timer >= m_simple_anim_frametime){
1434 m_walk_frame = (m_walk_frame + 1) % m_simple_anim_frames;
1438 int row = m_walk_frame;
1439 const float txs = 1.0;
1440 const float tys = 1.0 / m_simple_anim_frames;
1441 bill->setTCoords(0, v2f(txs*(1+col), tys*(1+row)));
1442 bill->setTCoords(1, v2f(txs*(1+col), tys*(0+row)));
1443 bill->setTCoords(2, v2f(txs*(0+col), tys*(0+row)));
1444 bill->setTCoords(3, v2f(txs*(0+col), tys*(1+row)));
1446 infostream<<"MobV2CAO::step(): Unknown sprite type \""
1447 <<m_sprite_type<<"\""<<std::endl;
1452 /* Damage local player */
1453 if(m_player_hit_damage && m_player_hit_timer <= 0.0){
1454 LocalPlayer *player = env->getLocalPlayer();
1457 v3f playerpos = player->getPosition();
1458 v2f playerpos_2d(playerpos.X,playerpos.Z);
1459 v2f objectpos_2d(m_position.X,m_position.Z);
1461 if(fabs(m_position.Y - playerpos.Y) < m_player_hit_distance*BS &&
1462 objectpos_2d.getDistanceFrom(playerpos_2d) < m_player_hit_distance*BS)
1464 env->damageLocalPlayer(m_player_hit_damage);
1465 m_player_hit_timer = m_player_hit_interval;
1471 m_player_hit_timer -= dtime;
1473 if(m_damage_visual_timer >= 0){
1474 m_damage_visual_timer -= dtime;
1475 if(m_damage_visual_timer <= 0){
1476 infostream<<"id="<<m_id<<" damage visual ended"<<std::endl;
1480 m_walking_unset_timer += dtime;
1481 if(m_walking_unset_timer >= 1.0){
1485 m_shooting_unset_timer -= dtime;
1486 if(m_shooting_unset_timer <= 0.0){
1487 if(m_bright_shooting){
1488 u8 li = decode_light(m_last_light);
1489 video::SColor color(255,li,li,li);
1490 bill->setColor(color);
1491 m_bright_shooting = false;
1498 void MobV2CAO::processMessage(const std::string &data)
1500 //infostream<<"MobV2CAO: Got message"<<std::endl;
1501 std::istringstream is(data, std::ios::binary);
1503 u8 cmd = readU8(is);
1509 m_position = readV3F1000(is);
1510 pos_translator.update(m_position);
1512 m_yaw = readF1000(is);
1515 m_walking_unset_timer = 0;
1522 //u16 damage = readU16(is);
1524 /*u8 li = decode_light(m_last_light);
1530 /*video::SColor color(255,255,0,0);
1531 m_node->setColor(color);
1533 m_damage_visual_timer = 0.2;*/
1539 m_shooting_unset_timer = readF1000(is);
1541 m_bright_shooting = readU8(is);
1542 if(m_bright_shooting){
1544 video::SColor color(255,li,li,li);
1545 m_node->setColor(color);
1552 void MobV2CAO::initialize(const std::string &data)
1554 //infostream<<"MobV2CAO: Got init data"<<std::endl;
1557 std::istringstream is(data, std::ios::binary);
1559 u8 version = readU8(is);
1562 infostream<<__FUNCTION_NAME<<": Invalid version"<<std::endl;
1566 std::ostringstream tmp_os(std::ios::binary);
1567 decompressZlib(is, tmp_os);
1568 std::istringstream tmp_is(tmp_os.str(), std::ios::binary);
1569 m_properties->parseConfigLines(tmp_is, "MobArgsEnd");
1571 infostream<<"MobV2CAO::initialize(): got properties:"<<std::endl;
1572 m_properties->writeLines(infostream);
1574 m_properties->setDefault("looks", "dummy_default");
1575 m_properties->setDefault("yaw", "0");
1576 m_properties->setDefault("pos", "(0,0,0)");
1577 m_properties->setDefault("player_hit_damage", "0");
1578 m_properties->setDefault("player_hit_distance", "1.5");
1579 m_properties->setDefault("player_hit_interval", "1.5");
1581 setLooks(m_properties->get("looks"));
1582 m_yaw = m_properties->getFloat("yaw");
1583 m_position = m_properties->getV3F("pos");
1584 m_player_hit_damage = m_properties->getS32("player_hit_damage");
1585 m_player_hit_distance = m_properties->getFloat("player_hit_distance");
1586 m_player_hit_interval = m_properties->getFloat("player_hit_interval");
1588 pos_translator.init(m_position);
1594 bool MobV2CAO::directReportPunch(const std::string &toolname, v3f dir)
1596 video::SColor color(255,255,0,0);
1597 m_node->setColor(color);
1599 m_damage_visual_timer = 0.05;
1601 m_position += dir * BS;
1602 pos_translator.sharpen();
1603 pos_translator.update(m_position);
1609 void MobV2CAO::setLooks(const std::string &looks)
1611 v2f selection_size = v2f(0.4, 0.4) * BS;
1612 float selection_y = 0 * BS;
1614 if(looks == "dungeon_master"){
1615 m_texture_name = "dungeon_master.png";
1616 m_sprite_type = "humanoid_1";
1617 m_sprite_size = v2f(2, 3) * BS;
1618 m_sprite_y = 0.85 * BS;
1619 selection_size = v2f(0.4, 2.6) * BS;
1620 selection_y = -0.4 * BS;
1622 else if(looks == "fireball"){
1623 m_texture_name = "fireball.png";
1624 m_sprite_type = "simple";
1625 m_sprite_size = v2f(1, 1) * BS;
1626 m_simple_anim_frames = 3;
1627 m_simple_anim_frametime = 0.1;
1628 m_lock_full_brightness = true;
1631 m_texture_name = "stone.png";
1632 m_sprite_type = "simple";
1633 m_sprite_size = v2f(1, 1) * BS;
1634 m_simple_anim_frames = 3;
1635 m_simple_anim_frametime = 0.333;
1636 selection_size = v2f(0.4, 0.4) * BS;
1637 selection_y = 0 * BS;
1640 m_selection_box = core::aabbox3d<f32>(
1641 -selection_size.X, selection_y, -selection_size.X,
1642 selection_size.X, selection_y+selection_size.Y,
1650 #include "luaentity_common.h"
1652 class LuaEntityCAO : public ClientActiveObject
1655 core::aabbox3d<f32> m_selection_box;
1656 scene::IMeshSceneNode *m_meshnode;
1657 scene::MyBillboardSceneNode *m_spritenode;
1662 struct LuaEntityProperties *m_prop;
1663 SmoothTranslator pos_translator;
1664 // Spritesheet/animation stuff
1667 bool m_tx_select_horiz_by_yawpitch;
1669 int m_anim_num_frames;
1670 float m_anim_framelength;
1674 LuaEntityCAO(IGameDef *gamedef, ClientEnvironment *env):
1675 ClientActiveObject(0, gamedef, env),
1676 m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.),
1679 m_position(v3f(0,10*BS,0)),
1680 m_velocity(v3f(0,0,0)),
1681 m_acceleration(v3f(0,0,0)),
1683 m_prop(new LuaEntityProperties),
1686 m_tx_select_horiz_by_yawpitch(false),
1688 m_anim_num_frames(1),
1689 m_anim_framelength(0.2),
1693 ClientActiveObject::registerType(getType(), create);
1696 void initialize(const std::string &data)
1698 infostream<<"LuaEntityCAO: Got init data"<<std::endl;
1700 std::istringstream is(data, std::ios::binary);
1702 u8 version = readU8(is);
1707 m_position = readV3F1000(is);
1709 m_yaw = readF1000(is);
1711 std::istringstream prop_is(deSerializeLongString(is), std::ios::binary);
1712 m_prop->deSerialize(prop_is);
1714 infostream<<"m_prop: "<<m_prop->dump()<<std::endl;
1716 m_selection_box = m_prop->collisionbox;
1717 m_selection_box.MinEdge *= BS;
1718 m_selection_box.MaxEdge *= BS;
1720 pos_translator.init(m_position);
1722 m_tx_size.X = 1.0 / m_prop->spritediv.X;
1723 m_tx_size.Y = 1.0 / m_prop->spritediv.Y;
1724 m_tx_basepos.X = m_tx_size.X * m_prop->initial_sprite_basepos.X;
1725 m_tx_basepos.Y = m_tx_size.Y * m_prop->initial_sprite_basepos.Y;
1735 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
1737 return new LuaEntityCAO(gamedef, env);
1742 return ACTIVEOBJECT_TYPE_LUAENTITY;
1744 core::aabbox3d<f32>* getSelectionBox()
1746 return &m_selection_box;
1750 return pos_translator.vect_show;
1753 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
1754 IrrlichtDevice *irr)
1756 if(m_meshnode != NULL || m_spritenode != NULL)
1759 //video::IVideoDriver* driver = smgr->getVideoDriver();
1761 if(m_prop->visual == "sprite"){
1762 infostream<<"LuaEntityCAO::addToScene(): single_sprite"<<std::endl;
1763 m_spritenode = new scene::MyBillboardSceneNode(
1764 smgr->getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1));
1765 m_spritenode->setMaterialTexture(0,
1766 tsrc->getTextureRaw("unknown_block.png"));
1767 m_spritenode->setMaterialFlag(video::EMF_LIGHTING, false);
1768 m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
1769 m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
1770 m_spritenode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
1771 m_spritenode->setColor(video::SColor(255,0,0,0));
1772 m_spritenode->setVisible(false); /* Set visible when brightness is known */
1773 m_spritenode->setSize(m_prop->visual_size*BS);
1775 const float txs = 1.0 / 1;
1776 const float tys = 1.0 / 1;
1777 m_spritenode->setTCoords(0, v2f(txs*1, tys*1));
1778 m_spritenode->setTCoords(1, v2f(txs*1, tys*0));
1779 m_spritenode->setTCoords(2, v2f(txs*0, tys*0));
1780 m_spritenode->setTCoords(3, v2f(txs*0, tys*1));
1782 } else if(m_prop->visual == "cube"){
1783 infostream<<"LuaEntityCAO::addToScene(): cube"<<std::endl;
1784 video::SColor c(255,255,255,255);
1785 video::S3DVertex vertices[24] =
1788 video::S3DVertex(-0.5,+0.5,-0.5, 0,1,0, c, 0,1),
1789 video::S3DVertex(-0.5,+0.5,+0.5, 0,1,0, c, 0,0),
1790 video::S3DVertex(+0.5,+0.5,+0.5, 0,1,0, c, 1,0),
1791 video::S3DVertex(+0.5,+0.5,-0.5, 0,1,0, c, 1,1),
1793 video::S3DVertex(-0.5,-0.5,-0.5, 0,-1,0, c, 0,0),
1794 video::S3DVertex(+0.5,-0.5,-0.5, 0,-1,0, c, 1,0),
1795 video::S3DVertex(+0.5,-0.5,+0.5, 0,-1,0, c, 1,1),
1796 video::S3DVertex(-0.5,-0.5,+0.5, 0,-1,0, c, 0,1),
1798 video::S3DVertex(+0.5,-0.5,-0.5, 1,0,0, c, 0,1),
1799 video::S3DVertex(+0.5,+0.5,-0.5, 1,0,0, c, 0,0),
1800 video::S3DVertex(+0.5,+0.5,+0.5, 1,0,0, c, 1,0),
1801 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, 1,1),
1804 video::S3DVertex(-0.5,-0.5,+0.5, -1,0,0, c, 0,1),
1805 video::S3DVertex(-0.5,+0.5,+0.5, -1,0,0, c, 0,0),
1806 video::S3DVertex(-0.5,+0.5,-0.5, -1,0,0, c, 1,0),
1808 video::S3DVertex(-0.5,-0.5,+0.5, 0,0,1, c, 1,1),
1809 video::S3DVertex(+0.5,-0.5,+0.5, 0,0,1, c, 0,1),
1810 video::S3DVertex(+0.5,+0.5,+0.5, 0,0,1, c, 0,0),
1811 video::S3DVertex(-0.5,+0.5,+0.5, 0,0,1, c, 1,0),
1813 video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1),
1814 video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0),
1815 video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0),
1816 video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1),
1819 for(u32 i=0; i<24; ++i){
1820 vertices[i].Pos *= BS;
1821 vertices[i].Pos.Y *= m_prop->visual_size.Y;
1822 vertices[i].Pos.X *= m_prop->visual_size.X;
1823 vertices[i].Pos.Z *= m_prop->visual_size.X;
1826 u16 indices[6] = {0,1,2,2,3,0};
1828 scene::SMesh* mesh = new scene::SMesh();
1829 for (u32 i=0; i<6; ++i)
1831 scene::IMeshBuffer* buf = new scene::SMeshBuffer();
1832 buf->append(vertices + 4 * i, 4, indices, 6);
1833 buf->recalculateBoundingBox();
1834 mesh->addMeshBuffer(buf);
1837 mesh->recalculateBoundingBox();
1839 m_meshnode = smgr->addMeshSceneNode(mesh, NULL);
1841 m_meshnode->setMesh(mesh);
1842 m_meshnode->setScale(v3f(1));
1843 // Will be shown when we know the brightness
1844 m_meshnode->setVisible(false);
1846 infostream<<"LuaEntityCAO::addToScene(): \""<<m_prop->visual
1847 <<"\" not supported"<<std::endl;
1853 void removeFromScene()
1856 m_meshnode->remove();
1860 m_spritenode->remove();
1861 m_spritenode = NULL;
1865 void updateLight(u8 light_at_pos)
1867 u8 li = decode_light(light_at_pos);
1868 video::SColor color(255,li,li,li);
1870 setMeshColor(m_meshnode->getMesh(), color);
1871 m_meshnode->setVisible(true);
1874 m_spritenode->setColor(color);
1875 m_spritenode->setVisible(true);
1879 v3s16 getLightPosition()
1881 return floatToInt(m_position, BS);
1884 void updateNodePos()
1887 m_meshnode->setPosition(pos_translator.vect_show);
1890 m_spritenode->setPosition(pos_translator.vect_show);
1894 void step(float dtime, ClientEnvironment *env)
1896 if(m_prop->physical){
1897 core::aabbox3d<f32> box = m_prop->collisionbox;
1900 collisionMoveResult moveresult;
1901 f32 pos_max_d = BS*0.25; // Distance per iteration
1902 v3f p_pos = m_position;
1903 v3f p_velocity = m_velocity;
1904 IGameDef *gamedef = env->getGameDef();
1905 moveresult = collisionMovePrecise(&env->getMap(), gamedef,
1906 pos_max_d, box, dtime, p_pos, p_velocity);
1909 m_velocity = p_velocity;
1911 bool is_end_position = moveresult.collides;
1912 pos_translator.update(m_position, is_end_position, dtime);
1913 pos_translator.translate(dtime);
1916 m_velocity += dtime * m_acceleration;
1918 m_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration;
1919 m_velocity += dtime * m_acceleration;
1920 pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time);
1921 pos_translator.translate(dtime);
1925 m_anim_timer += dtime;
1926 if(m_anim_timer >= m_anim_framelength){
1927 m_anim_timer -= m_anim_framelength;
1929 if(m_anim_frame >= m_anim_num_frames)
1936 void updateTexturePos()
1939 scene::ICameraSceneNode* camera =
1940 m_spritenode->getSceneManager()->getActiveCamera();
1943 v3f cam_to_entity = m_spritenode->getAbsolutePosition()
1944 - camera->getAbsolutePosition();
1945 cam_to_entity.normalize();
1947 int row = m_tx_basepos.Y;
1948 int col = m_tx_basepos.X;
1950 if(m_tx_select_horiz_by_yawpitch)
1952 if(cam_to_entity.Y > 0.75)
1954 else if(cam_to_entity.Y < -0.75)
1957 float mob_dir = atan2(cam_to_entity.Z, cam_to_entity.X) / PI * 180.;
1958 float dir = mob_dir - m_yaw;
1959 dir = wrapDegrees_180(dir);
1960 //infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
1961 if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
1963 else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
1965 else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
1967 else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
1974 // Animation goes downwards
1975 row += m_anim_frame;
1977 float txs = m_tx_size.X;
1978 float tys = m_tx_size.Y;
1979 m_spritenode->setTCoords(0, v2f(txs*(1+col), tys*(1+row)));
1980 m_spritenode->setTCoords(1, v2f(txs*(1+col), tys*(0+row)));
1981 m_spritenode->setTCoords(2, v2f(txs*(0+col), tys*(0+row)));
1982 m_spritenode->setTCoords(3, v2f(txs*(0+col), tys*(1+row)));
1986 void updateTextures(const std::string &mod)
1988 ITextureSource *tsrc = m_gamedef->tsrc();
1991 std::string texturestring = "unknown_block.png";
1992 if(m_prop->textures.size() >= 1)
1993 texturestring = m_prop->textures[0];
1994 texturestring += mod;
1995 m_spritenode->setMaterialTexture(0,
1996 tsrc->getTextureRaw(texturestring));
1999 for (u32 i = 0; i < 6; ++i)
2001 std::string texturestring = "unknown_block.png";
2002 if(m_prop->textures.size() > i)
2003 texturestring = m_prop->textures[i];
2004 texturestring += mod;
2005 AtlasPointer ap = tsrc->getTexture(texturestring);
2007 // Get the tile texture and atlas transformation
2008 video::ITexture* atlas = ap.atlas;
2012 // Set material flags and texture
2013 video::SMaterial& material = m_meshnode->getMaterial(i);
2014 material.setFlag(video::EMF_LIGHTING, false);
2015 material.setFlag(video::EMF_BILINEAR_FILTER, false);
2016 material.setTexture(0, atlas);
2017 material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
2018 material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
2023 void processMessage(const std::string &data)
2025 //infostream<<"LuaEntityCAO: Got message"<<std::endl;
2026 std::istringstream is(data, std::ios::binary);
2028 u8 cmd = readU8(is);
2029 if(cmd == 0) // update position
2032 bool do_interpolate = readU8(is);
2034 m_position = readV3F1000(is);
2036 m_velocity = readV3F1000(is);
2038 m_acceleration = readV3F1000(is);
2040 m_yaw = readF1000(is);
2041 // is_end_position (for interpolation)
2042 bool is_end_position = readU8(is);
2044 float update_interval = readF1000(is);
2047 if(!m_prop->physical)
2048 pos_translator.update(m_position, is_end_position, update_interval);
2050 pos_translator.init(m_position);
2054 else if(cmd == 1) // set texture modification
2056 std::string mod = deSerializeString(is);
2057 updateTextures(mod);
2059 else if(cmd == 2) // set sprite
2061 v2s16 p = readV2S16(is);
2062 int num_frames = readU16(is);
2063 float framelength = readF1000(is);
2064 bool select_horiz_by_yawpitch = readU8(is);
2067 m_anim_num_frames = num_frames;
2068 m_anim_framelength = framelength;
2069 m_tx_select_horiz_by_yawpitch = select_horiz_by_yawpitch;
2077 LuaEntityCAO proto_LuaEntityCAO(NULL, NULL);
2083 class PlayerCAO : public ClientActiveObject
2086 core::aabbox3d<f32> m_selection_box;
2087 scene::IMeshSceneNode *m_node;
2088 scene::ITextSceneNode* m_text;
2092 SmoothTranslator pos_translator;
2093 bool m_is_local_player;
2094 LocalPlayer *m_local_player;
2095 float m_damage_visual_timer;
2098 PlayerCAO(IGameDef *gamedef, ClientEnvironment *env):
2099 ClientActiveObject(0, gamedef, env),
2100 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.0,BS/3.),
2103 m_position(v3f(0,10*BS,0)),
2105 m_is_local_player(false),
2106 m_local_player(NULL),
2107 m_damage_visual_timer(0)
2110 ClientActiveObject::registerType(getType(), create);
2113 void initialize(const std::string &data)
2115 infostream<<"PlayerCAO: Got init data"<<std::endl;
2117 std::istringstream is(data, std::ios::binary);
2119 u8 version = readU8(is);
2124 m_name = deSerializeString(is);
2126 m_position = readV3F1000(is);
2128 m_yaw = readF1000(is);
2130 pos_translator.init(m_position);
2132 Player *player = m_env->getPlayer(m_name.c_str());
2133 if(player && player->isLocal()){
2134 m_is_local_player = true;
2135 m_local_player = (LocalPlayer*)player;
2145 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
2147 return new PlayerCAO(gamedef, env);
2152 return ACTIVEOBJECT_TYPE_PLAYER;
2154 core::aabbox3d<f32>* getSelectionBox()
2156 if(m_is_local_player)
2158 return &m_selection_box;
2162 return pos_translator.vect_show;
2165 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
2166 IrrlichtDevice *irr)
2170 if(m_is_local_player)
2173 //video::IVideoDriver* driver = smgr->getVideoDriver();
2174 gui::IGUIEnvironment* gui = irr->getGUIEnvironment();
2176 scene::SMesh *mesh = new scene::SMesh();
2178 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
2179 video::SColor c(255,255,255,255);
2180 video::S3DVertex vertices[4] =
2182 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
2183 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
2184 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
2185 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
2187 u16 indices[] = {0,1,2,2,3,0};
2188 buf->append(vertices, 4, indices, 6);
2190 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
2191 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
2192 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
2193 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
2195 mesh->addMeshBuffer(buf);
2199 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
2200 video::SColor c(255,255,255,255);
2201 video::S3DVertex vertices[4] =
2203 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
2204 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
2205 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
2206 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
2208 u16 indices[] = {0,1,2,2,3,0};
2209 buf->append(vertices, 4, indices, 6);
2211 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
2212 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
2213 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
2214 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
2216 mesh->addMeshBuffer(buf);
2219 m_node = smgr->addMeshSceneNode(mesh, NULL);
2221 // Set it to use the materials of the meshbuffers directly.
2222 // This is needed for changing the texture in the future
2223 m_node->setReadOnlyMaterials(true);
2226 // Add a text node for showing the name
2227 std::wstring wname = narrow_to_wide(m_name);
2228 m_text = smgr->addTextSceneNode(gui->getBuiltInFont(),
2229 wname.c_str(), video::SColor(255,255,255,255), m_node);
2230 m_text->setPosition(v3f(0, (f32)BS*2.1, 0));
2236 void removeFromScene()
2245 void updateLight(u8 light_at_pos)
2250 m_node->setVisible(true);
2252 u8 li = decode_light(light_at_pos);
2253 video::SColor color(255,li,li,li);
2254 setMeshColor(m_node->getMesh(), color);
2257 v3s16 getLightPosition()
2259 return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
2262 void updateNodePos()
2267 m_node->setPosition(pos_translator.vect_show);
2269 v3f rot = m_node->getRotation();
2271 m_node->setRotation(rot);
2274 void step(float dtime, ClientEnvironment *env)
2276 pos_translator.translate(dtime);
2279 if(m_damage_visual_timer > 0){
2280 m_damage_visual_timer -= dtime;
2281 if(m_damage_visual_timer <= 0){
2287 void processMessage(const std::string &data)
2289 //infostream<<"PlayerCAO: Got message"<<std::endl;
2290 std::istringstream is(data, std::ios::binary);
2292 u8 cmd = readU8(is);
2293 if(cmd == 0) // update position
2296 m_position = readV3F1000(is);
2298 m_yaw = readF1000(is);
2300 pos_translator.update(m_position, false);
2304 else if(cmd == 1) // punched
2307 s16 damage = readS16(is);
2309 if(m_is_local_player)
2310 m_env->damageLocalPlayer(damage, false);
2312 m_damage_visual_timer = 0.5;
2313 updateTextures("^[brighten");
2317 void updateTextures(const std::string &mod)
2321 ITextureSource *tsrc = m_gamedef->tsrc();
2322 scene::IMesh *mesh = m_node->getMesh();
2325 std::string tname = "player.png";
2327 scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
2328 buf->getMaterial().setTexture(0,
2329 tsrc->getTextureRaw(tname));
2332 std::string tname = "player_back.png";
2334 scene::IMeshBuffer *buf = mesh->getMeshBuffer(1);
2335 buf->getMaterial().setTexture(0,
2336 tsrc->getTextureRaw(tname));
2343 PlayerCAO proto_PlayerCAO(NULL, NULL);