Skip to content

Commit

Permalink
items: represent item to_hit as an object in JSON
Browse files Browse the repository at this point in the history
Add the ability to represent an item's to_hit as an object  that is parsed
into the integer modifier by item_factory.  Update kitchen_knives.json
as a proof of concept.
  • Loading branch information
mlangsdorf committed Aug 17, 2020
1 parent 7110dbf commit 42f91c8
Show file tree
Hide file tree
Showing 3 changed files with 178 additions and 9 deletions.
15 changes: 8 additions & 7 deletions data/json/items/melee/knives_kitchen.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"volume": "300 ml",
"price": 3000,
"price_postapoc": 50,
"to_hit": -1,
"to_hit": { "grip": "weapon", "length": "short", "surface": "point", "balance": "neutral" },
"bashing": 2,
"cutting": 10,
"qualities": [ [ "CUT", 1 ], [ "BUTCHER", 25 ] ],
Expand All @@ -36,6 +36,7 @@
"volume": "100 ml",
"price": 250,
"price_postapoc": 50,
"to_hit": { "grip": "weapon", "length": "hand", "surface": "point", "balance": "neutral" },
"bashing": 2,
"cutting": 7,
"qualities": [ [ "CUT", 1 ], [ "CUT_FINE", 1 ], [ "BUTCHER", 15 ] ],
Expand All @@ -53,7 +54,7 @@
"volume": "30 ml",
"price": 250,
"price_postapoc": 50,
"to_hit": -2,
"to_hit": { "grip": "weapon", "length": "hand", "surface": "point", "balance": "neutral" },
"bashing": 1,
"cutting": 6,
"qualities": [ [ "CUT", 1 ], [ "CUT_FINE", 1 ], [ "BUTCHER", 10 ] ],
Expand All @@ -71,7 +72,7 @@
"volume": "200 ml",
"price": 1500,
"price_postapoc": 100,
"to_hit": -1,
"to_hit": { "grip": "weapon", "length": "short", "surface": "point", "balance": "neutral" },
"bashing": 1,
"cutting": 10,
"qualities": [ [ "CUT", 1 ], [ "CUT_FINE", 1 ], [ "BUTCHER", 10 ] ],
Expand All @@ -89,7 +90,7 @@
"volume": "200 ml",
"price": 1500,
"price_postapoc": 50,
"to_hit": -3,
"to_hit": { "grip": "weapon", "length": "short", "surface": "point", "balance": "neutral" },
"bashing": 1,
"cutting": 8,
"qualities": [ [ "CUT", 1 ], [ "CUT_FINE", 1 ], [ "BUTCHER", 22 ] ],
Expand All @@ -109,7 +110,7 @@
"price_postapoc": 50,
"bashing": 4,
"cutting": 6,
"to_hit": -2,
"to_hit": { "grip": "weapon", "length": "hand", "surface": "any", "balance": "neutral" },
"qualities": [ [ "CUT", 1 ], [ "CUT_FINE", 1 ], [ "BUTCHER", 8 ] ],
"flags": [ "SHEATH_KNIFE" ]
},
Expand All @@ -125,7 +126,7 @@
"volume": "250 ml",
"price": 2500,
"price_postapoc": 50,
"to_hit": -1,
"to_hit": { "grip": "weapon", "length": "short", "surface": "line", "balance": "neutral" },
"bashing": 2,
"cutting": 10,
"qualities": [ [ "CUT", 1 ], [ "BUTCHER", 15 ] ],
Expand All @@ -143,7 +144,7 @@
"volume": "300 ml",
"price": 3500,
"price_postapoc": 50,
"to_hit": -1,
"to_hit": { "grip": "weapon", "length": "short", "surface": "line", "balance": "uneven" },
"bashing": 2,
"cutting": 12,
"qualities": [ [ "CUT", 1 ], [ "BUTCHER", 25 ] ],
Expand Down
21 changes: 20 additions & 1 deletion doc/JSON_INFO.md
Original file line number Diff line number Diff line change
Expand Up @@ -2061,7 +2061,13 @@ See also VEHICLE_JSON.md
"material": ["COTTON"], // Material types, can be as many as you want. See materials.json for possible options
"cutting": 0, // (Optional, default = 0) Cutting damage caused by using it as a melee weapon. This value cannot be negative.
"bashing": 0, // (Optional, default = 0) Bashing damage caused by using it as a melee weapon. This value cannot be negative.
"to_hit": 0, // (Optional, default = 0) To-hit bonus if using it as a melee weapon (whatever for?)
"to_hit": 0, // (Optional, deprecated, default = 0) To-hit bonus if using it as a melee weapon (whatever for?). The object version is preferred
"to_hit" { // (Optional, Preferred) To hit bonus values, see below
"grip": "solid", // the item's grip value
"length": "long", // the item's length value
"surface": "point", // the item's striking surface value
"balance": "neutral" // the item's balance value
}
"flags": ["VARSIZE"], // Indicates special effects, see JSON_FLAGS.md
"environmental_protection_with_filter": 6, // the resistance to environmental effects if an item (for example a gas mask) requires a filter to operate and this filter is installed. Used in combination with use_action 'GASMASK' and 'DIVE_TANK'
"magazine_well": 0, // Volume above which the magazine starts to protrude from the item and add extra volume
Expand All @@ -2088,6 +2094,19 @@ See also VEHICLE_JSON.md
},
```

#### To hit object
For additional clarity, an item's `to_hit` bonus can be encoded as string of 4 fields. All the fields are mandatory:

```C++
"to_hit": {
"grip": "weapon", // one of "bad", "none", "solid", or "weapon"
"length": "hand", // one of "hand", "short", or "long"
"surface": "any", // one of "point", "line", "any", or "every"
"balance": "neutral" // one of "clumsy", "uneven", "neutral", or "good"
}
```
See `GAME_BALANCE.md`'s `MELEE_WEAPONS` section for the criteria for selecting each value.

### Ammo

```C++
Expand Down
151 changes: 150 additions & 1 deletion src/item_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2608,6 +2608,148 @@ void Item_factory::add_special_pockets( itype &def )
}
}

enum class grip_val : int {
BAD = 0,
NONE = 1,
SOLID = 2,
WEAPON = 3,
LAST = 4
};
template<>
struct enum_traits<grip_val> {
static constexpr auto last = grip_val::LAST;
};
enum class length_val : int {
HAND = 0,
SHORT = 1,
LONG = 2,
LAST = 3
};
template<>
struct enum_traits<length_val> {
static constexpr auto last = length_val::LAST;
};
enum class surface_val : int {
POINT = 0,
LINE = 1,
ANY = 2,
EVERY = 3,
LAST = 4
};
template<>
struct enum_traits<surface_val> {
static constexpr auto last = surface_val::LAST;
};
enum class balance_val : int {
CLUMSY = 0,
UNEVEN = 1,
NEUTRAL = 2,
GOOD = 3,
LAST = 4
};
template<>
struct enum_traits<balance_val> {
static constexpr auto last = balance_val::LAST;
};

namespace io
{
// *INDENT-OFF*
template<>
std::string enum_to_string<grip_val>( grip_val val )
{
switch( val ) {
case grip_val::BAD: return "bad";
case grip_val::NONE: return "none";
case grip_val::SOLID: return "solid";
case grip_val::WEAPON: return "weapon";
default: break;
}
debugmsg( "Invalid grip val" );
abort();
}

template<>
std::string enum_to_string<length_val>( length_val val )
{
switch( val ) {
case length_val::HAND: return "hand";
case length_val::SHORT: return "short";
case length_val::LONG: return "long";
default: break;
}
debugmsg( "Invalid length val" );
abort();
}

template<>
std::string enum_to_string<surface_val>( surface_val val )
{
switch( val ) {
case surface_val::POINT: return "point";
case surface_val::LINE: return "line";
case surface_val::ANY: return "any";
case surface_val::EVERY: return "every";
default: break;
}
debugmsg( "Invalid surface val" );
abort();
}

template<>
std::string enum_to_string<balance_val>( balance_val val )
{
switch( val ) {
case balance_val::CLUMSY: return "clumsy";
case balance_val::UNEVEN: return "uneven";
case balance_val::NEUTRAL: return "neutral";
case balance_val::GOOD: return "good";
default: break;
}
debugmsg( "Invalid balance val" );
abort();
}

struct acc_data {
grip_val grip = grip_val::WEAPON;
length_val length = length_val::HAND;
surface_val surface = surface_val::ANY;
balance_val balance = balance_val::NEUTRAL;

// all items have a basic accuracy of -2, per GAME_BALANCE.md
static constexpr int base_acc = -2;
// grip val should go from -1 to 2 but enum_to_string wants to start at 0
static constexpr int grip_offset = -1;
// surface val should from from -2 to 1 but enum_to_string wants to start at 0
static constexpr int surface_offset = -2;
// balance val should from from -2 to 1 but enum_to_string wants to start at 0
static constexpr int balance_offset = -2;
// all the constant offsets and the base accuracy together
static constexpr int acc_offset = base_acc + grip_offset + surface_offset + balance_offset;
int sum_values() {
return acc_offset + static_cast<int>( grip ) + static_cast<int>( length ) +
static_cast<int>( surface ) + static_cast<int>( balance );
}
void deserialize( const JsonObject &jo );
void load( const JsonObject &jo );
};

void acc_data::deserialize( const JsonObject &jo )
{
load( jo );
}

void acc_data::load( const JsonObject &jo )
{
bool was_loaded = false;
optional( jo, was_loaded, "grip", grip, grip_val::WEAPON );
optional( jo, was_loaded, "length", length, length_val::HAND );
optional( jo, was_loaded, "surface", surface, surface_val::ANY );
optional( jo, was_loaded, "balance", balance, balance_val::NEUTRAL );
}
// *INDENT-ON*
} // namespace io

void Item_factory::load_basic_info( const JsonObject &jo, itype &def, const std::string &src )
{
bool strict = src == "dda";
Expand All @@ -2623,7 +2765,14 @@ void Item_factory::load_basic_info( const JsonObject &jo, itype &def, const std:
assign( jo, "integral_volume", def.integral_volume );
assign( jo, "bashing", def.melee[DT_BASH], strict, 0 );
assign( jo, "cutting", def.melee[DT_CUT], strict, 0 );
assign( jo, "to_hit", def.m_to_hit, strict );
if( jo.has_int( "to_hit" ) ) {
assign( jo, "to_hit", def.m_to_hit, strict );
} else if( jo.has_object( "to_hit" ) ) {
io::acc_data temp;
bool was_loaded = false;
mandatory( jo, was_loaded, "to_hit", temp );
def.m_to_hit = temp.sum_values();
}
assign( jo, "container", def.default_container );
assign( jo, "sealed", def.default_container_sealed );
assign( jo, "min_strength", def.min_str );
Expand Down

0 comments on commit 42f91c8

Please sign in to comment.