summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPerttu Ahola <celeron55@gmail.com>2012-03-10 01:38:48 +0200
committerPerttu Ahola <celeron55@gmail.com>2012-03-10 11:28:14 +0200
commitf9da2c9507f10a9193c9bd94d69cc85e53b58ba2 (patch)
tree00885e82f4ab7ff193d481637bbfdeb80c41d0a6
parent989aba1966373885d4cac306daea25e102f8d68d (diff)
downloadminetest-f9da2c9507f10a9193c9bd94d69cc85e53b58ba2.tar.gz
minetest-f9da2c9507f10a9193c9bd94d69cc85e53b58ba2.tar.bz2
minetest-f9da2c9507f10a9193c9bd94d69cc85e53b58ba2.zip
Immediate smoke puff when a normal entity is punched to death
-rw-r--r--data/clienttextures/smoke_puff.pngbin0 -> 2182 bytes
-rw-r--r--data/mods/experimental/init.lua29
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/clientsimpleobject.h38
-rw-r--r--src/content_cao.cpp23
-rw-r--r--src/content_cso.cpp89
-rw-r--r--src/content_cso.h30
-rw-r--r--src/content_sao.cpp46
-rw-r--r--src/environment.cpp29
-rw-r--r--src/environment.h8
-rw-r--r--src/scriptapi.cpp24
-rw-r--r--src/scriptapi.h3
12 files changed, 286 insertions, 34 deletions
diff --git a/data/clienttextures/smoke_puff.png b/data/clienttextures/smoke_puff.png
new file mode 100644
index 000000000..e346d204c
--- /dev/null
+++ b/data/clienttextures/smoke_puff.png
Binary files differ
diff --git a/data/mods/experimental/init.lua b/data/mods/experimental/init.lua
index 76b787031..1ee3fdc2e 100644
--- a/data/mods/experimental/init.lua
+++ b/data/mods/experimental/init.lua
@@ -378,10 +378,9 @@ minetest.register_alias("TNT", "experimental:tnt")
-- The dummyball!
--
-minetest.register_alias("dummyball", "experimental:dummyball")
-
minetest.register_entity("experimental:dummyball", {
-- Static definition
+ hp_max = 20,
physical = false,
collisionbox = {-0.4,-0.4,-0.4, 0.4,0.4,0.4},
visual = "sprite",
@@ -419,6 +418,32 @@ minetest.register_entity("experimental:dummyball", {
end,
})
+minetest.register_on_chat_message(function(name, message)
+ local cmd = "/dummyball"
+ if message:sub(0, #cmd) == cmd then
+ if not minetest.get_player_privs(name)["give"] then
+ minetest.chat_send_player(name, "you don't have permission to spawn (give)")
+ return true -- Handled chat message
+ end
+ if not minetest.get_player_privs(name)["interact"] then
+ minetest.chat_send_player(name, "you don't have permission to interact")
+ return true -- Handled chat message
+ end
+ local player = minetest.env:get_player_by_name(name)
+ if player == nil then
+ print("Unable to spawn entity, player is nil")
+ return true -- Handled chat message
+ end
+ local entityname = "experimental:dummyball"
+ local p = player:getpos()
+ p.y = p.y + 1
+ minetest.env:add_entity(p, entityname)
+ minetest.chat_send_player(name, '"'..entityname
+ ..'" spawned.');
+ return true -- Handled chat message
+ end
+end)
+
--
-- A test entity for testing animated and yaw-modulated sprites
--
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 860722712..d72128e01 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -157,6 +157,7 @@ endif()
# Client sources
set(minetest_SRCS
${common_SRCS}
+ content_cso.cpp
content_mapblock.cpp
content_cao.cpp
mesh.cpp
diff --git a/src/clientsimpleobject.h b/src/clientsimpleobject.h
new file mode 100644
index 000000000..ad0abfe3c
--- /dev/null
+++ b/src/clientsimpleobject.h
@@ -0,0 +1,38 @@
+/*
+Minetest-c55
+Copyright (C) 2012 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef CLIENTSIMPLEOBJECT_HEADER
+#define CLIENTSIMPLEOBJECT_HEADER
+
+#include "irrlichttypes.h"
+class ClientEnvironment;
+
+class ClientSimpleObject
+{
+protected:
+public:
+ bool m_to_be_removed;
+
+ ClientSimpleObject(): m_to_be_removed(false) {}
+ virtual ~ClientSimpleObject(){}
+ virtual void step(float dtime){}
+};
+
+#endif
+
diff --git a/src/content_cao.cpp b/src/content_cao.cpp
index 01f13df4e..3aba4c7cb 100644
--- a/src/content_cao.cpp
+++ b/src/content_cao.cpp
@@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "utility.h" // For IntervalLimiter
#include "itemdef.h"
#include "tool.h"
+#include "content_cso.h"
class Settings;
struct ToolCapabilities;
@@ -538,6 +539,7 @@ void ItemCAO::initialize(const std::string &data)
class LuaEntityCAO : public ClientActiveObject
{
private:
+ scene::ISceneManager *m_smgr;
core::aabbox3d<f32> m_selection_box;
scene::IMeshSceneNode *m_meshnode;
scene::IBillboardSceneNode *m_spritenode;
@@ -562,6 +564,7 @@ private:
public:
LuaEntityCAO(IGameDef *gamedef, ClientEnvironment *env):
ClientActiveObject(0, gamedef, env),
+ m_smgr(NULL),
m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.),
m_meshnode(NULL),
m_spritenode(NULL),
@@ -646,6 +649,8 @@ public:
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
IrrlichtDevice *irr)
{
+ m_smgr = smgr;
+
if(m_meshnode != NULL || m_spritenode != NULL)
return;
@@ -701,15 +706,16 @@ public:
void updateLight(u8 light_at_pos)
{
+ bool is_visible = (m_hp != 0);
u8 li = decode_light(light_at_pos);
video::SColor color(255,li,li,li);
if(m_meshnode){
setMeshColor(m_meshnode->getMesh(), color);
- m_meshnode->setVisible(true);
+ m_meshnode->setVisible(is_visible);
}
if(m_spritenode){
m_spritenode->setColor(color);
- m_spritenode->setVisible(true);
+ m_spritenode->setVisible(is_visible);
}
}
@@ -947,12 +953,19 @@ public:
if(result.did_punch && result.damage != 0)
{
- if(result.damage < m_hp)
+ if(result.damage < m_hp){
m_hp -= result.damage;
- else
+ } else {
m_hp = 0;
+ // TODO: Execute defined fast response
+ // As there is no definition, make a smoke puff
+ ClientSimpleObject *simple = createSmokePuff(
+ m_smgr, m_env, m_position,
+ m_prop->visual_size * BS);
+ m_env->addSimpleObject(simple);
+ }
// TODO: Execute defined fast response
- // I guess flashing is fine as of now
+ // Flashing shall suffice as there is no definition
updateTextures("^[brighten");
m_reset_textures_timer = 0.1;
}
diff --git a/src/content_cso.cpp b/src/content_cso.cpp
new file mode 100644
index 000000000..ce6ce0a21
--- /dev/null
+++ b/src/content_cso.cpp
@@ -0,0 +1,89 @@
+/*
+Minetest-c55
+Copyright (C) 2012 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "content_cso.h"
+#include <IBillboardSceneNode.h>
+#include "tile.h"
+#include "environment.h"
+#include "gamedef.h"
+#include "log.h"
+
+static void setBillboardTextureMatrix(scene::IBillboardSceneNode *bill,
+ float txs, float tys, int col, int row)
+{
+ video::SMaterial& material = bill->getMaterial(0);
+ core::matrix4& matrix = material.getTextureMatrix(0);
+ matrix.setTextureTranslate(txs*col, tys*row);
+ matrix.setTextureScale(txs, tys);
+}
+
+class SmokePuffCSO: public ClientSimpleObject
+{
+ float m_age;
+ scene::IBillboardSceneNode *m_spritenode;
+public:
+ SmokePuffCSO(scene::ISceneManager *smgr,
+ ClientEnvironment *env, v3f pos, v2f size):
+ m_age(0),
+ m_spritenode(NULL)
+ {
+ infostream<<"SmokePuffCSO: constructing"<<std::endl;
+ m_spritenode = smgr->addBillboardSceneNode(
+ NULL, v2f(1,1), pos, -1);
+ m_spritenode->setMaterialTexture(0,
+ env->getGameDef()->tsrc()->getTextureRaw("smoke_puff.png"));
+ m_spritenode->setMaterialFlag(video::EMF_LIGHTING, false);
+ m_spritenode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
+ //m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
+ m_spritenode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL);
+ m_spritenode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
+ m_spritenode->setColor(video::SColor(255,0,0,0));
+ m_spritenode->setVisible(true);
+ m_spritenode->setSize(size);
+ /* Update brightness */
+ u8 light = 64;
+ try{
+ MapNode n = env->getMap().getNode(floatToInt(pos, BS));
+ light = decode_light(n.getLightBlend(env->getDayNightRatio(),
+ env->getGameDef()->ndef()));
+ }
+ catch(InvalidPositionException &e){}
+ video::SColor color(255,light,light,light);
+ m_spritenode->setColor(color);
+ }
+ virtual ~SmokePuffCSO()
+ {
+ infostream<<"SmokePuffCSO: destructing"<<std::endl;
+ m_spritenode->remove();
+ }
+ void step(float dtime)
+ {
+ m_age += dtime;
+ if(m_age > 1.0){
+ m_to_be_removed = true;
+ }
+ }
+};
+
+ClientSimpleObject* createSmokePuff(scene::ISceneManager *smgr,
+ ClientEnvironment *env, v3f pos, v2f size)
+{
+ return new SmokePuffCSO(smgr, env, pos, size);
+}
+
diff --git a/src/content_cso.h b/src/content_cso.h
new file mode 100644
index 000000000..127107c16
--- /dev/null
+++ b/src/content_cso.h
@@ -0,0 +1,30 @@
+/*
+Minetest-c55
+Copyright (C) 2012 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef CONTENT_CSO_HEADER
+#define CONTENT_CSO_HEADER
+
+#include "common_irrlicht.h"
+#include "clientsimpleobject.h"
+
+ClientSimpleObject* createSmokePuff(scene::ISceneManager *smgr,
+ ClientEnvironment *env, v3f pos, v2f size);
+
+#endif
+
diff --git a/src/content_sao.cpp b/src/content_sao.cpp
index 568e4b1da..b04f03f26 100644
--- a/src/content_sao.cpp
+++ b/src/content_sao.cpp
@@ -381,42 +381,45 @@ void LuaEntitySAO::addedToEnvironment()
{
ServerActiveObject::addedToEnvironment();
- // Create entity from name and state
+ // Create entity from name
lua_State *L = m_env->getLua();
- m_registered = scriptapi_luaentity_add(L, m_id, m_init_name.c_str(),
- m_init_state.c_str());
+ m_registered = scriptapi_luaentity_add(L, m_id, m_init_name.c_str());
if(m_registered){
// Get properties
scriptapi_luaentity_get_properties(L, m_id, m_prop);
+ // Initialize HP from properties
+ m_hp = m_prop->hp_max;
}
+
+ // Activate entity, supplying serialized state
+ scriptapi_luaentity_activate(L, m_id, m_init_state.c_str());
}
ServerActiveObject* LuaEntitySAO::create(ServerEnvironment *env, v3f pos,
const std::string &data)
{
- std::istringstream is(data, std::ios::binary);
- // read version
- u8 version = readU8(is);
std::string name;
std::string state;
s16 hp = 1;
v3f velocity;
float yaw = 0;
- // check if version is supported
- if(version == 0){
- name = deSerializeString(is);
- state = deSerializeLongString(is);
- }
- else if(version == 1){
- name = deSerializeString(is);
- state = deSerializeLongString(is);
- hp = readS16(is);
- velocity = readV3F1000(is);
- yaw = readF1000(is);
- }
- else{
- return NULL;
+ if(data != ""){
+ std::istringstream is(data, std::ios::binary);
+ // read version
+ u8 version = readU8(is);
+ // check if version is supported
+ if(version == 0){
+ name = deSerializeString(is);
+ state = deSerializeLongString(is);
+ }
+ else if(version == 1){
+ name = deSerializeString(is);
+ state = deSerializeLongString(is);
+ hp = readS16(is);
+ velocity = readV3F1000(is);
+ yaw = readF1000(is);
+ }
}
// create object
infostream<<"LuaEntitySAO::create(name=\""<<name<<"\" state=\""
@@ -581,6 +584,9 @@ int LuaEntitySAO::punch(v3f dir,
ActiveObjectMessage aom(getId(), true, os.str());
m_messages_out.push_back(aom);
}
+
+ if(getHP() == 0)
+ m_removed = true;
}
lua_State *L = m_env->getLua();
diff --git a/src/environment.cpp b/src/environment.cpp
index 6f1d8ff55..6a8943d12 100644
--- a/src/environment.cpp
+++ b/src/environment.cpp
@@ -1806,6 +1806,8 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
#ifndef SERVER
+#include "clientsimpleobject.h"
+
/*
ClientEnvironment
*/
@@ -1831,6 +1833,12 @@ ClientEnvironment::~ClientEnvironment()
delete i.getNode()->getValue();
}
+ for(core::list<ClientSimpleObject*>::Iterator
+ i = m_simple_objects.begin(); i != m_simple_objects.end(); i++)
+ {
+ delete *i;
+ }
+
// Drop/delete map
m_map->drop();
}
@@ -2108,6 +2116,22 @@ void ClientEnvironment::step(float dtime)
obj->updateLight(light);
}
}
+
+ /*
+ Step and handle simple objects
+ */
+ for(core::list<ClientSimpleObject*>::Iterator
+ i = m_simple_objects.begin(); i != m_simple_objects.end();)
+ {
+ ClientSimpleObject *simple = *i;
+ core::list<ClientSimpleObject*>::Iterator cur = i;
+ i++;
+ simple->step(dtime);
+ if(simple->m_to_be_removed){
+ delete simple;
+ m_simple_objects.erase(cur);
+ }
+ }
}
void ClientEnvironment::updateMeshes(v3s16 blockpos)
@@ -2119,6 +2143,11 @@ void ClientEnvironment::expireMeshes(bool only_daynight_diffed)
{
m_map->expireMeshes(only_daynight_diffed);
}
+
+void ClientEnvironment::addSimpleObject(ClientSimpleObject *simple)
+{
+ m_simple_objects.push_back(simple);
+}
ClientActiveObject* ClientEnvironment::getActiveObject(u16 id)
{
diff --git a/src/environment.h b/src/environment.h
index 89c9fd676..fcd16e296 100644
--- a/src/environment.h
+++ b/src/environment.h
@@ -356,6 +356,7 @@ private:
#ifndef SERVER
#include "clientobject.h"
+class ClientSimpleObject;
/*
The client-side environment.
@@ -425,6 +426,12 @@ public:
}
/*
+ ClientSimpleObjects
+ */
+
+ void addSimpleObject(ClientSimpleObject *simple);
+
+ /*
ActiveObjects
*/
@@ -469,6 +476,7 @@ private:
IGameDef *m_gamedef;
IrrlichtDevice *m_irr;
core::map<u16, ClientActiveObject*> m_active_objects;
+ core::list<ClientSimpleObject*> m_simple_objects;
Queue<ClientEnvEvent> m_client_event_queue;
IntervalLimiter m_active_object_light_update_interval;
IntervalLimiter m_lava_hurt_interval;
diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp
index 541baa61c..7bdf7a9f4 100644
--- a/src/scriptapi.cpp
+++ b/src/scriptapi.cpp
@@ -4226,8 +4226,7 @@ void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp)
luaentity
*/
-bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
- const std::string &staticdata)
+bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name)
{
realitycheck(L);
assert(lua_checkstack(L, 20));
@@ -4274,6 +4273,21 @@ bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
lua_pushvalue(L, object); // Copy object to top of stack
lua_settable(L, -3);
+ return true;
+}
+
+void scriptapi_luaentity_activate(lua_State *L, u16 id,
+ const std::string &staticdata)
+{
+ realitycheck(L);
+ assert(lua_checkstack(L, 20));
+ infostream<<"scriptapi_luaentity_activate: id="<<id<<std::endl;
+ StackUnroller stack_unroller(L);
+
+ // Get minetest.luaentities[id]
+ luaentity_get(L, id);
+ int object = lua_gettop(L);
+
// Get on_activate function
lua_pushvalue(L, object);
lua_getfield(L, -1, "on_activate");
@@ -4283,11 +4297,9 @@ bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
lua_pushlstring(L, staticdata.c_str(), staticdata.size());
// Call with 2 arguments, 0 results
if(lua_pcall(L, 2, 0, 0))
- script_error(L, "error running function %s:on_activate: %s\n",
- name, lua_tostring(L, -1));
+ script_error(L, "error running function on_activate: %s\n",
+ lua_tostring(L, -1));
}
-
- return true;
}
void scriptapi_luaentity_rm(lua_State *L, u16 id)
diff --git a/src/scriptapi.h b/src/scriptapi.h
index aa2d9d4c7..f63cab368 100644
--- a/src/scriptapi.h
+++ b/src/scriptapi.h
@@ -75,7 +75,8 @@ bool scriptapi_node_on_dig(lua_State *L, v3s16 p, MapNode node,
/* luaentity */
// Returns true if succesfully added into Lua; false otherwise.
-bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name,
+bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name);
+void scriptapi_luaentity_activate(lua_State *L, u16 id,
const std::string &staticdata);
void scriptapi_luaentity_rm(lua_State *L, u16 id);
std::string scriptapi_luaentity_get_staticdata(lua_State *L, u16 id);