void npc::init_selling(std::vector<int> &indices, std::vector<int> &prices) { int val, price; for (int i = 0; i < inv.size(); i++) { val = value(inv[i]) - (inv[i].price() / 50); if (val <= NPC_LOW_VALUE || mission == NPC_MISSION_SHOPKEEP) { indices.push_back(i); price = inv[i].price() / (price_adjustment(sklevel[sk_barter])); prices.push_back(price); } } }
void npc::init_buying(std::vector<item> you, std::vector<int> &indices, std::vector<int> &prices) { int val, price; for (int i = 0; i < you.size(); i++) { val = value(you[i]); if (val >= NPC_HI_VALUE) { indices.push_back(i); price = you[i].price(); if (val >= NPC_VERY_HI_VALUE) price *= 2; price *= price_adjustment(sklevel[sk_barter]); prices.push_back(price); } } }
void npc::init_selling(std::vector<int> &indices, std::vector<int> &prices) { int val, price; bool found_lighter = false; for (int i = 0; i < inv.size(); i++) { if (inv[i].type->id == itm_lighter && !found_lighter) found_lighter = true; else { val = value(inv[i]) - (inv[i].price() / 50); if (val <= NPC_LOW_VALUE || mission == NPC_MISSION_SHOPKEEP) { indices.push_back(i); price = inv[i].price() / (price_adjustment(sklevel[sk_barter])); prices.push_back(price); } } } }
bool trade(game *g, npc *p, int cost, std::string deal) { WINDOW* w_head = newwin( 4, 80, 0, 0); WINDOW* w_them = newwin(21, 40, 4, 0); WINDOW* w_you = newwin(21, 40, 4, 40); WINDOW* w_tmp; mvwprintz(w_head, 0, 0, c_white, _("\ Trading with %s\n\ Tab key to switch lists, letters to pick items, Enter to finalize, Esc to quit\n\ ? to get information on an item"), p->name.c_str()); // Set up line drawings for (int i = 0; i < 80; i++) mvwputch(w_head, 3, i, c_white, LINE_OXOX); wrefresh(w_head); // End of line drawings // Populate the list of what the NPC is willing to buy, and the prices they pay // Note that the NPC's barter skill is factored into these prices. std::vector<int> theirs, their_price, yours, your_price; p->init_selling(theirs, their_price); p->init_buying(g->u.inv, yours, your_price); bool getting_theirs[theirs.size()], getting_yours[yours.size()]; // Adjust the prices based on your barter skill. for (int i = 0; i < their_price.size(); i++) { their_price[i] *= (price_adjustment(g->u.sklevel[sk_barter]) + (p->int_cur - g->u.int_cur) / 15); getting_theirs[i] = false; } for (int i = 0; i < your_price.size(); i++) { your_price[i] /= (price_adjustment(g->u.sklevel[sk_barter]) + (p->int_cur - g->u.int_cur) / 15); getting_yours[i] = false; } int cash = cost;// How much cash you get in the deal (negative = losing money) bool focus_them = true; // Is the focus on them? bool update = true; // Re-draw the screen? int them_off = 0, you_off = 0; // Offset from the start of the list char ch, help; do { if (update) { // Time to re-draw update = false; // Draw borders, one of which is highlighted werase(w_them); werase(w_you); for (int i = 1; i < 80; i++) mvwputch(w_head, 3, i, c_white, LINE_OXOX); mvwprintz(w_head, 3, 30, ((cash < 0 && g->u.cash >= cash * -1) || (cash >= 0 && p->cash >= cash) ? c_green : c_red), "%s $%d", (cash >= 0 ? _("Profit") : _("Cost")), abs(cash)); if (deal != "") mvwprintz(w_head, 3, 45, (cost < 0 ? c_ltred : c_ltgreen), deal.c_str()); if (focus_them) wattron(w_them, c_yellow); else wattron(w_you, c_yellow); wborder(w_them, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX, LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX ); wborder(w_you, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX, LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX ); wattroff(w_them, c_yellow); wattroff(w_you, c_yellow); mvwprintz(w_them, 0, 1, (cash < 0 || p->cash >= cash ? c_green : c_red), "%s: $%d", p->name.c_str(), p->cash); mvwprintz(w_you, 0, 2, (cash > 0 || g->u.cash>=cash*-1 ? c_green:c_red), "You: $%d", g->u.cash); // Draw their list of items, starting from them_off for (int i = them_off; i < theirs.size() && i < 17; i++) mvwprintz(w_them, i - them_off + 1, 1, (getting_theirs[i] ? c_white : c_ltgray), "%c %c %s - $%d", char(i + 'a'), (getting_theirs[i] ? '+' : '-'), p->inv[theirs[i + them_off]].tname().substr( 0,25).c_str(), their_price[i + them_off]); if (them_off > 0) mvwprintw(w_them, 19, 1, _("< Back")); if (them_off + 17 < theirs.size()) mvwprintw(w_them, 19, 9, _("More >")); // Draw your list of items, starting from you_off for (int i = you_off; i < yours.size() && i < 17; i++) mvwprintz(w_you, i - you_off + 1, 1, (getting_yours[i] ? c_white : c_ltgray), "%c %c %s - $%d", char(i + 'a'), (getting_yours[i] ? '+' : '-'), g->u.inv[yours[i + you_off]].tname().substr( 0,25).c_str(), your_price[i + you_off]); if (you_off > 0) mvwprintw(w_you, 19, 1, _("< Back")); if (you_off + 17 < yours.size()) mvwprintw(w_you, 19, 9, _("More >")); wrefresh(w_head); wrefresh(w_them); wrefresh(w_you); } // Done updating the screen ch = getch(); switch (ch) { case '\t': focus_them = !focus_them; update = true; break; case '<': if (focus_them) { if (them_off > 0) { them_off -= 17; update = true; } } else { if (you_off > 0) { you_off -= 17; update = true; } } break; case '>': if (focus_them) { if (them_off + 17 < theirs.size()) { them_off += 17; update = true; } } else { if (you_off + 17 < yours.size()) { you_off += 17; update = true; } } break; case '?': update = true; w_tmp = newwin(3, 21, 1, 30); mvwprintz(w_tmp, 1, 1, c_red, _("Examine which item?")); wborder(w_tmp, LINE_XOXO, LINE_XOXO, LINE_OXOX, LINE_OXOX, LINE_OXXO, LINE_OOXX, LINE_XXOO, LINE_XOOX ); wrefresh(w_tmp); help = getch(); help -= 'a'; werase(w_tmp); delwin(w_tmp); wrefresh(w_head); if (focus_them) { if (help >= 0 && help < theirs.size()) popup(p->inv[theirs[help]].info().c_str()); } else { if (help >= 0 && help < yours.size()) popup(g->u.inv[theirs[help]].info().c_str()); } break; case '\n': // Check if we have enough cash... if (cash < 0 && g->u.cash < cash * -1) { popup(_("Not enough cash! You have $%d, price is $%d."), g->u.cash, cash); update = true; ch = ' '; } else if (cash > 0 && p->cash < cash) p->op_of_u.owed += cash; break; default: // Letters & such if (ch >= 'a' && ch <= 'z') { ch -= 'a'; if (focus_them) { if (ch < theirs.size()) { getting_theirs[ch] = !getting_theirs[ch]; if (getting_theirs[ch]) cash -= their_price[ch]; else cash += their_price[ch]; update = true; } } else { // Focus is on the player's inventory if (ch < yours.size()) { getting_yours[ch] = !getting_yours[ch]; if (getting_yours[ch]) cash += your_price[ch]; else cash -= your_price[ch]; update = true; } } ch = 0; } } } while (ch != KEY_ESCAPE && ch != '\n'); if (ch == '\n') { inventory newinv; int practice = 0; std::vector<char> removing; for (int i = 0; i < yours.size(); i++) { if (getting_yours[i]) { newinv.push_back(g->u.inv[yours[i]]); practice++; removing.push_back(g->u.inv[yours[i]].invlet); } } // Do it in two passes, so removing items doesn't corrupt yours[] for (int i = 0; i < removing.size(); i++) g->u.i_rem(removing[i]); for (int i = 0; i < theirs.size(); i++) { item tmp = p->inv[theirs[i]]; if (getting_theirs[i]) { practice += 2; tmp.invlet = 'a'; while (g->u.has_item(tmp.invlet)) { if (tmp.invlet == 'z') tmp.invlet = 'A'; else if (tmp.invlet == 'Z') return false; // TODO: Do something else with these. else tmp.invlet++; } g->u.inv.push_back(tmp); } else newinv.push_back(tmp); } g->u.practice(sk_barter, practice / 2); p->inv = newinv; g->u.cash += cash; p->cash -= cash; } werase(w_head); werase(w_you); werase(w_them); wrefresh(w_head); wrefresh(w_you); wrefresh(w_them); delwin(w_head); delwin(w_you); delwin(w_them); if (ch == '\n') return true; return false; }