Permalink
Checking mergeability…
Don’t worry, you can still create the pull request.
Comparing changes
Open a pull request
2
contributors
Unified
Split
Showing
with
183 additions
and 9 deletions.
- +4 −0 action.cpp
- +1 −0 action.h
- +1 −1 data/raw/items/armor.json
- +25 −1 game.cpp
- +2 −1 game.h
- +14 −1 inventory.cpp
- +22 −1 item.cpp
- +2 −1 item_factory.cpp
- +109 −3 player.cpp
- +3 −0 player.h
| @@ -247,6 +247,8 @@ std::string action_ident(action_id act) | |||
| return "disassemble"; | |||
| case ACTION_SLEEP: | |||
| return "sleep"; | |||
| case ACTION_FOLD: | |||
| return "fold"; | |||
| case ACTION_CONTROL_VEHICLE: | |||
| return "control_vehicle"; | |||
| case ACTION_TOGGLE_SAFEMODE: | |||
| @@ -421,6 +423,8 @@ std::string action_name(action_id act) | |||
| return "Disassemble items"; | |||
| case ACTION_SLEEP: | |||
| return "Sleep"; | |||
| case ACTION_FOLD: | |||
| return "Fold"; | |||
| case ACTION_CONTROL_VEHICLE: | |||
| return "Control Vehicle"; | |||
| case ACTION_TOGGLE_SAFEMODE: | |||
| @@ -67,6 +67,7 @@ ACTION_LONGCRAFT, | |||
| ACTION_CONSTRUCT, | |||
| ACTION_DISASSEMBLE, | |||
| ACTION_SLEEP, | |||
| ACTION_FOLD, | |||
| ACTION_CONTROL_VEHICLE, | |||
| ACTION_TOGGLE_SAFEMODE, | |||
| ACTION_TOGGLE_AUTOSAFE, | |||
| @@ -2905,7 +2905,7 @@ | |||
| "ammo": "none", | |||
| "revert_to": "null", | |||
| "phase" : "solid", | |||
| "use_action" : "RAD_BADGE" | |||
| "use_action" : "RAD_BADGE" | |||
| }, | |||
| { | |||
| "type" : "ARMOR", | |||
| @@ -1339,9 +1339,10 @@ int game::inventory_item_menu(char chItem, int startx, int width) { | |||
| vMenu.push_back(iteminfo("MENU", "r", "eload", u.rate_action_reload(&oThisItem))); | |||
| vMenu.push_back(iteminfo("MENU", "D", "isassemble", u.rate_action_disassemble(&oThisItem, this))); | |||
| vMenu.push_back(iteminfo("MENU", "=", " reassign")); | |||
| vMenu.push_back(iteminfo("MENU", "f", " fold", u.rate_action_fold(&oThisItem))); | |||
| oThisItem.info(true, &vThisItem); | |||
| compare_split_screen_popup(startx, width, TERMY-VIEW_OFFSET_Y*2, oThisItem.tname(this), vThisItem, vDummy); | |||
| cMenu = compare_split_screen_popup(startx+width, 14, 16, "", vMenu, vDummy, | |||
| cMenu = compare_split_screen_popup(startx+width, 14, 17, "", vMenu, vDummy, | |||
| selected >= menustart && selected <= menuend ? selected : -1 | |||
| ); | |||
| switch(cMenu) { | |||
| @@ -1381,6 +1382,9 @@ int game::inventory_item_menu(char chItem, int startx, int width) { | |||
| case '=': | |||
| reassign_item(chItem); | |||
| break; | |||
| case 'f': | |||
| fold(chItem); | |||
| break; | |||
| case KEY_UP: | |||
| selected--; | |||
| break; | |||
| @@ -1897,6 +1901,10 @@ bool game::handle_action() | |||
| } | |||
| break; | |||
|
|
|||
| case ACTION_FOLD: | |||
| fold(); | |||
| break; | |||
|
|
|||
| case ACTION_SAVE: | |||
| if (!u.in_vehicle) { | |||
| if (query_yn("Save and quit?")) { | |||
| @@ -8480,6 +8488,22 @@ void game::eat(char chInput) | |||
| u.eat(this, u.lookup_item(ch)); | |||
| } | |||
|
|
|||
|
|
|||
| void game::fold(char chInput) | |||
| { | |||
| char ch; | |||
| if (chInput == '.') | |||
| ch = inv_type("Fold item:", IC_ARMOR); | |||
| else | |||
| ch = chInput; | |||
|
|
|||
| if (ch == ' ') { | |||
| add_msg("Never mind."); | |||
| return; | |||
| } | |||
| u.fold(this, ch); | |||
| } | |||
|
|
|||
| void game::wear(char chInput) | |||
| { | |||
| char ch; | |||
| @@ -401,8 +401,9 @@ class game | |||
| void complete_butcher(int index); // Finish the butchering process | |||
| void forage(); // Foraging ('a' on underbrush) | |||
| void eat(char chInput = '.'); // Eat food or fuel 'E' (or 'a') | |||
| void use_item(char chInput = '.');// Use item; also tries E,R,W 'a' | |||
| void use_item(char chInput = '.');// Use item; also tries E,R,"fold" 'a' | |||
| void use_wielded_item(); | |||
| void fold(char chInput = '.'); // Fold armor no default key, but used by 'a' | |||
| void wear(char chInput = '.'); // Wear armor 'W' (or 'a') | |||
| void takeoff(char chInput = '.'); // Remove armor 'T' | |||
| void reload(); // Reload a wielded gun/tool 'r' | |||
| @@ -4,6 +4,7 @@ | |||
| #include "keypress.h" | |||
| #include "mapdata.h" | |||
| #include "item_factory.h" | |||
| #include <stdlib.h> | |||
|
|
|||
| const std::string inv_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#&()*+./:;=?@[\\]^_{|}"; | |||
|
|
|||
| @@ -1303,7 +1304,19 @@ int inventory::volume() const | |||
| stack_iter != iter->end(); | |||
| ++stack_iter) | |||
| { | |||
| ret += stack_iter->volume(); | |||
| if (stack_iter->has_flag("FOLDED")) | |||
| { | |||
| if ( volume() >= 6) | |||
| { | |||
| ret += std::max(int(0.5 + stack_iter->volume() / 1.5), 5); | |||
| } | |||
| else | |||
| { | |||
| ret += int(volume() - 1); | |||
| } | |||
| } | |||
| else | |||
| ret += stack_iter->volume(); | |||
| } | |||
| } | |||
| return ret; | |||
| @@ -9,6 +9,7 @@ | |||
| #include "text_snippets.h" | |||
| #include "material.h" | |||
| #include "item_factory.h" | |||
| #include <stdlib.h> | |||
|
|
|||
| // mfb(n) converts a flag to its appropriate position in covers's bitfield | |||
| #ifndef mfb | |||
| @@ -385,7 +386,23 @@ std::string item::info(bool showtext, std::vector<iteminfo> *dump) | |||
|
|
|||
| if( !is_null() ) | |||
| { | |||
| dump->push_back(iteminfo("BASE", " Volume: ", "", int(volume()), "", false, true)); | |||
| // Reduce volume if the clothing item has tag "FOLDED" | |||
| if (has_flag("FOLDED")) | |||
| { | |||
| // Bigger items save more space | |||
| if (volume() >=6) | |||
| { | |||
| dump->push_back(iteminfo("BASE", " Volume: ", "", std::max(int(0.5 + volume() / 1.5), 5), " (folded)", false, true)); | |||
| } | |||
| else | |||
| { | |||
| dump->push_back(iteminfo("BASE", " Volume: ", "", int(volume() - 1), " (folded)", false, true)); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| dump->push_back(iteminfo("BASE", " Volume: ", "", int(volume()), "", false, true)); | |||
| } | |||
| dump->push_back(iteminfo("BASE", " Weight: ", "", int(weight()), "", true, true)); | |||
| dump->push_back(iteminfo("BASE", " Bash: ", "", int(type->melee_dam), "", false)); | |||
| dump->push_back(iteminfo("BASE", (has_flag("SPEAR") ? " Pierce: " : " Cut: "), "", int(type->melee_cut), "", false)); | |||
| @@ -755,6 +772,10 @@ std::string item::tname(game *g) | |||
| ret << damtext << " "; | |||
| } | |||
|
|
|||
| if (has_flag("FOLDED")) { | |||
| ret << "folded "; | |||
| } | |||
|
|
|||
| if (is_var_veh_part()){ | |||
| if(type->bigness_aspect == BIGNESS_ENGINE_DISPLACEMENT){ //liters, e.g. "3.21-Liter V8 engine" | |||
| ret.precision(4); | |||
| @@ -541,12 +541,13 @@ void Item_factory::load_item_templates_from(const std::string file_name){ | |||
| { | |||
| new_item_template->item_tags = entry.get("flags").as_tags(); | |||
| /* | |||
| List of current flags | |||
| List of current flags (probably) | |||
| FIT - Reduces encumberance by one | |||
| VARSIZE - Can be made to fit via tailoring | |||
| OVERSIZE - Can always be worn no matter encumberance/mutations/bionics/etc | |||
| HOOD - Will increase warmth for head if head is cold and player is not wearing a helmet (headwear of material that is not wool or cotton) | |||
| POCKETS - Will increase warmth for hands if hands are cold and the player is wielding nothing | |||
| FOLDED - Divides volume by 1.5, or reduces by 1, depending on size | |||
| */ | |||
| } | |||
|
|
|||
| @@ -16,6 +16,7 @@ | |||
| #include "weather.h" | |||
| #include "item.h" | |||
| #include "material.h" | |||
| #include <cmath> | |||
|
|
|||
| #include "name.h" | |||
| #include "cursesdef.h" | |||
| @@ -5172,6 +5173,102 @@ void player::pick_style(game *g) // Style selection menu | |||
| style_selected = "null"; | |||
| } | |||
|
|
|||
| hint_rating player::rate_action_fold(item *it) | |||
| { | |||
| std::string fold_error = "error"; | |||
| can_fold(it, fold_error); | |||
| if (fold_error == "no error") | |||
| { | |||
| return HINT_GOOD; | |||
| } | |||
|
|
|||
| return HINT_CANT; | |||
| } | |||
|
|
|||
| bool player::fold(game *g, char let) | |||
| { | |||
| item* to_fold = NULL; | |||
| std::string fold_error = "error"; | |||
|
|
|||
| // Check to see if we are wielding what we want to fold | |||
| if (weapon.invlet == let) | |||
| { | |||
| to_fold = &weapon; | |||
| } | |||
| else | |||
| { | |||
| to_fold = &inv.item_by_letter(let); | |||
| } | |||
| if (to_fold == NULL) | |||
| { | |||
| g->add_msg("You don't have item '%c'.", let); | |||
| return false; | |||
| } | |||
| can_fold(to_fold, fold_error); | |||
| if (fold_error != "no error") | |||
| { | |||
| // BUG all names are "(null)" | |||
| g->add_msg("%s", fold_error.c_str()); | |||
| return false; | |||
| } | |||
| if (to_fold->has_flag("FOLDED")) | |||
| { | |||
| // This same code is reused in "player::wear_item()" | |||
| g->add_msg("You unroll your %s.", to_fold->tname().c_str()); | |||
| to_fold->item_tags.erase("FOLDED"); | |||
| moves -= 30; | |||
| } | |||
| else | |||
| { | |||
| g->add_msg("You tightly roll up your %s.", to_fold->tname().c_str()); | |||
| to_fold->item_tags.insert("FOLDED"); | |||
| int item_density = int(sqrt(to_fold->volume()*to_fold->weight())); | |||
| moves -= 50*item_density; | |||
| } | |||
|
|
|||
| return true; | |||
| } | |||
|
|
|||
| void player::can_fold(item *to_fold, std::string &fold_error) | |||
| { | |||
| /* Start with exceptions (currently none) | |||
| Check if item is armor (this means the player can't fold clothing that he is wearing NOR fold non-armor items) | |||
| Check materials (if it is not made of cotton OR wool OR leather OR fur, then no good) | |||
| Check a blacklist of items that pass the material check | |||
| Then check footwear | |||
| Then check a few special case items | |||
| Check to see if it is too small to be folded */ | |||
| it_armor* armor_fold = dynamic_cast<it_armor*>(to_fold->type); | |||
| fold_error = "no error"; | |||
|
|
|||
| if (!to_fold->is_armor()) | |||
| { | |||
| fold_error = "You can't roll this up."; | |||
| return; | |||
| } | |||
| if (!(to_fold->made_of("cotton") || to_fold->made_of("wool") || to_fold->made_of("leather") || to_fold->made_of("fur"))) | |||
| { | |||
| fold_error = "This cannot be rolled up."; | |||
| return; | |||
| } | |||
| else if (armor_fold->covers & mfb (bp_feet) && !(to_fold->type->id == "socks_wool" || to_fold->type->id == "socks")) | |||
| { | |||
| fold_error = "This cannot be rolled up."; | |||
| return; | |||
| } | |||
| else if (to_fold->type->id == "armguard_hard" || to_fold->type->id == "arm_splint" || to_fold->type->id == "leg_splint") | |||
| { | |||
| fold_error = "This cannot be rolled up."; | |||
| return; | |||
| } | |||
| if (to_fold->volume() <= 3 && !to_fold->has_flag("FOLDED")) | |||
| { | |||
| fold_error = "Rolling this up won't do much."; | |||
| return; | |||
| } | |||
| return; | |||
| } | |||
|
|
|||
| hint_rating player::rate_action_wear(item *it) | |||
| { | |||
| //TODO flag already-worn items as HINT_IFFY | |||
| @@ -5315,9 +5412,18 @@ bool player::wear_item(game *g, item *to_wear) | |||
| g->add_msg("You can't wear %s with power armor!", to_wear->tname().c_str()); | |||
| return false; | |||
| } | |||
| } | |||
| } | |||
|
|
|||
| // Unfold clothing if it is folded | |||
| if (to_wear->has_flag("FOLDED")) | |||
| { | |||
| g->add_msg("You unfold your %s.", to_wear->tname().c_str()); | |||
| to_wear->item_tags.erase("FOLDED"); | |||
| moves -= 30; | |||
| } | |||
|
|
|||
|
|
|||
| if (!to_wear->has_flag("OVERSIZE")) { | |||
| if (!to_wear->has_flag("OVERSIZE")) { | |||
| // Make sure we're not wearing 2 of the item already | |||
| int count = 0; | |||
| for (int i = 0; i < worn.size(); i++) { | |||
| @@ -6174,7 +6280,7 @@ press 'U' while wielding the unloaded gun.", gun->tname(g).c_str()); | |||
| } else if (used->is_armor()) { | |||
| if (replace_item) | |||
| inv.add_item(copy); | |||
| wear(g, let); | |||
| fold(g, let); | |||
| return; | |||
| } else | |||
| g->add_msg("You can't do anything interesting with your %s.", | |||
| @@ -201,6 +201,8 @@ class player { | |||
| bool eat(game *g, char invlet); // Eat item; returns false on fail | |||
| virtual bool wield(game *g, char invlet);// Wield item; returns false on fail | |||
| void pick_style(game *g); // Pick a style | |||
| bool fold(game *g, char let); // Fold item; returns false on fail | |||
| void can_fold(item *to_fold, std::string &fold_error); // Fold check; returns error string | |||
| bool wear(game *g, char let); // Wear item; returns false on fail | |||
| bool wear_item(game *g, item *to_wear); | |||
| bool takeoff(game *g, char let);// Take off item; returns false on fail | |||
| @@ -222,6 +224,7 @@ class player { | |||
| hint_rating rate_action_reload(item *it); | |||
| hint_rating rate_action_unload(item *it); | |||
| hint_rating rate_action_disassemble(item *it, game *g); | |||
| hint_rating rate_action_fold(item *it); | |||
|
|
|||
| int warmth(body_part bp); // Warmth provided by armor &c | |||
| int encumb(body_part bp); // Encumberance from armor &c | |||