mirror of
https://github.com/zenorogue/hyperrogue.git
synced 2024-12-24 17:10:36 +00:00
Major refactoring, multisampling
This commit is contained in:
parent
c46ab39d1e
commit
069f7b0caf
1147
basegraph.cpp
Normal file
1147
basegraph.cpp
Normal file
File diff suppressed because it is too large
Load Diff
12
cell.cpp
12
cell.cpp
@ -1501,17 +1501,7 @@ void clearCellMemory() {
|
||||
allmaps.clear();
|
||||
}
|
||||
|
||||
void clearMemory() {
|
||||
extern void clearGameMemory();
|
||||
clearGameMemory();
|
||||
shmup::clearMemory();
|
||||
cleargraphmemory();
|
||||
#ifndef NOEDIT
|
||||
mapeditor::clearModelCells();
|
||||
#endif
|
||||
clearCellMemory();
|
||||
DEBMEM ( printf("ok\n"); )
|
||||
}
|
||||
auto cellhooks = addHook(clearmemory, 500, clearCellMemory);
|
||||
|
||||
int getHemisphere(cell *c, int which) {
|
||||
if(torus) return 0;
|
||||
|
14
complex.cpp
14
complex.cpp
@ -2761,3 +2761,17 @@ namespace ca {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto ccm = addHook(clearmemory, 0, [] () {
|
||||
offscreen.clear();
|
||||
princess::clear();
|
||||
mirrors.clear();
|
||||
clearing::bpdata.clear();
|
||||
tortoise::emap.clear();
|
||||
tortoise::babymap.clear();
|
||||
prairie::lasttreasure = NULL;
|
||||
prairie::enter = NULL;
|
||||
prairie::tchoices.clear();
|
||||
prairie::beaststogen.clear();
|
||||
});
|
||||
|
||||
|
1008
config.cpp
Normal file
1008
config.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,5 @@
|
||||
// Hyperbolic Rogue -- the conformal/history mode
|
||||
// Copyright (C) 2011-2016 Zeno Rogue, see 'hyper.cpp' for details
|
||||
#include <complex>
|
||||
|
||||
namespace polygonal {
|
||||
|
||||
@ -11,8 +10,6 @@ namespace polygonal {
|
||||
|
||||
int deg = 20;
|
||||
|
||||
#define MSI 120
|
||||
|
||||
ld matrix[MSI][MSI];
|
||||
ld ans[MSI];
|
||||
|
||||
@ -227,8 +224,15 @@ bool isbad(ld z) { return !isfinite(z) || fabs(z) > 1e6; }
|
||||
|
||||
namespace conformal {
|
||||
|
||||
void handleKeyC(int sym, int uni);
|
||||
|
||||
int lastprogress;
|
||||
|
||||
void progress_screen() {
|
||||
gamescreen(0);
|
||||
mouseovers = "";
|
||||
}
|
||||
|
||||
void progress(string str) {
|
||||
#ifndef NOSDL
|
||||
int tick = SDL_GetTicks();
|
||||
@ -429,9 +433,9 @@ namespace conformal {
|
||||
int siz = size(v);
|
||||
for(int j=1; j<siz-1; j++) {
|
||||
SDL_Surface *buffer = s;
|
||||
emtype cm = cmode;
|
||||
s = sav;
|
||||
cmode = emProgress;
|
||||
|
||||
pushScreen(progress_screen);
|
||||
|
||||
char buf[128];
|
||||
sprintf(buf, "#%03d", segid);
|
||||
@ -440,7 +444,6 @@ namespace conformal {
|
||||
calcparam();
|
||||
vid.radius = bandhalf;
|
||||
|
||||
cmode = cm;
|
||||
s = buffer;
|
||||
viewctr.h = v[j]->base->master;
|
||||
viewctr.spin = 0;
|
||||
@ -462,6 +465,8 @@ namespace conformal {
|
||||
|
||||
int bwidth = x-bandhalf;
|
||||
|
||||
popScreen();
|
||||
|
||||
drawsegment:
|
||||
|
||||
for(int cy=0; cy<bandfull; cy++) for(int cx=0; cx<bwidth; cx++)
|
||||
@ -572,10 +577,12 @@ namespace conformal {
|
||||
dialog::addItem(XLAT("exit this menu"), 'q');
|
||||
dialog::display();
|
||||
mouseovers = XLAT("see http://www.roguetemple.com/z/hyper/conformal.php");
|
||||
keyhandler = handleKeyC;
|
||||
}
|
||||
|
||||
int ib = 0;
|
||||
ld compbuf;
|
||||
|
||||
void applyIB() {
|
||||
using namespace polygonal;
|
||||
cld& tgt = coef[coefid];
|
||||
@ -583,7 +590,7 @@ namespace conformal {
|
||||
if(ib == 2) tgt = cld(real(tgt), compbuf);
|
||||
}
|
||||
|
||||
void handleKey(int sym, int uni) {
|
||||
void handleKeyC(int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
ib = 0;
|
||||
|
||||
@ -624,7 +631,7 @@ namespace conformal {
|
||||
dialog::sidedialog = true;
|
||||
}
|
||||
else if(sym == 'n' && pmodel == mdPolygonal) {
|
||||
dialog::editNumber(polygonal::deg, 2, MSI-1, 1, 2, XLAT("degree of the approximation"), "");
|
||||
dialog::editNumber(polygonal::deg, 2, polygonal::MSI-1, 1, 2, XLAT("degree of the approximation"), "");
|
||||
dialog::sidedialog = true;
|
||||
}
|
||||
else if(sym == 'x' && pmodel == mdPolynomial) {
|
||||
@ -642,7 +649,7 @@ namespace conformal {
|
||||
ib = 2;
|
||||
}
|
||||
else if(sym == 'n' && pmodel == mdPolynomial)
|
||||
dialog::editNumber(polygonal::coefid, 0, MSI-1, 1, 0, XLAT("which coefficient"), "");
|
||||
dialog::editNumber(polygonal::coefid, 0, polygonal::MSI-1, 1, 0, XLAT("which coefficient"), "");
|
||||
else if(sym == 'r') rotation += (shiftmul > 0 ? 1:3);
|
||||
else if(sym == 'a')
|
||||
dialog::editNumber(lvspeed, -5, 5, .1, 1, XLAT("animation speed"), "");
|
||||
@ -654,7 +661,6 @@ namespace conformal {
|
||||
#ifndef NOSDL
|
||||
else if(uni == 'f' && pmodel == mdBand && on) createImage(dospiral);
|
||||
#endif
|
||||
else if(sym == 'q' || sym == SDLK_ESCAPE || sym == '0') { cmode = emNormal; }
|
||||
else if(sym == 'i') {
|
||||
if(canmove && !cheater) {
|
||||
addMessage("Enable cheat mode or GAME OVER to use this");
|
||||
@ -666,6 +672,7 @@ namespace conformal {
|
||||
else if(sym == 'j') {
|
||||
autobandhistory = !autobandhistory;
|
||||
}
|
||||
else if(doexiton(sym, uni)) popScreen();
|
||||
}
|
||||
|
||||
void restore() {
|
||||
@ -718,5 +725,15 @@ namespace conformal {
|
||||
pmodel = spm;
|
||||
includeHistory = ih;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
auto hooks = addHook(clearmemory, 0, [] () {
|
||||
conformal::renderAutoband();
|
||||
conformal::on = false;
|
||||
conformal::killhistory.clear();
|
||||
conformal::findhistory.clear();
|
||||
conformal::movehistory.clear();
|
||||
conformal::includeHistory = false;
|
||||
});
|
||||
|
||||
}
|
||||
|
778
control.cpp
Normal file
778
control.cpp
Normal file
@ -0,0 +1,778 @@
|
||||
int frames;
|
||||
bool outoffocus = false;
|
||||
|
||||
int mousex, mousey, joyx, joyy, panjoyx, panjoyy;
|
||||
hyperpoint mouseh, mouseoh;
|
||||
|
||||
bool leftclick, rightclick, targetclick, hiliteclick, anyshiftclick, wheelclick,
|
||||
forcetarget, lshiftclick, lctrlclick;
|
||||
bool gtouched;
|
||||
|
||||
int getcstat, lgetcstat; ld getcshift; bool inslider;
|
||||
|
||||
int andmode = 0;
|
||||
|
||||
// is the player using mouse? (used for auto-cross)
|
||||
bool mousing = true;
|
||||
|
||||
// is the mouse button pressed?
|
||||
bool mousepressed = false;
|
||||
bool mousemoved = false;
|
||||
bool actonrelease = false;
|
||||
|
||||
ld shiftmul = 1;
|
||||
|
||||
cell *mouseover, *mouseover2, *lmouseover, *centerover;
|
||||
ld modist, modist2, centdist;
|
||||
movedir mousedest, joydir;
|
||||
|
||||
int lastt;
|
||||
|
||||
#ifdef WEB
|
||||
Uint8 *SDL_GetKeyState(void *v) { static Uint8 tab[1024]; return tab; }
|
||||
#endif
|
||||
|
||||
bool quitsaves() { return (items[itOrbSafety] && havesave); }
|
||||
|
||||
bool needConfirmation() {
|
||||
return canmove && (gold() >= 30 || tkills() >= 50) && !cheater && !quitsaves();
|
||||
}
|
||||
|
||||
bool mouseout() {
|
||||
if((getcstat != '-' && getcstat) || (lgetcstat && lgetcstat != '-')) return true;
|
||||
return outofmap(mouseh);
|
||||
}
|
||||
|
||||
bool mouseout2() {
|
||||
if((getcstat && getcstat != '-') || (lgetcstat && lgetcstat != '-')) return true;
|
||||
return outofmap(mouseh) || outofmap(mouseoh);
|
||||
}
|
||||
|
||||
movedir vectodir(const hyperpoint& P) {
|
||||
|
||||
hyperpoint H = sphereflip * tC0(cwtV);
|
||||
ld R = sqrt(H[0] * H[0] + H[1] * H[1]);
|
||||
transmatrix Centered = sphereflip * cwtV;
|
||||
if(!euclid)
|
||||
Centered = gpushxto0(H) * Centered;
|
||||
else if(R > 1e-9)
|
||||
Centered = eupush(-H[0], -H[1]) * Centered;
|
||||
ld binv = 99;
|
||||
|
||||
ld dirdist[7];
|
||||
for(int i=0; i<cwt.c->type; i++) {
|
||||
dirdist[i] = intval(Centered * xspinpush0(-i * 2 * M_PI /cwt.c->type, .5), P);
|
||||
}
|
||||
|
||||
movedir res;
|
||||
res.d = -1;
|
||||
|
||||
for(int i=0; i<cwt.c->type; i++) {
|
||||
if(dirdist[i] < binv) {
|
||||
binv = dirdist[i];
|
||||
res.d = i;
|
||||
res.subdir = dirdist[(i+1)%cwt.c->type] < dirdist[(i+cwt.c->type-1)%cwt.c->type] ? 1 : -1;
|
||||
if(sphere) res.subdir = -res.subdir;
|
||||
}
|
||||
}
|
||||
|
||||
// if(euclid) bdir = (bdir + 3) % 6;
|
||||
return res;
|
||||
}
|
||||
|
||||
void movepckeydir(int d) {
|
||||
DEBB(DF_GRAPH, (debugfile,"movepckeydir\n"));
|
||||
// EUCLIDEAN
|
||||
|
||||
movedir md =
|
||||
vectodir(spin(-d * M_PI/4) * tC0(pushone()));
|
||||
|
||||
movepcto(md);
|
||||
}
|
||||
|
||||
void calcMousedest() {
|
||||
if(mouseout()) return;
|
||||
if(vid.revcontrol == true) { mouseh[0] = -mouseh[0]; mouseh[1] = -mouseh[1]; }
|
||||
ld mousedist = intval(mouseh, tC0(shmup::ggmatrix(cwt.c)));
|
||||
mousedest.d = -1;
|
||||
|
||||
cellwalker bcwt = cwt;
|
||||
|
||||
ld dists[7];
|
||||
|
||||
for(int i=0; i<cwt.c->type; i++)
|
||||
dists[i] = intval(mouseh, tC0(shmup::ggmatrix(cwt.c->mov[i])));
|
||||
|
||||
/* printf("curcell = %Lf\n", mousedist);
|
||||
for(int i=0; i<cwt.c->type; i++)
|
||||
printf("d%d = %Lf\n", i, dists[i]); */
|
||||
|
||||
for(int i=0; i<cwt.c->type; i++) if(dists[i] < mousedist) {
|
||||
mousedist = dists[i];
|
||||
mousedest.d = fixdir(i - cwt.spin, cwt.c);
|
||||
|
||||
mousedest.subdir =
|
||||
dists[(i+1)%cwt.c->type] < dists[(i+cwt.c->type-1)%cwt.c->type] ? 1 : -1;
|
||||
|
||||
if(cwt.mirrored)
|
||||
mousedest.d = fixdir(-mousedest.d, cwt.c),
|
||||
mousedest.subdir = -mousedest.subdir;
|
||||
|
||||
if(sphere) mousedest.subdir = -mousedest.subdir;
|
||||
}
|
||||
|
||||
if(vid.revcontrol == true) { mouseh[0] = -mouseh[0]; mouseh[1] = -mouseh[1]; }
|
||||
cwt = bcwt;
|
||||
}
|
||||
|
||||
void mousemovement() {
|
||||
calcMousedest();
|
||||
movepcto(mousedest);
|
||||
lmouseover = NULL;
|
||||
}
|
||||
|
||||
#ifndef NOSDL
|
||||
SDL_Joystick* sticks[8];
|
||||
int numsticks;
|
||||
|
||||
void initJoysticks() {
|
||||
DEBB(DF_INIT, (debugfile,"init joysticks\n"));
|
||||
numsticks = SDL_NumJoysticks();
|
||||
if(numsticks > 8) numsticks = 8;
|
||||
for(int i=0; i<numsticks; i++) {
|
||||
sticks[i] = SDL_JoystickOpen(i);
|
||||
/* printf("axes = %d, balls = %d, buttons = %d, hats = %d\n",
|
||||
SDL_JoystickNumAxes(sticks[i]),
|
||||
SDL_JoystickNumBalls(sticks[i]),
|
||||
SDL_JoystickNumButtons(sticks[i]),
|
||||
SDL_JoystickNumHats(sticks[i])
|
||||
); */
|
||||
}
|
||||
}
|
||||
|
||||
void closeJoysticks() {
|
||||
DEBB(DF_INIT, (debugfile,"close joysticks\n"));
|
||||
for(int i=0; i<numsticks; i++) {
|
||||
SDL_JoystickClose(sticks[i]), sticks[i] = NULL;
|
||||
}
|
||||
numsticks = 0;
|
||||
}
|
||||
|
||||
void checkjoy() {
|
||||
DEBB(DF_GRAPH, (debugfile,"check joy\n"));
|
||||
if(!DEFAULTCONTROL) return;
|
||||
ld joyvalue1 = sqr(vid.joyvalue);
|
||||
ld joyvalue2 = sqr(vid.joyvalue2);
|
||||
|
||||
ld jx = joyx;
|
||||
ld jy = joyy;
|
||||
ld sq = jx*jx+jy*jy;
|
||||
|
||||
static int laststate = 0;
|
||||
int curstate = sq < joyvalue1 ? 0 : sq < joyvalue2 ? 1 : 2;
|
||||
if(curstate != laststate) flashMessages(), laststate = curstate;
|
||||
|
||||
if(autojoy) {
|
||||
if(sq < joyvalue1) { if(joydir.d >= 0) movepcto(joydir); joydir.d = -1; return; }
|
||||
if(sq < joyvalue2 && joydir.d == -1) return;
|
||||
}
|
||||
else {
|
||||
if(sq < joyvalue1) { joydir.d = -1; return; }
|
||||
}
|
||||
|
||||
joydir = vectodir(hpxy(jx, jy));
|
||||
}
|
||||
|
||||
void checkpanjoy(double t) {
|
||||
|
||||
if(shmup::on) return;
|
||||
|
||||
if(vid.joypanspeed < 1e-7) return;
|
||||
|
||||
if(sqr(panjoyx) + sqr(panjoyy) < sqr(vid.joypanthreshold))
|
||||
return;
|
||||
|
||||
ld jx = panjoyx * t * vid.joypanspeed;
|
||||
ld jy = panjoyy * t * vid.joypanspeed;
|
||||
|
||||
playermoved = false;
|
||||
View = gpushxto0(hpxy(jx, jy)) * View;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool quitmainloop = false;
|
||||
|
||||
bool doexiton(int sym, int uni) {
|
||||
if(sym == SDLK_ESCAPE) return true;
|
||||
if(sym == SDLK_F10) return true;
|
||||
if(uni != 0) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void handleKeyQuit(int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
// ignore the camera movement keys
|
||||
|
||||
#ifndef NORUG
|
||||
if(rug::rugged && (sym == SDLK_UP || sym == SDLK_DOWN || sym == SDLK_PAGEUP || sym == SDLK_PAGEDOWN ||
|
||||
sym == SDLK_RIGHT || sym == SDLK_LEFT))
|
||||
sym = 0;
|
||||
#endif
|
||||
|
||||
if(sym == SDLK_RETURN || sym == SDLK_KP_ENTER || sym == SDLK_F10) quitmainloop = true;
|
||||
else if(uni == 'r' || sym == SDLK_F5) {
|
||||
restartGame(), popScreen();
|
||||
msgs.clear();
|
||||
}
|
||||
else if(sym == SDLK_UP || sym == SDLK_KP8 || sym == PSEUDOKEY_WHEELUP) msgscroll++;
|
||||
else if(sym == SDLK_DOWN || sym == SDLK_KP2 || sym == PSEUDOKEY_WHEELDOWN) msgscroll--;
|
||||
else if(sym == SDLK_PAGEUP || sym == SDLK_KP9) msgscroll+=5;
|
||||
else if(sym == SDLK_PAGEDOWN || sym == SDLK_KP3) msgscroll-=5;
|
||||
else if(uni == 'v') popScreenAll(), pushScreen(showMainMenu);
|
||||
else if(sym == SDLK_F3 || (sym == ' ' || sym == SDLK_HOME))
|
||||
fullcenter();
|
||||
else if(uni == 'o' && DEFAULTNOR(sym)) setAppropriateOverview();
|
||||
#ifdef INV
|
||||
else if(uni == 'i' && DEFAULTNOR(sym) && inv::on)
|
||||
pushScreen(inv::show);
|
||||
#endif
|
||||
#ifndef NOSAVE
|
||||
else if(uni == 't') {
|
||||
if(!canmove) restartGame();
|
||||
loadScores();
|
||||
msgs.clear();
|
||||
}
|
||||
#endif
|
||||
|
||||
else if(doexiton(sym, uni) && !didsomething) {
|
||||
popScreen();
|
||||
msgscroll = 0;
|
||||
msgs.clear();
|
||||
if(!canmove) {
|
||||
addMessage(XLAT("GAME OVER"));
|
||||
addMessage(timeline());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool didsomething;
|
||||
|
||||
#ifdef MOBILE
|
||||
typedef int eventtype;
|
||||
#else
|
||||
typedef SDL_Event eventtype;
|
||||
#endif
|
||||
|
||||
void handlePanning(int sym, int uni) {
|
||||
if(rug::rugged) return;
|
||||
|
||||
#ifndef PANDORA
|
||||
if(sym == SDLK_RIGHT) {
|
||||
if(conformal::on)
|
||||
conformal::lvspeed += 0.1 * shiftmul;
|
||||
else
|
||||
View = xpush(-0.2*shiftmul) * View, playermoved = false, didsomething = true;
|
||||
}
|
||||
if(sym == SDLK_LEFT) {
|
||||
if(conformal::on)
|
||||
conformal::lvspeed -= 0.1 * shiftmul;
|
||||
else
|
||||
View = xpush(+0.2*shiftmul) * View, playermoved = false, didsomething = true;
|
||||
}
|
||||
if(sym == SDLK_UP) {
|
||||
if(conformal::on)
|
||||
conformal::lvspeed += 0.1 * shiftmul;
|
||||
else
|
||||
View = ypush(+0.2*shiftmul) * View, playermoved = false, didsomething = true;
|
||||
}
|
||||
if(sym == SDLK_DOWN) {
|
||||
if(conformal::on)
|
||||
conformal::lvspeed -= 0.1 * shiftmul;
|
||||
else
|
||||
View = ypush(-0.2*shiftmul) * View, playermoved = false, didsomething = true;
|
||||
}
|
||||
#endif
|
||||
if(sym == SDLK_PAGEUP) {
|
||||
if(conformal::on)
|
||||
conformal::rotation++;
|
||||
else
|
||||
View = spin(M_PI/S21*shiftmul) * View, didsomething = true;
|
||||
}
|
||||
if(sym == SDLK_PAGEDOWN) {
|
||||
if(conformal::on)
|
||||
conformal::rotation++;
|
||||
else
|
||||
View = spin(-M_PI/S21*shiftmul) * View, didsomething = true;
|
||||
}
|
||||
|
||||
if(sym == SDLK_PAGEUP || sym == SDLK_PAGEDOWN)
|
||||
if(isGravityLand(cwt.c->land)) playermoved = false;
|
||||
|
||||
if(sym == PSEUDOKEY_WHEELUP) {
|
||||
ld jx = (mousex - vid.xcenter - .0) / vid.radius / 10;
|
||||
ld jy = (mousey - vid.ycenter - .0) / vid.radius / 10;
|
||||
playermoved = false;
|
||||
View = gpushxto0(hpxy(jx, jy)) * View;
|
||||
sym = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void handleKeyNormal(int sym, int uni) {
|
||||
|
||||
if(cheater) {
|
||||
if(applyCheat(uni, mouseover))
|
||||
sym = 0;
|
||||
}
|
||||
|
||||
if(DEFAULTNOR(sym)) handlePanning(sym, uni);
|
||||
|
||||
if(!(uni >= 'A' && uni <= 'Z') && DEFAULTCONTROL) {
|
||||
if(sym == 'l' || sym == 'd' || sym == SDLK_KP6) movepckeydir(0);
|
||||
if(sym == 'n' || sym == 'c' || sym == SDLK_KP3) movepckeydir(1);
|
||||
if(sym == 'j' || sym == 'x' || sym == SDLK_KP2) movepckeydir(2);
|
||||
if(sym == 'b' || sym == 'z' || sym == SDLK_KP1) movepckeydir(3);
|
||||
if(sym == 'h' || sym == 'a' || sym == SDLK_KP4) movepckeydir(4);
|
||||
if(sym == 'y' || sym == 'q' || sym == SDLK_KP7) movepckeydir(5);
|
||||
if(sym == 'k' || sym == 'w' || sym == SDLK_KP8) movepckeydir(6);
|
||||
if(sym == 'u' || sym == 'e' || sym == SDLK_KP9) movepckeydir(7);
|
||||
}
|
||||
|
||||
#ifdef PANDORA
|
||||
if(DEFAULTCONTROL) {
|
||||
if(sym == SDLK_RIGHT) movepckeydir(0);
|
||||
if(sym == SDLK_LEFT) movepckeydir(4);
|
||||
if(sym == SDLK_DOWN) movepckeydir(2 + (leftclick?1:0) - (rightclick?1:0));
|
||||
if(sym == SDLK_UP) movepckeydir(6 - (leftclick?1:0) + (rightclick?1:0));
|
||||
}
|
||||
#endif
|
||||
|
||||
if(uni == sym && DEFAULTNOR(sym)) {
|
||||
gmodekeys(sym, uni);
|
||||
if(sym == '8') {
|
||||
backcolor = backcolor ^ 0xFFFFFF;
|
||||
bordcolor = bordcolor ^ 0xFFFFFF;
|
||||
forecolor = forecolor ^ 0xFFFFFF;
|
||||
printf("back = %x\n", backcolor);
|
||||
}
|
||||
if(sym == '9') {
|
||||
pmodel = eModel(8 - pmodel);
|
||||
// vid.yshift = 1 - vid.yshift;
|
||||
// vid.drawmousecircle = true;
|
||||
}
|
||||
if(sym == 'm' && canmove && cmode2 == smNormal && (centerover == cwt.c ? mouseover : centerover))
|
||||
performMarkCommand(mouseover);
|
||||
}
|
||||
|
||||
if(DEFAULTCONTROL) {
|
||||
if(sym == '.' || sym == 's') movepcto(-1, 1);
|
||||
if((sym == SDLK_DELETE || sym == SDLK_KP_PERIOD || sym == 'g') && uni != 'G' && uni != 'G'-64)
|
||||
movepcto(MD_DROP, 1);
|
||||
if(sym == 't' && uni != 'T' && uni != 'T'-64 && canmove && cmode2 == smNormal) {
|
||||
if(playermoved && items[itStrongWind]) {
|
||||
cell *c = whirlwind::jumpDestination(cwt.c);
|
||||
if(c) centerover = c;
|
||||
}
|
||||
targetRangedOrb(centerover, roKeyboard);
|
||||
sym = 0; uni = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(sym == SDLK_KP5 && DEFAULTCONTROL) movepcto(-1, 1);
|
||||
|
||||
// if(sym == SDLK_F4) restartGameSwitchEuclid();
|
||||
|
||||
if(sym == SDLK_F5) {
|
||||
if(needConfirmation())
|
||||
pushScreen(showMission);
|
||||
else restartGame();
|
||||
}
|
||||
|
||||
if(sym == SDLK_ESCAPE)
|
||||
showMissionScreen();
|
||||
|
||||
if(sym == SDLK_F10) {
|
||||
if(needConfirmation()) pushScreen(showMission);
|
||||
else quitmainloop = true;
|
||||
}
|
||||
|
||||
if(!canmove) {
|
||||
if(sym == SDLK_RETURN || sym == SDLK_KP_ENTER) quitmainloop = true;
|
||||
else if(uni == 'r') restartGame();
|
||||
#ifndef NOSAVE
|
||||
else if(uni == 't') {
|
||||
restartGame();
|
||||
loadScores();
|
||||
}
|
||||
#endif
|
||||
#ifndef NORUG
|
||||
else if(rug::rugged) ;
|
||||
#endif
|
||||
else if(sym == SDLK_UP || sym == SDLK_KP8) msgscroll++;
|
||||
else if(sym == SDLK_DOWN || sym == SDLK_KP2) msgscroll--;
|
||||
else if(sym == SDLK_PAGEUP || sym == SDLK_KP9) msgscroll+=5;
|
||||
else if(sym == SDLK_PAGEDOWN || sym == SDLK_KP3) msgscroll-=5;
|
||||
}
|
||||
|
||||
if(uni == 'o' && DEFAULTNOR(sym)) setAppropriateOverview();
|
||||
#ifdef INV
|
||||
if(uni == 'i' && DEFAULTNOR(sym) && inv::on)
|
||||
pushScreen(inv::show);
|
||||
#endif
|
||||
|
||||
if((sym == SDLK_HOME || sym == SDLK_F3 || sym == ' ') && DEFAULTNOR(sym))
|
||||
fullcenter();
|
||||
|
||||
if(sym == 'v' && DEFAULTNOR(sym))
|
||||
pushScreen(showMainMenu);
|
||||
|
||||
if(sym == '-' || sym == PSEUDOKEY_WHEELDOWN) {
|
||||
actonrelease = false;
|
||||
|
||||
shmup::cpid = 0;
|
||||
if(mouseover &&
|
||||
targetclick && (!shmup::on || numplayers() == 1) && targetRangedOrb(mouseover, forcetarget ? roMouseForce : roMouse)) {
|
||||
}
|
||||
else if(forcetarget)
|
||||
;
|
||||
else if(!DEFAULTCONTROL) {
|
||||
if(!shmup::on)
|
||||
multi::mousemovement(mouseover);
|
||||
}
|
||||
else mousemovement();
|
||||
}
|
||||
|
||||
if(sym == SDLK_F1) gotoHelp(help);
|
||||
|
||||
#ifdef ROGUEVIZ
|
||||
rogueviz::processKey(sym, uni);
|
||||
#endif
|
||||
}
|
||||
|
||||
void handlekey(int sym, int uni) {
|
||||
|
||||
if(callhandlers(false, hooks_handleKey, sym, uni)) return;
|
||||
|
||||
keyhandler(sym, uni);
|
||||
}
|
||||
|
||||
#ifdef NOSDL
|
||||
void mainloopiter() { printf("(compiled without SDL -- no action)\n"); quitmainloop = true; }
|
||||
#else
|
||||
|
||||
// Warning: a very long function! todo: refactor
|
||||
|
||||
int cframelimit = 1000;
|
||||
|
||||
void mainloopiter() {
|
||||
|
||||
DEBB(DF_GRAPH, (debugfile,"main loop\n"));
|
||||
|
||||
#ifndef GFX
|
||||
#ifndef GL
|
||||
vid.wallmode = 0;
|
||||
vid.monmode = 0;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
optimizeview();
|
||||
|
||||
if(conformal::on) conformal::apply();
|
||||
|
||||
ticks = SDL_GetTicks();
|
||||
|
||||
int timetowait = lastt + 1000 / cframelimit - ticks;
|
||||
|
||||
cframelimit = vid.framelimit;
|
||||
if(outoffocus && cframelimit > 10) cframelimit = 10;
|
||||
|
||||
if(DOSHMUP && cmode2 == smNormal)
|
||||
timetowait = 0, shmup::turn(ticks - lastt);
|
||||
|
||||
if(!DOSHMUP && (multi::alwaysuse || multi::players > 1) && cmode2 == smNormal)
|
||||
timetowait = 0, multi::handleMulti(ticks - lastt);
|
||||
|
||||
if(vid.sspeed >= 5 && gmatrix.count(cwt.c) && !elliptic) {
|
||||
cwtV = gmatrix[cwt.c] * ddspin(cwt.c, cwt.spin);
|
||||
if(cwt.mirrored) playerV = playerV * Mirror;
|
||||
}
|
||||
|
||||
#ifdef WEB
|
||||
if(playermoved && vid.sspeed > -4.99 && !outoffocus) {
|
||||
centerpc((ticks - lastt) / 1000.0 * exp(vid.sspeed));
|
||||
}
|
||||
if(!outoffocus) drawscreen();
|
||||
#else
|
||||
if(timetowait > 0)
|
||||
SDL_Delay(timetowait);
|
||||
else {
|
||||
if(cmode2 == smNormal) {
|
||||
if(playermoved && vid.sspeed > -4.99 && !outoffocus)
|
||||
centerpc((ticks - lastt) / 1000.0 * exp(vid.sspeed));
|
||||
if(panjoyx || panjoyy)
|
||||
checkpanjoy((ticks - lastt) / 1000.0);
|
||||
}
|
||||
tortoise::updateVals(ticks - lastt);
|
||||
frames++;
|
||||
if(!outoffocus) {
|
||||
drawscreen();
|
||||
}
|
||||
lastt = ticks;
|
||||
}
|
||||
#endif
|
||||
|
||||
Uint8 *keystate = SDL_GetKeyState(NULL);
|
||||
rightclick = keystate[SDLK_RCTRL];
|
||||
leftclick = keystate[SDLK_RSHIFT];
|
||||
lctrlclick = keystate[SDLK_LCTRL];
|
||||
lshiftclick = keystate[SDLK_LSHIFT];
|
||||
forcetarget = (keystate[SDLK_RSHIFT] | keystate[SDLK_LSHIFT]);
|
||||
hiliteclick = keystate[SDLK_LALT] | keystate[SDLK_RALT];
|
||||
anyshiftclick = keystate[SDLK_LSHIFT] | keystate[SDLK_RSHIFT];
|
||||
wheelclick = false;
|
||||
|
||||
getcshift = 1;
|
||||
if(keystate[SDLK_LSHIFT] || keystate[SDLK_RSHIFT]) getcshift = -1;
|
||||
if(keystate[SDLK_LCTRL] || keystate[SDLK_RCTRL]) getcshift /= 10;
|
||||
if(keystate[SDLK_LALT] || keystate[SDLK_RALT]) getcshift *= 10;
|
||||
|
||||
didsomething = false;
|
||||
|
||||
if(vid.shifttarget&1) {
|
||||
leftclick = false;
|
||||
targetclick = keystate[SDLK_RSHIFT] | keystate[SDLK_LSHIFT];
|
||||
}
|
||||
else {
|
||||
leftclick = keystate[SDLK_RSHIFT];
|
||||
targetclick = true;
|
||||
}
|
||||
|
||||
#ifdef SDLAUDIO
|
||||
if(audio) handlemusic();
|
||||
#endif
|
||||
SDL_Event ev;
|
||||
DEBB(DF_GRAPH, (debugfile,"polling for events\n"));
|
||||
|
||||
achievement_pump();
|
||||
while(SDL_PollEvent(&ev)) {
|
||||
DEBB(DF_GRAPH, (debugfile,"got event type #%d\n", ev.type));
|
||||
int sym = 0;
|
||||
int uni = 0;
|
||||
shiftmul = 1;
|
||||
|
||||
/* if(ev.type == SDL_JOYDEVICEADDED || ev.type == SDL_JOYDEVICEREMOVED) {
|
||||
joyx = joyy = 0;
|
||||
panjoyx = panjoyy = 0;
|
||||
closeJoysticks();
|
||||
initJoysticks();
|
||||
}*/
|
||||
|
||||
if(ev.type == SDL_ACTIVEEVENT) {
|
||||
if(ev.active.state & SDL_APPINPUTFOCUS) {
|
||||
if(ev.active.gain) {
|
||||
outoffocus = false;
|
||||
}
|
||||
else {
|
||||
outoffocus = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(ev.type == SDL_VIDEORESIZE) {
|
||||
vid.xres = ev.resize.w;
|
||||
vid.yres = ev.resize.h;
|
||||
vid.killreduction = 0;
|
||||
extern bool setfsize;
|
||||
setfsize = true;
|
||||
setvideomode();
|
||||
#ifdef GL
|
||||
if(vid.usingGL) glViewport(0, 0, vid.xres, vid.yres);
|
||||
#endif
|
||||
}
|
||||
|
||||
if(ev.type == SDL_VIDEOEXPOSE) {
|
||||
drawscreen();
|
||||
}
|
||||
|
||||
if(ev.type == SDL_JOYAXISMOTION) {
|
||||
if(ev.jaxis.which == 0) {
|
||||
if(ev.jaxis.axis == 0)
|
||||
joyx = ev.jaxis.value;
|
||||
else if(ev.jaxis.axis == 1)
|
||||
joyy = ev.jaxis.value;
|
||||
else if(ev.jaxis.axis == 3)
|
||||
panjoyx = ev.jaxis.value;
|
||||
else if(ev.jaxis.axis == 4)
|
||||
panjoyy = ev.jaxis.value;
|
||||
checkjoy();
|
||||
// printf("panjoy = %d,%d\n", panjoyx, panjoyy);
|
||||
}
|
||||
else {
|
||||
if(ev.jaxis.axis == 0)
|
||||
panjoyx = ev.jaxis.value;
|
||||
else
|
||||
panjoyy = ev.jaxis.value;
|
||||
}
|
||||
}
|
||||
|
||||
if(ev.type == SDL_JOYBUTTONDOWN && cmode2 == smShmupConfig && vid.scfg.setwhat) {
|
||||
int joyid = ev.jbutton.which;
|
||||
int button = ev.jbutton.button;
|
||||
if(joyid < 8 && button < 32)
|
||||
vid.scfg.joyaction[joyid][button] = vid.scfg.setwhat;
|
||||
vid.scfg.setwhat = 0;
|
||||
}
|
||||
|
||||
else if(ev.type == SDL_JOYHATMOTION && cmode2 == smShmupConfig && vid.scfg.setwhat) {
|
||||
int joyid = ev.jhat.which;
|
||||
int hat = ev.jhat.hat;
|
||||
int dir = 4;
|
||||
if(ev.jhat.value == SDL_HAT_UP) dir = 0;
|
||||
if(ev.jhat.value == SDL_HAT_RIGHT) dir = 1;
|
||||
if(ev.jhat.value == SDL_HAT_DOWN) dir = 2;
|
||||
if(ev.jhat.value == SDL_HAT_LEFT) dir = 3;
|
||||
if(joyid < 8 && hat < 4 && dir < 4) {
|
||||
vid.scfg.hataction[joyid][hat][dir] = vid.scfg.setwhat;
|
||||
vid.scfg.setwhat = 0;
|
||||
}
|
||||
}
|
||||
|
||||
else if(ev.type == SDL_JOYBUTTONDOWN && DEFAULTCONTROL) {
|
||||
flashMessages();
|
||||
movepcto(joydir);
|
||||
checkjoy();
|
||||
}
|
||||
|
||||
if(ev.type == SDL_KEYDOWN) {
|
||||
flashMessages();
|
||||
mousing = false;
|
||||
sym = ev.key.keysym.sym;
|
||||
uni = ev.key.keysym.unicode;
|
||||
if(ev.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT)) shiftmul = -1;
|
||||
if(ev.key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) shiftmul /= 10;
|
||||
if(sym == SDLK_RETURN && (ev.key.keysym.mod & (KMOD_LALT | KMOD_RALT))) {
|
||||
sym = 0; uni = 0;
|
||||
switchFullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
dialog::handleZooming(ev);
|
||||
|
||||
if(sym == SDLK_F1 && cmode2 == smNormal && playermoved)
|
||||
help = "@";
|
||||
|
||||
bool rollchange =
|
||||
cmode2 == smOverview && getcstat >= 2000 && cheater;
|
||||
|
||||
if(ev.type == SDL_MOUSEBUTTONDOWN) {
|
||||
flashMessages();
|
||||
mousepressed = true;
|
||||
mousing = true;
|
||||
actonrelease = true;
|
||||
|
||||
if(ev.button.button==SDL_BUTTON_WHEELDOWN) {
|
||||
sym = uni = PSEUDOKEY_WHEELDOWN;
|
||||
}
|
||||
if(ev.button.button==SDL_BUTTON_WHEELUP) {
|
||||
sym = uni = PSEUDOKEY_WHEELUP;
|
||||
}
|
||||
else if(ev.button.button == SDL_BUTTON_RIGHT) {
|
||||
sym = 1; didsomething = true;
|
||||
}
|
||||
else if(ev.button.button == SDL_BUTTON_MIDDLE) {
|
||||
sym = 2; didsomething = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(ev.type == SDL_MOUSEBUTTONUP) {
|
||||
mousepressed = false;
|
||||
mousing = true;
|
||||
if(ev.button.button==SDL_BUTTON_RIGHT || leftclick)
|
||||
sym = SDLK_F1;
|
||||
else if(ev.button.button==SDL_BUTTON_MIDDLE || rightclick)
|
||||
sym = 1, didsomething = true;
|
||||
else if(ev.button.button == SDL_BUTTON_LEFT && actonrelease) {
|
||||
sym = getcstat, uni = getcstat, shiftmul = getcshift;
|
||||
}
|
||||
else if(ev.button.button == SDL_BUTTON_WHEELUP && rollchange) {
|
||||
sym = getcstat, uni = getcstat, shiftmul = getcshift, wheelclick = true;
|
||||
}
|
||||
else if(ev.button.button == SDL_BUTTON_WHEELDOWN && rollchange) {
|
||||
sym = getcstat, uni = getcstat, shiftmul = -getcshift, wheelclick = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(ev.type == SDL_MOUSEMOTION) {
|
||||
mouseoh = mouseh;
|
||||
|
||||
mousing = true;
|
||||
mousemoved = true;
|
||||
mousex = ev.motion.x;
|
||||
mousey = ev.motion.y;
|
||||
|
||||
#ifndef NORUG
|
||||
if(rug::rugged)
|
||||
mouseh = rug::gethyper(mousex, mousey);
|
||||
else
|
||||
#endif
|
||||
mouseh = gethyper(mousex, mousey);
|
||||
|
||||
if((rightclick || (SDL_GetMouseState(NULL, NULL) & SDL_BUTTON_MMASK)) && !mouseout2() &&
|
||||
mouseh[2] < 50 && mouseoh[2] < 50) {
|
||||
panning(mouseoh, mouseh);
|
||||
}
|
||||
|
||||
#ifdef SIMULATE_JOYSTICK
|
||||
// pretend that both joysticks are present
|
||||
stick = panstick = (SDL_Joystick*) (&vid);
|
||||
panjoyx = 20 * (mousex - vid.xcenter);
|
||||
panjoyy = 20 * (mousey - vid.ycenter);
|
||||
checkjoy();
|
||||
#endif
|
||||
|
||||
if(mousepressed && inslider) {
|
||||
sym = getcstat, uni = getcstat, shiftmul = getcshift;
|
||||
}
|
||||
}
|
||||
|
||||
if(ev.type == SDL_QUIT) {
|
||||
if(needConfirmation() && cmode2 != smMission) showMissionScreen();
|
||||
else quitmainloop = true;
|
||||
}
|
||||
|
||||
handlekey(sym, uni);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void mainloop() {
|
||||
lastt = 0;
|
||||
#ifdef WEB
|
||||
initweb();
|
||||
emscripten_set_main_loop(mainloopiter, 0, true);
|
||||
#else
|
||||
while(!quitmainloop) mainloopiter();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MOBILE
|
||||
void displayabutton(int px, int py, string s, int col) {
|
||||
// TMP
|
||||
int siz = vid.yres > vid.xres ? vid.fsize*2 : vid.fsize * 3/2;
|
||||
int vrx = min(vid.radius, vid.xres/2 - 40);
|
||||
int vry = min(vid.radius, min(vid.ycenter, vid.yres - vid.ycenter) - 20);
|
||||
int x = vid.xcenter + px * vrx;
|
||||
int y = vid.ycenter + py * (vry - siz/2);
|
||||
int vrr = int(hypot(vrx, vry) * sqrt(2.));
|
||||
if(gtouched && !mouseover
|
||||
&& abs(mousex - vid.xcenter) < vrr
|
||||
&& abs(mousey - vid.ycenter) < vrr
|
||||
&& hypot(mousex-vid.xcenter, mousey-vid.ycenter) > vrr
|
||||
&& px == (mousex > vid.xcenter ? 1 : -1)
|
||||
&& py == (mousey > vid.ycenter ? 1 : -1)
|
||||
) col = 0xFF0000;
|
||||
if(displayfr(x, y, 0, siz, s, col, 8+8*px))
|
||||
buttonclicked = true;
|
||||
}
|
||||
#endif
|
||||
|
285
dialogs.cpp
285
dialogs.cpp
@ -386,7 +386,53 @@ namespace dialog {
|
||||
|
||||
int colorp = 0;
|
||||
|
||||
void drawColorDialog(int color) {
|
||||
int *colorPointer;
|
||||
|
||||
bool handleKeyColor(int sym, int uni) {
|
||||
int& color = *colorPointer;
|
||||
|
||||
if(uni >= 'A' && uni <= 'D') {
|
||||
int x = (mousex - vid.xres/4) * 510 / vid.xres;
|
||||
if(x < 0) x = 0;
|
||||
if(x > 255) x = 255;
|
||||
unsigned char* pts = (unsigned char*) &color;
|
||||
pts[uni - 'A'] = x;
|
||||
}
|
||||
else if(uni == ' ') {
|
||||
bool inHistory = false;
|
||||
for(int i=0; i<10; i++) if(colorhistory[i] == (unsigned) color)
|
||||
inHistory = true;
|
||||
if(!inHistory) { colorhistory[lch] = color; lch++; lch %= 10; }
|
||||
popScreen();
|
||||
}
|
||||
else if(uni >= '0' && uni <= '9') {
|
||||
color = colorhistory[uni - '0'];
|
||||
}
|
||||
else if(palette && uni >= 'a' && uni < 'a'+(int) palette[0]) {
|
||||
color = palette[1 + uni - 'a'];
|
||||
}
|
||||
else if(sym == SDLK_DOWN || sym == SDLK_KP2) {
|
||||
colorp = (colorp-1) & 3;
|
||||
}
|
||||
else if(sym == SDLK_UP || sym == SDLK_KP8) {
|
||||
colorp = (colorp+1) & 3;
|
||||
}
|
||||
else if(sym == SDLK_LEFT || sym == SDLK_KP4) {
|
||||
unsigned char* pts = (unsigned char*) &color;
|
||||
pts[colorp] -= abs(shiftmul) < .6 ? 1 : 17;
|
||||
}
|
||||
else if(sym == SDLK_RIGHT || sym == SDLK_KP6) {
|
||||
unsigned char* pts = (unsigned char*) &color;
|
||||
pts[colorp] += abs(shiftmul) < .6 ? 1 : 17;
|
||||
}
|
||||
else if(doexiton(sym, uni))
|
||||
popScreen();
|
||||
return false;
|
||||
}
|
||||
|
||||
void drawColorDialog() {
|
||||
int color = *colorPointer;
|
||||
|
||||
int ash = 8;
|
||||
|
||||
for(int j=0; j<10; j++) {
|
||||
@ -427,60 +473,13 @@ namespace dialog {
|
||||
}
|
||||
|
||||
displayColorButton(vid.xres/2, vid.yres/2+vid.fsize * 6, XLAT("select this color") + " : " + itsh(color), ' ', 8, 0, color >> ash);
|
||||
|
||||
keyhandler = handleKeyColor;
|
||||
}
|
||||
|
||||
// 0: nothing happened, 1: color accepted, 2: break
|
||||
int handleKeyColor(int sym, int uni, int& color) {
|
||||
|
||||
if(uni >= 'A' && uni <= 'D') {
|
||||
int x = (mousex - vid.xres/4) * 510 / vid.xres;
|
||||
if(x < 0) x = 0;
|
||||
if(x > 255) x = 255;
|
||||
unsigned char* pts = (unsigned char*) &color;
|
||||
pts[uni - 'A'] = x;
|
||||
}
|
||||
else if(uni == ' ') {
|
||||
bool inHistory = false;
|
||||
for(int i=0; i<10; i++) if(colorhistory[i] == (unsigned) color)
|
||||
inHistory = true;
|
||||
if(!inHistory) { colorhistory[lch] = color; lch++; lch %= 10; }
|
||||
return 1;
|
||||
}
|
||||
else if(uni >= '0' && uni <= '9') {
|
||||
color = colorhistory[uni - '0'];
|
||||
}
|
||||
else if(palette && uni >= 'a' && uni < 'a'+(int) palette[0]) {
|
||||
color = palette[1 + uni - 'a'];
|
||||
}
|
||||
else if(sym == SDLK_DOWN || sym == SDLK_KP2) {
|
||||
colorp = (colorp-1) & 3;
|
||||
}
|
||||
else if(sym == SDLK_UP || sym == SDLK_KP8) {
|
||||
colorp = (colorp+1) & 3;
|
||||
}
|
||||
else if(sym == SDLK_LEFT || sym == SDLK_KP4) {
|
||||
unsigned char* pts = (unsigned char*) &color;
|
||||
pts[colorp] -= abs(shiftmul) < .6 ? 1 : 17;
|
||||
}
|
||||
else if(sym == SDLK_RIGHT || sym == SDLK_KP6) {
|
||||
unsigned char* pts = (unsigned char*) &color;
|
||||
pts[colorp] += abs(shiftmul) < .6 ? 1 : 17;
|
||||
}
|
||||
else if(uni || sym == SDLK_F10) return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int *colorPointer;
|
||||
emtype lastmode;
|
||||
|
||||
void openColorDialog(int& col, unsigned int *pal) {
|
||||
colorPointer = &col; palette = pal;
|
||||
lastmode = cmode; cmode = emColor;
|
||||
}
|
||||
|
||||
void handleColor(int sym, int uni) {
|
||||
int ret = handleKeyColor(sym, uni, *colorPointer);
|
||||
if(ret) cmode = lastmode;
|
||||
pushScreen(drawColorDialog);
|
||||
}
|
||||
|
||||
struct numberEditor {
|
||||
@ -511,28 +510,6 @@ namespace dialog {
|
||||
ne.positive = true;
|
||||
}
|
||||
|
||||
void editNumber(ld& x, ld vmin, ld vmax, ld step, ld dft, string title, string help) {
|
||||
ne.editwhat = &x;
|
||||
ne.s = fts(x);
|
||||
ne.vmin = vmin;
|
||||
ne.vmax = vmax;
|
||||
ne.step = step;
|
||||
ne.dft = dft;
|
||||
ne.title = title;
|
||||
ne.help = help;
|
||||
lastmode = cmode; cmode = emNumber;
|
||||
ne.scale = ne.inverse_scale = identity;
|
||||
ne.intval = NULL;
|
||||
ne.positive = false;
|
||||
sidedialog = false;
|
||||
}
|
||||
|
||||
void editNumber(int& x, int vmin, int vmax, int step, int dft, string title, string help) {
|
||||
editNumber(ne.intbuf, vmin, vmax, step, dft, title, help);
|
||||
ne.intbuf = x; ne.intval = &x; ne.s = its(x);
|
||||
sidedialog = true;
|
||||
}
|
||||
|
||||
string disp(ld x) { if(ne.intval) return its((int) (x+.5)); else return fts(x); }
|
||||
|
||||
void affect(char kind) {
|
||||
@ -603,14 +580,14 @@ namespace dialog {
|
||||
if(ne.intval == &polygonal::coefid && polygonal::coefid < 0)
|
||||
*ne.editwhat = *ne.intval = 0, affect('v');
|
||||
|
||||
if(ne.intval == &polygonal::coefid && polygonal::coefid >= MSI)
|
||||
*ne.editwhat = *ne.intval = MSI-1, affect('v');
|
||||
if(ne.intval == &polygonal::coefid && polygonal::coefid >= polygonal::MSI)
|
||||
*ne.editwhat = *ne.intval = polygonal::MSI-1, affect('v');
|
||||
|
||||
if(ne.intval == &polygonal::deg && polygonal::deg < 0)
|
||||
*ne.editwhat = *ne.intval = MSI-1, affect('v');
|
||||
*ne.editwhat = *ne.intval = polygonal::MSI-1, affect('v');
|
||||
|
||||
if(ne.intval == &polygonal::deg && polygonal::deg >= MSI)
|
||||
*ne.editwhat = *ne.intval = MSI-1, affect('v');
|
||||
if(ne.intval == &polygonal::deg && polygonal::deg >= polygonal::MSI)
|
||||
*ne.editwhat = *ne.intval = polygonal::MSI-1, affect('v');
|
||||
|
||||
if(ne.intval == &polygonal::SI) polygonal::solve();
|
||||
if(ne.editwhat == &polygonal::STAR) polygonal::solve();
|
||||
@ -623,13 +600,15 @@ namespace dialog {
|
||||
if(ne.editwhat == &geom3::middetail && geom3::highdetail > geom3::middetail)
|
||||
geom3::highdetail = geom3::middetail;
|
||||
|
||||
if(lastmode == em3D) buildpolys();
|
||||
buildpolys();
|
||||
#ifdef GL
|
||||
if(lastmode == em3D) resetGL();
|
||||
resetGL();
|
||||
#endif
|
||||
}
|
||||
|
||||
void drawNumberDialog() {
|
||||
gamescreen(sidedialog ? 0 : 2);
|
||||
cmode2 = smNumber;
|
||||
init(ne.title);
|
||||
addInfo(ne.s);
|
||||
addSlider(ne.scale(ne.vmin), ne.scale(*ne.editwhat), ne.scale(ne.vmax), 500);
|
||||
@ -644,7 +623,7 @@ namespace dialog {
|
||||
|
||||
addBreak(100);
|
||||
|
||||
if(lastmode == em3D) ne.help = explain3D(ne.editwhat);
|
||||
ne.help = explain3D(ne.editwhat);
|
||||
|
||||
if(ne.help != "") {
|
||||
addHelp(ne.help);
|
||||
@ -671,69 +650,67 @@ namespace dialog {
|
||||
addBoolItem("finer lines at the boundary", vid.antialias & AA_LINEWIDTH, 'o');
|
||||
|
||||
display();
|
||||
}
|
||||
|
||||
void handleNumber(int sym, int uni) {
|
||||
handleNavigation(sym, uni);
|
||||
if((uni >= '0' && uni <= '9') || (uni == '.' && !ne.intval) || (uni == '-' && !ne.positive)) {
|
||||
ne.s += uni;
|
||||
affect('s');
|
||||
}
|
||||
else if(uni == '\b' || uni == '\t') {
|
||||
ne.s = ne.s. substr(0, size(ne.s)-1);
|
||||
sscanf(ne.s.c_str(), LDF, ne.editwhat);
|
||||
affect('s');
|
||||
}
|
||||
#ifndef MOBILE
|
||||
else if(sym == SDLK_RIGHT || sym == SDLK_KP6) {
|
||||
if(ne.intval && abs(shiftmul) < .6)
|
||||
(*ne.editwhat)++;
|
||||
else
|
||||
*ne.editwhat = ne.inverse_scale(ne.scale(*ne.editwhat) + shiftmul * ne.step);
|
||||
affect('v');
|
||||
}
|
||||
else if(sym == SDLK_LEFT || sym == SDLK_KP4) {
|
||||
if(ne.intval && abs(shiftmul) < .6)
|
||||
(*ne.editwhat)--;
|
||||
else
|
||||
*ne.editwhat = ne.inverse_scale(ne.scale(*ne.editwhat) - shiftmul * ne.step);
|
||||
affect('v');
|
||||
}
|
||||
#endif
|
||||
else if(sym == SDLK_HOME) {
|
||||
*ne.editwhat = ne.dft;
|
||||
affect('v');
|
||||
}
|
||||
else if(uni == 500) {
|
||||
int sl, sr;
|
||||
if(sidescreen)
|
||||
sl = vid.yres + vid.fsize*2, sr = vid.xres - vid.fsize*2;
|
||||
else
|
||||
sl = vid.xres/4, sr = vid.xres*3/4;
|
||||
ld d = (mousex - sl + .0) / (sr-sl);
|
||||
*ne.editwhat =
|
||||
ne.inverse_scale(d * (ne.scale(ne.vmax) - ne.scale(ne.vmin)) + ne.scale(ne.vmin));
|
||||
affect('v');
|
||||
}
|
||||
else if(uni == 'o' && ne.editwhat == &ne.intbuf && ne.intval == &sightrange && cheater)
|
||||
overgenerate = !overgenerate;
|
||||
else if(uni == 'o' && ne.editwhat == &vid.linewidth)
|
||||
vid.antialias ^= AA_LINEWIDTH;
|
||||
else if(uni == 'p' && ne.editwhat == &vid.alpha) {
|
||||
*ne.editwhat = 1; vid.scale = 1; ne.s = "1";
|
||||
}
|
||||
else if(uni == 'k' && ne.editwhat == &vid.alpha) {
|
||||
*ne.editwhat = 0; vid.scale = 1; ne.s = "0";
|
||||
}
|
||||
else if((uni == 'i' || uni == 'I' || uni == 'o' || uni == 'O') && ne.editwhat == &vid.alpha) {
|
||||
double d = exp(shiftmul/10);
|
||||
vid.alpha *= d;
|
||||
vid.scale *= d;
|
||||
ne.s = fts(vid.alpha);
|
||||
}
|
||||
else if(doexiton(sym, uni)) {
|
||||
cmode = lastmode;
|
||||
}
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
handleNavigation(sym, uni);
|
||||
if((uni >= '0' && uni <= '9') || (uni == '.' && !ne.intval) || (uni == '-' && !ne.positive)) {
|
||||
ne.s += uni;
|
||||
affect('s');
|
||||
}
|
||||
else if(uni == '\b' || uni == '\t') {
|
||||
ne.s = ne.s. substr(0, size(ne.s)-1);
|
||||
sscanf(ne.s.c_str(), LDF, ne.editwhat);
|
||||
affect('s');
|
||||
}
|
||||
#ifndef MOBILE
|
||||
else if(sym == SDLK_RIGHT || sym == SDLK_KP6) {
|
||||
if(ne.intval && abs(shiftmul) < .6)
|
||||
(*ne.editwhat)++;
|
||||
else
|
||||
*ne.editwhat = ne.inverse_scale(ne.scale(*ne.editwhat) + shiftmul * ne.step);
|
||||
affect('v');
|
||||
}
|
||||
else if(sym == SDLK_LEFT || sym == SDLK_KP4) {
|
||||
if(ne.intval && abs(shiftmul) < .6)
|
||||
(*ne.editwhat)--;
|
||||
else
|
||||
*ne.editwhat = ne.inverse_scale(ne.scale(*ne.editwhat) - shiftmul * ne.step);
|
||||
affect('v');
|
||||
}
|
||||
#endif
|
||||
else if(sym == SDLK_HOME) {
|
||||
*ne.editwhat = ne.dft;
|
||||
affect('v');
|
||||
}
|
||||
else if(uni == 500) {
|
||||
int sl, sr;
|
||||
if(sidescreen)
|
||||
sl = vid.yres + vid.fsize*2, sr = vid.xres - vid.fsize*2;
|
||||
else
|
||||
sl = vid.xres/4, sr = vid.xres*3/4;
|
||||
ld d = (mousex - sl + .0) / (sr-sl);
|
||||
*ne.editwhat =
|
||||
ne.inverse_scale(d * (ne.scale(ne.vmax) - ne.scale(ne.vmin)) + ne.scale(ne.vmin));
|
||||
affect('v');
|
||||
}
|
||||
else if(uni == 'o' && ne.editwhat == &ne.intbuf && ne.intval == &sightrange && cheater)
|
||||
overgenerate = !overgenerate;
|
||||
else if(uni == 'o' && ne.editwhat == &vid.linewidth)
|
||||
vid.antialias ^= AA_LINEWIDTH;
|
||||
else if(uni == 'p' && ne.editwhat == &vid.alpha) {
|
||||
*ne.editwhat = 1; vid.scale = 1; ne.s = "1";
|
||||
}
|
||||
else if(uni == 'k' && ne.editwhat == &vid.alpha) {
|
||||
*ne.editwhat = 0; vid.scale = 1; ne.s = "0";
|
||||
}
|
||||
else if((uni == 'i' || uni == 'I' || uni == 'o' || uni == 'O') && ne.editwhat == &vid.alpha) {
|
||||
double d = exp(shiftmul/10);
|
||||
vid.alpha *= d;
|
||||
vid.scale *= d;
|
||||
ne.s = fts(vid.alpha);
|
||||
}
|
||||
else if(doexiton(sym, uni)) popScreen();
|
||||
};
|
||||
}
|
||||
|
||||
int nlpage = 1;
|
||||
@ -785,4 +762,26 @@ namespace dialog {
|
||||
return true;
|
||||
}
|
||||
|
||||
void editNumber(ld& x, ld vmin, ld vmax, ld step, ld dft, string title, string help) {
|
||||
ne.editwhat = &x;
|
||||
ne.s = fts(x);
|
||||
ne.vmin = vmin;
|
||||
ne.vmax = vmax;
|
||||
ne.step = step;
|
||||
ne.dft = dft;
|
||||
ne.title = title;
|
||||
ne.help = help;
|
||||
ne.scale = ne.inverse_scale = identity;
|
||||
ne.intval = NULL;
|
||||
ne.positive = false;
|
||||
sidedialog = false;
|
||||
pushScreen(drawNumberDialog);
|
||||
}
|
||||
|
||||
void editNumber(int& x, int vmin, int vmax, int step, int dft, string title, string help) {
|
||||
editNumber(ne.intbuf, vmin, vmax, step, dft, title, help);
|
||||
ne.intbuf = x; ne.intval = &x; ne.s = its(x);
|
||||
sidedialog = true;
|
||||
}
|
||||
|
||||
};
|
||||
|
6
game.cpp
6
game.cpp
@ -5415,8 +5415,12 @@ void checkmove() {
|
||||
if(movepcto(1, 1, true))
|
||||
canmove = legalmoves[cwt.spin] = true;
|
||||
if(kills[moPlayer]) canmove = false;
|
||||
if(!canmove)
|
||||
|
||||
if(!canmove) {
|
||||
achievement_final(true);
|
||||
if(cmode2 == smNormal) showMissionScreen();
|
||||
}
|
||||
|
||||
if(canmove && timerstopped) {
|
||||
timerstart = time(NULL);
|
||||
timerstopped = false;
|
||||
|
816
help.cpp
Normal file
816
help.cpp
Normal file
@ -0,0 +1,816 @@
|
||||
string help;
|
||||
|
||||
#ifndef NOLAMBDAS
|
||||
function<void()> help_delegate;
|
||||
#endif
|
||||
|
||||
string buildHelpText() {
|
||||
DEBB(DF_GRAPH, (debugfile,"buildHelpText\n"));
|
||||
|
||||
#ifdef ROGUEVIZ
|
||||
if(rogueviz::on) return rogueviz::makehelp();
|
||||
#endif
|
||||
|
||||
string h;
|
||||
h += XLAT("Welcome to HyperRogue");
|
||||
#ifdef ANDROID
|
||||
h += XLAT(" for Android");
|
||||
#endif
|
||||
#ifdef IOS
|
||||
h += XLAT(" for iOS");
|
||||
#endif
|
||||
h += XLAT("! (version %1)\n\n", VER);
|
||||
|
||||
h += XLAT(
|
||||
"You have been trapped in a strange, non-Euclidean world. Collect as much treasure as possible "
|
||||
"before being caught by monsters. The more treasure you collect, the more "
|
||||
"monsters come to hunt you, as long as you are in the same land type. The "
|
||||
"Orbs of Yendor are the ultimate treasure; get at least one of them to win the game!"
|
||||
);
|
||||
h += XLAT(" (press ESC for some hints about it).");
|
||||
h += "\n\n";
|
||||
|
||||
h += XLAT(
|
||||
"You can fight most monsters by moving into their location. "
|
||||
"The monster could also kill you by moving into your location, but the game "
|
||||
"automatically cancels all moves which result in that.\n\n"
|
||||
);
|
||||
|
||||
h += XLAT(
|
||||
"There are many lands in HyperRogue. Collect 10 treasure "
|
||||
"in the given land type to complete it; this enables you to "
|
||||
"find the magical Orbs of this land, and in some cases "
|
||||
"get access to new lands. At 25 treasures "
|
||||
"this type of Orbs starts appearing in other lands as well. Press 'o' to "
|
||||
"get the details of all the Lands.\n\n");
|
||||
h += "\n\n";
|
||||
|
||||
#ifdef MOBILE
|
||||
h += XLAT(
|
||||
"Usually, you move by touching somewhere on the map; you can also touch one "
|
||||
"of the four buttons on the map corners to change this (to scroll the map "
|
||||
"or get information about map objects). You can also touch the "
|
||||
"numbers displayed to get their meanings.\n"
|
||||
);
|
||||
#else
|
||||
h += XLAT(
|
||||
"Move with mouse, num pad, qweadzxc, or hjklyubn. Wait by pressing 's' or '.'. Spin the world with arrows, PageUp/Down, and Home/Space. "
|
||||
"To save the game you need an Orb of Safety. Press 'v' for the main menu (configuration, special modes, etc.), ESC for the quest status.\n\n"
|
||||
);
|
||||
h += XLAT(
|
||||
"You can right click any element to get more information about it.\n\n"
|
||||
);
|
||||
h += XLAT("(You can also use right Shift)\n\n");
|
||||
#endif
|
||||
h += XLAT("See more on the website: ")
|
||||
+ "http//roguetemple.com/z/hyper/\n\n";
|
||||
|
||||
#ifdef TOUR
|
||||
h += XLAT("Try the Tutorial to help with understanding the "
|
||||
"geometry of HyperRogue (menu -> special modes).\n\n");
|
||||
#endif
|
||||
|
||||
h += XLAT("Still confused? Read the FAQ on the HyperRogue website!\n\n");
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
string buildCredits() {
|
||||
string h;
|
||||
h += XLAT("game design, programming, texts and graphics by Zeno Rogue <zeno@attnam.com>\n\n");
|
||||
if(lang() != 0)
|
||||
h += XLAT("add credits for your translation here");
|
||||
#ifndef NOLICENSE
|
||||
h += XLAT(
|
||||
"released under GNU General Public License version 2 and thus "
|
||||
"comes with absolutely no warranty; see COPYING for details\n\n"
|
||||
);
|
||||
#endif
|
||||
h += XLAT(
|
||||
"special thanks to the following people for their bug reports, feature requests, porting, and other help:\n\n%1\n\n",
|
||||
"Konstantin Stupnik, ortoslon, chrysn, Adam Borowski, Damyan Ivanov, Ryan Farnsley, mcobit, Darren Grey, tricosahedron, Maciej Chojecki, Marek Čtrnáct, "
|
||||
"wonderfullizardofoz, Piotr Migdał, tehora, Michael Heerdegen, Sprite Guard, zelda0x181e, Vipul, snowyowl0, Patashu, phenomist, Alan Malloy, Tom Fryers, Sinquetica, _monad, CtrlAltDestroy, jruderman"
|
||||
);
|
||||
#ifdef EXTRALICENSE
|
||||
h += EXTRALICENSE;
|
||||
#endif
|
||||
#ifndef MOBILE
|
||||
h += XLAT(
|
||||
"\n\nSee sounds/credits.txt for credits for sound effects"
|
||||
);
|
||||
#endif
|
||||
if(musiclicense != "") h += musiclicense;
|
||||
return h;
|
||||
}
|
||||
|
||||
string pushtext(stringpar p) {
|
||||
string s = XLAT(
|
||||
"\n\nNote: when pushing %the1 off a heptagonal cell, you can control the pushing direction "
|
||||
"by clicking left or right half of the heptagon.", p);
|
||||
#ifndef MOBILE
|
||||
s += XLAT(" With the keyboard, you can rotate the view for a similar effect (Page Up/Down).");
|
||||
#endif
|
||||
return s;
|
||||
}
|
||||
|
||||
string princedesc() {
|
||||
if(princessgender() == GEN_M)
|
||||
return XLAT("Apparently a prince is kept locked somewhere, but you won't ever find him in this hyperbolic palace. ");
|
||||
else
|
||||
return XLAT("Apparently a princess is kept locked somewhere, but you won't ever find her in this hyperbolic palace. ");
|
||||
}
|
||||
|
||||
string helptitle(string s, int col) {
|
||||
return "@" + its(col) + "\t" + s + "\n";
|
||||
}
|
||||
|
||||
string princessReviveHelp() {
|
||||
string h = "\n\n" +
|
||||
XLAT("Killed %1 can be revived with Orb of the Love, after you collect 20 more $$$.", moPrincess);
|
||||
if(princess::reviveAt)
|
||||
h += "\n\n" +
|
||||
XLAT("%The1 will be revivable at %2 $$$", moPrincess, its(princess::reviveAt));
|
||||
return h;
|
||||
}
|
||||
|
||||
void describeOrb(string& help, const orbinfo& oi) {
|
||||
eOrbLandRelation olr = getOLR(oi.orb, cwt.c->land);
|
||||
eItem tr = treasureType(oi.l);
|
||||
help += "\n\n" + XLAT(olrDescriptions[olr], cwt.c->land, tr, treasureType(cwt.c->land));
|
||||
int t = items[tr] * landMultiplier(oi.l);
|
||||
if(t >= 25)
|
||||
if(olr == olrPrize25 || olr == olrPrize3 || olr == olrGuest || olr == olrMonster || olr == olrAlways) {
|
||||
help += XLAT("\nSpawn rate (as prize Orb): %1%/%2\n",
|
||||
its(int(.5 + 100 * orbprizefun(t))),
|
||||
its(oi.gchance));
|
||||
}
|
||||
if(t >= 10)
|
||||
if(olr == olrHub) {
|
||||
help += XLAT("\nSpawn rate (in Hubs): %1%/%2\n",
|
||||
its(int(.5 + 100 * orbcrossfun(t))),
|
||||
its(oi.gchance));
|
||||
}
|
||||
}
|
||||
|
||||
string generateHelpForItem(eItem it) {
|
||||
|
||||
string help = helptitle(XLATN(iinf[it].name), iinf[it].color);
|
||||
|
||||
help += XLAT(iinf[it].help);
|
||||
|
||||
if(it == itSavedPrincess || it == itOrbLove)
|
||||
help += princessReviveHelp();
|
||||
|
||||
if(it == itTrollEgg)
|
||||
help += XLAT("\n\nAfter the Trolls leave, you have 750 turns to collect %the1, or it gets stolen.", it);
|
||||
|
||||
if(it == itIvory || it == itAmethyst || it == itLotus || it == itMutant) {
|
||||
help += XLAT(
|
||||
"\n\nEasy %1 might disappear when you collect more of its kind.", it);
|
||||
if(it != itMutant) help += XLAT(
|
||||
" You need to go deep to collect lots of them.");
|
||||
}
|
||||
|
||||
#ifdef MOBILE
|
||||
if(it == itOrbSafety)
|
||||
help += XLAT("This might be very useful for devices with limited memory.");
|
||||
#else
|
||||
if(it == itOrbSafety)
|
||||
help += XLAT("Thus, it is potentially useful for extremely long games, which would eat all the memory on your system otherwise.\n");
|
||||
#endif
|
||||
|
||||
if(isRangedOrb(it)) {
|
||||
help += XLAT("\nThis is a ranged Orb. ");
|
||||
#ifdef ISMOBILE
|
||||
if(vid.shifttarget&2)
|
||||
help += XLAT("\nRanged Orbs can be targeted by long touching the desired location.");
|
||||
else
|
||||
help += XLAT("\nRanged Orbs can be targeted by touching the desired location.");
|
||||
#else
|
||||
if(vid.shifttarget&1)
|
||||
help += XLAT("\nRanged Orbs can be targeted by shift-clicking the desired location. "
|
||||
else
|
||||
help += XLAT("\nRanged Orbs can be targeted by clicking the desired location. ");
|
||||
help += "You can also scroll to the desired location and then press 't'.");
|
||||
#endif
|
||||
help += XLAT("\nYou can never target cells which are adjacent to the player character, or ones out of the sight range.");
|
||||
}
|
||||
|
||||
#ifdef MOBILE
|
||||
if(it == itGreenStone)
|
||||
help += XLAT("You can touch the Dead Orb in your inventory to drop it.");
|
||||
#else
|
||||
if(it == itGreenStone)
|
||||
help += XLAT("You can press 'g' or click them in the list to drop a Dead Orb.");
|
||||
#endif
|
||||
if(it == itOrbLightning || it == itOrbFlash)
|
||||
help += XLAT("\n\nThis Orb is triggered on your first attack or illegal move.");
|
||||
if(it == itOrbShield)
|
||||
help += XLAT("\n\nThis Orb protects you from attacks, scents, and insulates you "
|
||||
"from electricity. It does not let you go through deadly terrain, but "
|
||||
"if you are attacked with fire, it lets you stay in place in it.");
|
||||
if(it == itOrbEmpathy) {
|
||||
int cnt = 0;
|
||||
for(int i=0; i<ittypes; i++) {
|
||||
eItem it2 = eItem(i);
|
||||
if(isEmpathyOrb(it2)) {
|
||||
help += XLAT(cnt ? ", %1" : " %1", it2);
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(itemclass(it) == IC_ORB || it == itGreenStone || it == itOrbYendor) {
|
||||
for(int i=0; i<ORBLINES; i++) {
|
||||
const orbinfo& oi(orbinfos[i]);
|
||||
if(oi.orb == it) describeOrb(help, oi);
|
||||
}
|
||||
}
|
||||
|
||||
if(itemclass(it) == IC_TREASURE) {
|
||||
for(int i=0; i<ORBLINES; i++) {
|
||||
const orbinfo& oi(orbinfos[i]);
|
||||
if(treasureType(oi.l) == it) {
|
||||
if(oi.gchance > 0) {
|
||||
help += XLAT("\n\nOrb unlocked: %1", oi.orb);
|
||||
describeOrb(help, oi);
|
||||
}
|
||||
else if(oi.l == cwt.c->land) {
|
||||
help += XLAT("\n\nSecondary orb: %1", oi.orb);
|
||||
describeOrb(help, oi);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return help;
|
||||
}
|
||||
|
||||
void addMinefieldExplanation(string& s) {
|
||||
|
||||
s += XLAT(
|
||||
"\n\nOnce you collect 10 Bomberbird Eggs, "
|
||||
"stepping on a cell with no adjacent mines also reveals the adjacent cells. "
|
||||
"Collecting even more Eggs will increase the radius. Additionally, collecting "
|
||||
"25 Bomberbird Eggs will reveal adjacent cells even in your future games."
|
||||
);
|
||||
|
||||
s += "\n\n";
|
||||
#ifdef MOBILE
|
||||
s += XLAT("Known mines may be marked by pressing 'm'. Your allies won't step on marked mines.");
|
||||
#else
|
||||
s += XLAT("Known mines may be marked by touching while in drag mode. Your allies won't step on marked mines.");
|
||||
#endif
|
||||
}
|
||||
|
||||
string generateHelpForWall(eWall w) {
|
||||
|
||||
string s = helptitle(XLATN(winf[w].name), winf[w].color);
|
||||
|
||||
s += XLAT(winf[w].help);
|
||||
if(w == waMineMine || w == waMineUnknown || w == waMineOpen)
|
||||
addMinefieldExplanation(s);
|
||||
if(isThumper(w)) s += pushtext(w);
|
||||
if((w == waClosePlate || w == waOpenPlate) && purehepta)
|
||||
s += "\n\n(For the heptagonal mode, the radius has been reduced to 2 for closing plates.)";
|
||||
return s;
|
||||
}
|
||||
|
||||
void buteol(string& s, int current, int req) {
|
||||
int siz = size(s);
|
||||
if(s[siz-1] == '\n') s.resize(siz-1);
|
||||
char buf[100]; sprintf(buf, " (%d/%d)", current, req);
|
||||
s += buf; s += "\n";
|
||||
}
|
||||
|
||||
string generateHelpForMonster(eMonster m) {
|
||||
string s = helptitle(XLATN(minf[m].name), minf[m].color);
|
||||
|
||||
if(m == moPlayer) {
|
||||
#ifdef TOUR
|
||||
if(tour::on)
|
||||
return s+XLAT(
|
||||
"A tourist from another world. They mutter something about the 'tutorial', "
|
||||
"and claim that they are here just to learn, and to leave without any treasures. "
|
||||
"Do not kill them!"
|
||||
);
|
||||
#endif
|
||||
s += XLAT(
|
||||
"This monster has come from another world, presumably to steal our treasures. "
|
||||
"Not as fast as an Eagle, not as resilient as the guards from the Palace, "
|
||||
"and not as huge as the Mutant Ivy from the Clearing; however, "
|
||||
"they are very dangerous because of their intelligence, "
|
||||
"and access to magical powers.\n\n");
|
||||
|
||||
if(cheater)
|
||||
s += XLAT("Actually, their powers appear god-like...\n\n");
|
||||
|
||||
else if(!hardcore)
|
||||
s += XLAT(
|
||||
"Rogues will never make moves which result in their immediate death. "
|
||||
"Even when cornered, they are able to instantly teleport back to their "
|
||||
"home world at any moment, taking the treasures forever... but "
|
||||
"at least they will not steal anything further!\n\n"
|
||||
);
|
||||
|
||||
if(!euclid)
|
||||
s += XLAT(
|
||||
"Despite this intelligence, Rogues appear extremely surprised "
|
||||
"by the most basic facts about geometry. They must come from "
|
||||
"some really strange world.\n\n"
|
||||
);
|
||||
|
||||
if(shmup::on)
|
||||
s += XLAT("In the Shoot'em Up mode, you are armed with thrown Knives.");
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
s += XLAT(minf[m].help);
|
||||
if(m == moPalace || m == moSkeleton)
|
||||
s += pushtext(m);
|
||||
if(m == moTroll) s += XLAT(trollhelp2);
|
||||
|
||||
if(isMonsterPart(m))
|
||||
s += XLAT("\n\nThis is a part of a monster. It does not count for your total kills.", m);
|
||||
|
||||
if(isFriendly(m))
|
||||
s += XLAT("\n\nThis is a friendly being. It does not count for your total kills.", m);
|
||||
|
||||
if(m == moTortoise)
|
||||
s += XLAT("\n\nTortoises are not monsters! They are just annoyed. They do not count for your total kills.", m);
|
||||
|
||||
if(isGhost(m))
|
||||
s += XLAT("\n\nA Ghost never moves to a cell which is adjacent to another Ghost of the same kind.", m);
|
||||
|
||||
if(m == moBat || m == moEagle)
|
||||
s += XLAT("\n\nFast flying creatures may attack or go against gravity only in their first move.", m);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
string generateHelpForLand(eLand l) {
|
||||
string s = helptitle(XLATN(linf[l].name), linf[l].color);
|
||||
|
||||
if(l == laPalace) s += princedesc();
|
||||
|
||||
s += XLAT(linf[l].help);
|
||||
|
||||
if(l == laMinefield) addMinefieldExplanation(s);
|
||||
|
||||
s += "\n\n";
|
||||
if(l == laIce || l == laCaves || l == laDesert || l == laMotion || l == laJungle ||
|
||||
l == laCrossroads || l == laAlchemist)
|
||||
s += XLAT("Always available.\n");
|
||||
|
||||
#define ACCONLY(z) s += XLAT("Accessible only from %the1.\n", z);
|
||||
#define ACCONLY2(z,x) s += XLAT("Accessible only from %the1 or %the2.\n", z, x);
|
||||
#define ACCONLYF(z) s += XLAT("Accessible only from %the1 (until finished).\n", z);
|
||||
#define TREQ(z) { s += XLAT("Treasure required: %1 $$$.\n", its(z)); buteol(s, gold(), z); }
|
||||
#define TREQ2(z,x) { s += XLAT("Treasure required: %1 x %2.\n", its(z), x); buteol(s, items[x], z); }
|
||||
|
||||
if(l == laMirror || l == laMinefield || l == laPalace ||
|
||||
l == laOcean || l == laLivefjord || l == laZebra || l == laWarpCoast || l == laWarpSea ||
|
||||
l == laReptile || l == laIvoryTower)
|
||||
TREQ(R30)
|
||||
|
||||
|
||||
if(isCoastal(l))
|
||||
s += XLAT("Coastal region -- connects inland and aquatic regions.\n");
|
||||
|
||||
if(isPureSealand(l))
|
||||
s += XLAT("Aquatic region -- accessible only from coastal regions and other aquatic regions.\n");
|
||||
|
||||
if(l == laWhirlpool) ACCONLY(laOcean)
|
||||
if(l == laRlyeh) ACCONLYF(laOcean)
|
||||
if(l == laTemple) ACCONLY(laRlyeh)
|
||||
if(l == laClearing) ACCONLY(laOvergrown)
|
||||
if(l == laHaunted) ACCONLY(laGraveyard)
|
||||
if(l == laPrincessQuest) ACCONLY(laPalace)
|
||||
if(l == laMountain) ACCONLY(laJungle)
|
||||
if(l == laCamelot) ACCONLY2(laCrossroads, laCrossroads3)
|
||||
|
||||
if(l == laDryForest || l == laWineyard || l == laDeadCaves || l == laHive || l == laRedRock ||
|
||||
l == laOvergrown || l == laStorms || l == laWhirlwind || l == laRose ||
|
||||
l == laCrossroads2 || l == laRlyeh)
|
||||
TREQ(R60)
|
||||
|
||||
if(l == laReptile) TREQ2(U10, itElixir)
|
||||
if(l == laEndorian) TREQ2(U10, itIvory)
|
||||
if(l == laKraken) TREQ2(U10, itFjord)
|
||||
if(l == laBurial) TREQ2(U10, itKraken)
|
||||
|
||||
if(l == laDungeon) TREQ2(U5, itIvory)
|
||||
if(l == laDungeon) TREQ2(U5, itPalace)
|
||||
if(l == laMountain) TREQ2(U5, itIvory)
|
||||
if(l == laMountain) TREQ2(U5, itRuby)
|
||||
|
||||
if(l == laPrairie) TREQ(R90)
|
||||
if(l == laBull) TREQ(R90)
|
||||
if(l == laCrossroads4) TREQ(R200)
|
||||
if(l == laCrossroads5) TREQ(R300)
|
||||
|
||||
if(l == laGraveyard || l == laHive) {
|
||||
s += XLAT("Kills required: %1.\n", "100");
|
||||
buteol(s, tkills(), R100);
|
||||
}
|
||||
|
||||
if(l == laDragon) {
|
||||
s += XLAT("Different kills required: %1.\n", "20");
|
||||
buteol(s, killtypes(), R20);
|
||||
}
|
||||
|
||||
if(l == laTortoise) ACCONLY(laDragon)
|
||||
if(l == laTortoise) s += XLAT("Find a %1 in %the2.", itBabyTortoise, laDragon);
|
||||
|
||||
if(l == laHell || l == laCrossroads3) {
|
||||
s += XLAT("Finished lands required: %1 (collect %2 treasure)\n", "9", its(R10));
|
||||
buteol(s, orbsUnlocked(), 9);
|
||||
}
|
||||
|
||||
if(l == laCocytus || l == laPower) TREQ2(U10, itHell)
|
||||
if(l == laRedRock) TREQ2(U10, itSpice)
|
||||
if(l == laOvergrown) TREQ2(U10, itRuby)
|
||||
if(l == laClearing) TREQ2(U5, itMutant)
|
||||
if(l == laCocytus) TREQ2(U10, itDiamond)
|
||||
if(l == laDeadCaves) TREQ2(U10, itGold)
|
||||
if(l == laTemple) TREQ2(U5, itStatue)
|
||||
if(l == laHaunted) TREQ2(U10, itBone)
|
||||
if(l == laCamelot) TREQ2(U5, itEmerald)
|
||||
if(l == laEmerald) {
|
||||
TREQ2(5, itFernFlower) TREQ2(5, itGold)
|
||||
s += XLAT("Alternatively: kill a %1 in %the2.\n", moVizier, laPalace);
|
||||
buteol(s, kills[moVizier], 1);
|
||||
}
|
||||
|
||||
#define KILLREQ(who, where) { s += XLAT("Kills required: %1 (%2).\n", who, where); buteol(s, kills[who], 1); }
|
||||
|
||||
if(l == laPrincessQuest)
|
||||
KILLREQ(moVizier, laPalace);
|
||||
|
||||
if(l == laElementalWall) {
|
||||
KILLREQ(moFireElemental, laDragon);
|
||||
KILLREQ(moEarthElemental, laDeadCaves);
|
||||
KILLREQ(moWaterElemental, laLivefjord);
|
||||
KILLREQ(moAirElemental, laWhirlwind);
|
||||
}
|
||||
|
||||
if(l == laTrollheim) {
|
||||
KILLREQ(moTroll, laCaves);
|
||||
KILLREQ(moFjordTroll, laLivefjord);
|
||||
KILLREQ(moDarkTroll, laDeadCaves);
|
||||
KILLREQ(moStormTroll, laStorms);
|
||||
KILLREQ(moForestTroll, laOvergrown);
|
||||
KILLREQ(moRedTroll, laRedRock);
|
||||
}
|
||||
|
||||
if(l == laZebra) TREQ2(U10, itFeather)
|
||||
|
||||
if(l == laCamelot || l == laPrincessQuest)
|
||||
s += XLAT("Completing the quest in this land is not necessary for the Hyperstone Quest.");
|
||||
|
||||
int rl = isRandland(l);
|
||||
if(rl == 2)
|
||||
s += XLAT("Variants of %the1 are always available in the Random Pattern Mode.", l);
|
||||
else if(rl == 1)
|
||||
s += XLAT(
|
||||
"Variants of %the1 are available in the Random Pattern Mode after "
|
||||
"getting a highscore of at least 10 %2.", l, treasureType(l));
|
||||
|
||||
if(l == laPrincessQuest) {
|
||||
s += XLAT("Unavailable in the shmup mode.\n");
|
||||
s += XLAT("Unavailable in the multiplayer mode.\n");
|
||||
}
|
||||
|
||||
if(noChaos(l))
|
||||
s += XLAT("Unavailable in the Chaos mode.\n");
|
||||
|
||||
if(l == laWildWest)
|
||||
s += XLAT("Bonus land, available only in some special modes.\n");
|
||||
|
||||
if(l == laWhirlpool)
|
||||
s += XLAT("Orbs of Safety always appear here, and may be used to escape.\n");
|
||||
|
||||
/* if(isHaunted(l) || l == laDungeon)
|
||||
s += XLAT("You may be unable to leave %the1 if you are not careful!\n", l); */
|
||||
|
||||
if(l == laStorms) {
|
||||
if(elec::lightningfast == 0) s += XLAT("\nSpecial conduct (still valid)\n");
|
||||
else s += XLAT("\nSpecial conduct failed:\n");
|
||||
|
||||
s += XLAT(
|
||||
"Avoid escaping from a discharge (\"That was close\").");
|
||||
}
|
||||
|
||||
if(isHaunted(l)) {
|
||||
if(survivalist) s += XLAT("\nSpecial conduct (still valid)\n");
|
||||
else s += XLAT("\nSpecial conduct failed:\n");
|
||||
|
||||
s += XLAT(
|
||||
"Avoid chopping trees, using Orbs, and non-graveyard monsters in the Haunted Woods."
|
||||
);
|
||||
}
|
||||
|
||||
#ifndef ISMOBILE
|
||||
if(l == laCA)
|
||||
s += XLAT("\n\nHint: use 'm' to toggle cells quickly");
|
||||
#endif
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
bool instat;
|
||||
|
||||
string turnstring(int i) {
|
||||
if(i == 1) return XLAT("1 turn");
|
||||
else return XLAT("%1 turns", its(i));
|
||||
}
|
||||
|
||||
void describeMouseover() {
|
||||
DEBB(DF_GRAPH, (debugfile,"describeMouseover\n"));
|
||||
|
||||
cell *c = mousing ? mouseover : playermoved ? NULL : centerover;
|
||||
string out = mouseovers;
|
||||
if(!c || instat || getcstat) { }
|
||||
else if(c->wall != waInvisibleFloor) {
|
||||
out = XLAT1(linf[c->land].name);
|
||||
help = generateHelpForLand(c->land);
|
||||
|
||||
// Celsius
|
||||
|
||||
// if(c->land == laIce) out = "Icy Lands (" + fts(60 * (c->heat - .4)) + " C)";
|
||||
|
||||
if(c->land == laIce || c->land == laCocytus)
|
||||
out += " (" + fts(heat::celsius(c)) + " °C)";
|
||||
if(c->land == laDryForest && c->landparam)
|
||||
out += " (" + its(c->landparam)+"/10)";
|
||||
if(c->land == laOcean && chaosmode)
|
||||
out += " (" + its(c->CHAOSPARAM)+"S"+its(c->SEADIST)+"L"+its(c->LANDDIST)+")";
|
||||
else if(c->land == laOcean && c->landparam <= 25) {
|
||||
if(shmup::on)
|
||||
out += " (" + its(c->landparam)+")";
|
||||
else {
|
||||
bool b = c->landparam >= tide[(turncount-1) % tidalsize];
|
||||
int t = 1;
|
||||
for(; t < 1000 && b == (c->landparam >= tide[(turncount+t-1) % tidalsize]); t++) ;
|
||||
if(b)
|
||||
out += " (" + turnstring(t) + XLAT(" to surface") + ")";
|
||||
else
|
||||
out += " (" + turnstring(t) + XLAT(" to submerge") + ")";
|
||||
}
|
||||
}
|
||||
|
||||
if(c->land == laTortoise && tortoise::seek()) out += " " + tortoise::measure(getBits(c));
|
||||
|
||||
/* if(c->land == laGraveyard || c->land == laHauntedBorder || c->land == laHaunted)
|
||||
out += " (" + its(c->landparam)+")"; */
|
||||
|
||||
if(buggyGeneration) {
|
||||
char buf[20]; sprintf(buf, " H=%d M=%d", c->landparam, c->mpdist); out += buf;
|
||||
}
|
||||
|
||||
// if(c->land == laBarrier)
|
||||
// out += "(" + string(linf[c->barleft].name) + " / " + string(linf[c->barright].name) + ")";
|
||||
|
||||
// out += "(" + its(c->bardir) + ":" + string(linf[c->barleft].name) + " / " + string(linf[c->barright].name) + ")";
|
||||
|
||||
// out += " MD"+its(c->mpdist);
|
||||
|
||||
// out += " WP:" + its(c->wparam);
|
||||
// out += " rose:" + its(rosemap[c]/4) + "." + its(rosemap[c]%4);
|
||||
// out += " MP:" + its(c->mpdist);
|
||||
// out += " cda:" + its(celldistAlt(c));
|
||||
|
||||
/* out += " DP=" + its(celldistance(c, cwt.c));
|
||||
out += " DO=" + its(celldist(c));
|
||||
out += " PD=" + its(c->pathdist); */
|
||||
|
||||
if(false) {
|
||||
|
||||
out += " LP:" + itsh(c->landparam)+"/"+its(turncount);
|
||||
|
||||
out += " CD:" + its(celldist(c));
|
||||
|
||||
out += " D:" + its(c->mpdist);
|
||||
|
||||
char zz[64]; sprintf(zz, " P%p", c); out += zz;
|
||||
// out += " rv" + its(rosedist(c));
|
||||
// if(rosemap.count(c))
|
||||
// out += " rv " + its(rosemap[c]/8) + "." + its(rosemap[c]%8);
|
||||
// out += " ai" + its(c->aitmp);
|
||||
if(euclid) {
|
||||
for(int i=0; i<4; i++) out += " " + its(getEuclidCdata(c->master)->val[i]);
|
||||
out += " " + itsh(getBits(c));
|
||||
}
|
||||
else {
|
||||
for(int i=0; i<4; i++) out += " " + its(getHeptagonCdata(c->master)->val[i]);
|
||||
// out += " " + itsh(getHeptagonCdata(c->master)->bits);
|
||||
out += " " + fts(tortoise::getScent(getBits(c)));
|
||||
}
|
||||
// itsh(getHeptagonCdata(c->master)->bits);
|
||||
// out += " barleft: " + s0 + dnameof(c->barleft);
|
||||
// out += " barright: " + s0 + dnameof(c->barright);
|
||||
}
|
||||
|
||||
// char zz[64]; sprintf(zz, " P%p", c); out += zz;
|
||||
|
||||
/* whirlwind::calcdirs(c);
|
||||
for(int i=0; i<whirlwind::qdirs; i++)
|
||||
out += " " + its(whirlwind::dfrom[i]) + ":" + its(whirlwind::dto[i]); */
|
||||
// out += " : " + its(whirlwinddir(c));
|
||||
|
||||
|
||||
|
||||
if(randomPatternsMode)
|
||||
out += " " + describeRPM(c->land);
|
||||
|
||||
if(euclid && cheater) {
|
||||
if(torus) {
|
||||
out += " ("+its(decodeId(c->master))+")";
|
||||
}
|
||||
else {
|
||||
eucoord x, y;
|
||||
decodeMaster(c->master, x, y);
|
||||
out += " ("+its(short(x))+","+its(short(y))+")";
|
||||
}
|
||||
}
|
||||
|
||||
// char zz[64]; sprintf(zz, " P%d", princess::dist(c)); out += zz;
|
||||
// out += " MD"+its(c->mpdist);
|
||||
// out += " H "+its(c->heat);
|
||||
// if(c->type != 6) out += " Z"+its(c->master->zebraval);
|
||||
// out += " H"+its(c->heat);
|
||||
|
||||
/* // Hive debug
|
||||
if(c->land == laHive) {
|
||||
out += " [" + its(c->tmp) + " H" + its(int(c->heat));
|
||||
if(c->tmp >= 0 && c->tmp < size(buginfo) && buginfo[c->tmp].where == c) {
|
||||
buginfo_t b(buginfo[c->tmp]);
|
||||
for(int k=0; k<3; k++) out += ":" + its(b.dist[k]);
|
||||
for(int k=0; k<3; k++)
|
||||
for(int i=0; i<size(bugqueue[k]); i++)
|
||||
if(bugqueue[k][i] == c->tmp)
|
||||
out += " B"+its(k)+":"+its(i);
|
||||
}
|
||||
out += "]";
|
||||
} */
|
||||
|
||||
if(c->wall &&
|
||||
!((c->wall == waFloorA || c->wall == waFloorB || c->wall == waFloorC || c->wall == waFloorD) && c->item)) {
|
||||
out += ", "; out += XLAT1(winf[c->wall].name);
|
||||
|
||||
if(c->wall == waRose) out += " (" + its(7-rosephase) + ")";
|
||||
|
||||
if((c->wall == waBigTree || c->wall == waSmallTree) && c->land != laDryForest)
|
||||
help =
|
||||
"Trees in this forest can be chopped down. Big trees take two turns to chop down.";
|
||||
else if(c->wall != waSea && c->wall != waPalace)
|
||||
if(!((c->wall == waCavefloor || c->wall == waCavewall) && c->land == laEmerald))
|
||||
help = generateHelpForWall(c->wall);
|
||||
}
|
||||
|
||||
if(isActivable(c)) out += XLAT(" (touch to activate)");
|
||||
|
||||
if(hasTimeout(c)) out += " [" + turnstring(c->wparam) + "]";
|
||||
|
||||
if(isReptile(c->wall))
|
||||
out += " [" + turnstring((unsigned char) c->wparam) + "]";
|
||||
|
||||
if(c->monst) {
|
||||
out += ", "; out += XLAT1(minf[c->monst].name);
|
||||
if(hasHitpoints(c->monst))
|
||||
out += " (" + its(c->hitpoints)+" HP)";
|
||||
if(isMutantIvy(c))
|
||||
out += " (" + its((c->stuntime - mutantphase) & 15) + "*)";
|
||||
else if(c->stuntime)
|
||||
out += " (" + its(c->stuntime) + "*)";
|
||||
|
||||
if(c->monst == moTortoise && tortoise::seek())
|
||||
out += " " + tortoise::measure(tortoise::getb(c));
|
||||
|
||||
help = generateHelpForMonster(c->monst);
|
||||
}
|
||||
|
||||
if(c->item && !itemHiddenFromSight(c)) {
|
||||
out += ", ";
|
||||
out += XLAT1(iinf[c->item].name);
|
||||
if(c->item == itBarrow) out += " (x" + its(c->landparam) + ")";
|
||||
if(c->item == itBabyTortoise && tortoise::seek())
|
||||
out += " " + tortoise::measure(tortoise::babymap[c]);
|
||||
if(!c->monst) help = generateHelpForItem(c->item);
|
||||
}
|
||||
|
||||
if(isPlayerOn(c) && !shmup::on) out += XLAT(", you"), help = generateHelpForMonster(moPlayer);
|
||||
|
||||
shmup::addShmupHelp(out);
|
||||
|
||||
if(rosedist(c) == 1)
|
||||
out += ", wave of scent (front)";
|
||||
|
||||
if(rosedist(c) == 2)
|
||||
out += ", wave of scent (back)";
|
||||
|
||||
if(sword::at(c)) out += ", Energy Sword";
|
||||
|
||||
if(rosedist(c) || c->land == laRose || c->wall == waRose)
|
||||
help += s0 + "\n\n" + rosedesc;
|
||||
|
||||
if(isWarped(c) && !isWarped(c->land))
|
||||
out += ", warped";
|
||||
|
||||
if(isWarped(c))
|
||||
help += s0 + "\n\n" + warpdesc;
|
||||
}
|
||||
/*
|
||||
else if(cmode == emGraphConfig) {
|
||||
if(getcstat == 'a' && vid.sspeed > -4.99)
|
||||
out = XLAT("+5 = center instantly, -5 = do not center the map");
|
||||
else if(getcstat == 'a')
|
||||
out = XLAT("press Space or Home to center on the PC");
|
||||
else if(getcstat == 'w')
|
||||
out = XLAT("also hold Alt during the game to toggle high contrast");
|
||||
else if(getcstat == 'f')
|
||||
out = XLAT("Reduce the framerate limit to conserve CPU energy");
|
||||
}
|
||||
else if(cmode == emBasicConfig) {
|
||||
if(getcstat == 'c')
|
||||
out = XLAT("The axes help with keyboard movement");
|
||||
else if(getcstat == 'g')
|
||||
out = XLAT("Affects looks and grammar");
|
||||
#ifndef MOBILE
|
||||
else if(getcstat == 's')
|
||||
out = XLAT("Config file: %1", conffile);
|
||||
#endif
|
||||
else out = "";
|
||||
}
|
||||
else if(cmode == emDisplayMode) {
|
||||
if(getcstat == 'p') {
|
||||
if(autojoy)
|
||||
out = XLAT("joystick mode: automatic (release the joystick to move)");
|
||||
if(!autojoy)
|
||||
out = XLAT("joystick mode: manual (press a button to move)");
|
||||
}
|
||||
}
|
||||
else if(cmode == emChangeMode) {
|
||||
if(getcstat == 'h')
|
||||
out = XLAT("One wrong move and it is game over!");
|
||||
}
|
||||
*/
|
||||
|
||||
mouseovers = out;
|
||||
|
||||
#ifdef ROGUEVIZ
|
||||
rogueviz::describe(c);
|
||||
#endif
|
||||
|
||||
int col = linf[cwt.c->land].color;
|
||||
if(cwt.c->land == laRedRock) col = 0xC00000;
|
||||
|
||||
#ifndef MOBILE
|
||||
displayfr(vid.xres/2, vid.fsize, 2, vid.fsize, out, col, 8);
|
||||
#endif
|
||||
|
||||
if(mousey < vid.fsize * 3/2) getcstat = SDLK_F1;
|
||||
}
|
||||
|
||||
void showHelp() {
|
||||
cmode2 = smHelp;
|
||||
getcstat = SDLK_ESCAPE;
|
||||
if(help == "HELPFUN") {
|
||||
help_delegate();
|
||||
return;
|
||||
}
|
||||
|
||||
if(help == "@") help = buildHelpText();
|
||||
|
||||
string help2;
|
||||
if(help[0] == '@') {
|
||||
int iv = help.find("\t");
|
||||
int id = help.find("\n");
|
||||
dialog::init(help.substr(iv+1, id-iv-1), atoi(help.c_str()+1), 120, 100);
|
||||
dialog::addHelp(help.substr(id+1));
|
||||
}
|
||||
else {
|
||||
dialog::init("help", forecolor, 120, 100);
|
||||
dialog::addHelp(help);
|
||||
}
|
||||
|
||||
if(help == buildHelpText()) dialog::addItem("credits", 'c');
|
||||
|
||||
dialog::display();
|
||||
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
if(sym == SDLK_F1 && help != "@")
|
||||
help = "@";
|
||||
else if(uni == 'c')
|
||||
help = buildCredits();
|
||||
else if(doexiton(sym, uni))
|
||||
popScreen();
|
||||
};
|
||||
}
|
||||
|
||||
void gotoHelp(const string& h) {
|
||||
help = h;
|
||||
pushScreen(showHelp);
|
||||
}
|
460
hud.cpp
Normal file
460
hud.cpp
Normal file
@ -0,0 +1,460 @@
|
||||
purehookset hooks_stats;
|
||||
|
||||
int monsterclass(eMonster m) {
|
||||
if(isFriendly(m) || m == moTortoise) return 1;
|
||||
else if(isMonsterPart(m)) return 2;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
int glyphclass(int i) {
|
||||
if(i < ittypes) {
|
||||
eItem it = eItem(i);
|
||||
return itemclass(it) == IC_TREASURE ? 0 : 1;
|
||||
}
|
||||
else {
|
||||
eMonster m = eMonster(i-ittypes);
|
||||
return monsterclass(m) == 0 ? 2 : 3;
|
||||
}
|
||||
}
|
||||
|
||||
int subclass(int i) {
|
||||
if(i < ittypes)
|
||||
return itemclass(eItem(i));
|
||||
else
|
||||
return monsterclass(eMonster(i-ittypes));
|
||||
}
|
||||
|
||||
#define GLYPH_MARKTODO 1
|
||||
#define GLYPH_MARKOVER 2
|
||||
#define GLYPH_LOCAL 4
|
||||
#define GLYPH_IMPORTANT 8
|
||||
#define GLYPH_NONUMBER 16
|
||||
#define GLYPH_DEMON 32
|
||||
#define GLYPH_RUNOUT 64
|
||||
#define GLYPH_INPORTRAIT 128
|
||||
#define GLYPH_LOCAL2 256
|
||||
#define GLYPH_TARGET 512
|
||||
#define GLYPH_INSQUARE 1024
|
||||
|
||||
eGlyphsortorder glyphsortorder;
|
||||
|
||||
int zero = 0;
|
||||
|
||||
int& ikmerge(int i) {
|
||||
if(i < ittypes) return items[i];
|
||||
else if(i == ittypes) return zero;
|
||||
else return kills[i-ittypes];
|
||||
}
|
||||
|
||||
const int glyphs = ittypes + motypes;
|
||||
|
||||
int gfirsttime[glyphs], glasttime[glyphs], gcopy[glyphs], ikland[glyphs];
|
||||
int glyphorder[glyphs];
|
||||
|
||||
void updatesort() {
|
||||
for(int i=0; i<glyphs; i++) {
|
||||
if(ikmerge(i) && gfirsttime[i] == 0)
|
||||
gfirsttime[i] = ticks;
|
||||
if(ikmerge(i) != gcopy[i])
|
||||
gcopy[i] = items[i], glasttime[i] = ticks;
|
||||
}
|
||||
}
|
||||
|
||||
void preparesort() {
|
||||
for(int i=0; i<glyphs; i++) glyphorder[i] = i;
|
||||
for(int i=0; i<LAND_OVERX; i++) {
|
||||
eLand l = land_over[i];
|
||||
ikland[treasureType(l)] = i+1;
|
||||
for(int mi=0; mi<motypes; mi++)
|
||||
if(isNative(l, eMonster(mi)))
|
||||
ikland[mi+ittypes] = i+1;
|
||||
}
|
||||
glyphsortorder = gsoLand; updatesort();
|
||||
glyphsortorder = gsoFirstTop;
|
||||
}
|
||||
|
||||
int glyphsortkey = 0;
|
||||
|
||||
int glyphcorner(int i) {
|
||||
if(i < ittypes)
|
||||
return itemclass(eItem(i)) == IC_ORB ? 2 : 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool glyphsort(int i, int j) {
|
||||
if(subclass(i) != subclass(j))
|
||||
return subclass(i) < subclass(j);
|
||||
if(glyphsortorder == gsoFirstTop)
|
||||
return gfirsttime[i] < gfirsttime[j];
|
||||
if(glyphsortorder == gsoFirstBottom)
|
||||
return gfirsttime[i] > gfirsttime[j];
|
||||
if(glyphsortorder == gsoLastTop)
|
||||
return glasttime[i] > glasttime[j];
|
||||
if(glyphsortorder == gsoLastBottom)
|
||||
return glasttime[i] < glasttime[j];
|
||||
if(glyphsortorder == gsoValue)
|
||||
return ikmerge(i) > ikmerge(j);
|
||||
if(glyphsortorder == gsoLand)
|
||||
return ikland[i] < ikland[j];
|
||||
return 0;
|
||||
}
|
||||
|
||||
int glyphflags(int gid) {
|
||||
int f = 0;
|
||||
if(gid < ittypes) {
|
||||
eItem i = eItem(gid);
|
||||
if(itemclass(i) == IC_NAI) f |= GLYPH_NONUMBER;
|
||||
if(isElementalShard(i)) {
|
||||
f |= GLYPH_LOCAL | GLYPH_INSQUARE;
|
||||
if(i == localshardof(cwt.c->land)) f |= GLYPH_LOCAL2;
|
||||
}
|
||||
if(i == treasureType(cwt.c->land))
|
||||
f |= GLYPH_LOCAL | GLYPH_LOCAL2 | GLYPH_IMPORTANT | GLYPH_INSQUARE;
|
||||
if(i == itHolyGrail) {
|
||||
if(items[i] >= 3) f |= GLYPH_MARKOVER;
|
||||
}
|
||||
else if(itemclass(i) == IC_TREASURE) {
|
||||
if(items[i] >= 25 && items[i] < 100) f |= GLYPH_MARKOVER;
|
||||
else if(items[i] < 10) f |= GLYPH_MARKTODO;
|
||||
}
|
||||
else {
|
||||
f |= GLYPH_IMPORTANT | GLYPH_INSQUARE;
|
||||
if(itemclass(i) == IC_ORB && items[i] < 10) f |= GLYPH_RUNOUT;
|
||||
}
|
||||
if(i == orbToTarget) f |= GLYPH_TARGET;
|
||||
f |= GLYPH_INPORTRAIT;
|
||||
}
|
||||
else {
|
||||
eMonster m = eMonster(gid-ittypes);
|
||||
if(m == moLesser) f |= GLYPH_IMPORTANT | GLYPH_DEMON | GLYPH_INPORTRAIT | GLYPH_INSQUARE;
|
||||
int isnat = isNative(cwt.c->land, m);
|
||||
if(isnat) f |= GLYPH_LOCAL | GLYPH_IMPORTANT | GLYPH_INPORTRAIT | GLYPH_INSQUARE;
|
||||
if(isnat == 2) f |= GLYPH_LOCAL2;
|
||||
if(m == monsterToSummon) f |= GLYPH_TARGET;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
|
||||
bool graphglyph() {
|
||||
return vid.graphglyph == 2 || (vid.graphglyph == 1 && vid.monmode);
|
||||
}
|
||||
|
||||
bool displayglyph(int cx, int cy, int buttonsize, char glyph, int color, int qty, int flags, int id) {
|
||||
|
||||
bool b =
|
||||
mousex >= cx && mousex < cx+buttonsize && mousey >= cy-buttonsize/2 && mousey <= cy-buttonsize/2+buttonsize;
|
||||
|
||||
int glsize = buttonsize;
|
||||
if(glyph == '%' || glyph == 'M' || glyph == 'W') glsize = glsize*4/5;
|
||||
|
||||
if(graphglyph()) {
|
||||
initquickqueue();
|
||||
if(id >= ittypes) {
|
||||
eMonster m = eMonster(id - ittypes);
|
||||
int bsize = buttonsize;
|
||||
if(m == moKrakenH) bsize /= 3;
|
||||
if(m == moKrakenT || m == moDragonTail) bsize /= 2;
|
||||
if(m == moSlime) bsize = (2*bsize+1)/3;
|
||||
transmatrix V = atscreenpos(cx+buttonsize/2, cy, bsize);
|
||||
int mcol = color;
|
||||
mcol -= (color & 0xFCFCFC) >> 2;
|
||||
drawMonsterType(m, NULL, V, mcol, 0);
|
||||
}
|
||||
else {
|
||||
eItem it = eItem(id);
|
||||
int bsize = buttonsize;
|
||||
if(glyph =='*') bsize *= 2;
|
||||
if(glyph == '$') bsize = (bsize*5+2)/3;
|
||||
if(glyph == 'o') bsize = (bsize*3+1)/2;
|
||||
if(glyph == 't') bsize = bsize*5/2;
|
||||
if(it == itWarning) bsize *= 2;
|
||||
if(it == itBombEgg || it == itTrollEgg || it == itDodeca) bsize = bsize*3/2;
|
||||
transmatrix V = atscreenpos(cx+buttonsize/2, cy, bsize);
|
||||
int icol = color;
|
||||
icol -= (color & 0xFCFCFC) >> 2;
|
||||
int ic = itemclass(it);
|
||||
drawItemType(it, NULL, V, icol, (ic == IC_ORB || ic == IC_NAI) ? ticks*2 : ((glyph == 't' && qty%5) || it == itOrbYendor) ? ticks/2 : 0, false);
|
||||
}
|
||||
quickqueue();
|
||||
}
|
||||
else if(glyph == '*')
|
||||
displaychr(cx + buttonsize/2, cy+buttonsize/4, 0, glsize*3/2, glyph, darkenedby(color, b?0:1));
|
||||
else
|
||||
displaychr(cx + buttonsize/2, cy, 0, glsize, glyph, darkenedby(color, b?0:1));
|
||||
|
||||
string fl = "";
|
||||
string str = its(qty);
|
||||
|
||||
if(flags & GLYPH_TARGET) fl += "!";
|
||||
if(flags & GLYPH_LOCAL2) fl += "+";
|
||||
else if(flags & GLYPH_LOCAL) fl += "-";
|
||||
if(flags & GLYPH_DEMON) fl += "X";
|
||||
if(flags & GLYPH_MARKOVER) str += "!";
|
||||
|
||||
if(fl != "")
|
||||
displaystr(cx + buttonsize, cy-buttonsize/2 + buttonsize/4, 0, buttonsize/2, fl, darkenedby(color, 0), 16);
|
||||
|
||||
if(flags & GLYPH_NONUMBER) str = "";
|
||||
|
||||
int bsize =
|
||||
(qty < 10 && (flags & (GLYPH_MARKTODO | GLYPH_RUNOUT))) ? buttonsize*3/4 :
|
||||
qty < 100 ? buttonsize / 2 :
|
||||
buttonsize / 3;
|
||||
if(str != "")
|
||||
displayfr(cx + buttonsize, cy + buttonsize/2 - bsize/2, 1, bsize, str, color, 16);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
void displayglyph2(int cx, int cy, int buttonsize, int i) {
|
||||
|
||||
char glyph = i < ittypes ? iinf[i].glyph : minf[i-ittypes].glyph;
|
||||
int color = i < ittypes ? iinf[i].color : minf[i-ittypes].color;
|
||||
int imp = glyphflags(i);
|
||||
|
||||
if(displayglyph(cx, cy, buttonsize, glyph, color, ikmerge(i), imp, i)) {
|
||||
instat = true;
|
||||
getcstat = SDLK_F1;
|
||||
if(i < ittypes) {
|
||||
eItem it = eItem(i);
|
||||
int t = itemclass(it);
|
||||
if(t == IC_TREASURE)
|
||||
mouseovers = XLAT("treasure collected: %1", it);
|
||||
if(t == IC_OTHER)
|
||||
mouseovers = XLAT("objects found: %1", it);
|
||||
if(t == IC_NAI)
|
||||
mouseovers = XLAT("%1", it);
|
||||
if(t == IC_ORB)
|
||||
mouseovers = XLAT("orb power: %1", eItem(i));
|
||||
if(it == itGreenStone) {
|
||||
mouseovers += XLAT(" (click to drop)");
|
||||
getcstat = 'g';
|
||||
}
|
||||
if(imp & GLYPH_LOCAL) mouseovers += XLAT(" (local treasure)");
|
||||
help = generateHelpForItem(it);
|
||||
}
|
||||
else {
|
||||
eMonster m = eMonster(i-ittypes);
|
||||
if(isMonsterPart(m))
|
||||
mouseovers = s0 + XLAT("parts destroyed: %1", m);
|
||||
else if(isFriendly(m) && isNonliving(m))
|
||||
mouseovers = s0 + XLAT("friends destroyed: %1", m);
|
||||
else if(isFriendly(m))
|
||||
mouseovers = s0 + XLAT("friends killed: %1", m);
|
||||
else if(isNonliving(m))
|
||||
mouseovers = s0 + XLAT("monsters destroyed: %1", m);
|
||||
else if(m == moTortoise)
|
||||
mouseovers = s0 + XLAT("animals killed: %1", m);
|
||||
else
|
||||
mouseovers = s0 + XLAT("monsters killed: %1", m);
|
||||
if(imp & GLYPH_LOCAL2) mouseovers += XLAT(" (killing increases treasure spawn)");
|
||||
else if(imp & GLYPH_LOCAL) mouseovers += XLAT(" (appears here)");
|
||||
help = generateHelpForMonster(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool nohud, nomenukey;
|
||||
|
||||
hookset<bool()> *hooks_prestats;
|
||||
|
||||
void drawStats() {
|
||||
callhandlers(false, hooks_prestats);
|
||||
#ifdef ROGUEVIZ
|
||||
if(rogueviz::on || nohud) return;
|
||||
#endif
|
||||
if(viewdists && sidescreen) {
|
||||
distcolors[0] = forecolor;
|
||||
dialog::init("");
|
||||
int qty[64];
|
||||
vector<cell*>& ac = currentmap->allcells();
|
||||
for(int i=0; i<64; i++) qty[i] = 0;
|
||||
for(int i=0; i<size(ac); i++) {
|
||||
int d = celldistance(ac[i], cwt.c);
|
||||
if(d >= 0 && d < 64) qty[d]++;
|
||||
}
|
||||
if(geometry == gNormal)
|
||||
for(int i=purehepta?6:8; i<=15; i++)
|
||||
qty[i] =
|
||||
purehepta ?
|
||||
3*qty[i-1] - qty[i-2]
|
||||
: qty[i-1] + qty[i-2] + qty[i-3] - qty[i-4];
|
||||
if(geometry == gEuclid)
|
||||
for(int i=8; i<=15; i++) qty[i] = 6*i;
|
||||
for(int i=0; i<64; i++) if(qty[i])
|
||||
dialog::addInfo(its(qty[i]), distcolors[i&7]);
|
||||
if(geometry == gNormal && !purehepta) {
|
||||
dialog::addBreak(200);
|
||||
dialog::addHelp("a(d+4) = a(d+3) + a(d+2) + a(d+1) - a(d)");
|
||||
dialog::addInfo("a(d) ~ 1.72208áµ", forecolor);
|
||||
}
|
||||
if(geometry == gNormal && purehepta) {
|
||||
dialog::addBreak(200);
|
||||
dialog::addHelp("a(d+2) = 3a(d+1) - a(d+2)");
|
||||
dialog::addInfo("a(d) ~ 2.61803áµ", forecolor);
|
||||
}
|
||||
if(geometry == gEuclid) {
|
||||
dialog::addBreak(300);
|
||||
dialog::addInfo("a(d) = 6d", forecolor);
|
||||
}
|
||||
dialog::display();
|
||||
}
|
||||
if(sidescreen) return;
|
||||
|
||||
if(vid.xres > vid.yres * 85/100 && vid.yres > vid.xres * 85/100) {
|
||||
int bycorner[4];
|
||||
for(int u=0; u<4; u++) bycorner[u] = 0;
|
||||
for(int i=0; i<glyphs; i++) if(ikmerge(i) && (glyphflags(i) & GLYPH_INSQUARE))
|
||||
bycorner[glyphcorner(i)]++;
|
||||
updatesort();
|
||||
stable_sort(glyphorder, glyphorder+glyphs, glyphsort);
|
||||
int rad = min(vid.xres, vid.yres) / 2;
|
||||
for(int cor=0; cor<3; cor++) {
|
||||
for(int a=5; a<41; a++) {
|
||||
int s = min(vid.xres, vid.yres) / a;
|
||||
int spots = 0;
|
||||
for(int u=vid.fsize; u<vid.xres/2-s; u += s)
|
||||
for(int v=vid.fsize; v<vid.yres/2-s; v += s)
|
||||
if(hypot(vid.xres/2-u-s, vid.yres/2-v-s) > rad) {
|
||||
spots++;
|
||||
}
|
||||
if(spots >= bycorner[cor] && spots >= 3) {
|
||||
int next = 0;
|
||||
vector<int> glyphstoshow;
|
||||
for(int i=0; i<glyphs; i++) {
|
||||
int g = glyphorder[i];
|
||||
if(ikmerge(g) && (glyphflags(g) & GLYPH_INSQUARE) && glyphcorner(g) == cor)
|
||||
glyphstoshow.push_back(g);
|
||||
}
|
||||
for(int u=vid.fsize; u<vid.xres/2-s; u += s)
|
||||
for(int v=vid.fsize; v<vid.yres/2-s; v += s)
|
||||
if(hypot(vid.xres/2-u-s, vid.yres/2-v-s) > rad) {
|
||||
if(next >= size(glyphstoshow)) break;
|
||||
|
||||
int cx = u;
|
||||
int cy = v + s/2;
|
||||
if(cor&1) cx = vid.xres-1-s-cx;
|
||||
if(cor&2) cy = vid.yres-1-cy;
|
||||
|
||||
displayglyph2(cx, cy, s, glyphstoshow[next++]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
instat = false;
|
||||
bool portrait = vid.xres < vid.yres;
|
||||
int colspace = portrait ? (vid.yres - vid.xres - vid.fsize*3) : (vid.xres - vid.yres - 16) / 2;
|
||||
int rowspace = portrait ? vid.xres - 16 : vid.yres - vid.fsize * 4;
|
||||
int colid[4], rowid[4];
|
||||
int maxbyclass[4];
|
||||
for(int z=0; z<4; z++) maxbyclass[z] = 0;
|
||||
for(int i=0; i<glyphs; i++) if(ikmerge(i))
|
||||
if(!portrait || (glyphflags(i) | GLYPH_INPORTRAIT))
|
||||
maxbyclass[glyphclass(i)]++;
|
||||
int buttonsize;
|
||||
int columns, rows;
|
||||
bool imponly = false;
|
||||
int minsize = vid.fsize * (portrait ? 4 : 2);
|
||||
rows = 0;
|
||||
while((buttonsize = minsize - vid.killreduction)) {
|
||||
columns = colspace / buttonsize;
|
||||
rows = rowspace / buttonsize;
|
||||
int coltaken = 0;
|
||||
for(int z=0; z<4; z++) {
|
||||
if(z == 2 && !portrait) {
|
||||
if(coltaken > columns) { vid.killreduction++; continue; }
|
||||
coltaken = 0;
|
||||
}
|
||||
colid[z] = coltaken, rowid[z] = 0,
|
||||
coltaken += (maxbyclass[z] + rows-1) / rows;
|
||||
}
|
||||
if(coltaken > columns) { vid.killreduction++; continue; }
|
||||
break;
|
||||
}
|
||||
|
||||
if(buttonsize <= vid.fsize*3/4) {
|
||||
imponly = true; buttonsize = minsize;
|
||||
rows = rowspace / buttonsize; if(!rows) return;
|
||||
colid[0] = 0; colid[2] = portrait ? 1 : 0;
|
||||
}
|
||||
|
||||
updatesort();
|
||||
stable_sort(glyphorder, glyphorder+glyphs, glyphsort);
|
||||
|
||||
for(int i0=0; i0<glyphs; i0++) {
|
||||
int i = glyphorder[i0];
|
||||
if(!ikmerge(i)) continue;
|
||||
int z = glyphclass(i);
|
||||
int imp = glyphflags(i);
|
||||
if(imponly) { z &=~1; if(!(imp & GLYPH_IMPORTANT)) continue; }
|
||||
|
||||
int cx, cy;
|
||||
if(portrait)
|
||||
cx = 8 + buttonsize * rowid[z], cy = vid.fsize*2 + buttonsize * (colid[z]) + buttonsize/2;
|
||||
else
|
||||
cx = 8 + buttonsize * (colid[z]), cy = vid.fsize * 3 + buttonsize * rowid[z];
|
||||
|
||||
if(!portrait && z < 2) cx = vid.xres - cx - buttonsize;
|
||||
|
||||
rowid[z]++; if(rowid[z] >= rows) rowid[z] = 0, colid[z]++;
|
||||
|
||||
displayglyph2(cx, cy, buttonsize, i);
|
||||
}
|
||||
|
||||
string s0;
|
||||
if(displayButtonS(vid.xres - 8, vid.fsize, "score: " + its(gold()), forecolor, 16, vid.fsize)) {
|
||||
mouseovers = XLAT("Your total wealth"),
|
||||
instat = true,
|
||||
getcstat = SDLK_F1,
|
||||
help = helptitle(XLAT("Your total wealth"), 0xFFD500) +
|
||||
XLAT(
|
||||
"The total value of the treasure you have collected.\n\n"
|
||||
"Every world type contains a specific type of treasure, worth 1 $$$; "
|
||||
"your goal is to collect as much treasure as possible, but every treasure you find "
|
||||
"causes more enemies to hunt you in its native land.\n\n"
|
||||
"Orbs of Yendor are worth 50 $$$ each.\n\n"
|
||||
);
|
||||
}
|
||||
if(displayButtonS(8, vid.fsize, "kills: " + its(tkills()), forecolor, 0, vid.fsize)) {
|
||||
instat = true,
|
||||
getcstat = SDLK_F1,
|
||||
mouseovers = XLAT("Your total kills")+": " + its(tkills()),
|
||||
help = helptitle(XLAT("Your total kills") + ": " + its(tkills()), 0x404040) +
|
||||
XLAT(
|
||||
"In most lands, more treasures are generated with each enemy native to this land you kill. "
|
||||
"Moreover, 100 kills is a requirement to enter the Graveyard and the Hive.\n\n"
|
||||
"Friendly creatures and parts of monsters (such as the Ivy) do appear in the list, "
|
||||
"but are not counted in the total kill count.");
|
||||
}
|
||||
if(displayButtonS(4, vid.yres - 4 - vid.fsize/2, s0+VER+ " fps: " + its(calcfps()), 0x202020, 0, vid.fsize/2)) {
|
||||
mouseovers = XLAT("frames per second"),
|
||||
getcstat = SDLK_F1,
|
||||
instat = true,
|
||||
help =
|
||||
helptitle(XLAT("frames per second"), 0xFF4040) +
|
||||
XLAT(
|
||||
"The higher the number, the smoother the animations in the game. "
|
||||
"If you find that animations are not smooth enough, you can try "
|
||||
"to change the options "
|
||||
) +
|
||||
#ifdef IOS
|
||||
XLAT(
|
||||
"(in the MENU). You can reduce the sight range, this should make "
|
||||
"the animations smoother.");
|
||||
#else
|
||||
XLAT(
|
||||
"(press v) and change the wall/monster mode to ASCII, or change "
|
||||
"the resolution.");
|
||||
#endif
|
||||
}
|
||||
|
||||
achievement_display();
|
||||
|
||||
callhooks(hooks_stats);
|
||||
}
|
||||
|
28
hyper.cpp
28
hyper.cpp
@ -387,11 +387,11 @@ else if(args()[0] == '-' && args()[1] == x && args()[2] == '0') { if(curphase ==
|
||||
return 0;
|
||||
}
|
||||
|
||||
hookset<bool(int argc, char** argv)> *hooks_main;
|
||||
|
||||
#ifndef NOMAIN
|
||||
int main(int argc, char **argv) {
|
||||
#ifdef EXTRA_MAIN
|
||||
if(extra::main(argc, argv)) return 0;
|
||||
#endif
|
||||
if(callhandlers(false, hooks_main, argc, argv)) return 0;
|
||||
#ifndef WEB
|
||||
#ifdef LINUX
|
||||
moreStack();
|
||||
@ -409,25 +409,25 @@ int main(int argc, char **argv) {
|
||||
#endif
|
||||
|
||||
#ifdef USE_COMMANDLINE
|
||||
purehookset hooks_config;
|
||||
|
||||
hookset<int()> *hooks_args;
|
||||
|
||||
namespace arg {
|
||||
int argc; char **argv;
|
||||
|
||||
auto ah = addHook(hooks_args, 0, readCommon);
|
||||
|
||||
void read(int phase) {
|
||||
curphase = phase;
|
||||
#ifdef EXTRA_CONFIG
|
||||
extra::config();
|
||||
#endif
|
||||
callhooks(hooks_config);
|
||||
while(argc) {
|
||||
int r;
|
||||
r = readCommon(); if(r == 2) return; if(r == 0) { lshift(); continue; }
|
||||
#ifdef EXTRA_ARG
|
||||
r = extra::arg(); if(r == 2) return; if(r == 0) { lshift(); continue; }
|
||||
#endif
|
||||
#ifdef ROGUEVIZ
|
||||
r = rogueviz::readArgs(); if(r == 2) return; if(r == 0) { lshift(); continue; }
|
||||
#endif
|
||||
for(auto& h: *hooks_args) {
|
||||
int r = h.second(); if(r == 2) return; if(r == 0) { lshift(); goto cont; }
|
||||
}
|
||||
printf("Unknown option: %s\n", args());
|
||||
exit(3);
|
||||
cont: ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
223
hyper.h
223
hyper.h
@ -151,6 +151,7 @@ void loadcs(FILE *f, charstyle& cs, int vernum);
|
||||
|
||||
namespace multi {
|
||||
|
||||
extern bool shmupcfg;
|
||||
void recall();
|
||||
extern cell *origpos[MAXPLAYER], *origtarget[MAXPLAYER];
|
||||
extern int players;
|
||||
@ -179,6 +180,10 @@ namespace multi {
|
||||
int deadzoneval[MAXJOY][MAXAXE];
|
||||
};
|
||||
|
||||
void saveConfig(FILE *f);
|
||||
void loadConfig(FILE *f);
|
||||
void initConfig();
|
||||
|
||||
charstyle scs[MAXPLAYER];
|
||||
|
||||
bool playerActive(int p);
|
||||
@ -186,9 +191,11 @@ namespace multi {
|
||||
cell *multiPlayerTarget(int i);
|
||||
void checklastmove();
|
||||
void leaveGame(int i);
|
||||
void showShmupConfig();
|
||||
}
|
||||
|
||||
namespace shmup {
|
||||
using namespace multi;
|
||||
void recall();
|
||||
extern bool on;
|
||||
extern bool safety;
|
||||
@ -217,6 +224,7 @@ namespace shmup {
|
||||
void virtualRebase(cell*& base, transmatrix& at, bool tohex);
|
||||
void virtualRebase(shmup::monster *m, bool tohex);
|
||||
void fixStorage();
|
||||
void addShmupHelp(string& out);
|
||||
}
|
||||
|
||||
// graph
|
||||
@ -228,8 +236,6 @@ void showMissionScreen();
|
||||
void restartGraph();
|
||||
void resetmusic();
|
||||
|
||||
void cleargraphmemory();
|
||||
|
||||
void drawFlash(cell* c);
|
||||
void drawBigFlash(cell* c);
|
||||
void drawParticle(cell *c, int col, int maxspeed = 100);
|
||||
@ -319,6 +325,7 @@ struct videopar {
|
||||
int flashtime;
|
||||
|
||||
int wallmode, monmode, axes;
|
||||
bool revcontrol;
|
||||
|
||||
// for OpenGL
|
||||
float scrdist;
|
||||
@ -331,6 +338,7 @@ struct videopar {
|
||||
#define AA_POLY 8
|
||||
#define AA_LINEWIDTH 16
|
||||
#define AA_FONT 32
|
||||
#define AA_MULTI 64
|
||||
ld linewidth;
|
||||
|
||||
int joyvalue, joyvalue2, joypanthreshold;
|
||||
@ -351,30 +359,11 @@ struct videopar {
|
||||
|
||||
extern videopar vid;
|
||||
|
||||
enum emtype {emNormal, emHelp,
|
||||
emMenu,
|
||||
emBasicConfig, emGraphConfig, emDisplayMode,
|
||||
emChangeMode, emCustomizeChar,
|
||||
emQuit, emDraw, emScores, emPickEuclidean,
|
||||
emPickScores,
|
||||
emShmupConfig,
|
||||
emMapEditor,
|
||||
emPatternPicker,
|
||||
emOverview,
|
||||
emNetgen,
|
||||
emYendor, emTactic, emRugConfig,
|
||||
emConformal,
|
||||
emProgress,
|
||||
emCheatMenu, emLeader,
|
||||
emJoyConfig,
|
||||
emColor, emNumber,
|
||||
em3D, emRogueviz,
|
||||
emLinepattern,
|
||||
emPeace, emInventory,
|
||||
emSlideshows
|
||||
};
|
||||
extern vector< function<void()> > screens;
|
||||
|
||||
extern emtype cmode, lastmode;
|
||||
template<class T> void pushScreen(T& x) { screens.push_back(x); }
|
||||
inline void popScreen() { screens.pop_back(); }
|
||||
inline void popScreenAll() { while(size(screens)>1) popScreen(); }
|
||||
|
||||
extern transmatrix View; // current rotation, relative to viewctr
|
||||
extern transmatrix cwtV; // player-relative view
|
||||
@ -390,26 +379,36 @@ namespace mapeditor {
|
||||
extern char whichCanvas;
|
||||
extern int displaycodes;
|
||||
int generateCanvas(cell *c);
|
||||
void clearModelCells();
|
||||
void applyModelcell(cell *c);
|
||||
int realpattern(cell *c);
|
||||
int patterndir(cell *c, char w = whichPattern);
|
||||
int subpattern(cell *c);
|
||||
extern cell *drawcell;
|
||||
void initdraw(cell *c);
|
||||
void showMapEditor();
|
||||
void showDrawEditor();
|
||||
}
|
||||
|
||||
#ifndef NORUG
|
||||
namespace rug {
|
||||
extern bool rugged;
|
||||
extern bool renderonce;
|
||||
extern bool rendernogl;
|
||||
extern int texturesize;
|
||||
extern double scale;
|
||||
void show();
|
||||
void init();
|
||||
void close();
|
||||
void actDraw();
|
||||
void select();
|
||||
void buildVertexInfo(cell *c, transmatrix V);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define HASLINEVIEW
|
||||
#include <complex>
|
||||
typedef complex<ld> cld;
|
||||
|
||||
namespace conformal {
|
||||
extern bool on;
|
||||
extern vector<pair<cell*, eMonster> > killhistory;
|
||||
@ -417,10 +416,15 @@ namespace conformal {
|
||||
extern vector<cell*> movehistory;
|
||||
extern bool includeHistory;
|
||||
extern int rotation;
|
||||
extern bool autoband;
|
||||
extern bool autobandhistory;
|
||||
extern bool dospiral;
|
||||
extern ld lvspeed;
|
||||
extern int bandsegment;
|
||||
extern int bandhalf;
|
||||
|
||||
void create();
|
||||
void clear();
|
||||
void handleKey();
|
||||
void show();
|
||||
void apply();
|
||||
void movetophase();
|
||||
@ -428,11 +432,16 @@ namespace conformal {
|
||||
|
||||
extern vector<shmup::monster*> v;
|
||||
extern double phase;
|
||||
void applyIB();
|
||||
}
|
||||
|
||||
namespace polygonal {
|
||||
static const int MSI = 120;
|
||||
extern int SI;
|
||||
extern ld STAR;
|
||||
extern int deg;
|
||||
extern complex<ld> coef[MSI];
|
||||
extern int maxcoef, coefid;
|
||||
void solve();
|
||||
pair<ld, ld> compute(ld x, ld y);
|
||||
}
|
||||
@ -805,12 +814,15 @@ namespace dialog {
|
||||
int position;
|
||||
};
|
||||
|
||||
extern vector<item> items;
|
||||
|
||||
item& lastItem();
|
||||
extern unsigned int *palette;
|
||||
|
||||
void addSelItem(string body, string value, int key);
|
||||
void addBoolItem(string body, bool value, int key);
|
||||
void addColorItem(string body, int value, int key);
|
||||
void openColorDialog(int& col, unsigned int *pal);
|
||||
void openColorDialog(int& col, unsigned int *pal = palette);
|
||||
void addHelp(string body);
|
||||
void addInfo(string body, int color = 0xC0C0C0);
|
||||
void addItem(string body, int key);
|
||||
@ -821,9 +833,6 @@ namespace dialog {
|
||||
void init(string title, int color = 0xE8E8E8, int scale = 150, int brk = 60);
|
||||
void display();
|
||||
|
||||
void drawColorDialog(int color);
|
||||
int handleKeyColor(int sym, int uni, int& color);
|
||||
|
||||
void editNumber(ld& x, ld vmin, ld vmax, ld step, ld dft, string title, string help);
|
||||
void editNumber(int& x, int vmin, int vmax, int step, int dft, string title, string help);
|
||||
void scaleLog();
|
||||
@ -1002,6 +1011,7 @@ extern eGlyphsortorder glyphsortorder;
|
||||
namespace rogueviz {
|
||||
extern bool on;
|
||||
string describe(shmup::monster *m);
|
||||
void describe(cell *c);
|
||||
void activate(shmup::monster *m);
|
||||
void drawVertex(const transmatrix &V, cell *c, shmup::monster *m);
|
||||
bool virt(shmup::monster *m);
|
||||
@ -1011,6 +1021,8 @@ namespace rogueviz {
|
||||
int readArgs();
|
||||
void close();
|
||||
void mark(cell *c);
|
||||
void showMenu();
|
||||
string makehelp();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1149,11 +1161,10 @@ namespace tour {
|
||||
extern string slidecommand;
|
||||
extern int currentslide;
|
||||
|
||||
bool handleKeyTour(int sym, int uni);
|
||||
|
||||
enum presmode {
|
||||
pmStartAll = 0,
|
||||
pmStart = 1, pmFrame = 2, pmStop = 3, pmKey = 4, pmRestart = 5,
|
||||
pmAfterFrame = 6,
|
||||
pmGeometry = 11, pmGeometryReset = 13, pmGeometryStart = 15
|
||||
};
|
||||
|
||||
@ -1192,7 +1203,6 @@ namespace tour {
|
||||
|
||||
namespace ss {
|
||||
void showMenu();
|
||||
void handleKey(int sym, int uni);
|
||||
void list(slide*);
|
||||
}
|
||||
|
||||
@ -1218,6 +1228,8 @@ extern bool dronemode;
|
||||
|
||||
extern ld whatever;
|
||||
|
||||
enum screenmode { smMenu, smNormal, smMission, smHelp, smMap, smDraw, smNumber, smShmupConfig, smOverview };
|
||||
|
||||
namespace linepatterns {
|
||||
|
||||
enum ePattern {
|
||||
@ -1242,6 +1254,7 @@ namespace linepatterns {
|
||||
void clearAll();
|
||||
void setColor(ePattern id, int col);
|
||||
void drawAll();
|
||||
void showMenu();
|
||||
};
|
||||
|
||||
transmatrix ddspin(cell *c, int d, int bonus = 0);
|
||||
@ -1290,3 +1303,145 @@ bool graphglyph();
|
||||
extern bool hiliteclick;
|
||||
extern int antialiaslines;
|
||||
extern int ringcolor;
|
||||
|
||||
#include <functional>
|
||||
|
||||
template<class T> class hookset : public map<int, function<T>> {};
|
||||
typedef hookset<void()> *purehookset;
|
||||
|
||||
template<class T, class U> int addHook(hookset<T>*& m, int prio, const U& hook) {
|
||||
if(!m) m = new hookset<T> ();
|
||||
(*m)[prio] = hook;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern purehookset hooks_frame, hooks_stats, clearmemory;
|
||||
|
||||
template<class T, class... U> void callhooks(hookset<T> *h, U... args) {
|
||||
if(h) for(auto& p: *h) p.second(args...);
|
||||
}
|
||||
|
||||
template<class T, class V, class... U> V callhandlers(V zero, hookset<T> *h, U... args) {
|
||||
if(h) for(auto& p: *h) {
|
||||
auto z = p.second(args...);
|
||||
if(z != zero) return z;
|
||||
}
|
||||
return zero;
|
||||
}
|
||||
|
||||
extern hookset<bool(int sym, int uni)> *hooks_handleKey;
|
||||
extern hookset<void(cell *c, const transmatrix& V)> *hooks_drawcell;
|
||||
extern hookset<bool(int argc, char** argv)> *hooks_main;
|
||||
extern hookset<int()> *hooks_args;
|
||||
extern hookset<eLand(eLand)> *hooks_nextland;
|
||||
|
||||
// hooks to extend HyperRogue with an external program
|
||||
// start compilation from another file which defines EXTRA_..., includes
|
||||
// hyper.cpp, then defines the necessary functions
|
||||
|
||||
extern ld shiftmul;
|
||||
void initcs(charstyle &cs);
|
||||
charstyle& getcs();
|
||||
|
||||
struct msginfo {
|
||||
int stamp;
|
||||
char flashout;
|
||||
char spamtype;
|
||||
int quantity;
|
||||
string msg;
|
||||
};
|
||||
|
||||
extern vector<msginfo> msgs;
|
||||
void flashMessages();
|
||||
|
||||
extern int lightat, safetyat;
|
||||
|
||||
int watercolor(int phase);
|
||||
bool doHighlight();
|
||||
string buildHelpText();
|
||||
string buildCredits();
|
||||
void setAppropriateOverview();
|
||||
bool quitsaves();
|
||||
extern bool sidescreen;
|
||||
|
||||
static const char* COLORBAR = "###";
|
||||
int textwidth(int siz, const string &str);
|
||||
#define GLERR(call) glError(call, __FILE__, __LINE__)
|
||||
|
||||
extern bool gtouched, mousepressed, mousemoved, actonrelease;
|
||||
extern bool inslider;
|
||||
|
||||
#ifdef ROGUEVIZ
|
||||
#define DOSHMUP (shmup::on || rogueviz::on)
|
||||
#else
|
||||
#define DOSHMUP shmup::on
|
||||
#endif
|
||||
|
||||
extern bool outoffocus;
|
||||
extern int frames;
|
||||
extern transmatrix playerV;
|
||||
extern bool didsomething;
|
||||
extern void drawStats();
|
||||
extern int calcfps();
|
||||
extern int distcolors[8];
|
||||
|
||||
extern eItem orbToTarget;
|
||||
extern eMonster monsterToSummon;
|
||||
|
||||
void panning(hyperpoint hf, hyperpoint ht);
|
||||
extern transmatrix sphereflip;
|
||||
|
||||
void initConfig();
|
||||
void loadConfig();
|
||||
|
||||
extern bool auraNOGL;
|
||||
|
||||
#ifndef NOSDL
|
||||
extern void initJoysticks();
|
||||
extern int joyx, joyy, panjoyx, panjoyy;
|
||||
extern bool autojoy;
|
||||
extern movedir joydir;
|
||||
extern SDL_Joystick* sticks[8];
|
||||
extern int numsticks;
|
||||
void closeJoysticks();
|
||||
#endif
|
||||
|
||||
void preparesort();
|
||||
|
||||
#ifdef MOBILE
|
||||
#define SHMUPTITLE "shoot'em up mode"
|
||||
#else
|
||||
#define SHMUPTITLE "shoot'em up and multiplayer"
|
||||
#endif
|
||||
|
||||
bool dodrawcell(cell *c);
|
||||
void drawcell(cell *c, transmatrix V, int spinv, bool mirrored);
|
||||
extern double downspin;
|
||||
|
||||
extern int frameid;
|
||||
extern bool leftclick;
|
||||
void clearMemory();
|
||||
|
||||
extern function <void(int sym, int uni)> keyhandler;
|
||||
void gmodekeys(int sym, int uni);
|
||||
|
||||
void switchGL();
|
||||
void switchFullscreen();
|
||||
extern screenmode cmode2;
|
||||
|
||||
void gotoHelp(const string& h);
|
||||
void showCustomizeChar();
|
||||
void showScores();
|
||||
void showPickScores();
|
||||
void showCheatMenu();
|
||||
void showDisplayMode();
|
||||
void showChangeMode();
|
||||
void showEuclideanMenu();
|
||||
void show3D();
|
||||
void gameoverscreen();
|
||||
void showJoyConfig();
|
||||
|
||||
void gamescreen(int darken);
|
||||
void showMission();
|
||||
void handleKeyQuit(int sym, int uni);
|
||||
void handlePanning(int sym, int uni);
|
||||
|
@ -474,3 +474,5 @@ transmatrix mzscale(const transmatrix& t, double fac) {
|
||||
return res;
|
||||
}
|
||||
|
||||
transmatrix pushone() { return euclid ? eupush(1, 0) : xpush(sphere?.5 : 1); }
|
||||
|
||||
|
561
hypgraph.cpp
Normal file
561
hypgraph.cpp
Normal file
@ -0,0 +1,561 @@
|
||||
ld ghx, ghy, ghgx, ghgy;
|
||||
hyperpoint ghpm = C0;
|
||||
|
||||
void ghcheck(hyperpoint &ret, const hyperpoint &H) {
|
||||
if(hypot(ret[0]-ghx, ret[1]-ghy) < hypot(ghgx-ghx, ghgy-ghy)) {
|
||||
ghpm = H; ghgx = ret[0]; ghgy = ret[1];
|
||||
}
|
||||
}
|
||||
|
||||
void camrotate(ld& hx, ld& hy) {
|
||||
ld cam = vid.camera_angle * M_PI / 180;
|
||||
GLfloat cc = cos(cam);
|
||||
GLfloat ss = sin(cam);
|
||||
ld ux = hx, uy = hy * cc + ss, uz = cc - ss * hy;
|
||||
hx = ux / uz, hy = uy / uz;
|
||||
}
|
||||
|
||||
hyperpoint gethyper(ld x, ld y) {
|
||||
|
||||
ld hx = (x - vid.xcenter) / vid.radius;
|
||||
ld hy = (y - vid.ycenter) / vid.radius;
|
||||
|
||||
if(pmodel) {
|
||||
ghx = hx, ghy = hy;
|
||||
return ghpm;
|
||||
}
|
||||
|
||||
if(euclid)
|
||||
return hpxy(hx * (EUCSCALE + vid.alphax), hy * (EUCSCALE + vid.alphax));
|
||||
|
||||
if(vid.camera_angle) camrotate(hx, hy);
|
||||
|
||||
ld hr = hx*hx+hy*hy;
|
||||
|
||||
if(hr > .9999 && !sphere) return Hypc;
|
||||
|
||||
// hz*hz-(hx/(hz+alpha))^2 - (hy/(hz+alpha))^2 =
|
||||
|
||||
// hz*hz-hr*(hz+alpha)^2 == 1
|
||||
// hz*hz - hr*hr*hz*Hz
|
||||
|
||||
|
||||
ld A, B, C;
|
||||
|
||||
ld curv = sphere ? 1 : -1;
|
||||
|
||||
A = 1+curv*hr;
|
||||
B = 2*hr*vid.alphax*-curv;
|
||||
C = 1 - curv*hr*vid.alphax*vid.alphax;
|
||||
|
||||
// Az^2 - Bz = C
|
||||
B /= A; C /= A;
|
||||
|
||||
// z^2 - Bz = C
|
||||
// z^2 - Bz + (B^2/4) = C + (B^2/4)
|
||||
// z = (B/2) + sqrt(C + B^2/4)
|
||||
|
||||
ld rootsign = 1;
|
||||
if(sphere && vid.alphax > 1) rootsign = -1;
|
||||
|
||||
ld hz = B / 2 + rootsign * sqrt(C + B*B/4);
|
||||
|
||||
hyperpoint H;
|
||||
H[0] = hx * (hz+vid.alphax);
|
||||
H[1] = hy * (hz+vid.alphax);
|
||||
H[2] = hz;
|
||||
|
||||
return H;
|
||||
}
|
||||
|
||||
void ballmodel(hyperpoint& ret, double alpha, double d, double zl) {
|
||||
hyperpoint H = ypush(geom3::camera) * xpush(d) * ypush(zl) * C0;
|
||||
ld tzh = vid.ballproj + H[2];
|
||||
ld ax = H[0] / tzh;
|
||||
ld ay = H[1] / tzh;
|
||||
ld ball = vid.ballangle * M_PI / 180;
|
||||
|
||||
ld ca = cos(alpha), sa = sin(alpha);
|
||||
ld cb = cos(ball), sb = sin(ball);
|
||||
|
||||
ret[0] = ax * ca;
|
||||
ret[1] = ay * cb + ax * sa * sb;
|
||||
ret[2] = - ax * sa * cb - ay * sb;
|
||||
}
|
||||
|
||||
void applymodel(hyperpoint H, hyperpoint& ret) {
|
||||
|
||||
ld tz = euclid ? (EUCSCALE+vid.alphax) : vid.alphax+H[2];
|
||||
if(tz < 1e-3 && tz > -1e-3) tz = 1000;
|
||||
|
||||
if(pmodel == mdUnchanged) {
|
||||
for(int i=0; i<3; i++) ret[i] = H[i] / vid.radius;
|
||||
return;
|
||||
}
|
||||
|
||||
if(pmodel == mdBall) {
|
||||
ld zlev = zlevel(H);
|
||||
using namespace hyperpoint_vec;
|
||||
H = H / zlev;
|
||||
|
||||
ld zl = geom3::depth-geom3::factor_to_lev(zlev);
|
||||
double alpha = atan2(H[1], H[0]);
|
||||
double d = hdist0(H);
|
||||
|
||||
ballmodel(ret, alpha, d, zl);
|
||||
ghcheck(ret,H);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(pmodel == mdHyperboloid) {
|
||||
|
||||
ld ball = vid.ballangle * M_PI / 180;
|
||||
ld cb = cos(ball), sb = sin(ball);
|
||||
|
||||
ret[0] = H[0] / 3;
|
||||
ret[1] = (1 - H[2]) / 3 * cb + H[1] / 3 * sb;
|
||||
ret[2] = H[1] / 3 * cb - (1 - H[2]) / 3 * sb;
|
||||
|
||||
ghcheck(ret,H);
|
||||
return;
|
||||
}
|
||||
|
||||
if(pmodel == mdDisk) {
|
||||
|
||||
if(!vid.camera_angle) {
|
||||
ret[0] = H[0] / tz;
|
||||
ret[1] = H[1] / tz;
|
||||
ret[2] = (1 - vid.beta / tz);
|
||||
}
|
||||
else {
|
||||
ld tx = H[0];
|
||||
ld ty = H[1];
|
||||
ld cam = vid.camera_angle * M_PI / 180;
|
||||
GLfloat cc = cos(cam);
|
||||
GLfloat ss = sin(cam);
|
||||
ld ux = tx, uy = ty * cc - ss * tz, uz = tz * cc + ss * ty;
|
||||
ret[0] = ux / uz;
|
||||
ret[1] = uy / uz;
|
||||
ret[2] = 1 - vid.beta / uz;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
ld zlev = 1;
|
||||
|
||||
if(wmspatial || mmspatial) {
|
||||
zlev = zlevel(H);
|
||||
using namespace hyperpoint_vec;
|
||||
H = H / zlev;
|
||||
}
|
||||
|
||||
if(pmodel == mdEquidistant || pmodel == mdEquiarea) {
|
||||
ld rad = sqrt(H[0] * H[0] + H[1] * H[1]);
|
||||
ld d = hdist0(H);
|
||||
if(pmodel == 6 && sphere)
|
||||
d = sqrt(2*(1 - cos(d))) * 1.25; // /1.5 to make it fit on the screen better
|
||||
else if(pmodel == 6)
|
||||
d = sqrt(2*(cosh(d) - 1)) / 1.5;
|
||||
ret[0] = d * H[0] / rad / 4;
|
||||
ret[1] = d * H[1] / rad / 4;
|
||||
ret[2] = 0;
|
||||
if(zlev != 1 && vid.goteyes)
|
||||
ret[2] = geom3::factor_to_lev(zlev);
|
||||
ghcheck(ret,H);
|
||||
return;
|
||||
}
|
||||
|
||||
tz = H[2]+vid.alphax;
|
||||
|
||||
if(pmodel == mdPolygonal || pmodel == mdPolynomial) {
|
||||
pair<long double, long double> p = polygonal::compute(H[0]/tz, H[1]/tz);
|
||||
ret[0] = p.first;
|
||||
ret[1] = p.second;
|
||||
ret[2] = 0;
|
||||
ghcheck(ret,H);
|
||||
return;
|
||||
}
|
||||
|
||||
// Poincare to half-plane
|
||||
|
||||
ld x0, y0;
|
||||
x0 = H[0] / tz;
|
||||
y0 = H[1] / tz;
|
||||
y0 += 1;
|
||||
double rad = x0*x0 + y0*y0;
|
||||
y0 /= rad;
|
||||
x0 /= rad;
|
||||
y0 -= .5;
|
||||
|
||||
if(pmodel == mdHalfplane) {
|
||||
ret[0] = x0;
|
||||
if(wmspatial || mmspatial) y0 *= zlev;
|
||||
ret[1] = 1 - y0;
|
||||
ret[2] = 0;
|
||||
if(zlev != 1 && vid.goteyes)
|
||||
ret[2] = y0 * geom3::factor_to_lev(zlev);
|
||||
ghcheck(ret,H);
|
||||
return;
|
||||
}
|
||||
|
||||
// center
|
||||
x0 *= 2; y0 *= 2;
|
||||
|
||||
// half-plane to band
|
||||
double tau = (log((x0+1)*(x0+1) + y0*y0) - log((x0-1)*(x0-1) + y0*y0)) / 2;
|
||||
double u=(1-x0*x0-y0*y0);
|
||||
u = (1 - x0*x0 - y0*y0 + sqrt(u*u+4*y0*y0));
|
||||
double yv = 2*y0 / u;
|
||||
double sigma = 2 * atan(yv * zlev) - M_PI/2;
|
||||
|
||||
x0 = tau; y0 = sigma;
|
||||
|
||||
/* if(zlev != 1) {
|
||||
double alp = (y0 * y0) / (1-y0*y0);
|
||||
double gx = alp + sqrt(alp*alp-1);
|
||||
double gy = y0 * (gx+1);
|
||||
double yr = zlev * gy / (zlev * gx + 1);
|
||||
printf("zlev = %10.5lf y0 = %20.10lf yr = %20.10lf\n", double(zlev), (double)y0, yr);
|
||||
y0 = yr;
|
||||
} */
|
||||
|
||||
ret[0] = x0/M_PI*2;
|
||||
ret[1] = -y0/M_PI*2;
|
||||
ret[2] = 0;
|
||||
|
||||
if(zlev != 1 && vid.goteyes)
|
||||
ret[2] = geom3::factor_to_lev(zlev) / (1 + yv * yv);
|
||||
|
||||
ghcheck(ret,H);
|
||||
}
|
||||
|
||||
// game-related graphics
|
||||
|
||||
transmatrix View; // current rotation, relative to viewctr
|
||||
transmatrix cwtV; // player-relative view
|
||||
transmatrix sphereflip; // on the sphere, flip
|
||||
heptspin viewctr; // heptagon and rotation where the view is centered at
|
||||
bool playerfound; // has player been found in the last drawing?
|
||||
|
||||
double eurad = 0.52;
|
||||
double q3 = sqrt(double(3));
|
||||
|
||||
bool outofmap(hyperpoint h) {
|
||||
if(euclid)
|
||||
return false; // h[0] * h[0] + h[1] * h[1] > 15 * eurad;
|
||||
else if(sphere)
|
||||
return h[2] < .1 && h[2] > -.1 && h[1] > -.1 && h[1] < .1 && h[0] > -.1 && h[0] < .1;
|
||||
else
|
||||
return h[2] < .5;
|
||||
}
|
||||
|
||||
hyperpoint mirrorif(const hyperpoint& V, bool b) {
|
||||
if(b) return Mirror*V;
|
||||
else return V;
|
||||
}
|
||||
|
||||
// -1 if away, 0 if not away
|
||||
int away(const transmatrix& V2) {
|
||||
return intval(C0, V2 * xpush0(1)) > intval(C0, tC0(V2));
|
||||
}
|
||||
|
||||
/* double zgrad(double f1, double f2, int nom, int den) {
|
||||
using namespace geom3;
|
||||
ld fo1 = factor_to_lev(f1);
|
||||
ld fo2 = factor_to_lev(f2);
|
||||
return lev_to_factor(fo1 + (fo2-fo1) * nom / den);
|
||||
} */
|
||||
|
||||
double zgrad0(double l1, double l2, int nom, int den) {
|
||||
using namespace geom3;
|
||||
return lev_to_factor(l1 + (l2-l1) * nom / den);
|
||||
}
|
||||
|
||||
bool behindsphere(const hyperpoint& h) {
|
||||
if(!sphere) return false;
|
||||
|
||||
if(vid.alpha > 1) {
|
||||
if(h[2] > -1/vid.alpha) return true;
|
||||
}
|
||||
|
||||
if(vid.alpha <= 1) {
|
||||
if(h[2] < -.8) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool behindsphere(const transmatrix& V) {
|
||||
return behindsphere(tC0(V));
|
||||
}
|
||||
|
||||
bool confusingGeometry() {
|
||||
return elliptic || quotient == 1 || torus;
|
||||
}
|
||||
|
||||
void drawrec(const heptspin& hs, int lev, hstate s, const transmatrix& V) {
|
||||
|
||||
// shmup::calc_relative_matrix(cwt.c, hs.h);
|
||||
|
||||
cell *c = hs.h->c7;
|
||||
|
||||
transmatrix V10;
|
||||
const transmatrix& V1 = hs.mirrored ? (V10 = V * Mirror) : V;
|
||||
|
||||
if(dodrawcell(c)) {
|
||||
reclevel = maxreclevel - lev;
|
||||
drawcell(c, (hs.spin || purehepta) ? V1 * spin(hs.spin*2*M_PI/S7 + (purehepta ? M_PI:0)) : V1, hs.spin,
|
||||
hs.mirrored);
|
||||
}
|
||||
|
||||
if(lev <= 0) return;
|
||||
|
||||
if(!purehepta) for(int d=0; d<S7; d++) {
|
||||
int ds = fixrot(hs.spin + d);
|
||||
reclevel = maxreclevel - lev + 1;
|
||||
// createMov(c, ds);
|
||||
if(c->mov[ds] && c->spn(ds) == 0 && dodrawcell(c->mov[ds])) {
|
||||
drawcell(c->mov[ds], V1 * hexmove[d], 0, hs.mirrored ^ c->mirror(ds));
|
||||
}
|
||||
}
|
||||
|
||||
if(lev <= 1) return;
|
||||
|
||||
for(int d=0; d<S7; d++) {
|
||||
hstate s2 = transition(s, d);
|
||||
if(s2 == hsError) continue;
|
||||
heptspin hs2 = hsstep(hsspin(hs, d), 0);
|
||||
drawrec(hs2, lev-2, s2, V * heptmove[d]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int mindx=-7, mindy=-7, maxdx=7, maxdy=7;
|
||||
|
||||
transmatrix eumove(int x, int y) {
|
||||
transmatrix Mat = Id;
|
||||
Mat[2][2] = 1;
|
||||
Mat[0][2] += (x + y * .5) * eurad;
|
||||
// Mat[2][0] += (x + y * .5) * eurad;
|
||||
Mat[1][2] += y * q3 /2 * eurad;
|
||||
// Mat[2][1] += y * q3 /2 * eurad;
|
||||
while(Mat[0][2] <= -16384 * eurad) Mat[0][2] += 32768 * eurad;
|
||||
while(Mat[0][2] >= 16384 * eurad) Mat[0][2] -= 32768 * eurad;
|
||||
while(Mat[1][2] <= -16384 * q3 * eurad) Mat[1][2] += 32768 * q3 * eurad;
|
||||
while(Mat[1][2] >= 16384 * q3 * eurad) Mat[1][2] -= 32768 * q3 * eurad;
|
||||
return Mat;
|
||||
}
|
||||
|
||||
transmatrix eumovedir(int d) {
|
||||
d = fix6(d);
|
||||
switch(d) {
|
||||
case 0: return eumove(1,0);
|
||||
case 1: return eumove(0,1);
|
||||
case 2: return eumove(-1,1);
|
||||
case 3: return eumove(-1,0);
|
||||
case 4: return eumove(0,-1);
|
||||
case 5: return eumove(1,-1);
|
||||
}
|
||||
return eumove(0,0);
|
||||
}
|
||||
|
||||
void drawEuclidean() {
|
||||
DEBB(DF_GRAPH, (debugfile,"drawEuclidean\n"));
|
||||
eucoord px=0, py=0;
|
||||
if(!centerover) centerover = cwt.c;
|
||||
// printf("centerover = %p player = %p [%d,%d]-[%d,%d]\n", lcenterover, cwt.c,
|
||||
// mindx, mindy, maxdx, maxdy);
|
||||
int pid;
|
||||
const bool b = torus;
|
||||
if(b)
|
||||
pid = decodeId(centerover->master);
|
||||
else
|
||||
decodeMaster(centerover->master, px, py);
|
||||
|
||||
int minsx = mindx-1, maxsx=maxdx+1, minsy=mindy-1, maxsy=maxdy+1;
|
||||
mindx=maxdx=mindy=maxdy=0;
|
||||
|
||||
for(int dx=minsx; dx<=maxsx; dx++)
|
||||
for(int dy=minsy; dy<=maxsy; dy++) {
|
||||
reclevel = eudist(dx, dy);
|
||||
cell *c;
|
||||
transmatrix Mat;
|
||||
if(b) {
|
||||
reclevel = eudist(dx, dy);
|
||||
c = getTorusId(pid+torusconfig::dx*dx+torusconfig::dy*dy);
|
||||
Mat = eumove(dx,dy);
|
||||
}
|
||||
else {
|
||||
eucoord x = dx+px;
|
||||
eucoord y = dy+py;
|
||||
c = euclideanAt(x,y);
|
||||
Mat = eumove(x, y);
|
||||
}
|
||||
if(!c) continue;
|
||||
Mat = View * Mat;
|
||||
|
||||
// Mat[0][0] = -1;
|
||||
// Mat[1][1] = -1;
|
||||
|
||||
// Mat[2][0] = x*x/10;
|
||||
// Mat[2][1] = y*y/10;
|
||||
// Mat = Mat * xpush(x-30) * ypush(y-30);
|
||||
|
||||
int cx, cy, shift;
|
||||
getcoord0(tC0(Mat), cx, cy, shift);
|
||||
if(cx >= 0 && cy >= 0 && cx < vid.xres && cy < vid.yres) {
|
||||
if(dx < mindx) mindx = dx;
|
||||
if(dy < mindy) mindy = dy;
|
||||
if(dx > maxdx) maxdx = dx;
|
||||
if(dy > maxdy) maxdy = dy;
|
||||
}
|
||||
|
||||
if(dodrawcell(c)) {
|
||||
drawcell(c, Mat, 0, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void spinEdge(ld aspd) {
|
||||
if(downspin > aspd) downspin = aspd;
|
||||
if(downspin < -aspd) downspin = -aspd;
|
||||
View = spin(downspin) * View;
|
||||
}
|
||||
|
||||
void centerpc(ld aspd) {
|
||||
if(vid.sspeed >= 4.99) aspd = 1000;
|
||||
DEBB(DF_GRAPH, (debugfile,"center pc\n"));
|
||||
hyperpoint H = ypush(-vid.yshift) * sphereflip * tC0(cwtV);
|
||||
if(H[0] == 0 && H[1] == 0) return; // either already centered or direction unknown
|
||||
ld R = hdist0(H); // = sqrt(H[0] * H[0] + H[1] * H[1]);
|
||||
if(R < 1e-9) {
|
||||
/* if(playerfoundL && playerfoundR) {
|
||||
|
||||
} */
|
||||
spinEdge(aspd);
|
||||
fixmatrix(View);
|
||||
return;
|
||||
}
|
||||
|
||||
if(euclid) {
|
||||
// Euclidean
|
||||
aspd *= (2+3*R*R);
|
||||
if(aspd > R) aspd = R;
|
||||
|
||||
View[0][2] -= cwtV[0][2] * aspd / R;
|
||||
View[1][2] -= cwtV[1][2] * aspd / R;
|
||||
}
|
||||
|
||||
else {
|
||||
aspd *= (1+R+(shmup::on?1:0));
|
||||
|
||||
if(R < aspd) {
|
||||
View = gpushxto0(H) * View;
|
||||
}
|
||||
else
|
||||
View = rspintox(H) * xpush(-aspd) * spintox(H) * View;
|
||||
|
||||
fixmatrix(View);
|
||||
spinEdge(aspd);
|
||||
}
|
||||
}
|
||||
|
||||
void optimizeview() {
|
||||
|
||||
DEBB(DF_GRAPH, (debugfile,"optimize view\n"));
|
||||
int turn = 0;
|
||||
ld best = INF;
|
||||
|
||||
transmatrix TB = Id;
|
||||
|
||||
for(int i=-1; i<S7; i++) {
|
||||
|
||||
ld trot = -i * M_PI * 2 / (S7+.0);
|
||||
transmatrix T = i < 0 ? Id : spin(trot) * xpush(tessf) * pispin;
|
||||
hyperpoint H = View * tC0(T);
|
||||
if(H[2] < best) best = H[2], turn = i, TB = T;
|
||||
}
|
||||
|
||||
if(turn >= 0) {
|
||||
View = View * TB;
|
||||
fixmatrix(View);
|
||||
viewctr = hsspin(viewctr, turn);
|
||||
viewctr = hsstep(viewctr, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void addball(ld a, ld b, ld c) {
|
||||
hyperpoint h;
|
||||
ballmodel(h, a, b, c);
|
||||
for(int i=0; i<3; i++) h[i] *= vid.radius;
|
||||
curvepoint(h);
|
||||
}
|
||||
|
||||
void ballgeometry() {
|
||||
queuereset(vid.usingGL ? mdDisk : mdUnchanged, PPR_CIRCLE);
|
||||
for(int i=0; i<60; i++)
|
||||
addball(i * M_PI/30, 10, 0);
|
||||
for(double d=10; d>=-10; d-=.2)
|
||||
addball(0, d, 0);
|
||||
for(double d=-10; d<=10; d+=.2)
|
||||
addball(0, d, geom3::depth);
|
||||
addball(0, 0, -geom3::camera);
|
||||
addball(0, 0, geom3::depth);
|
||||
addball(0, 0, -geom3::camera);
|
||||
addball(0, -10, 0);
|
||||
addball(0, 0, -geom3::camera);
|
||||
queuecurve(darkena(0xFF, 0, 0x80), 0, PPR_CIRCLE);
|
||||
queuereset(pmodel, PPR_CIRCLE);
|
||||
}
|
||||
|
||||
void resetview() {
|
||||
DEBB(DF_GRAPH, (debugfile,"reset view\n"));
|
||||
View = Id;
|
||||
// EUCLIDEAN
|
||||
if(!euclid)
|
||||
viewctr.h = cwt.c->master,
|
||||
viewctr.spin = cwt.spin;
|
||||
else centerover = cwt.c;
|
||||
// SDL_LockSurface(s);
|
||||
// SDL_UnlockSurface(s);
|
||||
}
|
||||
|
||||
|
||||
void panning(hyperpoint hf, hyperpoint ht) {
|
||||
View =
|
||||
rgpushxto0(hf) * rgpushxto0(gpushxto0(hf) * ht) * gpushxto0(hf) * View;
|
||||
playermoved = false;
|
||||
}
|
||||
|
||||
void fullcenter() {
|
||||
if(playerfound && false) centerpc(INF);
|
||||
else {
|
||||
bfs();
|
||||
resetview();
|
||||
drawthemap();
|
||||
centerpc(INF);
|
||||
}
|
||||
playermoved = true;
|
||||
}
|
||||
|
||||
transmatrix screenpos(ld x, ld y) {
|
||||
transmatrix V = Id;
|
||||
V[0][2] += (x - vid.xcenter) / vid.radius * (1+vid.alphax);
|
||||
V[1][2] += (y - vid.ycenter) / vid.radius * (1+vid.alphax);
|
||||
return V;
|
||||
}
|
||||
|
||||
transmatrix atscreenpos(ld x, ld y, ld size) {
|
||||
transmatrix V = Id;
|
||||
|
||||
V[0][2] += (x - vid.xcenter);
|
||||
V[1][2] += (y - vid.ycenter);
|
||||
V[0][0] = size * 2 * hcrossf / crossf;
|
||||
V[1][1] = size * 2 * hcrossf / crossf;
|
||||
V[2][2] = vid.scrdist;
|
||||
if(euclid) V[2][2] /= EUCSCALE;
|
||||
|
||||
return V;
|
||||
}
|
||||
|
97
init.cpp
97
init.cpp
@ -1,6 +1,6 @@
|
||||
#define VER "9.4n1"
|
||||
#define VERNUM 9415
|
||||
#define VERNUM_HEX 0x9415
|
||||
#define VER "9.4n2"
|
||||
#define VERNUM 9416
|
||||
#define VERNUM_HEX 0x9416
|
||||
|
||||
#define GEN_M 0
|
||||
#define GEN_F 1
|
||||
@ -276,6 +276,23 @@ const char *loadlevel = NULL;
|
||||
#ifdef EXTRA
|
||||
#include "extra/extra.cpp"
|
||||
#endif
|
||||
#include "basegraph.cpp"
|
||||
#include "help.cpp"
|
||||
#include "config.cpp"
|
||||
#include "scores.cpp"
|
||||
#include "menus.cpp"
|
||||
#ifdef FIXEDSIZE
|
||||
#include "nofont.cpp"
|
||||
#endif
|
||||
#include "shmup.cpp"
|
||||
#ifdef ROGUEVIZ
|
||||
#include "rogueviz.cpp"
|
||||
#endif
|
||||
#include "conformal.cpp"
|
||||
#include "rug.cpp"
|
||||
#include "control.cpp"
|
||||
#include "hud.cpp"
|
||||
#include "hypgraph.cpp"
|
||||
#include "graph.cpp"
|
||||
#include "sound.cpp"
|
||||
#include "achievement.cpp"
|
||||
@ -299,7 +316,6 @@ void initAll() {
|
||||
eLand f = firstland;
|
||||
|
||||
// initlanguage();
|
||||
cmode = emNormal;
|
||||
initgraph();
|
||||
#ifndef NOSAVE
|
||||
loadsave();
|
||||
@ -396,7 +412,7 @@ bool useRangedOrb;
|
||||
|
||||
void handleclick(MOBPAR_FORMAL) {
|
||||
|
||||
if(!shmup::on && andmode == 0 && cmode == emNormal && canmove && !useRangedOrb && vid.mobilecompasssize > 0) {
|
||||
if(!shmup::on && andmode == 0 && size(screens) == 1 && canmove && !useRangedOrb && vid.mobilecompasssize > 0) {
|
||||
using namespace shmupballs;
|
||||
int dx = mousex - xmove;
|
||||
int dy = mousey - yb;
|
||||
@ -404,7 +420,7 @@ void handleclick(MOBPAR_FORMAL) {
|
||||
if(h < rad) {
|
||||
if(h < rad*SKIPFAC) movepcto(MD_WAIT);
|
||||
else {
|
||||
double d = revcontrol ? -1 : 1;
|
||||
double d = vid.revcontrol ? -1 : 1;
|
||||
mouseh = hpxy(dx * d / rad, dy * d / rad);
|
||||
mousemovement();
|
||||
}
|
||||
@ -415,7 +431,7 @@ void handleclick(MOBPAR_FORMAL) {
|
||||
|
||||
if(buttonclicked || mouseout()) {
|
||||
|
||||
if(andmode == 0 && getcstat == 'g' && !shmup::on && (cmode == emNormal || cmode == emQuit)) {
|
||||
if(andmode == 0 && getcstat == 'g' && !shmup::on && size(screens) == 1) {
|
||||
movepcto(MD_DROP);
|
||||
getcstat = 0;
|
||||
}
|
||||
@ -424,7 +440,7 @@ void handleclick(MOBPAR_FORMAL) {
|
||||
int px = mousex < vid.xcenter ? 0 : 1;
|
||||
int py = mousey < vid.ycenter ? 0 : 1;
|
||||
|
||||
if(cmode == (canmove ? emNormal : emQuit)) {
|
||||
if(size(screens) == 1) {
|
||||
if(px == 0 && py == 1) {
|
||||
if(andmode == 0 && shmup::on) ;
|
||||
else andmode = 10;
|
||||
@ -456,7 +472,7 @@ void handleclick(MOBPAR_FORMAL) {
|
||||
}
|
||||
}
|
||||
|
||||
if(andmode == 0 && cmode == (canmove ? emNormal : emQuit) && !mouseout()) {
|
||||
if(andmode == 0 && size(screens) == 1 && !mouseout()) {
|
||||
|
||||
bool forcetarget = longclick;
|
||||
|
||||
@ -499,7 +515,7 @@ void mobile_draw(MOBPAR_FORMAL) {
|
||||
if(playermoved && vid.sspeed > -4.99)
|
||||
centerpc(tdiff / 1000.0 * exp(vid.sspeed));
|
||||
|
||||
if(shmup::on && (andmode == 0 || andmode == 10) && cmode == emNormal)
|
||||
if(shmup::on && (andmode == 0 || andmode == 10) && size(screens) == 1)
|
||||
shmup::turn(tdiff);
|
||||
|
||||
safety = false;
|
||||
@ -520,7 +536,7 @@ void mobile_draw(MOBPAR_FORMAL) {
|
||||
if(hypot(mousex - xmove, mousey - yb) < rad) targetclick = false;
|
||||
}
|
||||
|
||||
if(cmode == emNormal) {
|
||||
if(size(screens) == 1) {
|
||||
lmouseover = (gtouched && lclicked) ? mouseover : NULL;
|
||||
if(!shmup::on && !useRangedOrb && vid.mobilecompasssize) {
|
||||
using namespace shmupballs;
|
||||
@ -530,7 +546,7 @@ void mobile_draw(MOBPAR_FORMAL) {
|
||||
if(h < rad) {
|
||||
if(h < rad*SKIPFAC) { lmouseover = cwt.c; mousedest.d = -1; }
|
||||
else {
|
||||
double d = revcontrol ? -1 : 1;
|
||||
double d = vid.revcontrol ? -1 : 1;
|
||||
mouseh = hpxy(dx * d / rad, dy * d / rad);
|
||||
calcMousedest();
|
||||
}
|
||||
@ -556,6 +572,8 @@ void mobile_draw(MOBPAR_FORMAL) {
|
||||
shiftmul = getcshift;
|
||||
calcMousedest();
|
||||
|
||||
inmenu = size(screens) > 1;
|
||||
|
||||
if(lclicked && !clicked && !inmenu) handleclick(MOBPAR_ACTUAL);
|
||||
|
||||
if(inmenu && !clicked && !lclicked) inmenu = false;
|
||||
@ -581,29 +599,20 @@ void mobile_draw(MOBPAR_FORMAL) {
|
||||
|
||||
#ifdef ANDROIDSHARE
|
||||
if(getcstat == 's'-96 && keyreact) {
|
||||
cmode = canmove ? emQuit : emNormal;
|
||||
popScreenAll().
|
||||
shareScore(MOBPAR_ACTUAL);
|
||||
cmode = emNormal;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(andmode == 2 && cmode != emNormal) andmode = 12;
|
||||
if(andmode == 2 && size(screens) != 1) andmode = 12;
|
||||
|
||||
if((cmode == emQuit && !canmove && keyreact && lclicked && !clicked) && !buttonclicked) {
|
||||
cmode = emNormal; printf("back to quit\n");
|
||||
popScreenAll(); printf("back to quit\n");
|
||||
}
|
||||
else if(cmode == emScores) handleScoreKeys(0, 0);
|
||||
else if(getcstat && keyreact) {
|
||||
|
||||
if(cmode == (canmove ? emQuit : emNormal))
|
||||
handleQuit(getcstat, getcstat);
|
||||
|
||||
else {
|
||||
if(cmode != emNormal && cmode != emQuit) inmenu = true;
|
||||
if(cmode == emMenu && getcstat == 'q') openURL();
|
||||
else { extra ex; handlekey(getcstat, getcstat, ex); }
|
||||
}
|
||||
|
||||
if(cmode == emMenu && getcstat == 'q') openURL();
|
||||
else { extra ex; handlekey(getcstat, getcstat, ex); }
|
||||
}
|
||||
|
||||
#ifdef IOS
|
||||
@ -621,7 +630,7 @@ void mobile_draw(MOBPAR_FORMAL) {
|
||||
if(andmode == 1 && lclicked && !clicked && !inmenu && mouseover)
|
||||
performMarkCommand(mouseover);
|
||||
|
||||
if(clicked && andmode == 2 && (mouseover != lmouseover || mouseovers != lmouseovers) && cmode == emNormal) {
|
||||
if(clicked && andmode == 2 && (mouseover != lmouseover || mouseovers != lmouseovers) && !inmenu) {
|
||||
addMessage(mouseovers);
|
||||
lmouseovers = mouseovers;
|
||||
}
|
||||
@ -630,7 +639,7 @@ void mobile_draw(MOBPAR_FORMAL) {
|
||||
if(andmode == 20 && clicked != lclicked) andmode = 10;
|
||||
|
||||
if(andmode == 2 && lclicked && !clicked) {
|
||||
if(cmode == emNormal)
|
||||
if(!inmenu)
|
||||
showHelp(MOBPAR_ACTUAL, help);
|
||||
else if(cmode != emScores && cmode != emPickScores)
|
||||
cmode = emNormal;
|
||||
@ -664,35 +673,3 @@ void mobile_draw(MOBPAR_FORMAL) {
|
||||
#ifdef NOAUDIO
|
||||
void playSound(cell*, const string &s, int vol) { printf("play sound: %s vol %d\n", s.c_str(), vol); }
|
||||
#endif
|
||||
|
||||
// optional hooks
|
||||
// you may include hyper.cpp from another file and define EXTRA_... to change some things
|
||||
namespace extra {
|
||||
|
||||
// on drawing cells
|
||||
void drawcell(cell *c, const transmatrix& V);
|
||||
|
||||
// on each frame
|
||||
void frame();
|
||||
|
||||
// on stats drawing
|
||||
void stats();
|
||||
|
||||
// return true if key is handled
|
||||
bool handleKey(int sym, int uni);
|
||||
|
||||
// return true to exit immediately
|
||||
bool main(int argc, char **argv);
|
||||
|
||||
// extra configuration, called together with reading arguments
|
||||
void config();
|
||||
|
||||
// read command line arguments
|
||||
int arg();
|
||||
|
||||
// change land distribution
|
||||
eLand getNext(eLand old);
|
||||
|
||||
// change musics
|
||||
bool changeMusic(eLand id);
|
||||
}
|
||||
|
@ -68,9 +68,9 @@ void loadsamples(const char *fname) {
|
||||
while(true) {
|
||||
sample s;
|
||||
alloc(s.val);
|
||||
for(int i=0; i<cols; i++)
|
||||
if(fscanf(f, "%lf", &s.val[i]) != 1) { fclose(f); return; }
|
||||
if(feof(f)) break;
|
||||
for(int i=0; i<cols; i++)
|
||||
if(fscanf(f, "%lf", &s.val[i]) != 1) { break; }
|
||||
fgetc(f);
|
||||
while(true) {
|
||||
int c = fgetc(f);
|
||||
|
22
landgen.cpp
22
landgen.cpp
@ -1596,26 +1596,12 @@ bool createOnSea(eLand old) {
|
||||
(old == laOcean && (chaosmode ? hrand(2) : !generatingEquidistant));
|
||||
}
|
||||
|
||||
hookset<eLand(eLand)> *hooks_nextland;
|
||||
|
||||
eLand getNewLand(eLand old) {
|
||||
|
||||
#ifdef EXTRA_NEWLAND
|
||||
if(true) {
|
||||
eLand l = extra::getNext(old);
|
||||
if(l) return l;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TOUR
|
||||
if(tour::on) {
|
||||
eLand l = tour::getNext(old);
|
||||
if(l) return l;
|
||||
}
|
||||
|
||||
if(peace::on) {
|
||||
eLand l = peace::getNext(old);
|
||||
if(l) return l;
|
||||
}
|
||||
#endif
|
||||
eLand l = callhandlers(laNone, hooks_nextland, old);
|
||||
if(l) return l;
|
||||
|
||||
if(cheatdest != old) if(!isCyclic(cheatdest) && !isTechnicalLand(cheatdest)) return cheatdest;
|
||||
|
||||
|
14103
language-data.cpp
Normal file
14103
language-data.cpp
Normal file
File diff suppressed because it is too large
Load Diff
676
mapeditor.cpp
676
mapeditor.cpp
@ -26,9 +26,8 @@ namespace mapeditor {
|
||||
#ifndef NOEDIT
|
||||
map<int, cell*> modelcell;
|
||||
|
||||
void clearModelCells() {
|
||||
modelcell.clear();
|
||||
}
|
||||
void handleKeyMap(int sym, int uni);
|
||||
bool handleKeyFile(int sym, int uni);
|
||||
|
||||
void applyModelcell(cell *c) {
|
||||
if(mapeditor::whichPattern == 'H') return;
|
||||
@ -157,7 +156,6 @@ namespace mapstream {
|
||||
|
||||
clearMemory();
|
||||
initcells();
|
||||
cleargraphmemory();
|
||||
if(shmup::on) shmup::init();
|
||||
|
||||
while(true) {
|
||||
@ -425,8 +423,6 @@ namespace mapeditor {
|
||||
return true;
|
||||
}
|
||||
|
||||
int subscreen; //0=normal, 1=config, 2=patterns, 3=predesigned
|
||||
|
||||
cell *drawcell;
|
||||
|
||||
#ifndef NOEDIT
|
||||
@ -557,11 +553,15 @@ namespace mapeditor {
|
||||
return f1.first < f2.first;
|
||||
}
|
||||
|
||||
string filecaption, cfileext;
|
||||
string *cfileptr;
|
||||
|
||||
void drawFileDialog() {
|
||||
displayfr(vid.xres/2, 30 + vid.fsize, 2, vid.fsize,
|
||||
XLAT(cmode == emDraw ? "pics to save/load:" : "level to save/load:"), forecolor, 8);
|
||||
filecaption, forecolor, 8);
|
||||
|
||||
string& cfile = *cfileptr;
|
||||
|
||||
string cfile = cmode == emDraw ? picfile : levelfile;
|
||||
displayfr(vid.xres/2, 34 + vid.fsize * 2, 2, vid.fsize,
|
||||
cfile, editext ? 0xFF00FF : 0xFFFF00, 8);
|
||||
|
||||
@ -589,7 +589,7 @@ namespace mapeditor {
|
||||
while ((dir = readdir(d)) != NULL) {
|
||||
string s = dir->d_name;
|
||||
if(s != ".." && s[0] == '.') ;
|
||||
else if(size(s) > 4 && s.substr(size(s)-4) == (cmode == emDraw ? ".pic" : ".lev"))
|
||||
else if(size(s) > 4 && s.substr(size(s)-4) == cfileext)
|
||||
v.push_back(make_pair(s, CFILE));
|
||||
else if(dir->d_type & DT_DIR)
|
||||
v.push_back(make_pair(s+"/", CDIR));
|
||||
@ -608,6 +608,8 @@ namespace mapeditor {
|
||||
|
||||
displayColorButton(x, y, v[i].first, 1000 + i, 0, 0, v[i].second, 0xFFFF00);
|
||||
}
|
||||
|
||||
keyhandler = handleKeyFile;
|
||||
}
|
||||
|
||||
void displayFunctionKeys() {
|
||||
@ -630,142 +632,190 @@ namespace mapeditor {
|
||||
v.push_back(make_pair(s, i));
|
||||
}
|
||||
|
||||
void showPrePattern() {
|
||||
dialog::init("predesigned patterns");
|
||||
dialog::addItem(XLAT("Gameboard"), 'g');
|
||||
dialog::addItem(XLAT("random colors"), 'r');
|
||||
dialog::addItem(XLAT("rainbow landscape"), 'l');
|
||||
dialog::addItem(XLAT("dark rainbow landscape"), 'd');
|
||||
dialog::addItem(XLAT("football"), 'F');
|
||||
|
||||
dialog::addSelItem(XLAT("emerald pattern"), "emerald", 'e');
|
||||
|
||||
dialog::addSelItem(XLAT("four elements"), "palace", 'b');
|
||||
dialog::addSelItem(XLAT("eight domains"), "palace", 'a');
|
||||
|
||||
dialog::addSelItem(XLAT("zebra pattern"), "zebra", 'z');
|
||||
dialog::addSelItem(XLAT("four triangles"), "zebra", 't');
|
||||
dialog::addSelItem(XLAT("three stripes"), "zebra", 'x');
|
||||
|
||||
dialog::addSelItem(XLAT("random black-and-white"), "current", 'w');
|
||||
|
||||
dialog::addSelItem(XLAT("field pattern C"), "field", 'C');
|
||||
dialog::addSelItem(XLAT("field pattern D"), "field", 'D');
|
||||
dialog::addSelItem(XLAT("field pattern N"), "field", 'N');
|
||||
dialog::addSelItem(XLAT("field pattern S"), "field", 'S');
|
||||
|
||||
dialog::display();
|
||||
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
if((uni >= 'a' && uni <= 'z') || (uni >= 'A' && uni <= 'Z')) {
|
||||
whichCanvas = uni;
|
||||
subcanvas = rand();
|
||||
firstland = laCanvas; randomPatternsMode = false;
|
||||
restartGame();
|
||||
}
|
||||
else if(doexiton(sym, uni)) popScreen();
|
||||
};
|
||||
}
|
||||
|
||||
void showPattern() {
|
||||
dialog::init();
|
||||
|
||||
dialog::addBoolItem(XLAT(euclid ? "three colors" : "Emerald Pattern"), (whichPattern == 'f'), 'f');
|
||||
dialog::addBoolItem(XLAT("Palace Pattern"), (whichPattern == 'p'), 'p');
|
||||
dialog::addBoolItem(XLAT(euclid ? "three colors rotated" : "Zebra Pattern"), (whichPattern == 'z'), 'z');
|
||||
dialog::addBoolItem(XLAT("field pattern"), (whichPattern == 'F'), 'F');
|
||||
|
||||
if(whichPattern == 'f') symRotation = true;
|
||||
if(whichPattern == 'F') ;
|
||||
else if(!euclid) {
|
||||
dialog::addBoolItem(XLAT("rotational symmetry"), (symRotation), '0');
|
||||
dialog::addBoolItem(XLAT("symmetry 0-1"), (sym01), '1');
|
||||
dialog::addBoolItem(XLAT("symmetry 0-2"), (sym02), '2');
|
||||
dialog::addBoolItem(XLAT("symmetry 0-3"), (sym03), '3');
|
||||
}
|
||||
else
|
||||
dialog::addBoolItem(XLAT("edit all three colors"), (symRotation), '0');
|
||||
|
||||
dialog::addBoolItem(XLAT("display pattern codes (full)"), (displaycodes == 1), 'd');
|
||||
dialog::addBoolItem(XLAT("display pattern codes (simplified)"), (displaycodes == 2), 's');
|
||||
|
||||
dialog::addBoolItem(XLAT("display only hexagons"), (whichShape == '6'), '6');
|
||||
dialog::addBoolItem(XLAT("display only heptagons"), (whichShape == '7'), '7');
|
||||
dialog::addBoolItem(XLAT("display the triheptagonal grid"), (whichShape == '8'), '8');
|
||||
dialog::addItem(XLAT("line patterns"), 'l');
|
||||
|
||||
dialog::addItem(XLAT("predesigned patterns"), 'r');
|
||||
dialog::display();
|
||||
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
if(uni == 'f' || uni == 'p' || uni == 'z' || uni == 'H' || uni == 'F') {
|
||||
if(whichPattern == uni) whichPattern = 0;
|
||||
else whichPattern = uni;
|
||||
modelcell.clear();
|
||||
}
|
||||
|
||||
else if(uni == '0') symRotation = !symRotation;
|
||||
else if(uni == '1') sym01 = !sym01;
|
||||
else if(uni == '2') sym02 = !sym02;
|
||||
else if(uni == '3') sym03 = !sym03;
|
||||
else if(uni == '6' || uni == '7' || uni == '8') {
|
||||
if(whichShape == uni) whichShape = 0;
|
||||
else whichShape = uni;
|
||||
}
|
||||
else if(uni == '3') sym03 = !sym03;
|
||||
else if(uni == 'd') displaycodes = displaycodes == 1 ? 0 : 1;
|
||||
else if(uni == 's') displaycodes = displaycodes == 2 ? 0 : 2;
|
||||
|
||||
else if(uni == 'l')
|
||||
pushScreen(linepatterns::showMenu);
|
||||
|
||||
else if(uni == 'r') pushScreen(showPrePattern);
|
||||
|
||||
else if(doexiton(sym, uni)) popScreen();
|
||||
};
|
||||
}
|
||||
|
||||
void showList() {
|
||||
v.clear();
|
||||
if(painttype == 4) painttype = 0;
|
||||
switch(painttype) {
|
||||
case 0:
|
||||
for(int i=0; i<motypes; i++) {
|
||||
eMonster m = eMonster(i);
|
||||
if(
|
||||
m == moTongue || m == moPlayer || m == moFireball || m == moBullet ||
|
||||
m == moFlailBullet || m == moShadow || m == moAirball ||
|
||||
m == moWolfMoved || m == moGolemMoved ||
|
||||
m == moTameBomberbirdMoved || m == moKnightMoved ||
|
||||
m == moDeadBug || m == moLightningBolt || m == moDeadBird ||
|
||||
m == moMouseMoved || m == moPrincessMoved || m == moPrincessArmedMoved) ;
|
||||
else vpush(i, minf[i].name);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
for(int i=0; i<ittypes; i++) vpush(i, iinf[i].name);
|
||||
break;
|
||||
case 2:
|
||||
for(int i=0; i<landtypes; i++) vpush(i, linf[i].name);
|
||||
break;
|
||||
case 3:
|
||||
for(int i=0; i<walltypes; i++) if(i != waChasmD) vpush(i, winf[i].name);
|
||||
break;
|
||||
}
|
||||
// sort(v.begin(), v.end());
|
||||
|
||||
if(infix != "") mouseovers = infix;
|
||||
|
||||
int q = v.size();
|
||||
int percolumn = vid.yres / (vid.fsize+5) - 4;
|
||||
int columns = 1 + (q-1) / percolumn;
|
||||
|
||||
for(int i=0; i<q; i++) {
|
||||
int x = 16 + (vid.xres * (i/percolumn)) / columns;
|
||||
int y = (vid.fsize+5) * (i % percolumn) + vid.fsize*2;
|
||||
|
||||
int actkey = 1000 + i;
|
||||
string vv = v[i].first;
|
||||
if(i < 9) { vv += ": "; vv += ('1' + i); }
|
||||
|
||||
displayButton(x, y, vv, actkey, 0);
|
||||
}
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
if(uni >= '1' && uni <= '9') uni = 1000 + uni - '1';
|
||||
if(sym == SDLK_RETURN || sym == SDLK_KP_ENTER || sym == '-' || sym == SDLK_KP_MINUS) uni = 1000;
|
||||
for(int z=0; z<size(v); z++) if(1000 + z == uni) {
|
||||
paintwhat = v[z].second;
|
||||
paintwhat_str = v[z].first;
|
||||
mousepressed = false;
|
||||
popScreen();
|
||||
return;
|
||||
}
|
||||
if(editInfix(uni)) ;
|
||||
else if(doexiton(sym, uni)) popScreen();
|
||||
};
|
||||
}
|
||||
|
||||
void showMapEditor() {
|
||||
cmode2 = smMap;
|
||||
gamescreen(0);
|
||||
|
||||
if(choosefile) { drawFileDialog(); return; }
|
||||
int fs = vid.fsize + 5;
|
||||
|
||||
if(subscreen == 2) {
|
||||
dialog::init();
|
||||
getcstat = '-';
|
||||
|
||||
dialog::addBoolItem(XLAT(euclid ? "three colors" : "Emerald Pattern"), (whichPattern == 'f'), 'f');
|
||||
dialog::addBoolItem(XLAT("Palace Pattern"), (whichPattern == 'p'), 'p');
|
||||
dialog::addBoolItem(XLAT(euclid ? "three colors rotated" : "Zebra Pattern"), (whichPattern == 'z'), 'z');
|
||||
dialog::addBoolItem(XLAT("field pattern"), (whichPattern == 'F'), 'F');
|
||||
displayfr(8, 8 + fs, 2, vid.fsize, paintwhat_str, forecolor, 0);
|
||||
displayfr(8, 8+fs*2, 2, vid.fsize, XLAT("use at your own risk!"), 0x800000, 0);
|
||||
|
||||
if(whichPattern == 'f') symRotation = true;
|
||||
if(whichPattern == 'F') ;
|
||||
else if(!euclid) {
|
||||
dialog::addBoolItem(XLAT("rotational symmetry"), (symRotation), '0');
|
||||
dialog::addBoolItem(XLAT("symmetry 0-1"), (sym01), '1');
|
||||
dialog::addBoolItem(XLAT("symmetry 0-2"), (sym02), '2');
|
||||
dialog::addBoolItem(XLAT("symmetry 0-3"), (sym03), '3');
|
||||
}
|
||||
else
|
||||
dialog::addBoolItem(XLAT("edit all three colors"), (symRotation), '0');
|
||||
displayButton(8, 8+fs*4, XLAT("0-9 = radius (%1)", its(radius)), ('0' + (radius+1)%10), 0);
|
||||
displayButton(8, 8+fs*5, XLAT("b = boundary"), 'b', 0);
|
||||
displayButton(8, 8+fs*6, XLAT("m = monsters"), 'm', 0);
|
||||
displayButton(8, 8+fs*7, XLAT("w = walls"), 'w', 0);
|
||||
displayButton(8, 8+fs*8, XLAT("i = items"), 'i', 0);
|
||||
displayButton(8, 8+fs*9, XLAT("l = lands"), 'l', 0);
|
||||
displayfr(8, 8+fs*10, 2, vid.fsize, XLAT("c = copy"), 0xC0C0C0, 0);
|
||||
displayButton(8, 8+fs*11, XLAT("u = undo"), 'u', 0);
|
||||
if(painttype == 4)
|
||||
displayButton(8, 8+fs*12, XLAT("f = flip %1", ONOFF(copyflip)), 'u', 0);
|
||||
displayButton(8, 8+fs*13, XLAT("r = regular"), 'r', 0);
|
||||
displayButton(8, 8+fs*14, XLAT("p = paint"), 'p', 0);
|
||||
|
||||
dialog::addBoolItem(XLAT("display pattern codes (full)"), (displaycodes == 1), 'd');
|
||||
dialog::addBoolItem(XLAT("display pattern codes (simplified)"), (displaycodes == 2), 's');
|
||||
displayFunctionKeys();
|
||||
|
||||
dialog::addBoolItem(XLAT("display only hexagons"), (whichShape == '6'), '6');
|
||||
dialog::addBoolItem(XLAT("display only heptagons"), (whichShape == '7'), '7');
|
||||
dialog::addBoolItem(XLAT("display the triheptagonal grid"), (whichShape == '8'), '8');
|
||||
dialog::addItem(XLAT("line patterns"), 'l');
|
||||
|
||||
dialog::addItem(XLAT("predesigned patterns"), 'r');
|
||||
dialog::display();
|
||||
}
|
||||
else if(subscreen == 3) {
|
||||
dialog::init("predesigned patterns");
|
||||
dialog::addItem(XLAT("Gameboard"), 'g');
|
||||
dialog::addItem(XLAT("random colors"), 'r');
|
||||
dialog::addItem(XLAT("rainbow landscape"), 'l');
|
||||
dialog::addItem(XLAT("dark rainbow landscape"), 'd');
|
||||
dialog::addItem(XLAT("football"), 'F');
|
||||
|
||||
dialog::addSelItem(XLAT("emerald pattern"), "emerald", 'e');
|
||||
|
||||
dialog::addSelItem(XLAT("four elements"), "palace", 'b');
|
||||
dialog::addSelItem(XLAT("eight domains"), "palace", 'a');
|
||||
|
||||
dialog::addSelItem(XLAT("zebra pattern"), "zebra", 'z');
|
||||
dialog::addSelItem(XLAT("four triangles"), "zebra", 't');
|
||||
dialog::addSelItem(XLAT("three stripes"), "zebra", 'x');
|
||||
|
||||
dialog::addSelItem(XLAT("random black-and-white"), "current", 'w');
|
||||
|
||||
dialog::addSelItem(XLAT("field pattern C"), "field", 'C');
|
||||
dialog::addSelItem(XLAT("field pattern D"), "field", 'D');
|
||||
dialog::addSelItem(XLAT("field pattern N"), "field", 'N');
|
||||
dialog::addSelItem(XLAT("field pattern S"), "field", 'S');
|
||||
|
||||
dialog::display();
|
||||
}
|
||||
else if(subscreen == 1 && painttype == 6)
|
||||
dialog::drawColorDialog(paintwhat);
|
||||
else if(subscreen == 1) {
|
||||
v.clear();
|
||||
if(painttype == 4) painttype = 0;
|
||||
switch(painttype) {
|
||||
case 0:
|
||||
for(int i=0; i<motypes; i++) {
|
||||
eMonster m = eMonster(i);
|
||||
if(
|
||||
m == moTongue || m == moPlayer || m == moFireball || m == moBullet ||
|
||||
m == moFlailBullet || m == moShadow || m == moAirball ||
|
||||
m == moWolfMoved || m == moGolemMoved ||
|
||||
m == moTameBomberbirdMoved || m == moKnightMoved ||
|
||||
m == moDeadBug || m == moLightningBolt || m == moDeadBird ||
|
||||
m == moMouseMoved || m == moPrincessMoved || m == moPrincessArmedMoved) ;
|
||||
else vpush(i, minf[i].name);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
for(int i=0; i<ittypes; i++) vpush(i, iinf[i].name);
|
||||
break;
|
||||
case 2:
|
||||
for(int i=0; i<landtypes; i++) vpush(i, linf[i].name);
|
||||
break;
|
||||
case 3:
|
||||
for(int i=0; i<walltypes; i++) if(i != waChasmD) vpush(i, winf[i].name);
|
||||
break;
|
||||
}
|
||||
// sort(v.begin(), v.end());
|
||||
|
||||
if(infix != "") mouseovers = infix;
|
||||
|
||||
int q = v.size();
|
||||
int percolumn = vid.yres / (vid.fsize+5) - 4;
|
||||
int columns = 1 + (q-1) / percolumn;
|
||||
|
||||
for(int i=0; i<q; i++) {
|
||||
int x = 16 + (vid.xres * (i/percolumn)) / columns;
|
||||
int y = (vid.fsize+5) * (i % percolumn) + vid.fsize*2;
|
||||
|
||||
int actkey = 1000 + i;
|
||||
string vv = v[i].first;
|
||||
if(i < 9) { vv += ": "; vv += ('1' + i); }
|
||||
|
||||
displayButton(x, y, vv, actkey, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* displayfr(vid.xres/2, vid.ycenter - vid.radius * 3/4 - vid.fsize*3/2, 2,
|
||||
vid.fsize,
|
||||
XLAT("MAP EDITOR: ") + paintwhat_str,
|
||||
0xFFFFFF, 8); */
|
||||
|
||||
int fs = vid.fsize + 5;
|
||||
|
||||
getcstat = '-';
|
||||
|
||||
displayfr(8, 8 + fs, 2, vid.fsize, paintwhat_str, forecolor, 0);
|
||||
displayfr(8, 8+fs*2, 2, vid.fsize, XLAT("use at your own risk!"), 0x800000, 0);
|
||||
|
||||
displayButton(8, 8+fs*4, XLAT("0-9 = radius (%1)", its(radius)), ('0' + (radius+1)%10), 0);
|
||||
displayButton(8, 8+fs*5, XLAT("b = boundary"), 'b', 0);
|
||||
displayButton(8, 8+fs*6, XLAT("m = monsters"), 'm', 0);
|
||||
displayButton(8, 8+fs*7, XLAT("w = walls"), 'w', 0);
|
||||
displayButton(8, 8+fs*8, XLAT("i = items"), 'i', 0);
|
||||
displayButton(8, 8+fs*9, XLAT("l = lands"), 'l', 0);
|
||||
displayfr(8, 8+fs*10, 2, vid.fsize, XLAT("c = copy"), 0xC0C0C0, 0);
|
||||
displayButton(8, 8+fs*11, XLAT("u = undo"), 'u', 0);
|
||||
if(painttype == 4)
|
||||
displayButton(8, 8+fs*12, XLAT("f = flip %1", ONOFF(copyflip)), 'u', 0);
|
||||
displayButton(8, 8+fs*13, XLAT("r = regular"), 'r', 0);
|
||||
displayButton(8, 8+fs*14, XLAT("p = paint"), 'p', 0);
|
||||
|
||||
displayFunctionKeys();
|
||||
}
|
||||
keyhandler = handleKeyMap;
|
||||
}
|
||||
|
||||
int spillinc() {
|
||||
@ -1032,16 +1082,16 @@ namespace mapeditor {
|
||||
}
|
||||
}
|
||||
|
||||
bool handleKeyFile(int uni, int& sym) {
|
||||
string& s(cmode == emDraw ? picfile : levelfile);
|
||||
bool handleKeyFile(int uni, int sym) {
|
||||
string& s(*cfileptr);
|
||||
int i = size(s) - (editext?0:4);
|
||||
if(uni > 2000) sym = uni - 2000;
|
||||
if(sym == SDLK_RETURN || sym == SDLK_KP_ENTER || sym == SDLK_ESCAPE) {
|
||||
choosefile = false;
|
||||
popScreen();
|
||||
return true;
|
||||
}
|
||||
else if(sym == SDLK_F2 || sym == SDLK_F3) {
|
||||
choosefile = false;
|
||||
popScreen();
|
||||
return false;
|
||||
}
|
||||
else if(sym == SDLK_F4) {
|
||||
@ -1075,132 +1125,80 @@ namespace mapeditor {
|
||||
return true;
|
||||
}
|
||||
|
||||
void handleKey(int sym, int uni) {
|
||||
if(choosefile && handleKeyFile(sym, uni)) ;
|
||||
else if(subscreen == 1 && painttype == 6) {
|
||||
void handleKeyMap(int sym, int uni) {
|
||||
handlePanning(sym, uni);
|
||||
|
||||
// left-clicks are coded with '-', and right-clicks are coded with sym F1
|
||||
if(uni == '-') undoLock();
|
||||
if(mousepressed && mouseover && sym != SDLK_F1)
|
||||
allInPattern(mouseover, radius, neighborId(mouseover, mouseover2));
|
||||
|
||||
if(mouseover) for(int i=0; i<mouseover->type; i++) createMov(mouseover, i);
|
||||
if(uni == 'u') applyUndo();
|
||||
else if(uni == 'v' || sym == SDLK_F10 || sym == SDLK_ESCAPE) popScreen();
|
||||
else if(uni >= '0' && uni <= '9') radius = uni - '0';
|
||||
else if(uni == 'm') pushScreen(showList), painttype = 0, infix = "";
|
||||
else if(uni == 'i') pushScreen(showList), painttype = 1, infix = "";
|
||||
else if(uni == 'l') pushScreen(showList), painttype = 2, infix = "";
|
||||
else if(uni == 'w') pushScreen(showList), painttype = 3, infix = "";
|
||||
else if(uni == 'r') pushScreen(showPattern);
|
||||
else if(uni == 't' && mouseover) {
|
||||
cwt.c = mouseover; playermoved = true;
|
||||
cwt.spin = neighborId(mouseover, mouseover2);
|
||||
}
|
||||
else if(uni == 'b') painttype = 5, paintwhat_str = XLAT("boundary");
|
||||
else if(uni == 'p') {
|
||||
painttype = 6;
|
||||
paintwhat_str = "paint";
|
||||
int v = dialog::handleKeyColor(sym, uni, paintwhat);
|
||||
if(v == 1) subscreen = 0;
|
||||
if(v == 2) cmode = emNormal;
|
||||
dialog::openColorDialog(paintwhat = (painttype ==6 ? paintwhat : 0x808080));
|
||||
}
|
||||
else if(subscreen == 1) {
|
||||
if(uni >= '1' && uni <= '9') uni = 1000 + uni - '1';
|
||||
if(sym == SDLK_RETURN || sym == SDLK_KP_ENTER || sym == '-' || sym == SDLK_KP_MINUS) uni = 1000;
|
||||
for(int z=0; z<size(v); z++) if(1000 + z == uni) {
|
||||
paintwhat = v[z].second;
|
||||
paintwhat_str = v[z].first;
|
||||
subscreen = 0;
|
||||
mousepressed = false;
|
||||
}
|
||||
if(editInfix(uni)) ;
|
||||
else if(subscreen == 1 && uni != 0) cmode = emNormal;
|
||||
else if(sym == SDLK_F2) {
|
||||
if(mapstream::saveMap(levelfile.c_str()))
|
||||
addMessage(XLAT("Map saved to %1", levelfile));
|
||||
else
|
||||
addMessage(XLAT("Failed to save map to %1", levelfile));
|
||||
}
|
||||
else if(subscreen == 3) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
if((uni >= 'a' && uni <= 'z') || (uni >= 'A' && uni <= 'Z')) {
|
||||
whichCanvas = uni;
|
||||
subcanvas = rand();
|
||||
firstland = laCanvas; randomPatternsMode = false;
|
||||
restartGame(); subscreen = 0;
|
||||
}
|
||||
else if(uni != 0) subscreen = 0;
|
||||
else if(sym == SDLK_F5) {
|
||||
restartGame();
|
||||
}
|
||||
else if(subscreen == 2) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
if(uni == 'f' || uni == 'p' || uni == 'z' || uni == 'H' || uni == 'F') {
|
||||
if(whichPattern == uni) whichPattern = 0;
|
||||
else whichPattern = uni;
|
||||
clearModelCells();
|
||||
}
|
||||
|
||||
else if(uni == '0') symRotation = !symRotation;
|
||||
else if(uni == '1') sym01 = !sym01;
|
||||
else if(uni == '2') sym02 = !sym02;
|
||||
else if(uni == '3') sym03 = !sym03;
|
||||
else if(uni == '6' || uni == '7' || uni == '8') {
|
||||
if(whichShape == uni) whichShape = 0;
|
||||
else whichShape = uni;
|
||||
}
|
||||
else if(uni == '3') sym03 = !sym03;
|
||||
else if(uni == 'd') displaycodes = displaycodes == 1 ? 0 : 1;
|
||||
else if(uni == 's') displaycodes = displaycodes == 2 ? 0 : 2;
|
||||
|
||||
else if(uni == 'l')
|
||||
cmode = emLinepattern;
|
||||
|
||||
else if(uni == 'r')
|
||||
subscreen = 3;
|
||||
|
||||
else if(uni != 0) subscreen = 0;
|
||||
else if(sym == SDLK_F3) {
|
||||
if(mapstream::loadMap(levelfile.c_str()))
|
||||
addMessage(XLAT("Map loaded from %1", levelfile));
|
||||
else
|
||||
addMessage(XLAT("Failed to load map from %1", levelfile));
|
||||
}
|
||||
else {
|
||||
// left-clicks are coded with '-', and right-clicks are coded with sym F1
|
||||
if(uni == '-') undoLock();
|
||||
if(mousepressed && mouseover && sym != SDLK_F1)
|
||||
allInPattern(mouseover, radius, neighborId(mouseover, mouseover2));
|
||||
|
||||
if(mouseover) for(int i=0; i<mouseover->type; i++) createMov(mouseover, i);
|
||||
if(uni == 'u') applyUndo();
|
||||
else if(uni == 'v' || sym == SDLK_F10 || sym == SDLK_ESCAPE) cmode = emNormal;
|
||||
else if(uni >= '0' && uni <= '9') radius = uni - '0';
|
||||
else if(uni == 'm') subscreen = 1, painttype = 0, infix = "";
|
||||
else if(uni == 'i') subscreen = 1, painttype = 1, infix = "";
|
||||
else if(uni == 'l') subscreen = 1, painttype = 2, infix = "";
|
||||
else if(uni == 'w') subscreen = 1, painttype = 3, infix = "";
|
||||
else if(uni == 'r') subscreen = 2;
|
||||
else if(uni == 't' && mouseover) {
|
||||
cwt.c = mouseover; playermoved = true;
|
||||
cwt.spin = neighborId(mouseover, mouseover2);
|
||||
}
|
||||
else if(uni == 'b') painttype = 5, paintwhat_str = XLAT("boundary");
|
||||
else if(uni == 'p')
|
||||
subscreen = 1, paintwhat = (painttype ==6 ? paintwhat : 0x808080), painttype = 6;
|
||||
else if(sym == SDLK_F2) {
|
||||
if(mapstream::saveMap(levelfile.c_str()))
|
||||
addMessage(XLAT("Map saved to %1", levelfile));
|
||||
else
|
||||
addMessage(XLAT("Failed to save map to %1", levelfile));
|
||||
}
|
||||
else if(sym == SDLK_F5) {
|
||||
restartGame();
|
||||
}
|
||||
else if(sym == SDLK_F3) {
|
||||
if(mapstream::loadMap(levelfile.c_str()))
|
||||
addMessage(XLAT("Map loaded from %1", levelfile));
|
||||
else
|
||||
addMessage(XLAT("Failed to load map from %1", levelfile));
|
||||
}
|
||||
else if(sym == SDLK_F4)
|
||||
choosefile = true;
|
||||
else if(sym == SDLK_F6) {
|
||||
saveHighQualityShot();
|
||||
}
|
||||
else if(sym == SDLK_F8) {
|
||||
svg::render();
|
||||
}
|
||||
else if(sym == SDLK_F7) {
|
||||
drawplayer = !drawplayer;
|
||||
}
|
||||
else if(uni == 'c') {
|
||||
if(mouseover && mouseover2)
|
||||
copydir = neighborId(mouseover, mouseover2);
|
||||
if(copydir<0) copydir = 0;
|
||||
copyflip = (uni == 'f');
|
||||
copywhat = mouseover, painttype = 4;
|
||||
paintwhat_str = XLAT("copying");
|
||||
}
|
||||
else if(uni == 'f') {
|
||||
copyflip = !copyflip;
|
||||
}
|
||||
else if(uni == 'h' || sym == SDLK_F1) {
|
||||
lastmode = cmode;
|
||||
cmode = emHelp;
|
||||
help = mehelptext();
|
||||
}
|
||||
else if(uni == ' ') {
|
||||
cmode = emDraw;
|
||||
initdraw(mouseover ? mouseover : cwt.c);
|
||||
}
|
||||
else if(sym == SDLK_F4) {
|
||||
cfileptr = &levelfile;
|
||||
filecaption = XLAT("level to save/load:");
|
||||
cfileext = ".lev";
|
||||
pushScreen(drawFileDialog);
|
||||
}
|
||||
else if(sym == SDLK_F6) {
|
||||
saveHighQualityShot();
|
||||
}
|
||||
else if(sym == SDLK_F8) {
|
||||
svg::render();
|
||||
}
|
||||
else if(sym == SDLK_F7) {
|
||||
drawplayer = !drawplayer;
|
||||
}
|
||||
else if(uni == 'c') {
|
||||
if(mouseover && mouseover2)
|
||||
copydir = neighborId(mouseover, mouseover2);
|
||||
if(copydir<0) copydir = 0;
|
||||
copyflip = (uni == 'f');
|
||||
copywhat = mouseover, painttype = 4;
|
||||
paintwhat_str = XLAT("copying");
|
||||
}
|
||||
else if(uni == 'f') {
|
||||
copyflip = !copyflip;
|
||||
}
|
||||
else if(uni == 'h' || sym == SDLK_F1)
|
||||
gotoHelp(mehelptext());
|
||||
else if(uni == ' ') {
|
||||
popScreen();
|
||||
pushScreen(showDrawEditor);
|
||||
initdraw(mouseover ? mouseover : cwt.c);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1216,7 +1214,7 @@ namespace mapeditor {
|
||||
"the screen for more keys.";
|
||||
|
||||
string drawhelptext() {
|
||||
return XLAT(mapeditor::drawhelp);
|
||||
return XLAT(drawhelp);
|
||||
}
|
||||
|
||||
int dslayer;
|
||||
@ -1235,83 +1233,57 @@ namespace mapeditor {
|
||||
}
|
||||
|
||||
void drawGhosts(cell *c, const transmatrix& V, int ct) {
|
||||
/* if(cmode == emDraw && cwt.c->type == 6 && ct == 6) for(int a=0; a<dsCur->rots; a++) {
|
||||
|
||||
transmatrix V2 = V * spin(M_PI + 2*M_PI*a/dsCur->rots);
|
||||
|
||||
if(mouseout()) break;
|
||||
|
||||
hyperpoint P2 = V2 * inverse(cwtV) * mouseh;
|
||||
|
||||
int xc, yc, sc;
|
||||
getcoord(P2, xc, yc, sc);
|
||||
displaychr(xc, yc, sc, 10, 'x', 0xFF);
|
||||
|
||||
if(crad > 0 && c->cpdist <= 3) {
|
||||
lalpha = 0x80;
|
||||
transmatrix movtocc = V2 * inverse(cwtV) * rgpushxto0(ccenter);
|
||||
for(int d=0; d<84; d++)
|
||||
drawline(movtocc * ddi(d+1, crad) * C0, movtocc * ddi(d, crad) * C0, 0xC00000);
|
||||
lalpha = 0xFF;
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
hyperpoint ccenter = C0;
|
||||
hyperpoint coldcenter = C0;
|
||||
|
||||
void drawGrid() {
|
||||
if(cmode == emDraw && !inHighQual) {
|
||||
|
||||
for(int d=0; d<84; d++) {
|
||||
transmatrix d2 = drawtrans * rgpushxto0(ccenter);
|
||||
int lalpha;
|
||||
if(d % (84/drawcell->type) == 0)
|
||||
lalpha = 0x40;
|
||||
else
|
||||
lalpha = 0x20;
|
||||
int col = darkena(0xC0C0C0, 0, lalpha);
|
||||
queueline(d2 * C0, d2 * spin(M_PI*d/42)* xpush(1) * C0, col);
|
||||
for(int u=2; u<=20; u++) {
|
||||
if(u % 5 == 0) lalpha = 0x40;
|
||||
else lalpha = 0x20;
|
||||
queueline(
|
||||
d2 * spin(M_PI*d/42)* xpush(u/20.) * C0,
|
||||
d2 * spin(M_PI*(d+1)/42)* xpush(u/20.) * C0,
|
||||
darkena(0xC0C0C0, 0, lalpha));
|
||||
}
|
||||
for(int d=0; d<84; d++) {
|
||||
transmatrix d2 = drawtrans * rgpushxto0(ccenter);
|
||||
int lalpha;
|
||||
if(d % (84/drawcell->type) == 0)
|
||||
lalpha = 0x40;
|
||||
else
|
||||
lalpha = 0x20;
|
||||
int col = darkena(0xC0C0C0, 0, lalpha);
|
||||
queueline(d2 * C0, d2 * spin(M_PI*d/42)* xpush(1) * C0, col);
|
||||
for(int u=2; u<=20; u++) {
|
||||
if(u % 5 == 0) lalpha = 0x40;
|
||||
else lalpha = 0x20;
|
||||
queueline(
|
||||
d2 * spin(M_PI*d/42)* xpush(u/20.) * C0,
|
||||
d2 * spin(M_PI*(d+1)/42)* xpush(u/20.) * C0,
|
||||
darkena(0xC0C0C0, 0, lalpha));
|
||||
}
|
||||
queueline(drawtrans*ccenter, drawtrans*coldcenter, darkena(0xC0C0C0, 0, 0x20));
|
||||
}
|
||||
queueline(drawtrans*ccenter, drawtrans*coldcenter, darkena(0xC0C0C0, 0, 0x20));
|
||||
|
||||
int sg = drawcellShapeGroup();
|
||||
int sg = drawcellShapeGroup();
|
||||
|
||||
if(0) for(int i=0; i<USERSHAPEIDS; i++) if(editingShape(sg, i) && usershapes[sg][i]) {
|
||||
if(0) for(int i=0; i<USERSHAPEIDS; i++) if(editingShape(sg, i) && usershapes[sg][i]) {
|
||||
|
||||
usershapelayer &ds(usershapes[sg][i]->d[mapeditor::dslayer]);
|
||||
usershapelayer &ds(usershapes[sg][i]->d[mapeditor::dslayer]);
|
||||
|
||||
for(int a=0; a<size(ds.list); a++) {
|
||||
hyperpoint P2 = drawtrans * ds.list[a];
|
||||
for(int a=0; a<size(ds.list); a++) {
|
||||
hyperpoint P2 = drawtrans * ds.list[a];
|
||||
|
||||
queuechr(P2, 10, 'x',
|
||||
darkena(a == 0 ? 0x00FF00 :
|
||||
a == size(ds.list)-1 ? 0xFF0000 :
|
||||
0xFFFF00, 0, 0xFF));
|
||||
}
|
||||
queuechr(P2, 10, 'x',
|
||||
darkena(a == 0 ? 0x00FF00 :
|
||||
a == size(ds.list)-1 ? 0xFF0000 :
|
||||
0xFFFF00, 0, 0xFF));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void drawHandleKey(int sym, int uni);
|
||||
|
||||
void showDrawEditor() {
|
||||
cmode2 = smDraw;
|
||||
drawGrid();
|
||||
|
||||
if(!mouseout()) getcstat = '-';
|
||||
|
||||
if(coloring) {
|
||||
dialog::drawColorDialog(colortouse);
|
||||
return;
|
||||
}
|
||||
|
||||
if(choosefile) { drawFileDialog(); return; }
|
||||
|
||||
int sg = drawcellShapeGroup();
|
||||
|
||||
string line1, line2;
|
||||
@ -1395,6 +1367,8 @@ namespace mapeditor {
|
||||
}
|
||||
|
||||
displayFunctionKeys();
|
||||
|
||||
keyhandler = drawHandleKey;
|
||||
}
|
||||
|
||||
bool rebuildPolys = false;
|
||||
@ -1589,17 +1563,10 @@ namespace mapeditor {
|
||||
|
||||
void drawHandleKey(int sym, int uni) {
|
||||
|
||||
if(choosefile && handleKeyFile(sym, uni)) return;
|
||||
handlePanning(sym, uni);
|
||||
|
||||
if(uni == SETMOUSEKEY) mousekey = newmousekey;
|
||||
|
||||
if(coloring) {
|
||||
int v = dialog::handleKeyColor(sym, uni, colortouse);
|
||||
if(v == 2) { coloring = false; return; }
|
||||
else if(v == 1) { coloring = false; uni = COLORKEY; }
|
||||
else return;
|
||||
}
|
||||
|
||||
dslayer %= USERLAYERS;
|
||||
hyperpoint mh = inverse(drawtrans) * mouseh;
|
||||
|
||||
@ -1638,11 +1605,21 @@ namespace mapeditor {
|
||||
if(uni == 'z') vid.scale *= 2;
|
||||
if(uni == 'o') vid.scale /= 2;
|
||||
|
||||
if(uni == ' ' && cheater) cmode = emMapEditor;
|
||||
if(uni == ' ' && cheater) {
|
||||
popScreen();
|
||||
pushScreen(showMapEditor);
|
||||
}
|
||||
|
||||
if(uni == 'p') coloring = true;
|
||||
if(uni == 'p')
|
||||
dialog::openColorDialog(colortouse);
|
||||
|
||||
if(sym == SDLK_F4) choosefile = true;
|
||||
if(sym == SDLK_F4) {
|
||||
filecaption = XLAT("pics to save/load:");
|
||||
cfileptr = &picfile;
|
||||
cfileext = ".pic";
|
||||
pushScreen(drawFileDialog);
|
||||
return;
|
||||
}
|
||||
|
||||
if(sym == SDLK_F2) {
|
||||
FILE *f = fopen(picfile.c_str(), "wt");
|
||||
@ -1728,20 +1705,28 @@ namespace mapeditor {
|
||||
if(usershapes[i][j]) delete usershapes[i][j];
|
||||
}
|
||||
|
||||
if(sym == SDLK_ESCAPE) cmode = emNormal;
|
||||
if(sym == SDLK_ESCAPE) popScreen();
|
||||
|
||||
if(sym == SDLK_F1) {
|
||||
lastmode = cmode;
|
||||
cmode = emHelp;
|
||||
sym = 0;
|
||||
help = drawhelptext();
|
||||
gotoHelp(drawhelptext());
|
||||
}
|
||||
|
||||
if(sym == SDLK_F10) cmode = emNormal;
|
||||
if(sym == SDLK_F10) popScreen();
|
||||
|
||||
if(rebuildPolys)
|
||||
buildpolys(), rebuildPolys = false;
|
||||
}
|
||||
|
||||
auto hooks = addHook(clearmemory, 0, [] () {
|
||||
if(mapeditor::painttype == 4)
|
||||
mapeditor::painttype = 0, mapeditor::paintwhat = 0,
|
||||
mapeditor::paintwhat_str = "clear monster";
|
||||
mapeditor::copywhat = NULL;
|
||||
mapeditor::undo.clear();
|
||||
if(!cheater) mapeditor::displaycodes = 0;
|
||||
if(!cheater) mapeditor::whichShape = 0;
|
||||
modelcell.clear();
|
||||
});
|
||||
#endif
|
||||
|
||||
int canvasback = linf[laCanvas].color >> 2;
|
||||
@ -1897,7 +1882,7 @@ namespace mapeditor {
|
||||
}
|
||||
|
||||
#ifndef NOEDIT
|
||||
if(cmode == emDraw && mapeditor::editingShape(group, id)) {
|
||||
if(cmode2 == smDraw && mapeditor::editingShape(group, id)) {
|
||||
|
||||
/* for(int a=0; a<size(ds.list); a++) {
|
||||
hyperpoint P2 = V * ds.list[a];
|
||||
@ -2264,12 +2249,13 @@ lessalphaif(col, behindsphere(V), behindsphere(gmatrix[c2]))
|
||||
dialog::addInfo("change the alpha parameter to show the lines");
|
||||
|
||||
dialog::display();
|
||||
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
if(uni >= 'a' && uni < 'a' + numpat)
|
||||
dialog::openColorDialog(patterns[uni - 'a'].color, NULL);
|
||||
else if(doexiton(sym,uni)) popScreen();
|
||||
};
|
||||
}
|
||||
|
||||
void handleMenu(int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
if(uni >= 'a' && uni < 'a' + numpat)
|
||||
dialog::openColorDialog(patterns[uni - 'a'].color, NULL);
|
||||
else if(doexiton(sym,uni)) cmode = emNormal;
|
||||
}
|
||||
};
|
||||
|
64
netgen.cpp
64
netgen.cpp
@ -659,48 +659,48 @@ namespace netgen {
|
||||
|
||||
dialog::display();
|
||||
}
|
||||
}
|
||||
|
||||
void handleKey(int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
|
||||
if(!loaded) {
|
||||
loadData();
|
||||
if(!loaded) {
|
||||
addMessage(XLAT("Failed to load the file 'papermodeldata.txt'"));
|
||||
cmode = emNormal;
|
||||
loadData();
|
||||
if(!loaded) {
|
||||
addMessage(XLAT("Failed to load the file 'papermodeldata.txt'"));
|
||||
popScreen();
|
||||
return;
|
||||
}
|
||||
if(!created) {
|
||||
View = Id;
|
||||
if(centerover) viewctr.h = centerover->master;
|
||||
else viewctr.h = cwt.c->master;
|
||||
playermoved = false;
|
||||
dataFromHR();
|
||||
designNet();
|
||||
created = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(mode == 2 && uni != 0) {
|
||||
mode = 0;
|
||||
return;
|
||||
}
|
||||
if(!created) {
|
||||
if(uni == 's') {
|
||||
View = Id;
|
||||
if(centerover) viewctr.h = centerover->master;
|
||||
else viewctr.h = cwt.c->master;
|
||||
playermoved = false;
|
||||
dataFromHR();
|
||||
designNet();
|
||||
created = 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(mode == 2 && uni != 0) {
|
||||
mode = 0;
|
||||
return;
|
||||
}
|
||||
if(uni == 's') {
|
||||
View = Id;
|
||||
if(centerover) viewctr.h = centerover->master;
|
||||
else viewctr.h = cwt.c->master;
|
||||
playermoved = false;
|
||||
}
|
||||
else if(uni == 'c') {
|
||||
createPapermodel();
|
||||
addMessage(XLAT("The paper model created as papermodel-*.bmp"));
|
||||
}
|
||||
else if(uni == 'd') designNet();
|
||||
else if(uni == 't') mode = 2;
|
||||
else if(doexiton(sym, uni))
|
||||
cmode = emNormal;
|
||||
else if(uni == 'c') {
|
||||
createPapermodel();
|
||||
addMessage(XLAT("The paper model created as papermodel-*.bmp"));
|
||||
}
|
||||
else if(uni == 'd') designNet();
|
||||
else if(uni == 't') mode = 2;
|
||||
else if(doexiton(sym, uni))
|
||||
popScreen();
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
70
rogueviz.cpp
70
rogueviz.cpp
@ -955,9 +955,9 @@ string describe(shmup::monster *m) {
|
||||
|
||||
sort(alledges.begin(), alledges.end(), edgecmp);
|
||||
|
||||
help = "Edges: ";
|
||||
::help = "Edges: ";
|
||||
|
||||
if(vd.info) help = (*vd.info) + "\n" + help;
|
||||
if(vd.info) ::help = (*vd.info) + "\n" + help;
|
||||
|
||||
for(int j=0; j<size(alledges); j++) {
|
||||
edgeinfo *ei = alledges[j];
|
||||
@ -1741,37 +1741,37 @@ void showMenu() {
|
||||
dialog::addItem(XLAT("exit menu"), 'v');
|
||||
|
||||
dialog::display();
|
||||
}
|
||||
|
||||
void handleMenu(int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
if(uni == 't')
|
||||
dialog::editNumber(sag::temperature, sag::lowtemp, sag::hightemp, 1, 0, XLAT("temperature"), "");
|
||||
else if(uni == 'm') {
|
||||
sag::sagmode = sag::eSagmode( (1+sag::sagmode) % 3 );
|
||||
}
|
||||
else if(uni == 'l') showlabels = !showlabels;
|
||||
else if(uni == 'v') rog3 = !rog3;
|
||||
else if(uni == 'x') specialmark = !specialmark;
|
||||
else if(uni == 'b') backcolor ^= 0xFFFFFF, bordcolor ^= 0xFFFFFF, forecolor ^= 0xFFFFFF;
|
||||
else if(uni == 'g') {
|
||||
dialog::editNumber(ggamma, 0, 5, .01, 0.5, XLAT("gamma value for edges"), "");
|
||||
dialog::sidedialog = true;
|
||||
}
|
||||
else if(uni == 'z') {
|
||||
for(int i=0; i<size(named)-1; i++) if(named[i] == cwt.c)
|
||||
swap(named[i], named[i+1]);
|
||||
if(!size(named) || named[size(named)-1] != cwt.c) named.push_back(cwt.c);
|
||||
printf("named = %d\n", size(named));
|
||||
cmode = emNormal;
|
||||
}
|
||||
else if(kind == kKohonen && kohonen::handleMenu(sym, uni)) ;
|
||||
else if(doexiton(sym, uni)) cmode = emNormal;
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
if(uni == 't')
|
||||
dialog::editNumber(sag::temperature, sag::lowtemp, sag::hightemp, 1, 0, XLAT("temperature"), "");
|
||||
else if(uni == 'm') {
|
||||
sag::sagmode = sag::eSagmode( (1+sag::sagmode) % 3 );
|
||||
}
|
||||
else if(uni == 'l') showlabels = !showlabels;
|
||||
else if(uni == 'v') rog3 = !rog3;
|
||||
else if(uni == 'x') specialmark = !specialmark;
|
||||
else if(uni == 'b') backcolor ^= 0xFFFFFF, bordcolor ^= 0xFFFFFF, forecolor ^= 0xFFFFFF;
|
||||
else if(uni == 'g') {
|
||||
dialog::editNumber(ggamma, 0, 5, .01, 0.5, XLAT("gamma value for edges"), "");
|
||||
dialog::sidedialog = true;
|
||||
}
|
||||
else if(uni == 'z') {
|
||||
for(int i=0; i<size(named)-1; i++) if(named[i] == cwt.c)
|
||||
swap(named[i], named[i+1]);
|
||||
if(!size(named) || named[size(named)-1] != cwt.c) named.push_back(cwt.c);
|
||||
printf("named = %d\n", size(named));
|
||||
popScreen();
|
||||
}
|
||||
else if(kind == kKohonen && kohonen::handleMenu(sym, uni)) ;
|
||||
else if(doexiton(sym, uni)) popScreen();
|
||||
};
|
||||
}
|
||||
|
||||
void processKey(int sym, int uni) { }
|
||||
|
||||
string help() {
|
||||
string makehelp() {
|
||||
string ret =
|
||||
"This is RogueViz, a visualization engine based on HyperRogue.\n\nUse WASD to move, v for menu.\n\n"
|
||||
"Read more about RogueViz on : http://roguetemple.com/z/hyper/rogueviz.php\n\n";
|
||||
@ -1822,15 +1822,16 @@ template<class T, class T1> function<void(presmode)> roguevizslide_action(char c
|
||||
return [c,t,act] (presmode mode) {
|
||||
mapeditor::canvasback = 0x101010;
|
||||
setCanvas(mode, c);
|
||||
if(mode == 1 || mode == pmGeometryStart) t();
|
||||
if(mode == pmStart || mode == pmGeometryStart) t();
|
||||
|
||||
if(mode == 3 || mode == pmGeometry || mode == pmGeometryReset) {
|
||||
act(mode);
|
||||
|
||||
if(mode == pmStop || mode == pmGeometry || mode == pmGeometryReset) {
|
||||
rogueviz::close();
|
||||
shmup::clearMonsters();
|
||||
if(mode == pmGeometryReset) t();
|
||||
}
|
||||
|
||||
act(mode);
|
||||
};
|
||||
}
|
||||
|
||||
@ -1983,4 +1984,11 @@ slide rvslides[] = {
|
||||
|
||||
}
|
||||
|
||||
auto hooks =
|
||||
addHook(hooks_frame, 0, drawExtra) +
|
||||
addHook(hooks_args, 100, readArgs) +
|
||||
addHook(clearmemory, 0, clear) +
|
||||
addHook(hooks_config, 0, [] () { ss::list(rogueviz::rvtour::rvslides); });
|
||||
|
||||
|
||||
};
|
||||
|
61
rug.cpp
61
rug.cpp
@ -667,50 +667,45 @@ void show() {
|
||||
dialog::addBoolItem(XLAT("render texture without OpenGL"), (rendernogl), 'g');
|
||||
dialog::addSelItem(XLAT("texture size"), its(texturesize)+"x"+its(texturesize), 's');
|
||||
dialog::display();
|
||||
}
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
#ifdef PANDORA
|
||||
rendernogl = true;
|
||||
#endif
|
||||
dialog::handleNavigation(sym, uni);
|
||||
|
||||
void handleKey(int sym, int uni) {
|
||||
#ifdef PANDORA
|
||||
rendernogl = true;
|
||||
#endif
|
||||
dialog::handleNavigation(sym, uni);
|
||||
|
||||
if(uni == 'h') {
|
||||
lastmode = cmode;
|
||||
cmode = emHelp;
|
||||
help =
|
||||
if(uni == 'h') gotoHelp(
|
||||
"In this mode, HyperRogue is played on a 3D model of a part of the hyperbolic plane, "
|
||||
"similar to one you get from the 'paper model creator' or by hyperbolic crocheting.\n\n"
|
||||
"This requires some OpenGL extensions and may crash or not work correctly -- enabling "
|
||||
"the 'render texture without OpenGL' options may be helpful in this case. Also the 'render once' option "
|
||||
"will make the rendering faster, but the surface will be rendered only once, so "
|
||||
"you won't be able to play a game on it.\n\n"
|
||||
"Use arrow keys to rotate, Page Up/Down to zoom.";
|
||||
}
|
||||
else if(uni == 'u') {
|
||||
if(sphere) restartGame('E');
|
||||
if(euclid) restartGame('e');
|
||||
rug::init();
|
||||
cmode = emNormal;
|
||||
}
|
||||
else if(uni == 'o')
|
||||
renderonce = !renderonce;
|
||||
#ifndef PANDORA
|
||||
else if(uni == 'g')
|
||||
rendernogl = !rendernogl;
|
||||
#endif
|
||||
else if(uni == 's') {
|
||||
texturesize *= 2;
|
||||
if(texturesize == 8192) texturesize = 128;
|
||||
dialog::scaleLog();
|
||||
}
|
||||
else if(doexiton(sym, uni))
|
||||
cmode = emChangeMode;
|
||||
"Use arrow keys to rotate, Page Up/Down to zoom."
|
||||
);
|
||||
else if(uni == 'u') {
|
||||
if(sphere) restartGame('E');
|
||||
if(euclid) restartGame('e');
|
||||
rug::init();
|
||||
popScreen();
|
||||
}
|
||||
else if(uni == 'o')
|
||||
renderonce = !renderonce;
|
||||
#ifndef PANDORA
|
||||
else if(uni == 'g')
|
||||
rendernogl = !rendernogl;
|
||||
#endif
|
||||
else if(uni == 's') {
|
||||
texturesize *= 2;
|
||||
if(texturesize == 8192) texturesize = 128;
|
||||
dialog::scaleLog();
|
||||
}
|
||||
else if(doexiton(sym, uni)) popScreen();
|
||||
};
|
||||
}
|
||||
|
||||
void select() {
|
||||
if(rug::rugged) rug::close();
|
||||
else cmode = emRugConfig;
|
||||
else pushScreen(rug::show);
|
||||
}
|
||||
|
||||
}
|
||||
|
288
scores.cpp
Normal file
288
scores.cpp
Normal file
@ -0,0 +1,288 @@
|
||||
#ifndef NOSAVE
|
||||
vector<score> scores;
|
||||
|
||||
int scoresort = 2;
|
||||
int scoredisplay = 1;
|
||||
int scorefrom = 0;
|
||||
int scoremode = 0;
|
||||
bool scorerev = false;
|
||||
|
||||
bool scorecompare(const score& s1, const score &s2) {
|
||||
return s1.box[scoresort] > s2.box[scoresort];
|
||||
}
|
||||
|
||||
bool fakescore() {
|
||||
return fakebox[scoredisplay];
|
||||
}
|
||||
|
||||
string displayfor(score* S) {
|
||||
// printf("S=%p, scoredisplay = %d\n", S, scoredisplay);
|
||||
if(S == NULL) {
|
||||
return XLATN(boxname[scoredisplay]);
|
||||
}
|
||||
if(scoredisplay == 0) {
|
||||
char buf[10];
|
||||
snprintf(buf, 10, "%d:%02d", S->box[0]/60, S->box[0]%60);
|
||||
return buf;
|
||||
}
|
||||
if(scoredisplay == 1) {
|
||||
time_t tim = S->box[1];
|
||||
char buf[128]; strftime(buf, 128, "%c", localtime(&tim));
|
||||
return buf;
|
||||
}
|
||||
return its(S->box[scoredisplay]);
|
||||
}
|
||||
|
||||
void loadScores() {
|
||||
scores.clear();
|
||||
FILE *f = fopen(scorefile, "rt");
|
||||
if(!f) {
|
||||
printf("Could not open the score file '%s'!\n", scorefile);
|
||||
addMessage(s0 + "Could not open the score file: " + scorefile);
|
||||
return;
|
||||
}
|
||||
while(!feof(f)) {
|
||||
char buf[120];
|
||||
if(fgets(buf, 120, f) == NULL) break;
|
||||
if(buf[0] == 'H' && buf[1] == 'y') {
|
||||
score sc; bool ok = true;
|
||||
{if(fscanf(f, "%s", buf) <= 0) break;} sc.ver = buf;
|
||||
|
||||
for(int i=0; i<MAXBOX; i++) {
|
||||
if(fscanf(f, "%d", &sc.box[i]) <= 0) { boxid = i; break; }
|
||||
}
|
||||
|
||||
for(int i=boxid; i<MAXBOX; i++) sc.box[i] = 0;
|
||||
|
||||
if(sc.ver >= "4.4") {
|
||||
sc.box[0] = sc.box[65];
|
||||
// the first executable on Steam included a corruption
|
||||
if(sc.box[65] > 1420000000 && sc.box[65] < 1430000000) {
|
||||
sc.box[0] = sc.box[65] - sc.box[1];
|
||||
sc.box[65] = sc.box[0];
|
||||
}
|
||||
// do not include saves
|
||||
if(sc.box[65 + 4 + itOrbSafety - itOrbLightning]) ok = false;
|
||||
}
|
||||
else
|
||||
sc.box[0] = sc.box[1] - sc.box[0]; // could not save then
|
||||
if(ok && boxid > 20) scores.push_back(sc);
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
addMessage(its(size(scores))+" games have been recorded in "+scorefile);
|
||||
pushScreen(showScores);
|
||||
boxid = 0; applyBoxes();
|
||||
scoresort = 2; reverse(scores.begin(), scores.end());
|
||||
scoremode = 0;
|
||||
if(shmup::on) scoremode = 1;
|
||||
else if(hardcore) scoremode = 2;
|
||||
scorefrom = 0;
|
||||
stable_sort(scores.begin(), scores.end(), scorecompare);
|
||||
#ifdef MOBILE
|
||||
extern int andmode;
|
||||
andmode = 2;
|
||||
#endif
|
||||
}
|
||||
|
||||
vector<pair<string, int> > pickscore_options;
|
||||
|
||||
void sortScores() {
|
||||
if(scorerev) reverse(scores.begin(), scores.end());
|
||||
else {
|
||||
scorerev = true;
|
||||
scoresort = scoredisplay;
|
||||
stable_sort(scores.begin(), scores.end(), scorecompare);
|
||||
}
|
||||
}
|
||||
|
||||
void shiftScoreDisplay(int delta) {
|
||||
scoredisplay = (scoredisplay + POSSCORE + delta) % POSSCORE, scorerev = false;
|
||||
if(fakescore()) shiftScoreDisplay(delta);
|
||||
}
|
||||
|
||||
void showScores() {
|
||||
int y = vid.fsize * 7/2;
|
||||
int bx = vid.fsize;
|
||||
getcstat = 1;
|
||||
|
||||
string modes =
|
||||
scoremode == 0 ? XLAT(", m - mode: normal") :
|
||||
scoremode == 1 ? XLAT(", m - mode: shoot'em up") :
|
||||
scoremode == 2 ? XLAT(", m - mode: hardcore only") :
|
||||
"?";
|
||||
|
||||
if(euclid) modes += XLAT(" (E:%1)", euclidland);
|
||||
|
||||
|
||||
mouseovers = XLAT("t/left/right - change display, up/down - scroll, s - sort by") + modes;
|
||||
|
||||
displaystr(bx*4, vid.fsize*2, 0, vid.fsize, "#", forecolor, 16);
|
||||
displaystr(bx*8, vid.fsize*2, 0, vid.fsize, "$$$", forecolor, 16);
|
||||
displaystr(bx*12, vid.fsize*2, 0, vid.fsize, XLAT("kills"), forecolor, 16);
|
||||
displaystr(bx*18, vid.fsize*2, 0, vid.fsize, XLAT("time"), forecolor, 16);
|
||||
displaystr(bx*22, vid.fsize*2, 0, vid.fsize, XLAT("ver"), forecolor, 16);
|
||||
displaystr(bx*23, vid.fsize*2, 0, vid.fsize, displayfor(NULL), forecolor, 0);
|
||||
if(scorefrom < 0) scorefrom = 0;
|
||||
int id = 0;
|
||||
int omit = scorefrom;
|
||||
int rank = 0;
|
||||
while(y < (ISMOBILE ? vid.yres - 5*vid.fsize : vid.yres - 2 * vid.fsize)) {
|
||||
if(id >= size(scores)) break;
|
||||
|
||||
score& S(scores[id]);
|
||||
|
||||
bool wrongtype = false;
|
||||
|
||||
wrongtype |= (euclid && (!S.box[116] || S.box[120] != euclidland));
|
||||
wrongtype |= (!euclid && S.box[116]);
|
||||
|
||||
wrongtype |= (scoremode == 1 && !S.box[119]);
|
||||
wrongtype |= (scoremode != 1 && S.box[119]);
|
||||
wrongtype |= (scoremode == 2 && (!S.box[117] || S.box[118] >= PUREHARDCORE_LEVEL));
|
||||
|
||||
if(wrongtype) { id++; continue; }
|
||||
|
||||
if(omit) { omit--; rank++; id++; continue; }
|
||||
|
||||
char buf[16];
|
||||
|
||||
rank++; sprintf(buf, "%d", rank);
|
||||
displaystr(bx*4, y, 0, vid.fsize, buf, 0xC0C0C0, 16);
|
||||
|
||||
sprintf(buf, "%d", S.box[2]);
|
||||
displaystr(bx*8, y, 0, vid.fsize, buf, 0xC0C0C0, 16);
|
||||
|
||||
sprintf(buf, "%d", S.box[3]);
|
||||
displaystr(bx*12, y, 0, vid.fsize, buf, 0xC0C0C0, 16);
|
||||
|
||||
sprintf(buf, "%d:%02d", S.box[0]/60, S.box[0] % 60);
|
||||
displaystr(bx*18, y, 0, vid.fsize, buf, 0xC0C0C0, 16);
|
||||
|
||||
displaystr(bx*22, y, 0, vid.fsize, S.ver, 0xC0C0C0, 16);
|
||||
|
||||
displaystr(bx*23, y, 0, vid.fsize, displayfor(&S), 0xC0C0C0, 0);
|
||||
|
||||
y += vid.fsize*5/4; id++;
|
||||
}
|
||||
|
||||
#ifdef MOBILE
|
||||
buttonclicked = false;
|
||||
displayabutton(-1, +1, XLAT("SORT"), BTON);
|
||||
displayabutton( 0, +1, XLAT("PICK"), BTON);
|
||||
displayabutton(+1, +1, XLAT("PLAY"), BTON);
|
||||
#endif
|
||||
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
#ifndef MOBILE
|
||||
if(sym == SDLK_LEFT || sym == SDLK_KP4 || sym == 'h' || sym == 'a')
|
||||
shiftScoreDisplay(-1);
|
||||
else if(sym == SDLK_RIGHT || sym == SDLK_KP6 || sym == 'l' || sym == 'd')
|
||||
shiftScoreDisplay(1);
|
||||
else if(sym == 't') { mapeditor::infix = ""; pushScreen(showPickScores); }
|
||||
else if(sym == SDLK_UP || sym == 'k' || sym == 'w')
|
||||
scorefrom -= 5;
|
||||
else if(sym == SDLK_DOWN || sym == 'j' || sym == 'x')
|
||||
scorefrom += 5;
|
||||
else if(sym == PSEUDOKEY_WHEELUP)
|
||||
scorefrom--;
|
||||
else if(sym == PSEUDOKEY_WHEELDOWN)
|
||||
scorefrom++;
|
||||
else if(sym == 's') sortScores();
|
||||
else if(sym == 'm') { scoremode++; scoremode %= 3; }
|
||||
else if(doexiton(sym, uni)) popScreen();
|
||||
#else
|
||||
static int scoredragx, scoredragy;
|
||||
extern bool clicked, lclicked;
|
||||
extern int andmode;
|
||||
|
||||
if(andmode) {
|
||||
if(!clicked && !lclicked) {
|
||||
andmode = 0;
|
||||
scoredragx = mousex;
|
||||
scoredragy = mousey;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
if(clicked && !lclicked)
|
||||
scoredragx = mousex, scoredragy = mousey;
|
||||
|
||||
else if(lclicked && !clicked) {
|
||||
if(mousey > vid.ycenter - 2 * vid.fsize) {
|
||||
if(mousex < vid.xcenter*2/3) sortScores();
|
||||
else if(mousex < vid.xcenter*4/3)
|
||||
cmode = emPickScores;
|
||||
else andmode = 0, popScreen();
|
||||
}
|
||||
}
|
||||
|
||||
else if(clicked && lclicked) {
|
||||
// if(mousex > scoredragx + 80) scoredragx += 80, shiftScoreDisplay(1);
|
||||
// if(mousex < scoredragx - 80) scoredragx -= 80, shiftScoreDisplay(-1);
|
||||
while(mousey > scoredragy + vid.fsize) scoredragy += vid.fsize, scorefrom--;
|
||||
while(mousey < scoredragy - vid.fsize) scoredragy -= vid.fsize, scorefrom++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
bool monsterpage = false;
|
||||
|
||||
void showPickScores() {
|
||||
|
||||
getcstat = '0';
|
||||
int d = scoredisplay;
|
||||
|
||||
pickscore_options.clear();
|
||||
|
||||
scorerev = false;
|
||||
|
||||
for(int i=0; i<POSSCORE; i++) {
|
||||
scoredisplay = i;
|
||||
if(!fakescore()) {
|
||||
string s = displayfor(NULL);
|
||||
if(mapeditor::hasInfix(s))
|
||||
if(monsbox[scoredisplay] == monsterpage)
|
||||
pickscore_options.push_back(make_pair(s, i));
|
||||
}
|
||||
}
|
||||
sort(pickscore_options.begin(), pickscore_options.end());
|
||||
|
||||
int q = (int) pickscore_options.size();
|
||||
int percolumn = vid.yres / (vid.fsize+3) - 4;
|
||||
int columns = 1 + (q-1) / percolumn;
|
||||
|
||||
for(int i=0; i<q; i++) {
|
||||
int x = 16 + (vid.xres * (i/percolumn)) / columns;
|
||||
int y = (vid.fsize+3) * (i % percolumn) + vid.fsize*2;
|
||||
|
||||
scoredisplay = pickscore_options[i].second;
|
||||
if(q <= 9)
|
||||
pickscore_options[i].first = pickscore_options[i].first + " [" + its(i+1) + "]";
|
||||
if(!fakescore())
|
||||
displayButton(x, y, pickscore_options[i].first, 1000+i, 0);
|
||||
}
|
||||
|
||||
displayButton(vid.xres/2, vid.yres - vid.fsize*2, "kills", 'm', 8);
|
||||
|
||||
scoredisplay = d;
|
||||
|
||||
mouseovers = mapeditor::infix;
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
extern int andmode;
|
||||
andmode = 2;
|
||||
if(uni == 'm') monsterpage = !monsterpage; else
|
||||
if(uni >= '1' && uni <= '9') uni = uni + 1000 - '1';
|
||||
else if(uni >= 1000 && uni < 1000 + size(pickscore_options)) {
|
||||
scoredisplay = pickscore_options[uni - 1000].second;
|
||||
popScreen();
|
||||
}
|
||||
else if(mapeditor::editInfix(uni)) ;
|
||||
else if(doexiton(sym, uni)) popScreen();
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
52
shmup.cpp
52
shmup.cpp
@ -4,12 +4,6 @@
|
||||
|
||||
// implementation of the shoot'em up mode
|
||||
|
||||
#ifdef MOBILE
|
||||
#define SHMUPTITLE "shoot'em up mode"
|
||||
#else
|
||||
#define SHMUPTITLE "shoot'em up and multiplayer"
|
||||
#endif
|
||||
|
||||
extern int mousex, mousey;
|
||||
extern bool clicked;
|
||||
|
||||
@ -215,6 +209,8 @@ bool shmupcfg;
|
||||
|
||||
bool configdead;
|
||||
|
||||
void handleConfig(int sym, int uni);
|
||||
|
||||
void showShmupConfig() {
|
||||
#ifndef NOSDL
|
||||
|
||||
@ -362,6 +358,8 @@ void showShmupConfig() {
|
||||
|
||||
dialog::display();
|
||||
}
|
||||
|
||||
keyhandler = handleConfig;
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -380,7 +378,7 @@ void handleConfig(int sym, int uni) {
|
||||
else if(uni == '7') vid.scfg.subconfig = 8;
|
||||
else if(uni == 'j') vid.scfg.subconfig = SCJOY;
|
||||
else if(uni == 'a') multi::alwaysuse = !multi::alwaysuse;
|
||||
else if(uni == 'b') cmode = emJoyConfig;
|
||||
else if(uni == 'b') pushScreen(showJoyConfig);
|
||||
else if(uni == 'r')
|
||||
for(int i=0; i<MAXPLAYER; i++)
|
||||
kills[i] = deaths[i] = treasures[i] = 0;
|
||||
@ -396,20 +394,7 @@ void handleConfig(int sym, int uni) {
|
||||
if(vid.scfg.players <= 0) vid.scfg.players += MAXPLAYER;
|
||||
}
|
||||
else if(sym == SDLK_F1 || uni == '?' || uni == 'h') {
|
||||
lastmode = cmode;
|
||||
cmode = emHelp;
|
||||
|
||||
/* help =
|
||||
"In the shmup (shoot'em up) mode, you can play a hyperbolic shoot'em up "
|
||||
"game. The game is based on the usual turn-based grid-based HyperRogue, "
|
||||
"but there are some changes. You fight by throwing knives, and you "
|
||||
"have three extra lives. There are no friendly monsters, so Orbs of "
|
||||
"Life and Friendship give you extra lives instead. Some other rules have been "
|
||||
"adapted too.\n\n"
|
||||
"It is possible for two players to play the shmup mode cooperatively "
|
||||
"(locally). When playing together, lives, orbs, and treasures are shared, "
|
||||
"knives recharge slower, orbs drain faster, and player characters are not "
|
||||
"allowed to separate."; */
|
||||
gotoHelp("");
|
||||
|
||||
help =
|
||||
XLAT(
|
||||
@ -438,8 +423,8 @@ help += XLATN(iinf[itOrbSafety].name); help += "\n\n";
|
||||
help += XLAT("This menu can be also used to configure keys.\n\n");
|
||||
|
||||
}
|
||||
else if(uni || sym == SDLK_F10) {
|
||||
cmode = emNormal;
|
||||
else if(doexiton(sym, uni)) {
|
||||
popScreen();
|
||||
if(shmup::on != shmupcfg) { restartGame('s'); resetScores(); }
|
||||
else if(vid.scfg.players != players) { restartGame(); resetScores(); }
|
||||
}
|
||||
@ -3335,8 +3320,23 @@ void virtualRebase(shmup::monster *m, bool tohex) {
|
||||
virtualRebase(m->base, m->at, tohex);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void addShmupHelp(string& out) {
|
||||
if(shmup::mousetarget && intval(mouseh, tC0(shmup::mousetarget->pat)) < .1) {
|
||||
out += ", ";
|
||||
#ifdef ROGUEVIZ
|
||||
#include "rogueviz.cpp"
|
||||
if(shmup::mousetarget->type == moRogueviz) {
|
||||
help = XLAT(minf[shmup::mousetarget->type].help);
|
||||
out += rogueviz::describe(shmup::mousetarget);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
out += XLAT1(minf[shmup::mousetarget->type].name);
|
||||
help = generateHelpForMonster(shmup::mousetarget->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto hooks = addHook(clearmemory, 0, shmup::clearMemory);
|
||||
|
||||
}
|
||||
|
@ -65,13 +65,13 @@ int musfadeval = 2000;
|
||||
|
||||
eLand cid = laNone;
|
||||
|
||||
hookset<bool(eLand)> *hooks_music;
|
||||
|
||||
void handlemusic() {
|
||||
DEBB(DF_GRAPH, (debugfile,"handle music\n"));
|
||||
if(audio && musicvolume) {
|
||||
eLand id = getCurrentLandForMusic();
|
||||
#ifdef EXTRA_MUSIC
|
||||
if(extra::changemusic(id)) return;
|
||||
#endif
|
||||
if(callhandlers(false, hooks_music, id)) return;
|
||||
if(outoffocus) id = eLand(0);
|
||||
if(musfname[id] == "LAST") id = cid;
|
||||
if(!loaded[id]) {
|
||||
|
59
system.cpp
59
system.cpp
@ -925,6 +925,7 @@ namespace gamestack {
|
||||
};
|
||||
|
||||
void restartGame(char switchWhat, bool push) {
|
||||
popScreenAll();
|
||||
DEBB(DF_INIT, (debugfile,"restartGame\n"));
|
||||
|
||||
if(push)
|
||||
@ -1061,41 +1062,6 @@ void restartGame(char switchWhat, bool push) {
|
||||
resetmusic();
|
||||
}
|
||||
|
||||
void clearGameMemory() {
|
||||
#ifdef HASLINEVIEW
|
||||
conformal::renderAutoband();
|
||||
conformal::on = false;
|
||||
#endif
|
||||
DEBB(DF_INIT, (debugfile,"clearGameMemory\n"));
|
||||
pathq.clear();
|
||||
dcal.clear();
|
||||
yendor::yii = NOYENDOR; yendor::yi.clear();
|
||||
clearshadow();
|
||||
offscreen.clear();
|
||||
princess::clear();
|
||||
buggycells.clear();
|
||||
mirrors.clear();
|
||||
clearing::bpdata.clear();
|
||||
tortoise::emap.clear();
|
||||
tortoise::babymap.clear();
|
||||
seenSevenMines = false;
|
||||
#ifdef HASLINEVIEW
|
||||
conformal::killhistory.clear();
|
||||
conformal::findhistory.clear();
|
||||
conformal::movehistory.clear();
|
||||
conformal::includeHistory = false;
|
||||
#endif
|
||||
recallCell = NULL;
|
||||
prairie::lasttreasure = NULL;
|
||||
prairie::enter = NULL;
|
||||
prairie::tchoices.clear();
|
||||
prairie::beaststogen.clear();
|
||||
butterflies.clear();
|
||||
#ifdef ROGUEVIZ
|
||||
rogueviz::close();
|
||||
#endif
|
||||
}
|
||||
|
||||
static int orbid = 0;
|
||||
|
||||
eItem nextOrb() {
|
||||
@ -1222,7 +1188,6 @@ bool applyCheat(char u, cell *c = NULL) {
|
||||
items[itOrbShield] += 1;
|
||||
cheater++; addMessage(XLAT("Orb power gained!"));
|
||||
canmove = true;
|
||||
if(cmode == emQuit) cmode = emNormal;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1235,12 +1200,12 @@ bool applyCheat(char u, cell *c = NULL) {
|
||||
#ifndef NOEDIT
|
||||
if(u == 'A') {
|
||||
lastexplore = turncount;
|
||||
cmode = emMapEditor;
|
||||
pushScreen(mapeditor::showMapEditor);
|
||||
return true;
|
||||
}
|
||||
if(u == 'A'-64) {
|
||||
mapeditor::drawcell = mouseover ? mouseover : cwt.c;
|
||||
cmode = emDraw;
|
||||
pushScreen(mapeditor::showDrawEditor);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
@ -1366,7 +1331,7 @@ bool applyCheat(char u, cell *c = NULL) {
|
||||
return true;
|
||||
}
|
||||
if(u == 'W'-64) {
|
||||
cmode = emLinepattern;
|
||||
pushScreen(linepatterns::showMenu);
|
||||
return true;
|
||||
}
|
||||
if(u == 'G'-64) {
|
||||
@ -1423,3 +1388,19 @@ bool applyCheat(char u, cell *c = NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
purehookset clearmemory;
|
||||
|
||||
void clearMemory() {
|
||||
callhooks(clearmemory);
|
||||
}
|
||||
|
||||
auto cgm = addHook(clearmemory, 40, [] () {
|
||||
pathq.clear();
|
||||
dcal.clear();
|
||||
clearshadow();
|
||||
seenSevenMines = false;
|
||||
recallCell = NULL;
|
||||
butterflies.clear();
|
||||
buggycells.clear();
|
||||
});
|
||||
|
||||
|
91
tour.cpp
91
tour.cpp
@ -72,21 +72,20 @@ void presentation(presmode mode) {
|
||||
}
|
||||
|
||||
void slidehelp() {
|
||||
if(texts && slides[currentslide].help[0]) {
|
||||
help =
|
||||
helptitle(XLAT(slides[currentslide].name), 0xFF8000) +
|
||||
XLAT(slides[currentslide].help);
|
||||
if(cmode != emHelp)
|
||||
lastmode = cmode;
|
||||
cmode = emHelp;
|
||||
}
|
||||
if(texts && slides[currentslide].help[0])
|
||||
gotoHelp(
|
||||
help =
|
||||
helptitle(XLAT(slides[currentslide].name), 0xFF8000) +
|
||||
XLAT(slides[currentslide].help)
|
||||
);
|
||||
}
|
||||
|
||||
bool handleKeyTour(int sym, int uni) {
|
||||
bool normode = (cmode == emHelp || cmode == emNormal || cmode == emQuit);
|
||||
if(!normode) return false;
|
||||
if(!tour::on) return false;
|
||||
if(!cmode2) return false;
|
||||
int flags = slides[currentslide].flags;
|
||||
if((sym == SDLK_RETURN || sym == SDLK_KP_ENTER) && (cmode != emHelp || (flags & QUICKSKIP))) {
|
||||
if((sym == SDLK_RETURN || sym == SDLK_KP_ENTER) && (cmode2 != smHelp || (flags & QUICKSKIP))) {
|
||||
if(cmode2) popScreen();
|
||||
if(geometry || purehepta) {
|
||||
restartGame(0, false);
|
||||
if(!(flags & QUICKGEO)) return true;
|
||||
@ -106,7 +105,7 @@ bool handleKeyTour(int sym, int uni) {
|
||||
if(currentslide == 0) { slidehelp(); return true; }
|
||||
presentation(pmStop);
|
||||
currentslide--;
|
||||
if(cmode == emHelp) slidehelp();
|
||||
if(cmode2 == smHelp) popScreen(), slidehelp();
|
||||
presentation(pmStart);
|
||||
return true;
|
||||
}
|
||||
@ -164,7 +163,7 @@ bool handleKeyTour(int sym, int uni) {
|
||||
return true;
|
||||
}
|
||||
if(sym == '4') {
|
||||
cmode = emNormal;
|
||||
popScreenAll();
|
||||
if(items[itOrbTeleport]) goto give_aether;
|
||||
items[itOrbTeleport] = 1;
|
||||
checkmove();
|
||||
@ -214,15 +213,15 @@ bool handleKeyTour(int sym, int uni) {
|
||||
return true;
|
||||
}
|
||||
if(sym == '9') {
|
||||
cmode = emSlideshows;
|
||||
pushScreen(ss::showMenu);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void checkGoodLand(eLand l) {
|
||||
if(!showland(l) && texts) {
|
||||
help = XLAT(
|
||||
if(!showland(l) && texts)
|
||||
gotoHelp(XLAT(
|
||||
"This tutorial is different than most other game tutorials -- "
|
||||
"you are not forced to do anything, and you can go wherever you want.\n\n"
|
||||
"However, %the1 is not what we are talking about now. "
|
||||
@ -230,9 +229,7 @@ void checkGoodLand(eLand l) {
|
||||
"get lost there.\n\n"
|
||||
"Remember that you can get to the next slide by pressing Enter.",
|
||||
l
|
||||
);
|
||||
cmode = emHelp;
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
namespace ss {
|
||||
@ -260,42 +257,38 @@ namespace ss {
|
||||
if(size(slideshows) > 1) dialog::addItem(XLAT("change slideshow"), '1');
|
||||
dialog::addItem(XLAT("exit menu"), '0');
|
||||
dialog::display();
|
||||
}
|
||||
|
||||
void handleKey(int sym, int uni) {
|
||||
if(uni >= 'a' && uni < 'a' + sssize) {
|
||||
if(geometry || purehepta) {
|
||||
restartGame(0, false);
|
||||
presentation(pmGeometryReset);
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
if(uni >= 'a' && uni < 'a' + sssize) {
|
||||
if(geometry || purehepta) {
|
||||
restartGame(0, false);
|
||||
presentation(pmGeometryReset);
|
||||
}
|
||||
if(slides != wts) {
|
||||
while(tour::on) restartGame('T', false);
|
||||
slides = wts;
|
||||
tour::start();
|
||||
}
|
||||
presentation(pmStop);
|
||||
currentslide = uni - 'a';
|
||||
popScreenAll();
|
||||
presentation(pmStart);
|
||||
slidehelp();
|
||||
}
|
||||
if(slides != wts) {
|
||||
while(tour::on) restartGame('T', false);
|
||||
slides = wts;
|
||||
tour::start();
|
||||
else if(uni == '1') {
|
||||
list(wts);
|
||||
for(int i=0; i<size(slideshows)-1; i++) if(slideshows[i] == wts) {
|
||||
wts = slideshows[i+1]; return;
|
||||
}
|
||||
wts = slideshows[0];
|
||||
}
|
||||
presentation(pmStop);
|
||||
currentslide = uni - 'a';
|
||||
cmode = emNormal;
|
||||
presentation(pmStart);
|
||||
slidehelp();
|
||||
}
|
||||
else if(uni == '1') {
|
||||
list(wts);
|
||||
for(int i=0; i<size(slideshows)-1; i++) if(slideshows[i] == wts) {
|
||||
wts = slideshows[i+1]; return;
|
||||
}
|
||||
wts = slideshows[0];
|
||||
}
|
||||
else if(doexiton(sym, uni)) { wts = NULL; cmode = emNormal; }
|
||||
else if(doexiton(sym, uni)) { wts = NULL; popScreen(); }
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void start() {
|
||||
ss::list(default_slides);
|
||||
#ifdef ROGUEVIZ
|
||||
ss::list(rogueviz::rvtour::rvslides);
|
||||
#endif
|
||||
currentslide = 0;
|
||||
vid.scale = 1;
|
||||
vid.alpha = 1;
|
||||
@ -760,4 +753,8 @@ slide default_slides[] = {
|
||||
|
||||
slide *slides = default_slides;
|
||||
|
||||
auto a1 = addHook(hooks_frame, 100, [] () { if(tour::on) tour::presentation(tour::pmFrame); });
|
||||
auto a2 = addHook(hooks_handleKey, 100, handleKeyTour);
|
||||
auto a3 = addHook(hooks_nextland, 100, [] (eLand l) { return tour::on ? getNext(l) : laNone; });
|
||||
|
||||
}
|
||||
|
1
util.cpp
1
util.cpp
@ -23,6 +23,7 @@ typedef long double ld;
|
||||
#define ASINH asinhl
|
||||
#endif
|
||||
|
||||
long double sqr(long double x) { return x*x; }
|
||||
template<class T> int size(const T& x) {return int(x.size()); }
|
||||
string its(int i) { char buf[64]; sprintf(buf, "%d", i); return buf; }
|
||||
string fts(float x) { char buf[64]; sprintf(buf, "%4.2f", x); return buf; }
|
||||
|
207
yendor.cpp
207
yendor.cpp
@ -412,6 +412,31 @@ namespace yendor {
|
||||
};
|
||||
vector<scoredata> scoreboard;
|
||||
|
||||
const char *chelp =
|
||||
"There are many possible solutions to the Yendor Quest. In the Yendor "
|
||||
"Challenge, you will try many of them!\n\n"
|
||||
"Each challenge takes part in a specific land, and you have to use what "
|
||||
"you have available.\n\n"
|
||||
|
||||
"You need to obtain an Orb of Yendor in the normal game to activate "
|
||||
"this challenge, and (ever) collect 10 treasures in one or two lands "
|
||||
"to activate a specific level.\n\n"
|
||||
|
||||
"After you complete each challenge, you can try it again, on a harder "
|
||||
"difficulty level.\n\n"
|
||||
|
||||
"All the solutions showcased in the Yendor Challenge work in the normal "
|
||||
"play too. However, passages to other lands, and (sometimes) some land features "
|
||||
"are disabled in the Yendor "
|
||||
"Challenge, so that you have to use the expected method. Also, "
|
||||
"the generation rules are changed slightly for the Palace "
|
||||
"and Minefield while you are looking for the Orb of Yendor, "
|
||||
"to make the challenge more balanced "
|
||||
"(but these changes are also active during the normal Yendor Quest).\n\n"
|
||||
|
||||
"You get 1000 points for each challenge won, and 1 extra point for "
|
||||
"each extra difficulty level.";
|
||||
|
||||
void showMenu() {
|
||||
int s = vid.fsize;
|
||||
vid.fsize = vid.fsize * 4/5;
|
||||
@ -475,55 +500,26 @@ namespace yendor {
|
||||
|
||||
yendor::uploadScore();
|
||||
vid.fsize = s;
|
||||
}
|
||||
|
||||
const char *chelp =
|
||||
"There are many possible solutions to the Yendor Quest. In the Yendor "
|
||||
"Challenge, you will try many of them!\n\n"
|
||||
"Each challenge takes part in a specific land, and you have to use what "
|
||||
"you have available.\n\n"
|
||||
|
||||
"You need to obtain an Orb of Yendor in the normal game to activate "
|
||||
"this challenge, and (ever) collect 10 treasures in one or two lands "
|
||||
"to activate a specific level.\n\n"
|
||||
|
||||
"After you complete each challenge, you can try it again, on a harder "
|
||||
"difficulty level.\n\n"
|
||||
|
||||
"All the solutions showcased in the Yendor Challenge work in the normal "
|
||||
"play too. However, passages to other lands, and (sometimes) some land features "
|
||||
"are disabled in the Yendor "
|
||||
"Challenge, so that you have to use the expected method. Also, "
|
||||
"the generation rules are changed slightly for the Palace "
|
||||
"and Minefield while you are looking for the Orb of Yendor, "
|
||||
"to make the challenge more balanced "
|
||||
"(but these changes are also active during the normal Yendor Quest).\n\n"
|
||||
|
||||
"You get 1000 points for each challenge won, and 1 extra point for "
|
||||
"each extra difficulty level.";
|
||||
|
||||
void handleKey(int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
if(uni >= 'a' && uni < 'a'+YENDORLEVELS-1) {
|
||||
challenge = uni-'a' + 1;
|
||||
if(levelUnlocked(challenge) || autocheat) {
|
||||
restartGame(yendor::on ? 0 : 'y');
|
||||
cmode = emNormal;
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
if(uni >= 'a' && uni < 'a'+YENDORLEVELS-1) {
|
||||
challenge = uni-'a' + 1;
|
||||
if(levelUnlocked(challenge) || autocheat) {
|
||||
restartGame(yendor::on ? 0 : 'y');
|
||||
popScreen();
|
||||
}
|
||||
else
|
||||
addMessage("Collect 10 treasures in various lands to unlock the challenges there");
|
||||
}
|
||||
else
|
||||
addMessage("Collect 10 treasures in various lands to unlock the challenges there");
|
||||
}
|
||||
else if(uni == '0') {
|
||||
if(yendor::on) restartGame('y');
|
||||
cmode = emNormal;
|
||||
}
|
||||
else if(uni == '1') easy = !easy;
|
||||
else if(uni == '2' || sym == SDLK_F1) {
|
||||
lastmode = cmode;
|
||||
cmode = emHelp;
|
||||
help = chelp;
|
||||
}
|
||||
else if(doexiton(sym, uni)) cmode = emNormal;
|
||||
else if(uni == '0') {
|
||||
if(yendor::on) restartGame('y');
|
||||
popScreen();
|
||||
}
|
||||
else if(uni == '1') easy = !easy;
|
||||
else if(uni == '2' || sym == SDLK_F1) gotoHelp(chelp);
|
||||
else if(doexiton(sym, uni)) popScreen();
|
||||
};
|
||||
}
|
||||
|
||||
void collected(cell* c2) {
|
||||
@ -565,6 +561,10 @@ namespace yendor {
|
||||
achievement_collection(itOrbYendor, pg, gold());
|
||||
achievement_victory(false);
|
||||
}
|
||||
|
||||
auto hooks = addHook(clearmemory, 0, [] () {
|
||||
yendor::yii = NOYENDOR; yendor::yi.clear();
|
||||
});
|
||||
};
|
||||
|
||||
#define MAXTAC 20
|
||||
@ -738,23 +738,20 @@ namespace tactic {
|
||||
}
|
||||
displayScore(scorehere, xr * 50);
|
||||
}
|
||||
}
|
||||
|
||||
void handleKey(int sym, int uni) {
|
||||
if(uni >= 1000 && uni < 1000 + LAND_TAC) {
|
||||
firstland = euclidland = getLandById(uni - 1000);
|
||||
restartGame(tactic::on ? 0 : 't');
|
||||
cmode = emNormal;
|
||||
}
|
||||
else if(uni == '0') {
|
||||
cmode = emNormal;
|
||||
firstland = laIce;
|
||||
if(tactic::on) restartGame('t');
|
||||
}
|
||||
else if(sym == SDLK_F1) {
|
||||
lastmode = cmode;
|
||||
cmode = emHelp;
|
||||
help =
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
if(uni >= 1000 && uni < 1000 + LAND_TAC) {
|
||||
firstland = euclidland = getLandById(uni - 1000);
|
||||
restartGame(tactic::on ? 0 : 't');
|
||||
popScreen();
|
||||
}
|
||||
else if(uni == '0') {
|
||||
popScreen();
|
||||
firstland = laIce;
|
||||
if(tactic::on) restartGame('t');
|
||||
}
|
||||
|
||||
else if(sym == SDLK_F1) gotoHelp(
|
||||
"In the pure tactics mode, you concentrate on a specific land. "
|
||||
"Your goal to obtain as high score as possible, without using "
|
||||
"features of the other lands. You can then compare your score "
|
||||
@ -775,12 +772,13 @@ namespace tactic {
|
||||
"The rate of treasure spawn is static in this mode. It is not "
|
||||
"increased by killing monsters.\n\n"
|
||||
|
||||
"Good luck, and have fun!";
|
||||
|
||||
}
|
||||
else if(dialog::handlePageButtons(uni)) ;
|
||||
else if(doexiton(sym, uni)) cmode = emNormal;
|
||||
"Good luck, and have fun!"
|
||||
);
|
||||
else if(dialog::handlePageButtons(uni)) ;
|
||||
else if(doexiton(sym, uni)) popScreen();
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
int modecodetable[42][6] = {
|
||||
@ -931,6 +929,7 @@ namespace peace {
|
||||
int qty;
|
||||
|
||||
eLand getNext(eLand last) {
|
||||
if(!peace::on) return laNone;
|
||||
if(isElemental(last) && hrand(100) < 90)
|
||||
return laNone;
|
||||
else if(createOnSea(last))
|
||||
@ -949,23 +948,6 @@ namespace peace {
|
||||
return false;
|
||||
}
|
||||
|
||||
void showMenu() {
|
||||
dialog::init(XLAT(otherpuzzles ? "hyperbolic puzzles" : "memory game"), 0x40A040, 150, 100);
|
||||
|
||||
levellist = otherpuzzles ? explorelevels : simonlevels;
|
||||
|
||||
for(qty = 0; levellist[qty]; qty++)
|
||||
dialog::addItem(XLAT1(linf[levellist[qty]].name), 'a'+qty);
|
||||
|
||||
dialog::addBreak(100);
|
||||
dialog::addItem(XLAT(otherpuzzles ? "memory game" : "other hyperbolic puzzles"), '1');
|
||||
dialog::addBoolItem(XLAT("display hints"), hint, '2');
|
||||
dialog::addItem(XLAT("Help"), SDLK_F1);
|
||||
dialog::addItem(XLAT("Return to the normal game"), '0');
|
||||
|
||||
dialog::display();
|
||||
}
|
||||
|
||||
const char *chelp = NODESCYET;
|
||||
|
||||
namespace simon {
|
||||
@ -1043,26 +1025,41 @@ namespace peace {
|
||||
}
|
||||
}
|
||||
|
||||
void handleKey(int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
void showMenu() {
|
||||
dialog::init(XLAT(otherpuzzles ? "hyperbolic puzzles" : "memory game"), 0x40A040, 150, 100);
|
||||
|
||||
if(uni == '1') otherpuzzles = !otherpuzzles;
|
||||
else if(uni >= 'a' && uni < 'a' + qty) {
|
||||
whichland = levellist[uni - 'a'];
|
||||
restartGame(peace::on ? 0 : 'P');
|
||||
cmode = emNormal;
|
||||
}
|
||||
else if(uni == '2') { hint = !hint; cmode = emNormal; }
|
||||
else if(uni == '0') {
|
||||
firstland = laIce;
|
||||
if(peace::on) restartGame('P');
|
||||
cmode = emNormal;
|
||||
}
|
||||
else if(uni == 'h' || sym == SDLK_F1) {
|
||||
lastmode = cmode;
|
||||
cmode = emHelp;
|
||||
help = chelp;
|
||||
}
|
||||
else if(doexiton(sym, uni)) cmode = emNormal;
|
||||
levellist = otherpuzzles ? explorelevels : simonlevels;
|
||||
|
||||
for(qty = 0; levellist[qty]; qty++)
|
||||
dialog::addItem(XLAT1(linf[levellist[qty]].name), 'a'+qty);
|
||||
|
||||
dialog::addBreak(100);
|
||||
dialog::addItem(XLAT(otherpuzzles ? "memory game" : "other hyperbolic puzzles"), '1');
|
||||
dialog::addBoolItem(XLAT("display hints"), hint, '2');
|
||||
dialog::addItem(XLAT("Help"), SDLK_F1);
|
||||
dialog::addItem(XLAT("Return to the normal game"), '0');
|
||||
|
||||
dialog::display();
|
||||
|
||||
keyhandler = [] (int sym, int uni) {
|
||||
dialog::handleNavigation(sym, uni);
|
||||
|
||||
if(uni == '1') otherpuzzles = !otherpuzzles;
|
||||
else if(uni >= 'a' && uni < 'a' + qty) {
|
||||
whichland = levellist[uni - 'a'];
|
||||
restartGame(peace::on ? 0 : 'P');
|
||||
popScreen();
|
||||
}
|
||||
else if(uni == '2') { hint = !hint; popScreen(); }
|
||||
else if(uni == '0') {
|
||||
firstland = laIce;
|
||||
if(peace::on) restartGame('P');
|
||||
popScreen();
|
||||
}
|
||||
else if(uni == 'h' || sym == SDLK_F1) gotoHelp(chelp);
|
||||
else if(doexiton(sym, uni)) popScreen();
|
||||
};
|
||||
}
|
||||
|
||||
auto aNext = addHook(hooks_nextland, 100, getNext);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user