forked from Mirrorlandia_minetest/minetest
Add reasons to on_dieplayer and on_hpchange
This commit is contained in:
parent
2323842dd3
commit
dfc8198349
@ -529,11 +529,11 @@ end
|
|||||||
|
|
||||||
core.registered_on_player_hpchanges = { modifiers = { }, loggers = { } }
|
core.registered_on_player_hpchanges = { modifiers = { }, loggers = { } }
|
||||||
|
|
||||||
function core.registered_on_player_hpchange(player, hp_change)
|
function core.registered_on_player_hpchange(player, hp_change, reason)
|
||||||
local last = false
|
local last = false
|
||||||
for i = #core.registered_on_player_hpchanges.modifiers, 1, -1 do
|
for i = #core.registered_on_player_hpchanges.modifiers, 1, -1 do
|
||||||
local func = core.registered_on_player_hpchanges.modifiers[i]
|
local func = core.registered_on_player_hpchanges.modifiers[i]
|
||||||
hp_change, last = func(player, hp_change)
|
hp_change, last = func(player, hp_change, reason)
|
||||||
if type(hp_change) ~= "number" then
|
if type(hp_change) ~= "number" then
|
||||||
local debuginfo = debug.getinfo(func)
|
local debuginfo = debug.getinfo(func)
|
||||||
error("The register_on_hp_changes function has to return a number at " ..
|
error("The register_on_hp_changes function has to return a number at " ..
|
||||||
@ -544,7 +544,7 @@ function core.registered_on_player_hpchange(player, hp_change)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
for i, func in ipairs(core.registered_on_player_hpchanges.loggers) do
|
for i, func in ipairs(core.registered_on_player_hpchanges.loggers) do
|
||||||
func(player, hp_change)
|
func(player, hp_change, reason)
|
||||||
end
|
end
|
||||||
return hp_change
|
return hp_change
|
||||||
end
|
end
|
||||||
|
@ -1136,7 +1136,7 @@ previous.
|
|||||||
|
|
||||||
This combination results in noise varying very roughly between -2.0 and 2.0 and
|
This combination results in noise varying very roughly between -2.0 and 2.0 and
|
||||||
with an average value of 0.0, so `scale` and `offset` are then used to multiply
|
with an average value of 0.0, so `scale` and `offset` are then used to multiply
|
||||||
and offset the noise variation.
|
and offset the noise variation.
|
||||||
|
|
||||||
The final perlin noise variation is created as follows:
|
The final perlin noise variation is created as follows:
|
||||||
|
|
||||||
@ -2779,8 +2779,6 @@ Call these functions only at load time!
|
|||||||
is a bit faster than usually.
|
is a bit faster than usually.
|
||||||
* `minetest.register_on_newplayer(func(ObjectRef))`
|
* `minetest.register_on_newplayer(func(ObjectRef))`
|
||||||
* Called after a new player has been created
|
* Called after a new player has been created
|
||||||
* `minetest.register_on_dieplayer(func(ObjectRef))`
|
|
||||||
* Called when a player dies
|
|
||||||
* `minetest.register_on_punchplayer(func(player, hitter, time_from_last_punch, tool_capabilities, dir, damage))`
|
* `minetest.register_on_punchplayer(func(player, hitter, time_from_last_punch, tool_capabilities, dir, damage))`
|
||||||
* Called when a player is punched
|
* Called when a player is punched
|
||||||
* `player` - ObjectRef - Player that was punched
|
* `player` - ObjectRef - Player that was punched
|
||||||
@ -2792,15 +2790,28 @@ Call these functions only at load time!
|
|||||||
the puncher to the punched.
|
the puncher to the punched.
|
||||||
* `damage` - number that represents the damage calculated by the engine
|
* `damage` - number that represents the damage calculated by the engine
|
||||||
* should return `true` to prevent the default damage mechanism
|
* should return `true` to prevent the default damage mechanism
|
||||||
* `minetest.register_on_player_hpchange(func(player, hp_change), modifier)`
|
* `minetest.register_on_player_hpchange(func(player, hp_change, reason), modifier)`
|
||||||
* Called when the player gets damaged or healed
|
* Called when the player gets damaged or healed
|
||||||
* `player`: ObjectRef of the player
|
* `player`: ObjectRef of the player
|
||||||
* `hp_change`: the amount of change. Negative when it is damage.
|
* `hp_change`: the amount of change. Negative when it is damage.
|
||||||
|
* `reason`: a PlayerHPChangeReason table.
|
||||||
|
* The `type` field will have one of the following values:
|
||||||
|
* `set_hp` - A mod or the engine called `set_hp` without
|
||||||
|
giving a type - use this for custom damage types.
|
||||||
|
* `punch` - Was punched. `reason.object` will hold the puncher, or nil if none.
|
||||||
|
* `fall`
|
||||||
|
* `node_damage` - damage_per_second from a neighbouring node.
|
||||||
|
* `drown`
|
||||||
|
* `respawn`
|
||||||
|
* Any of the above types may have additional fields from mods.
|
||||||
|
* `reason.from` will be `mod` or `engine`.
|
||||||
* `modifier`: when true, the function should return the actual `hp_change`.
|
* `modifier`: when true, the function should return the actual `hp_change`.
|
||||||
Note: modifiers only get a temporary hp_change that can be modified by
|
Note: modifiers only get a temporary hp_change that can be modified by later modifiers.
|
||||||
later modifiers. modifiers can return true as a second argument to stop
|
modifiers can return true as a second argument to stop the execution of further functions.
|
||||||
the execution of further functions. Non-modifiers receive the final hp
|
Non-modifiers receive the final hp change calculated by the modifiers.
|
||||||
change calculated by the modifiers.
|
* `minetest.register_on_dieplayer(func(ObjectRef, reason))`
|
||||||
|
* Called when a player dies
|
||||||
|
* `reason`: a PlayerHPChangeReason table, see register_on_player_hpchange
|
||||||
* `minetest.register_on_respawnplayer(func(ObjectRef))`
|
* `minetest.register_on_respawnplayer(func(ObjectRef))`
|
||||||
* Called when player is to be respawned
|
* Called when player is to be respawned
|
||||||
* Called _before_ repositioning of player occurs
|
* Called _before_ repositioning of player occurs
|
||||||
@ -3939,7 +3950,8 @@ This is basically a reference to a C++ `ServerActiveObject`
|
|||||||
* `direction`: can be `nil`
|
* `direction`: can be `nil`
|
||||||
* `right_click(clicker)`; `clicker` is another `ObjectRef`
|
* `right_click(clicker)`; `clicker` is another `ObjectRef`
|
||||||
* `get_hp()`: returns number of hitpoints (2 * number of hearts)
|
* `get_hp()`: returns number of hitpoints (2 * number of hearts)
|
||||||
* `set_hp(hp)`: set number of hitpoints (2 * number of hearts)
|
* `set_hp(hp, reason)`: set number of hitpoints (2 * number of hearts).
|
||||||
|
* See reason in register_on_player_hpchange
|
||||||
* `get_inventory()`: returns an `InvRef`
|
* `get_inventory()`: returns an `InvRef`
|
||||||
* `get_wield_list()`: returns the name of the inventory list the wielded item
|
* `get_wield_list()`: returns the name of the inventory list the wielded item
|
||||||
is in.
|
is in.
|
||||||
|
@ -9,3 +9,32 @@ assert(pseudo:next() == 22290)
|
|||||||
assert(pseudo:next() == 13854)
|
assert(pseudo:next() == 13854)
|
||||||
|
|
||||||
|
|
||||||
|
--
|
||||||
|
-- HP Change Reasons
|
||||||
|
--
|
||||||
|
local expect = nil
|
||||||
|
minetest.register_on_joinplayer(function(player)
|
||||||
|
expect = { type = "set_hp", from = "mod" }
|
||||||
|
player:set_hp(3)
|
||||||
|
assert(expect == nil)
|
||||||
|
|
||||||
|
expect = { a = 234, type = "set_hp", from = "mod" }
|
||||||
|
player:set_hp(10, { a= 234 })
|
||||||
|
assert(expect == nil)
|
||||||
|
|
||||||
|
expect = { df = 3458973454, type = "fall", from = "mod" }
|
||||||
|
player:set_hp(10, { type = "fall", df = 3458973454 })
|
||||||
|
assert(expect == nil)
|
||||||
|
end)
|
||||||
|
|
||||||
|
minetest.register_on_player_hpchange(function(player, hp, reason)
|
||||||
|
for key, value in pairs(reason) do
|
||||||
|
assert(expect[key] == value)
|
||||||
|
end
|
||||||
|
|
||||||
|
for key, value in pairs(expect) do
|
||||||
|
assert(reason[key] == value)
|
||||||
|
end
|
||||||
|
|
||||||
|
expect = nil
|
||||||
|
end)
|
||||||
|
@ -921,8 +921,9 @@ void PlayerSAO::step(float dtime, bool send_recommended)
|
|||||||
|
|
||||||
// No more breath, damage player
|
// No more breath, damage player
|
||||||
if (m_breath == 0) {
|
if (m_breath == 0) {
|
||||||
setHP(m_hp - c.drowning);
|
PlayerHPChangeReason reason(PlayerHPChangeReason::DROWNING);
|
||||||
m_env->getGameDef()->SendPlayerHPOrDie(this);
|
setHP(m_hp - c.drowning, reason);
|
||||||
|
m_env->getGameDef()->SendPlayerHPOrDie(this, reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -961,8 +962,9 @@ void PlayerSAO::step(float dtime, bool send_recommended)
|
|||||||
|
|
||||||
if (damage_per_second != 0 && m_hp > 0) {
|
if (damage_per_second != 0 && m_hp > 0) {
|
||||||
s16 newhp = ((s32) damage_per_second > m_hp ? 0 : m_hp - damage_per_second);
|
s16 newhp = ((s32) damage_per_second > m_hp ? 0 : m_hp - damage_per_second);
|
||||||
setHP(newhp);
|
PlayerHPChangeReason reason(PlayerHPChangeReason::NODE_DAMAGE);
|
||||||
m_env->getGameDef()->SendPlayerHPOrDie(this);
|
setHP(newhp, reason);
|
||||||
|
m_env->getGameDef()->SendPlayerHPOrDie(this, reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1208,7 +1210,8 @@ int PlayerSAO::punch(v3f dir,
|
|||||||
hitparams.hp);
|
hitparams.hp);
|
||||||
|
|
||||||
if (!damage_handled) {
|
if (!damage_handled) {
|
||||||
setHP(getHP() - hitparams.hp);
|
setHP(getHP() - hitparams.hp,
|
||||||
|
PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, puncher));
|
||||||
} else { // override client prediction
|
} else { // override client prediction
|
||||||
if (puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
|
if (puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
|
||||||
std::string str = gob_cmd_punched(0, getHP());
|
std::string str = gob_cmd_punched(0, getHP());
|
||||||
@ -1238,11 +1241,11 @@ s16 PlayerSAO::readDamage()
|
|||||||
return damage;
|
return damage;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerSAO::setHP(s16 hp)
|
void PlayerSAO::setHP(s16 hp, const PlayerHPChangeReason &reason)
|
||||||
{
|
{
|
||||||
s16 oldhp = m_hp;
|
s16 oldhp = m_hp;
|
||||||
|
|
||||||
s16 hp_change = m_env->getScriptIface()->on_player_hpchange(this, hp - oldhp);
|
s16 hp_change = m_env->getScriptIface()->on_player_hpchange(this, hp - oldhp, reason);
|
||||||
if (hp_change == 0)
|
if (hp_change == 0)
|
||||||
return;
|
return;
|
||||||
hp = oldhp + hp_change;
|
hp = oldhp + hp_change;
|
||||||
|
@ -245,7 +245,7 @@ public:
|
|||||||
ServerActiveObject *puncher,
|
ServerActiveObject *puncher,
|
||||||
float time_from_last_punch);
|
float time_from_last_punch);
|
||||||
void rightClick(ServerActiveObject *clicker) {}
|
void rightClick(ServerActiveObject *clicker) {}
|
||||||
void setHP(s16 hp);
|
void setHP(s16 hp, const PlayerHPChangeReason &reason);
|
||||||
void setHPRaw(s16 hp) { m_hp = hp; }
|
void setHPRaw(s16 hp) { m_hp = hp; }
|
||||||
s16 readDamage();
|
s16 readDamage();
|
||||||
u16 getBreath() const { return m_breath; }
|
u16 getBreath() const { return m_breath; }
|
||||||
@ -417,3 +417,64 @@ public:
|
|||||||
bool m_physics_override_new_move = true;
|
bool m_physics_override_new_move = true;
|
||||||
bool m_physics_override_sent = false;
|
bool m_physics_override_sent = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct PlayerHPChangeReason {
|
||||||
|
enum Type : u8 {
|
||||||
|
SET_HP,
|
||||||
|
PLAYER_PUNCH,
|
||||||
|
FALL,
|
||||||
|
NODE_DAMAGE,
|
||||||
|
DROWNING,
|
||||||
|
RESPAWN
|
||||||
|
};
|
||||||
|
|
||||||
|
Type type = SET_HP;
|
||||||
|
ServerActiveObject *object;
|
||||||
|
bool from_mod = false;
|
||||||
|
int lua_reference = -1;
|
||||||
|
|
||||||
|
bool setTypeFromString(const std::string &typestr)
|
||||||
|
{
|
||||||
|
if (typestr == "set_hp")
|
||||||
|
type = SET_HP;
|
||||||
|
else if (typestr == "punch")
|
||||||
|
type = PLAYER_PUNCH;
|
||||||
|
else if (typestr == "fall")
|
||||||
|
type = FALL;
|
||||||
|
else if (typestr == "node_damage")
|
||||||
|
type = NODE_DAMAGE;
|
||||||
|
else if (typestr == "drown")
|
||||||
|
type = DROWNING;
|
||||||
|
else if (typestr == "respawn")
|
||||||
|
type = RESPAWN;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string getTypeAsString() const
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case PlayerHPChangeReason::SET_HP:
|
||||||
|
return "set_hp";
|
||||||
|
case PlayerHPChangeReason::PLAYER_PUNCH:
|
||||||
|
return "punch";
|
||||||
|
case PlayerHPChangeReason::FALL:
|
||||||
|
return "fall";
|
||||||
|
case PlayerHPChangeReason::NODE_DAMAGE:
|
||||||
|
return "node_damage";
|
||||||
|
case PlayerHPChangeReason::DROWNING:
|
||||||
|
return "drown";
|
||||||
|
case PlayerHPChangeReason::RESPAWN:
|
||||||
|
return "respawn";
|
||||||
|
default:
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerHPChangeReason(Type type, ServerActiveObject *object=NULL):
|
||||||
|
type(type), object(object)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
@ -812,8 +812,9 @@ void Server::handleCommand_Damage(NetworkPacket* pkt)
|
|||||||
<< (int)damage << " hp at " << PP(playersao->getBasePosition() / BS)
|
<< (int)damage << " hp at " << PP(playersao->getBasePosition() / BS)
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
|
||||||
playersao->setHP(playersao->getHP() - damage);
|
PlayerHPChangeReason reason(PlayerHPChangeReason::FALL);
|
||||||
SendPlayerHPOrDie(playersao);
|
playersao->setHP(playersao->getHP() - damage, reason);
|
||||||
|
SendPlayerHPOrDie(playersao, reason);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1175,12 +1176,14 @@ void Server::handleCommand_Interact(NetworkPacket* pkt)
|
|||||||
// If the object is a player and its HP changed
|
// If the object is a player and its HP changed
|
||||||
if (src_original_hp != pointed_object->getHP() &&
|
if (src_original_hp != pointed_object->getHP() &&
|
||||||
pointed_object->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
|
pointed_object->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
|
||||||
SendPlayerHPOrDie((PlayerSAO *)pointed_object);
|
SendPlayerHPOrDie((PlayerSAO *)pointed_object,
|
||||||
|
PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, playersao));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the puncher is a player and its HP changed
|
// If the puncher is a player and its HP changed
|
||||||
if (dst_origin_hp != playersao->getHP())
|
if (dst_origin_hp != playersao->getHP())
|
||||||
SendPlayerHPOrDie(playersao);
|
SendPlayerHPOrDie(playersao,
|
||||||
|
PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, pointed_object));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // action == 0
|
} // action == 0
|
||||||
|
@ -43,6 +43,7 @@ extern "C" {
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include "script/common/c_content.h"
|
#include "script/common/c_content.h"
|
||||||
|
#include "content_sao.h"
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
|
||||||
@ -151,7 +152,7 @@ void ScriptApiBase::clientOpenLibs(lua_State *L)
|
|||||||
{ LUA_JITLIBNAME, luaopen_jit },
|
{ LUA_JITLIBNAME, luaopen_jit },
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const std::pair<std::string, lua_CFunction> &lib : m_libs) {
|
for (const std::pair<std::string, lua_CFunction> &lib : m_libs) {
|
||||||
lua_pushcfunction(L, lib.second);
|
lua_pushcfunction(L, lib.second);
|
||||||
lua_pushstring(L, lib.first.c_str());
|
lua_pushstring(L, lib.first.c_str());
|
||||||
@ -381,6 +382,26 @@ void ScriptApiBase::objectrefGetOrCreate(lua_State *L,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScriptApiBase::pushPlayerHPChangeReason(lua_State *L, const PlayerHPChangeReason &reason)
|
||||||
|
{
|
||||||
|
if (reason.lua_reference >= 0) {
|
||||||
|
lua_rawgeti(L, LUA_REGISTRYINDEX, reason.lua_reference);
|
||||||
|
luaL_unref(L, LUA_REGISTRYINDEX, reason.lua_reference);
|
||||||
|
} else
|
||||||
|
lua_newtable(L);
|
||||||
|
|
||||||
|
lua_pushstring(L, reason.getTypeAsString().c_str());
|
||||||
|
lua_setfield(L, -2, "type");
|
||||||
|
|
||||||
|
lua_pushstring(L, reason.from_mod ? "mod" : "engine");
|
||||||
|
lua_setfield(L, -2, "from");
|
||||||
|
|
||||||
|
if (reason.object) {
|
||||||
|
objectrefGetOrCreate(L, reason.object);
|
||||||
|
lua_setfield(L, -2, "object");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Server* ScriptApiBase::getServer()
|
Server* ScriptApiBase::getServer()
|
||||||
{
|
{
|
||||||
return dynamic_cast<Server *>(m_gamedef);
|
return dynamic_cast<Server *>(m_gamedef);
|
||||||
|
@ -72,6 +72,7 @@ class IGameDef;
|
|||||||
class Environment;
|
class Environment;
|
||||||
class GUIEngine;
|
class GUIEngine;
|
||||||
class ServerActiveObject;
|
class ServerActiveObject;
|
||||||
|
class PlayerHPChangeReason;
|
||||||
|
|
||||||
class ScriptApiBase {
|
class ScriptApiBase {
|
||||||
public:
|
public:
|
||||||
@ -139,6 +140,8 @@ protected:
|
|||||||
|
|
||||||
void objectrefGetOrCreate(lua_State *L, ServerActiveObject *cobj);
|
void objectrefGetOrCreate(lua_State *L, ServerActiveObject *cobj);
|
||||||
|
|
||||||
|
void pushPlayerHPChangeReason(lua_State *L, const PlayerHPChangeReason& reason);
|
||||||
|
|
||||||
std::recursive_mutex m_luastackmutex;
|
std::recursive_mutex m_luastackmutex;
|
||||||
std::string m_last_run_mod;
|
std::string m_last_run_mod;
|
||||||
bool m_secure = false;
|
bool m_secure = false;
|
||||||
|
@ -36,16 +36,20 @@ void ScriptApiPlayer::on_newplayer(ServerActiveObject *player)
|
|||||||
runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
|
runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptApiPlayer::on_dieplayer(ServerActiveObject *player)
|
void ScriptApiPlayer::on_dieplayer(ServerActiveObject *player, const PlayerHPChangeReason &reason)
|
||||||
{
|
{
|
||||||
SCRIPTAPI_PRECHECKHEADER
|
SCRIPTAPI_PRECHECKHEADER
|
||||||
|
|
||||||
// Get core.registered_on_dieplayers
|
// Get callback table
|
||||||
lua_getglobal(L, "core");
|
lua_getglobal(L, "core");
|
||||||
lua_getfield(L, -1, "registered_on_dieplayers");
|
lua_getfield(L, -1, "registered_on_dieplayers");
|
||||||
// Call callbacks
|
|
||||||
|
// Push arguments
|
||||||
objectrefGetOrCreate(L, player);
|
objectrefGetOrCreate(L, player);
|
||||||
runCallbacks(1, RUN_CALLBACKS_MODE_FIRST);
|
pushPlayerHPChangeReason(L, reason);
|
||||||
|
|
||||||
|
// Run callbacks
|
||||||
|
runCallbacks(2, RUN_CALLBACKS_MODE_FIRST);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ScriptApiPlayer::on_punchplayer(ServerActiveObject *player,
|
bool ScriptApiPlayer::on_punchplayer(ServerActiveObject *player,
|
||||||
@ -71,7 +75,7 @@ bool ScriptApiPlayer::on_punchplayer(ServerActiveObject *player,
|
|||||||
}
|
}
|
||||||
|
|
||||||
s16 ScriptApiPlayer::on_player_hpchange(ServerActiveObject *player,
|
s16 ScriptApiPlayer::on_player_hpchange(ServerActiveObject *player,
|
||||||
s16 hp_change)
|
s16 hp_change, const PlayerHPChangeReason &reason)
|
||||||
{
|
{
|
||||||
SCRIPTAPI_PRECHECKHEADER
|
SCRIPTAPI_PRECHECKHEADER
|
||||||
|
|
||||||
@ -82,9 +86,13 @@ s16 ScriptApiPlayer::on_player_hpchange(ServerActiveObject *player,
|
|||||||
lua_getfield(L, -1, "registered_on_player_hpchange");
|
lua_getfield(L, -1, "registered_on_player_hpchange");
|
||||||
lua_remove(L, -2);
|
lua_remove(L, -2);
|
||||||
|
|
||||||
|
// Push arguments
|
||||||
objectrefGetOrCreate(L, player);
|
objectrefGetOrCreate(L, player);
|
||||||
lua_pushnumber(L, hp_change);
|
lua_pushnumber(L, hp_change);
|
||||||
PCALL_RES(lua_pcall(L, 2, 1, error_handler));
|
pushPlayerHPChangeReason(L, reason);
|
||||||
|
|
||||||
|
// Call callbacks
|
||||||
|
PCALL_RES(lua_pcall(L, 3, 1, error_handler));
|
||||||
hp_change = lua_tointeger(L, -1);
|
hp_change = lua_tointeger(L, -1);
|
||||||
lua_pop(L, 2); // Pop result and error handler
|
lua_pop(L, 2); // Pop result and error handler
|
||||||
return hp_change;
|
return hp_change;
|
||||||
|
@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
|
|
||||||
struct ToolCapabilities;
|
struct ToolCapabilities;
|
||||||
|
struct PlayerHPChangeReason;
|
||||||
|
|
||||||
class ScriptApiPlayer : virtual public ScriptApiBase
|
class ScriptApiPlayer : virtual public ScriptApiBase
|
||||||
{
|
{
|
||||||
@ -31,7 +32,7 @@ public:
|
|||||||
virtual ~ScriptApiPlayer() = default;
|
virtual ~ScriptApiPlayer() = default;
|
||||||
|
|
||||||
void on_newplayer(ServerActiveObject *player);
|
void on_newplayer(ServerActiveObject *player);
|
||||||
void on_dieplayer(ServerActiveObject *player);
|
void on_dieplayer(ServerActiveObject *player, const PlayerHPChangeReason &reason);
|
||||||
bool on_respawnplayer(ServerActiveObject *player);
|
bool on_respawnplayer(ServerActiveObject *player);
|
||||||
bool on_prejoinplayer(const std::string &name, const std::string &ip,
|
bool on_prejoinplayer(const std::string &name, const std::string &ip,
|
||||||
std::string *reason);
|
std::string *reason);
|
||||||
@ -42,7 +43,8 @@ public:
|
|||||||
bool on_punchplayer(ServerActiveObject *player, ServerActiveObject *hitter,
|
bool on_punchplayer(ServerActiveObject *player, ServerActiveObject *hitter,
|
||||||
float time_from_last_punch, const ToolCapabilities *toolcap,
|
float time_from_last_punch, const ToolCapabilities *toolcap,
|
||||||
v3f dir, s16 damage);
|
v3f dir, s16 damage);
|
||||||
s16 on_player_hpchange(ServerActiveObject *player, s16 hp_change);
|
s16 on_player_hpchange(ServerActiveObject *player, s16 hp_change,
|
||||||
|
const PlayerHPChangeReason &reason);
|
||||||
void on_playerReceiveFields(ServerActiveObject *player,
|
void on_playerReceiveFields(ServerActiveObject *player,
|
||||||
const std::string &formname, const StringMap &fields);
|
const std::string &formname, const StringMap &fields);
|
||||||
void on_auth_failure(const std::string &name, const std::string &ip);
|
void on_auth_failure(const std::string &name, const std::string &ip);
|
||||||
|
@ -194,13 +194,14 @@ int ObjectRef::l_punch(lua_State *L)
|
|||||||
// If the punched is a player, and its HP changed
|
// If the punched is a player, and its HP changed
|
||||||
if (src_original_hp != co->getHP() &&
|
if (src_original_hp != co->getHP() &&
|
||||||
co->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
|
co->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
|
||||||
getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co);
|
getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co, PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, puncher));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the puncher is a player, and its HP changed
|
// If the puncher is a player, and its HP changed
|
||||||
if (dst_origin_hp != puncher->getHP() &&
|
if (dst_origin_hp != puncher->getHP() &&
|
||||||
puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
|
puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) {
|
||||||
getServer(L)->SendPlayerHPOrDie((PlayerSAO *)puncher);
|
getServer(L)->SendPlayerHPOrDie((PlayerSAO *)puncher,
|
||||||
|
PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, co));
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -226,17 +227,36 @@ int ObjectRef::l_right_click(lua_State *L)
|
|||||||
int ObjectRef::l_set_hp(lua_State *L)
|
int ObjectRef::l_set_hp(lua_State *L)
|
||||||
{
|
{
|
||||||
NO_MAP_LOCK_REQUIRED;
|
NO_MAP_LOCK_REQUIRED;
|
||||||
|
|
||||||
|
// Get Object
|
||||||
ObjectRef *ref = checkobject(L, 1);
|
ObjectRef *ref = checkobject(L, 1);
|
||||||
luaL_checknumber(L, 2);
|
luaL_checknumber(L, 2);
|
||||||
ServerActiveObject *co = getobject(ref);
|
ServerActiveObject *co = getobject(ref);
|
||||||
if (co == NULL) return 0;
|
if (co == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Get HP
|
||||||
int hp = lua_tonumber(L, 2);
|
int hp = lua_tonumber(L, 2);
|
||||||
/*infostream<<"ObjectRef::l_set_hp(): id="<<co->getId()
|
|
||||||
<<" hp="<<hp<<std::endl;*/
|
// Get Reason
|
||||||
|
PlayerHPChangeReason reason(PlayerHPChangeReason::SET_HP);
|
||||||
|
reason.from_mod = true;
|
||||||
|
if (lua_istable(L, 3)) {
|
||||||
|
lua_pushvalue(L, 3);
|
||||||
|
|
||||||
|
lua_getfield(L, -1, "type");
|
||||||
|
if (lua_isstring(L, -1) && !reason.setTypeFromString(lua_tostring(L, -1))) {
|
||||||
|
errorstream << "Bad type given!" << std::endl;
|
||||||
|
}
|
||||||
|
lua_pop(L, 1);
|
||||||
|
|
||||||
|
reason.lua_reference = luaL_ref(L, LUA_REGISTRYINDEX);
|
||||||
|
}
|
||||||
|
|
||||||
// Do it
|
// Do it
|
||||||
co->setHP(hp);
|
co->setHP(hp, reason);
|
||||||
if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER)
|
if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER)
|
||||||
getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co);
|
getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co, reason);
|
||||||
|
|
||||||
// Return
|
// Return
|
||||||
return 0;
|
return 0;
|
||||||
@ -729,9 +749,10 @@ int ObjectRef::l_set_properties(lua_State *L)
|
|||||||
return 0;
|
return 0;
|
||||||
read_object_properties(L, 2, prop, getServer(L)->idef());
|
read_object_properties(L, 2, prop, getServer(L)->idef());
|
||||||
if (prop->hp_max < co->getHP()) {
|
if (prop->hp_max < co->getHP()) {
|
||||||
co->setHP(prop->hp_max);
|
PlayerHPChangeReason reason(PlayerHPChangeReason::SET_HP);
|
||||||
|
co->setHP(prop->hp_max, reason);
|
||||||
if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER)
|
if (co->getType() == ACTIVEOBJECT_TYPE_PLAYER)
|
||||||
getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co);
|
getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co, reason);
|
||||||
}
|
}
|
||||||
co->notifyObjectPropertiesModified();
|
co->notifyObjectPropertiesModified();
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1029,7 +1029,8 @@ PlayerSAO* Server::StageTwoClientInit(session_t peer_id)
|
|||||||
if (playersao->isDead())
|
if (playersao->isDead())
|
||||||
SendDeathscreen(peer_id, false, v3f(0,0,0));
|
SendDeathscreen(peer_id, false, v3f(0,0,0));
|
||||||
else
|
else
|
||||||
SendPlayerHPOrDie(playersao);
|
SendPlayerHPOrDie(playersao,
|
||||||
|
PlayerHPChangeReason(PlayerHPChangeReason::SET_HP));
|
||||||
|
|
||||||
// Send Breath
|
// Send Breath
|
||||||
SendPlayerBreath(playersao);
|
SendPlayerBreath(playersao);
|
||||||
@ -1392,7 +1393,7 @@ void Server::SendMovement(session_t peer_id)
|
|||||||
Send(&pkt);
|
Send(&pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::SendPlayerHPOrDie(PlayerSAO *playersao)
|
void Server::SendPlayerHPOrDie(PlayerSAO *playersao, const PlayerHPChangeReason &reason)
|
||||||
{
|
{
|
||||||
if (!g_settings->getBool("enable_damage"))
|
if (!g_settings->getBool("enable_damage"))
|
||||||
return;
|
return;
|
||||||
@ -1403,7 +1404,7 @@ void Server::SendPlayerHPOrDie(PlayerSAO *playersao)
|
|||||||
if (is_alive)
|
if (is_alive)
|
||||||
SendPlayerHP(peer_id);
|
SendPlayerHP(peer_id);
|
||||||
else
|
else
|
||||||
DiePlayer(peer_id);
|
DiePlayer(peer_id, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::SendHP(session_t peer_id, u16 hp)
|
void Server::SendHP(session_t peer_id, u16 hp)
|
||||||
@ -2493,7 +2494,7 @@ void Server::sendDetachedInventories(session_t peer_id)
|
|||||||
Something random
|
Something random
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Server::DiePlayer(session_t peer_id)
|
void Server::DiePlayer(session_t peer_id, const PlayerHPChangeReason &reason)
|
||||||
{
|
{
|
||||||
PlayerSAO *playersao = getPlayerSAO(peer_id);
|
PlayerSAO *playersao = getPlayerSAO(peer_id);
|
||||||
// In some rare cases this can be NULL -- if the player is disconnected
|
// In some rare cases this can be NULL -- if the player is disconnected
|
||||||
@ -2505,10 +2506,10 @@ void Server::DiePlayer(session_t peer_id)
|
|||||||
<< playersao->getPlayer()->getName()
|
<< playersao->getPlayer()->getName()
|
||||||
<< " dies" << std::endl;
|
<< " dies" << std::endl;
|
||||||
|
|
||||||
playersao->setHP(0);
|
playersao->setHP(0, reason);
|
||||||
|
|
||||||
// Trigger scripted stuff
|
// Trigger scripted stuff
|
||||||
m_script->on_dieplayer(playersao);
|
m_script->on_dieplayer(playersao, reason);
|
||||||
|
|
||||||
SendPlayerHP(peer_id);
|
SendPlayerHP(peer_id);
|
||||||
SendDeathscreen(peer_id, false, v3f(0,0,0));
|
SendDeathscreen(peer_id, false, v3f(0,0,0));
|
||||||
@ -2523,7 +2524,8 @@ void Server::RespawnPlayer(session_t peer_id)
|
|||||||
<< playersao->getPlayer()->getName()
|
<< playersao->getPlayer()->getName()
|
||||||
<< " respawns" << std::endl;
|
<< " respawns" << std::endl;
|
||||||
|
|
||||||
playersao->setHP(playersao->accessObjectProperties()->hp_max);
|
playersao->setHP(playersao->accessObjectProperties()->hp_max,
|
||||||
|
PlayerHPChangeReason(PlayerHPChangeReason::RESPAWN));
|
||||||
playersao->setBreath(playersao->accessObjectProperties()->breath_max);
|
playersao->setBreath(playersao->accessObjectProperties()->breath_max);
|
||||||
|
|
||||||
bool repositioned = m_script->on_respawnplayer(playersao);
|
bool repositioned = m_script->on_respawnplayer(playersao);
|
||||||
|
@ -53,6 +53,7 @@ class Inventory;
|
|||||||
class ModChannelMgr;
|
class ModChannelMgr;
|
||||||
class RemotePlayer;
|
class RemotePlayer;
|
||||||
class PlayerSAO;
|
class PlayerSAO;
|
||||||
|
struct PlayerHPChangeReason;
|
||||||
class IRollbackManager;
|
class IRollbackManager;
|
||||||
struct RollbackAction;
|
struct RollbackAction;
|
||||||
class EmergeManager;
|
class EmergeManager;
|
||||||
@ -328,7 +329,7 @@ public:
|
|||||||
|
|
||||||
void printToConsoleOnly(const std::string &text);
|
void printToConsoleOnly(const std::string &text);
|
||||||
|
|
||||||
void SendPlayerHPOrDie(PlayerSAO *player);
|
void SendPlayerHPOrDie(PlayerSAO *player, const PlayerHPChangeReason &reason);
|
||||||
void SendPlayerBreath(PlayerSAO *sao);
|
void SendPlayerBreath(PlayerSAO *sao);
|
||||||
void SendInventory(PlayerSAO* playerSAO);
|
void SendInventory(PlayerSAO* playerSAO);
|
||||||
void SendMovePlayer(session_t peer_id);
|
void SendMovePlayer(session_t peer_id);
|
||||||
@ -451,7 +452,7 @@ private:
|
|||||||
Something random
|
Something random
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void DiePlayer(session_t peer_id);
|
void DiePlayer(session_t peer_id, const PlayerHPChangeReason &reason);
|
||||||
void RespawnPlayer(session_t peer_id);
|
void RespawnPlayer(session_t peer_id);
|
||||||
void DeleteClient(session_t peer_id, ClientDeletionReason reason);
|
void DeleteClient(session_t peer_id, ClientDeletionReason reason);
|
||||||
void UpdateCrafting(RemotePlayer *player);
|
void UpdateCrafting(RemotePlayer *player);
|
||||||
|
@ -46,6 +46,7 @@ class ServerEnvironment;
|
|||||||
struct ItemStack;
|
struct ItemStack;
|
||||||
struct ToolCapabilities;
|
struct ToolCapabilities;
|
||||||
struct ObjectProperties;
|
struct ObjectProperties;
|
||||||
|
struct PlayerHPChangeReason;
|
||||||
|
|
||||||
class ServerActiveObject : public ActiveObject
|
class ServerActiveObject : public ActiveObject
|
||||||
{
|
{
|
||||||
@ -139,7 +140,7 @@ public:
|
|||||||
{ return 0; }
|
{ return 0; }
|
||||||
virtual void rightClick(ServerActiveObject *clicker)
|
virtual void rightClick(ServerActiveObject *clicker)
|
||||||
{}
|
{}
|
||||||
virtual void setHP(s16 hp)
|
virtual void setHP(s16 hp, const PlayerHPChangeReason &reason)
|
||||||
{}
|
{}
|
||||||
virtual s16 getHP() const
|
virtual s16 getHP() const
|
||||||
{ return 0; }
|
{ return 0; }
|
||||||
|
Loading…
Reference in New Issue
Block a user