1
0
mirror of https://github.com/zenorogue/hyperrogue.git synced 2025-05-07 09:44:08 +00:00

rogueviz::ads:: highscore list

This commit is contained in:
Zeno Rogue 2025-02-10 15:51:26 +01:00
parent cc2e61cc50
commit 8dac0e0f68
7 changed files with 209 additions and 14 deletions

View File

@ -2,7 +2,7 @@
/* Compile with mymake -O3 -rv rogueviz/ads/ads-game */
/* Best run with -ads-menu; more detailed options are available too */
#define VER_RH "0.2"
#define VER_RH "1.0"
#ifdef RELHELL
@ -42,6 +42,7 @@ namespace rogueviz { std::vector<hr::reaction_t> cleanup; }
#include "views.cpp"
#include "tour.cpp"
#include "help.cpp"
#include "hiscore.cpp"
namespace hr {
@ -84,6 +85,7 @@ void restart() {
paused = false;
ship_pt = 0;
init_gamedata();
}
void run_ads_game_hooks() {
@ -216,6 +218,7 @@ void gamedata(hr::gamedata* gd) {
}
void set_config() {
load_hiscores();
lps_enable(&lps_relhell);
// enable_canvas();
}
@ -329,6 +332,9 @@ auto shot_hooks =
param_color(ghost_color, "color:ghost", true);
param_enum(hi_sort_by, "sort_by", 3)
->editable({{"platinum", ""}, {"plasteel", ""}, {"uranium", ""}, {"total score", ""}}, "sort high scores by", 'h');
rsrc_config();
});

View File

@ -223,7 +223,7 @@ bool ads_turn(int idelta) {
pdata.oxygen -= pt;
if(pdata.oxygen < 0) {
pdata.oxygen = 0;
game_over = true;
game_over_with_message("suffocated");
}
}
else view_pt += tc;

View File

@ -265,9 +265,9 @@ void ds_gen_particles(int qty, transmatrix from, ld shift, color_t col, ld spd,
}
}
void ds_crash_ship() {
void ds_crash_ship(const string &reason) {
if(ship_pt < invincibility_pt) return;
common_crash_ship();
common_crash_ship(reason);
dynamicval<eGeometry> g(geometry, gSpace435);
ds_gen_particles(rpoisson(crash_particle_qty * 2), inverse(current.T) * spin(ang*degree), current.shift, rsrc_color[rtHull], crash_particle_rapidity, crash_particle_life);
}
@ -292,6 +292,7 @@ void ds_handle_crashes() {
for(auto r: drocks) {
if(pointcrash(h, r->pts)) {
m->life_end = m->pt_main.shift;
cur.rocks_hit++;
if(r->type != oMainRock)
r->life_end = r->pt_main.shift;
dynamicval<eGeometry> g(geometry, gSpace435);
@ -308,11 +309,12 @@ void ds_handle_crashes() {
ld ds_scale = get_scale();
hyperpoint h = spin(ang*degree) * hpxyz(shape_ship[i] * ds_scale, shape_ship[i+1] * ds_scale, 1);
for(auto r: drocks) {
if(pointcrash(h, r->pts)) ds_crash_ship();
if(pointcrash(h, r->pts)) ds_crash_ship(r == main_rock ? "crashed into the home star" : "crashed into a star");
}
for(auto r: dresources) {
if(pointcrash(h, r->pts)) {
r->life_end = r->pt_main.shift;
cur.rsrc_collected++;
gain_resource(r->resource);
}
}
@ -408,7 +410,7 @@ bool ds_turn(int idelta) {
pdata.oxygen -= pt;
if(pdata.oxygen < 0) {
pdata.oxygen = 0;
game_over = true;
game_over_with_message("suffocated");
}
}
else view_pt += tc;
@ -732,6 +734,7 @@ void ds_restart() {
reset_textures();
pick_textures();
init_rsrc();
init_gamedata();
}
void run_ds_game_hooks() {

View File

@ -228,4 +228,23 @@ struct cellinfo {
}
};
struct gamedata {
int gameid;
string myname;
string timerstart, timerend;
string variant;
string deathreason;
ld scores[8];
int seconds;
int turrets_hit, rocks_hit, rsrc_collected;
};
extern gamedata cur;
void init_gamedata();
void game_over_with_message(const string& reason);
void save_to_hiscores();
void hiscore_menu();
void load_hiscores();
}}

154
rogueviz/ads/hiscore.cpp Normal file
View File

@ -0,0 +1,154 @@
namespace hr {
namespace ads_game {
gamedata cur;
vector<gamedata> allsaves;
void init_gamedata() {
cur.rocks_hit = 0;
cur.rsrc_collected = 0;
cur.turrets_hit = 0;
cur.deathreason = "still alive";
char buf[128]; strftime(buf, 128, "%c", localtime(&timerstart)); cur.timerstart = buf;
cur.myname = cur.timerstart;
}
void fill_gamedata() {
time_t timer = time(NULL);
char buf[128]; strftime(buf, 128, "%c", localtime(&timer)); cur.timerend = buf;
cur.seconds = int(timer - timerstart);
for(int a=0; a<3; a++) cur.scores[a] = pdata.score[a];
shstream hs;
print(hs, main_rock ? "2 " : "1 ");
print(hs, DS_(simspeed), " ", DS_(accel), " ", DS_(how_much_invincibility), " ", vid.creature_scale, " ", DS_(missile_rapidity));
if(!main_rock) print(hs, " ", rock_max_rapidity, " ", rock_density, " ", max_gen_per_frame, " ", draw_per_frame);
auto all = [&] (player_data& d) {
print(hs, " ", d.hitpoints, " ", d.ammo, " ", d.fuel, " ", d.oxygen);
};
all(DS_(max_pdata));
all(DS_(tank_pdata));
cur.variant = hs.s;
}
unsigned myhash(const string& s) {
std::size_t seed = s.size();
for(auto& i : s) {
seed ^= i + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
return seed;
}
void save(const gamedata& sd) {
#if CAP_SAVE
fhstream f("relhell.save", "at");
println(f, "Relative Hell ", VER_RH);
println(f, sd.myname);
println(f, sd.timerstart);
println(f, sd.timerend);
println(f, sd.variant);
println(f, sd.deathreason);
shstream hs;
print(hs, sd.scores[0], " ", sd.scores[1], " ", sd.scores[2], " ", sd.seconds, " ", sd.rocks_hit, " ", sd.rsrc_collected, " ", sd.turrets_hit);
println(f, hs.s);
println(f, myhash(sd.variant + "#" + hs.s));
#endif
}
void game_over_with_message(const string& reason) {
if(game_over) return;
fill_gamedata();
cur.deathreason = reason;
if(pdata.fuel <= 0) cur.deathreason += " while out of fuel";
if(pdata.ammo <= 0) cur.deathreason += " while out of ammo";
game_over = true;
}
void save_to_hiscores() {
if(!main_rock && (pdata.score[0] + pdata.score[1] + pdata.score[2] == 0)) return;
if(main_rock && pdata.score[0] < 5) return;
save(cur);
allsaves.push_back(cur);
}
void load_hiscores() {
allsaves.clear();
fhstream f("relhell.save", "rt");
if(!f.f) return;
string s;
while(!feof(f.f)) {
s = scanline_noblank(f);
if(s == "Relative Hell 1.0") {
gamedata gd;
gd.myname = scanline_noblank(f);
gd.timerstart = scanline_noblank(f);
gd.timerend = scanline_noblank(f);
gd.variant = scanline_noblank(f);
gd.deathreason = scanline_noblank(f);
sscanf(scanline_noblank(f).c_str(), "%lf%lf%lf%d%d%d%d",
&gd.scores[0], &gd.scores[1], &gd.scores[2], &gd.seconds, &gd.rocks_hit, &gd.rsrc_collected, &gd.turrets_hit);
allsaves.push_back(std::move(gd));
}
}
}
int hi_sort_by = 3;
void hiscore_menu() {
emptyscreen();
dialog::init("High scores");
fill_gamedata();
vector<gamedata*> v;
for(auto& ad: allsaves)
if(ad.variant == cur.variant)
v.push_back(&ad);
v.push_back(&cur);
auto getval = [] (gamedata *g) {
if(!main_rock) return g->scores[0];
if(hi_sort_by == 3) return g->scores[0] + g->scores[1] + g->scores[2];
return g->scores[hi_sort_by];
};
sort(v.begin(), v.end(), [&] (gamedata* g1, gamedata* g2) { return getval(g1) > getval(g2); });
dialog::start_list(900, 900, '1');
for(auto ad: v) {
dialog::addSelItem(ad->myname + " (" + ad->deathreason + ")", main_rock ? fts(getval(ad)) : its(getval(ad)), dialog::list_fake_key++);
dialog::add_action_push([ad] {
emptyscreen();
dialog::init(ad->myname);
if(!main_rock) {
dialog::addSelItem("platinum", its(ad->scores[0]), 'p');
dialog::addSelItem("plasteel", its(ad->scores[1]), 'l');
dialog::addSelItem("uranium", its(ad->scores[2]), 'u');
}
else {
dialog::addSelItem("score", fts(ad->scores[0]), 's');
}
if(!main_rock) dialog::addSelItem("stars hit", its(ad->rocks_hit), 'h');
if(main_rock) dialog::addSelItem("rocks hit", its(ad->rocks_hit), 'r');
if(!main_rock) dialog::addSelItem("turrets hit", its(ad->turrets_hit), 't');
dialog::addSelItem("resources collected", its(ad->rsrc_collected), 'c');
dialog::addSelItem("played", ad->timerstart, 'T');
dialog::addSelItem("seconds", its(ad->seconds), 'S');
dialog::addBack();
dialog::display();
});
}
dialog::end_list();
if(!main_rock) add_edit(hi_sort_by);
dialog::addSelItem("name", cur.myname, 'n');
dialog::add_action([] { dialog::edit_string(cur.myname, "enter your name", ""); });
dialog::addBack();
dialog::display();
}
}
}

View File

@ -281,16 +281,16 @@ bool pointcrash(hyperpoint h, const vector<cross_result>& vf) {
return winding & 1;
}
void common_crash_ship() {
void common_crash_ship(const string &reason) {
invincibility_pt = ship_pt + DS_(how_much_invincibility);
pdata.hitpoints--;
if(pdata.hitpoints <= 0) game_over = true;
if(pdata.hitpoints <= 0) game_over_with_message(reason);
playSound(nullptr, "explosion");
}
void ads_crash_ship() {
void ads_crash_ship(const string &reason) {
if(ship_pt < invincibility_pt) return;
common_crash_ship();
common_crash_ship(reason);
hybrid::in_actual([&] {
gen_particles(rpoisson(crash_particle_qty * 2), vctr, ads_inverse(current * vctrV) * spin(ang*degree), rsrc_color[rtHull], crash_particle_rapidity, crash_particle_life);
});
@ -458,6 +458,8 @@ void handle_crashes() {
if(pointcrash(h, r->pts)) {
m->life_end = m->pt_main.shift;
r->life_end = r->pt_main.shift;
if(r->type == oTurret) cur.turrets_hit++;
if(r->type == oRock) cur.rocks_hit++;
hybrid::in_actual([&] {
gen_particles(rpoisson(crash_particle_qty), m->owner, m->at * ads_matrix(Id, m->life_end), missile_color, crash_particle_rapidity, crash_particle_life);
gen_particles(rpoisson(crash_particle_qty), r->owner, r->at * ads_matrix(Id, r->life_end), r->col, crash_particle_rapidity, crash_particle_life);
@ -471,23 +473,24 @@ void handle_crashes() {
ld ads_scale = get_scale();
hyperpoint h = spin(ang*degree) * hpxyz(shape_ship[i] * ads_scale, shape_ship[i+1] * ads_scale, 1);
for(auto r: rocks) {
if(pointcrash(h, r->pts)) ads_crash_ship();
if(pointcrash(h, r->pts)) ads_crash_ship(r->type == oTurret ? "crashed into a turret" : "crashed into an asteroid");
}
for(auto r: enemy_missiles) {
if(pointcrash(h, r->pts)) {
r->life_end = r->pt_main.shift;
ads_crash_ship();
ads_crash_ship("hit by a missile");
}
}
for(auto r: resources) {
if(pointcrash(h, r->pts)) {
r->life_end = r->pt_main.shift;
cur.rsrc_collected++;
gain_resource(r->resource);
}
}
hyperpoint h1 = normalize(h);
bool crashed = false;
bool crashed = false; string crash_what;
hybrid::in_actual([&] {
h1[3] = h1[2]; h1[2] = 0;
ads_point rel = ads_inverse(current * vctrV) * ads_point(h1, 0);
@ -500,10 +503,13 @@ void handle_crashes() {
if(ci.type == wtDestructible || ci.type == wtSolid || (ci.type == wtGate && (int(floor(t)) & 3) == 0) || ci.type == wtBarrier) {
if(!crashed && ship_pt > invincibility_pt) println(hlog, "crashed at t = ", t / TAU, " shift = ", rel.shift/TAU, " sec = ", w.second*cgi.plevel/TAU);
crashed = true;
if(ci.type == wtGate) crash_what = "crashed into a gate";
if(ci.type == wtDestructible || ci.type == wtSolid) crash_what = "crashed into a wall";
if(ci.type == wtBarrier) crash_what = "hit a Great Wall";
}
});
if(crashed) ads_crash_ship();
if(crashed) ads_crash_ship(crash_what);
}
});
}

View File

@ -171,10 +171,15 @@ void game_menu() {
dialog::addItem(XLAT("restart game"), 'r');
dialog::add_action([] {
game_over_with_message("restarted");
save_to_hiscores();
if(main_rock) ds_restart();
else restart();
popScreen(); });
dialog::addItem(XLAT("highscores"), 'h');
dialog::add_action_push(hiscore_menu);
dialog::addItem(XLAT("refill cheat"), 'R');
dialog::add_action([] { init_rsrc(); popScreen(); });
@ -209,6 +214,8 @@ void game_menu() {
dialog::addItem("quit the game", 'q');
dialog::add_action([] {
game_over_with_message("quit");
save_to_hiscores();
quitmainloop = true;
});