diff options
author | PilzAdam <pilzadam@minetest.net> | 2013-03-28 21:40:44 +0100 |
---|---|---|
committer | PilzAdam <pilzadam@minetest.net> | 2013-03-29 20:14:09 +0100 |
commit | 7d9329ecfe84733cdefa34eab25ee3d124c94c59 (patch) | |
tree | c31fa17924b27fc57e30e5c3fe619d96b75f14d4 | |
parent | 3640c8c051bc6b72f4af52752b2d48ced274f539 (diff) | |
download | minetest-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.txt | 28 | ||||
-rw-r--r-- | src/clientserver.h | 4 | ||||
-rw-r--r-- | src/content_sao.cpp | 6 | ||||
-rw-r--r-- | src/itemdef.cpp | 8 | ||||
-rw-r--r-- | src/itemdef.h | 6 | ||||
-rw-r--r-- | src/scriptapi_common.cpp | 24 | ||||
-rw-r--r-- | src/server.cpp | 6 | ||||
-rw-r--r-- | src/server.h | 2 | ||||
-rw-r--r-- | src/tool.cpp | 57 | ||||
-rw-r--r-- | src/tool.h | 21 |
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), |