int PlayerSAO::punch(v3f dir, const ToolCapabilities *toolcap, ServerActiveObject *puncher, float time_from_last_punch) { if (!toolcap) return 0; // No effect if PvP disabled if (!g_settings->getBool("enable_pvp")) { if (puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) { std::string str = gob_cmd_punched(0, getHP()); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); return 0; } } HitParams hitparams = getHitParams(m_armor_groups, toolcap, time_from_last_punch); std::string punchername = "nil"; if (puncher != 0) punchername = puncher->getDescription(); PlayerSAO *playersao = m_player->getPlayerSAO(); bool damage_handled = m_env->getScriptIface()->on_punchplayer(playersao, puncher, time_from_last_punch, toolcap, dir, hitparams.hp); if (!damage_handled) { setHP(getHP() - hitparams.hp, PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, puncher)); } else { // override client prediction if (puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) { std::string str = gob_cmd_punched(0, getHP()); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } } actionstream << "Player " << m_player->getName() << " punched by " << punchername; if (!damage_handled) { actionstream << ", damage " << hitparams.hp << " HP"; } else { actionstream << ", damage handled by lua"; } actionstream << std::endl; return hitparams.wear; }
int LuaEntitySAO::punch(v3f dir, const ToolCapabilities *toolcap, ServerActiveObject *puncher, float time_from_last_punch) { if (!m_registered) { // Delete unknown LuaEntities when punched m_pending_removal = true; return 0; } ItemStack *punchitem = NULL; ItemStack punchitem_static; if (puncher) { punchitem_static = puncher->getWieldedItem(); punchitem = &punchitem_static; } PunchDamageResult result = getPunchDamage( m_armor_groups, toolcap, punchitem, time_from_last_punch); bool damage_handled = m_env->getScriptIface()->luaentity_Punch(m_id, puncher, time_from_last_punch, toolcap, dir, result.did_punch ? result.damage : 0); if (!damage_handled) { if (result.did_punch) { setHP(getHP() - result.damage, PlayerHPChangeReason(PlayerHPChangeReason::SET_HP)); if (result.damage > 0) { std::string punchername = puncher ? puncher->getDescription() : "nil"; actionstream << getDescription() << " punched by " << punchername << ", damage " << result.damage << " hp, health now " << getHP() << " hp" << std::endl; } std::string str = gob_cmd_punched(result.damage, getHP()); // create message and add to list ActiveObjectMessage aom(getId(), true, str); m_messages_out.push(aom); } } if (getHP() == 0 && !isGone()) { m_pending_removal = true; clearParentAttachment(); clearChildAttachments(); m_env->getScriptIface()->luaentity_on_death(m_id, puncher); } return result.wear; }
// punch(self, puncher, time_from_last_punch, tool_capabilities, dir) int ObjectRef::l_punch(lua_State *L) { NO_MAP_LOCK_REQUIRED; ObjectRef *ref = checkobject(L, 1); ObjectRef *puncher_ref = checkobject(L, 2); ServerActiveObject *co = getobject(ref); ServerActiveObject *puncher = getobject(puncher_ref); if (co == NULL) return 0; if (puncher == NULL) return 0; v3f dir; if (lua_type(L, 5) != LUA_TTABLE) dir = co->getBasePosition() - puncher->getBasePosition(); else dir = read_v3f(L, 5); float time_from_last_punch = 1000000; if (lua_isnumber(L, 3)) time_from_last_punch = lua_tonumber(L, 3); ToolCapabilities toolcap = read_tool_capabilities(L, 4); dir.normalize(); u16 src_original_hp = co->getHP(); u16 dst_origin_hp = puncher->getHP(); // Do it co->punch(dir, &toolcap, puncher, time_from_last_punch); // If the punched is a player, and its HP changed if (src_original_hp != co->getHP() && co->getType() == ACTIVEOBJECT_TYPE_PLAYER) { getServer(L)->SendPlayerHPOrDie((PlayerSAO *)co, PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, puncher)); } // If the puncher is a player, and its HP changed if (dst_origin_hp != puncher->getHP() && puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER) { getServer(L)->SendPlayerHPOrDie((PlayerSAO *)puncher, PlayerHPChangeReason(PlayerHPChangeReason::PLAYER_PUNCH, co)); } return 0; }