Immediate smoke puff when a normal entity is punched to death

This commit is contained in:
Perttu Ahola 2012-03-10 01:38:48 +02:00
parent 989aba1966
commit f9da2c9507
12 changed files with 286 additions and 34 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -378,10 +378,9 @@ minetest.register_alias("TNT", "experimental:tnt")
-- The dummyball! -- The dummyball!
-- --
minetest.register_alias("dummyball", "experimental:dummyball")
minetest.register_entity("experimental:dummyball", { minetest.register_entity("experimental:dummyball", {
-- Static definition -- Static definition
hp_max = 20,
physical = false, physical = false,
collisionbox = {-0.4,-0.4,-0.4, 0.4,0.4,0.4}, collisionbox = {-0.4,-0.4,-0.4, 0.4,0.4,0.4},
visual = "sprite", visual = "sprite",
@ -419,6 +418,32 @@ minetest.register_entity("experimental:dummyball", {
end, 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 -- A test entity for testing animated and yaw-modulated sprites
-- --

View File

@ -157,6 +157,7 @@ endif()
# Client sources # Client sources
set(minetest_SRCS set(minetest_SRCS
${common_SRCS} ${common_SRCS}
content_cso.cpp
content_mapblock.cpp content_mapblock.cpp
content_cao.cpp content_cao.cpp
mesh.cpp mesh.cpp

38
src/clientsimpleobject.h Normal file
View File

@ -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

View File

@ -33,6 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "utility.h" // For IntervalLimiter #include "utility.h" // For IntervalLimiter
#include "itemdef.h" #include "itemdef.h"
#include "tool.h" #include "tool.h"
#include "content_cso.h"
class Settings; class Settings;
struct ToolCapabilities; struct ToolCapabilities;
@ -538,6 +539,7 @@ void ItemCAO::initialize(const std::string &data)
class LuaEntityCAO : public ClientActiveObject class LuaEntityCAO : public ClientActiveObject
{ {
private: private:
scene::ISceneManager *m_smgr;
core::aabbox3d<f32> m_selection_box; core::aabbox3d<f32> m_selection_box;
scene::IMeshSceneNode *m_meshnode; scene::IMeshSceneNode *m_meshnode;
scene::IBillboardSceneNode *m_spritenode; scene::IBillboardSceneNode *m_spritenode;
@ -562,6 +564,7 @@ private:
public: public:
LuaEntityCAO(IGameDef *gamedef, ClientEnvironment *env): LuaEntityCAO(IGameDef *gamedef, ClientEnvironment *env):
ClientActiveObject(0, gamedef, env), ClientActiveObject(0, gamedef, env),
m_smgr(NULL),
m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.), m_selection_box(-BS/3.,-BS/3.,-BS/3., BS/3.,BS/3.,BS/3.),
m_meshnode(NULL), m_meshnode(NULL),
m_spritenode(NULL), m_spritenode(NULL),
@ -646,6 +649,8 @@ public:
void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc, void addToScene(scene::ISceneManager *smgr, ITextureSource *tsrc,
IrrlichtDevice *irr) IrrlichtDevice *irr)
{ {
m_smgr = smgr;
if(m_meshnode != NULL || m_spritenode != NULL) if(m_meshnode != NULL || m_spritenode != NULL)
return; return;
@ -701,15 +706,16 @@ public:
void updateLight(u8 light_at_pos) void updateLight(u8 light_at_pos)
{ {
bool is_visible = (m_hp != 0);
u8 li = decode_light(light_at_pos); u8 li = decode_light(light_at_pos);
video::SColor color(255,li,li,li); video::SColor color(255,li,li,li);
if(m_meshnode){ if(m_meshnode){
setMeshColor(m_meshnode->getMesh(), color); setMeshColor(m_meshnode->getMesh(), color);
m_meshnode->setVisible(true); m_meshnode->setVisible(is_visible);
} }
if(m_spritenode){ if(m_spritenode){
m_spritenode->setColor(color); 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.did_punch && result.damage != 0)
{ {
if(result.damage < m_hp) if(result.damage < m_hp){
m_hp -= result.damage; m_hp -= result.damage;
else } else {
m_hp = 0; 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 // TODO: Execute defined fast response
// I guess flashing is fine as of now // Flashing shall suffice as there is no definition
updateTextures("^[brighten"); updateTextures("^[brighten");
m_reset_textures_timer = 0.1; m_reset_textures_timer = 0.1;
} }

89
src/content_cso.cpp Normal file
View File

@ -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);
}

30
src/content_cso.h Normal file
View File

@ -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

View File

@ -381,42 +381,45 @@ void LuaEntitySAO::addedToEnvironment()
{ {
ServerActiveObject::addedToEnvironment(); ServerActiveObject::addedToEnvironment();
// Create entity from name and state // Create entity from name
lua_State *L = m_env->getLua(); lua_State *L = m_env->getLua();
m_registered = scriptapi_luaentity_add(L, m_id, m_init_name.c_str(), m_registered = scriptapi_luaentity_add(L, m_id, m_init_name.c_str());
m_init_state.c_str());
if(m_registered){ if(m_registered){
// Get properties // Get properties
scriptapi_luaentity_get_properties(L, m_id, m_prop); 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, ServerActiveObject* LuaEntitySAO::create(ServerEnvironment *env, v3f pos,
const std::string &data) const std::string &data)
{ {
std::istringstream is(data, std::ios::binary);
// read version
u8 version = readU8(is);
std::string name; std::string name;
std::string state; std::string state;
s16 hp = 1; s16 hp = 1;
v3f velocity; v3f velocity;
float yaw = 0; float yaw = 0;
// check if version is supported if(data != ""){
if(version == 0){ std::istringstream is(data, std::ios::binary);
name = deSerializeString(is); // read version
state = deSerializeLongString(is); u8 version = readU8(is);
} // check if version is supported
else if(version == 1){ if(version == 0){
name = deSerializeString(is); name = deSerializeString(is);
state = deSerializeLongString(is); state = deSerializeLongString(is);
hp = readS16(is); }
velocity = readV3F1000(is); else if(version == 1){
yaw = readF1000(is); name = deSerializeString(is);
} state = deSerializeLongString(is);
else{ hp = readS16(is);
return NULL; velocity = readV3F1000(is);
yaw = readF1000(is);
}
} }
// create object // create object
infostream<<"LuaEntitySAO::create(name=\""<<name<<"\" state=\"" infostream<<"LuaEntitySAO::create(name=\""<<name<<"\" state=\""
@ -581,6 +584,9 @@ int LuaEntitySAO::punch(v3f dir,
ActiveObjectMessage aom(getId(), true, os.str()); ActiveObjectMessage aom(getId(), true, os.str());
m_messages_out.push_back(aom); m_messages_out.push_back(aom);
} }
if(getHP() == 0)
m_removed = true;
} }
lua_State *L = m_env->getLua(); lua_State *L = m_env->getLua();

View File

@ -1806,6 +1806,8 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete)
#ifndef SERVER #ifndef SERVER
#include "clientsimpleobject.h"
/* /*
ClientEnvironment ClientEnvironment
*/ */
@ -1831,6 +1833,12 @@ ClientEnvironment::~ClientEnvironment()
delete i.getNode()->getValue(); 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 // Drop/delete map
m_map->drop(); m_map->drop();
} }
@ -2108,6 +2116,22 @@ void ClientEnvironment::step(float dtime)
obj->updateLight(light); 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) void ClientEnvironment::updateMeshes(v3s16 blockpos)
@ -2120,6 +2144,11 @@ void ClientEnvironment::expireMeshes(bool only_daynight_diffed)
m_map->expireMeshes(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) ClientActiveObject* ClientEnvironment::getActiveObject(u16 id)
{ {
core::map<u16, ClientActiveObject*>::Node *n; core::map<u16, ClientActiveObject*>::Node *n;

View File

@ -356,6 +356,7 @@ private:
#ifndef SERVER #ifndef SERVER
#include "clientobject.h" #include "clientobject.h"
class ClientSimpleObject;
/* /*
The client-side environment. The client-side environment.
@ -424,6 +425,12 @@ public:
} }
} }
/*
ClientSimpleObjects
*/
void addSimpleObject(ClientSimpleObject *simple);
/* /*
ActiveObjects ActiveObjects
*/ */
@ -469,6 +476,7 @@ private:
IGameDef *m_gamedef; IGameDef *m_gamedef;
IrrlichtDevice *m_irr; IrrlichtDevice *m_irr;
core::map<u16, ClientActiveObject*> m_active_objects; core::map<u16, ClientActiveObject*> m_active_objects;
core::list<ClientSimpleObject*> m_simple_objects;
Queue<ClientEnvEvent> m_client_event_queue; Queue<ClientEnvEvent> m_client_event_queue;
IntervalLimiter m_active_object_light_update_interval; IntervalLimiter m_active_object_light_update_interval;
IntervalLimiter m_lava_hurt_interval; IntervalLimiter m_lava_hurt_interval;

View File

@ -4226,8 +4226,7 @@ void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp)
luaentity luaentity
*/ */
bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name, bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name)
const std::string &staticdata)
{ {
realitycheck(L); realitycheck(L);
assert(lua_checkstack(L, 20)); 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_pushvalue(L, object); // Copy object to top of stack
lua_settable(L, -3); 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 // Get on_activate function
lua_pushvalue(L, object); lua_pushvalue(L, object);
lua_getfield(L, -1, "on_activate"); 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()); lua_pushlstring(L, staticdata.c_str(), staticdata.size());
// Call with 2 arguments, 0 results // Call with 2 arguments, 0 results
if(lua_pcall(L, 2, 0, 0)) if(lua_pcall(L, 2, 0, 0))
script_error(L, "error running function %s:on_activate: %s\n", script_error(L, "error running function on_activate: %s\n",
name, lua_tostring(L, -1)); lua_tostring(L, -1));
} }
return true;
} }
void scriptapi_luaentity_rm(lua_State *L, u16 id) void scriptapi_luaentity_rm(lua_State *L, u16 id)

View File

@ -75,7 +75,8 @@ bool scriptapi_node_on_dig(lua_State *L, v3s16 p, MapNode node,
/* luaentity */ /* luaentity */
// Returns true if succesfully added into Lua; false otherwise. // 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); const std::string &staticdata);
void scriptapi_luaentity_rm(lua_State *L, u16 id); void scriptapi_luaentity_rm(lua_State *L, u16 id);
std::string scriptapi_luaentity_get_staticdata(lua_State *L, u16 id); std::string scriptapi_luaentity_get_staticdata(lua_State *L, u16 id);