From f723a8d4199e45967adb9833c48ac34607495231 Mon Sep 17 00:00:00 2001 From: Zeno Rogue Date: Fri, 9 Aug 2019 23:48:28 +0200 Subject: [PATCH] further cleanup, separated multi.cpp from shmup.cpp --- compileunits.h | 1 + config.cpp | 2 +- hyper.h | 43 +-- multi.cpp | 963 +++++++++++++++++++++++++++++++++++++++++++++++++ orbs.cpp | 2 +- savemem.cpp | 13 +- shmup.cpp | 942 ----------------------------------------------- 7 files changed, 974 insertions(+), 992 deletions(-) create mode 100644 multi.cpp diff --git a/compileunits.h b/compileunits.h index bbb34cca..63e7b889 100644 --- a/compileunits.h +++ b/compileunits.h @@ -91,6 +91,7 @@ namespace hr { namespace inv { bool on, activating; } } #include "menus.cpp" #include "geom-exp.cpp" #include "quit.cpp" +#include "multi.cpp" #include "shmup.cpp" #if CAP_RACING diff --git a/config.cpp b/config.cpp index 3cdfcd3e..9270618b 100644 --- a/config.cpp +++ b/config.cpp @@ -534,7 +534,7 @@ EX void reset_graph_settings() { vid.wallmode = DEFAULT_WALLMODE; } -EX void resetModes(char leave) { +EX void resetModes(char leave IS('c')) { while(game_active || gamestack::pushed()) { if(game_active) stop_game(); if(gamestack::pushed()) gamestack::pop(); diff --git a/hyper.h b/hyper.h index 78a1f7ba..2cd7caef 100644 --- a/hyper.h +++ b/hyper.h @@ -201,25 +201,6 @@ struct charstyle { bool lefthanded; }; -static const int MAXPLAYER = 7; -static const int MAXJOY = 8; -static const int MAXBUTTON = 64; -static const int MAXAXE = 16; -static const int MAXHAT = 4; - -namespace multi { - - struct config { - char keyaction[512]; - char joyaction[MAXJOY][MAXBUTTON]; - char axeaction[MAXJOY][MAXAXE]; - char hataction[MAXJOY][MAXHAT][4]; - int deadzoneval[MAXJOY][MAXAXE]; - }; - - extern config scfg; - } - enum eStereo { sOFF, sAnaglyph, sLR, sODS }; struct videopar { @@ -1300,6 +1281,8 @@ namespace tortoise { int getRandomBits(); } +static const int MAXPLAYER = 7; + namespace sword { struct sworddir { @@ -2207,34 +2190,12 @@ template void hrandom_shuffle(T* x, int n) { for(int k=1; k void eliminate_if(vector& data, U pred) { for(int i=0; i revive_queue; // queue for revival + + EX cell *origpos[MAXPLAYER], *origtarget[MAXPLAYER]; + + EX bool flipped[MAXPLAYER]; + + // treasure collection, kill, and death statistics + EX int treasures[MAXPLAYER], kills[MAXPLAYER], deaths[MAXPLAYER]; + + EX bool alwaysuse = false; + + EX void recall() { + for(int i=0; itype; + cell *c2 = cwt.at->move(idir); + makeEmpty(c2); + if(!passable(c2, NULL, P_ISPLAYER)) c2 = cwt.at; + multi::player[i].at = c2; + multi::player[i].spin = 0; + + multi::flipped[i] = true; + multi::whereto[i].d = MD_UNDECIDED; + } + } + + transmatrix whereis[MAXPLAYER]; + transmatrix crosscenter[MAXPLAYER]; + double ccdist[MAXPLAYER]; + cell *ccat[MAXPLAYER]; + + bool combo[MAXPLAYER]; + + EX int cpid; // player id -- an extra parameter for player-related functions + EX int cpid_edit; // cpid currently being edited + + EX movedir whereto[MAXPLAYER]; // player's target cell + + double mdx[MAXPLAYER], mdy[MAXPLAYER]; // movement vector for the next move + + static const int CMDS = 15; + static const int CMDS_PAN = 11; + + vector playercmds_shmup = { + "forward", "backward", "turn left", "turn right", + "move up", "move right", "move down", "move left", + "throw a knife", "face the pointer", "throw at the pointer", + "drop Dead Orb", "center the map on me", "Orb power (target: mouse)", + "Orb power (target: facing)" + }; + + vector playercmds_shmup3 = { + "rotate up", "rotate down", "rotate left", "rotate right", + "move forward", "strafe right", "move backward", "strafe left", + "throw a knife", "face the pointer", "throw at the pointer", + "drop Dead Orb", "center the map on me", "Orb power (target: mouse)", + "Orb power (target: facing)" + }; + + vector playercmds_turn = { + "move up-right", "move up-left", "move down-right", "move down-left", + "move up", "move right", "move down", "move left", + "stay in place (left + right)", "cancel move", "leave the game", + "drop Dead Orb (up + down)", "center the map on me", "", + "" + }; + + vector pancmds = { + "pan up", "pan right", "pan down", "pan left", + "rotate left", "rotate right", "home", + "world overview", "review your quest", "inventory", "main menu" + }; + + vector pancmds3 = { + "look up", "look right", "look down", "look left", + "rotate left", "rotate right", "home", + "world overview", "review your quest", "inventory", "main menu", + "scroll forward", "scroll backward" + }; + +#define SHMUPAXES_BASE 4 +#define SHMUPAXES ((SHMUPAXES_BASE) + 4 * (MAXPLAYER)) +#define SHMUPAXES_CUR ((SHMUPAXES_BASE) + 4 * playercfg) + +const char* axemodes[SHMUPAXES] = { + "do nothing", + "rotate view", + "panning X", + "panning Y", + "player 1 X", + "player 1 Y", + "player 1 go", + "player 1 spin", + "player 2 X", + "player 2 Y", + "player 2 go", + "player 2 spin", + "player 3 X", + "player 3 Y", + "player 3 go", + "player 3 spin", + "player 4 X", + "player 4 Y", + "player 4 go", + "player 4 spin", + "player 5 X", + "player 5 Y", + "player 5 go", + "player 5 spin", + "player 6 X", + "player 6 Y", + "player 6 go", + "player 6 spin", + "player 7 X", + "player 7 Y", + "player 7 go", + "player 7 spin" + }; + +const char* axemodes3[4] = { + "do nothing", + "camera forward", + "camera rotate X", + "camera rotate Y" + }; + +int centerplayer = -1; + +char* axeconfigs[24]; int numaxeconfigs; +int* dzconfigs[24]; + +string listkeys(int id) { +#if CAP_SDL + string lk = ""; + for(int i=0; i<512; i++) + if(scfg.keyaction[i] == id) + lk = lk + " " + SDL_GetKeyName(SDLKey(i)); +#if CAP_SDLJOY + for(int i=0; i& shmupcmdtable; + int setwhat; + + key_configurer(int sc, vector& sct) : sc(sc), shmupcmdtable(sct), setwhat(0) {} + + void operator() () { + + dialog::init( + XLAT(sc == 1 ? "configure player 1" : + sc == 2 ? "configure player 2" : + sc == 3 ? "configure panning" : + sc == 4 ? "configure player 3" : + sc == 5 ? "configure player 4" : + sc == 6 ? "configure player 5" : + sc == 7 ? "configure player 6" : + sc == 8 ? "configure player 7" : "" + )); + + getcstat = ' '; + + for(int i=0; i1 && i == (setwhat&15) ? '?' : 0) : 'a'+i); + else dialog::addBreak(100); + + if(setwhat == 1) + dialog::addItem(XLAT("press a key to unassign"), 0); + else if(setwhat) + dialog::addItem(XLAT("press a key for '%1'", XLAT(shmupcmdtable[setwhat&15])), 0); + else + dialog::addItem(XLAT("unassign a key"), 'z'); + + dialog::display(); + + keyhandler = [this] (int sym, int uni) { + if(!setwhat) dialog::handleNavigation(sym, uni); + if(sym) { + if(setwhat) { + scfg.keyaction[sym] = setwhat; + setwhat = 0; + } + else if(uni >= 'a' && uni < 'a' + isize(shmupcmdtable) && shmupcmdtable[uni-'a'][0]) + setwhat = 16*sc+uni - 'a'; + else if(uni == 'z') + setwhat = 1; + else if(doexiton(sym, uni)) + popScreen(); + } + }; + +#if CAP_SDLJOY + joyhandler = [this] (SDL_Event& ev) { + if(ev.type == SDL_JOYBUTTONDOWN && setwhat) { + int joyid = ev.jbutton.which; + int button = ev.jbutton.button; + if(joyid < 8 && button < 32) + scfg.joyaction[joyid][button] = setwhat; + setwhat = 0; + return true; + } + + else if(ev.type == SDL_JOYHATMOTION && 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; + printf("%d %d %d\n", joyid, hat, dir); + if(joyid < 8 && hat < 4 && dir < 4) { + scfg.hataction[joyid][hat][dir] = setwhat; + setwhat = 0; + return true; + } + } + return false; + }; +#endif + } + }; + +#if CAP_SDLJOY +struct joy_configurer { + + bool shmupcfg, racecfg; + int playercfg; + joy_configurer(int playercfg) : playercfg(playercfg) {} + + void operator() () { + dialog::init(); + getcstat = ' '; + numaxeconfigs = 0; + for(int j=0; j 10000) buf += "+", y -= 10000; + while(y < -10000) buf += "-", y += 10000; + if(y>0) buf += "+"; + if(y<0) buf += "-"; + } + axeconfigs[numaxeconfigs] = &(scfg.axeaction[j][ax]); + dzconfigs[numaxeconfigs] = &(scfg.deadzoneval[j][ax]); + char aa = *axeconfigs[numaxeconfigs]; + string what = configdead ? its(scfg.deadzoneval[j][ax]) : + (DIM == 3 && (aa%SHMUPAXES < 4)) ? XLAT(axemodes3[aa%SHMUPAXES]) : + XLAT(axemodes[aa%SHMUPAXES]); + dialog::addSelItem(XLAT("Joystick %1, axis %2", cts('A'+j), its(ax)) + buf, + what, 'a'+numaxeconfigs); + numaxeconfigs++; + } + } + + dialog::addBoolItem(XLAT("Configure dead zones"), (configdead), 'z'); + dialog::display(); + + keyhandler = [this] (int sym, int uni) { + dialog::handleNavigation(sym, uni); + if(sym) { + char xuni = uni | 96; + if(xuni >= 'a' && xuni < 'a' + numaxeconfigs) { + if(configdead) + dialog::editNumber( (*dzconfigs[xuni - 'a']), 0, 65536, 100, 0, XLAT("Configure dead zones"), ""); + else { + int v = (*axeconfigs[xuni - 'a']); + v += (shiftmul>0?1:-1); + v += SHMUPAXES_CUR; + v %= SHMUPAXES_CUR; + (*axeconfigs[xuni - 'a']) = v; + } + } + else if(xuni == 'z') + configdead = !configdead; + else if(doexiton(sym, uni)) + popScreen(); + } + }; + } + }; +#endif + +struct shmup_configurer { + + void operator()() { + #if CAP_SDL + cmode = sm::SHMUPCONFIG; + gamescreen(3); + dialog::init(XLAT("keyboard & joysticks")); + + bool haveconfig = shmup::on || players > 1 || multi::alwaysuse; + + if(haveconfig) + dialog::addItem(XLAT("configure player 1"), '1'); + else + dialog::addBreak(100); + if(players > 1) + dialog::addItem(XLAT("configure player 2"), '2'); + else if(players == 1 && !shmup::on) + dialog::addSelItem(XLAT("input"), XLAT(multi::alwaysuse ? "config" : "default"), 'a'); + else + dialog::addBreak(100); + if(players > 2) + dialog::addItem(XLAT("configure player 3"), '3'); + #if CAP_SDLJOY + else if(!haveconfig) + dialog::addItem(XLAT("old style joystick configuration"), 'b'); + #endif + else dialog::addBreak(100); + if(players > 3) + dialog::addItem(XLAT("configure player 4"), '4'); + else if(!shmup::on && !multi::alwaysuse) { + dialog::addBoolItem(XLAT("smooth scrolling"), smooth_scrolling, 'c'); + } + else if(alwaysuse) + dialog::addInfo(XLAT("note: configured input is designed for")); + else dialog::addBreak(100); + + if(players > 4) + dialog::addItem(XLAT("configure player 5"), '5'); + else if(!shmup::on && !multi::alwaysuse) { + if(GDIM == 2) { + const char *axmodes[5] = {"OFF", "auto", "light", "heavy", "arrows"}; + dialog::addSelItem(XLAT("help for keyboard users"), XLAT(axmodes[vid.axes]), 'h'); + dialog::add_action([] {vid.axes += 60 + (shiftmul > 0 ? 1 : -1); vid.axes %= 5; } ); + } + else dialog::addBreak(100); + } + else if(alwaysuse) + dialog::addInfo(XLAT("multiplayer and shmup mode; some features")); + else dialog::addBreak(100); + + if(players > 5) + dialog::addItem(XLAT("configure player 6"), '6'); + else if(alwaysuse) + dialog::addInfo(XLAT("work worse if you use it.")); + else dialog::addBreak(100); + + if(players > 6) + dialog::addItem(XLAT("configure player 7"), '7'); + else dialog::addBreak(100); + + if(shmup::on || multi::alwaysuse || players > 1) + dialog::addItem(XLAT("configure panning and general keys"), 'p'); + else dialog::addBreak(100); + + #if CAP_SDLJOY + if(numsticks > 0) { + if(shmup::on || multi::alwaysuse || players > 1) + dialog::addItem(XLAT("configure joystick axes"), 'j'); + else dialog::addBreak(100); + } + #endif + + dialog::addBreak(50); + + dialog::addHelp(); + + dialog::addBack(); + dialog::display(); + + keyhandler = [this] (int sym, int uni) { return handleConfig(sym, uni); }; + #endif + } + + void handleConfig(int sym, int uni) { + auto& cmdlist = shmup::on ? (WDIM == 3 ? playercmds_shmup3 : playercmds_shmup) : playercmds_turn; + dialog::handleNavigation(sym, uni); + + if(0) ; + #if CAP_SDL + else if(uni == '1') pushScreen(key_configurer(1, cmdlist)); + else if(uni == '2') pushScreen(key_configurer(2, cmdlist)); + else if(uni == 'p') pushScreen(key_configurer(3, GDIM == 3 ? pancmds3 : pancmds)); + else if(uni == '3') pushScreen(key_configurer(4, cmdlist)); + else if(uni == '4') pushScreen(key_configurer(5, cmdlist)); + else if(uni == '5') pushScreen(key_configurer(6, cmdlist)); + else if(uni == '6') pushScreen(key_configurer(7, cmdlist)); + else if(uni == '7') pushScreen(key_configurer(8, cmdlist)); + #if CAP_SDLJOY + else if(uni == 'j') pushScreen(joy_configurer(players)); + #endif + else if(uni == 'a') multi::alwaysuse = !multi::alwaysuse; + #if CAP_SDLJOY + else if(uni == 'b') pushScreen(showJoyConfig); + #endif + else if(uni == 'c') smooth_scrolling = !smooth_scrolling; + #endif + else if(doexiton(sym, uni)) popScreen(); + } + }; + +EX void configure() { + pushScreen(shmup_configurer()); + } + +EX void showConfigureMultiplayer() { + gamescreen(1); + dialog::init("multiplayer"); + + for(int i=1; i <= MAXPLAYER; i++) { + string s = player_count_name(i); + if(i <= players) s += dsc(i-1); + dialog::addBoolItem(s, i == multi::players, '0' + i); + if(!dual::state) dialog::add_action([i] { + dialog::do_if_confirmed([i] { + stop_game(); + players = i; + start_game(); + }); + }); + } + + if(multi::players > 1) { + dialog::addItem(XLAT("reset per-player statistics"), 'r'); + dialog::add_action([] { + for(int i=0; i= 0 && id < NUMACT) + actionspressed[id]++; + } + +bool notremapped(int sym) { + int k = scfg.keyaction[sym]; + if(k == 0) return true; + k /= 16; + if(k > 3) k--; else if(k==3) k = 0; + return k > multi::players; + } + +EX void initConfig() { + + char* t = scfg.keyaction; + + t[(int)'w'] = 16 + 4; + t[(int)'d'] = 16 + 5; + t[(int)'s'] = 16 + 6; + t[(int)'a'] = 16 + 7; + +#if ISMOBILE==0 + t[SDLK_KP8] = 16 + 4; + t[SDLK_KP6] = 16 + 5; + t[SDLK_KP2] = 16 + 6; + t[SDLK_KP4] = 16 + 7; +#endif + + t[(int)'f'] = 16 + pcFire; + t[(int)'g'] = 16 + pcFace; + t[(int)'h'] = 16 + pcFaceFire; + t[(int)'r'] = 16 + pcDrop; + t[(int)'t'] = 16 + pcOrbPower; + t[(int)'y'] = 16 + pcCenter; + + t[(int)'i'] = 32 + 4; + t[(int)'l'] = 32 + 5; + t[(int)'k'] = 32 + 6; + t[(int)'j'] = 32 + 7; + t[(int)';'] = 32 + 8; + t[(int)'\''] = 32 + 9; + t[(int)'p'] = 32 + 10; + t[(int)'['] = 32 + pcCenter; + +#if ISMOBILE==0 + t[SDLK_UP] = 48 ; + t[SDLK_RIGHT] = 48 + 1; + t[SDLK_DOWN] = 48 + 2; + t[SDLK_LEFT] = 48 + 3; + t[SDLK_PAGEUP] = 48 + 4; + t[SDLK_PAGEDOWN] = 48 + 5; + t[SDLK_HOME] = 48 + 6; +#endif + + scfg.joyaction[0][0] = 16 + pcFire; + scfg.joyaction[0][1] = 16 + pcOrbPower; + scfg.joyaction[0][2] = 16 + pcDrop; + scfg.joyaction[0][3] = 16 + pcCenter; + scfg.joyaction[0][4] = 16 + pcFace; + scfg.joyaction[0][5] = 16 + pcFaceFire; + + scfg.joyaction[1][0] = 32 + pcFire; + scfg.joyaction[1][1] = 32 + pcOrbPower; + scfg.joyaction[1][2] = 32 + pcDrop; + scfg.joyaction[1][3] = 32 + pcCenter; + scfg.joyaction[1][4] = 32 + pcFace; + scfg.joyaction[1][5] = 32 + pcFaceFire; + + scfg.axeaction[0][0] = 4; + scfg.axeaction[0][1] = 5; + scfg.axeaction[0][3] = 2; + scfg.axeaction[0][4] = 3; + + scfg.axeaction[1][0] = 8; + scfg.axeaction[1][1] = 9; + + // ULRD + scfg.hataction[0][0][0] = 16 + 0; + scfg.hataction[0][0][1] = 16 + 3; + scfg.hataction[0][0][2] = 16 + 1; + scfg.hataction[0][0][3] = 16 + 2; + scfg.hataction[0][1][0] = 16 + 4; + scfg.hataction[0][1][1] = 16 + 7; + scfg.hataction[0][1][2] = 16 + 5; + scfg.hataction[0][1][3] = 16 + 6; + + scfg.hataction[1][0][0] = 32 + 0; + scfg.hataction[1][0][1] = 32 + 3; + scfg.hataction[1][0][2] = 32 + 1; + scfg.hataction[1][0][3] = 32 + 2; + scfg.hataction[1][1][0] = 32 + 4; + scfg.hataction[1][1][1] = 32 + 7; + scfg.hataction[1][1][2] = 32 + 5; + scfg.hataction[1][1][3] = 32 + 6; + + int charidtable[MAXPLAYER] = {0, 1, 4, 6, 2, 3, 0}; + + for(int i=0; i dz) value -= dz; else if(value < -dz) value += dz; + else value = 0; + axespressed[scfg.axeaction[j][b] % SHMUPAXES] += value; + } + } +#endif + + if(keystate[SDLK_LCTRL] || keystate[SDLK_RCTRL]) d /= 5; + + double panx = + actionspressed[49] - actionspressed[51] + axespressed[2] / 32000.0; + double pany = + actionspressed[50] - actionspressed[48] + axespressed[3] / 32000.0; + + double panspin = actionspressed[52] - actionspressed[53]; + + double panmove = actionspressed[59] - actionspressed[60]; + + if(DIM == 3) + panmove += axespressed[1] / 32000.0; + else + panspin += axespressed[1] / 32000.0; + + if(actionspressed[54]) { centerplayer = -1, playermoved = true; centerpc(100); } + + if(actionspressed[55] && !lactionpressed[55]) + get_o_key().second(); + + if(actionspressed[56] && !lactionpressed[56]) + showMissionScreen(); + +#if CAP_INV + if(actionspressed[57] && !lactionpressed[57] && inv::on) + pushScreen(inv::show); +#endif + + if(actionspressed[58] && !lactionpressed[58]) + pushScreen(showMainMenu); + + panx *= d; + pany *= d; + panspin *= d; + panmove *= d; + + #if CAP_MOUSEGRAB + if(lctrlclick) { + panx += mouseaim_x / 2; + pany += mouseaim_y / 2; + mouseaim_x = mouseaim_y = 0; + } + #endif + + if(panx || pany || panspin || (GDIM == 3 && panmove)) { + if(DIM == 2) { + View = xpush(-panx) * ypush(-pany) * spin(panspin) * View; + playermoved = false; + } + else { + View = cspin(0, 2, -panx) * cspin(1, 2, -pany) * spin(panspin) * cpush(2, panmove) * View; + if(panmove) playermoved = false; + } + } +#endif + } + + int tableid[7] = {1, 2, 4, 5, 6, 7, 8}; + + EX void leaveGame(int i) { + multi::player[i].at = NULL; + multi::deaths[i]++; + revive_queue.push_back(i); + checklastmove(); + } + + EX bool playerActive(int p) { + if(multi::players == 1 || shmup::on) return true; + return player[p].at; + } + + EX int activePlayers() { + int q = 0; + for(int i=0; i= 0) + cwti = cwti + dir + wstep; + return cwti.at; + } + + EX void checklastmove() { + for(int i=0; i 1) { + addMessage(XLAT("Left the game.")); + multi::leaveGame(i); + } + + if(actionspressed[b+pcDrop] || + (multi::actionspressed[b+pcMoveUp] && multi::actionspressed[b+pcMoveDown])) + multi::combo[i] = true, multi::whereto[i].d = MD_DROP; + + if(actionspressed[b+pcCenter]) { + centerplayer = cpid; centerpc(100); playermoved = true; + } + + if(multi::whereto[i].d == MD_UNDECIDED) alldecided = false; + + for(int ik=0; ik<16; ik++) if(actionspressed[b+ik]) anypressed = true; + + if(anypressed) alldecided = false, needinput = false; + else multi::mdx[i] = multi::mdy[i] = 0; + } + + cwtV = bcwtV; + cwt = bcwt; + + if(alldecided) { + flashMessages(); + // check for crashes + needinput = true; + + for(int i=0; i 8) { + addMessage("Players cannot get that far away!"); + return; + } */ + } + + if(multi::players == 1) { + if(movepcto(multi::whereto[0])) + multi::whereto[0].d = MD_UNDECIDED; + return; + } + + multi::cpid = 0; + if(multimove()) { + multi::aftermove = false; + monstersTurn(); + checklastmove(); + } + } + } + + void mousemovement(cell *c) { + if(!c) return; + int countplayers = 0; + int countplayers_undecided = 0; + for(int i=0; i 0 && ! isUndecided) continue; + if(playerpos(i) == c) + multi::whereto[i].d = MD_WAIT; + else { + for(int d=0; dtype; d++) { + cdir = d; + if(multi::multiPlayerTarget(i) == c) break; + cdir = scdir; + } + } + } + + needinput = + ((countplayers == 2 && !countplayers_undecided) || countplayers_undecided >= 2); + } + + EX } + +} \ No newline at end of file diff --git a/orbs.cpp b/orbs.cpp index 909cab92..c4020368 100644 --- a/orbs.cpp +++ b/orbs.cpp @@ -575,7 +575,7 @@ void teleportTo(cell *dest) { auto_teleport_charges(); } -void jumpTo(cell *dest, eItem byWhat, int bonuskill, eMonster dashmon) { +EX void jumpTo(cell *dest, eItem byWhat, int bonuskill IS(0), eMonster dashmon IS(moNone)) { if(byWhat != itStrongWind) playSound(dest, "orb-frog"); cell *from = cwt.at; diff --git a/savemem.cpp b/savemem.cpp index 050fe5e5..8cba75f2 100644 --- a/savemem.cpp +++ b/savemem.cpp @@ -7,16 +7,16 @@ namespace hr { static const int PSEUDOKEY_MEMORY = 16397; #endif -bool memory_saving_mode = true; +EX bool memory_saving_mode = true; bool show_memory_warning = true; bool ignored_memory_warning; static const int LIM = 150; -heptagon *last_cleared; +EX heptagon *last_cleared; -void destroycellcontents(cell *c) { +EX void destroycellcontents(cell *c) { c->land = laMemory; c->wall = waChasm; c->item = itNone; @@ -32,8 +32,7 @@ void degrade(cell *c) { destroycellcontents(c); } -vector removed_cells; - +EX vector removed_cells; void slow_delete_cell(cell *c) { while(c->mpdist < BARLEV) @@ -169,11 +168,11 @@ void save_memory() { EX purehookset hooks_removecells; -bool is_cell_removed(cell *c) { +EX bool is_cell_removed(cell *c) { return binary_search(removed_cells.begin(), removed_cells.end(), c); } -void set_if_removed(cell*& c, cell *val) { +EX void set_if_removed(cell*& c, cell *val) { if(is_cell_removed(c)) c = val; } diff --git a/shmup.cpp b/shmup.cpp index 44209b44..64a28a48 100644 --- a/shmup.cpp +++ b/shmup.cpp @@ -6,9 +6,6 @@ namespace hr { -extern int mousex, mousey; -extern bool clicked; - // joysticks for controlling the mobile shmup mode namespace shmupballs { int xmove, xfire, yb, rad; @@ -22,945 +19,6 @@ namespace shmupballs { } } -EX namespace multi { - - config scfg; - EX charstyle scs[MAXPLAYER]; - - EX int players = 1; - EX cellwalker player[MAXPLAYER]; - EX vector revive_queue; // queue for revival - - EX cell *origpos[MAXPLAYER], *origtarget[MAXPLAYER]; - - EX bool flipped[MAXPLAYER]; - - // treasure collection, kill, and death statistics - EX int treasures[MAXPLAYER], kills[MAXPLAYER], deaths[MAXPLAYER]; - - EX bool alwaysuse = false; - - EX void recall() { - for(int i=0; itype; - cell *c2 = cwt.at->move(idir); - makeEmpty(c2); - if(!passable(c2, NULL, P_ISPLAYER)) c2 = cwt.at; - multi::player[i].at = c2; - multi::player[i].spin = 0; - - multi::flipped[i] = true; - multi::whereto[i].d = MD_UNDECIDED; - } - } - - transmatrix whereis[MAXPLAYER]; - transmatrix crosscenter[MAXPLAYER]; - double ccdist[MAXPLAYER]; - cell *ccat[MAXPLAYER]; - - bool combo[MAXPLAYER]; - - EX int cpid; // player id -- an extra parameter for player-related functions - EX int cpid_edit; // cpid currently being edited - - EX movedir whereto[MAXPLAYER]; // player's target cell - - double mdx[MAXPLAYER], mdy[MAXPLAYER]; // movement vector for the next move - - static const int CMDS = 15; - static const int CMDS_PAN = 11; - - vector playercmds_shmup = { - "forward", "backward", "turn left", "turn right", - "move up", "move right", "move down", "move left", - "throw a knife", "face the pointer", "throw at the pointer", - "drop Dead Orb", "center the map on me", "Orb power (target: mouse)", - "Orb power (target: facing)" - }; - - vector playercmds_shmup3 = { - "rotate up", "rotate down", "rotate left", "rotate right", - "move forward", "strafe right", "move backward", "strafe left", - "throw a knife", "face the pointer", "throw at the pointer", - "drop Dead Orb", "center the map on me", "Orb power (target: mouse)", - "Orb power (target: facing)" - }; - - vector playercmds_turn = { - "move up-right", "move up-left", "move down-right", "move down-left", - "move up", "move right", "move down", "move left", - "stay in place (left + right)", "cancel move", "leave the game", - "drop Dead Orb (up + down)", "center the map on me", "", - "" - }; - - vector pancmds = { - "pan up", "pan right", "pan down", "pan left", - "rotate left", "rotate right", "home", - "world overview", "review your quest", "inventory", "main menu" - }; - - vector pancmds3 = { - "look up", "look right", "look down", "look left", - "rotate left", "rotate right", "home", - "world overview", "review your quest", "inventory", "main menu", - "scroll forward", "scroll backward" - }; - -#define SHMUPAXES_BASE 4 -#define SHMUPAXES ((SHMUPAXES_BASE) + 4 * (MAXPLAYER)) -#define SHMUPAXES_CUR ((SHMUPAXES_BASE) + 4 * playercfg) - -const char* axemodes[SHMUPAXES] = { - "do nothing", - "rotate view", - "panning X", - "panning Y", - "player 1 X", - "player 1 Y", - "player 1 go", - "player 1 spin", - "player 2 X", - "player 2 Y", - "player 2 go", - "player 2 spin", - "player 3 X", - "player 3 Y", - "player 3 go", - "player 3 spin", - "player 4 X", - "player 4 Y", - "player 4 go", - "player 4 spin", - "player 5 X", - "player 5 Y", - "player 5 go", - "player 5 spin", - "player 6 X", - "player 6 Y", - "player 6 go", - "player 6 spin", - "player 7 X", - "player 7 Y", - "player 7 go", - "player 7 spin" - }; - -const char* axemodes3[4] = { - "do nothing", - "camera forward", - "camera rotate X", - "camera rotate Y" - }; - -int centerplayer = -1; - -char* axeconfigs[24]; int numaxeconfigs; -int* dzconfigs[24]; - -string listkeys(int id) { -#if CAP_SDL - string lk = ""; - for(int i=0; i<512; i++) - if(scfg.keyaction[i] == id) - lk = lk + " " + SDL_GetKeyName(SDLKey(i)); -#if CAP_SDLJOY - for(int i=0; i& shmupcmdtable; - int setwhat; - - key_configurer(int sc, vector& sct) : sc(sc), shmupcmdtable(sct), setwhat(0) {} - - void operator() () { - - dialog::init( - XLAT(sc == 1 ? "configure player 1" : - sc == 2 ? "configure player 2" : - sc == 3 ? "configure panning" : - sc == 4 ? "configure player 3" : - sc == 5 ? "configure player 4" : - sc == 6 ? "configure player 5" : - sc == 7 ? "configure player 6" : - sc == 8 ? "configure player 7" : "" - )); - - getcstat = ' '; - - for(int i=0; i1 && i == (setwhat&15) ? '?' : 0) : 'a'+i); - else dialog::addBreak(100); - - if(setwhat == 1) - dialog::addItem(XLAT("press a key to unassign"), 0); - else if(setwhat) - dialog::addItem(XLAT("press a key for '%1'", XLAT(shmupcmdtable[setwhat&15])), 0); - else - dialog::addItem(XLAT("unassign a key"), 'z'); - - dialog::display(); - - keyhandler = [this] (int sym, int uni) { - if(!setwhat) dialog::handleNavigation(sym, uni); - if(sym) { - if(setwhat) { - scfg.keyaction[sym] = setwhat; - setwhat = 0; - } - else if(uni >= 'a' && uni < 'a' + isize(shmupcmdtable) && shmupcmdtable[uni-'a'][0]) - setwhat = 16*sc+uni - 'a'; - else if(uni == 'z') - setwhat = 1; - else if(doexiton(sym, uni)) - popScreen(); - } - }; - -#if CAP_SDLJOY - joyhandler = [this] (SDL_Event& ev) { - if(ev.type == SDL_JOYBUTTONDOWN && setwhat) { - int joyid = ev.jbutton.which; - int button = ev.jbutton.button; - if(joyid < 8 && button < 32) - scfg.joyaction[joyid][button] = setwhat; - setwhat = 0; - return true; - } - - else if(ev.type == SDL_JOYHATMOTION && 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; - printf("%d %d %d\n", joyid, hat, dir); - if(joyid < 8 && hat < 4 && dir < 4) { - scfg.hataction[joyid][hat][dir] = setwhat; - setwhat = 0; - return true; - } - } - return false; - }; -#endif - } - }; - -#if CAP_SDLJOY -struct joy_configurer { - - bool shmupcfg, racecfg; - int playercfg; - joy_configurer(int playercfg) : playercfg(playercfg) {} - - void operator() () { - dialog::init(); - getcstat = ' '; - numaxeconfigs = 0; - for(int j=0; j 10000) buf += "+", y -= 10000; - while(y < -10000) buf += "-", y += 10000; - if(y>0) buf += "+"; - if(y<0) buf += "-"; - } - axeconfigs[numaxeconfigs] = &(scfg.axeaction[j][ax]); - dzconfigs[numaxeconfigs] = &(scfg.deadzoneval[j][ax]); - char aa = *axeconfigs[numaxeconfigs]; - string what = configdead ? its(scfg.deadzoneval[j][ax]) : - (DIM == 3 && (aa%SHMUPAXES < 4)) ? XLAT(axemodes3[aa%SHMUPAXES]) : - XLAT(axemodes[aa%SHMUPAXES]); - dialog::addSelItem(XLAT("Joystick %1, axis %2", cts('A'+j), its(ax)) + buf, - what, 'a'+numaxeconfigs); - numaxeconfigs++; - } - } - - dialog::addBoolItem(XLAT("Configure dead zones"), (configdead), 'z'); - dialog::display(); - - keyhandler = [this] (int sym, int uni) { - dialog::handleNavigation(sym, uni); - if(sym) { - char xuni = uni | 96; - if(xuni >= 'a' && xuni < 'a' + numaxeconfigs) { - if(configdead) - dialog::editNumber( (*dzconfigs[xuni - 'a']), 0, 65536, 100, 0, XLAT("Configure dead zones"), ""); - else { - int v = (*axeconfigs[xuni - 'a']); - v += (shiftmul>0?1:-1); - v += SHMUPAXES_CUR; - v %= SHMUPAXES_CUR; - (*axeconfigs[xuni - 'a']) = v; - } - } - else if(xuni == 'z') - configdead = !configdead; - else if(doexiton(sym, uni)) - popScreen(); - } - }; - } - }; -#endif - -struct shmup_configurer { - - void operator()() { - #if CAP_SDL - cmode = sm::SHMUPCONFIG; - gamescreen(3); - dialog::init(XLAT("keyboard & joysticks")); - - bool haveconfig = shmup::on || players > 1 || multi::alwaysuse; - - if(haveconfig) - dialog::addItem(XLAT("configure player 1"), '1'); - else - dialog::addBreak(100); - if(players > 1) - dialog::addItem(XLAT("configure player 2"), '2'); - else if(players == 1 && !shmup::on) - dialog::addSelItem(XLAT("input"), XLAT(multi::alwaysuse ? "config" : "default"), 'a'); - else - dialog::addBreak(100); - if(players > 2) - dialog::addItem(XLAT("configure player 3"), '3'); - #if CAP_SDLJOY - else if(!haveconfig) - dialog::addItem(XLAT("old style joystick configuration"), 'b'); - #endif - else dialog::addBreak(100); - if(players > 3) - dialog::addItem(XLAT("configure player 4"), '4'); - else if(!shmup::on && !multi::alwaysuse) { - dialog::addBoolItem(XLAT("smooth scrolling"), smooth_scrolling, 'c'); - } - else if(alwaysuse) - dialog::addInfo(XLAT("note: configured input is designed for")); - else dialog::addBreak(100); - - if(players > 4) - dialog::addItem(XLAT("configure player 5"), '5'); - else if(!shmup::on && !multi::alwaysuse) { - if(GDIM == 2) { - const char *axmodes[5] = {"OFF", "auto", "light", "heavy", "arrows"}; - dialog::addSelItem(XLAT("help for keyboard users"), XLAT(axmodes[vid.axes]), 'h'); - dialog::add_action([] {vid.axes += 60 + (shiftmul > 0 ? 1 : -1); vid.axes %= 5; } ); - } - else dialog::addBreak(100); - } - else if(alwaysuse) - dialog::addInfo(XLAT("multiplayer and shmup mode; some features")); - else dialog::addBreak(100); - - if(players > 5) - dialog::addItem(XLAT("configure player 6"), '6'); - else if(alwaysuse) - dialog::addInfo(XLAT("work worse if you use it.")); - else dialog::addBreak(100); - - if(players > 6) - dialog::addItem(XLAT("configure player 7"), '7'); - else dialog::addBreak(100); - - if(shmup::on || multi::alwaysuse || players > 1) - dialog::addItem(XLAT("configure panning and general keys"), 'p'); - else dialog::addBreak(100); - - #if CAP_SDLJOY - if(numsticks > 0) { - if(shmup::on || multi::alwaysuse || players > 1) - dialog::addItem(XLAT("configure joystick axes"), 'j'); - else dialog::addBreak(100); - } - #endif - - dialog::addBreak(50); - - dialog::addHelp(); - - dialog::addBack(); - dialog::display(); - - keyhandler = [this] (int sym, int uni) { return handleConfig(sym, uni); }; - #endif - } - - void handleConfig(int sym, int uni) { - auto& cmdlist = shmup::on ? (WDIM == 3 ? playercmds_shmup3 : playercmds_shmup) : playercmds_turn; - dialog::handleNavigation(sym, uni); - - if(0) ; - #if CAP_SDL - else if(uni == '1') pushScreen(key_configurer(1, cmdlist)); - else if(uni == '2') pushScreen(key_configurer(2, cmdlist)); - else if(uni == 'p') pushScreen(key_configurer(3, GDIM == 3 ? pancmds3 : pancmds)); - else if(uni == '3') pushScreen(key_configurer(4, cmdlist)); - else if(uni == '4') pushScreen(key_configurer(5, cmdlist)); - else if(uni == '5') pushScreen(key_configurer(6, cmdlist)); - else if(uni == '6') pushScreen(key_configurer(7, cmdlist)); - else if(uni == '7') pushScreen(key_configurer(8, cmdlist)); - #if CAP_SDLJOY - else if(uni == 'j') pushScreen(joy_configurer(players)); - #endif - else if(uni == 'a') multi::alwaysuse = !multi::alwaysuse; - #if CAP_SDLJOY - else if(uni == 'b') pushScreen(showJoyConfig); - #endif - else if(uni == 'c') smooth_scrolling = !smooth_scrolling; - #endif - else if(doexiton(sym, uni)) popScreen(); - } - }; - -EX void configure() { - pushScreen(shmup_configurer()); - } - -EX void showConfigureMultiplayer() { - gamescreen(1); - dialog::init("multiplayer"); - - for(int i=1; i <= MAXPLAYER; i++) { - string s = player_count_name(i); - if(i <= players) s += dsc(i-1); - dialog::addBoolItem(s, i == multi::players, '0' + i); - if(!dual::state) dialog::add_action([i] { - dialog::do_if_confirmed([i] { - stop_game(); - players = i; - start_game(); - }); - }); - } - - if(multi::players > 1) { - dialog::addItem(XLAT("reset per-player statistics"), 'r'); - dialog::add_action([] { - for(int i=0; i= 0 && id < NUMACT) - actionspressed[id]++; - } - -bool notremapped(int sym) { - int k = scfg.keyaction[sym]; - if(k == 0) return true; - k /= 16; - if(k > 3) k--; else if(k==3) k = 0; - return k > multi::players; - } - -EX void initConfig() { - - char* t = scfg.keyaction; - - t[(int)'w'] = 16 + 4; - t[(int)'d'] = 16 + 5; - t[(int)'s'] = 16 + 6; - t[(int)'a'] = 16 + 7; - -#if ISMOBILE==0 - t[SDLK_KP8] = 16 + 4; - t[SDLK_KP6] = 16 + 5; - t[SDLK_KP2] = 16 + 6; - t[SDLK_KP4] = 16 + 7; -#endif - - t[(int)'f'] = 16 + pcFire; - t[(int)'g'] = 16 + pcFace; - t[(int)'h'] = 16 + pcFaceFire; - t[(int)'r'] = 16 + pcDrop; - t[(int)'t'] = 16 + pcOrbPower; - t[(int)'y'] = 16 + pcCenter; - - t[(int)'i'] = 32 + 4; - t[(int)'l'] = 32 + 5; - t[(int)'k'] = 32 + 6; - t[(int)'j'] = 32 + 7; - t[(int)';'] = 32 + 8; - t[(int)'\''] = 32 + 9; - t[(int)'p'] = 32 + 10; - t[(int)'['] = 32 + pcCenter; - -#if ISMOBILE==0 - t[SDLK_UP] = 48 ; - t[SDLK_RIGHT] = 48 + 1; - t[SDLK_DOWN] = 48 + 2; - t[SDLK_LEFT] = 48 + 3; - t[SDLK_PAGEUP] = 48 + 4; - t[SDLK_PAGEDOWN] = 48 + 5; - t[SDLK_HOME] = 48 + 6; -#endif - - scfg.joyaction[0][0] = 16 + pcFire; - scfg.joyaction[0][1] = 16 + pcOrbPower; - scfg.joyaction[0][2] = 16 + pcDrop; - scfg.joyaction[0][3] = 16 + pcCenter; - scfg.joyaction[0][4] = 16 + pcFace; - scfg.joyaction[0][5] = 16 + pcFaceFire; - - scfg.joyaction[1][0] = 32 + pcFire; - scfg.joyaction[1][1] = 32 + pcOrbPower; - scfg.joyaction[1][2] = 32 + pcDrop; - scfg.joyaction[1][3] = 32 + pcCenter; - scfg.joyaction[1][4] = 32 + pcFace; - scfg.joyaction[1][5] = 32 + pcFaceFire; - - scfg.axeaction[0][0] = 4; - scfg.axeaction[0][1] = 5; - scfg.axeaction[0][3] = 2; - scfg.axeaction[0][4] = 3; - - scfg.axeaction[1][0] = 8; - scfg.axeaction[1][1] = 9; - - // ULRD - scfg.hataction[0][0][0] = 16 + 0; - scfg.hataction[0][0][1] = 16 + 3; - scfg.hataction[0][0][2] = 16 + 1; - scfg.hataction[0][0][3] = 16 + 2; - scfg.hataction[0][1][0] = 16 + 4; - scfg.hataction[0][1][1] = 16 + 7; - scfg.hataction[0][1][2] = 16 + 5; - scfg.hataction[0][1][3] = 16 + 6; - - scfg.hataction[1][0][0] = 32 + 0; - scfg.hataction[1][0][1] = 32 + 3; - scfg.hataction[1][0][2] = 32 + 1; - scfg.hataction[1][0][3] = 32 + 2; - scfg.hataction[1][1][0] = 32 + 4; - scfg.hataction[1][1][1] = 32 + 7; - scfg.hataction[1][1][2] = 32 + 5; - scfg.hataction[1][1][3] = 32 + 6; - - int charidtable[MAXPLAYER] = {0, 1, 4, 6, 2, 3, 0}; - - for(int i=0; i dz) value -= dz; else if(value < -dz) value += dz; - else value = 0; - axespressed[scfg.axeaction[j][b] % SHMUPAXES] += value; - } - } -#endif - - if(keystate[SDLK_LCTRL] || keystate[SDLK_RCTRL]) d /= 5; - - double panx = - actionspressed[49] - actionspressed[51] + axespressed[2] / 32000.0; - double pany = - actionspressed[50] - actionspressed[48] + axespressed[3] / 32000.0; - - double panspin = actionspressed[52] - actionspressed[53]; - - double panmove = actionspressed[59] - actionspressed[60]; - - if(DIM == 3) - panmove += axespressed[1] / 32000.0; - else - panspin += axespressed[1] / 32000.0; - - if(actionspressed[54]) { centerplayer = -1, playermoved = true; centerpc(100); } - - if(actionspressed[55] && !lactionpressed[55]) - get_o_key().second(); - - if(actionspressed[56] && !lactionpressed[56]) - showMissionScreen(); - -#if CAP_INV - if(actionspressed[57] && !lactionpressed[57] && inv::on) - pushScreen(inv::show); -#endif - - if(actionspressed[58] && !lactionpressed[58]) - pushScreen(showMainMenu); - - panx *= d; - pany *= d; - panspin *= d; - panmove *= d; - - #if CAP_MOUSEGRAB - if(lctrlclick) { - panx += mouseaim_x / 2; - pany += mouseaim_y / 2; - mouseaim_x = mouseaim_y = 0; - } - #endif - - if(panx || pany || panspin || (GDIM == 3 && panmove)) { - if(DIM == 2) { - View = xpush(-panx) * ypush(-pany) * spin(panspin) * View; - playermoved = false; - } - else { - View = cspin(0, 2, -panx) * cspin(1, 2, -pany) * spin(panspin) * cpush(2, panmove) * View; - if(panmove) playermoved = false; - } - } -#endif - } - - int tableid[7] = {1, 2, 4, 5, 6, 7, 8}; - - EX void leaveGame(int i) { - multi::player[i].at = NULL; - multi::deaths[i]++; - revive_queue.push_back(i); - checklastmove(); - } - - EX bool playerActive(int p) { - if(multi::players == 1 || shmup::on) return true; - return player[p].at; - } - - EX int activePlayers() { - int q = 0; - for(int i=0; i= 0) - cwti = cwti + dir + wstep; - return cwti.at; - } - - EX void checklastmove() { - for(int i=0; i 1) { - addMessage(XLAT("Left the game.")); - multi::leaveGame(i); - } - - if(actionspressed[b+pcDrop] || - (multi::actionspressed[b+pcMoveUp] && multi::actionspressed[b+pcMoveDown])) - multi::combo[i] = true, multi::whereto[i].d = MD_DROP; - - if(actionspressed[b+pcCenter]) { - centerplayer = cpid; centerpc(100); playermoved = true; - } - - if(multi::whereto[i].d == MD_UNDECIDED) alldecided = false; - - for(int ik=0; ik<16; ik++) if(actionspressed[b+ik]) anypressed = true; - - if(anypressed) alldecided = false, needinput = false; - else multi::mdx[i] = multi::mdy[i] = 0; - } - - cwtV = bcwtV; - cwt = bcwt; - - if(alldecided) { - flashMessages(); - // check for crashes - needinput = true; - - for(int i=0; i 8) { - addMessage("Players cannot get that far away!"); - return; - } */ - } - - if(multi::players == 1) { - if(movepcto(multi::whereto[0])) - multi::whereto[0].d = MD_UNDECIDED; - return; - } - - multi::cpid = 0; - if(multimove()) { - multi::aftermove = false; - monstersTurn(); - checklastmove(); - } - } - } - - void mousemovement(cell *c) { - if(!c) return; - int countplayers = 0; - int countplayers_undecided = 0; - for(int i=0; i 0 && ! isUndecided) continue; - if(playerpos(i) == c) - multi::whereto[i].d = MD_WAIT; - else { - for(int d=0; dtype; d++) { - cdir = d; - if(multi::multiPlayerTarget(i) == c) break; - cdir = scdir; - } - } - } - - needinput = - ((countplayers == 2 && !countplayers_undecided) || countplayers_undecided >= 2); - } - - EX } - /* const char *lastprofile = ""; int lt = 0;