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;}
187 std::string infoText()
191 core::aabbox3d<f32> m_selection_box;
192 scene::IMeshSceneNode *m_node;
194 std::string m_inventorystring;
195 std::string m_infotext;
202 class RatCAO : public ClientActiveObject
205 RatCAO(IGameDef *gamedef, ClientEnvironment *env);
210 return ACTIVEOBJECT_TYPE_RAT;
213 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
215 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
216 IrrlichtDevice *irr);
217 void removeFromScene();
218 void updateLight(u8 light_at_pos);
219 v3s16 getLightPosition();
220 void updateNodePos();
222 void step(float dtime, ClientEnvironment *env);
224 void processMessage(const std::string &data);
226 void initialize(const std::string &data);
228 core::aabbox3d<f32>* getSelectionBox()
229 {return &m_selection_box;}
231 {return pos_translator.vect_show;}
232 //{return m_position;}
235 core::aabbox3d<f32> m_selection_box;
236 scene::IMeshSceneNode *m_node;
239 SmoothTranslator pos_translator;
246 class Oerkki1CAO : public ClientActiveObject
249 Oerkki1CAO(IGameDef *gamedef, ClientEnvironment *env);
250 virtual ~Oerkki1CAO();
254 return ACTIVEOBJECT_TYPE_OERKKI1;
257 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
259 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
260 IrrlichtDevice *irr);
261 void removeFromScene();
262 void updateLight(u8 light_at_pos);
263 v3s16 getLightPosition();
264 void updateNodePos();
266 void step(float dtime, ClientEnvironment *env);
268 void processMessage(const std::string &data);
270 void initialize(const std::string &data);
272 core::aabbox3d<f32>* getSelectionBox()
273 {return &m_selection_box;}
275 {return pos_translator.vect_show;}
276 //{return m_position;}
278 // If returns true, punch will not be sent to the server
279 bool directReportPunch(const std::string &toolname, v3f dir);
282 IntervalLimiter m_attack_interval;
283 core::aabbox3d<f32> m_selection_box;
284 scene::IMeshSceneNode *m_node;
287 SmoothTranslator pos_translator;
288 float m_damage_visual_timer;
289 bool m_damage_texture_enabled;
296 class FireflyCAO : public ClientActiveObject
299 FireflyCAO(IGameDef *gamedef, ClientEnvironment *env);
300 virtual ~FireflyCAO();
304 return ACTIVEOBJECT_TYPE_FIREFLY;
307 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
309 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
310 IrrlichtDevice *irr);
311 void removeFromScene();
312 void updateLight(u8 light_at_pos);
313 v3s16 getLightPosition();
314 void updateNodePos();
316 void step(float dtime, ClientEnvironment *env);
318 void processMessage(const std::string &data);
320 void initialize(const std::string &data);
322 core::aabbox3d<f32>* getSelectionBox()
323 {return &m_selection_box;}
328 core::aabbox3d<f32> m_selection_box;
329 scene::IMeshSceneNode *m_node;
332 SmoothTranslator pos_translator;
339 class MobV2CAO : public ClientActiveObject
342 MobV2CAO(IGameDef *gamedef, ClientEnvironment *env);
347 return ACTIVEOBJECT_TYPE_MOBV2;
350 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
352 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
353 IrrlichtDevice *irr);
354 void removeFromScene();
355 void updateLight(u8 light_at_pos);
356 v3s16 getLightPosition();
357 void updateNodePos();
359 void step(float dtime, ClientEnvironment *env);
361 void processMessage(const std::string &data);
363 void initialize(const std::string &data);
365 core::aabbox3d<f32>* getSelectionBox()
366 {return &m_selection_box;}
368 {return pos_translator.vect_show;}
369 //{return m_position;}
370 bool doShowSelectionBox(){return false;}
372 // If returns true, punch will not be sent to the server
373 bool directReportPunch(const std::string &toolname, v3f dir);
376 void setLooks(const std::string &looks);
378 IntervalLimiter m_attack_interval;
379 core::aabbox3d<f32> m_selection_box;
380 scene::MyBillboardSceneNode *m_node;
382 std::string m_texture_name;
384 SmoothTranslator pos_translator;
386 float m_walking_unset_timer;
389 float m_damage_visual_timer;
392 float m_shooting_unset_timer;
395 bool m_bright_shooting;
396 std::string m_sprite_type;
397 int m_simple_anim_frames;
398 float m_simple_anim_frametime;
399 bool m_lock_full_brightness;
400 int m_player_hit_damage;
401 float m_player_hit_distance;
402 float m_player_hit_interval;
403 float m_player_hit_timer;
405 Settings *m_properties;
413 TestCAO proto_TestCAO(NULL, NULL);
415 TestCAO::TestCAO(IGameDef *gamedef, ClientEnvironment *env):
416 ClientActiveObject(0, gamedef, env),
418 m_position(v3f(0,10*BS,0))
420 ClientActiveObject::registerType(getType(), create);
427 ClientActiveObject* TestCAO::create(IGameDef *gamedef, ClientEnvironment *env)
429 return new TestCAO(gamedef, env);
432 void TestCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
438 //video::IVideoDriver* driver = smgr->getVideoDriver();
440 scene::SMesh *mesh = new scene::SMesh();
441 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
442 video::SColor c(255,255,255,255);
443 video::S3DVertex vertices[4] =
445 video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
446 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
447 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
448 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),
450 u16 indices[] = {0,1,2,2,3,0};
451 buf->append(vertices, 4, indices, 6);
453 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
454 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
455 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("rat.png"));
456 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
457 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
458 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
460 mesh->addMeshBuffer(buf);
462 m_node = smgr->addMeshSceneNode(mesh, NULL);
467 void TestCAO::removeFromScene()
476 void TestCAO::updateLight(u8 light_at_pos)
480 v3s16 TestCAO::getLightPosition()
482 return floatToInt(m_position, BS);
485 void TestCAO::updateNodePos()
490 m_node->setPosition(m_position);
491 //m_node->setRotation(v3f(0, 45, 0));
494 void TestCAO::step(float dtime, ClientEnvironment *env)
498 v3f rot = m_node->getRotation();
499 //infostream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
500 rot.Y += dtime * 180;
501 m_node->setRotation(rot);
505 void TestCAO::processMessage(const std::string &data)
507 infostream<<"TestCAO: Got data: "<<data<<std::endl;
508 std::istringstream is(data, std::ios::binary);
526 #include "inventory.h"
529 ItemCAO proto_ItemCAO(NULL, NULL);
531 ItemCAO::ItemCAO(IGameDef *gamedef, ClientEnvironment *env):
532 ClientActiveObject(0, gamedef, env),
533 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.),
535 m_position(v3f(0,10*BS,0))
539 ClientActiveObject::registerType(getType(), create);
547 ClientActiveObject* ItemCAO::create(IGameDef *gamedef, ClientEnvironment *env)
549 return new ItemCAO(gamedef, env);
552 void ItemCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
558 //video::IVideoDriver* driver = smgr->getVideoDriver();
560 scene::SMesh *mesh = new scene::SMesh();
561 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
562 video::SColor c(255,255,255,255);
563 video::S3DVertex vertices[4] =
565 /*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
566 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
567 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
568 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/
569 video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1),
570 video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1),
571 video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0),
572 video::S3DVertex(BS/3.,0+BS*2./3.,0, 0,0,0, c, 0,0),
574 u16 indices[] = {0,1,2,2,3,0};
575 buf->append(vertices, 4, indices, 6);
577 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
578 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
579 //buf->getMaterial().setTexture(0, NULL);
580 // Initialize with the stick texture
581 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("stick.png"));
582 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
583 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
584 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
586 mesh->addMeshBuffer(buf);
588 m_node = smgr->addMeshSceneNode(mesh, NULL);
590 // Set it to use the materials of the meshbuffers directly.
591 // This is needed for changing the texture in the future
592 m_node->setReadOnlyMaterials(true);
599 // Create an inventory item to see what is its image
600 std::istringstream is(m_inventorystring, std::ios_base::binary);
601 video::ITexture *texture = NULL;
603 InventoryItem *item = NULL;
604 item = InventoryItem::deSerialize(is, m_gamedef);
605 infostream<<__FUNCTION_NAME<<": m_inventorystring=\""
606 <<m_inventorystring<<"\" -> item="<<item
610 texture = item->getImage();
614 catch(SerializationError &e)
616 infostream<<"WARNING: "<<__FUNCTION_NAME
617 <<": error deSerializing inventorystring \""
618 <<m_inventorystring<<"\""<<std::endl;
621 // Set meshbuffer texture
622 buf->getMaterial().setTexture(0, texture);
625 void ItemCAO::removeFromScene()
634 void ItemCAO::updateLight(u8 light_at_pos)
639 u8 li = decode_light(light_at_pos);
640 video::SColor color(255,li,li,li);
641 setMeshColor(m_node->getMesh(), color);
644 v3s16 ItemCAO::getLightPosition()
646 return floatToInt(m_position, BS);
649 void ItemCAO::updateNodePos()
654 m_node->setPosition(m_position);
657 void ItemCAO::step(float dtime, ClientEnvironment *env)
661 /*v3f rot = m_node->getRotation();
662 rot.Y += dtime * 120;
663 m_node->setRotation(rot);*/
664 LocalPlayer *player = env->getLocalPlayer();
666 v3f rot = m_node->getRotation();
667 rot.Y = 180.0 - (player->getYaw());
668 m_node->setRotation(rot);
672 void ItemCAO::processMessage(const std::string &data)
674 //infostream<<"ItemCAO: Got message"<<std::endl;
675 std::istringstream is(data, std::ios::binary);
681 m_position = readV3F1000(is);
686 void ItemCAO::initialize(const std::string &data)
688 infostream<<"ItemCAO: Got init data"<<std::endl;
691 std::istringstream is(data, std::ios::binary);
693 u8 version = readU8(is);
698 m_position = readV3F1000(is);
700 m_inventorystring = deSerializeString(is);
706 Set infotext to item name if item cannot be deserialized
709 InventoryItem *item = NULL;
710 item = InventoryItem::deSerialize(m_inventorystring, m_gamedef);
713 m_infotext = "Unknown item: '" + m_inventorystring + "'";
717 catch(SerializationError &e)
719 m_infotext = "Unknown item: '" + m_inventorystring + "'";
727 #include "inventory.h"
730 RatCAO proto_RatCAO(NULL, NULL);
732 RatCAO::RatCAO(IGameDef *gamedef, ClientEnvironment *env):
733 ClientActiveObject(0, gamedef, env),
734 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
736 m_position(v3f(0,10*BS,0)),
739 ClientActiveObject::registerType(getType(), create);
746 ClientActiveObject* RatCAO::create(IGameDef *gamedef, ClientEnvironment *env)
748 return new RatCAO(gamedef, env);
751 void RatCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
757 //video::IVideoDriver* driver = smgr->getVideoDriver();
759 scene::SMesh *mesh = new scene::SMesh();
760 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
761 video::SColor c(255,255,255,255);
762 video::S3DVertex vertices[4] =
764 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
765 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
766 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
767 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
769 u16 indices[] = {0,1,2,2,3,0};
770 buf->append(vertices, 4, indices, 6);
772 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
773 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
774 //buf->getMaterial().setTexture(0, NULL);
775 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("rat.png"));
776 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
777 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
778 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
780 mesh->addMeshBuffer(buf);
782 m_node = smgr->addMeshSceneNode(mesh, NULL);
784 // Set it to use the materials of the meshbuffers directly.
785 // This is needed for changing the texture in the future
786 m_node->setReadOnlyMaterials(true);
790 void RatCAO::removeFromScene()
799 void RatCAO::updateLight(u8 light_at_pos)
804 u8 li = decode_light(light_at_pos);
805 video::SColor color(255,li,li,li);
806 setMeshColor(m_node->getMesh(), color);
809 v3s16 RatCAO::getLightPosition()
811 return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
814 void RatCAO::updateNodePos()
819 //m_node->setPosition(m_position);
820 m_node->setPosition(pos_translator.vect_show);
822 v3f rot = m_node->getRotation();
823 rot.Y = 180.0 - m_yaw;
824 m_node->setRotation(rot);
827 void RatCAO::step(float dtime, ClientEnvironment *env)
829 pos_translator.translate(dtime);
833 void RatCAO::processMessage(const std::string &data)
835 //infostream<<"RatCAO: Got message"<<std::endl;
836 std::istringstream is(data, std::ios::binary);
842 m_position = readV3F1000(is);
843 pos_translator.update(m_position);
845 m_yaw = readF1000(is);
850 void RatCAO::initialize(const std::string &data)
852 //infostream<<"RatCAO: Got init data"<<std::endl;
855 std::istringstream is(data, std::ios::binary);
857 u8 version = readU8(is);
862 m_position = readV3F1000(is);
863 pos_translator.init(m_position);
873 #include "inventory.h"
876 Oerkki1CAO proto_Oerkki1CAO(NULL, NULL);
878 Oerkki1CAO::Oerkki1CAO(IGameDef *gamedef, ClientEnvironment *env):
879 ClientActiveObject(0, gamedef, env),
880 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.),
882 m_position(v3f(0,10*BS,0)),
884 m_damage_visual_timer(0),
885 m_damage_texture_enabled(false)
887 ClientActiveObject::registerType(getType(), create);
890 Oerkki1CAO::~Oerkki1CAO()
894 ClientActiveObject* Oerkki1CAO::create(IGameDef *gamedef, ClientEnvironment *env)
896 return new Oerkki1CAO(gamedef, env);
899 void Oerkki1CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
905 //video::IVideoDriver* driver = smgr->getVideoDriver();
907 scene::SMesh *mesh = new scene::SMesh();
908 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
909 video::SColor c(255,255,255,255);
910 video::S3DVertex vertices[4] =
912 video::S3DVertex(-BS/2-BS,0,0, 0,0,0, c, 0,1),
913 video::S3DVertex(BS/2+BS,0,0, 0,0,0, c, 1,1),
914 video::S3DVertex(BS/2+BS,BS*2,0, 0,0,0, c, 1,0),
915 video::S3DVertex(-BS/2-BS,BS*2,0, 0,0,0, c, 0,0),
917 u16 indices[] = {0,1,2,2,3,0};
918 buf->append(vertices, 4, indices, 6);
920 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
921 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
922 //buf->getMaterial().setTexture(0, NULL);
923 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("oerkki1.png"));
924 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
925 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
926 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
928 mesh->addMeshBuffer(buf);
930 m_node = smgr->addMeshSceneNode(mesh, NULL);
932 // Set it to use the materials of the meshbuffers directly.
933 // This is needed for changing the texture in the future
934 m_node->setReadOnlyMaterials(true);
938 void Oerkki1CAO::removeFromScene()
947 void Oerkki1CAO::updateLight(u8 light_at_pos)
952 if(light_at_pos <= 2)
954 m_node->setVisible(false);
958 m_node->setVisible(true);
960 u8 li = decode_light(light_at_pos);
961 video::SColor color(255,li,li,li);
962 setMeshColor(m_node->getMesh(), color);
965 v3s16 Oerkki1CAO::getLightPosition()
967 return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
970 void Oerkki1CAO::updateNodePos()
975 //m_node->setPosition(m_position);
976 m_node->setPosition(pos_translator.vect_show);
978 v3f rot = m_node->getRotation();
979 rot.Y = 180.0 - m_yaw + 90.0;
980 m_node->setRotation(rot);
983 void Oerkki1CAO::step(float dtime, ClientEnvironment *env)
985 ITextureSource *tsrc = m_gamedef->tsrc();
987 pos_translator.translate(dtime);
990 LocalPlayer *player = env->getLocalPlayer();
993 v3f playerpos = player->getPosition();
994 v2f playerpos_2d(playerpos.X,playerpos.Z);
995 v2f objectpos_2d(m_position.X,m_position.Z);
997 if(fabs(m_position.Y - playerpos.Y) < 1.5*BS &&
998 objectpos_2d.getDistanceFrom(playerpos_2d) < 1.5*BS)
1000 if(m_attack_interval.step(dtime, 0.5))
1002 env->damageLocalPlayer(2);
1006 if(m_damage_visual_timer > 0)
1008 if(!m_damage_texture_enabled)
1010 // Enable damage texture
1013 /*video::IVideoDriver* driver =
1014 m_node->getSceneManager()->getVideoDriver();*/
1016 scene::IMesh *mesh = m_node->getMesh();
1020 u16 mc = mesh->getMeshBufferCount();
1021 for(u16 j=0; j<mc; j++)
1023 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
1024 buf->getMaterial().setTexture(0,
1025 tsrc->getTextureRaw("oerkki1_damaged.png"));
1028 m_damage_texture_enabled = true;
1030 m_damage_visual_timer -= dtime;
1034 if(m_damage_texture_enabled)
1036 // Disable damage texture
1039 /*video::IVideoDriver* driver =
1040 m_node->getSceneManager()->getVideoDriver();*/
1042 scene::IMesh *mesh = m_node->getMesh();
1046 u16 mc = mesh->getMeshBufferCount();
1047 for(u16 j=0; j<mc; j++)
1049 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
1050 buf->getMaterial().setTexture(0,
1051 tsrc->getTextureRaw("oerkki1.png"));
1054 m_damage_texture_enabled = false;
1059 void Oerkki1CAO::processMessage(const std::string &data)
1061 //infostream<<"Oerkki1CAO: Got message"<<std::endl;
1062 std::istringstream is(data, std::ios::binary);
1064 u8 cmd = readU8(is);
1068 m_position = readV3F1000(is);
1069 pos_translator.update(m_position);
1071 m_yaw = readF1000(is);
1076 //u16 damage = readU8(is);
1077 m_damage_visual_timer = 1.0;
1081 void Oerkki1CAO::initialize(const std::string &data)
1083 //infostream<<"Oerkki1CAO: Got init data"<<std::endl;
1086 std::istringstream is(data, std::ios::binary);
1088 u8 version = readU8(is);
1093 m_position = readV3F1000(is);
1094 pos_translator.init(m_position);
1100 bool Oerkki1CAO::directReportPunch(const std::string &toolname, v3f dir)
1102 m_damage_visual_timer = 1.0;
1104 m_position += dir * BS;
1105 pos_translator.sharpen();
1106 pos_translator.update(m_position);
1117 FireflyCAO proto_FireflyCAO(NULL, NULL);
1119 FireflyCAO::FireflyCAO(IGameDef *gamedef, ClientEnvironment *env):
1120 ClientActiveObject(0, gamedef, env),
1121 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
1123 m_position(v3f(0,10*BS,0)),
1126 ClientActiveObject::registerType(getType(), create);
1129 FireflyCAO::~FireflyCAO()
1133 ClientActiveObject* FireflyCAO::create(IGameDef *gamedef, ClientEnvironment *env)
1135 return new FireflyCAO(gamedef, env);
1138 void FireflyCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
1139 IrrlichtDevice *irr)
1144 //video::IVideoDriver* driver = smgr->getVideoDriver();
1146 scene::SMesh *mesh = new scene::SMesh();
1147 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
1148 video::SColor c(255,255,255,255);
1149 video::S3DVertex vertices[4] =
1151 video::S3DVertex(0,0,0, 0,0,0, c, 0,1),
1152 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
1153 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
1154 video::S3DVertex(0,BS/2,0, 0,0,0, c, 0,0),
1156 u16 indices[] = {0,1,2,2,3,0};
1157 buf->append(vertices, 4, indices, 6);
1159 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
1160 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
1161 //buf->getMaterial().setTexture(0, NULL);
1162 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("firefly.png"));
1163 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
1164 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
1165 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
1167 mesh->addMeshBuffer(buf);
1169 m_node = smgr->addMeshSceneNode(mesh, NULL);
1171 // Set it to use the materials of the meshbuffers directly.
1172 // This is needed for changing the texture in the future
1173 m_node->setReadOnlyMaterials(true);
1177 void FireflyCAO::removeFromScene()
1186 void FireflyCAO::updateLight(u8 light_at_pos)
1192 video::SColor color(255,li,li,li);
1193 setMeshColor(m_node->getMesh(), color);
1196 v3s16 FireflyCAO::getLightPosition()
1198 return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
1201 void FireflyCAO::updateNodePos()
1206 //m_node->setPosition(m_position);
1207 m_node->setPosition(pos_translator.vect_show);
1209 v3f rot = m_node->getRotation();
1210 rot.Y = 180.0 - m_yaw;
1211 m_node->setRotation(rot);
1214 void FireflyCAO::step(float dtime, ClientEnvironment *env)
1216 pos_translator.translate(dtime);
1220 void FireflyCAO::processMessage(const std::string &data)
1222 //infostream<<"FireflyCAO: Got message"<<std::endl;
1223 std::istringstream is(data, std::ios::binary);
1225 u8 cmd = readU8(is);
1229 m_position = readV3F1000(is);
1230 pos_translator.update(m_position);
1232 m_yaw = readF1000(is);
1237 void FireflyCAO::initialize(const std::string &data)
1239 //infostream<<"FireflyCAO: Got init data"<<std::endl;
1242 std::istringstream is(data, std::ios::binary);
1244 u8 version = readU8(is);
1249 m_position = readV3F1000(is);
1250 pos_translator.init(m_position);
1261 MobV2CAO proto_MobV2CAO(NULL, NULL);
1263 MobV2CAO::MobV2CAO(IGameDef *gamedef, ClientEnvironment *env):
1264 ClientActiveObject(0, gamedef, env),
1265 m_selection_box(-0.4*BS,-0.4*BS,-0.4*BS, 0.4*BS,0.8*BS,0.4*BS),
1267 m_position(v3f(0,10*BS,0)),
1270 m_walking_unset_timer(0),
1273 m_damage_visual_timer(0),
1276 m_shooting_unset_timer(0),
1277 m_sprite_size(BS,BS),
1279 m_bright_shooting(false),
1280 m_lock_full_brightness(false),
1281 m_player_hit_timer(0)
1283 ClientActiveObject::registerType(getType(), create);
1285 m_properties = new Settings;
1288 MobV2CAO::~MobV2CAO()
1290 delete m_properties;
1293 ClientActiveObject* MobV2CAO::create(IGameDef *gamedef, ClientEnvironment *env)
1295 return new MobV2CAO(gamedef, env);
1298 void MobV2CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
1299 IrrlichtDevice *irr)
1304 /*infostream<<"MobV2CAO::addToScene using texture_name="<<
1305 m_texture_name<<std::endl;*/
1306 std::string texture_string = m_texture_name +
1307 "^[makealpha:128,0,0^[makealpha:128,128,0";
1309 scene::MyBillboardSceneNode *bill = new scene::MyBillboardSceneNode(
1310 smgr->getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1));
1311 bill->setMaterialTexture(0, tsrc->getTextureRaw(texture_string));
1312 bill->setMaterialFlag(video::EMF_LIGHTING, false);
1313 bill->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
1314 bill->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
1315 bill->setMaterialFlag(video::EMF_FOG_ENABLE, true);
1316 bill->setColor(video::SColor(255,0,0,0));
1317 bill->setVisible(false); /* Set visible when brightness is known */
1318 bill->setSize(m_sprite_size);
1319 if(m_sprite_type == "humanoid_1"){
1320 const float txp = 1./192;
1321 const float txs = txp*32;
1322 const float typ = 1./240;
1323 const float tys = typ*48;
1324 bill->setTCoords(0, v2f(txs*1, tys*1));
1325 bill->setTCoords(1, v2f(txs*1, tys*0));
1326 bill->setTCoords(2, v2f(txs*0, tys*0));
1327 bill->setTCoords(3, v2f(txs*0, tys*1));
1328 } else if(m_sprite_type == "simple"){
1329 const float txs = 1.0;
1330 const float tys = 1.0 / m_simple_anim_frames;
1331 bill->setTCoords(0, v2f(txs*1, tys*1));
1332 bill->setTCoords(1, v2f(txs*1, tys*0));
1333 bill->setTCoords(2, v2f(txs*0, tys*0));
1334 bill->setTCoords(3, v2f(txs*0, tys*1));
1336 infostream<<"MobV2CAO: Unknown sprite type \""<<m_sprite_type<<"\""
1345 void MobV2CAO::removeFromScene()
1355 void MobV2CAO::updateLight(u8 light_at_pos)
1357 if(m_lock_full_brightness)
1360 m_last_light = light_at_pos;
1365 if(m_damage_visual_timer > 0)
1368 if(m_shooting && m_bright_shooting)
1371 /*if(light_at_pos <= 2){
1372 m_node->setVisible(false);
1376 m_node->setVisible(true);
1378 u8 li = decode_light(light_at_pos);
1379 video::SColor color(255,li,li,li);
1380 m_node->setColor(color);
1383 v3s16 MobV2CAO::getLightPosition()
1385 return floatToInt(m_position+v3f(0,0,0), BS);
1388 void MobV2CAO::updateNodePos()
1393 m_node->setPosition(pos_translator.vect_show + v3f(0,m_sprite_y,0));
1396 void MobV2CAO::step(float dtime, ClientEnvironment *env)
1398 scene::MyBillboardSceneNode *bill = m_node;
1402 pos_translator.translate(dtime);
1404 if(m_sprite_type == "humanoid_1"){
1405 scene::ICameraSceneNode* camera = m_node->getSceneManager()->getActiveCamera();
1408 v3f cam_to_mob = m_node->getAbsolutePosition() - camera->getAbsolutePosition();
1409 cam_to_mob.normalize();
1411 if(cam_to_mob.Y > 0.75)
1413 else if(cam_to_mob.Y < -0.75)
1416 float mob_dir = atan2(cam_to_mob.Z, cam_to_mob.X) / PI * 180.;
1417 float dir = mob_dir - m_yaw;
1418 dir = wrapDegrees_180(dir);
1419 //infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
1420 if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
1422 else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
1424 else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
1426 else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
1435 } else if(m_walking){
1436 m_walk_timer += dtime;
1437 if(m_walk_timer >= 0.5){
1438 m_walk_frame = (m_walk_frame + 1) % 2;
1441 if(m_walk_frame == 0)
1447 const float txp = 1./192;
1448 const float txs = txp*32;
1449 const float typ = 1./240;
1450 const float tys = typ*48;
1451 bill->setTCoords(0, v2f(txs*(1+col), tys*(1+row)));
1452 bill->setTCoords(1, v2f(txs*(1+col), tys*(0+row)));
1453 bill->setTCoords(2, v2f(txs*(0+col), tys*(0+row)));
1454 bill->setTCoords(3, v2f(txs*(0+col), tys*(1+row)));
1455 } else if(m_sprite_type == "simple"){
1456 m_walk_timer += dtime;
1457 if(m_walk_timer >= m_simple_anim_frametime){
1458 m_walk_frame = (m_walk_frame + 1) % m_simple_anim_frames;
1462 int row = m_walk_frame;
1463 const float txs = 1.0;
1464 const float tys = 1.0 / m_simple_anim_frames;
1465 bill->setTCoords(0, v2f(txs*(1+col), tys*(1+row)));
1466 bill->setTCoords(1, v2f(txs*(1+col), tys*(0+row)));
1467 bill->setTCoords(2, v2f(txs*(0+col), tys*(0+row)));
1468 bill->setTCoords(3, v2f(txs*(0+col), tys*(1+row)));
1470 infostream<<"MobV2CAO::step(): Unknown sprite type \""
1471 <<m_sprite_type<<"\""<<std::endl;
1476 /* Damage local player */
1477 if(m_player_hit_damage && m_player_hit_timer <= 0.0){
1478 LocalPlayer *player = env->getLocalPlayer();
1481 v3f playerpos = player->getPosition();
1482 v2f playerpos_2d(playerpos.X,playerpos.Z);
1483 v2f objectpos_2d(m_position.X,m_position.Z);
1485 if(fabs(m_position.Y - playerpos.Y) < m_player_hit_distance*BS &&
1486 objectpos_2d.getDistanceFrom(playerpos_2d) < m_player_hit_distance*BS)
1488 env->damageLocalPlayer(m_player_hit_damage);
1489 m_player_hit_timer = m_player_hit_interval;
1495 m_player_hit_timer -= dtime;
1497 if(m_damage_visual_timer >= 0){
1498 m_damage_visual_timer -= dtime;
1499 if(m_damage_visual_timer <= 0){
1500 infostream<<"id="<<m_id<<" damage visual ended"<<std::endl;
1504 m_walking_unset_timer += dtime;
1505 if(m_walking_unset_timer >= 1.0){
1509 m_shooting_unset_timer -= dtime;
1510 if(m_shooting_unset_timer <= 0.0){
1511 if(m_bright_shooting){
1512 u8 li = decode_light(m_last_light);
1513 video::SColor color(255,li,li,li);
1514 bill->setColor(color);
1515 m_bright_shooting = false;
1522 void MobV2CAO::processMessage(const std::string &data)
1524 //infostream<<"MobV2CAO: Got message"<<std::endl;
1525 std::istringstream is(data, std::ios::binary);
1527 u8 cmd = readU8(is);
1533 m_position = readV3F1000(is);
1534 pos_translator.update(m_position);
1536 m_yaw = readF1000(is);
1539 m_walking_unset_timer = 0;
1546 //u16 damage = readU16(is);
1548 /*u8 li = decode_light(m_last_light);
1554 /*video::SColor color(255,255,0,0);
1555 m_node->setColor(color);
1557 m_damage_visual_timer = 0.2;*/
1563 m_shooting_unset_timer = readF1000(is);
1565 m_bright_shooting = readU8(is);
1566 if(m_bright_shooting){
1568 video::SColor color(255,li,li,li);
1569 m_node->setColor(color);
1576 void MobV2CAO::initialize(const std::string &data)
1578 //infostream<<"MobV2CAO: Got init data"<<std::endl;
1581 std::istringstream is(data, std::ios::binary);
1583 u8 version = readU8(is);
1586 infostream<<__FUNCTION_NAME<<": Invalid version"<<std::endl;
1590 std::ostringstream tmp_os(std::ios::binary);
1591 decompressZlib(is, tmp_os);
1592 std::istringstream tmp_is(tmp_os.str(), std::ios::binary);
1593 m_properties->parseConfigLines(tmp_is, "MobArgsEnd");
1595 infostream<<"MobV2CAO::initialize(): got properties:"<<std::endl;
1596 m_properties->writeLines(infostream);
1598 m_properties->setDefault("looks", "dummy_default");
1599 m_properties->setDefault("yaw", "0");
1600 m_properties->setDefault("pos", "(0,0,0)");
1601 m_properties->setDefault("player_hit_damage", "0");
1602 m_properties->setDefault("player_hit_distance", "1.5");
1603 m_properties->setDefault("player_hit_interval", "1.5");
1605 setLooks(m_properties->get("looks"));
1606 m_yaw = m_properties->getFloat("yaw");
1607 m_position = m_properties->getV3F("pos");
1608 m_player_hit_damage = m_properties->getS32("player_hit_damage");
1609 m_player_hit_distance = m_properties->getFloat("player_hit_distance");
1610 m_player_hit_interval = m_properties->getFloat("player_hit_interval");
1612 pos_translator.init(m_position);
1618 bool MobV2CAO::directReportPunch(const std::string &toolname, v3f dir)
1620 video::SColor color(255,255,0,0);
1621 m_node->setColor(color);
1623 m_damage_visual_timer = 0.05;
1625 m_position += dir * BS;
1626 pos_translator.sharpen();
1627 pos_translator.update(m_position);
1633 void MobV2CAO::setLooks(const std::string &looks)
1635 v2f selection_size = v2f(0.4, 0.4) * BS;
1636 float selection_y = 0 * BS;
1638 if(looks == "dungeon_master"){
1639 m_texture_name = "dungeon_master.png";
1640 m_sprite_type = "humanoid_1";
1641 m_sprite_size = v2f(2, 3) * BS;
1642 m_sprite_y = 0.85 * BS;
1643 selection_size = v2f(0.4, 2.6) * BS;
1644 selection_y = -0.4 * BS;
1646 else if(looks == "fireball"){
1647 m_texture_name = "fireball.png";
1648 m_sprite_type = "simple";
1649 m_sprite_size = v2f(1, 1) * BS;
1650 m_simple_anim_frames = 3;
1651 m_simple_anim_frametime = 0.1;
1652 m_lock_full_brightness = true;
1655 m_texture_name = "stone.png";
1656 m_sprite_type = "simple";
1657 m_sprite_size = v2f(1, 1) * BS;
1658 m_simple_anim_frames = 3;
1659 m_simple_anim_frametime = 0.333;
1660 selection_size = v2f(0.4, 0.4) * BS;
1661 selection_y = 0 * BS;
1664 m_selection_box = core::aabbox3d<f32>(
1665 -selection_size.X, selection_y, -selection_size.X,
1666 selection_size.X, selection_y+selection_size.Y,
1674 #include "luaentity_common.h"
1676 class LuaEntityCAO : public ClientActiveObject
1679 core::aabbox3d<f32> m_selection_box;
1680 scene::IMeshSceneNode *m_meshnode;
1681 scene::MyBillboardSceneNode *m_spritenode;
1686 struct LuaEntityProperties *m_prop;
1687 SmoothTranslator pos_translator;
1688 // Spritesheet/animation stuff
1691 bool m_tx_select_horiz_by_yawpitch;
1693 int m_anim_num_frames;
1694 float m_anim_framelength;
1698 LuaEntityCAO(IGameDef *gamedef, ClientEnvironment *env):
1699 ClientActiveObject(0, gamedef, env),
1700 m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.),
1703 m_position(v3f(0,10*BS,0)),
1704 m_velocity(v3f(0,0,0)),
1705 m_acceleration(v3f(0,0,0)),
1707 m_prop(new LuaEntityProperties),
1710 m_tx_select_horiz_by_yawpitch(false),
1712 m_anim_num_frames(1),
1713 m_anim_framelength(0.2),
1717 ClientActiveObject::registerType(getType(), create);
1720 void initialize(const std::string &data)
1722 infostream<<"LuaEntityCAO: Got init data"<<std::endl;
1724 std::istringstream is(data, std::ios::binary);
1726 u8 version = readU8(is);
1731 m_position = readV3F1000(is);
1733 m_yaw = readF1000(is);
1735 std::istringstream prop_is(deSerializeLongString(is), std::ios::binary);
1736 m_prop->deSerialize(prop_is);
1738 infostream<<"m_prop: "<<m_prop->dump()<<std::endl;
1740 m_selection_box = m_prop->collisionbox;
1741 m_selection_box.MinEdge *= BS;
1742 m_selection_box.MaxEdge *= BS;
1744 pos_translator.init(m_position);
1746 m_tx_size.X = 1.0 / m_prop->spritediv.X;
1747 m_tx_size.Y = 1.0 / m_prop->spritediv.Y;
1748 m_tx_basepos.X = m_tx_size.X * m_prop->initial_sprite_basepos.X;
1749 m_tx_basepos.Y = m_tx_size.Y * m_prop->initial_sprite_basepos.Y;
1759 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
1761 return new LuaEntityCAO(gamedef, env);
1766 return ACTIVEOBJECT_TYPE_LUAENTITY;
1768 core::aabbox3d<f32>* getSelectionBox()
1770 return &m_selection_box;
1774 return pos_translator.vect_show;
1777 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
1778 IrrlichtDevice *irr)
1780 if(m_meshnode != NULL || m_spritenode != NULL)
1783 //video::IVideoDriver* driver = smgr->getVideoDriver();
1785 if(m_prop->visual == "sprite"){
1786 infostream<<"LuaEntityCAO::addToScene(): single_sprite"<<std::endl;
1787 m_spritenode = new scene::MyBillboardSceneNode(
1788 smgr->getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1));
1789 m_spritenode->setMaterialTexture(0,
1790 tsrc->getTextureRaw("unknown_block.png"));
1791 m_spritenode->setMaterialFlag(video::EMF_LIGHTING, false);
1792 m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
1793 m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
1794 m_spritenode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
1795 m_spritenode->setColor(video::SColor(255,0,0,0));
1796 m_spritenode->setVisible(false); /* Set visible when brightness is known */
1797 m_spritenode->setSize(m_prop->visual_size*BS);
1799 const float txs = 1.0 / 1;
1800 const float tys = 1.0 / 1;
1801 m_spritenode->setTCoords(0, v2f(txs*1, tys*1));
1802 m_spritenode->setTCoords(1, v2f(txs*1, tys*0));
1803 m_spritenode->setTCoords(2, v2f(txs*0, tys*0));
1804 m_spritenode->setTCoords(3, v2f(txs*0, tys*1));
1806 } else if(m_prop->visual == "cube"){
1807 infostream<<"LuaEntityCAO::addToScene(): cube"<<std::endl;
1808 video::SColor c(255,255,255,255);
1809 video::S3DVertex vertices[24] =
1812 video::S3DVertex(-0.5,+0.5,-0.5, 0,1,0, c, 0,1),
1813 video::S3DVertex(-0.5,+0.5,+0.5, 0,1,0, c, 0,0),
1814 video::S3DVertex(+0.5,+0.5,+0.5, 0,1,0, c, 1,0),
1815 video::S3DVertex(+0.5,+0.5,-0.5, 0,1,0, c, 1,1),
1817 video::S3DVertex(-0.5,-0.5,-0.5, 0,-1,0, c, 0,0),
1818 video::S3DVertex(+0.5,-0.5,-0.5, 0,-1,0, c, 1,0),
1819 video::S3DVertex(+0.5,-0.5,+0.5, 0,-1,0, c, 1,1),
1820 video::S3DVertex(-0.5,-0.5,+0.5, 0,-1,0, c, 0,1),
1822 video::S3DVertex(+0.5,-0.5,-0.5, 1,0,0, c, 0,1),
1823 video::S3DVertex(+0.5,+0.5,-0.5, 1,0,0, c, 0,0),
1824 video::S3DVertex(+0.5,+0.5,+0.5, 1,0,0, c, 1,0),
1825 video::S3DVertex(+0.5,-0.5,+0.5, 1,0,0, c, 1,1),
1827 video::S3DVertex(-0.5,-0.5,-0.5, -1,0,0, c, 1,1),
1828 video::S3DVertex(-0.5,-0.5,+0.5, -1,0,0, c, 0,1),
1829 video::S3DVertex(-0.5,+0.5,+0.5, -1,0,0, c, 0,0),
1830 video::S3DVertex(-0.5,+0.5,-0.5, -1,0,0, c, 1,0),
1832 video::S3DVertex(-0.5,-0.5,+0.5, 0,0,1, c, 1,1),
1833 video::S3DVertex(+0.5,-0.5,+0.5, 0,0,1, c, 0,1),
1834 video::S3DVertex(+0.5,+0.5,+0.5, 0,0,1, c, 0,0),
1835 video::S3DVertex(-0.5,+0.5,+0.5, 0,0,1, c, 1,0),
1837 video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1),
1838 video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0),
1839 video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0),
1840 video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1),
1843 for(u32 i=0; i<24; ++i){
1844 vertices[i].Pos *= BS;
1845 vertices[i].Pos.Y *= m_prop->visual_size.Y;
1846 vertices[i].Pos.X *= m_prop->visual_size.X;
1847 vertices[i].Pos.Z *= m_prop->visual_size.X;
1850 u16 indices[6] = {0,1,2,2,3,0};
1852 scene::SMesh* mesh = new scene::SMesh();
1853 for (u32 i=0; i<6; ++i)
1855 scene::IMeshBuffer* buf = new scene::SMeshBuffer();
1856 buf->append(vertices + 4 * i, 4, indices, 6);
1857 buf->recalculateBoundingBox();
1858 mesh->addMeshBuffer(buf);
1861 mesh->recalculateBoundingBox();
1863 m_meshnode = smgr->addMeshSceneNode(mesh, NULL);
1865 m_meshnode->setMesh(mesh);
1866 m_meshnode->setScale(v3f(1));
1867 // Will be shown when we know the brightness
1868 m_meshnode->setVisible(false);
1870 infostream<<"LuaEntityCAO::addToScene(): \""<<m_prop->visual
1871 <<"\" not supported"<<std::endl;
1877 void removeFromScene()
1880 m_meshnode->remove();
1884 m_spritenode->remove();
1885 m_spritenode = NULL;
1889 void updateLight(u8 light_at_pos)
1891 u8 li = decode_light(light_at_pos);
1892 video::SColor color(255,li,li,li);
1894 setMeshColor(m_meshnode->getMesh(), color);
1895 m_meshnode->setVisible(true);
1898 m_spritenode->setColor(color);
1899 m_spritenode->setVisible(true);
1903 v3s16 getLightPosition()
1905 return floatToInt(m_position, BS);
1908 void updateNodePos()
1911 m_meshnode->setPosition(pos_translator.vect_show);
1914 m_spritenode->setPosition(pos_translator.vect_show);
1918 void step(float dtime, ClientEnvironment *env)
1920 if(m_prop->physical){
1921 core::aabbox3d<f32> box = m_prop->collisionbox;
1924 collisionMoveResult moveresult;
1925 f32 pos_max_d = BS*0.25; // Distance per iteration
1926 v3f p_pos = m_position;
1927 v3f p_velocity = m_velocity;
1928 IGameDef *gamedef = env->getGameDef();
1929 moveresult = collisionMovePrecise(&env->getMap(), gamedef,
1930 pos_max_d, box, dtime, p_pos, p_velocity);
1933 m_velocity = p_velocity;
1935 bool is_end_position = moveresult.collides;
1936 pos_translator.update(m_position, is_end_position, dtime);
1937 pos_translator.translate(dtime);
1940 m_velocity += dtime * m_acceleration;
1942 m_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration;
1943 m_velocity += dtime * m_acceleration;
1944 pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time);
1945 pos_translator.translate(dtime);
1949 m_anim_timer += dtime;
1950 if(m_anim_timer >= m_anim_framelength){
1951 m_anim_timer -= m_anim_framelength;
1953 if(m_anim_frame >= m_anim_num_frames)
1960 void updateTexturePos()
1963 scene::ICameraSceneNode* camera =
1964 m_spritenode->getSceneManager()->getActiveCamera();
1967 v3f cam_to_entity = m_spritenode->getAbsolutePosition()
1968 - camera->getAbsolutePosition();
1969 cam_to_entity.normalize();
1971 int row = m_tx_basepos.Y;
1972 int col = m_tx_basepos.X;
1974 if(m_tx_select_horiz_by_yawpitch)
1976 if(cam_to_entity.Y > 0.75)
1978 else if(cam_to_entity.Y < -0.75)
1981 float mob_dir = atan2(cam_to_entity.Z, cam_to_entity.X) / PI * 180.;
1982 float dir = mob_dir - m_yaw;
1983 dir = wrapDegrees_180(dir);
1984 //infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
1985 if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
1987 else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
1989 else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
1991 else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
1998 // Animation goes downwards
1999 row += m_anim_frame;
2001 float txs = m_tx_size.X;
2002 float tys = m_tx_size.Y;
2003 m_spritenode->setTCoords(0, v2f(txs*(1+col), tys*(1+row)));
2004 m_spritenode->setTCoords(1, v2f(txs*(1+col), tys*(0+row)));
2005 m_spritenode->setTCoords(2, v2f(txs*(0+col), tys*(0+row)));
2006 m_spritenode->setTCoords(3, v2f(txs*(0+col), tys*(1+row)));
2010 void updateTextures(const std::string &mod)
2012 ITextureSource *tsrc = m_gamedef->tsrc();
2015 std::string texturestring = "unknown_block.png";
2016 if(m_prop->textures.size() >= 1)
2017 texturestring = m_prop->textures[0];
2018 texturestring += mod;
2019 m_spritenode->setMaterialTexture(0,
2020 tsrc->getTextureRaw(texturestring));
2023 for (u32 i = 0; i < 6; ++i)
2025 std::string texturestring = "unknown_block.png";
2026 if(m_prop->textures.size() > i)
2027 texturestring = m_prop->textures[i];
2028 texturestring += mod;
2029 AtlasPointer ap = tsrc->getTexture(texturestring);
2031 // Get the tile texture and atlas transformation
2032 video::ITexture* atlas = ap.atlas;
2036 // Set material flags and texture
2037 video::SMaterial& material = m_meshnode->getMaterial(i);
2038 material.setFlag(video::EMF_LIGHTING, false);
2039 material.setFlag(video::EMF_BILINEAR_FILTER, false);
2040 material.setTexture(0, atlas);
2041 material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
2042 material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
2047 void processMessage(const std::string &data)
2049 //infostream<<"LuaEntityCAO: Got message"<<std::endl;
2050 std::istringstream is(data, std::ios::binary);
2052 u8 cmd = readU8(is);
2053 if(cmd == 0) // update position
2056 bool do_interpolate = readU8(is);
2058 m_position = readV3F1000(is);
2060 m_velocity = readV3F1000(is);
2062 m_acceleration = readV3F1000(is);
2064 m_yaw = readF1000(is);
2065 // is_end_position (for interpolation)
2066 bool is_end_position = readU8(is);
2068 float update_interval = readF1000(is);
2071 if(!m_prop->physical)
2072 pos_translator.update(m_position, is_end_position, update_interval);
2074 pos_translator.init(m_position);
2078 else if(cmd == 1) // set texture modification
2080 std::string mod = deSerializeString(is);
2081 updateTextures(mod);
2083 else if(cmd == 2) // set sprite
2085 v2s16 p = readV2S16(is);
2086 int num_frames = readU16(is);
2087 float framelength = readF1000(is);
2088 bool select_horiz_by_yawpitch = readU8(is);
2091 m_anim_num_frames = num_frames;
2092 m_anim_framelength = framelength;
2093 m_tx_select_horiz_by_yawpitch = select_horiz_by_yawpitch;
2101 LuaEntityCAO proto_LuaEntityCAO(NULL, NULL);
2107 class PlayerCAO : public ClientActiveObject
2110 core::aabbox3d<f32> m_selection_box;
2111 scene::IMeshSceneNode *m_node;
2112 scene::ITextSceneNode* m_text;
2116 SmoothTranslator pos_translator;
2117 bool m_is_local_player;
2118 LocalPlayer *m_local_player;
2119 float m_damage_visual_timer;
2122 PlayerCAO(IGameDef *gamedef, ClientEnvironment *env):
2123 ClientActiveObject(0, gamedef, env),
2124 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.0,BS/3.),
2127 m_position(v3f(0,10*BS,0)),
2129 m_is_local_player(false),
2130 m_local_player(NULL),
2131 m_damage_visual_timer(0)
2134 ClientActiveObject::registerType(getType(), create);
2137 void initialize(const std::string &data)
2139 infostream<<"PlayerCAO: Got init data"<<std::endl;
2141 std::istringstream is(data, std::ios::binary);
2143 u8 version = readU8(is);
2148 m_name = deSerializeString(is);
2150 m_position = readV3F1000(is);
2152 m_yaw = readF1000(is);
2154 pos_translator.init(m_position);
2156 Player *player = m_env->getPlayer(m_name.c_str());
2157 if(player && player->isLocal()){
2158 m_is_local_player = true;
2159 m_local_player = (LocalPlayer*)player;
2169 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
2171 return new PlayerCAO(gamedef, env);
2176 return ACTIVEOBJECT_TYPE_PLAYER;
2178 core::aabbox3d<f32>* getSelectionBox()
2180 if(m_is_local_player)
2182 return &m_selection_box;
2186 return pos_translator.vect_show;
2189 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
2190 IrrlichtDevice *irr)
2194 if(m_is_local_player)
2197 //video::IVideoDriver* driver = smgr->getVideoDriver();
2198 gui::IGUIEnvironment* gui = irr->getGUIEnvironment();
2200 scene::SMesh *mesh = new scene::SMesh();
2202 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
2203 video::SColor c(255,255,255,255);
2204 video::S3DVertex vertices[4] =
2206 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
2207 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
2208 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
2209 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
2211 u16 indices[] = {0,1,2,2,3,0};
2212 buf->append(vertices, 4, indices, 6);
2214 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
2215 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
2216 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
2217 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
2219 mesh->addMeshBuffer(buf);
2223 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
2224 video::SColor c(255,255,255,255);
2225 video::S3DVertex vertices[4] =
2227 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
2228 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
2229 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
2230 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
2232 u16 indices[] = {0,1,2,2,3,0};
2233 buf->append(vertices, 4, indices, 6);
2235 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
2236 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
2237 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
2238 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
2240 mesh->addMeshBuffer(buf);
2243 m_node = smgr->addMeshSceneNode(mesh, NULL);
2245 // Set it to use the materials of the meshbuffers directly.
2246 // This is needed for changing the texture in the future
2247 m_node->setReadOnlyMaterials(true);
2250 // Add a text node for showing the name
2251 std::wstring wname = narrow_to_wide(m_name);
2252 m_text = smgr->addTextSceneNode(gui->getBuiltInFont(),
2253 wname.c_str(), video::SColor(255,255,255,255), m_node);
2254 m_text->setPosition(v3f(0, (f32)BS*2.1, 0));
2260 void removeFromScene()
2269 void updateLight(u8 light_at_pos)
2274 m_node->setVisible(true);
2276 u8 li = decode_light(light_at_pos);
2277 video::SColor color(255,li,li,li);
2278 setMeshColor(m_node->getMesh(), color);
2281 v3s16 getLightPosition()
2283 return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
2286 void updateNodePos()
2291 m_node->setPosition(pos_translator.vect_show);
2293 v3f rot = m_node->getRotation();
2295 m_node->setRotation(rot);
2298 void step(float dtime, ClientEnvironment *env)
2300 pos_translator.translate(dtime);
2303 if(m_damage_visual_timer > 0){
2304 m_damage_visual_timer -= dtime;
2305 if(m_damage_visual_timer <= 0){
2311 void processMessage(const std::string &data)
2313 //infostream<<"PlayerCAO: Got message"<<std::endl;
2314 std::istringstream is(data, std::ios::binary);
2316 u8 cmd = readU8(is);
2317 if(cmd == 0) // update position
2320 m_position = readV3F1000(is);
2322 m_yaw = readF1000(is);
2324 pos_translator.update(m_position, false);
2328 else if(cmd == 1) // punched
2331 s16 damage = readS16(is);
2333 if(m_is_local_player)
2334 m_env->damageLocalPlayer(damage, false);
2336 m_damage_visual_timer = 0.5;
2337 updateTextures("^[brighten");
2341 void updateTextures(const std::string &mod)
2345 ITextureSource *tsrc = m_gamedef->tsrc();
2346 scene::IMesh *mesh = m_node->getMesh();
2349 std::string tname = "player.png";
2351 scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
2352 buf->getMaterial().setTexture(0,
2353 tsrc->getTextureRaw(tname));
2356 std::string tname = "player_back.png";
2358 scene::IMeshBuffer *buf = mesh->getMeshBuffer(1);
2359 buf->getMaterial().setTexture(0,
2360 tsrc->getTextureRaw(tname));
2367 PlayerCAO proto_PlayerCAO(NULL, NULL);