Compare commits

...

19 Commits

Author SHA1 Message Date
Zeno Rogue 0ec4e46bf0 SDL2 bugfix to shmup and game_keys_scroll 2024-03-24 13:15:58 +01:00
Zeno Rogue c55550de57 13.0d 2024-03-24 12:18:40 +01:00
Zeno Rogue 886a7ff43e fixed on older compiler 2024-03-24 11:36:22 +01:00
Zeno Rogue deb207e4c3 load_mode_data now resets creature scale in shmup 2024-03-24 11:15:33 +01:00
Zeno Rogue 819d815d59 mode now includes specialland, creature_scale and global_boundary_ratio parameters 2024-03-24 11:15:13 +01:00
Zeno Rogue b20288557e specialland now has param 2024-03-24 11:14:49 +01:00
Zeno Rogue 4a8eb08340 fixed face_the_player in VR 2024-03-24 11:14:28 +01:00
Zeno Rogue 007a111eab compass/Yendor targets now should be displayed in VR 2024-03-24 11:14:05 +01:00
Zeno Rogue 65e9f68bc7 disable achievements on custom land list 2024-03-24 00:56:15 +01:00
Zeno Rogue 3e30a7ded1 test command in custom land list 2024-03-24 00:51:20 +01:00
Zeno Rogue 5f8d250940 refactored gen_landvisited 2024-03-24 00:51:00 +01:00
Zeno Rogue dee90f8d7c creature_scale saved to modedata 2024-03-24 00:41:36 +01:00
Zeno Rogue d43b19625e scale now always can be changed, but cheater flag is set in shmup 2024-03-24 00:39:02 +01:00
Zeno Rogue f32a2708b4 do not call auto_creator when loading valid irregular save 2024-03-24 00:30:50 +01:00
Zeno Rogue be27fc0fce protect save_map_bin and load_map_bin from possible lacking base 2024-03-24 00:30:04 +01:00
Zeno Rogue 61720cec5e nicer plain floorshapes in IRREGULAR maps 2024-03-24 00:29:45 +01:00
Zeno Rogue 7cf1643c5d ls:: removed debug from landscape 2024-03-23 23:48:48 +01:00
Zeno Rogue 3791daf9e3 map editor now can save irregular maps (also should save modes too) 2024-03-23 21:21:16 +01:00
Zeno Rogue e9941d29d3 hstream_exception now can contain explanation 2024-03-23 21:19:04 +01:00
19 changed files with 238 additions and 57 deletions

View File

@ -119,6 +119,7 @@ EX bool wrongMode(char flags) {
if(disksize) return true;
}
if(ineligible_starting_land && !flags) return true;
if(use_custom_land_list) return true;
if(shmup::on != (flags == rg::shmup || flags == rg::racing)) return true;
if(racing::on != (flags == rg::racing)) return true;
@ -144,6 +145,7 @@ EX bool wrongMode(char flags) {
dls = land_structure;
if(land_structure != dls) return true;
if(shmup::on && vid.creature_scale != 1) return true;
if(numplayers() > 1 && !multi::friendly_fire) return true;
if(numplayers() > 1 && multi::pvp_mode) return true;
if(numplayers() > 1 && multi::split_screen) return true;
@ -804,6 +806,7 @@ EX void achievement_final(bool really_final) {
if(bow::crossbow_mode() && bow::style == bow::cbBull) specialcode += 32;
if(bow::crossbow_mode() && bow::style == bow::cbGeodesic) specialcode += 64;
if(bow::crossbow_mode() && bow::style == bow::cbGeometric) specialcode += 96;
if(shmup::on && vid.creature_scale != 1) return;
if(sphere && specialland == laHalloween) {
if(specialcode) return;
@ -814,6 +817,7 @@ EX void achievement_final(bool really_final) {
if(ineligible_starting_land) return;
if(geometry) return;
if(NONSTDVAR) return;
if(use_custom_land_list) return;
if(numplayers() > 1 && !multi::friendly_fire) return;
if(numplayers() > 1 && multi::pvp_mode) return;

View File

@ -1132,7 +1132,7 @@ EX void setLandSphere(cell *c) {
vector<eLand> euland;
map<int, eLand> euland3;
map<int, eLand> euland3_hash;
EX map<tuple<int, int, int>, eLand> landscape_lands;
EX map<array<int, 3>, eLand> landscape_lands;
EX eLand& get_euland(int c) {
euland.resize(max_vec);
@ -1146,7 +1146,7 @@ EX void clear_euland(eLand first) {
euland3.clear();
euland3[0] = first;
landscape_lands.clear();
landscape_lands[{0,0,0}] = first;
landscape_lands[make_array(0,0,0)] = first;
}
bool valid_wall_at(int c) {

View File

@ -2497,15 +2497,8 @@ void celldrawer::draw_item_full() {
if(doHighlight()) asciiborder = kind_outline(it) >> 8;
if(it == itCompass && isPlayerOn(c)) {
cell *c1 = c ? findcompass(c) : NULL;
if(c1) {
shiftmatrix P = ggmatrix(c1);
shiftpoint P1 = tC0(P);
queuestr(P1, 2*vid.fsize, "X", 0x10100 * int(128 + 100 * sintick(150)));
queuestr(P1, vid.fsize, its(-compassDist(c)), 0x10101 * int(128 - 100 * sintick(150)));
addauraspecial(P1, 0xFF0000, 0);
}
shiftpoint dummy;
mark_compass(c, dummy);
}
}

View File

@ -5141,3 +5141,43 @@ Other:
- when you press ESC in the gameover screen, the YASC message is displayed
- special YASC message for pinches, and being on the Round Table
- in YASC messages, mention the knights blocking the way, and also mention their names
2024-03-24 11:32 Update 13.0d:
System:
* itch.io Windows binaries and Steam Windows/Linux binaries now use SDL2 instead of SDL1.2
Custom mode:
* A new mode where you can select the lands to be used.
* Another menu can be used to save a mode to a file.
* Enabling Halloween or Space Rocks in infinite geometries now produces something that makes sense.
* Previously changing the creature scale was disabled in non-cheat shmup. Now it can be changed (but it counts as a cheat).
* New land structure 'landscape'.
Graphics:
* Font scale used in ASCII maps now can be changed.
* Items moved by Orb of Water, Magnetism, Winter, Space, and Repulsion are now animated.
* VR: fixed items, Ivy, compasses, etc. being placed incorrectly in 2.5D.
* VR: compass/Yendor targets now should be displayed.
Gameplay:
* Void Beasts are now pulled by Orb of Air.
* Changed the electrical properties of some walls to make Eclectic City more friendly.
* Trees etc are now mentioned as blockers in YASC messages.
* YASC codes work better if killed on a 10+ tile.
Alternate geometries:
* Clear more walls when generating Wild West in high GP.
* Better Emerald in Octagon chamfered.
* Fixed Emerald Mine and Vineyard generating very bad in {n,oo} and binary tiling.
* Fixed the lack of non-trapdoors in Zebra 435.
* Better 'pseudohept' tiles in INVERSE tilings.
* In grid mode, don't try to draw greatwall lines outside of normal geometry pure/bitruncated.
* Nicer cell boundaries used in Archimedean and irregular tilings.
* When you save an irregular map using Orb of Safety or map editor (or custom mode), it should now save the irregular map used.
Bug fixes:
* Fixed dice hints over different heights.
* Fixed troll nests in Horodisk/Voronoi.
* Fixed a crash when running away from Clearing in single-land mode.
* Some values are tracked in savefiles while previously they did not (fatigue, snake oil, crossbow reload time, gun ammo, etc.) (Thanks to jlm)

View File

@ -1388,7 +1388,7 @@ EX void initConfig() {
addsaverenum(variation, "mode-variation", eVariation::bitruncated);
addsaver(peace::on, "mode-peace");
addsaver(peace::otherpuzzles, "mode-peace-submode");
addsaverenum(specialland, "land for special modes");
param_enum(specialland, "specialland", "land for special modes", specialland);
addsaver(viewdists, "expansion mode");
param_f(backbrightness, "back", "brightness behind sphere");
@ -2955,8 +2955,7 @@ EX void show3D() {
dialog::addSelItem(XLAT("3D detailed settings"), "", 'D');
dialog::add_action_push(show3D_height_details);
if(scale_used())
add_edit(vid.creature_scale);
add_edit(vid.creature_scale);
}
else {
add_edit(vid.creature_scale);
@ -3105,7 +3104,9 @@ EX int config3 = addHook(hooks_configfile, 100, [] {
}, "context help", 'H');
param_f(vid.creature_scale, "creature_scale", "3d-creaturescale", 1)
->editable(0, 1, .1, "Creature scale", "", 'C');
->editable(0, 1, .1, "Creature scale", "", 'C')
->set_extra([] { dialog::addInfo(XLAT("changing this during shmup is counted as cheating")); })
->set_reaction([] { if(shmup::on) cheater++; });
param_f(vid.height_width, "heiwi", "3d-heightwidth", 1.5)
->editable(0, 1, .1, "Height to width", "", 'h');
param_f(vid.yshift, "yshift", "Y shift", 0)

View File

@ -957,7 +957,7 @@ EX void mainloopiter() {
}
else sc_ticks = ticks;
if(game_keys_scroll && !shmup::on && (cmode & sm::NORMAL) && !keystate[SDLK_LALT] && !keystate[SDLK_RALT]) {
if(game_keys_scroll && !shmup::on && (cmode & sm::NORMAL) && !keystate[SDL12(SDLK_LALT, SDL_SCANCODE_LALT)] && !keystate[SDL12(SDLK_RALT, SDL_SCANCODE_RALT)]) {
rug::using_rugview urv;
auto& lastticks = sc_ticks2;
ld t = (ticks - lastticks) * shiftmul / 1000.;

View File

@ -507,7 +507,7 @@ void geometry_information::generate_floorshapes_for(int id, cell *c, int siid, i
}
}
else if(arb::in() || aperiodic || arcm::in()) {
else if(arb::in() || aperiodic || arcm::in() || IRREGULAR) {
vector<hyperpoint> actual;
for(int j=0; j<cor; j++)
actual.push_back(get_corner_position(c, j));

View File

@ -152,11 +152,8 @@ void validity_info() {
EX bool showquotients;
string validclasses[4] = {" (X)", " (½)", "", " (!)"};
EX void ge_land_selection() {
cmode = sm::SIDE | sm::MAYDARK;
gamescreen();
EX void gen_landvisited() {
if(cheater) for(int i=0; i<landtypes; i++) landvisited[i] = true;
for(int i=0; i<landtypes; i++)
@ -177,6 +174,13 @@ EX void ge_land_selection() {
landvisited[laCamelot] |= hiitemsMax(treasureType(laCamelot)) >= 1;
landvisited[laCA] = true;
landvisited[laAsteroids] = true;
}
EX void ge_land_selection() {
cmode = sm::SIDE | sm::MAYDARK;
gamescreen();
gen_landvisited();
dialog::init(XLAT("select the starting land"));
if(dialog::infix != "") mouseovers = dialog::infix;

View File

@ -576,8 +576,6 @@ EX void add_wall(int i, const vector<hyperpoint>& h) {
static constexpr ld hcrossf7 = 0.620672, hexf7 = 0.378077, tessf7 = 1.090550, hexhexdist7 = 0.566256;
#endif
EX bool scale_used() { return (shmup::on && geometry == gNormal && BITRUNCATED) ? (cheater || autocheat) : true; }
EX bool is_subcube_based(eVariation var) {
return among(var, eVariation::subcubes, eVariation::dual_subcubes, eVariation::bch, eVariation::bch_oct);
}
@ -784,13 +782,13 @@ void geometry_information::prepare_basics() {
if(msphere && geuclid) scalefactor *= (1 + vid.depth);
if(msphere && ghyperbolic) scalefactor *= sinh(1 + vid.depth);
if(scale_used()) {
if(true) {
scalefactor *= vid.creature_scale;
orbsize *= vid.creature_scale;
}
zhexf = BITRUNCATED ? hexf : crossf* .55;
if(scale_used()) zhexf *= vid.creature_scale;
zhexf *= vid.creature_scale;
if(WDIM == 2 && GDIM == 3) zhexf *= 1.5, orbsize *= 1.2;
if(cgi.emb->is_euc_in_hyp()) {
@ -1314,7 +1312,7 @@ EX string cgi_string() {
V("RS:", fts(geom3::euclid_embed_rotate));
}
if(scale_used()) V("CS", fts(vid.creature_scale));
if(vid.creature_scale != 1) V("CS", fts(vid.creature_scale));
if(WDIM == 3) V("HTW", fts(vid.height_width));

View File

@ -769,11 +769,12 @@ EX shiftmatrix face_the_player(const shiftmatrix V) {
if(nonisotropic) return shiftless(spin_towards(unshift(V), dummy, C0, 2, 0));
#if CAP_VR
if(vrhr::enabled) {
shiftpoint h = tC0(V);
shiftpoint h = tC0(V);
hyperpoint uh = unshift(h);
return shiftless(cspin90(1, 2) * lrspintox(cspin90(2, 1) * uh) * xpush(hdist0(uh)) * cspin90(0, 2) * spin270());
return shiftless(cspin90(1, 2) * rspintox(cspin90(2, 1) * uh) * xpush(hdist0(uh)) * cspin90(0, 2) * spin270());
}
#endif
return rgpushxto0(tC0(V));
}
@ -852,6 +853,35 @@ EX void draw_ascii(const shiftmatrix& V, char glyph, color_t col, ld size) {
while(id < isize(ptds)) ptds[id++]->prio = PPR::MONSTER_BODY;
}
EX void queue_goal_text(shiftpoint P1, ld sizemul, const string& s, color_t color) {
#if CAP_VR
if(vrhr::enabled) {
auto e = inverse_exp(P1);
e = e * 3 / hypot_d(GDIM, e);
auto T = face_the_player(shiftless(rgpushxto0(direct_exp(e))));
queuestrn(T, sizemul * mapfontscale / 100, s, color);
return;
}
#endif
queuestr(P1, vid.fsize * sizemul, s, color);
}
EX bool mark_compass(cell *c, shiftpoint& P1) {
cell *c1 = c ? findcompass(c) : NULL;
if(!c1) return false;
shiftmatrix P = ggmatrix(c1);
P1 = tC0(P);
if(isPlayerOn(c)) {
queue_goal_text(P1, 2, "X", 0x10100 * int(128 + 100 * sintick(150)));
// queuestr(V, 1, its(compassDist(c)), 0x10101 * int(128 - 100 * sin(ticks / 150.)), 1);
queue_goal_text(P1, 1, its(-compassDist(c)), 0x10101 * int(128 - 100 * sintick(150)));
addauraspecial(P1, 0xFF0000, 0);
}
return true;
}
EX bool drawItemType(eItem it, cell *c, const shiftmatrix& V, color_t icol, int pticks, bool hidden) {
if(!it) return false;
char xch = iinf[it].glyph;
@ -953,18 +983,8 @@ EX bool drawItemType(eItem it, cell *c, const shiftmatrix& V, color_t icol, int
else
#endif
if(1) {
cell *c1 = c ? findcompass(c) : NULL;
if(c1) {
shiftmatrix P = ggmatrix(c1);
shiftpoint P1 = tC0(P);
if(isPlayerOn(c)) {
queuestr(P1, 2*vid.fsize, "X", 0x10100 * int(128 + 100 * sintick(150)));
// queuestr(V, 1, its(compassDist(c)), 0x10101 * int(128 - 100 * sin(ticks / 150.)), 1);
queuestr(P1, vid.fsize, its(-compassDist(c)), 0x10101 * int(128 - 100 * sintick(150)));
addauraspecial(P1, 0xFF0000, 0);
}
shiftpoint P1;
if(mark_compass(c, P1)) {
V2 = V * lrspintox(inverse_shift(V, P1));
}
else V2 = V;
@ -4786,7 +4806,7 @@ EX void drawMarkers() {
}
shiftpoint H = tC0(ggmatrix(keycell));
#if CAP_QUEUE
queuestr(H, 2*vid.fsize, "X", 0x10101 * int(128 + 100 * sintick(150)));
queue_goal_text(H, 2, "X", 0x10101 * int(128 + 100 * sintick(150)));
int cd = celldistance(yi[yii].key(), cwt.at);
if(cd == DISTANCE_UNKNOWN) for(int i2 = 0; i2<YDIST; i2++) {
int cd2 = celldistance(cwt.at, yi[yii].path[i2]);
@ -4795,7 +4815,7 @@ EX void drawMarkers() {
println(hlog, "i2 = ", i2, " cd = ", celldistance(cwt.at, keycell));
}
}
queuestr(H, vid.fsize, its(cd), 0x10101 * int(128 - 100 * sintick(150)));
queue_goal_text(H, 1, its(cd), 0x10101 * int(128 - 100 * sintick(150)));
#endif
addauraspecial(H, iinf[itOrbYendor].color, 0);
}

View File

@ -144,7 +144,10 @@ template<class T, class U> void hread(hstream& hs, map<T,U>& a) {
template<class C, class C1, class... CS> void hwrite(hstream& hs, const C& c, const C1& c1, const CS&... cs) { hwrite(hs, c); hwrite(hs, c1, cs...); }
template<class C, class C1, class... CS> void hread(hstream& hs, C& c, C1& c1, CS&... cs) { hread(hs, c); hread(hs, c1, cs...); }
struct hstream_exception : hr_exception {};
struct hstream_exception : hr_exception {
hstream_exception() : hr_exception("hstream_exception") {}
hstream_exception(const std::string &s) : hr_exception(s) {}
};
struct fhstream : hstream {
FILE *f;

View File

@ -13,8 +13,8 @@
#define _HYPER_H_
// version numbers
#define VER "13.0c"
#define VERNUM_HEX 0xAA03
#define VER "13.0d"
#define VERNUM_HEX 0xAA04
#include "sysconfig.h"

View File

@ -770,7 +770,7 @@ EX int celldist(cell *c, bool alts) {
return hi.celldists[alts][cells[cellindex[c]].localindex];
}
eGeometry orig_geometry;
eGeometry orig_geometry, base_geometry;
void start_game_on_created_map() {
popScreen();
@ -807,6 +807,32 @@ bool save_map(const string& fname) {
return true;
}
EX void save_map_bin(hstream& f) {
if(!base) { f.write<short>(-1); return; }
auto& all = base->allcells();
int origcells = 0;
for(cellinfo& ci: cells)
if(ci.generation == 0)
origcells++;
f.write<short> (base_geometry);
f.write<short> (isize(all));
f.write<short> (origcells);
for(auto h: all) {
origcells = 0;
for(auto i: cells_of_heptagon[h->master])
if(cells[i].generation == 0)
origcells++;
f.write<short> (origcells);
for(auto i: cells_of_heptagon[h->master]) if(cells[i].generation == 0) {
auto &ci = cells[i];
f.write<ld>(ci.p[0]);
f.write<ld>(ci.p[1]);
f.write<ld>(ci.p[LDIM]);
}
}
}
bool load_map(const string &fname) {
fhstream f(fname, "rt");
if(!f.f) return false;
@ -839,6 +865,48 @@ bool load_map(const string &fname) {
return true;
}
EX void load_map_bin(hstream& f) {
auto& all = base->allcells();
eGeometry g = (eGeometry) f.get<short>();
if(int(g) == -1) return;
int sa = f.get<short>();
cellcount = f.get<short>();
if(g != geometry) throw hstream_exception("bad geometry");
if(sa != isize(all)) throw hstream_exception("bad size of all");
density = cellcount * 1. / isize(all);
cells.clear();
for(auto h: all) {
int q = f.get<short>();
if(q < 0 || q > cellcount) throw hstream_exception("incorrect quantity");
while(q--) {
cells.emplace_back();
cellinfo& s = cells.back();
s.patterndir = -1;
double a, b, c;
a = f.get<ld>();
b = f.get<ld>();
c = f.get<ld>();
s.p = hpxyz(a, b, c);
s.p = normalize(s.p);
for(auto c0: all) s.relmatrices[c0] = calc_relative_matrix(c0, h, s.p);
s.owner = h;
}
}
make_cells_of_heptagon();
runlevel = 2;
}
EX void load_map_full(hstream& f) {
init();
load_map_bin(f);
while(runlevel < 10) step(1000);
start_game_on_created_map();
}
void cancel_map_creation() {
base = NULL;
runlevel = 0;
@ -950,7 +1018,7 @@ void show_gridmaker() {
};
}
EX void visual_creator() {
EX void init() {
stop_game();
orig_geometry = geometry;
switch(geometry) {
@ -966,13 +1034,19 @@ EX void visual_creator() {
break;
}
base_geometry = geometry;
variation = eVariation::pure;
start_game();
if(base) delete base;
base = currentmap;
base_config = euc::eu;
drawthemap();
cellcount = int(isize(base->allcells()) * density + .5);
gridmaking = true;
drawthemap();
}
EX void visual_creator() {
init();
pushScreen(show_gridmaker);
runlevel = 0;
gridmaking = true;
@ -1015,7 +1089,7 @@ int readArgs() {
else if(argis("-irrload")) {
PHASE(3);
restart_game();
visual_creator();
init();
showstartmenu = false;
shift();
load_map(args());

View File

@ -2913,7 +2913,6 @@ EX void set_land_for_geometry(cell *c) {
if(landscape_div < 0) landscape_div = 1;
array<int, 3> a;
for(int i=0; i<3; i++) a[i] = getCdata(c, i);
auto ca = a;
auto& ld = landscape_div;
auto ld2 = ld * 2;
int sh = 0;
@ -2927,7 +2926,7 @@ EX void set_land_for_geometry(cell *c) {
if(sh * 2 < ld * 3) a[i] = gdiv(a[i], ld2)*2+1;
else a[i] = gdiv(a[i]+ld, ld2)*2;
}
eLand& l = landscape_lands[{a[0], a[1], a[2]}];
eLand& l = landscape_lands[make_array(a[0], a[1], a[2])];
if(l == laNone) l = random_land();
setland(c, l);
return;

View File

@ -826,7 +826,7 @@ EX const int walls_when = 388;
EX void mark_tamper() { cheater++; }
EX void customize_land_in_list(eLand l) {
cmode = sm::DARKEN; gamescreen();
cmode = sm::SIDE | sm::MAYDARK; gamescreen();
dialog::init(XLATN(linf[l].name), linf[l].color);
@ -859,12 +859,20 @@ EX void customize_land_in_list(eLand l) {
dialog::get_ne().reaction = mark_tamper;
});
gen_landvisited();
if(landvisited[l]) {
dialog::addItem(XLAT("test"), 'T');
dialog::add_action([l] {
stop_game(); firstland = specialland = l; start_game();
});
}
dialog::addBack();
dialog::display();
}
EX void customize_land_list() {
cmode = sm::DARKEN; gamescreen();
cmode = sm::SIDE | sm::MAYDARK; gamescreen();
dialog::init(XLAT("custom land list"));
if(dialog::infix != "") mouseovers = dialog::infix;

View File

@ -491,6 +491,9 @@ EX namespace mapstream {
f.write(gp::param.second);
}
#endif
#if CAP_IRR
if(IRREGULAR) irr::save_map_bin(f);
#endif
#if MAXMDIM >= 4
if(variation == eVariation::coxeter) {
f.write(reg3::coxeter_param);
@ -587,6 +590,9 @@ EX namespace mapstream {
f.read(gp::param.second);
}
#endif
#if CAP_IRR
if(IRREGULAR) { irr::load_map_full(f); stop_game(); }
#endif
#if MAXMDIM >= 4
if(variation == eVariation::coxeter && vernum >= 0xA908) {
f.read(reg3::coxeter_param);

View File

@ -821,7 +821,8 @@ EX void handleInput(int delta, config &scfg) {
get_actions(scfg);
const Uint8 *keystate = SDL12_GetKeyState(NULL);
if(keystate[SDLK_LCTRL] || keystate[SDLK_RCTRL]) d /= 5;
if(keystate[SDL12(SDLK_LCTRL, SDL_SCANCODE_LCTRL)] || keystate[SDL12(SDLK_RCTRL, SDL_SCANCODE_RCTRL)]) d /= 5;
double panx =
actionspressed[49] - actionspressed[51] + axespressed[2] / 32000.0;

View File

@ -1763,7 +1763,7 @@ EX void initAll() {
#if CAP_SAVE
select_savefile();
loadsave();
if(IRREGULAR) irr::auto_creator();
if(IRREGULAR && !irr::base) irr::auto_creator();
#endif
start_game();
restore_all_golems();
@ -1792,6 +1792,10 @@ EX void finishAll() {
string modheader = "# HyperRogue saved game mode file";
set<string> allowed_params = {
"creature_scale", "global_boundary_ratio", "specialland"
};
EX void save_mode_to_file(const string& fname) {
shstream ss;
save_mode_data(ss);
@ -1801,6 +1805,12 @@ EX void save_mode_to_file(const string& fname) {
println(f, modheader);
println(f, s);
if(custom_welcome != "") println(f, "CMSG ", custom_welcome);
for(auto& ap: allowed_params) {
auto& s = params[ap]->saver;
if(s->dosave())
println(f, ap, "=", s->save());
}
}
EX void load_mode_from_file(const string& fname) {
@ -1813,9 +1823,21 @@ EX void load_mode_from_file(const string& fname) {
ss.s = from_hexstring(hex + "00");
custom_welcome = "";
while(true) {
string s = scanline(f);
string s = scanline_noblank(f);
if(s == "") break;
if(s.substr(0, 5) == "CMSG ") custom_welcome = s.substr(5);
else if(s.substr(0, 5) == "CMSG ") custom_welcome = s.substr(5);
else {
auto pos = s.find("=");
if(pos != string::npos) {
string name = s.substr(0, pos);
string value = s.substr(pos+1);
if(!params.count(name) || !allowed_params.count(name)) {
println(hlog, "# parameter unknown: ", name);
continue;
}
params[name]->load_as_animation(value);
}
}
}
stop_game();
load_mode_data_with_zero(ss);

View File

@ -1008,6 +1008,10 @@ EX void save_mode_data(hstream& f) {
f.write<char>(6);
f.write<int>(landscape_div);
}
if(shmup::on && vid.creature_scale != 1) {
f.write<char>(7);
f.write<ld>(vid.creature_scale);
}
}
EX void load_mode_data_with_zero(hstream& f) {
@ -1028,6 +1032,7 @@ EX void load_mode_data_with_zero(hstream& f) {
xcheat = f.get<char>();
casual = false;
bow::weapon = bow::wBlade;
if(shmup::on) vid.creature_scale = 1;
while(true) {
char option = f.get<char>();
@ -1070,6 +1075,9 @@ EX void load_mode_data_with_zero(hstream& f) {
landscape_div = f.get<int>();
break;
case 7:
vid.creature_scale = f.get<ld>();
default:
throw hstream_exception();
}