Skip to content

Commit

Permalink
add item blacklist in json data to prevent items from appearing in-game
Browse files Browse the repository at this point in the history
  • Loading branch information
BevapDin committed Feb 6, 2014
1 parent bf9692c commit d91d8cc
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 0 deletions.
3 changes: 3 additions & 0 deletions src/init.cpp
Expand Up @@ -193,6 +193,8 @@ void DynamicDataLoader::initialize()
type_function_map["monitems"] = new ClassFunctionAccessor<game>(g, &game::load_monitem);

type_function_map["region_settings"] = new StaticFunctionAccessor(&load_region_settings);
type_function_map["ITEM_BLACKLIST"] = new ClassFunctionAccessor<Item_factory>(item_controller,
&Item_factory::load_item_blacklist);

// ...unimplemented?
type_function_map["INSTRUMENT"] = new StaticFunctionAccessor(&load_ingored_type);
Expand Down Expand Up @@ -388,6 +390,7 @@ void DynamicDataLoader::finalize_loaded_data() {
calculate_mapgen_weights();
MonsterGenerator::generator().finalize_mtypes();
g->finalize_vehicles();
item_controller->finialize_item_blacklist();
finalize_recipes();
check_consistency();
}
Expand Down
98 changes: 98 additions & 0 deletions src/item_factory.cpp
Expand Up @@ -5,6 +5,7 @@
#include "addiction.h"
#include "translations.h"
#include "bodypart.h"
#include "crafting.h"
#include <algorithm>
#include <cstdlib>
#include <iostream>
Expand All @@ -30,6 +31,103 @@ static const std::string category_id_other("other");

Item_factory* item_controller = new Item_factory();

extern std::map<std::string, std::queue<std::pair<recipe *, int> > > recipe_booksets;

typedef std::set<std::string> t_string_set;
static t_string_set item_blacklist;

bool remove_item(const std::string &itm, std::vector<component>& com) {
std::vector<component>::iterator a = com.begin();
while(a != com.end()) {
if(a->type == itm) {
a = com.erase(a);
} else {
++a;
}
}
return com.empty();
}

bool remove_item(const std::string &itm, std::vector<std::vector<component> >& com) {
for(size_t i = 0; i < com.size(); i++) {
// Note: this assumes that coms[i] is never an empty vector
if(remove_item(itm, com[i])) {
return true;
}
}
return false;
}

void remove_item(const std::string &itm, std::vector<map_bash_item_drop>& vec) {
for(size_t i = 0; i < vec.size(); i++) {
if(vec[i].itemtype == itm) {
vec.erase(vec.begin() + i);
i--;
}
}
}

void Item_factory::finialize_item_blacklist() {
std::set<recipe*> deleted_recipes;
for(t_string_set::const_iterator a = item_blacklist.begin(); a != item_blacklist.end(); ++a) {
const std::string &itm = *a;
for(std::map<Item_tag, Item_group*>::iterator b = m_template_groups.begin(); b != m_template_groups.end(); ++b) {
b->second->remove_item(itm);
}
for(recipe_map::iterator b = recipes.begin(); b != recipes.end(); ++b) {
for(size_t c = 0; c < b->second.size(); c++) {
recipe *r = b->second[c];
if(r->result == itm || remove_item(itm, r->components) || remove_item(itm, r->tools)) {
deleted_recipes.insert(r);
delete r;
b->second.erase(b->second.begin() + c);
c--;
continue;
}
}
}
for(size_t i = 0; i < constructions.size(); i++) {
construction *c = constructions[i];
if(remove_item(itm, c->components) || remove_item(itm, c->tools)) {
delete c;
constructions.erase(constructions.begin() + i);
i--;
}
}
for(size_t i = 0; i < terlist.size(); i++) {
remove_item(itm, terlist[i].bash.items);
}
for(size_t i = 0; i < furnlist.size(); i++) {
remove_item(itm, furnlist[i].bash.items);
}
}
// look through the recipe-to-book mapping and remove any mapping
// to recipes that have been removed (and already deleted! - dangling pointers ahead)
for (std::map<std::string, std::queue<std::pair<recipe *, int> > >::iterator book_ref_it =
recipe_booksets.begin(); book_ref_it != recipe_booksets.end(); ++book_ref_it) {
// std::queue doesn't support erase, have to make a copy
// without the delete recipes and use that
std::queue<std::pair<recipe *, int> > copy;
while (!book_ref_it->second.empty()) {
std::pair<recipe *, int> rec_pair = book_ref_it->second.front();
book_ref_it->second.pop();
if (deleted_recipes.count(rec_pair.first) == 0) {
copy.push(rec_pair); // not delete, recipe still valid
}
}
// std::queue doesn't even has a swap function, have to use slow copy assignment
book_ref_it->second = copy;
}
item_blacklist.clear();
}

void Item_factory::load_item_blacklist(JsonObject &json) {
JsonArray jarr = json.get_array("items");
while(jarr.has_more()) {
item_blacklist.insert(jarr.next_string());
}
}

//Every item factory comes with a missing item
Item_factory::Item_factory(){
init();
Expand Down
3 changes: 3 additions & 0 deletions src/item_factory.h
Expand Up @@ -83,6 +83,9 @@ class Item_factory
void load_bionic (JsonObject &jo);
void load_veh_part (JsonObject &jo);

void load_item_blacklist(JsonObject &jo);
void finialize_item_blacklist();

// Check that all items referenced in the groups
// do actually exist (are defined)
void check_items_of_groups_exist() const;
Expand Down
42 changes: 42 additions & 0 deletions src/item_group.cpp
Expand Up @@ -114,3 +114,45 @@ bool Item_group::has_item(const Item_tag item_id) {

return 0;
}

void Item_group::remove_item(const Item_tag &item_id) {
std::set<std::string> rec;
remove_item(item_id, rec);
}

void Item_group::remove_item(const Item_tag &item_id, std::set<std::string> &rec) {
if(rec.count(m_id) > 0) {
return;
}
rec.insert(m_id);
// If this removes an item/group, m_max_odds must be decreased
// by the chance of the removed item/group. But the chance of
// that is not directly stored, but as offset from the previous
// item/group (see add_entry/add_group)
int delta_max_odds = 0;
int prev_upper_bound = 0;
for(size_t i = 0; i < m_groups.size(); i++) {
m_groups[i]->m_group->remove_item(item_id, rec);
if(m_groups[i]->m_group->m_max_odds == 0) {
delta_max_odds += (m_groups[i]->m_upper_bound - prev_upper_bound);
delete m_groups[i];
m_groups.erase(m_groups.begin() + i);
i--;
} else {
m_groups[i]->m_upper_bound -= delta_max_odds;
prev_upper_bound = m_groups[i]->m_upper_bound;
}
}
for(size_t i = 0; i < m_entries.size(); i++) {
if(m_entries[i]->m_id == item_id) {
delta_max_odds += (m_entries[i]->m_upper_bound - prev_upper_bound);
delete m_entries[i];
m_entries.erase(m_entries.begin() + i);
i--;
} else {
m_entries[i]->m_upper_bound -= delta_max_odds;
prev_upper_bound = m_entries[i]->m_upper_bound;
}
}
m_max_odds -= delta_max_odds;
}
6 changes: 6 additions & 0 deletions src/item_group.h
Expand Up @@ -2,6 +2,8 @@
#define _ITEM_GROUP_H_

#include <vector>
#include <set>
#include <string>

typedef std::string Item_tag;

Expand All @@ -19,13 +21,15 @@ friend class Item_factory;
bool guns_have_ammo();
void add_entry(const Item_tag item_id, int chance);
void add_group(Item_group*, int chance);
void remove_item(const Item_tag &item_id);

// Does this item group contain the given item?
bool has_item(const Item_tag item_id);
// Check that all items referenced here do actually exist (are defined)
// this is not recursive
void check_items_exist() const;
private:
void remove_item(const Item_tag &item_id, std::set<std::string> &rec);

const Item_tag m_id;
int m_max_odds;
Expand All @@ -39,6 +43,7 @@ friend class Item_factory;
//to add a lower bound value.
class Item_group_entry
{
friend class Item_group;
public:
Item_group_entry(const Item_tag id, int upper_bound);

Expand All @@ -51,6 +56,7 @@ class Item_group_entry

class Item_group_group
{
friend class Item_group;
public:
Item_group_group(Item_group* group, int upper_bound);

Expand Down

0 comments on commit d91d8cc

Please sign in to comment.