diff --git a/rogueviz/ru/classes.cpp b/rogueviz/ru/classes.cpp index 4087c7f3..2a281ef7 100644 --- a/rogueviz/ru/classes.cpp +++ b/rogueviz/ru/classes.cpp @@ -188,6 +188,7 @@ struct entity { virtual struct moving_platform* as_platform() { return nullptr; } virtual struct shopitem* as_shopitem() { return nullptr; } virtual struct trader* as_trader() { return nullptr; } + virtual struct missile* as_missile() { return nullptr; } int hp; int invinc_end; @@ -276,6 +277,8 @@ struct entity { } virtual string get_help() { return "No help about this."; } + + virtual bool hit_by_missile(missile *m) { return false; } }; struct statdata { @@ -316,6 +319,8 @@ struct man : public entity { void on_kill() override; + bool hit_by_missile(missile *m) override { return true; } + virtual void spiked() { entity::spiked(); addMessage("OUCH! These spikes hurt!"); @@ -418,6 +423,7 @@ struct enemy : public entity { void attacked(int s) override; void regenerate() override { where = respawn; vel = xy(0, 0); existing = true; hp = max_hp(); } virtual int base_xp() { return 0; } + bool hit_by_missile(missile *m) override { return true; } }; struct vtrap : public entity { @@ -607,22 +613,27 @@ struct loot : public item { }; struct missile : public entity { + int power; missile() { destroyed = false; } - xy siz() override { return {4, 4}; } + xy siz() override { auto p = 2 + sqrt(power); return {p, p}; } string glyph() override { return "*"; } + set hit_list; void act() override; void hit_wall() override { destroyed = true; } + struct missile* as_missile() override { return this; } }; struct ice_missile : public missile { color_t color() override { return 0x8080FFFF; } bool freezing() override { return true; } + bool hit_by_missile(missile *m) override { return m->burning(); } }; struct fire_missile : public missile { int index; color_t color() override { return gradient(0xFFFF00FF, 0xFF0000FF, -1, sin(index+ticks/100), 1); } bool burning() override { return true; } + bool hit_by_missile(missile *m) override { return m->freezing(); } }; } diff --git a/rogueviz/ru/entity.cpp b/rogueviz/ru/entity.cpp index 7ac34b12..a07ff08d 100644 --- a/rogueviz/ru/entity.cpp +++ b/rogueviz/ru/entity.cpp @@ -266,6 +266,13 @@ void entity::kino() { void missile::act() { kino(); if(where.x > screen_x || where.x < 0 || where.y < 0 || where.y > screen_y) destroyed = true; + for(auto& e: current_room->entities) if(e->hit_by_missile(this) && intersect(get_pixel_bbox(), e->get_pixel_bbox()) && !hit_list.count(&*e)) { + if(burning() && e->as_missile() && e->freezing()) { destroyed = true; e->destroyed = true; } + if(freezing() && e->as_missile() && e->burning()) { destroyed = true; e->destroyed = true; } + hit_list.insert(&*e); + e->invinc_end = 0; + e->attacked(power); + } } void npc_or_trader::act() { diff --git a/rogueviz/ru/randeff.cpp b/rogueviz/ru/randeff.cpp index db59c484..267b904d 100644 --- a/rogueviz/ru/randeff.cpp +++ b/rogueviz/ru/randeff.cpp @@ -78,7 +78,7 @@ randeff fire_spit("Fiery Spit", "Lets you spit fire.", "You feel fire in your mo mi->where = m.where + xy(m.facing * m.get_scale() * m.siz().y * 0.45, 0); mi->vel = m.vel + xy(m.facing * d.modv * i, d.modv * (10-i) / 5.); mi->clearg(); - mi->index = i; + mi->index = i; mi->power = m.current.stats[stat::wis] * 2 / 5 + 1e-6; current_room->entities.emplace_back(std::move(mi)); } });