1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-07-20 18:02:50 +00:00

ru:: shops

This commit is contained in:
Zeno Rogue 2025-05-11 01:37:14 +02:00
parent 30e0adef50
commit 5bd984e508
5 changed files with 155 additions and 9 deletions

View File

@ -166,6 +166,8 @@ struct entity {
xy zero_vel; /* relative to the platform */
virtual struct moving_platform* as_platform() { return nullptr; }
virtual struct shopitem* as_shopitem() { return nullptr; }
virtual struct trader* as_trader() { return nullptr; }
int hp;
int invinc_end;
@ -313,19 +315,33 @@ struct pendulum_platform : public moving_platform {
string get_help() override { return "These pendulum platforms go back and forth between two locations, taking the shortest path possible."; }
};
struct npc : public entity {
string sglyph, name;
color_t col;
struct npc_or_trader : public entity {
string text;
string name;
int talk_on;
xy siz() override { return {12, 12}; }
void act() override;
string get_name() override { return name; }
};
struct npc : public npc_or_trader {
string sglyph;
color_t col;
xy siz() override { return {12, 12}; }
string glyph() override { return sglyph; }
color_t color() override { return col; }
void act() override;
string get_name() override { return name; }
string get_help() override { return "Stay awhile and listen."; }
};
struct trader : public npc_or_trader {
xy siz() override { return {18, 18}; }
string glyph() override { return "@"; }
color_t color() override { return 0x2020D0FF; }
void act() override;
string get_help() override { return "Stay awhile and listen. Or use gold to pay."; }
virtual struct trader* as_trader() { return this; }
};
struct enemy : public entity {
xy respawn;
int num_kills;
@ -452,6 +468,26 @@ struct item : public entity {
string get_help() override { return powers[id].get_desc(); }
};
struct shopitem : public item {
int qty1;
int price;
bool bought;
string glyph() override;
color_t color() override;
bool last_intersect;
void act() override {
kino();
bool next_intersect = intersect(get_pixel_bbox(), m.get_pixel_bbox());
if(next_intersect && !last_intersect) {
addMessage("This costs " + its(price) + " gold.");
}
last_intersect = next_intersect;
}
string get_name() override { if(bought) return its(price) + " gold"; return item::get_name(); }
string get_help() override { if(bought) return "You have bought something from this shop. The trader has stored the gold here."; return item::get_help() + "\n\nPrice: " + its(price); }
shopitem* as_shopitem() override { return this; }
};
struct missile : public entity {
missile() { destroyed = false; }
xy siz() override { return {4, 4}; }

View File

@ -247,14 +247,14 @@ void missile::act() {
if(where.x > screen_x || where.x < 0 || where.y < 0 || where.y > screen_y) destroyed = true;
}
void npc::act() {
void npc_or_trader::act() {
kino();
if(gframeid > m.last_action + 300 && intersect(extend_all(get_pixel_bbox(), get_scale()*12), m.get_pixel_bbox()) && talk_on != m.last_action) {
talk_on = m.last_action = gframeid;
cmode = mode::menu;
pushScreen([&] { cmode = mode::playing; popScreen(); });
pushScreen([&] {
dialog::init(name, col >> 8);
dialog::init(name, color() >> 8);
dialog::addHelp(text);
dialog::addBreak(100);
dialog::addBack();
@ -263,6 +263,27 @@ void npc::act() {
}
}
extern int gold_id;
string shopitem::glyph() { if(bought) return powers[gold_id].get_glyph(); else return item::glyph(); }
color_t shopitem::color() { if(bought) return powers[gold_id].get_color(); else return item::color(); }
void trader::act() {
bool any_purchases = false;
for(auto& e: current_room->entities) if(auto si = e->as_shopitem()) if(!si->existing) any_purchases = true;
if(any_purchases) {
walls[wShopDoor].glyph = '+';
walls[wShopDoor].flags = W_BLOCK | W_BLOCKBIRD;
}
else {
walls[wShopDoor].glyph = '\'';
walls[wShopDoor].flags = W_TRANS;
}
if(any_purchases) talk_on = m.last_action;
npc_or_trader::act();
}
void boar::act() {
stay_on_screen();
kino();

View File

@ -1182,6 +1182,15 @@ Why is there always gold lying in these mazes...
ITEM 308 261
toughness
You find a beautiful ring.
SHOPITEM 421 238 50 1 0
toughness
You find a beautiful ring in this store.
SHOPITEM 420 200 50 1 0
wisdom
You find another beautiful ring in this store.
TRADER 458 247
John the trader
Hello here! Please buy something from my shop!
OK
MOVE 2 Mazes of Menace

View File

@ -146,6 +146,12 @@ power& gen_power(int key, string name, string desc, string glyph, color_t color,
power *extra_life;
int gold_id;
void power_death_revert(power& p) {
int q0 = p.qty_filled;
int q1 = p.qty_owned;
add_revert(death_revert, [&p, q0, q1] { p.qty_filled = q0; p.qty_owned = q1; });
}
void gen_powers() {
powers.reserve(100);
@ -405,13 +411,69 @@ void gen_powers() {
gold_id = isize(powers);
gen_power('g', "gold",
gen_power('t', "gold",
"For some weird reason, people love gold, and they will give you anything if you give them enough gold.\n\n"
"This can be used to buy things in shops. "
"Just stand on the item, press the hotkey, go to the shopkeeper, and press the hotkey again.\n\n"
"If you decide not to buy, press the hotkey without going to the shopkeeper.",
"$", 0xFFD500FF,
[] (data& d) {}
[] (data& d) {
if(d.keystate == 1) {
trader *tr;
for(auto& e: current_room->entities) if(auto t = e->as_trader()) tr = t;
bool on_trader = intersect(tr->get_pixel_bbox(), m.get_pixel_bbox());
bool done_something = false;
for(int it: {0, 1})
for(auto& e: current_room->entities) if(auto si = e->as_shopitem()) {
bool on = intersect(si->get_pixel_bbox(), m.get_pixel_bbox());
if(it == 0 && on && si->existing && !si->bought) {
done_something = true;
addMessage(si->pickup_message);
power_death_revert(powers[si->id]);
powers[si->id].qty_owned += si->qty; powers[si->id].qty_filled += si->qty1;
add_revert(death_revert, [si] { si->existing = true; });
si->existing = false;
}
else if(it == 0 && on && si->existing && si->bought) {
done_something = true;
addMessage("You get some gold.");
power_death_revert(powers[gold_id]);
powers[gold_id].qty_owned += si->price; powers[gold_id].qty_filled += si->price;
add_revert(death_revert, [si] { si->existing = true; });
si->existing = false;
}
else if((it ? !done_something : on) && !si->existing && !si->bought) {
done_something = true;
addMessage("You rethink your purchase.");
power_death_revert(powers[si->id]);
powers[si->id].qty_owned -= si->qty; powers[si->id].qty_filled -= si->qty1;
add_revert(death_revert, [si] { si->existing = false; });
si->existing = true;
}
else if((it ? !done_something : on) && !si->existing && si->bought) {
done_something = true;
addMessage("You rethink your actions.");
power_death_revert(powers[gold_id]);
powers[gold_id].qty_owned -= si->price; powers[gold_id].qty_filled -= si->price;
add_revert(death_revert, [si] { si->existing = false; });
si->existing = true;
}
else if(it == 0 && on_trader && !si->existing && d.p->qty_owned >= si->price) {
done_something = true;
addMessage("You buy the " + powers[si->id].get_name() + ".");
power_death_revert(powers[gold_id]);
powers[gold_id].qty_owned -= si->price; powers[gold_id].qty_filled -= si->price;
si->existing = true; si->bought = true;
add_revert(death_revert, [si] { si->existing = false; si->bought = false; });
}
else if(it == 0 && on_trader && !si->existing && !si->bought) {
done_something = true;
addMessage("You have not enough gold to buy the " + powers[si->id].get_name() + ".");
}
}
if(!done_something) addMessage("You count your gold. You have " + its(d.p->qty_owned) + " gold.");
}
}
).be_resource("pieces of gold");
};

View File

@ -120,6 +120,17 @@ void load_room(fhstream& f, cell *c) {
b->pickup_message = scanline_noblank(f);
r.entities.emplace_back(std::move(b));
}
else if(cap == "SHOPITEM") {
auto b = std::make_unique<shopitem>();
b->qty = 1; b->qty1 = 0;
sscanf(param.c_str(), "%lf%lf%d%d%d", &b->where.x, &b->where.y, &b->price, &b->qty, &b->qty1);
s = scanline_noblank(f);
b->id = -1;
for(int i=0; i<isize(powers); i++) if(powers[i].name == s) b->id = i;
if(b->id == -1) println(hlog, "error: unknown item name ", s), b->id = 0;
b->pickup_message = scanline_noblank(f);
r.entities.emplace_back(std::move(b));
}
else if(cap == "NPC") {
auto b = std::make_unique<npc>();
sscanf(param.c_str(), "%lf%lf%08x", &b->where.x, &b->where.y, &b->col);
@ -129,6 +140,13 @@ void load_room(fhstream& f, cell *c) {
b->text = scanline_noblank(f);
r.entities.emplace_back(std::move(b));
}
else if(cap == "TRADER") {
auto b = std::make_unique<trader>();
sscanf(param.c_str(), "%lf%lf", &b->where.x, &b->where.y);
b->name = scanline_noblank(f);
b->text = scanline_noblank(f);
r.entities.emplace_back(std::move(b));
}
else if(cap == "BOAR") {
auto b = std::make_unique<boar>();
sscanf(param.c_str(), "%lf%lf", &b->where.x, &b->where.y);