Skip to content

Commit

Permalink
Merge pull request #79388 from ShnitzelX2/character-map-book-chapters
Browse files Browse the repository at this point in the history
Chapters are Character-mapped for unique books
  • Loading branch information
Maleclypse authored Jan 29, 2025
2 parents 9baaa00 + c21b37d commit e02f107
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 28 deletions.
8 changes: 8 additions & 0 deletions data/json/items/book/abstract.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@
"copy-from": "book_fict_tpl",
"melee_damage": { "bash": 1 }
},
{
"abstract": "book_fict_soft_collection_tpl",
"type": "BOOK",
"copy-from": "book_fict_soft_tpl",
"name": { "str": "paperback novel", "str_pl": "paperbacks" },
"description": "Paperback fiction novel generic collection",
"generic": true
},
{
"abstract": "book_nonf_hard_tpl",
"type": "BOOK",
Expand Down
40 changes: 25 additions & 15 deletions data/json/items/book/misc.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@
"intelligence": 10,
"time": "26 m",
"chapters": 40,
"generic": true,
"fun": 3
},
{
Expand Down Expand Up @@ -170,6 +171,7 @@
"color": "pink",
"time": "10 m",
"chapters": 4,
"generic": true,
"fun": 1
},
{
Expand All @@ -194,7 +196,7 @@
"type": "BOOK",
"name": { "str": "adventure novel" },
"description": "The stirring tale of a race against time, in search of a lost city located in the heart of the African continent.",
"copy-from": "book_fict_soft_tpl",
"copy-from": "book_fict_soft_collection_tpl",
"price": "8 USD 50 cent",
"price_postapoc": "50 cent",
"time": "20 m",
Expand All @@ -205,7 +207,7 @@
"type": "BOOK",
"name": { "str": "buddy novel" },
"description": "A gripping tale of two friends struggling to survive on the streets of New York City.",
"copy-from": "book_fict_soft_tpl",
"copy-from": "book_fict_soft_collection_tpl",
"weight": "244 g",
"volume": "500 ml",
"price": "6 USD 50 cent",
Expand All @@ -215,7 +217,7 @@
"id": "novel_crime",
"type": "BOOK",
"name": { "str": "crime novel" },
"copy-from": "book_fict_soft_tpl",
"copy-from": "book_fict_soft_collection_tpl",
"description": "After their diamond heist goes wrong, the surviving criminals begin to suspect that one of them is a police informant.",
"intelligence": 6,
"time": "20 m",
Expand Down Expand Up @@ -252,7 +254,7 @@
"type": "BOOK",
"name": { "str": "drama novel" },
"description": "A real book for real adults.",
"copy-from": "book_fict_soft_tpl",
"copy-from": "book_fict_soft_collection_tpl",
"intelligence": 7,
"time": "25 m",
"chapters": 28,
Expand All @@ -263,7 +265,7 @@
"type": "BOOK",
"name": { "str": "erotic novel" },
"description": "A hackneyed fictional narrative concealing low-grade literary smut.",
"copy-from": "book_fict_soft_tpl",
"copy-from": "book_fict_soft_collection_tpl",
"weight": "200 g",
"volume": "500 ml",
"time": "18 m",
Expand All @@ -274,7 +276,7 @@
"type": "BOOK",
"name": { "str": "experimental novel" },
"description": "A bizarre play about the philosophy of existential absurdity. Or maybe it's about two guys waiting for their friend to show up. It's confusing.",
"copy-from": "book_fict_soft_tpl",
"copy-from": "book_fict_soft_collection_tpl",
"weight": "142 g",
"volume": "500 ml",
"intelligence": 7,
Expand All @@ -286,7 +288,7 @@
"type": "BOOK",
"name": { "str": "fantasy novel" },
"description": "Basic sword & sorcery.",
"copy-from": "book_fict_soft_tpl",
"copy-from": "book_fict_soft_collection_tpl",
"weight": "227 g",
"volume": "1 L",
"intelligence": 7,
Expand All @@ -300,7 +302,7 @@
"type": "BOOK",
"name": { "str": "horror novel" },
"description": "Maybe not the best reading material considering the situation.",
"copy-from": "book_fict_soft_tpl",
"copy-from": "book_fict_soft_collection_tpl",
"weight": "227 g",
"intelligence": 7,
"time": "18 m",
Expand All @@ -312,7 +314,7 @@
"type": "BOOK",
"name": { "str": "mystery novel" },
"description": "A detective investigates an unusual murder in a secluded location.",
"copy-from": "book_fict_soft_tpl",
"copy-from": "book_fict_soft_collection_tpl",
"intelligence": 7,
"time": "18 m",
"chapters": 28,
Expand All @@ -323,7 +325,7 @@
"type": "BOOK",
"name": { "str": "road novel" },
"description": "A tale about a group of friends who wander the USA in the 1960s against a backdrop of jazz, poetry and drug use.",
"copy-from": "book_fict_soft_tpl",
"copy-from": "book_fict_soft_collection_tpl",
"weight": "244 g",
"volume": "500 ml",
"time": "20 m",
Expand All @@ -345,7 +347,7 @@
"type": "BOOK",
"name": { "str": "romance novel" },
"description": "Drama and mild smut.",
"copy-from": "book_fict_soft_tpl"
"copy-from": "book_fict_soft_collection_tpl"
},
{
"id": "paperback_romance_circuses",
Expand Down Expand Up @@ -497,7 +499,7 @@
"type": "BOOK",
"name": { "str": "spy novel" },
"description": "A tale of intrigue and espionage among Nazis, no, Commies, no, Iraqis!",
"copy-from": "book_fict_soft_tpl",
"copy-from": "book_fict_soft_collection_tpl",
"intelligence": 5,
"time": "18 m",
"chapters": 20,
Expand All @@ -524,7 +526,7 @@
"description": "An exciting seventeenth century tale of how an enslaved Irish doctor and his comrades-in-chains escape and become heroic pirates of the Robin Hood variety.",
"weight": "582 g",
"volume": "750 ml",
"copy-from": "book_fict_soft_tpl",
"copy-from": "book_fict_soft_collection_tpl",
"intelligence": 7,
"time": "20 m",
"chapters": 28,
Expand Down Expand Up @@ -582,7 +584,7 @@
"type": "BOOK",
"name": { "str": "war novel" },
"description": "A thrilling narrative of survival in a prisoner of war camp during the Second World War, filled with riveting subplots about rat farming and dysentery.",
"copy-from": "book_fict_soft_tpl",
"copy-from": "book_fict_soft_collection_tpl",
"weight": "686 g",
"price_postapoc": "50 cent",
"intelligence": 7,
Expand All @@ -604,7 +606,7 @@
"type": "BOOK",
"name": { "str": "western novel" },
"description": "The classic tale of a gunfighting stranger who comes to a small settlement and is hired to help the townsfolk defend themselves from a band of marauding outlaws.",
"copy-from": "book_fict_soft_tpl",
"copy-from": "book_fict_soft_collection_tpl",
"intelligence": 5,
"time": "20 m",
"chapters": 28,
Expand Down Expand Up @@ -680,6 +682,7 @@
"intelligence": 4,
"time": "1 m",
"chapters": 200,
"generic": true,
"fun": -5,
"melee_damage": { "bash": 2 }
},
Expand All @@ -698,6 +701,7 @@
"color": "light_gray",
"time": "10 m",
"chapters": 4,
"generic": true,
"fun": 1,
"flags": [ "INSPIRATIONAL" ]
},
Expand All @@ -717,6 +721,7 @@
"intelligence": 9,
"time": "18 m",
"chapters": 36,
"generic": true,
"fun": 2
},
{
Expand All @@ -735,6 +740,7 @@
"intelligence": 9,
"time": "18 m",
"chapters": 36,
"generic": true,
"fun": 2
},
{
Expand Down Expand Up @@ -825,6 +831,7 @@
"intelligence": 7,
"time": "48 m",
"chapters": 28,
"generic": true,
"fun": 5
},
{
Expand All @@ -843,6 +850,7 @@
"intelligence": 6,
"time": "18 m",
"chapters": 24,
"generic": true,
"fun": 3
},
{
Expand Down Expand Up @@ -978,6 +986,7 @@
"intelligence": 7,
"time": "28 m",
"chapters": 40,
"generic": true,
"fun": 3
},
{
Expand Down Expand Up @@ -1073,6 +1082,7 @@
"intelligence": 7,
"time": "28 m",
"chapters": 40,
"generic": true,
"fun": 4
},
{
Expand Down
1 change: 1 addition & 0 deletions doc/JSON/JSON_INFO.md
Original file line number Diff line number Diff line change
Expand Up @@ -3905,6 +3905,7 @@ Books can be defined like this:
"fun" : -2, // Morale bonus/penalty for reading
"skill" : "computer", // Skill raised
"chapters" : 4, // Number of chapters (for fun only books), each reading "consumes" a chapter. Books with no chapters left are less fun (because the content is already known to the character).
"generic": false, // This book counts chapters by item instance instead of by type (this book represents a generic variety of books, like "book of essays")
"required_level" : 2, // Minimum skill level required to learn
"martial_art": "style_mma", // Martial art learned from this book; incompatible with `skill`
"proficiencies": [ // Having this book mitigate lack of proficiency, required for crafting
Expand Down
2 changes: 2 additions & 0 deletions src/character.h
Original file line number Diff line number Diff line change
Expand Up @@ -2313,6 +2313,8 @@ class Character : public Creature, public visitable
/** Calculates the total fun bonus relative to this character's traits and chapter progress */
bool fun_to_read( const item &book ) const;
int book_fun_for( const item &book, const Character &p ) const;
/** The number of chapters remaining for each book itype */
std::map<itype_id, int> book_chapters;

bool can_pickVolume( const item &it, bool safe = false, const item *avoid = nullptr,
bool ignore_pkt_settings = true ) const;
Expand Down
36 changes: 24 additions & 12 deletions src/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8857,7 +8857,7 @@ void item::set_browsed( bool browsed )

bool item::is_ecopiable() const
{
return has_flag( flag_E_COPIABLE ) || ( is_book() && get_chapters() == 0 );
return has_flag( flag_E_COPIABLE ) || ( is_book() && !type->book->generic );
}

bool item::efiles_all_browsed() const
Expand Down Expand Up @@ -10776,22 +10776,34 @@ int item::get_chapters() const

int item::get_remaining_chapters( const Character &u ) const
{
// NOLINTNEXTLINE(cata-translate-string-literal)
const std::string var = string_format( "remaining-chapters-%d", u.getID().get_value() );
return get_var( var, get_chapters() );
const itype_id &type = typeId();
if( is_book() && type->book->generic ) {
// NOLINTNEXTLINE(cata-translate-string-literal)
const std::string var = string_format( "remaining-chapters-%d", u.getID().get_value() );
return get_var( var, get_chapters() );
}
const std::map<itype_id, int> &book_chapters = u.book_chapters;
auto find_chapters = book_chapters.find( type );
if( find_chapters == book_chapters.end() ) {
return get_chapters();
}
return find_chapters->second;
}

void item::mark_chapter_as_read( const Character &u )
void item::mark_chapter_as_read( Character &u )
{
// NOLINTNEXTLINE(cata-translate-string-literal)
const std::string var = string_format( "remaining-chapters-%d", u.getID().get_value() );
if( type->book && type->book->chapters == 0 ) {
// books without chapters will always have remaining chapters == 0, so we don't need to store them
erase_var( var );
// books without chapters will always have remaining chapters == 0, so we don't need to store them
if( is_book() && get_chapters() == 0 ) {
return;
}
if( is_book() && type->book->generic ) {
// NOLINTNEXTLINE(cata-translate-string-literal)
const std::string var = string_format( "remaining-chapters-%d", u.getID().get_value() );
const int remain = std::max( 0, get_remaining_chapters( u ) - 1 );
set_var( var, remain );
return;
}
const int remain = std::max( 0, get_remaining_chapters( u ) - 1 );
set_var( var, remain );
u.book_chapters[typeId()] = std::max( 0, get_remaining_chapters( u ) - 1 );
}

std::set<recipe_id> item::get_saved_recipes() const
Expand Down
2 changes: 1 addition & 1 deletion src/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -2409,7 +2409,7 @@ class item : public visitable
* Mark one chapter of the book as read by the given player. May do nothing if the book has
* no unread chapters. This is a per-character setting, see @ref get_remaining_chapters.
*/
void mark_chapter_as_read( const Character &u );
void mark_chapter_as_read( Character &u );
/**
* Returns recipes stored on the item (laptops, smartphones, sd cards etc)
* Filters out !is_valid() recipes
Expand Down
1 change: 1 addition & 0 deletions src/item_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3264,6 +3264,7 @@ void islot_book::load( const JsonObject &jo )
optional( jo, was_loaded, "skill", skill, skill_id::NULL_ID() );
optional( jo, was_loaded, "martial_art", martial_art, matype_id::NULL_ID() );
optional( jo, was_loaded, "chapters", chapters, 0 );
optional( jo, was_loaded, "generic", generic, false );
optional( jo, was_loaded, "proficiencies", proficiencies );
optional( jo, was_loaded, "scannable", is_scannable, true );
}
Expand Down
5 changes: 5 additions & 0 deletions src/itype.h
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,11 @@ struct islot_book {
* "To read" means getting 1 skill point, not all of them.
*/
time_duration time = 0_turns;
/**
* This book counts chapters by item instance instead of by type
* (i.e. this book represents a generic variety of books, like "book of essays")
*/
bool generic = false;
/**
* Fun books have chapters; after all are read, the book is less fun.
*/
Expand Down
2 changes: 2 additions & 0 deletions src/savegame_json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1112,6 +1112,7 @@ void Character::load( const JsonObject &data )
data.read( "male", male );
data.read( "cash", cash );
data.read( "recoil", recoil );
data.read( "book_chapters", book_chapters );
data.read( "in_vehicle", in_vehicle );
data.read( "last_sleep_check", last_sleep_check );
if( data.read( "id", tmpid ) && tmpid.is_valid() ) {
Expand Down Expand Up @@ -1489,6 +1490,7 @@ void Character::store( JsonOut &json ) const

json.member( "cash", cash );
json.member( "recoil", recoil );
json.member( "book_chapters", book_chapters );
json.member( "in_vehicle", in_vehicle );
json.member( "id", getID() );

Expand Down

0 comments on commit e02f107

Please sign in to comment.