mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2026-01-01 18:09:04 +00:00
implemented three more health powers
This commit is contained in:
@@ -28,7 +28,7 @@ struct randeff {
|
||||
void hs(struct stater& s);
|
||||
};
|
||||
|
||||
enum class mod { burning, freezing, disarming };
|
||||
enum class mod { burning, freezing, disarming, vampire };
|
||||
|
||||
struct power {
|
||||
int key;
|
||||
@@ -379,6 +379,8 @@ struct man : public entity {
|
||||
entity *morphed = nullptr;
|
||||
vector<effect> effects;
|
||||
|
||||
int vampire, protection, healbubble;
|
||||
|
||||
int last_action;
|
||||
|
||||
int experience;
|
||||
@@ -420,6 +422,8 @@ struct man : public entity {
|
||||
addMessage("OUCH! These spikes hurt!");
|
||||
}
|
||||
|
||||
bool reduce_hp(int x) override;
|
||||
|
||||
void launch_attack(power *p, int fac, boxfun f);
|
||||
|
||||
virtual void hs(stater& s);
|
||||
@@ -688,6 +692,17 @@ struct kestrel : public enemy {
|
||||
xy default_vel() override { return respawn_vel; }
|
||||
};
|
||||
|
||||
struct healthbubble : public entity {
|
||||
ld power;
|
||||
xy siz() override { return {10, 10}; }
|
||||
string glyph() override { return "o"; }
|
||||
color_t color() override { return 0xA04040FF; }
|
||||
void act() override;
|
||||
string get_name() override { return "health bubble"; }
|
||||
string get_help() override { return "Can be catched to replenish your health."; }
|
||||
virtual void hs(stater& s) override { entity::hs(s); s.act("power", power, 0); }
|
||||
};
|
||||
|
||||
struct gridbug : public enemy {
|
||||
int next_move;
|
||||
xy siz() override { return {10, 10}; }
|
||||
|
||||
@@ -691,6 +691,19 @@ void kestrel::act() {
|
||||
}
|
||||
}
|
||||
|
||||
void healthbubble::act() {
|
||||
stay_on_screen();
|
||||
apply_walls_reflect();
|
||||
apply_vel();
|
||||
|
||||
if(intersect(get_pixel_bbox(), m.get_pixel_bbox()) && gframeid >= invinc_end) {
|
||||
addMessage("The " + hal()->get_name() + " heals you!");
|
||||
m.hp += power;
|
||||
existing = false;
|
||||
if(m.hp > m.max_hp()) m.hp = m.max_hp();
|
||||
}
|
||||
}
|
||||
|
||||
void gridbug::act() {
|
||||
|
||||
if(intersect(get_pixel_bbox(), m.get_pixel_bbox())) {
|
||||
|
||||
@@ -189,6 +189,8 @@ extern shiftmatrix scrm;
|
||||
|
||||
struct hr_name_error : hr_exception { hr_name_error(const char *s) : hr_exception(s) {} };
|
||||
|
||||
extern vector<unique_ptr<struct entity>> new_entities;
|
||||
|
||||
string unspace(const string& s);
|
||||
string respace(const string& s);
|
||||
|
||||
|
||||
@@ -86,6 +86,9 @@ void man::hs(stater& s) {
|
||||
sdata(next, "next.");
|
||||
|
||||
entity::hs(s);
|
||||
s.act("protection", protection, 0);
|
||||
s.act("vampire", vampire, 0);
|
||||
s.act("healbubble", healbubble, 0);
|
||||
}
|
||||
|
||||
void man::act() {
|
||||
@@ -131,6 +134,32 @@ void man::act() {
|
||||
check_fountains();
|
||||
}
|
||||
|
||||
bool man::reduce_hp(int x) {
|
||||
if(protection && gframeid >= invinc_end) {
|
||||
ld fraction = 1 - 100 / (protection + 100);
|
||||
int take = ceil(x * fraction);
|
||||
if(take > protection) take = protection;
|
||||
protection -= take;
|
||||
x -= protection;
|
||||
}
|
||||
if(healbubble && gframeid >= invinc_end) {
|
||||
int take = x;
|
||||
if(take > healbubble) take = healbubble;
|
||||
healbubble -= take;
|
||||
auto d = m.get_dat();
|
||||
auto mi = std::make_unique<healthbubble>();
|
||||
mi->id = "HEALBUBBLE";
|
||||
ld r = (rand() % 360) * degree;
|
||||
mi->hs(fountain_resetter);
|
||||
mi->power = take * 2;
|
||||
mi->where = m.where;
|
||||
mi->vel = { cos(r) * d.modv * 3, sin(r) * d.modv * 3 };
|
||||
mi->invinc_end = gframeid + 300;
|
||||
new_entities.emplace_back(std::move(mi));
|
||||
}
|
||||
return entity::reduce_hp(x);
|
||||
}
|
||||
|
||||
bool man::can_see(entity& e) {
|
||||
if(m.current.detect_area) {
|
||||
ld d = hdist(to_hyper(m.where), to_hyper(e.where));
|
||||
@@ -179,11 +208,16 @@ void man::launch_attack(power *p, int fac, boxfun f) {
|
||||
for(auto& e: current_room->entities)
|
||||
if(e->existing && intersect(e->get_pixel_bbox(), pb)) {
|
||||
int sav = e->invinc_end;
|
||||
e->attacked((m.current.stats[stat::str] + 1) * 3 / 2);
|
||||
for(auto& [m, qty]: p->mods) {
|
||||
if(m == mod::burning) { e->invinc_end = sav; e->attacked(qty); }
|
||||
if(m == mod::freezing) { e->invinc_end = sav; e->attacked(qty); }
|
||||
if(m == mod::disarming && e->hidden()) {
|
||||
int dam = (m.current.stats[stat::str] + 1) * 3 / 2;
|
||||
e->attacked(dam);
|
||||
for(auto& [md, qty]: p->mods) {
|
||||
if(md == mod::burning) { e->invinc_end = sav; e->attacked(qty); }
|
||||
if(md == mod::freezing) { e->invinc_end = sav; e->attacked(qty); }
|
||||
if(md == mod::vampire) {
|
||||
int dam1 = min(dam, m.vampire);
|
||||
hp += dam1; m.vampire -= dam1;
|
||||
}
|
||||
if(md == mod::disarming && e->hidden()) {
|
||||
e->existing = false;
|
||||
addMessage("You have disarmed a "+e->hal()->get_name()+".");
|
||||
}
|
||||
|
||||
@@ -32,12 +32,14 @@ power& power::be_weapon() {
|
||||
if(m == mod::burning) s = "flaming " + s;
|
||||
if(m == mod::freezing) s = "freezing " + s;
|
||||
if(m == mod::disarming) s = "disarming " + s;
|
||||
if(m == mod::vampire) s = "vampiric " + s;
|
||||
}
|
||||
return s;
|
||||
};
|
||||
auto gc = get_color; get_color = [gc, this] {
|
||||
auto col = gc();
|
||||
for(auto& [m, qty]: mods) {
|
||||
if(m == mod::vampire) col = 0x802020FF;
|
||||
if(m == mod::disarming) col = 0x4040C0FF;
|
||||
if(m == mod::burning) col = gradient(0xFFFF00FF, 0xFF0000FF, -1, sin(ticks/100), 1);
|
||||
if(m == mod::freezing) col = 0x8080FFFF;
|
||||
|
||||
@@ -103,13 +103,17 @@ randeff health_regen("Regeneration", "Heals you over a period of time.", "You fe
|
||||
}
|
||||
});
|
||||
randeff health_protect("Protection", "Makes you more resistant to damage.", "You feel protected!", [] (data &d) {
|
||||
// m.protection += 3 * m.current.stats[stat::wis] + m.hp * m.current.stats[stat::wis] * 2 / 100;
|
||||
m.protection += 3 * m.current.stats[stat::wis] + m.hp * m.current.stats[stat::wis] * 2 / 100;
|
||||
});
|
||||
randeff health_vampire("Vampirism", "Attacks with your [weapon] restore your health.", "Your [weapon] wants blood!", [] (data &d) {
|
||||
// m.vampire += 4 * m.current.stats[stat::wis] + m.max_hp() * m.current.stats[stat::wis] * 3 / 100;
|
||||
if(d.mode == rev::start)
|
||||
m.vampire += 4 * m.current.stats[stat::wis] + m.max_hp() * m.current.stats[stat::wis] * 3 / 100;
|
||||
if(d.mode == rev::active && m.vampire)
|
||||
m.next.mods.emplace_back(d.re->which_weapon, mod::vampire, 2 * m.current.stats[stat::wis] + 1e-6);
|
||||
});
|
||||
randeff health_bubbles("Bubbles", "When you are attacked, you produce red bubbles that you can collect to heal yourself back.", "You feel something bouncy growing inside you!", [] (data &d) {
|
||||
// m.healbubbles += 4 * m.current.stats[stat::wis] + m.max_hp() * m.current.stats[stat::wis] * 3 / 100;
|
||||
if(d.mode == rev::start)
|
||||
m.healbubble += 4 * m.current.stats[stat::wis] + m.max_hp() * m.current.stats[stat::wis] * 3 / 100;
|
||||
});
|
||||
|
||||
// fire powers
|
||||
@@ -181,7 +185,7 @@ void assign_potion_powers() {
|
||||
fire_weapon.which_weapon = wpn[0];
|
||||
trap_disarm.which_weapon = wpn[1];
|
||||
using relist = vector<randeff*>;
|
||||
find_power("health").randeffs = relist{ pick(&health_heal, &health_regen, &health_protect), random_powers[0] };
|
||||
find_power("health").randeffs = relist{ pick(&health_heal, &health_regen, &health_protect, &health_vampire, &health_bubbles, &health_protect), random_powers[0] };
|
||||
find_power("the thief").randeffs = relist{ pick(&trap_detect, &trap_snake, &trap_disarm, &trap_detect_cross), random_powers[1] };
|
||||
find_power("polymorph").randeffs = relist{ pick(&morph_cat, &morph_capy), random_powers[2] };
|
||||
find_power("reach").randeffs = relist{ pick(&jump_double, &jump_high, &jump_bubble, &jump_light), random_powers[3] };
|
||||
|
||||
@@ -145,6 +145,8 @@ tuple<xy, ld, int> get_next_room(xy w, room *r, int which) {
|
||||
return {w, 1, -1};
|
||||
}
|
||||
|
||||
vector<unique_ptr<struct entity>> new_entities;
|
||||
|
||||
void playing_frame() {
|
||||
m.act();
|
||||
|
||||
@@ -156,6 +158,9 @@ void playing_frame() {
|
||||
for(auto& e: ents) if(!e->destroyed) *(mb++) = std::move(e);
|
||||
ents.resize(mb - ents.begin());
|
||||
|
||||
for(auto &e: new_entities) ents.push_back(std::move(e));
|
||||
new_entities.clear();
|
||||
|
||||
if(one_room) return;
|
||||
|
||||
auto [w1, vmul, cr] = get_next_room(m.where, current_room);
|
||||
@@ -283,7 +288,12 @@ void run() {
|
||||
if(cmode == mode::playing) {
|
||||
titlecolor = 0xFFFFFF;
|
||||
mouseovers = current_room->roomname;
|
||||
displayfr(vid.fsize, vid.fsize, 2, vid.fsize, "HP " + its(m.hp) + "/" + its(m.max_hp()), titlecolor, 0);
|
||||
shstream ss;
|
||||
print(ss, "HP ", m.hp, "/", m.max_hp());
|
||||
if(m.vampire) print(ss, " V");
|
||||
if(m.healbubble) print(ss, " B");
|
||||
if(m.protection) print(ss, " P");
|
||||
displayfr(vid.fsize, vid.fsize, 2, vid.fsize, ss.s, titlecolor, 0);
|
||||
if(current_target && current_target->existing)
|
||||
displayfr(vid.xres - vid.fsize, vid.fsize, 2, vid.fsize, "HP " + its(current_target->hp) + "/" + its(current_target->max_hp()) + " " + current_target->get_name(), titlecolor, 16);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user