core.registered_on_play_sound, core.register_on_play_sound = make_registration()
core.registered_on_spawn_particle, core.register_on_spawn_particle = make_registration()
core.registered_on_object_properties_change, core.register_on_object_properties_change = make_registration()
+core.registered_on_object_hp_change, core.register_on_object_hp_change = make_registration()
core.registered_nodes = {}
core.registered_items = {}
* `minetest.register_on_object_properties_change(function(obj))`
* Called every time the properties of an object are changed server-side
* May modify the object's properties without the fear of infinite recursion
+* `minetest.register_on_object_hp_change(function(obj))`
+ * Called every time the hp of an object are changes server-side
### Setting-related
* `minetest.settings`: Settings object containing all of the settings from the
* `punch()`: punches the object
* `rightclick()`: rightclicks the object
* `remove()`: removes the object permanently
+* `set_nametag_images(images)`: Provides a list of images to be drawn below the nametag
### `Raycast`
#include "util/numeric.h"
#include "constants.h"
#include "fontengine.h"
+#include "guiscalingfilter.h"
#include "script/scripting_client.h"
#define CAMERA_OFFSET_STEP 200
screen_pos.Y = screensize.Y *
(0.5 - transformed_pos[1] * zDiv * 0.5) - textsize.Height / 2;
core::rect<s32> size(0, 0, textsize.Width, textsize.Height);
- core::rect<s32> bg_size(-2, 0, textsize.Width+2, textsize.Height);
+ core::rect<s32> bg_size(-2, 0, std::max(textsize.Width+2, (u32) nametag->images_dim.Width), textsize.Height + nametag->images_dim.Height);
auto bgcolor = nametag->getBgColor(m_show_nametag_backgrounds);
if (bgcolor.getAlpha() != 0)
font->draw(
translate_string(utf8_to_wide(nametag->text)).c_str(),
size + screen_pos, nametag->textcolor);
+
+ v2s32 image_pos(screen_pos);
+ image_pos.Y += textsize.Height;
+
+ const video::SColor color(255, 255, 255, 255);
+ const video::SColor colors[] = {color, color, color, color};
+
+ for (video::ITexture *texture : nametag->images) {
+ core::dimension2di imgsize(texture->getOriginalSize());
+ core::rect<s32> rect(core::position2d<s32>(0, 0), imgsize);
+ draw2DImageFilterScaled(driver, texture, rect + image_pos, rect, NULL, colors, true);
+ image_pos += core::dimension2di(imgsize.Width, 0);
+ }
+
}
}
}
-
Nametag *Camera::addNametag(scene::ISceneNode *parent_node,
const std::string &text, video::SColor textcolor,
- Optional<video::SColor> bgcolor, const v3f &pos)
+ Optional<video::SColor> bgcolor, const v3f &pos,
+ const std::vector<std::string> &images)
{
- Nametag *nametag = new Nametag(parent_node, text, textcolor, bgcolor, pos);
+ Nametag *nametag = new Nametag(parent_node, text, textcolor, bgcolor, pos, m_client->tsrc(), images);
m_nametags.push_back(nametag);
return nametag;
}
video::SColor textcolor;
Optional<video::SColor> bgcolor;
v3f pos;
+ ITextureSource *texture_source;
+ std::vector<video::ITexture *> images;
+ core::dimension2di images_dim;
Nametag(scene::ISceneNode *a_parent_node,
const std::string &text,
const video::SColor &textcolor,
const Optional<video::SColor> &bgcolor,
- const v3f &pos):
+ const v3f &pos,
+ ITextureSource *tsrc,
+ const std::vector<std::string> &image_names):
parent_node(a_parent_node),
text(text),
textcolor(textcolor),
bgcolor(bgcolor),
- pos(pos)
+ pos(pos),
+ texture_source(tsrc),
+ images(),
+ images_dim(0, 0)
{
+ setImages(image_names);
+ }
+
+ void setImages(const std::vector<std::string> &image_names)
+ {
+ images.clear();
+ images_dim = core::dimension2di(0, 0);
+
+ for (const std::string &image_name : image_names) {
+ video::ITexture *texture = texture_source->getTexture(image_name);
+ core::dimension2di imgsize(texture->getOriginalSize());
+
+ images_dim.Width += imgsize.Width;
+ if (images_dim.Height < imgsize.Height)
+ images_dim.Height = imgsize.Height;
+
+ images.push_back(texture);
+ }
}
video::SColor getBgColor(bool use_fallback) const
Nametag *addNametag(scene::ISceneNode *parent_node,
const std::string &text, video::SColor textcolor,
- Optional<video::SColor> bgcolor, const v3f &pos);
+ Optional<video::SColor> bgcolor, const v3f &pos,
+ const std::vector<std::string> &image_names);
void removeNametag(Nametag *nametag);
// Add nametag
m_nametag = m_client->getCamera()->addNametag(node,
m_prop.nametag, m_prop.nametag_color,
- m_prop.nametag_bgcolor, pos);
+ m_prop.nametag_bgcolor, pos, nametag_images);
} else {
// Update nametag
m_nametag->text = m_prop.nametag;
m_nametag->textcolor = m_prop.nametag_color;
m_nametag->bgcolor = m_prop.nametag_bgcolor;
m_nametag->pos = pos;
+ m_nametag->setImages(nametag_images);
}
}
// Same as 'ObjectRef::l_remove'
if (!m_is_player)
clearChildAttachments();
+ } else {
+ if (m_client->modsLoaded())
+ m_client->getScript()->on_object_hp_change(m_id);
}
} else if (cmd == AO_CMD_UPDATE_ARMOR_GROUPS) {
m_armor_groups.clear();
void setProperties(ObjectProperties newprops);
void updateMeshCulling();
+
+ std::vector<std::string> nametag_images = {};
};
bool selected)
{
if (selected) {
- /* draw hihlighting around selected item */
+ /* draw highlighting around selected item */
if (use_hotbar_selected_image) {
core::rect<s32> imgrect2 = rect;
imgrect2.UpperLeftCorner.X -= (m_padding*2);
runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
}
+void ScriptApiClient::on_object_hp_change(s16 id)
+{
+ SCRIPTAPI_PRECHECKHEADER
+
+ // Get core.on_object_hp_change
+ lua_getglobal(L, "core");
+ lua_getfield(L, -1, "registered_on_object_hp_change");
+
+ // Push data
+ ClientObjectRef::create(L, id);
+
+ // Call functions
+ runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
+}
+
bool ScriptApiClient::on_inventory_open(Inventory *inventory)
{
SCRIPTAPI_PRECHECKHEADER
bool on_play_sound(SimpleSoundSpec spec);
bool on_spawn_particle(struct ParticleParameters param);
void on_object_properties_change(s16 id);
+ void on_object_hp_change(s16 id);
bool on_inventory_open(Inventory *inventory);
void open_enderchest();
return 0;
}
+int ClientObjectRef::l_set_nametag_images(lua_State *L)
+{
+ ClientObjectRef *ref = checkobject(L, 1);
+ GenericCAO *gcao = get_generic_cao(ref, L);
+ gcao->nametag_images.clear();
+ if(lua_istable(L, 2)){
+ lua_pushnil(L);
+ while(lua_next(L, 2) != 0){
+ gcao->nametag_images.push_back(lua_tostring(L, -1));
+ lua_pop(L, 1);
+ }
+ }
+ gcao->updateNametag();
+
+ return 0;
+}
+
ClientObjectRef::ClientObjectRef(ClientActiveObject *object) : m_object(object)
{
}
luamethod(ClientObjectRef, get_properties),
luamethod(ClientObjectRef, set_properties),
luamethod(ClientObjectRef, get_hp),
- luamethod(ClientObjectRef, get_max_hp), luamethod(ClientObjectRef, punch),
- luamethod(ClientObjectRef, rightclick), {0, 0}};
+ luamethod(ClientObjectRef, get_max_hp),
+ luamethod(ClientObjectRef, punch),
+ luamethod(ClientObjectRef, rightclick),
+ luamethod(ClientObjectRef, set_nametag_images), {0, 0}};
// remove(self)
static int l_remove(lua_State *L);
+
+ // set_nametag_images(self, images)
+ static int l_set_nametag_images(lua_State *L);
};