rogueviz:: ru:: extra reach powers implemented

This commit is contained in:
Zeno Rogue
2026-09-17 09:33:53 +02:00
parent 138bb0452e
commit 296a7c6ba7
6 changed files with 190 additions and 7 deletions
+39
View File
@@ -317,6 +317,7 @@ struct entity {
bool on_floor, fallthru, wallhug, on_bounce, is_stable;
int on_ice;
moving_platform *on_floor_platform;
bool destroyed;
void kino();
@@ -402,6 +403,8 @@ struct statdata {
int jump_control, coyote_time, hallucinating;
ld detect_area, detect_cross, rough_detect;
int heavy_armor, spikes, max_mageshield, stealth_bonus, dodge_value;
ld jump_power, gravity_value;
int extra_jumps, boost_max;
void reset();
vector<weaponmod> mods;
vector<hr::function<void(int&)>> on_hit;
@@ -423,6 +426,7 @@ struct man : public entity {
int facing;
int on_floor_when;
int dresstime;
int jumps_used, boost_left;
entity *morphed = nullptr;
vector<effect> effects;
power *use_next_turn;
@@ -478,6 +482,7 @@ struct man : public entity {
void launch_attack(power *p, int fac, boxfun f);
virtual void hs(stater& s);
virtual double grav() { return entity::grav() / current.gravity_value; }
};
extern man m;
@@ -500,6 +505,40 @@ struct moving_platform : public entity {
string get_name() override { return get_shape_name() + " platform"; }
string get_help() override { return "Moving platforms move."; }
bool nonstatic() override { return false; }
virtual void jumped_on() {}
};
struct freemoving_platform : public moving_platform {
xy last_position;
int position_time;
xy location_at(ld t) override;
virtual void hs(stater& s) {
moving_platform::hs(s);
s.act("last_position", last_position, xy(0,0))
.act("position_time", position_time, 0);
}
};
struct floating_bubble_platform : public freemoving_platform {
virtual int width() { return 1; }
xy siz() override { return {6.*width(), 6}; }
void act() override;
string glyph() override { return "O"; }
color_t color() override { return 0xC0FFFFFF; }
string get_name() override { return "floating bubble"; }
string get_help() override { return "This upward-floating bubble acts as a temporary platform."; }
void jumped_on() override;
};
struct levitating_bubble_platform : public freemoving_platform {
virtual int width() { return 1; }
xy siz() override { return {6.*width(), 6}; }
void act() override;
string glyph() override { return "O"; }
color_t color() override { return 0xC0FFFFFF; }
string get_name() override { return "levitating bubble"; }
string get_help() override { return "This levitating bubble acts as a temporary platform."; }
void jumped_on() override;
};
struct ferris_platform : public moving_platform {
+59 -1
View File
@@ -274,13 +274,17 @@ void entity::apply_walls() {
bool reset = false;
if(p->platform_type() == wStaircase) {
if(!fallthru) { on_floor = true; zero_vel = zvel; if(rvel.y > 0) rvel.y = 0; }
if(!fallthru) {
on_floor = true; zero_vel = zvel; if(rvel.y > 0) rvel.y = 0;
on_floor_platform = p;
}
}
else if(intersect(pb, get_pixel_bbox_at(rmow))) { /* should not happen */ }
else if(!intersect(pb, get_pixel_bbox_at(rmow + xy(rvel.x, 0))) && rvel.y > 0) {
on_floor = true;
on_floor_platform = p;
rvel.y /= 2;
if(abs(rvel.y) < 1e-6) rvel.y = 0;
reset = true;
@@ -361,6 +365,7 @@ void entity::kill_off_screen() {
void entity::kino() {
on_floor = false;
on_floor_platform = nullptr;
on_ice = 0;
wallhug = false;
on_bounce = false;
@@ -846,6 +851,59 @@ void kestrel::act() {
}
}
xy freemoving_platform::location_at(ld t) {
act();
if(t == gframeid-1) return last_position;
if(t == gframeid) return where;
auto h1 = to_hyper(last_position);
auto h2 = to_hyper(where);
auto d = hdist(h1, h2);
auto x = d * (t - (gframeid - 1));
return from_hyper(rgpushxto0(h1) * rspintox(gpushxto0(h1) * h2) * xpush0(x));
}
void floating_bubble_platform::act() {
if(position_time == gframeid) return;
last_position = where;
position_time = gframeid;
stay_on_screen();
apply_walls_reflect();
apply_vel();
auto dat = get_dat();
bool man_on = intersect(extend(get_pixel_bbox(), 0, 0, dat.d, 0), m.get_pixel_bbox());
if(man_on) vel.y += dat.d * dat.moda * 0.01;
else vel.y -= dat.d * dat.moda * 0.01;
vel.x = lerp(vel.x, 0, 1. / game_fps);
vel.y = lerp(vel.y, 0, 1. / game_fps);
}
void floating_bubble_platform::jumped_on() {
auto d = get_dat();
vel.y += 1.5 * d.d * d.modv * m.current.jump_power;
}
void levitating_bubble_platform::act() {
if(position_time == gframeid) return;
last_position = where;
position_time = gframeid;
stay_on_screen();
apply_walls_reflect();
apply_vel();
vel.x = lerp(vel.x, 0, 10. / game_fps);
vel.y = lerp(vel.y, 0, 10. / game_fps);
}
void levitating_bubble_platform::jumped_on() {
auto d = get_dat();
vel.y += 1.5 * d.d * d.modv * m.current.jump_power;
}
void healthbubble::act() {
stay_on_screen();
apply_walls_reflect();
+13
View File
@@ -54,6 +54,11 @@ void statdata::reset() {
mods.clear();
on_hit.clear();
status_strings.clear();
jump_power = 1;
gravity_value = 1;
extra_jumps = 0;
boost_max = 0;
}
man::man() {
@@ -83,6 +88,9 @@ void man::hs(stater& s) {
int prof = (int) profession; s1.act("profession", prof, -1); profession = (stat) prof;
for(auto st: allstats) s1.act(statinfos[st].name, base_stats[st], 10);
s1.act("jumps_used", jumps_used, 0);
s1.act("boost_left", boost_left, 0);
auto sdata = [&s1] (statdata& sd, string prefix) {
for(auto st: allstats) s1.act(prefix + statinfos[st].name, sd.stats[st], 10);
s1.act(prefix + "jump_control", sd.jump_control, 0);
@@ -97,6 +105,11 @@ void man::hs(stater& s) {
s1.act(prefix + "max_mageshield", sd.max_mageshield, 0);
s1.act(prefix + "stealth_bonus", sd.stealth_bonus, 0);
s1.act(prefix + "dodge_value", sd.dodge_value, 0);
s1.act(prefix + "jump_power", sd.jump_power, 1);
s1.act(prefix + "gravity_value", sd.gravity_value, 1);
s1.act(prefix + "extra_jumps", sd.extra_jumps, 0);
s1.act(prefix + "boost_max", sd.boost_max, 0);
};
sdata(current, "curr.");
+12 -1
View File
@@ -396,11 +396,22 @@ void gen_powers() {
"^", 0xFF0000FF,
[] (data& d) {
if(d.keystate & 1) {
if(m.on_floor) m.jumps_used = 0;
bool can_jump = m.on_floor;
if(gframeid <= m.on_floor_when + m.current.coyote_time) can_jump = true;
if(m.dresstime) can_jump = false;
if(can_jump) m.vel.y = m.zero_vel.y-(non_hyperbolic ? 3 : 5) * d.d * d.modv, m.on_floor_when = -1000;
if(!can_jump && m.current.extra_jumps > m.jumps_used && !(d.keystate & 2) && !m.dresstime) {
m.jumps_used++;
can_jump = true;
}
if(can_jump) {
if(m.on_floor_platform) m.on_floor_platform->jumped_on();
m.vel.y = m.zero_vel.y-(non_hyperbolic ? 3 : 5) * d.d * d.modv * m.current.jump_power, m.on_floor_when = -1000;
}
if(m.boost_left > 0) m.next.gravity_value += 1, m.boost_left --;
}
if(m.boost_left < m.current.boost_max && m.on_floor) m.boost_left++;
if(m.boost_left > m.current.boost_max) m.boost_left--;
}
).is_starting(),
+66 -5
View File
@@ -35,10 +35,71 @@ randeff confux("Confusion", "Makes you unable to tell left and right.", "You fee
});
// jump powers
randeff jump_double("Double Jump", "Lets you jump while already in air.", "You feel a strange force in your legs!", [] (data &d) { });
randeff jump_high("High Jump", "Lets you jump higher.", "Your legs feel stronger!", [] (data &d) { });
randeff jump_bubble("Bubble", "Lets you create bubbles to reach higher places.", "You feel strange bubbles growing in your mouth!", [] (data &d) { });
randeff jump_light("Lightness", "Causes you to be less affected by gravity.", "You feel lighter!", [] (data &d) { });
randeff jump_double("Double Jump", "Lets you jump while already in air.", "You feel a strange force in your legs!", [] (data &d) {
m.next.extra_jumps++;
});
randeff jump_high("High Jump", "Lets you jump higher.", "Your legs feel stronger!", [] (data &d) {
m.next.jump_power += 0.5;
});
randeff jump_boost("Boost", "Lets you move upwards during jump.", "Your feet feel magical!", [] (data &d) {
m.next.boost_max += game_fps;
});
randeff jump_floating_bubble("Floating Bubble", "Lets you create floating bubbles to reach higher places.", "You feel strange bubbles growing in your mouth!", [] (data &d) {
if(d.mode == rev::start || (d.mode == rev::active && d.keystate == 1)) {
int bubbles_found = 0;
for(auto& e: current_room->entities) if(e->id == "FBUBBLE") {
if(e->existing) bubbles_found++;
e->existing = false;
e->destroyed = true;
}
if(bubbles_found) return;
// auto d = m.get_dat();
auto mi = std::make_unique<floating_bubble_platform>();
mi->id = "FBUBBLE";
// mi->ctr = m.where + xy(m.facing * m.get_scale() * 1.5, 0);
mi->hs(fountain_resetter);
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, 0);
current_room->entities.emplace_back(std::move(mi));
}
});
randeff jump_levitating_bubble("Levitating Bubble", "Lets you create levitating bubbles to reach higher places.", "You feel strange bubbles growing in your stomach!", [] (data &d) {
auto& re = *d.re;
auto& bubble_available = re.a;
if(d.mode == rev::start) bubble_available = false;
if(m.on_floor) bubble_available = true;
if(m.on_floor_platform && m.on_floor_platform->id == "LBUBBLE") bubble_available = false;
if(d.mode == rev::start || (d.mode == rev::active && d.keystate == 1)) {
int bubbles_found = 0;
for(auto& e: current_room->entities) if(e->id == "LBUBBLE") {
if(e->existing) bubbles_found++;
e->existing = false;
e->destroyed = true;
}
if(bubbles_found || !bubble_available) return;
bubble_available = false;
auto mi = std::make_unique<levitating_bubble_platform>();
mi->id = "LBUBBLE";
mi->hs(fountain_resetter);
mi->where = m.where + xy(0, m.facing * m.get_scale() * m.siz().y * 0.25);
mi->vel = m.vel + xy(0, d.modv * 2);
current_room->entities.emplace_back(std::move(mi));
}
});
randeff jump_light("Lightness", "Causes you to be less affected by gravity.", "You feel lighter!", [] (data &d) {
m.next.gravity_value += 1;
});
// trap powers
randeff trap_detect("Detect traps", "Lets you see traps and secret passages in a circle around you.", "You see things you could not see before!", [] (data &d) {
@@ -308,7 +369,7 @@ void assign_potion_powers() {
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] };
find_power("reach").randeffs = relist{ pick(&jump_double, &jump_high, &jump_light, &jump_boost, &jump_floating_bubble, &jump_levitating_bubble), random_powers[3] };
find_power("fire").randeffs = relist{ pick(&fire_spit, &fire_weapon), random_powers[4] };
find_power("mystery").randeffs = relist{ random_powers[5], random_powers[6], random_powers[7] };
find_power("surprise").randeffs = relist{ random_powers[8] }; // need more random powers
+1
View File
@@ -314,6 +314,7 @@ void run() {
if(m.current.dodge_value) print(ss, " DV ", m.current.dodge_value, "%");
if(m.current.heavy_armor) print(ss, " PV ", m.current.heavy_armor, "%");
if(m.current.spikes) print(ss, " SP ", m.current.spikes);
if(m.current.boost_max) print(ss, " B ", m.boost_left, "/", m.current.boost_max);
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);