summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPilzAdam <pilzadam@minetest.net>2013-03-28 21:40:44 +0100
committerPilzAdam <pilzadam@minetest.net>2013-03-29 20:14:09 +0100
commit7d9329ecfe84733cdefa34eab25ee3d124c94c59 (patch)
treec31fa17924b27fc57e30e5c3fe619d96b75f14d4
parent3640c8c051bc6b72f4af52752b2d48ced274f539 (diff)
downloadminetest-7d9329ecfe84733cdefa34eab25ee3d124c94c59.tar.gz
minetest-7d9329ecfe84733cdefa34eab25ee3d124c94c59.tar.bz2
minetest-7d9329ecfe84733cdefa34eab25ee3d124c94c59.zip
New damage system, add damageGroups to ToolCapabilities, bump protocol version
-rw-r--r--doc/lua_api.txt28
-rw-r--r--src/clientserver.h4
-rw-r--r--src/content_sao.cpp6
-rw-r--r--src/itemdef.cpp8
-rw-r--r--src/itemdef.h6
-rw-r--r--src/scriptapi_common.cpp24
-rw-r--r--src/server.cpp6
-rw-r--r--src/server.h2
-rw-r--r--src/tool.cpp57
-rw-r--r--src/tool.h21
10 files changed, 105 insertions, 57 deletions
diff --git a/doc/lua_api.txt b/doc/lua_api.txt
index 8ef92bdf3..42ca58239 100644
--- a/doc/lua_api.txt
+++ b/doc/lua_api.txt
@@ -471,9 +471,11 @@ a node is destroyable and how long it takes to destroy by a tool.
Groups of entities
-------------------
For entities, groups are, as of now, used only for calculating damage.
+The rating is the percentage of damage caused by tools with this damage group.
+See "Entity damage mechanism".
-object.get_armor_groups() -> a group-rating table (eg. {fleshy=3})
-object.set_armor_groups({level=2, fleshy=2, cracky=2})
+object.get_armor_groups() -> a group-rating table (eg. {fleshy=100})
+object.set_armor_groups({fleshy=30, cracky=80})
Groups of tools
----------------
@@ -522,7 +524,6 @@ Special groups
Known damage and digging time defining groups
----------------------------------------------
-Valid ratings for these are 0, 1, 2 and 3, unless otherwise stated.
- crumbly: dirt, sand
- cracky: tough but crackable stuff like stone.
- snappy: something that can be cut using fine tools; eg. leaves, small
@@ -575,6 +576,7 @@ groups to enable interaction with tools.
* Uses (until the tool breaks)
* Maximum level (usually 0, 1, 2 or 3)
* Digging times
+ * Damage groups
**Full punch interval**:
When used as a weapon, the tool will do full damage if this time is spent
@@ -606,8 +608,9 @@ maximum level.
result in the tool to be able to dig nodes that have a rating of 2 or 3
for this group, and unable to dig the rating 1, which is the toughest.
Unless there is a matching group that enables digging otherwise.
- * For entities, damage equals the amount of nodes dug in the time spent
- between hits, with a maximum time of ''full_punch_interval''.
+
+**Damage groups**
+List of damage for groups of entities. See "Entity damage mechanism".
Example definition of the capabilities of a tool
-------------------------------------------------
@@ -617,6 +620,7 @@ tool_capabilities = {
groupcaps={
crumbly={maxlevel=2, uses=20, times={[1]=1.60, [2]=1.20, [3]=0.80}}
}
+ damage_groups = {fleshy=2},
}
This makes the tool be able to dig nodes that fullfill both of these:
@@ -647,10 +651,12 @@ Notes:
Entity damage mechanism
------------------------
Damage calculation:
-- Take the time spent after the last hit
-- Limit time to full_punch_interval
-- Take the damage groups and imagine a bunch of nodes that have them
-- Damage in HP is the amount of nodes destroyed in this time.
+damage = 0
+foreach group in cap.damage_groups:
+ damage += cap.damage_groups[group] * limit(actual_interval / cap.full_punch_interval, 0.0, 1.0)
+ * (object.armor_groups[group] / 100.0)
+ -- Where object.armor_groups[group] is 0 for inexisting values
+return damage
Client predicts damage based on damage groups. Because of this, it is able to
give an immediate response when an entity is damaged or dies; the response is
@@ -1496,10 +1502,10 @@ Item definition (register_node, register_craftitem, register_tool)
max_drop_level=0,
groupcaps={
-- For example:
- fleshy={times={[2]=0.80, [3]=0.40}, maxwear=0.05, maxlevel=1},
snappy={times={[2]=0.80, [3]=0.40}, maxwear=0.05, maxlevel=1},
choppy={times={[3]=0.90}, maxwear=0.05, maxlevel=0}
- }
+ },
+ damage_groups = {groupname=damage},
}
node_placement_prediction = nil,
^ If nil and item is node, prediction is made automatically
diff --git a/src/clientserver.h b/src/clientserver.h
index 535fc04d8..aba84fb31 100644
--- a/src/clientserver.h
+++ b/src/clientserver.h
@@ -85,9 +85,11 @@ SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed);
TOCLIENT_SPAWN_PARTICLE
TOCLIENT_ADD_PARTICLESPAWNER
TOCLIENT_DELETE_PARTICLESPAWNER
+ PROTOCOL_VERSION 18:
+ damageGroups added to ToolCapabilities
*/
-#define LATEST_PROTOCOL_VERSION 17
+#define LATEST_PROTOCOL_VERSION 18
// Server's supported network protocol range
#define SERVER_PROTOCOL_VERSION_MIN 13
diff --git a/src/content_sao.cpp b/src/content_sao.cpp
index 468dfd218..ae08b4260 100644
--- a/src/content_sao.cpp
+++ b/src/content_sao.cpp
@@ -381,8 +381,7 @@ LuaEntitySAO::LuaEntitySAO(ServerEnvironment *env, v3f pos,
}
// Initialize something to armor groups
- m_armor_groups["fleshy"] = 3;
- m_armor_groups["snappy"] = 2;
+ m_armor_groups["fleshy"] = 100;
}
LuaEntitySAO::~LuaEntitySAO()
@@ -942,8 +941,7 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
assert(m_peer_id != 0);
setBasePosition(m_player->getPosition());
m_inventory = &m_player->inventory;
- m_armor_groups["choppy"] = 2;
- m_armor_groups["fleshy"] = 3;
+ m_armor_groups["fleshy"] = 100;
m_prop.hp_max = PLAYER_MAX_HP;
m_prop.physical = false;
diff --git a/src/itemdef.cpp b/src/itemdef.cpp
index 4bd4181f9..98d7ce0a8 100644
--- a/src/itemdef.cpp
+++ b/src/itemdef.cpp
@@ -111,7 +111,7 @@ void ItemDefinition::reset()
node_placement_prediction = "";
}
-void ItemDefinition::serialize(std::ostream &os) const
+void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const
{
writeU8(os, 1); // version
writeU8(os, type);
@@ -126,7 +126,7 @@ void ItemDefinition::serialize(std::ostream &os) const
std::string tool_capabilities_s = "";
if(tool_capabilities){
std::ostringstream tmp_os(std::ios::binary);
- tool_capabilities->serialize(tmp_os);
+ tool_capabilities->serialize(tmp_os, protocol_version);
tool_capabilities_s = tmp_os.str();
}
os<<serializeString(tool_capabilities_s);
@@ -547,7 +547,7 @@ public:
m_aliases[name] = convert_to;
}
}
- void serialize(std::ostream &os)
+ void serialize(std::ostream &os, u16 protocol_version)
{
writeU8(os, 0); // version
u16 count = m_item_definitions.size();
@@ -559,7 +559,7 @@ public:
ItemDefinition *def = i->second;
// Serialize ItemDefinition and write wrapped in a string
std::ostringstream tmp_os(std::ios::binary);
- def->serialize(tmp_os);
+ def->serialize(tmp_os, protocol_version);
os<<serializeString(tmp_os.str());
}
writeU16(os, m_aliases.size());
diff --git a/src/itemdef.h b/src/itemdef.h
index dd20ba353..cbbe7e2ad 100644
--- a/src/itemdef.h
+++ b/src/itemdef.h
@@ -80,7 +80,7 @@ struct ItemDefinition
ItemDefinition& operator=(const ItemDefinition &def);
~ItemDefinition();
void reset();
- void serialize(std::ostream &os) const;
+ void serialize(std::ostream &os, u16 protocol_version) const;
void deSerialize(std::istream &is);
private:
void resetInitial();
@@ -109,7 +109,7 @@ public:
IGameDef *gamedef) const=0;
#endif
- virtual void serialize(std::ostream &os)=0;
+ virtual void serialize(std::ostream &os, u16 protocol_version)=0;
};
class IWritableItemDefManager : public IItemDefManager
@@ -146,7 +146,7 @@ public:
virtual void registerAlias(const std::string &name,
const std::string &convert_to)=0;
- virtual void serialize(std::ostream &os)=0;
+ virtual void serialize(std::ostream &os, u16 protocol_version)=0;
virtual void deSerialize(std::istream &is)=0;
// Do stuff asked by threads that can only be done in the main thread
diff --git a/src/scriptapi_common.cpp b/src/scriptapi_common.cpp
index 8ee8d6a84..2d6f6c72b 100644
--- a/src/scriptapi_common.cpp
+++ b/src/scriptapi_common.cpp
@@ -117,6 +117,20 @@ ToolCapabilities read_tool_capabilities(
}
}
lua_pop(L, 1);
+ lua_getfield(L, table, "damage_groups");
+ if(lua_istable(L, -1)){
+ int table_damage_groups = lua_gettop(L);
+ lua_pushnil(L);
+ while(lua_next(L, table_damage_groups) != 0){
+ // key at index -2 and value at index -1
+ std::string groupname = luaL_checkstring(L, -2);
+ u16 value = luaL_checkinteger(L, -1);
+ toolcap.damageGroups[groupname] = value;
+ // removes value, keeps key for next iteration
+ lua_pop(L, 1);
+ }
+ }
+ lua_pop(L, 1);
return toolcap;
}
@@ -154,6 +168,16 @@ void set_tool_capabilities(lua_State *L, int table,
}
// Set groupcaps table
lua_setfield(L, -2, "groupcaps");
+ //Create damage_groups table
+ lua_newtable(L);
+ // For each damage group
+ for(std::map<std::string, s16>::const_iterator
+ i = toolcap.damageGroups.begin(); i != toolcap.damageGroups.end(); i++){
+ // Create damage group table
+ lua_pushinteger(L, i->second);
+ lua_setfield(L, -2, i->first.c_str());
+ }
+ lua_setfield(L, -2, "damage_groups");
}
void push_tool_capabilities(lua_State *L,
diff --git a/src/server.cpp b/src/server.cpp
index db05b95cc..6bdebcec4 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -2080,7 +2080,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
SendMovement(m_con, peer_id);
// Send item definitions
- SendItemDef(m_con, peer_id, m_itemdef);
+ SendItemDef(m_con, peer_id, m_itemdef, client->net_proto_version);
// Send node definitions
SendNodeDef(m_con, peer_id, m_nodedef, client->net_proto_version);
@@ -3342,7 +3342,7 @@ void Server::SendDeathscreen(con::Connection &con, u16 peer_id,
}
void Server::SendItemDef(con::Connection &con, u16 peer_id,
- IItemDefManager *itemdef)
+ IItemDefManager *itemdef, u16 protocol_version)
{
DSTACK(__FUNCTION_NAME);
std::ostringstream os(std::ios_base::binary);
@@ -3354,7 +3354,7 @@ void Server::SendItemDef(con::Connection &con, u16 peer_id,
*/
writeU16(os, TOCLIENT_ITEMDEF);
std::ostringstream tmp_os(std::ios::binary);
- itemdef->serialize(tmp_os);
+ itemdef->serialize(tmp_os, protocol_version);
std::ostringstream tmp_os2(std::ios::binary);
compressZlib(tmp_os.str(), tmp_os2);
os<<serializeLongString(tmp_os2.str());
diff --git a/src/server.h b/src/server.h
index 813dc9828..04e693fc8 100644
--- a/src/server.h
+++ b/src/server.h
@@ -556,7 +556,7 @@ private:
static void SendDeathscreen(con::Connection &con, u16 peer_id,
bool set_camera_point_target, v3f camera_point_target);
static void SendItemDef(con::Connection &con, u16 peer_id,
- IItemDefManager *itemdef);
+ IItemDefManager *itemdef, u16 protocol_version);
static void SendNodeDef(con::Connection &con, u16 peer_id,
INodeDefManager *nodedef, u16 protocol_version);
diff --git a/src/tool.cpp b/src/tool.cpp
index 04f19749c..4d809e2c4 100644
--- a/src/tool.cpp
+++ b/src/tool.cpp
@@ -24,9 +24,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/serialize.h"
#include "util/numeric.h"
-void ToolCapabilities::serialize(std::ostream &os) const
+void ToolCapabilities::serialize(std::ostream &os, u16 protocol_version) const
{
- writeU8(os, 1); // version
+ if(protocol_version <= 17)
+ writeU8(os, 1); // version
+ else
+ writeU8(os, 2); // version
writeF1000(os, full_punch_interval);
writeS16(os, max_drop_level);
writeU32(os, groupcaps.size());
@@ -44,12 +47,20 @@ void ToolCapabilities::serialize(std::ostream &os) const
writeF1000(os, i->second);
}
}
+ if(protocol_version > 17){
+ writeU32(os, damageGroups.size());
+ for(std::map<std::string, s16>::const_iterator
+ i = damageGroups.begin(); i != damageGroups.end(); i++){
+ os<<serializeString(i->first);
+ writeS16(os, i->second);
+ }
+ }
}
void ToolCapabilities::deSerialize(std::istream &is)
{
int version = readU8(is);
- if(version != 1) throw SerializationError(
+ if(version != 1 && version != 2) throw SerializationError(
"unsupported ToolCapabilities version");
full_punch_interval = readF1000(is);
max_drop_level = readS16(is);
@@ -68,6 +79,15 @@ void ToolCapabilities::deSerialize(std::istream &is)
}
groupcaps[name] = cap;
}
+ if(version == 2)
+ {
+ u32 damage_groups_size = readU32(is);
+ for(u32 i=0; i<damage_groups_size; i++){
+ std::string name = deSerializeString(is);
+ s16 rating = readS16(is);
+ damageGroups[name] = rating;
+ }
+ }
}
DigParams getDigParams(const ItemGroupList &groups,
@@ -136,28 +156,26 @@ DigParams getDigParams(const ItemGroupList &groups,
return getDigParams(groups, tp, 1000000);
}
-HitParams getHitParams(const ItemGroupList &groups,
+HitParams getHitParams(const ItemGroupList &armor_groups,
const ToolCapabilities *tp, float time_from_last_punch)
{
- DigParams digprop = getDigParams(groups, tp,
- time_from_last_punch);
-
- if(time_from_last_punch > tp->full_punch_interval)
- time_from_last_punch = tp->full_punch_interval;
- // Damage in hp is equivalent to nodes dug in time_from_last_punch
- s16 hp = 0;
- if(digprop.diggable)
- hp = time_from_last_punch / digprop.time;
- // Wear is the same as for digging a single node
- s16 wear = (float)digprop.wear;
-
- return HitParams(hp, wear, digprop.main_group);
+ s16 damage = 0;
+ float full_punch_interval = tp->full_punch_interval;
+
+ for(std::map<std::string, s16>::const_iterator
+ i = tp->damageGroups.begin(); i != tp->damageGroups.end(); i++){
+ s16 armor = itemgroup_get(armor_groups, i->first);
+ damage += i->second * rangelim(time_from_last_punch * full_punch_interval, 0.0, 1.0)
+ * armor / 100.0;
+ }
+
+ return HitParams(damage, 0);
}
-HitParams getHitParams(const ItemGroupList &groups,
+HitParams getHitParams(const ItemGroupList &armor_groups,
const ToolCapabilities *tp)
{
- return getHitParams(groups, tp, 1000000);
+ return getHitParams(armor_groups, tp, 1000000);
}
PunchDamageResult getPunchDamage(
@@ -187,7 +205,6 @@ PunchDamageResult getPunchDamage(
result.did_punch = true;
result.wear = hitparams.wear;
result.damage = hitparams.hp;
- result.main_group = hitparams.main_group;
}
return result;
diff --git a/src/tool.h b/src/tool.h
index e812a9e36..509561a16 100644
--- a/src/tool.h
+++ b/src/tool.h
@@ -52,6 +52,7 @@ struct ToolGroupCap
// CLANG SUCKS DONKEY BALLS
typedef std::map<std::string, struct ToolGroupCap> ToolGCMap;
+typedef std::map<std::string, s16> DamageGroup;
struct ToolCapabilities
{
@@ -59,19 +60,22 @@ struct ToolCapabilities
int max_drop_level;
// CLANG SUCKS DONKEY BALLS
ToolGCMap groupcaps;
+ DamageGroup damageGroups;
ToolCapabilities(
float full_punch_interval_=1.4,
int max_drop_level_=1,
// CLANG SUCKS DONKEY BALLS
- ToolGCMap groupcaps_=ToolGCMap()
+ ToolGCMap groupcaps_=ToolGCMap(),
+ DamageGroup damageGroups_=DamageGroup()
):
full_punch_interval(full_punch_interval_),
max_drop_level(max_drop_level_),
- groupcaps(groupcaps_)
+ groupcaps(groupcaps_),
+ damageGroups(damageGroups_)
{}
- void serialize(std::ostream &os) const;
+ void serialize(std::ostream &os, u16 version) const;
void deSerialize(std::istream &is);
};
@@ -103,19 +107,17 @@ struct HitParams
{
s16 hp;
s16 wear;
- std::string main_group;
- HitParams(s16 hp_=0, s16 wear_=0, std::string main_group_=""):
+ HitParams(s16 hp_=0, s16 wear_=0):
hp(hp_),
- wear(wear_),
- main_group(main_group_)
+ wear(wear_)
{}
};
-HitParams getHitParams(const ItemGroupList &groups,
+HitParams getHitParams(const ItemGroupList &armor_groups,
const ToolCapabilities *tp, float time_from_last_punch);
-HitParams getHitParams(const ItemGroupList &groups,
+HitParams getHitParams(const ItemGroupList &armor_groups,
const ToolCapabilities *tp);
struct PunchDamageResult
@@ -123,7 +125,6 @@ struct PunchDamageResult
bool did_punch;
int damage;
int wear;
- std::string main_group;
PunchDamageResult():
did_punch(false),