Skip to content

Commit

Permalink
Dehardcoded skill and damage requirements in martialarts.cpp (#34602)
Browse files Browse the repository at this point in the history
  • Loading branch information
Hymore246 authored and kevingranade committed Dec 14, 2019
1 parent 72dbda8 commit 488d353
Show file tree
Hide file tree
Showing 8 changed files with 255 additions and 267 deletions.
109 changes: 38 additions & 71 deletions data/json/martialarts.json

Large diffs are not rendered by default.

74 changes: 32 additions & 42 deletions data/json/martialarts_fictional.json

Large diffs are not rendered by default.

248 changes: 113 additions & 135 deletions data/json/techniques.json

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion doc/MARTIALART_JSON.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
"unarmed_allowed" : true, // Can an unarmed character use this technique
"unarmed_weapons_allowed" : true, // Does this technique require the character to be actually unarmed or does it allow unarmed weapons
"melee_allowed" : true, // Means that ANY melee weapon can be used, NOT just the martial art's weapons
"min_melee" : 3, // Minimum skill and its level required to use this technique. Can be any skill.
"skill_requirements": [ { "name": "melee", "level": 3 } ], // Skills and their minimum levels required to use this technique. Can be any skill.
"weapon_damage_requirements": [ { "type": "bash", "min": 5 } ], // Minimum weapon damage required to use this technique. Can be any damage type.
"req_buffs": [ "eskrima_hit_buff" ], // This technique requires a named buff to be active
"crit_tec" : true, // This technique only works on a critical hit
"crit_ok" : true, // This technique works on both normal and critical hits
Expand Down
5 changes: 5 additions & 0 deletions src/damage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,11 @@ static const std::map<std::string, damage_type> dt_map = {
{ translate_marker_context( "damage type", "electric" ), DT_ELECTRIC }
};

const std::map<std::string, damage_type> &get_dt_map()
{
return dt_map;
}

damage_type dt_by_name( const std::string &name )
{
const auto &iter = dt_map.find( name );
Expand Down
2 changes: 2 additions & 0 deletions src/damage.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#define DAMAGE_H

#include <array>
#include <map>
#include <vector>
#include <string>

Expand Down Expand Up @@ -103,6 +104,7 @@ struct resistances {
resistances &operator+=( const resistances &other );
};

const std::map<std::string, damage_type> &get_dt_map();
damage_type dt_by_name( const std::string &name );
std::string name_by_dt( const damage_type &dt );

Expand Down
77 changes: 61 additions & 16 deletions src/martialarts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,6 @@
#include "enums.h"
#include "optional.h"

static const skill_id skill_melee( "melee" );
static const skill_id skill_bashing( "bashing" );
static const skill_id skill_cutting( "cutting" );
static const skill_id skill_stabbing( "stabbing" );
static const skill_id skill_unarmed( "unarmed" );

namespace
{
generic_factory<ma_technique> ma_techniques( "martial art technique" );
Expand Down Expand Up @@ -74,6 +68,52 @@ void add_if_exists( const JsonObject &jo, Container &cont, bool was_loaded,
}
}

class ma_skill_reader : public generic_typed_reader<ma_skill_reader>
{
public:
std::pair<skill_id, int> get_next( JsonIn &jin ) const {
JsonObject jo = jin.get_object();
return std::pair<skill_id, int>( skill_id( jo.get_string( "name" ) ), jo.get_int( "level" ) );
}
template<typename C>
void erase_next( JsonIn &jin, C &container ) const {
const skill_id id = skill_id( jin.get_string() );
reader_detail::handler<C>().erase_if( container, [&id]( const std::pair<skill_id, int> &e ) {
return e.first == id;
} );
}
};

class ma_weapon_damage_reader : public generic_typed_reader<ma_weapon_damage_reader>
{
public:
std::map<std::string, damage_type> dt_map = get_dt_map();

std::pair<damage_type, int> get_next( JsonIn &jin ) const {
JsonObject jo = jin.get_object();
std::string type = jo.get_string( "type" );
const auto iter = get_dt_map().find( type );
if( iter == get_dt_map().end() ) {
jo.throw_error( "Invalid damage type" );
}
const damage_type dt = iter->second;
return std::pair<damage_type, int>( dt, jo.get_int( "min" ) );
}
template<typename C>
void erase_next( JsonIn &jin, C &container ) const {
JsonObject jo = jin.get_object();
std::string type = jo.get_string( "type" );
const auto iter = get_dt_map().find( type );
if( iter == get_dt_map().end() ) {
jo.throw_error( "Invalid damage type" );
}
damage_type id = iter->second;
reader_detail::handler<C>().erase_if( container, [&id]( const std::pair<damage_type, int> &e ) {
return e.first == id;
} );
}
};

void ma_requirements::load( const JsonObject &jo, const std::string & )
{
optional( jo, was_loaded, "unarmed_allowed", unarmed_allowed, false );
Expand All @@ -85,16 +125,8 @@ void ma_requirements::load( const JsonObject &jo, const std::string & )
optional( jo, was_loaded, "req_buffs", req_buffs, auto_flags_reader<mabuff_id> {} );
optional( jo, was_loaded, "req_flags", req_flags, auto_flags_reader<> {} );

// TODO: De-hardcode the skills and damage types here
add_if_exists( jo, min_skill, was_loaded, "min_melee", skill_melee );
add_if_exists( jo, min_skill, was_loaded, "min_unarmed", skill_unarmed );
add_if_exists( jo, min_skill, was_loaded, "min_bashing", skill_bashing );
add_if_exists( jo, min_skill, was_loaded, "min_cutting", skill_cutting );
add_if_exists( jo, min_skill, was_loaded, "min_stabbing", skill_stabbing );

add_if_exists( jo, min_damage, was_loaded, "min_bashing_damage", DT_BASH );
add_if_exists( jo, min_damage, was_loaded, "min_cutting_damage", DT_CUT );
add_if_exists( jo, min_damage, was_loaded, "min_stabbing_damage", DT_STAB );
optional( jo, was_loaded, "skill_requirements", min_skill, ma_skill_reader {} );
optional( jo, was_loaded, "weapon_damage_requirements", min_damage, ma_weapon_damage_reader {} );
}

void ma_technique::load( const JsonObject &jo, const std::string &src )
Expand Down Expand Up @@ -469,6 +501,19 @@ std::string ma_requirements::get_description( bool buff ) const
}, enumeration_conjunction::none ) << std::endl;
}

if( std::any_of( min_damage.begin(),
min_damage.end(), []( const std::pair<damage_type, int> &pr ) {
return pr.second > 0;
} ) ) {
dump << ngettext( "<bold>Damage type required: </bold>",
"<bold>Damage types required: </bold>", min_damage.size() );

dump << enumerate_as_string( min_damage.begin(),
min_damage.end(), []( const std::pair<damage_type, int> &pr ) {
return string_format( _( "%s: <stat>%d</stat>" ), name_by_dt( pr.first ), pr.second );
}, enumeration_conjunction::none ) << std::endl;
}

if( !req_buffs.empty() ) {
dump << _( "<bold>Requires:</bold> " );

Expand Down
4 changes: 2 additions & 2 deletions src/martialarts.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ struct ma_requirements {
bool wall_adjacent; // Does it only work near a wall?

/** Minimum amount of given skill to trigger this bonus */
std::map<skill_id, int> min_skill;
std::vector<std::pair<skill_id, int>> min_skill;

/** Minimum amount of given damage type on the weapon
* Note: DT_FIRE currently won't work, not even on flaming weapons!
*/
std::map<damage_type, int> min_damage;
std::vector<std::pair<damage_type, int>> min_damage;

std::set<mabuff_id> req_buffs; // other buffs required to trigger this bonus
std::set<std::string> req_flags; // any item flags required for this technique
Expand Down

0 comments on commit 488d353

Please sign in to comment.