Skip to content

Commit

Permalink
Implement mod tracking for items and furn/terrain (CleverRaven#49723)
Browse files Browse the repository at this point in the history
Track which mods the items are modified in, and in what order, display
it in the descriptions.
  • Loading branch information
anothersimulacrum authored Jul 8, 2021
1 parent 31be9a3 commit 8ce3dc5
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 4 deletions.
13 changes: 11 additions & 2 deletions src/descriptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "input.h"
#include "map.h"
#include "mapdata.h"
#include "mod_manager.h"
#include "output.h"
#include "string_formatter.h"
#include "translations.h"
Expand Down Expand Up @@ -108,15 +109,23 @@ void game::extended_description( const tripoint &p )
desc = _( "You do not see any furniture here." );
} else {
const furn_id fid = m.furn( p );
desc = fid.obj().extended_description();
const std::string mod_src = enumerate_as_string( fid->src.begin(),
fid->src.end(), []( const std::pair<furn_str_id, mod_id> &source ) {
return string_format( "'%s'", source.second->name() );
}, enumeration_conjunction::arrow );
desc = string_format( _( "Origin: %s\n%s" ), mod_src, fid->extended_description() );
}
break;
case description_target::terrain:
if( !u.sees( p ) ) {
desc = _( "You can't see the terrain here." );
} else {
const ter_id tid = m.ter( p );
desc = tid.obj().extended_description();
const std::string mod_src = enumerate_as_string( tid->src.begin(),
tid->src.end(), []( const std::pair<ter_str_id, mod_id> &source ) {
return string_format( "'%s'", source.second->name() );
}, enumeration_conjunction::arrow );
desc = string_format( _( "Origin: %s\n%s" ), mod_src, tid->extended_description() );
}
break;
}
Expand Down
5 changes: 5 additions & 0 deletions src/generic_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "init.h"
#include "int_id.h"
#include "json.h"
#include "mod_tracker.h"
#include "output.h"
#include "string_id.h"
#include "units.h"
Expand Down Expand Up @@ -264,6 +265,7 @@ class generic_factory
}
if( jo.has_string( id_member_name ) ) {
def.id = string_id<T>( jo.get_string( id_member_name ) );
assign_src( def, src );
def.load( jo, src );
insert( def );

Expand All @@ -284,6 +286,7 @@ class generic_factory
break;
}
def.id = string_id<T>( e );
assign_src( def, src );
def.load( jo, src );
insert( def );
}
Expand All @@ -294,6 +297,7 @@ class generic_factory

} else if( jo.has_string( legacy_id_member_name ) ) {
def.id = string_id<T>( jo.get_string( legacy_id_member_name ) );
assign_src( def, src );
def.load( jo, src );
insert( def );

Expand All @@ -314,6 +318,7 @@ class generic_factory
break;
}
def.id = string_id<T>( e );
assign_src( def, src );
def.load( jo, src );
insert( def );
}
Expand Down
9 changes: 9 additions & 0 deletions src/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
#include "martialarts.h"
#include "material.h"
#include "messages.h"
#include "mod_manager.h"
#include "monster.h"
#include "mtype.h"
#include "npc.h"
Expand Down Expand Up @@ -1697,6 +1698,14 @@ double item::average_dps( const Character &guy ) const
void item::basic_info( std::vector<iteminfo> &info, const iteminfo_query *parts, int batch,
bool /* debug */ ) const
{
if( parts->test( iteminfo_parts::BASE_MOD_SRC ) ) {
info.emplace_back( "BASE", string_format( _( "Origin: %s" ), enumerate_as_string( type->src.begin(),
type->src.end(), []( const std::pair<itype_id, mod_id> &source ) {
return string_format( "'%s'", source.second->name() );
}, enumeration_conjunction::arrow ) ) );
insert_separation_line( info );
}

const std::string space = " ";
if( parts->test( iteminfo_parts::BASE_MATERIAL ) ) {
const std::vector<const material_type *> mat_types = made_of_types();
Expand Down
5 changes: 5 additions & 0 deletions src/item_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3079,6 +3079,11 @@ void Item_factory::load_basic_info( const JsonObject &jo, itype &def, const std:
jo.read( "id", def.id, true );
}

if( !def.src.empty() && def.src.back().first != def.id ) {
def.src.clear();
}
def.src.emplace_back( def.id, mod_id( src ) );

if( def.magazines.empty() ) {
migrate_mag_from_pockets( def );
}
Expand Down
1 change: 1 addition & 0 deletions src/iteminfo_query.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

enum class iteminfo_parts : size_t {
BASE_CATEGORY = 0,
BASE_MOD_SRC,
BASE_PRICE,
BASE_BARTER,
BASE_OWNER,
Expand Down
2 changes: 2 additions & 0 deletions src/itype.h
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,8 @@ struct itype {

using FlagsSetType = std::set<flag_id>;

std::vector<std::pair<itype_id, mod_id>> src;

/**
* Slots for various item type properties. Each slot may contain a valid pointer or null, check
* this before using it.
Expand Down
6 changes: 6 additions & 0 deletions src/mapdata.h
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,9 @@ struct map_data_common_t {
* Short for terrain type. This struct defines all of the metadata for a given terrain id (an enum below).
*/
struct ter_t : map_data_common_t {

std::vector<std::pair<ter_str_id, mod_id>> src;

ter_str_id id; // The terrain's ID. Must be set, must be unique.
ter_str_id open; // Open action: transform into terrain with matching id
ter_str_id close; // Close action: transform into terrain with matching id
Expand Down Expand Up @@ -397,6 +400,9 @@ void reset_furn_ter();
*/

struct furn_t : map_data_common_t {

std::vector<std::pair<furn_str_id, mod_id>> src;

furn_str_id id;
furn_str_id open; // Open action: transform into furniture with matching id
furn_str_id close; // Close action: transform into furniture with matching id
Expand Down
51 changes: 51 additions & 0 deletions src/mod_tracker.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#pragma once
#ifndef CATA_SRC_MOD_TRACKER_H
#define CATA_SRC_MOD_TRACKER_H

#include <string>

#include "cata_void.h"
#include "type_id.h"

/**
* Mod Tracking:
*
* These functions live here to provide various JSON-loaded entities
* with the ids of the mods that they are from.
*
* To subscribe, a JSON-loaded entity simply needs to have a
* 'std::vector<std::pair<(string or int)_id<T>, mod_id> src;' member.
* (As well as storing their id in an 'id' member of either string or int id type)
*
* If the entity is loaded with generic_factory, no further changes are needed.
* If the entity is not loaded with generic_factory, 'assign_src()' must be called sometime
* after the 'id' member has been assigned.
*/

/** Template magic to determine if the conditions above are satisfied */
template<typename T, typename = cata::void_t<>>
struct has_src_member : std::false_type {};

template<typename T>
struct has_src_member<T, cata::void_t<decltype( std::declval<T &>().src.emplace_back( std::declval<T &>().id, mod_id() ) )>> :
std::true_type {};

/** Dummy function, for if those conditions are not satisfied */
template < typename T, typename std::enable_if_t < !has_src_member<T>::value > * = nullptr >
void assign_src( T &, const std::string & )
{
}

/** If those conditions are satisfied, keep track of where this item has been modified */
template<typename T, typename std::enable_if_t<has_src_member<T>::value > * = nullptr>
void assign_src( T &def, const std::string &src )
{
// We need to make sure we're keeping where this entity has been loaded
// If the id this was last loaded with is not this one, discard the history and start again
if( !def.src.empty() && def.src.back().first != def.id ) {
def.src.clear();
}
def.src.emplace_back( def.id, mod_id( src ) );
}

#endif // CATA_SRC_MOD_TRACKER_H
16 changes: 14 additions & 2 deletions src/output.h
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,8 @@ inline std::string get_labeled_bar( const double val, const int width, const std
enum class enumeration_conjunction : int {
none,
and_,
or_
or_,
arrow
};

/**
Expand All @@ -692,18 +693,29 @@ std::string enumerate_as_string( const _Container &values,
return ( values.size() > 2 ? _( ", and " ) : _( " and " ) );
case enumeration_conjunction::or_:
return ( values.size() > 2 ? _( ", or " ) : _( " or " ) );
case enumeration_conjunction::arrow:
return _( " > " );
}
debugmsg( "Unexpected conjunction" );
return _( ", " );
}
();
const std::string separator = [&conj]() {
switch( conj ) {
case enumeration_conjunction::arrow:
return _( " > " );
default:
return _( ", " );
}
}
();
std::string res;
for( auto iter = values.begin(); iter != values.end(); ++iter ) {
if( iter != values.begin() ) {
if( std::next( iter ) == values.end() ) {
res += final_separator;
} else {
res += _( ", " );
res += separator;
}
}
res += *iter;
Expand Down

0 comments on commit 8ce3dc5

Please sign in to comment.