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 "serialization.h" // For decompressZlib
28 core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
35 TestCAO proto_TestCAO(NULL);
37 TestCAO::TestCAO(IGameDef *gamedef):
38 ClientActiveObject(0, gamedef),
40 m_position(v3f(0,10*BS,0))
42 ClientActiveObject::registerType(getType(), create);
49 ClientActiveObject* TestCAO::create(IGameDef *gamedef)
51 return new TestCAO(gamedef);
54 void TestCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc)
59 //video::IVideoDriver* driver = smgr->getVideoDriver();
61 scene::SMesh *mesh = new scene::SMesh();
62 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
63 video::SColor c(255,255,255,255);
64 video::S3DVertex vertices[4] =
66 video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
67 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
68 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
69 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),
71 u16 indices[] = {0,1,2,2,3,0};
72 buf->append(vertices, 4, indices, 6);
74 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
75 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
76 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("rat.png"));
77 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
78 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
79 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
81 mesh->addMeshBuffer(buf);
83 m_node = smgr->addMeshSceneNode(mesh, NULL);
88 void TestCAO::removeFromScene()
97 void TestCAO::updateLight(u8 light_at_pos)
101 v3s16 TestCAO::getLightPosition()
103 return floatToInt(m_position, BS);
106 void TestCAO::updateNodePos()
111 m_node->setPosition(m_position);
112 //m_node->setRotation(v3f(0, 45, 0));
115 void TestCAO::step(float dtime, ClientEnvironment *env)
119 v3f rot = m_node->getRotation();
120 //infostream<<"dtime="<<dtime<<", rot.Y="<<rot.Y<<std::endl;
121 rot.Y += dtime * 180;
122 m_node->setRotation(rot);
126 void TestCAO::processMessage(const std::string &data)
128 infostream<<"TestCAO: Got data: "<<data<<std::endl;
129 std::istringstream is(data, std::ios::binary);
147 #include "inventory.h"
150 ItemCAO proto_ItemCAO(NULL);
152 ItemCAO::ItemCAO(IGameDef *gamedef):
153 ClientActiveObject(0, gamedef),
154 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.),
156 m_position(v3f(0,10*BS,0))
158 ClientActiveObject::registerType(getType(), create);
165 ClientActiveObject* ItemCAO::create(IGameDef *gamedef)
167 return new ItemCAO(gamedef);
170 void ItemCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc)
175 //video::IVideoDriver* driver = smgr->getVideoDriver();
177 scene::SMesh *mesh = new scene::SMesh();
178 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
179 video::SColor c(255,255,255,255);
180 video::S3DVertex vertices[4] =
182 /*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1),
183 video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1),
184 video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0),
185 video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/
186 video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1),
187 video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1),
188 video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0),
189 video::S3DVertex(BS/3.,0+BS*2./3.,0, 0,0,0, c, 0,0),
191 u16 indices[] = {0,1,2,2,3,0};
192 buf->append(vertices, 4, indices, 6);
194 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
195 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
196 //buf->getMaterial().setTexture(0, NULL);
197 // Initialize with the stick texture
198 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("stick.png"));
199 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
200 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
201 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
203 mesh->addMeshBuffer(buf);
205 m_node = smgr->addMeshSceneNode(mesh, NULL);
207 // Set it to use the materials of the meshbuffers directly.
208 // This is needed for changing the texture in the future
209 m_node->setReadOnlyMaterials(true);
216 // Create an inventory item to see what is its image
217 std::istringstream is(m_inventorystring, std::ios_base::binary);
218 video::ITexture *texture = NULL;
220 InventoryItem *item = NULL;
221 item = InventoryItem::deSerialize(is, m_gamedef);
222 infostream<<__FUNCTION_NAME<<": m_inventorystring=\""
223 <<m_inventorystring<<"\" -> item="<<item
227 texture = item->getImage();
231 catch(SerializationError &e)
233 infostream<<"WARNING: "<<__FUNCTION_NAME
234 <<": error deSerializing inventorystring \""
235 <<m_inventorystring<<"\""<<std::endl;
238 // Set meshbuffer texture
239 buf->getMaterial().setTexture(0, texture);
242 void ItemCAO::removeFromScene()
251 void ItemCAO::updateLight(u8 light_at_pos)
256 u8 li = decode_light(light_at_pos);
257 video::SColor color(255,li,li,li);
258 setMeshVerticesColor(m_node->getMesh(), color);
261 v3s16 ItemCAO::getLightPosition()
263 return floatToInt(m_position, BS);
266 void ItemCAO::updateNodePos()
271 m_node->setPosition(m_position);
274 void ItemCAO::step(float dtime, ClientEnvironment *env)
278 /*v3f rot = m_node->getRotation();
279 rot.Y += dtime * 120;
280 m_node->setRotation(rot);*/
281 LocalPlayer *player = env->getLocalPlayer();
283 v3f rot = m_node->getRotation();
284 rot.Y = 180.0 - (player->getYaw());
285 m_node->setRotation(rot);
289 void ItemCAO::processMessage(const std::string &data)
291 infostream<<"ItemCAO: Got message"<<std::endl;
292 std::istringstream is(data, std::ios::binary);
298 m_position = readV3F1000(is);
303 void ItemCAO::initialize(const std::string &data)
305 infostream<<"ItemCAO: Got init data"<<std::endl;
308 std::istringstream is(data, std::ios::binary);
310 u8 version = readU8(is);
315 m_position = readV3F1000(is);
317 m_inventorystring = deSerializeString(is);
327 #include "inventory.h"
330 RatCAO proto_RatCAO(NULL);
332 RatCAO::RatCAO(IGameDef *gamedef):
333 ClientActiveObject(0, gamedef),
334 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
336 m_position(v3f(0,10*BS,0)),
339 ClientActiveObject::registerType(getType(), create);
346 ClientActiveObject* RatCAO::create(IGameDef *gamedef)
348 return new RatCAO(gamedef);
351 void RatCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc)
356 //video::IVideoDriver* driver = smgr->getVideoDriver();
358 scene::SMesh *mesh = new scene::SMesh();
359 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
360 video::SColor c(255,255,255,255);
361 video::S3DVertex vertices[4] =
363 video::S3DVertex(-BS/2,0,0, 0,0,0, c, 0,1),
364 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
365 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
366 video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
368 u16 indices[] = {0,1,2,2,3,0};
369 buf->append(vertices, 4, indices, 6);
371 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
372 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
373 //buf->getMaterial().setTexture(0, NULL);
374 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("rat.png"));
375 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
376 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
377 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
379 mesh->addMeshBuffer(buf);
381 m_node = smgr->addMeshSceneNode(mesh, NULL);
383 // Set it to use the materials of the meshbuffers directly.
384 // This is needed for changing the texture in the future
385 m_node->setReadOnlyMaterials(true);
389 void RatCAO::removeFromScene()
398 void RatCAO::updateLight(u8 light_at_pos)
403 u8 li = decode_light(light_at_pos);
404 video::SColor color(255,li,li,li);
405 setMeshVerticesColor(m_node->getMesh(), color);
408 v3s16 RatCAO::getLightPosition()
410 return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
413 void RatCAO::updateNodePos()
418 //m_node->setPosition(m_position);
419 m_node->setPosition(pos_translator.vect_show);
421 v3f rot = m_node->getRotation();
422 rot.Y = 180.0 - m_yaw;
423 m_node->setRotation(rot);
426 void RatCAO::step(float dtime, ClientEnvironment *env)
428 pos_translator.translate(dtime);
432 void RatCAO::processMessage(const std::string &data)
434 //infostream<<"RatCAO: Got message"<<std::endl;
435 std::istringstream is(data, std::ios::binary);
441 m_position = readV3F1000(is);
442 pos_translator.update(m_position);
444 m_yaw = readF1000(is);
449 void RatCAO::initialize(const std::string &data)
451 //infostream<<"RatCAO: Got init data"<<std::endl;
454 std::istringstream is(data, std::ios::binary);
456 u8 version = readU8(is);
461 m_position = readV3F1000(is);
462 pos_translator.init(m_position);
472 #include "inventory.h"
475 Oerkki1CAO proto_Oerkki1CAO(NULL);
477 Oerkki1CAO::Oerkki1CAO(IGameDef *gamedef):
478 ClientActiveObject(0, gamedef),
479 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2.,BS/3.),
481 m_position(v3f(0,10*BS,0)),
483 m_damage_visual_timer(0),
484 m_damage_texture_enabled(false)
486 ClientActiveObject::registerType(getType(), create);
489 Oerkki1CAO::~Oerkki1CAO()
493 ClientActiveObject* Oerkki1CAO::create(IGameDef *gamedef)
495 return new Oerkki1CAO(gamedef);
498 void Oerkki1CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc)
503 //video::IVideoDriver* driver = smgr->getVideoDriver();
505 scene::SMesh *mesh = new scene::SMesh();
506 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
507 video::SColor c(255,255,255,255);
508 video::S3DVertex vertices[4] =
510 video::S3DVertex(-BS/2-BS,0,0, 0,0,0, c, 0,1),
511 video::S3DVertex(BS/2+BS,0,0, 0,0,0, c, 1,1),
512 video::S3DVertex(BS/2+BS,BS*2,0, 0,0,0, c, 1,0),
513 video::S3DVertex(-BS/2-BS,BS*2,0, 0,0,0, c, 0,0),
515 u16 indices[] = {0,1,2,2,3,0};
516 buf->append(vertices, 4, indices, 6);
518 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
519 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
520 //buf->getMaterial().setTexture(0, NULL);
521 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("oerkki1.png"));
522 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
523 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
524 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
526 mesh->addMeshBuffer(buf);
528 m_node = smgr->addMeshSceneNode(mesh, NULL);
530 // Set it to use the materials of the meshbuffers directly.
531 // This is needed for changing the texture in the future
532 m_node->setReadOnlyMaterials(true);
536 void Oerkki1CAO::removeFromScene()
545 void Oerkki1CAO::updateLight(u8 light_at_pos)
550 if(light_at_pos <= 2)
552 m_node->setVisible(false);
556 m_node->setVisible(true);
558 u8 li = decode_light(light_at_pos);
559 video::SColor color(255,li,li,li);
560 setMeshVerticesColor(m_node->getMesh(), color);
563 v3s16 Oerkki1CAO::getLightPosition()
565 return floatToInt(m_position+v3f(0,BS*1.5,0), BS);
568 void Oerkki1CAO::updateNodePos()
573 //m_node->setPosition(m_position);
574 m_node->setPosition(pos_translator.vect_show);
576 v3f rot = m_node->getRotation();
577 rot.Y = 180.0 - m_yaw + 90.0;
578 m_node->setRotation(rot);
581 void Oerkki1CAO::step(float dtime, ClientEnvironment *env)
583 ITextureSource *tsrc = m_gamedef->tsrc();
585 pos_translator.translate(dtime);
588 LocalPlayer *player = env->getLocalPlayer();
591 v3f playerpos = player->getPosition();
592 v2f playerpos_2d(playerpos.X,playerpos.Z);
593 v2f objectpos_2d(m_position.X,m_position.Z);
595 if(fabs(m_position.Y - playerpos.Y) < 1.5*BS &&
596 objectpos_2d.getDistanceFrom(playerpos_2d) < 1.5*BS)
598 if(m_attack_interval.step(dtime, 0.5))
600 env->damageLocalPlayer(2);
604 if(m_damage_visual_timer > 0)
606 if(!m_damage_texture_enabled)
608 // Enable damage texture
611 /*video::IVideoDriver* driver =
612 m_node->getSceneManager()->getVideoDriver();*/
614 scene::IMesh *mesh = m_node->getMesh();
618 u16 mc = mesh->getMeshBufferCount();
619 for(u16 j=0; j<mc; j++)
621 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
622 buf->getMaterial().setTexture(0,
623 tsrc->getTextureRaw("oerkki1_damaged.png"));
626 m_damage_texture_enabled = true;
628 m_damage_visual_timer -= dtime;
632 if(m_damage_texture_enabled)
634 // Disable damage texture
637 /*video::IVideoDriver* driver =
638 m_node->getSceneManager()->getVideoDriver();*/
640 scene::IMesh *mesh = m_node->getMesh();
644 u16 mc = mesh->getMeshBufferCount();
645 for(u16 j=0; j<mc; j++)
647 scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
648 buf->getMaterial().setTexture(0,
649 tsrc->getTextureRaw("oerkki1.png"));
652 m_damage_texture_enabled = false;
657 void Oerkki1CAO::processMessage(const std::string &data)
659 //infostream<<"Oerkki1CAO: Got message"<<std::endl;
660 std::istringstream is(data, std::ios::binary);
666 m_position = readV3F1000(is);
667 pos_translator.update(m_position);
669 m_yaw = readF1000(is);
674 //u16 damage = readU8(is);
675 m_damage_visual_timer = 1.0;
679 void Oerkki1CAO::initialize(const std::string &data)
681 //infostream<<"Oerkki1CAO: Got init data"<<std::endl;
684 std::istringstream is(data, std::ios::binary);
686 u8 version = readU8(is);
691 m_position = readV3F1000(is);
692 pos_translator.init(m_position);
698 bool Oerkki1CAO::directReportPunch(const std::string &toolname, v3f dir)
700 m_damage_visual_timer = 1.0;
702 m_position += dir * BS;
703 pos_translator.sharpen();
704 pos_translator.update(m_position);
715 FireflyCAO proto_FireflyCAO(NULL);
717 FireflyCAO::FireflyCAO(IGameDef *gamedef):
718 ClientActiveObject(0, gamedef),
719 m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS/2.,BS/3.),
721 m_position(v3f(0,10*BS,0)),
724 ClientActiveObject::registerType(getType(), create);
727 FireflyCAO::~FireflyCAO()
731 ClientActiveObject* FireflyCAO::create(IGameDef *gamedef)
733 return new FireflyCAO(gamedef);
736 void FireflyCAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc)
741 //video::IVideoDriver* driver = smgr->getVideoDriver();
743 scene::SMesh *mesh = new scene::SMesh();
744 scene::IMeshBuffer *buf = new scene::SMeshBuffer();
745 video::SColor c(255,255,255,255);
746 video::S3DVertex vertices[4] =
748 video::S3DVertex(0,0,0, 0,0,0, c, 0,1),
749 video::S3DVertex(BS/2,0,0, 0,0,0, c, 1,1),
750 video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 1,0),
751 video::S3DVertex(0,BS/2,0, 0,0,0, c, 0,0),
753 u16 indices[] = {0,1,2,2,3,0};
754 buf->append(vertices, 4, indices, 6);
756 buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
757 buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
758 //buf->getMaterial().setTexture(0, NULL);
759 buf->getMaterial().setTexture(0, tsrc->getTextureRaw("firefly.png"));
760 buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
761 buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
762 buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
764 mesh->addMeshBuffer(buf);
766 m_node = smgr->addMeshSceneNode(mesh, NULL);
768 // Set it to use the materials of the meshbuffers directly.
769 // This is needed for changing the texture in the future
770 m_node->setReadOnlyMaterials(true);
774 void FireflyCAO::removeFromScene()
783 void FireflyCAO::updateLight(u8 light_at_pos)
789 video::SColor color(255,li,li,li);
790 setMeshVerticesColor(m_node->getMesh(), color);
793 v3s16 FireflyCAO::getLightPosition()
795 return floatToInt(m_position+v3f(0,BS*0.5,0), BS);
798 void FireflyCAO::updateNodePos()
803 //m_node->setPosition(m_position);
804 m_node->setPosition(pos_translator.vect_show);
806 v3f rot = m_node->getRotation();
807 rot.Y = 180.0 - m_yaw;
808 m_node->setRotation(rot);
811 void FireflyCAO::step(float dtime, ClientEnvironment *env)
813 pos_translator.translate(dtime);
817 void FireflyCAO::processMessage(const std::string &data)
819 //infostream<<"FireflyCAO: Got message"<<std::endl;
820 std::istringstream is(data, std::ios::binary);
826 m_position = readV3F1000(is);
827 pos_translator.update(m_position);
829 m_yaw = readF1000(is);
834 void FireflyCAO::initialize(const std::string &data)
836 //infostream<<"FireflyCAO: Got init data"<<std::endl;
839 std::istringstream is(data, std::ios::binary);
841 u8 version = readU8(is);
846 m_position = readV3F1000(is);
847 pos_translator.init(m_position);
858 MobV2CAO proto_MobV2CAO(NULL);
860 MobV2CAO::MobV2CAO(IGameDef *gamedef):
861 ClientActiveObject(0, gamedef),
862 m_selection_box(-0.4*BS,-0.4*BS,-0.4*BS, 0.4*BS,0.8*BS,0.4*BS),
864 m_position(v3f(0,10*BS,0)),
867 m_walking_unset_timer(0),
870 m_damage_visual_timer(0),
873 m_shooting_unset_timer(0),
874 m_sprite_size(BS,BS),
876 m_bright_shooting(false),
877 m_lock_full_brightness(false),
878 m_player_hit_timer(0)
880 ClientActiveObject::registerType(getType(), create);
882 m_properties = new Settings;
885 MobV2CAO::~MobV2CAO()
890 ClientActiveObject* MobV2CAO::create(IGameDef *gamedef)
892 return new MobV2CAO(gamedef);
895 void MobV2CAO::addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc)
900 /*infostream<<"MobV2CAO::addToScene using texture_name="<<
901 m_texture_name<<std::endl;*/
902 std::string texture_string = "[makealpha2:128,0,0;128,128,0:";
903 texture_string += m_texture_name;
905 scene::MyBillboardSceneNode *bill = new scene::MyBillboardSceneNode(
906 smgr->getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1));
907 bill->setMaterialTexture(0, tsrc->getTextureRaw(texture_string));
908 bill->setMaterialFlag(video::EMF_LIGHTING, false);
909 bill->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
910 bill->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
911 bill->setMaterialFlag(video::EMF_FOG_ENABLE, true);
912 bill->setColor(video::SColor(255,0,0,0));
913 bill->setVisible(false); /* Set visible when brightness is known */
914 bill->setSize(m_sprite_size);
915 if(m_sprite_type == "humanoid_1"){
916 const float txp = 1./192;
917 const float txs = txp*32;
918 const float typ = 1./240;
919 const float tys = typ*48;
920 bill->setTCoords(0, v2f(txs*1, tys*1));
921 bill->setTCoords(1, v2f(txs*1, tys*0));
922 bill->setTCoords(2, v2f(txs*0, tys*0));
923 bill->setTCoords(3, v2f(txs*0, tys*1));
924 } else if(m_sprite_type == "simple"){
925 const float txs = 1.0;
926 const float tys = 1.0 / m_simple_anim_frames;
927 bill->setTCoords(0, v2f(txs*1, tys*1));
928 bill->setTCoords(1, v2f(txs*1, tys*0));
929 bill->setTCoords(2, v2f(txs*0, tys*0));
930 bill->setTCoords(3, v2f(txs*0, tys*1));
932 infostream<<"MobV2CAO: Unknown sprite type \""<<m_sprite_type<<"\""
941 void MobV2CAO::removeFromScene()
951 void MobV2CAO::updateLight(u8 light_at_pos)
953 if(m_lock_full_brightness)
956 m_last_light = light_at_pos;
961 if(m_damage_visual_timer > 0)
964 if(m_shooting && m_bright_shooting)
967 /*if(light_at_pos <= 2){
968 m_node->setVisible(false);
972 m_node->setVisible(true);
974 u8 li = decode_light(light_at_pos);
975 video::SColor color(255,li,li,li);
976 m_node->setColor(color);
979 v3s16 MobV2CAO::getLightPosition()
981 return floatToInt(m_position+v3f(0,0,0), BS);
984 void MobV2CAO::updateNodePos()
989 m_node->setPosition(pos_translator.vect_show + v3f(0,m_sprite_y,0));
992 void MobV2CAO::step(float dtime, ClientEnvironment *env)
994 scene::MyBillboardSceneNode *bill = m_node;
998 pos_translator.translate(dtime);
1000 if(m_sprite_type == "humanoid_1"){
1001 scene::ICameraSceneNode* camera = m_node->getSceneManager()->getActiveCamera();
1004 v3f cam_to_mob = m_node->getAbsolutePosition() - camera->getAbsolutePosition();
1005 cam_to_mob.normalize();
1007 if(cam_to_mob.Y > 0.75)
1009 else if(cam_to_mob.Y < -0.75)
1012 float mob_dir = atan2(cam_to_mob.Z, cam_to_mob.X) / PI * 180.;
1013 float dir = mob_dir - m_yaw;
1014 dir = wrapDegrees_180(dir);
1015 //infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
1016 if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
1018 else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
1020 else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
1022 else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
1031 } else if(m_walking){
1032 m_walk_timer += dtime;
1033 if(m_walk_timer >= 0.5){
1034 m_walk_frame = (m_walk_frame + 1) % 2;
1037 if(m_walk_frame == 0)
1043 const float txp = 1./192;
1044 const float txs = txp*32;
1045 const float typ = 1./240;
1046 const float tys = typ*48;
1047 bill->setTCoords(0, v2f(txs*(1+col), tys*(1+row)));
1048 bill->setTCoords(1, v2f(txs*(1+col), tys*(0+row)));
1049 bill->setTCoords(2, v2f(txs*(0+col), tys*(0+row)));
1050 bill->setTCoords(3, v2f(txs*(0+col), tys*(1+row)));
1051 } else if(m_sprite_type == "simple"){
1052 m_walk_timer += dtime;
1053 if(m_walk_timer >= m_simple_anim_frametime){
1054 m_walk_frame = (m_walk_frame + 1) % m_simple_anim_frames;
1058 int row = m_walk_frame;
1059 const float txs = 1.0;
1060 const float tys = 1.0 / m_simple_anim_frames;
1061 bill->setTCoords(0, v2f(txs*(1+col), tys*(1+row)));
1062 bill->setTCoords(1, v2f(txs*(1+col), tys*(0+row)));
1063 bill->setTCoords(2, v2f(txs*(0+col), tys*(0+row)));
1064 bill->setTCoords(3, v2f(txs*(0+col), tys*(1+row)));
1066 infostream<<"MobV2CAO::step(): Unknown sprite type \""
1067 <<m_sprite_type<<"\""<<std::endl;
1072 /* Damage local player */
1073 if(m_player_hit_damage && m_player_hit_timer <= 0.0){
1074 LocalPlayer *player = env->getLocalPlayer();
1077 v3f playerpos = player->getPosition();
1078 v2f playerpos_2d(playerpos.X,playerpos.Z);
1079 v2f objectpos_2d(m_position.X,m_position.Z);
1081 if(fabs(m_position.Y - playerpos.Y) < m_player_hit_distance*BS &&
1082 objectpos_2d.getDistanceFrom(playerpos_2d) < m_player_hit_distance*BS)
1084 env->damageLocalPlayer(m_player_hit_damage);
1085 m_player_hit_timer = m_player_hit_interval;
1091 m_player_hit_timer -= dtime;
1093 if(m_damage_visual_timer >= 0){
1094 m_damage_visual_timer -= dtime;
1095 if(m_damage_visual_timer <= 0){
1096 infostream<<"id="<<m_id<<" damage visual ended"<<std::endl;
1100 m_walking_unset_timer += dtime;
1101 if(m_walking_unset_timer >= 1.0){
1105 m_shooting_unset_timer -= dtime;
1106 if(m_shooting_unset_timer <= 0.0){
1107 if(m_bright_shooting){
1108 u8 li = decode_light(m_last_light);
1109 video::SColor color(255,li,li,li);
1110 bill->setColor(color);
1111 m_bright_shooting = false;
1118 void MobV2CAO::processMessage(const std::string &data)
1120 //infostream<<"MobV2CAO: Got message"<<std::endl;
1121 std::istringstream is(data, std::ios::binary);
1123 u8 cmd = readU8(is);
1129 m_position = readV3F1000(is);
1130 pos_translator.update(m_position);
1132 m_yaw = readF1000(is);
1135 m_walking_unset_timer = 0;
1142 //u16 damage = readU16(is);
1144 /*u8 li = decode_light(m_last_light);
1150 /*video::SColor color(255,255,0,0);
1151 m_node->setColor(color);
1153 m_damage_visual_timer = 0.2;*/
1159 m_shooting_unset_timer = readF1000(is);
1161 m_bright_shooting = readU8(is);
1162 if(m_bright_shooting){
1164 video::SColor color(255,li,li,li);
1165 m_node->setColor(color);
1172 void MobV2CAO::initialize(const std::string &data)
1174 //infostream<<"MobV2CAO: Got init data"<<std::endl;
1177 std::istringstream is(data, std::ios::binary);
1179 u8 version = readU8(is);
1182 infostream<<__FUNCTION_NAME<<": Invalid version"<<std::endl;
1186 std::ostringstream tmp_os(std::ios::binary);
1187 decompressZlib(is, tmp_os);
1188 std::istringstream tmp_is(tmp_os.str(), std::ios::binary);
1189 m_properties->parseConfigLines(tmp_is, "MobArgsEnd");
1191 infostream<<"MobV2CAO::initialize(): got properties:"<<std::endl;
1192 m_properties->writeLines(infostream);
1194 m_properties->setDefault("looks", "dummy_default");
1195 m_properties->setDefault("yaw", "0");
1196 m_properties->setDefault("pos", "(0,0,0)");
1197 m_properties->setDefault("player_hit_damage", "0");
1198 m_properties->setDefault("player_hit_distance", "1.5");
1199 m_properties->setDefault("player_hit_interval", "1.5");
1201 setLooks(m_properties->get("looks"));
1202 m_yaw = m_properties->getFloat("yaw");
1203 m_position = m_properties->getV3F("pos");
1204 m_player_hit_damage = m_properties->getS32("player_hit_damage");
1205 m_player_hit_distance = m_properties->getFloat("player_hit_distance");
1206 m_player_hit_interval = m_properties->getFloat("player_hit_interval");
1208 pos_translator.init(m_position);
1214 bool MobV2CAO::directReportPunch(const std::string &toolname, v3f dir)
1216 video::SColor color(255,255,0,0);
1217 m_node->setColor(color);
1219 m_damage_visual_timer = 0.05;
1221 m_position += dir * BS;
1222 pos_translator.sharpen();
1223 pos_translator.update(m_position);
1229 void MobV2CAO::setLooks(const std::string &looks)
1231 v2f selection_size = v2f(0.4, 0.4) * BS;
1232 float selection_y = 0 * BS;
1234 if(looks == "dungeon_master"){
1235 m_texture_name = "dungeon_master.png";
1236 m_sprite_type = "humanoid_1";
1237 m_sprite_size = v2f(2, 3) * BS;
1238 m_sprite_y = 0.85 * BS;
1239 selection_size = v2f(0.4, 2.6) * BS;
1240 selection_y = -0.4 * BS;
1242 else if(looks == "fireball"){
1243 m_texture_name = "fireball.png";
1244 m_sprite_type = "simple";
1245 m_sprite_size = v2f(1, 1) * BS;
1246 m_simple_anim_frames = 3;
1247 m_simple_anim_frametime = 0.1;
1248 m_lock_full_brightness = true;
1251 m_texture_name = "stone.png";
1252 m_sprite_type = "simple";
1253 m_sprite_size = v2f(1, 1) * BS;
1254 m_simple_anim_frames = 3;
1255 m_simple_anim_frametime = 0.333;
1256 selection_size = v2f(0.4, 0.4) * BS;
1257 selection_y = 0 * BS;
1260 m_selection_box = core::aabbox3d<f32>(
1261 -selection_size.X, selection_y, -selection_size.X,
1262 selection_size.X, selection_y+selection_size.Y,
1270 #include "luaentity_common.h"
1272 class CLuaEntityCAO : public LuaEntityCAO
1275 core::aabbox3d<f32> m_selection_box;
1276 scene::IMeshSceneNode *m_meshnode;
1277 scene::MyBillboardSceneNode *m_spritenode;
1282 struct LuaEntityProperties *m_prop;
1283 SmoothTranslator pos_translator;
1288 return ACTIVEOBJECT_TYPE_LUAENTITY;
1290 core::aabbox3d<f32>* getSelectionBox()
1292 return &m_selection_box;
1296 return pos_translator.vect_show;
1299 CLuaEntityCAO(IGameDef *gamedef):
1300 LuaEntityCAO(gamedef),
1301 m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.),
1304 m_position(v3f(0,10*BS,0)),
1305 m_velocity(v3f(0,0,0)),
1306 m_acceleration(v3f(0,0,0)),
1308 m_prop(new LuaEntityProperties)
1310 ClientActiveObject::registerType(getType(), create);
1318 static ClientActiveObject* create(IGameDef *gamedef)
1320 return new CLuaEntityCAO(gamedef);
1323 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc)
1325 if(m_meshnode != NULL || m_spritenode != NULL)
1328 //video::IVideoDriver* driver = smgr->getVideoDriver();
1330 if(m_prop->visual == "single_sprite"){
1331 infostream<<"CLuaEntityCAO::addToScene(): single_sprite"<<std::endl;
1332 m_spritenode = new scene::MyBillboardSceneNode(
1333 smgr->getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1));
1334 m_spritenode->setMaterialTexture(0,
1335 tsrc->getTextureRaw("unknown_block.png"));
1336 m_spritenode->setMaterialFlag(video::EMF_LIGHTING, false);
1337 m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
1338 m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
1339 m_spritenode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
1340 m_spritenode->setColor(video::SColor(255,0,0,0));
1341 m_spritenode->setVisible(false); /* Set visible when brightness is known */
1342 m_spritenode->setSize(v2f(1,1)*1.0*BS);
1344 const float txs = 1.0 / 1;
1345 const float tys = 1.0 / 1;
1346 m_spritenode->setTCoords(0, v2f(txs*1, tys*1));
1347 m_spritenode->setTCoords(1, v2f(txs*1, tys*0));
1348 m_spritenode->setTCoords(2, v2f(txs*0, tys*0));
1349 m_spritenode->setTCoords(3, v2f(txs*0, tys*1));
1351 } else if(m_prop->visual == "cube"){
1352 infostream<<"CLuaEntityCAO::addToScene(): cube"<<std::endl;
1353 video::SColor c(255,255,255,255);
1354 video::S3DVertex vertices[24] =
1357 video::S3DVertex(-0.5,+0.5,-0.5, 0,1,0, c, 0,1),
1358 video::S3DVertex(-0.5,+0.5,+0.5, 0,1,0, c, 0,0),
1359 video::S3DVertex(+0.5,+0.5,+0.5, 0,1,0, c, 1,0),
1360 video::S3DVertex(+0.5,+0.5,-0.5, 0,1,0, c, 1,1),
1362 video::S3DVertex(-0.5,-0.5,-0.5, 0,-1,0, c, 0,0),
1363 video::S3DVertex(+0.5,-0.5,-0.5, 0,-1,0, c, 1,0),
1364 video::S3DVertex(+0.5,-0.5,+0.5, 0,-1,0, c, 1,1),
1365 video::S3DVertex(-0.5,-0.5,+0.5, 0,-1,0, c, 0,1),
1367 video::S3DVertex(+0.5,-0.5,-0.5, 1,0,0, c, 0,1),
1368 video::S3DVertex(+0.5,+0.5,-0.5, 1,0,0, c, 0,0),
1369 video::S3DVertex(+0.5,+0.5,+0.5, 1,0,0, c, 1,0),
1370 video::S3DVertex(+0.5,-0.5,+0.5, 1,0,0, c, 1,1),
1372 video::S3DVertex(-0.5,-0.5,-0.5, -1,0,0, c, 1,1),
1373 video::S3DVertex(-0.5,-0.5,+0.5, -1,0,0, c, 0,1),
1374 video::S3DVertex(-0.5,+0.5,+0.5, -1,0,0, c, 0,0),
1375 video::S3DVertex(-0.5,+0.5,-0.5, -1,0,0, c, 1,0),
1377 video::S3DVertex(-0.5,-0.5,+0.5, 0,0,1, c, 1,1),
1378 video::S3DVertex(+0.5,-0.5,+0.5, 0,0,1, c, 0,1),
1379 video::S3DVertex(+0.5,+0.5,+0.5, 0,0,1, c, 0,0),
1380 video::S3DVertex(-0.5,+0.5,+0.5, 0,0,1, c, 1,0),
1382 video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1),
1383 video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0),
1384 video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0),
1385 video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1),
1388 for(u32 i=0; i<24; ++i){
1389 vertices[i].Pos *= BS;
1392 u16 indices[6] = {0,1,2,2,3,0};
1394 scene::SMesh* mesh = new scene::SMesh();
1395 for (u32 i=0; i<6; ++i)
1397 scene::IMeshBuffer* buf = new scene::SMeshBuffer();
1398 buf->append(vertices + 4 * i, 4, indices, 6);
1399 buf->recalculateBoundingBox();
1400 mesh->addMeshBuffer(buf);
1403 mesh->recalculateBoundingBox();
1405 m_meshnode = smgr->addMeshSceneNode(mesh, NULL);
1407 m_meshnode->setMesh(mesh);
1408 m_meshnode->setScale(v3f(1));
1409 // Will be shown when we know the brightness
1410 m_meshnode->setVisible(false);
1412 infostream<<"CLuaEntityCAO::addToScene(): \""<<m_prop->visual
1413 <<"\" not supported"<<std::endl;
1419 void removeFromScene()
1422 m_meshnode->remove();
1426 m_spritenode->remove();
1427 m_spritenode = NULL;
1431 void updateLight(u8 light_at_pos)
1433 u8 li = decode_light(light_at_pos);
1434 video::SColor color(255,li,li,li);
1436 setMeshVerticesColor(m_meshnode->getMesh(), color);
1437 m_meshnode->setVisible(true);
1440 m_spritenode->setColor(color);
1441 m_spritenode->setVisible(true);
1445 v3s16 getLightPosition()
1447 return floatToInt(m_position, BS);
1450 void updateNodePos()
1453 m_meshnode->setPosition(pos_translator.vect_show);
1456 m_spritenode->setPosition(pos_translator.vect_show);
1460 void step(float dtime, ClientEnvironment *env)
1462 if(m_prop->physical){
1463 core::aabbox3d<f32> box = m_prop->collisionbox;
1466 collisionMoveResult moveresult;
1467 f32 pos_max_d = BS*0.25; // Distance per iteration
1468 v3f p_pos = m_position;
1469 v3f p_velocity = m_velocity;
1470 IGameDef *gamedef = env->getGameDef();
1471 moveresult = collisionMovePrecise(&env->getMap(), gamedef,
1472 pos_max_d, box, dtime, p_pos, p_velocity);
1475 m_velocity = p_velocity;
1477 bool is_end_position = moveresult.collides;
1478 pos_translator.update(m_position, is_end_position, dtime);
1479 pos_translator.translate(dtime);
1482 m_velocity += dtime * m_acceleration;
1484 m_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration;
1485 m_velocity += dtime * m_acceleration;
1486 pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time);
1487 pos_translator.translate(dtime);
1492 void updateTextures(const std::string &mod)
1494 ITextureSource *tsrc = m_gamedef->tsrc();
1497 std::string texturestring = "unknown_block.png";
1498 if(m_prop->textures.size() >= 1)
1499 texturestring = m_prop->textures[0];
1500 texturestring += mod;
1501 m_spritenode->setMaterialTexture(0,
1502 tsrc->getTextureRaw(texturestring));
1505 for (u32 i = 0; i < 6; ++i)
1507 std::string texturestring = "unknown_block.png";
1508 if(m_prop->textures.size() > i)
1509 texturestring = m_prop->textures[i];
1510 texturestring += mod;
1511 AtlasPointer ap = tsrc->getTexture(texturestring);
1513 // Get the tile texture and atlas transformation
1514 video::ITexture* atlas = ap.atlas;
1518 // Set material flags and texture
1519 video::SMaterial& material = m_meshnode->getMaterial(i);
1520 material.setFlag(video::EMF_LIGHTING, false);
1521 material.setFlag(video::EMF_BILINEAR_FILTER, false);
1522 material.setTexture(0, atlas);
1523 material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
1524 material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
1529 void processMessage(const std::string &data)
1531 infostream<<"CLuaEntityCAO: Got message"<<std::endl;
1532 std::istringstream is(data, std::ios::binary);
1534 u8 cmd = readU8(is);
1535 if(cmd == 0) // update position
1538 bool do_interpolate = readU8(is);
1540 m_position = readV3F1000(is);
1542 m_velocity = readV3F1000(is);
1544 m_acceleration = readV3F1000(is);
1546 m_yaw = readF1000(is);
1547 // is_end_position (for interpolation)
1548 bool is_end_position = readU8(is);
1550 float update_interval = readF1000(is);
1553 if(!m_prop->physical)
1554 pos_translator.update(m_position, is_end_position, update_interval);
1556 pos_translator.init(m_position);
1560 else if(cmd == 1) // set texture modification
1562 std::string mod = deSerializeString(is);
1563 updateTextures(mod);
1567 void initialize(const std::string &data)
1569 infostream<<"CLuaEntityCAO: Got init data"<<std::endl;
1571 std::istringstream is(data, std::ios::binary);
1573 u8 version = readU8(is);
1578 m_position = readV3F1000(is);
1580 m_yaw = readF1000(is);
1582 std::istringstream prop_is(deSerializeLongString(is), std::ios::binary);
1583 m_prop->deSerialize(prop_is);
1585 infostream<<"m_prop: "<<m_prop->dump()<<std::endl;
1587 m_selection_box = m_prop->collisionbox;
1588 m_selection_box.MinEdge *= BS;
1589 m_selection_box.MaxEdge *= BS;
1591 pos_translator.init(m_position);
1598 CLuaEntityCAO proto_CLuaEntityCAO(NULL);