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 <IBillboardSceneNode.h>
27 #include "serialization.h" // For decompressZlib
29 #include "clientobject.h"
30 #include "content_object.h"
32 #include "utility.h" // For IntervalLimiter
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;
335 static void setBillboardTextureMatrix(scene::IBillboardSceneNode *bill,
336 float txs, float tys, int col, int row)
338 video::SMaterial& material = bill->getMaterial(0);
339 core::matrix4& matrix = material.getTextureMatrix(0);
340 matrix.setTextureTranslate(txs*col, tys*row);
341 matrix.setTextureScale(txs, tys);
348 class MobV2CAO : public ClientActiveObject
351 MobV2CAO(IGameDef *gamedef, ClientEnvironment *env);
356 return ACTIVEOBJECT_TYPE_MOBV2;
359 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env);
361 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
362 IrrlichtDevice *irr);
363 void removeFromScene();
364 void updateLight(u8 light_at_pos);
365 v3s16 getLightPosition();
366 void updateNodePos();
368 void step(float dtime, ClientEnvironment *env);
370 void processMessage(const std::string &data);
372 void initialize(const std::string &data);
374 core::aabbox3d<f32>* getSelectionBox()
375 {return &m_selection_box;}
377 {return pos_translator.vect_show;}
378 //{return m_position;}
379 bool doShowSelectionBox(){return false;}
381 // If returns true, punch will not be sent to the server
382 bool directReportPunch(const std::string &toolname, v3f dir);
385 void setLooks(const std::string &looks);
387 IntervalLimiter m_attack_interval;
388 core::aabbox3d<f32> m_selection_box;
389 scene::IBillboardSceneNode *m_node;
391 std::string m_texture_name;
393 SmoothTranslator pos_translator;
395 float m_walking_unset_timer;
398 float m_damage_visual_timer;
401 float m_shooting_unset_timer;
404 bool m_bright_shooting;
405 std::string m_sprite_type;
406 int m_simple_anim_frames;
407 float m_simple_anim_frametime;
408 bool m_lock_full_brightness;
409 int m_player_hit_damage;
410 float m_player_hit_distance;
411 float m_player_hit_interval;
412 float m_player_hit_timer;
414 Settings *m_properties;
422 TestCAO proto_TestCAO(NULL, NULL);
424 TestCAO::TestCAO(IGameDef *gamedef, ClientEnvironment *env):
425 ClientActiveObject(0, gamedef, env),
427 m_position(v3f(0,10*BS,0))
429 ClientActiveObject::registerType(getType(), create);
436 ClientActiveObject* TestCAO::create(IGameDef *gamedef, ClientEnvironment *env)
438 return new TestCAO(gamedef, env);
441 void TestCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
447 //video::IVideoDriver* driver = smgr->getVideoDriver();
449 scene::SMesh *mesh = new scene::SMesh();
450 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
451 video::SColor c(255,255,255,255);
452 video::S3DVertex vertices[4] =
454 video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
455 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
456 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
457 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),
459 u16 indices[] = {0,1,2,2,3,0};
460 buf->append(vertices, 4, indices, 6);
462 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
463 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
464 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("rat.png"));
465 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
466 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
467 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
469 mesh->addMeshBuffer(buf);
471 m_node = smgr->addMeshSceneNode(mesh, NULL);
476 void TestCAO::removeFromScene()
485 void TestCAO::updateLight(u8 light_at_pos)
489 v3s16 TestCAO::getLightPosition()
491 return floatToInt(m_position, BS);
494 void TestCAO::updateNodePos()
499 m_node->setPosition(m_position);
500 //m_node->setRotation(v3f(0, 45, 0));
503 void TestCAO::step(float dtime, ClientEnvironment *env)
507 v3f rot = m_node->getRotation();
508 //infostream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
509 rot.Y += dtime * 180;
510 m_node->setRotation(rot);
514 void TestCAO::processMessage(const std::string &data)
516 infostream<<"TestCAO: Got data: "<<data<<std::endl;
517 std::istringstream is(data, std::ios::binary);
535 #include "inventory.h"
538 ItemCAO proto_ItemCAO(NULL, NULL);
540 ItemCAO::ItemCAO(IGameDef *gamedef, ClientEnvironment *env):
541 ClientActiveObject(0, gamedef, env),
542 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.),
544 m_position(v3f(0,10*BS,0))
548 ClientActiveObject::registerType(getType(), create);
556 ClientActiveObject* ItemCAO::create(IGameDef *gamedef, ClientEnvironment *env)
558 return new ItemCAO(gamedef, env);
561 void ItemCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
567 //video::IVideoDriver* driver = smgr->getVideoDriver();
569 scene::SMesh *mesh = new scene::SMesh();
570 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
571 video::SColor c(255,255,255,255);
572 video::S3DVertex vertices[4] =
574 /*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
575 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
576 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
577 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/
578 video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1),
579 video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1),
580 video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0),
581 video::S3DVertex(BS/3.,0+BS*2./3.,0, 0,0,0, c, 0,0),
583 u16 indices[] = {0,1,2,2,3,0};
584 buf->append(vertices, 4, indices, 6);
586 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
587 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
588 // Initialize with a generated placeholder texture
589 buf->getMaterial().setTexture(0, tsrc->getTextureRaw(""));
590 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
591 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
592 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
594 mesh->addMeshBuffer(buf);
596 m_node = smgr->addMeshSceneNode(mesh, NULL);
598 // Set it to use the materials of the meshbuffers directly.
599 // This is needed for changing the texture in the future
600 m_node->setReadOnlyMaterials(true);
607 // Create an inventory item to see what is its image
608 std::istringstream is(m_inventorystring, std::ios_base::binary);
609 video::ITexture *texture = NULL;
611 InventoryItem *item = NULL;
612 item = InventoryItem::deSerialize(is, m_gamedef);
613 infostream<<__FUNCTION_NAME<<": m_inventorystring=\""
614 <<m_inventorystring<<"\" -> item="<<item
618 texture = item->getImage();
622 catch(SerializationError &e)
624 infostream<<"WARNING: "<<__FUNCTION_NAME
625 <<": error deSerializing inventorystring \""
626 <<m_inventorystring<<"\""<<std::endl;
629 // Set meshbuffer texture
630 buf->getMaterial().setTexture(0, texture);
633 void ItemCAO::removeFromScene()
642 void ItemCAO::updateLight(u8 light_at_pos)
647 u8 li = decode_light(light_at_pos);
648 video::SColor color(255,li,li,li);
649 setMeshColor(m_node->getMesh(), color);
652 v3s16 ItemCAO::getLightPosition()
654 return floatToInt(m_position, BS);
657 void ItemCAO::updateNodePos()
662 m_node->setPosition(m_position);
665 void ItemCAO::step(float dtime, ClientEnvironment *env)
669 /*v3f rot = m_node->getRotation();
670 rot.Y += dtime * 120;
671 m_node->setRotation(rot);*/
672 LocalPlayer *player = env->getLocalPlayer();
674 v3f rot = m_node->getRotation();
675 rot.Y = 180.0 - (player->getYaw());
676 m_node->setRotation(rot);
680 void ItemCAO::processMessage(const std::string &data)
682 //infostream<<"ItemCAO: Got message"<<std::endl;
683 std::istringstream is(data, std::ios::binary);
689 m_position = readV3F1000(is);
694 void ItemCAO::initialize(const std::string &data)
696 infostream<<"ItemCAO: Got init data"<<std::endl;
699 std::istringstream is(data, std::ios::binary);
701 u8 version = readU8(is);
706 m_position = readV3F1000(is);
708 m_inventorystring = deSerializeString(is);
714 Set infotext to item name if item cannot be deserialized
717 InventoryItem *item = NULL;
718 item = InventoryItem::deSerialize(m_inventorystring, m_gamedef);
721 m_infotext = "Unknown item: '" + m_inventorystring + "'";
725 catch(SerializationError &e)
727 m_infotext = "Unknown item: '" + m_inventorystring + "'";
735 #include "inventory.h"
738 RatCAO proto_RatCAO(NULL, NULL);
740 RatCAO::RatCAO(IGameDef *gamedef, ClientEnvironment *env):
741 ClientActiveObject(0, gamedef, env),
742 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
744 m_position(v3f(0,10*BS,0)),
747 ClientActiveObject::registerType(getType(), create);
754 ClientActiveObject* RatCAO::create(IGameDef *gamedef, ClientEnvironment *env)
756 return new RatCAO(gamedef, env);
759 void RatCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
765 //video::IVideoDriver* driver = smgr->getVideoDriver();
767 scene::SMesh *mesh = new scene::SMesh();
768 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
769 video::SColor c(255,255,255,255);
770 video::S3DVertex vertices[4] =
772 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
773 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
774 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
775 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
777 u16 indices[] = {0,1,2,2,3,0};
778 buf->append(vertices, 4, indices, 6);
780 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
781 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
782 //buf->getMaterial().setTexture(0, NULL);
783 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("rat.png"));
784 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
785 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
786 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
788 mesh->addMeshBuffer(buf);
790 m_node = smgr->addMeshSceneNode(mesh, NULL);
792 // Set it to use the materials of the meshbuffers directly.
793 // This is needed for changing the texture in the future
794 m_node->setReadOnlyMaterials(true);
798 void RatCAO::removeFromScene()
807 void RatCAO::updateLight(u8 light_at_pos)
812 u8 li = decode_light(light_at_pos);
813 video::SColor color(255,li,li,li);
814 setMeshColor(m_node->getMesh(), color);
817 v3s16 RatCAO::getLightPosition()
819 return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
822 void RatCAO::updateNodePos()
827 //m_node->setPosition(m_position);
828 m_node->setPosition(pos_translator.vect_show);
830 v3f rot = m_node->getRotation();
831 rot.Y = 180.0 - m_yaw;
832 m_node->setRotation(rot);
835 void RatCAO::step(float dtime, ClientEnvironment *env)
837 pos_translator.translate(dtime);
841 void RatCAO::processMessage(const std::string &data)
843 //infostream<<"RatCAO: Got message"<<std::endl;
844 std::istringstream is(data, std::ios::binary);
850 m_position = readV3F1000(is);
851 pos_translator.update(m_position);
853 m_yaw = readF1000(is);
858 void RatCAO::initialize(const std::string &data)
860 //infostream<<"RatCAO: Got init data"<<std::endl;
863 std::istringstream is(data, std::ios::binary);
865 u8 version = readU8(is);
870 m_position = readV3F1000(is);
871 pos_translator.init(m_position);
881 #include "inventory.h"
884 Oerkki1CAO proto_Oerkki1CAO(NULL, NULL);
886 Oerkki1CAO::Oerkki1CAO(IGameDef *gamedef, ClientEnvironment *env):
887 ClientActiveObject(0, gamedef, env),
888 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.),
890 m_position(v3f(0,10*BS,0)),
892 m_damage_visual_timer(0),
893 m_damage_texture_enabled(false)
895 ClientActiveObject::registerType(getType(), create);
898 Oerkki1CAO::~Oerkki1CAO()
902 ClientActiveObject* Oerkki1CAO::create(IGameDef *gamedef, ClientEnvironment *env)
904 return new Oerkki1CAO(gamedef, env);
907 void Oerkki1CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
913 //video::IVideoDriver* driver = smgr->getVideoDriver();
915 scene::SMesh *mesh = new scene::SMesh();
916 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
917 video::SColor c(255,255,255,255);
918 video::S3DVertex vertices[4] =
920 video::S3DVertex(-BS/2-BS,0,0, 0,0,0, c, 0,1),
921 video::S3DVertex(BS/2+BS,0,0, 0,0,0, c, 1,1),
922 video::S3DVertex(BS/2+BS,BS*2,0, 0,0,0, c, 1,0),
923 video::S3DVertex(-BS/2-BS,BS*2,0, 0,0,0, c, 0,0),
925 u16 indices[] = {0,1,2,2,3,0};
926 buf->append(vertices, 4, indices, 6);
928 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
929 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
930 //buf->getMaterial().setTexture(0, NULL);
931 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("oerkki1.png"));
932 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
933 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
934 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
936 mesh->addMeshBuffer(buf);
938 m_node = smgr->addMeshSceneNode(mesh, NULL);
940 // Set it to use the materials of the meshbuffers directly.
941 // This is needed for changing the texture in the future
942 m_node->setReadOnlyMaterials(true);
946 void Oerkki1CAO::removeFromScene()
955 void Oerkki1CAO::updateLight(u8 light_at_pos)
960 if(light_at_pos <= 2)
962 m_node->setVisible(false);
966 m_node->setVisible(true);
968 u8 li = decode_light(light_at_pos);
969 video::SColor color(255,li,li,li);
970 setMeshColor(m_node->getMesh(), color);
973 v3s16 Oerkki1CAO::getLightPosition()
975 return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
978 void Oerkki1CAO::updateNodePos()
983 //m_node->setPosition(m_position);
984 m_node->setPosition(pos_translator.vect_show);
986 v3f rot = m_node->getRotation();
987 rot.Y = 180.0 - m_yaw + 90.0;
988 m_node->setRotation(rot);
991 void Oerkki1CAO::step(float dtime, ClientEnvironment *env)
993 ITextureSource *tsrc = m_gamedef->tsrc();
995 pos_translator.translate(dtime);
998 LocalPlayer *player = env->getLocalPlayer();
1001 v3f playerpos = player->getPosition();
1002 v2f playerpos_2d(playerpos.X,playerpos.Z);
1003 v2f objectpos_2d(m_position.X,m_position.Z);
1005 if(fabs(m_position.Y - playerpos.Y) < 1.5*BS &&
1006 objectpos_2d.getDistanceFrom(playerpos_2d) < 1.5*BS)
1008 if(m_attack_interval.step(dtime, 0.5))
1010 env->damageLocalPlayer(2);
1014 if(m_damage_visual_timer > 0)
1016 if(!m_damage_texture_enabled)
1018 // Enable damage texture
1021 /*video::IVideoDriver* driver =
1022 m_node->getSceneManager()->getVideoDriver();*/
1024 scene::IMesh *mesh = m_node->getMesh();
1028 u16 mc = mesh->getMeshBufferCount();
1029 for(u16 j=0; j<mc; j++)
1031 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
1032 buf->getMaterial().setTexture(0,
1033 tsrc->getTextureRaw("oerkki1_damaged.png"));
1036 m_damage_texture_enabled = true;
1038 m_damage_visual_timer -= dtime;
1042 if(m_damage_texture_enabled)
1044 // Disable damage texture
1047 /*video::IVideoDriver* driver =
1048 m_node->getSceneManager()->getVideoDriver();*/
1050 scene::IMesh *mesh = m_node->getMesh();
1054 u16 mc = mesh->getMeshBufferCount();
1055 for(u16 j=0; j<mc; j++)
1057 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
1058 buf->getMaterial().setTexture(0,
1059 tsrc->getTextureRaw("oerkki1.png"));
1062 m_damage_texture_enabled = false;
1067 void Oerkki1CAO::processMessage(const std::string &data)
1069 //infostream<<"Oerkki1CAO: Got message"<<std::endl;
1070 std::istringstream is(data, std::ios::binary);
1072 u8 cmd = readU8(is);
1076 m_position = readV3F1000(is);
1077 pos_translator.update(m_position);
1079 m_yaw = readF1000(is);
1084 //u16 damage = readU8(is);
1085 m_damage_visual_timer = 1.0;
1089 void Oerkki1CAO::initialize(const std::string &data)
1091 //infostream<<"Oerkki1CAO: Got init data"<<std::endl;
1094 std::istringstream is(data, std::ios::binary);
1096 u8 version = readU8(is);
1101 m_position = readV3F1000(is);
1102 pos_translator.init(m_position);
1108 bool Oerkki1CAO::directReportPunch(const std::string &toolname, v3f dir)
1110 m_damage_visual_timer = 1.0;
1112 m_position += dir * BS;
1113 pos_translator.sharpen();
1114 pos_translator.update(m_position);
1125 FireflyCAO proto_FireflyCAO(NULL, NULL);
1127 FireflyCAO::FireflyCAO(IGameDef *gamedef, ClientEnvironment *env):
1128 ClientActiveObject(0, gamedef, env),
1129 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
1131 m_position(v3f(0,10*BS,0)),
1134 ClientActiveObject::registerType(getType(), create);
1137 FireflyCAO::~FireflyCAO()
1141 ClientActiveObject* FireflyCAO::create(IGameDef *gamedef, ClientEnvironment *env)
1143 return new FireflyCAO(gamedef, env);
1146 void FireflyCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
1147 IrrlichtDevice *irr)
1152 //video::IVideoDriver* driver = smgr->getVideoDriver();
1154 scene::SMesh *mesh = new scene::SMesh();
1155 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
1156 video::SColor c(255,255,255,255);
1157 video::S3DVertex vertices[4] =
1159 video::S3DVertex(0,0,0, 0,0,0, c, 0,1),
1160 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
1161 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
1162 video::S3DVertex(0,BS/2,0, 0,0,0, c, 0,0),
1164 u16 indices[] = {0,1,2,2,3,0};
1165 buf->append(vertices, 4, indices, 6);
1167 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
1168 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
1169 //buf->getMaterial().setTexture(0, NULL);
1170 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("firefly.png"));
1171 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
1172 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
1173 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
1175 mesh->addMeshBuffer(buf);
1177 m_node = smgr->addMeshSceneNode(mesh, NULL);
1179 // Set it to use the materials of the meshbuffers directly.
1180 // This is needed for changing the texture in the future
1181 m_node->setReadOnlyMaterials(true);
1185 void FireflyCAO::removeFromScene()
1194 void FireflyCAO::updateLight(u8 light_at_pos)
1200 video::SColor color(255,li,li,li);
1201 setMeshColor(m_node->getMesh(), color);
1204 v3s16 FireflyCAO::getLightPosition()
1206 return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
1209 void FireflyCAO::updateNodePos()
1214 //m_node->setPosition(m_position);
1215 m_node->setPosition(pos_translator.vect_show);
1217 v3f rot = m_node->getRotation();
1218 rot.Y = 180.0 - m_yaw;
1219 m_node->setRotation(rot);
1222 void FireflyCAO::step(float dtime, ClientEnvironment *env)
1224 pos_translator.translate(dtime);
1228 void FireflyCAO::processMessage(const std::string &data)
1230 //infostream<<"FireflyCAO: Got message"<<std::endl;
1231 std::istringstream is(data, std::ios::binary);
1233 u8 cmd = readU8(is);
1237 m_position = readV3F1000(is);
1238 pos_translator.update(m_position);
1240 m_yaw = readF1000(is);
1245 void FireflyCAO::initialize(const std::string &data)
1247 //infostream<<"FireflyCAO: Got init data"<<std::endl;
1250 std::istringstream is(data, std::ios::binary);
1252 u8 version = readU8(is);
1257 m_position = readV3F1000(is);
1258 pos_translator.init(m_position);
1269 MobV2CAO proto_MobV2CAO(NULL, NULL);
1271 MobV2CAO::MobV2CAO(IGameDef *gamedef, ClientEnvironment *env):
1272 ClientActiveObject(0, gamedef, env),
1273 m_selection_box(-0.4*BS,-0.4*BS,-0.4*BS, 0.4*BS,0.8*BS,0.4*BS),
1275 m_position(v3f(0,10*BS,0)),
1278 m_walking_unset_timer(0),
1281 m_damage_visual_timer(0),
1284 m_shooting_unset_timer(0),
1285 m_sprite_size(BS,BS),
1287 m_bright_shooting(false),
1288 m_lock_full_brightness(false),
1289 m_player_hit_timer(0)
1291 ClientActiveObject::registerType(getType(), create);
1293 m_properties = new Settings;
1296 MobV2CAO::~MobV2CAO()
1298 delete m_properties;
1301 ClientActiveObject* MobV2CAO::create(IGameDef *gamedef, ClientEnvironment *env)
1303 return new MobV2CAO(gamedef, env);
1306 void MobV2CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
1307 IrrlichtDevice *irr)
1312 /*infostream<<"MobV2CAO::addToScene using texture_name="<<
1313 m_texture_name<<std::endl;*/
1314 std::string texture_string = m_texture_name +
1315 "^[makealpha:128,0,0^[makealpha:128,128,0";
1317 scene::IBillboardSceneNode *bill = smgr->addBillboardSceneNode(
1318 NULL, v2f(1, 1), v3f(0,0,0), -1);
1319 bill->setMaterialTexture(0, tsrc->getTextureRaw(texture_string));
1320 bill->setMaterialFlag(video::EMF_LIGHTING, false);
1321 bill->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
1322 bill->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
1323 bill->setMaterialFlag(video::EMF_FOG_ENABLE, true);
1324 bill->setColor(video::SColor(255,0,0,0));
1325 bill->setVisible(false); /* Set visible when brightness is known */
1326 bill->setSize(m_sprite_size);
1327 if(m_sprite_type == "humanoid_1"){
1328 const float txp = 1./192;
1329 const float txs = txp*32;
1330 const float typ = 1./240;
1331 const float tys = typ*48;
1332 setBillboardTextureMatrix(bill, txs, tys, 0, 0);
1333 } else if(m_sprite_type == "simple"){
1334 const float txs = 1.0;
1335 const float tys = 1.0 / m_simple_anim_frames;
1336 setBillboardTextureMatrix(bill, txs, tys, 0, 0);
1338 infostream<<"MobV2CAO: Unknown sprite type \""<<m_sprite_type<<"\""
1347 void MobV2CAO::removeFromScene()
1356 void MobV2CAO::updateLight(u8 light_at_pos)
1358 if(m_lock_full_brightness)
1361 m_last_light = light_at_pos;
1366 if(m_damage_visual_timer > 0)
1369 if(m_shooting && m_bright_shooting)
1372 /*if(light_at_pos <= 2){
1373 m_node->setVisible(false);
1377 m_node->setVisible(true);
1379 u8 li = decode_light(light_at_pos);
1380 video::SColor color(255,li,li,li);
1381 m_node->setColor(color);
1384 v3s16 MobV2CAO::getLightPosition()
1386 return floatToInt(m_position+v3f(0,0,0), BS);
1389 void MobV2CAO::updateNodePos()
1394 m_node->setPosition(pos_translator.vect_show + v3f(0,m_sprite_y,0));
1397 void MobV2CAO::step(float dtime, ClientEnvironment *env)
1399 scene::IBillboardSceneNode *bill = m_node;
1403 pos_translator.translate(dtime);
1405 if(m_sprite_type == "humanoid_1"){
1406 scene::ICameraSceneNode* camera = m_node->getSceneManager()->getActiveCamera();
1409 v3f cam_to_mob = m_node->getAbsolutePosition() - camera->getAbsolutePosition();
1410 cam_to_mob.normalize();
1412 if(cam_to_mob.Y > 0.75)
1414 else if(cam_to_mob.Y < -0.75)
1417 float mob_dir = atan2(cam_to_mob.Z, cam_to_mob.X) / PI * 180.;
1418 float dir = mob_dir - m_yaw;
1419 dir = wrapDegrees_180(dir);
1420 //infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
1421 if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
1423 else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
1425 else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
1427 else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
1436 } else if(m_walking){
1437 m_walk_timer += dtime;
1438 if(m_walk_timer >= 0.5){
1439 m_walk_frame = (m_walk_frame + 1) % 2;
1442 if(m_walk_frame == 0)
1448 const float txp = 1./192;
1449 const float txs = txp*32;
1450 const float typ = 1./240;
1451 const float tys = typ*48;
1452 setBillboardTextureMatrix(bill, txs, tys, col, row);
1453 } else if(m_sprite_type == "simple"){
1454 m_walk_timer += dtime;
1455 if(m_walk_timer >= m_simple_anim_frametime){
1456 m_walk_frame = (m_walk_frame + 1) % m_simple_anim_frames;
1460 int row = m_walk_frame;
1461 const float txs = 1.0;
1462 const float tys = 1.0 / m_simple_anim_frames;
1463 setBillboardTextureMatrix(bill, txs, tys, col, row);
1465 infostream<<"MobV2CAO::step(): Unknown sprite type \""
1466 <<m_sprite_type<<"\""<<std::endl;
1471 /* Damage local player */
1472 if(m_player_hit_damage && m_player_hit_timer <= 0.0){
1473 LocalPlayer *player = env->getLocalPlayer();
1476 v3f playerpos = player->getPosition();
1477 v2f playerpos_2d(playerpos.X,playerpos.Z);
1478 v2f objectpos_2d(m_position.X,m_position.Z);
1480 if(fabs(m_position.Y - playerpos.Y) < m_player_hit_distance*BS &&
1481 objectpos_2d.getDistanceFrom(playerpos_2d) < m_player_hit_distance*BS)
1483 env->damageLocalPlayer(m_player_hit_damage);
1484 m_player_hit_timer = m_player_hit_interval;
1490 m_player_hit_timer -= dtime;
1492 if(m_damage_visual_timer >= 0){
1493 m_damage_visual_timer -= dtime;
1494 if(m_damage_visual_timer <= 0){
1495 infostream<<"id="<<m_id<<" damage visual ended"<<std::endl;
1499 m_walking_unset_timer += dtime;
1500 if(m_walking_unset_timer >= 1.0){
1504 m_shooting_unset_timer -= dtime;
1505 if(m_shooting_unset_timer <= 0.0){
1506 if(m_bright_shooting){
1507 u8 li = decode_light(m_last_light);
1508 video::SColor color(255,li,li,li);
1509 bill->setColor(color);
1510 m_bright_shooting = false;
1517 void MobV2CAO::processMessage(const std::string &data)
1519 //infostream<<"MobV2CAO: Got message"<<std::endl;
1520 std::istringstream is(data, std::ios::binary);
1522 u8 cmd = readU8(is);
1528 m_position = readV3F1000(is);
1529 pos_translator.update(m_position);
1531 m_yaw = readF1000(is);
1534 m_walking_unset_timer = 0;
1541 //u16 damage = readU16(is);
1543 /*u8 li = decode_light(m_last_light);
1549 /*video::SColor color(255,255,0,0);
1550 m_node->setColor(color);
1552 m_damage_visual_timer = 0.2;*/
1558 m_shooting_unset_timer = readF1000(is);
1560 m_bright_shooting = readU8(is);
1561 if(m_bright_shooting){
1563 video::SColor color(255,li,li,li);
1564 m_node->setColor(color);
1571 void MobV2CAO::initialize(const std::string &data)
1573 //infostream<<"MobV2CAO: Got init data"<<std::endl;
1576 std::istringstream is(data, std::ios::binary);
1578 u8 version = readU8(is);
1581 infostream<<__FUNCTION_NAME<<": Invalid version"<<std::endl;
1585 std::ostringstream tmp_os(std::ios::binary);
1586 decompressZlib(is, tmp_os);
1587 std::istringstream tmp_is(tmp_os.str(), std::ios::binary);
1588 m_properties->parseConfigLines(tmp_is, "MobArgsEnd");
1590 infostream<<"MobV2CAO::initialize(): got properties:"<<std::endl;
1591 m_properties->writeLines(infostream);
1593 m_properties->setDefault("looks", "dummy_default");
1594 m_properties->setDefault("yaw", "0");
1595 m_properties->setDefault("pos", "(0,0,0)");
1596 m_properties->setDefault("player_hit_damage", "0");
1597 m_properties->setDefault("player_hit_distance", "1.5");
1598 m_properties->setDefault("player_hit_interval", "1.5");
1600 setLooks(m_properties->get("looks"));
1601 m_yaw = m_properties->getFloat("yaw");
1602 m_position = m_properties->getV3F("pos");
1603 m_player_hit_damage = m_properties->getS32("player_hit_damage");
1604 m_player_hit_distance = m_properties->getFloat("player_hit_distance");
1605 m_player_hit_interval = m_properties->getFloat("player_hit_interval");
1607 pos_translator.init(m_position);
1613 bool MobV2CAO::directReportPunch(const std::string &toolname, v3f dir)
1615 video::SColor color(255,255,0,0);
1616 m_node->setColor(color);
1618 m_damage_visual_timer = 0.05;
1620 m_position += dir * BS;
1621 pos_translator.sharpen();
1622 pos_translator.update(m_position);
1628 void MobV2CAO::setLooks(const std::string &looks)
1630 v2f selection_size = v2f(0.4, 0.4) * BS;
1631 float selection_y = 0 * BS;
1633 if(looks == "dungeon_master"){
1634 m_texture_name = "dungeon_master.png";
1635 m_sprite_type = "humanoid_1";
1636 m_sprite_size = v2f(2, 3) * BS;
1637 m_sprite_y = 0.85 * BS;
1638 selection_size = v2f(0.4, 2.6) * BS;
1639 selection_y = -0.4 * BS;
1641 else if(looks == "fireball"){
1642 m_texture_name = "fireball.png";
1643 m_sprite_type = "simple";
1644 m_sprite_size = v2f(1, 1) * BS;
1645 m_simple_anim_frames = 3;
1646 m_simple_anim_frametime = 0.1;
1647 m_lock_full_brightness = true;
1650 m_texture_name = "stone.png";
1651 m_sprite_type = "simple";
1652 m_sprite_size = v2f(1, 1) * BS;
1653 m_simple_anim_frames = 3;
1654 m_simple_anim_frametime = 0.333;
1655 selection_size = v2f(0.4, 0.4) * BS;
1656 selection_y = 0 * BS;
1659 m_selection_box = core::aabbox3d<f32>(
1660 -selection_size.X, selection_y, -selection_size.X,
1661 selection_size.X, selection_y+selection_size.Y,
1669 #include "luaentity_common.h"
1671 class LuaEntityCAO : public ClientActiveObject
1674 core::aabbox3d<f32> m_selection_box;
1675 scene::IMeshSceneNode *m_meshnode;
1676 scene::IBillboardSceneNode *m_spritenode;
1681 struct LuaEntityProperties *m_prop;
1682 SmoothTranslator pos_translator;
1683 // Spritesheet/animation stuff
1686 bool m_tx_select_horiz_by_yawpitch;
1688 int m_anim_num_frames;
1689 float m_anim_framelength;
1693 LuaEntityCAO(IGameDef *gamedef, ClientEnvironment *env):
1694 ClientActiveObject(0, gamedef, env),
1695 m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.),
1698 m_position(v3f(0,10*BS,0)),
1699 m_velocity(v3f(0,0,0)),
1700 m_acceleration(v3f(0,0,0)),
1702 m_prop(new LuaEntityProperties),
1705 m_tx_select_horiz_by_yawpitch(false),
1707 m_anim_num_frames(1),
1708 m_anim_framelength(0.2),
1712 ClientActiveObject::registerType(getType(), create);
1715 void initialize(const std::string &data)
1717 infostream<<"LuaEntityCAO: Got init data"<<std::endl;
1719 std::istringstream is(data, std::ios::binary);
1721 u8 version = readU8(is);
1726 m_position = readV3F1000(is);
1728 m_yaw = readF1000(is);
1730 std::istringstream prop_is(deSerializeLongString(is), std::ios::binary);
1731 m_prop->deSerialize(prop_is);
1733 infostream<<"m_prop: "<<m_prop->dump()<<std::endl;
1735 m_selection_box = m_prop->collisionbox;
1736 m_selection_box.MinEdge *= BS;
1737 m_selection_box.MaxEdge *= BS;
1739 pos_translator.init(m_position);
1741 m_tx_size.X = 1.0 / m_prop->spritediv.X;
1742 m_tx_size.Y = 1.0 / m_prop->spritediv.Y;
1743 m_tx_basepos.X = m_tx_size.X * m_prop->initial_sprite_basepos.X;
1744 m_tx_basepos.Y = m_tx_size.Y * m_prop->initial_sprite_basepos.Y;
1754 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
1756 return new LuaEntityCAO(gamedef, env);
1761 return ACTIVEOBJECT_TYPE_LUAENTITY;
1763 core::aabbox3d<f32>* getSelectionBox()
1765 return &m_selection_box;
1769 return pos_translator.vect_show;
1772 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
1773 IrrlichtDevice *irr)
1775 if(m_meshnode != NULL || m_spritenode != NULL)
1778 //video::IVideoDriver* driver = smgr->getVideoDriver();
1780 if(m_prop->visual == "sprite"){
1781 infostream<<"LuaEntityCAO::addToScene(): single_sprite"<<std::endl;
1782 m_spritenode = smgr->addBillboardSceneNode(
1783 NULL, v2f(1, 1), v3f(0,0,0), -1);
1784 m_spritenode->setMaterialTexture(0,
1785 tsrc->getTextureRaw("unknown_block.png"));
1786 m_spritenode->setMaterialFlag(video::EMF_LIGHTING, false);
1787 m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
1788 m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
1789 m_spritenode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
1790 m_spritenode->setColor(video::SColor(255,0,0,0));
1791 m_spritenode->setVisible(false); /* Set visible when brightness is known */
1792 m_spritenode->setSize(m_prop->visual_size*BS);
1794 const float txs = 1.0 / 1;
1795 const float tys = 1.0 / 1;
1796 setBillboardTextureMatrix(m_spritenode,
1799 } else if(m_prop->visual == "cube"){
1800 infostream<<"LuaEntityCAO::addToScene(): cube"<<std::endl;
1801 scene::IMesh *mesh = createCubeMesh(v3f(BS,BS,BS));
1802 m_meshnode = smgr->addMeshSceneNode(mesh, NULL);
1805 m_meshnode->setScale(v3f(1));
1806 // Will be shown when we know the brightness
1807 m_meshnode->setVisible(false);
1809 infostream<<"LuaEntityCAO::addToScene(): \""<<m_prop->visual
1810 <<"\" not supported"<<std::endl;
1816 void removeFromScene()
1819 m_meshnode->remove();
1823 m_spritenode->remove();
1824 m_spritenode = NULL;
1828 void updateLight(u8 light_at_pos)
1830 u8 li = decode_light(light_at_pos);
1831 video::SColor color(255,li,li,li);
1833 setMeshColor(m_meshnode->getMesh(), color);
1834 m_meshnode->setVisible(true);
1837 m_spritenode->setColor(color);
1838 m_spritenode->setVisible(true);
1842 v3s16 getLightPosition()
1844 return floatToInt(m_position, BS);
1847 void updateNodePos()
1850 m_meshnode->setPosition(pos_translator.vect_show);
1853 m_spritenode->setPosition(pos_translator.vect_show);
1857 void step(float dtime, ClientEnvironment *env)
1859 if(m_prop->physical){
1860 core::aabbox3d<f32> box = m_prop->collisionbox;
1863 collisionMoveResult moveresult;
1864 f32 pos_max_d = BS*0.25; // Distance per iteration
1865 v3f p_pos = m_position;
1866 v3f p_velocity = m_velocity;
1867 IGameDef *gamedef = env->getGameDef();
1868 moveresult = collisionMovePrecise(&env->getMap(), gamedef,
1869 pos_max_d, box, dtime, p_pos, p_velocity);
1872 m_velocity = p_velocity;
1874 bool is_end_position = moveresult.collides;
1875 pos_translator.update(m_position, is_end_position, dtime);
1876 pos_translator.translate(dtime);
1879 m_velocity += dtime * m_acceleration;
1881 m_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration;
1882 m_velocity += dtime * m_acceleration;
1883 pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time);
1884 pos_translator.translate(dtime);
1888 m_anim_timer += dtime;
1889 if(m_anim_timer >= m_anim_framelength){
1890 m_anim_timer -= m_anim_framelength;
1892 if(m_anim_frame >= m_anim_num_frames)
1899 void updateTexturePos()
1902 scene::ICameraSceneNode* camera =
1903 m_spritenode->getSceneManager()->getActiveCamera();
1906 v3f cam_to_entity = m_spritenode->getAbsolutePosition()
1907 - camera->getAbsolutePosition();
1908 cam_to_entity.normalize();
1910 int row = m_tx_basepos.Y;
1911 int col = m_tx_basepos.X;
1913 if(m_tx_select_horiz_by_yawpitch)
1915 if(cam_to_entity.Y > 0.75)
1917 else if(cam_to_entity.Y < -0.75)
1920 float mob_dir = atan2(cam_to_entity.Z, cam_to_entity.X) / PI * 180.;
1921 float dir = mob_dir - m_yaw;
1922 dir = wrapDegrees_180(dir);
1923 //infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
1924 if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
1926 else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
1928 else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
1930 else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
1937 // Animation goes downwards
1938 row += m_anim_frame;
1940 float txs = m_tx_size.X;
1941 float tys = m_tx_size.Y;
1942 setBillboardTextureMatrix(m_spritenode,
1943 txs, tys, col, row);
1947 void updateTextures(const std::string &mod)
1949 ITextureSource *tsrc = m_gamedef->tsrc();
1952 std::string texturestring = "unknown_block.png";
1953 if(m_prop->textures.size() >= 1)
1954 texturestring = m_prop->textures[0];
1955 texturestring += mod;
1956 m_spritenode->setMaterialTexture(0,
1957 tsrc->getTextureRaw(texturestring));
1960 for (u32 i = 0; i < 6; ++i)
1962 std::string texturestring = "unknown_block.png";
1963 if(m_prop->textures.size() > i)
1964 texturestring = m_prop->textures[i];
1965 texturestring += mod;
1966 AtlasPointer ap = tsrc->getTexture(texturestring);
1968 // Get the tile texture and atlas transformation
1969 video::ITexture* atlas = ap.atlas;
1973 // Set material flags and texture
1974 video::SMaterial& material = m_meshnode->getMaterial(i);
1975 material.setFlag(video::EMF_LIGHTING, false);
1976 material.setFlag(video::EMF_BILINEAR_FILTER, false);
1977 material.setTexture(0, atlas);
1978 material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
1979 material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
1984 void processMessage(const std::string &data)
1986 //infostream<<"LuaEntityCAO: Got message"<<std::endl;
1987 std::istringstream is(data, std::ios::binary);
1989 u8 cmd = readU8(is);
1990 if(cmd == 0) // update position
1993 bool do_interpolate = readU8(is);
1995 m_position = readV3F1000(is);
1997 m_velocity = readV3F1000(is);
1999 m_acceleration = readV3F1000(is);
2001 m_yaw = readF1000(is);
2002 // is_end_position (for interpolation)
2003 bool is_end_position = readU8(is);
2005 float update_interval = readF1000(is);
2008 if(!m_prop->physical)
2009 pos_translator.update(m_position, is_end_position, update_interval);
2011 pos_translator.init(m_position);
2015 else if(cmd == 1) // set texture modification
2017 std::string mod = deSerializeString(is);
2018 updateTextures(mod);
2020 else if(cmd == 2) // set sprite
2022 v2s16 p = readV2S16(is);
2023 int num_frames = readU16(is);
2024 float framelength = readF1000(is);
2025 bool select_horiz_by_yawpitch = readU8(is);
2028 m_anim_num_frames = num_frames;
2029 m_anim_framelength = framelength;
2030 m_tx_select_horiz_by_yawpitch = select_horiz_by_yawpitch;
2038 LuaEntityCAO proto_LuaEntityCAO(NULL, NULL);
2044 class PlayerCAO : public ClientActiveObject
2047 core::aabbox3d<f32> m_selection_box;
2048 scene::IMeshSceneNode *m_node;
2049 scene::ITextSceneNode* m_text;
2053 SmoothTranslator pos_translator;
2054 bool m_is_local_player;
2055 LocalPlayer *m_local_player;
2056 float m_damage_visual_timer;
2059 PlayerCAO(IGameDef *gamedef, ClientEnvironment *env):
2060 ClientActiveObject(0, gamedef, env),
2061 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.0,BS/3.),
2064 m_position(v3f(0,10*BS,0)),
2066 m_is_local_player(false),
2067 m_local_player(NULL),
2068 m_damage_visual_timer(0)
2071 ClientActiveObject::registerType(getType(), create);
2074 void initialize(const std::string &data)
2076 infostream<<"PlayerCAO: Got init data"<<std::endl;
2078 std::istringstream is(data, std::ios::binary);
2080 u8 version = readU8(is);
2085 m_name = deSerializeString(is);
2087 m_position = readV3F1000(is);
2089 m_yaw = readF1000(is);
2091 pos_translator.init(m_position);
2093 Player *player = m_env->getPlayer(m_name.c_str());
2094 if(player && player->isLocal()){
2095 m_is_local_player = true;
2096 m_local_player = (LocalPlayer*)player;
2106 static ClientActiveObject* create(IGameDef *gamedef, ClientEnvironment *env)
2108 return new PlayerCAO(gamedef, env);
2113 return ACTIVEOBJECT_TYPE_PLAYER;
2115 core::aabbox3d<f32>* getSelectionBox()
2117 if(m_is_local_player)
2119 return &m_selection_box;
2123 return pos_translator.vect_show;
2126 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
2127 IrrlichtDevice *irr)
2131 if(m_is_local_player)
2134 //video::IVideoDriver* driver = smgr->getVideoDriver();
2135 gui::IGUIEnvironment* gui = irr->getGUIEnvironment();
2137 scene::SMesh *mesh = new scene::SMesh();
2139 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
2140 video::SColor c(255,255,255,255);
2141 video::S3DVertex vertices[4] =
2143 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
2144 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
2145 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
2146 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
2148 u16 indices[] = {0,1,2,2,3,0};
2149 buf->append(vertices, 4, indices, 6);
2151 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
2152 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
2153 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
2154 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
2156 mesh->addMeshBuffer(buf);
2160 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
2161 video::SColor c(255,255,255,255);
2162 video::S3DVertex vertices[4] =
2164 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
2165 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
2166 video::S3DVertex(-BS/2,BS*2,0, 0,0,0, c, 0,0),
2167 video::S3DVertex(BS/2,BS*2,0, 0,0,0, c, 1,0),
2169 u16 indices[] = {0,1,2,2,3,0};
2170 buf->append(vertices, 4, indices, 6);
2172 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
2173 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
2174 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
2175 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
2177 mesh->addMeshBuffer(buf);
2180 m_node = smgr->addMeshSceneNode(mesh, NULL);
2182 // Set it to use the materials of the meshbuffers directly.
2183 // This is needed for changing the texture in the future
2184 m_node->setReadOnlyMaterials(true);
2187 // Add a text node for showing the name
2188 std::wstring wname = narrow_to_wide(m_name);
2189 m_text = smgr->addTextSceneNode(gui->getBuiltInFont(),
2190 wname.c_str(), video::SColor(255,255,255,255), m_node);
2191 m_text->setPosition(v3f(0, (f32)BS*2.1, 0));
2197 void removeFromScene()
2206 void updateLight(u8 light_at_pos)
2211 m_node->setVisible(true);
2213 u8 li = decode_light(light_at_pos);
2214 video::SColor color(255,li,li,li);
2215 setMeshColor(m_node->getMesh(), color);
2218 v3s16 getLightPosition()
2220 return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
2223 void updateNodePos()
2228 m_node->setPosition(pos_translator.vect_show);
2230 v3f rot = m_node->getRotation();
2232 m_node->setRotation(rot);
2235 void step(float dtime, ClientEnvironment *env)
2237 pos_translator.translate(dtime);
2240 if(m_damage_visual_timer > 0){
2241 m_damage_visual_timer -= dtime;
2242 if(m_damage_visual_timer <= 0){
2248 void processMessage(const std::string &data)
2250 //infostream<<"PlayerCAO: Got message"<<std::endl;
2251 std::istringstream is(data, std::ios::binary);
2253 u8 cmd = readU8(is);
2254 if(cmd == 0) // update position
2257 m_position = readV3F1000(is);
2259 m_yaw = readF1000(is);
2261 pos_translator.update(m_position, false);
2265 else if(cmd == 1) // punched
2268 s16 damage = readS16(is);
2270 if(m_is_local_player)
2271 m_env->damageLocalPlayer(damage, false);
2273 m_damage_visual_timer = 0.5;
2274 updateTextures("^[brighten");
2278 void updateTextures(const std::string &mod)
2282 ITextureSource *tsrc = m_gamedef->tsrc();
2283 scene::IMesh *mesh = m_node->getMesh();
2286 std::string tname = "player.png";
2288 scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
2289 buf->getMaterial().setTexture(0,
2290 tsrc->getTextureRaw(tname));
2293 std::string tname = "player_back.png";
2295 scene::IMeshBuffer *buf = mesh->getMeshBuffer(1);
2296 buf->getMaterial().setTexture(0,
2297 tsrc->getTextureRaw(tname));
2304 PlayerCAO proto_PlayerCAO(NULL, NULL);