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 = m_texture_name +
903 "^[makealpha:128,0,0^[makealpha:128,128,0";
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;
1284 // Spritesheet/animation stuff
1287 bool m_tx_select_horiz_by_yawpitch;
1289 int m_anim_num_frames;
1290 float m_anim_framelength;
1294 CLuaEntityCAO(IGameDef *gamedef):
1295 LuaEntityCAO(gamedef),
1296 m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.),
1299 m_position(v3f(0,10*BS,0)),
1300 m_velocity(v3f(0,0,0)),
1301 m_acceleration(v3f(0,0,0)),
1303 m_prop(new LuaEntityProperties),
1306 m_tx_select_horiz_by_yawpitch(false),
1308 m_anim_num_frames(1),
1309 m_anim_framelength(0.2),
1312 ClientActiveObject::registerType(getType(), create);
1315 void initialize(const std::string &data)
1317 infostream<<"CLuaEntityCAO: Got init data"<<std::endl;
1319 std::istringstream is(data, std::ios::binary);
1321 u8 version = readU8(is);
1326 m_position = readV3F1000(is);
1328 m_yaw = readF1000(is);
1330 std::istringstream prop_is(deSerializeLongString(is), std::ios::binary);
1331 m_prop->deSerialize(prop_is);
1333 infostream<<"m_prop: "<<m_prop->dump()<<std::endl;
1335 m_selection_box = m_prop->collisionbox;
1336 m_selection_box.MinEdge *= BS;
1337 m_selection_box.MaxEdge *= BS;
1339 pos_translator.init(m_position);
1341 m_tx_size.X = 1.0 / m_prop->spritediv.X;
1342 m_tx_size.Y = 1.0 / m_prop->spritediv.Y;
1343 m_tx_basepos.X = m_tx_size.X * m_prop->initial_sprite_basepos.X;
1344 m_tx_basepos.Y = m_tx_size.Y * m_prop->initial_sprite_basepos.Y;
1354 static ClientActiveObject* create(IGameDef *gamedef)
1356 return new CLuaEntityCAO(gamedef);
1361 return ACTIVEOBJECT_TYPE_LUAENTITY;
1363 core::aabbox3d<f32>* getSelectionBox()
1365 return &m_selection_box;
1369 return pos_translator.vect_show;
1372 void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc)
1374 if(m_meshnode != NULL || m_spritenode != NULL)
1377 //video::IVideoDriver* driver = smgr->getVideoDriver();
1379 if(m_prop->visual == "sprite"){
1380 infostream<<"CLuaEntityCAO::addToScene(): single_sprite"<<std::endl;
1381 m_spritenode = new scene::MyBillboardSceneNode(
1382 smgr->getRootSceneNode(), smgr, -1, v3f(0,0,0), v2f(1,1));
1383 m_spritenode->setMaterialTexture(0,
1384 tsrc->getTextureRaw("unknown_block.png"));
1385 m_spritenode->setMaterialFlag(video::EMF_LIGHTING, false);
1386 m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
1387 m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
1388 m_spritenode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
1389 m_spritenode->setColor(video::SColor(255,0,0,0));
1390 m_spritenode->setVisible(false); /* Set visible when brightness is known */
1391 m_spritenode->setSize(m_prop->visual_size*BS);
1393 const float txs = 1.0 / 1;
1394 const float tys = 1.0 / 1;
1395 m_spritenode->setTCoords(0, v2f(txs*1, tys*1));
1396 m_spritenode->setTCoords(1, v2f(txs*1, tys*0));
1397 m_spritenode->setTCoords(2, v2f(txs*0, tys*0));
1398 m_spritenode->setTCoords(3, v2f(txs*0, tys*1));
1400 } else if(m_prop->visual == "cube"){
1401 infostream<<"CLuaEntityCAO::addToScene(): cube"<<std::endl;
1402 video::SColor c(255,255,255,255);
1403 video::S3DVertex vertices[24] =
1406 video::S3DVertex(-0.5,+0.5,-0.5, 0,1,0, c, 0,1),
1407 video::S3DVertex(-0.5,+0.5,+0.5, 0,1,0, c, 0,0),
1408 video::S3DVertex(+0.5,+0.5,+0.5, 0,1,0, c, 1,0),
1409 video::S3DVertex(+0.5,+0.5,-0.5, 0,1,0, c, 1,1),
1411 video::S3DVertex(-0.5,-0.5,-0.5, 0,-1,0, c, 0,0),
1412 video::S3DVertex(+0.5,-0.5,-0.5, 0,-1,0, c, 1,0),
1413 video::S3DVertex(+0.5,-0.5,+0.5, 0,-1,0, c, 1,1),
1414 video::S3DVertex(-0.5,-0.5,+0.5, 0,-1,0, c, 0,1),
1416 video::S3DVertex(+0.5,-0.5,-0.5, 1,0,0, c, 0,1),
1417 video::S3DVertex(+0.5,+0.5,-0.5, 1,0,0, c, 0,0),
1418 video::S3DVertex(+0.5,+0.5,+0.5, 1,0,0, c, 1,0),
1419 video::S3DVertex(+0.5,-0.5,+0.5, 1,0,0, c, 1,1),
1421 video::S3DVertex(-0.5,-0.5,-0.5, -1,0,0, c, 1,1),
1422 video::S3DVertex(-0.5,-0.5,+0.5, -1,0,0, c, 0,1),
1423 video::S3DVertex(-0.5,+0.5,+0.5, -1,0,0, c, 0,0),
1424 video::S3DVertex(-0.5,+0.5,-0.5, -1,0,0, c, 1,0),
1426 video::S3DVertex(-0.5,-0.5,+0.5, 0,0,1, c, 1,1),
1427 video::S3DVertex(+0.5,-0.5,+0.5, 0,0,1, c, 0,1),
1428 video::S3DVertex(+0.5,+0.5,+0.5, 0,0,1, c, 0,0),
1429 video::S3DVertex(-0.5,+0.5,+0.5, 0,0,1, c, 1,0),
1431 video::S3DVertex(-0.5,-0.5,-0.5, 0,0,-1, c, 0,1),
1432 video::S3DVertex(-0.5,+0.5,-0.5, 0,0,-1, c, 0,0),
1433 video::S3DVertex(+0.5,+0.5,-0.5, 0,0,-1, c, 1,0),
1434 video::S3DVertex(+0.5,-0.5,-0.5, 0,0,-1, c, 1,1),
1437 for(u32 i=0; i<24; ++i){
1438 vertices[i].Pos *= BS;
1439 vertices[i].Pos.Y *= m_prop->visual_size.Y;
1440 vertices[i].Pos.X *= m_prop->visual_size.X;
1441 vertices[i].Pos.Z *= m_prop->visual_size.X;
1444 u16 indices[6] = {0,1,2,2,3,0};
1446 scene::SMesh* mesh = new scene::SMesh();
1447 for (u32 i=0; i<6; ++i)
1449 scene::IMeshBuffer* buf = new scene::SMeshBuffer();
1450 buf->append(vertices + 4 * i, 4, indices, 6);
1451 buf->recalculateBoundingBox();
1452 mesh->addMeshBuffer(buf);
1455 mesh->recalculateBoundingBox();
1457 m_meshnode = smgr->addMeshSceneNode(mesh, NULL);
1459 m_meshnode->setMesh(mesh);
1460 m_meshnode->setScale(v3f(1));
1461 // Will be shown when we know the brightness
1462 m_meshnode->setVisible(false);
1464 infostream<<"CLuaEntityCAO::addToScene(): \""<<m_prop->visual
1465 <<"\" not supported"<<std::endl;
1471 void removeFromScene()
1474 m_meshnode->remove();
1478 m_spritenode->remove();
1479 m_spritenode = NULL;
1483 void updateLight(u8 light_at_pos)
1485 u8 li = decode_light(light_at_pos);
1486 video::SColor color(255,li,li,li);
1488 setMeshVerticesColor(m_meshnode->getMesh(), color);
1489 m_meshnode->setVisible(true);
1492 m_spritenode->setColor(color);
1493 m_spritenode->setVisible(true);
1497 v3s16 getLightPosition()
1499 return floatToInt(m_position, BS);
1502 void updateNodePos()
1505 m_meshnode->setPosition(pos_translator.vect_show);
1508 m_spritenode->setPosition(pos_translator.vect_show);
1512 void step(float dtime, ClientEnvironment *env)
1514 if(m_prop->physical){
1515 core::aabbox3d<f32> box = m_prop->collisionbox;
1518 collisionMoveResult moveresult;
1519 f32 pos_max_d = BS*0.25; // Distance per iteration
1520 v3f p_pos = m_position;
1521 v3f p_velocity = m_velocity;
1522 IGameDef *gamedef = env->getGameDef();
1523 moveresult = collisionMovePrecise(&env->getMap(), gamedef,
1524 pos_max_d, box, dtime, p_pos, p_velocity);
1527 m_velocity = p_velocity;
1529 bool is_end_position = moveresult.collides;
1530 pos_translator.update(m_position, is_end_position, dtime);
1531 pos_translator.translate(dtime);
1534 m_velocity += dtime * m_acceleration;
1536 m_position += dtime * m_velocity + 0.5 * dtime * dtime * m_acceleration;
1537 m_velocity += dtime * m_acceleration;
1538 pos_translator.update(m_position, pos_translator.aim_is_end, pos_translator.anim_time);
1539 pos_translator.translate(dtime);
1543 m_anim_timer += dtime;
1544 if(m_anim_timer >= m_anim_framelength){
1545 m_anim_timer -= m_anim_framelength;
1547 if(m_anim_frame >= m_anim_num_frames)
1554 void updateTexturePos()
1557 scene::ICameraSceneNode* camera =
1558 m_spritenode->getSceneManager()->getActiveCamera();
1561 v3f cam_to_entity = m_spritenode->getAbsolutePosition()
1562 - camera->getAbsolutePosition();
1563 cam_to_entity.normalize();
1565 int row = m_tx_basepos.Y;
1566 int col = m_tx_basepos.X;
1568 if(m_tx_select_horiz_by_yawpitch)
1570 if(cam_to_entity.Y > 0.75)
1572 else if(cam_to_entity.Y < -0.75)
1575 float mob_dir = atan2(cam_to_entity.Z, cam_to_entity.X) / PI * 180.;
1576 float dir = mob_dir - m_yaw;
1577 dir = wrapDegrees_180(dir);
1578 //infostream<<"id="<<m_id<<" dir="<<dir<<std::endl;
1579 if(fabs(wrapDegrees_180(dir - 0)) <= 45.1)
1581 else if(fabs(wrapDegrees_180(dir - 90)) <= 45.1)
1583 else if(fabs(wrapDegrees_180(dir - 180)) <= 45.1)
1585 else if(fabs(wrapDegrees_180(dir + 90)) <= 45.1)
1592 // Animation goes downwards
1593 row += m_anim_frame;
1595 float txs = m_tx_size.X;
1596 float tys = m_tx_size.Y;
1597 m_spritenode->setTCoords(0, v2f(txs*(1+col), tys*(1+row)));
1598 m_spritenode->setTCoords(1, v2f(txs*(1+col), tys*(0+row)));
1599 m_spritenode->setTCoords(2, v2f(txs*(0+col), tys*(0+row)));
1600 m_spritenode->setTCoords(3, v2f(txs*(0+col), tys*(1+row)));
1604 void updateTextures(const std::string &mod)
1606 ITextureSource *tsrc = m_gamedef->tsrc();
1609 std::string texturestring = "unknown_block.png";
1610 if(m_prop->textures.size() >= 1)
1611 texturestring = m_prop->textures[0];
1612 texturestring += mod;
1613 m_spritenode->setMaterialTexture(0,
1614 tsrc->getTextureRaw(texturestring));
1617 for (u32 i = 0; i < 6; ++i)
1619 std::string texturestring = "unknown_block.png";
1620 if(m_prop->textures.size() > i)
1621 texturestring = m_prop->textures[i];
1622 texturestring += mod;
1623 AtlasPointer ap = tsrc->getTexture(texturestring);
1625 // Get the tile texture and atlas transformation
1626 video::ITexture* atlas = ap.atlas;
1630 // Set material flags and texture
1631 video::SMaterial& material = m_meshnode->getMaterial(i);
1632 material.setFlag(video::EMF_LIGHTING, false);
1633 material.setFlag(video::EMF_BILINEAR_FILTER, false);
1634 material.setTexture(0, atlas);
1635 material.getTextureMatrix(0).setTextureTranslate(pos.X, pos.Y);
1636 material.getTextureMatrix(0).setTextureScale(size.X, size.Y);
1641 void processMessage(const std::string &data)
1643 infostream<<"CLuaEntityCAO: Got message"<<std::endl;
1644 std::istringstream is(data, std::ios::binary);
1646 u8 cmd = readU8(is);
1647 if(cmd == 0) // update position
1650 bool do_interpolate = readU8(is);
1652 m_position = readV3F1000(is);
1654 m_velocity = readV3F1000(is);
1656 m_acceleration = readV3F1000(is);
1658 m_yaw = readF1000(is);
1659 // is_end_position (for interpolation)
1660 bool is_end_position = readU8(is);
1662 float update_interval = readF1000(is);
1665 if(!m_prop->physical)
1666 pos_translator.update(m_position, is_end_position, update_interval);
1668 pos_translator.init(m_position);
1672 else if(cmd == 1) // set texture modification
1674 std::string mod = deSerializeString(is);
1675 updateTextures(mod);
1677 else if(cmd == 2) // set sprite
1679 v2s16 p = readV2S16(is);
1680 int num_frames = readU16(is);
1681 float framelength = readF1000(is);
1682 bool select_horiz_by_yawpitch = readU8(is);
1685 m_anim_num_frames = num_frames;
1686 m_anim_framelength = framelength;
1687 m_tx_select_horiz_by_yawpitch = select_horiz_by_yawpitch;
1695 CLuaEntityCAO proto_CLuaEntityCAO(NULL);