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:
parent
cc2e61cc50
commit
8dac0e0f68
@ -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();
|
||||
});
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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() {
|
||||
|
@ -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
154
rogueviz/ads/hiscore.cpp
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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;
|
||||
});
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user