From e87a167c933ed33ce52a4991bc872a8ee443ca97 Mon Sep 17 00:00:00 2001 From: driAn Date: Sat, 29 Dec 2007 16:54:44 +0000 Subject: [PATCH] firstrun script, new menu items, lanconnect fix git-svn-id: svn://svn.code.sf.net/p/actiongame/code/trunk/ac@1512 e016b1c5-ed68-44aa-a2f7-31cac88cffde --- config/menus.cfg | 110 ++++++- config/securemaps.cfg | 4 +- source/src/client.cpp | 3 +- source/src/clientgame.cpp | 6 + source/src/console.cpp | 117 ++------ source/src/console.h | 80 +++++ source/src/docs.cpp | 8 +- source/src/main.cpp | 7 +- source/src/menus.cpp | 616 ++++++++++++++++++++++++++------------ source/src/protos.h | 31 +- source/src/sound.cpp | 2 +- source/src/worldio.cpp | 2 +- 12 files changed, 693 insertions(+), 293 deletions(-) diff --git a/config/menus.cfg b/config/menus.cfg index 7b3a64b7..8405f800 100755 --- a/config/menus.cfg +++ b/config/menus.cfg @@ -14,6 +14,112 @@ menuitem "About" "showmenu about" menuitem "Quit" "quit" +newmenu "quick setup" + +menuitemtextinput "nickname: " "unnamed" [ + if (= $arg1 0) [ alias new_name $arg2 ] [] +] +menuitemtextinput "screen width: " "$scr_w" [ + if (= $arg1 0) [ alias new_scr_w $arg2 ] [] +] +menuitemtextinput "screen height: " "$scr_h" [ + if (= $arg1 0) [ alias new_scr_h $arg2 ] [] +] +menuitemslider "mouse sensitivity: "2 100 "($sensitivity)" 2 "" [ + if (= $arg1 0) [] [ alias new_sensitivity $arg3 ] +] +menuitemslider "graphics quality: " 1 4 "(getgfxq; $gfxq)" 1 "low medium good awesome" [ + if (= $arg1 0) [] [ alias new_gfx_quality $arg3 ] +] +menuitemslider "sound quality: " 1 3 "(getsoundq; $soundq)" 1 "low medium good" [ + if (= $arg1 0) [] [ alias new_sound_quality $arg3 ] +] +menuitem "OK" [ + name $new_name + sensitivity $new_sensitivity + + scr_w $new_scr_w + scr_h $new_scr_h + + if (= $new_gfx_quality 4) [ // awesome gfx quality + minlod 200 + fpsrange 100 1000 + watersubdiv 2 + dynlight 16 + waterrefract 1 + dynshadow 40 + lighterror 1 + fsaa 16 + ] [ + if (= $new_gfx_quality 3) [ // high + minlod 100 + fpsrange 60 60 + watersubdiv 2 + dynlight 16 + waterrefract 1 + dynshadow 40 + lighterror 4 + fsaa 4 + ] [ + if (= $new_gfx_quality 2) [ // medium + minlod 60 + fpsrange 30 40 + watersubdiv 4 + dynlight 16 + waterrefract 1 + dynshadow 40 + lighterror 4 + fsaa 0 + ] [ // poor + minlod 25 + fpsrange 20 25 + watersubdiv 16 + dynlight 0 + waterrefract 0 + dynshadow 0 + lighterror 10 + fsaa 0 + ] + ] + ] + + if (= $new_sound_quality 3) [ // high sound + soundchans 64 + maxsoundsatonce 15 + soundbufferlen 1024 + ] [ + if (= $new_sound_quality 2) [ // medium + soundchans 32 + maxsoundsatonce 5 + soundbufferlen 1024 + ] [ // low + soundchans 32 + maxsoundsatonce 5 + soundbufferlen 2048 // causes sound lag while reducing cpu load + ] + ] + + showmenu restart +] + +alias getgfxq [ + if (= $minlod 200) [ alias gfxq 4 ] [ + if (= $minlod 100) [ alias gfxq 3 ] [ + if (= $minlod 60) [ gfxq 2 ] [ gfxq 1 ] + ] + ] +] + +alias getsoundq [ + if (= $soundchans 64) [ alias soundq 3 ] [ + if (= $soundbufferlen 1024) [ alias soundq 2 ] [ alias soundq 1 ] + ] +] + +newmenu restart +menuitem "You need to restart AssaultCube" "quit" + + // menumdl path anim rotation-speed{0..100} scale{0..100} // chmenumdl menuname newpath @@ -486,7 +592,7 @@ menuitem "subdivision 16 (my 486 can do water too)" "watersubdiv 16" newmenu dynlight -menuitem "enable dynamic light/shadows" "dynlight 1" +menuitem "enable dynamic light/shadows" "dynlight 16" menuitem "disable dynamic light/shadows" "dynlight 0" newmenu "water reflection" @@ -501,7 +607,7 @@ menuitem "disable dynamic player shadows" "dynshadow 0" newmenu about -menuitem "AssaultCube v0.93" "" +menuitem "AssaultCube v0.94" "" menuitem "" menuitem " ...help" "showmenu help" menuitem " ...credits" "showmenu credits" diff --git a/config/securemaps.cfg b/config/securemaps.cfg index b41c2f9f..0f1e03e4 100644 --- a/config/securemaps.cfg +++ b/config/securemaps.cfg @@ -4,4 +4,6 @@ securemap ac_desert securemap ac_desert2 securemap ac_depot securemap ac_snow -securemap ac_toxic \ No newline at end of file +securemap ac_toxic +securemap ac_elevation +securemap ac_power \ No newline at end of file diff --git a/source/src/client.cpp b/source/src/client.cpp index 86731d3b..cbd4a2d6 100644 --- a/source/src/client.cpp +++ b/source/src/client.cpp @@ -72,7 +72,8 @@ void connects(char *servername, char *serverport, char *password) s_strcpy(clientpassword, password ? password : ""); ENetAddress address; - int p = atoi(serverport); + int p = 0; + if(serverport) p = atoi(serverport); address.port = p > 0 ? p : CUBE_DEFAULT_SERVER_PORT; if(servername) diff --git a/source/src/clientgame.cpp b/source/src/clientgame.cpp index a8ab1c0f..2a899a48 100644 --- a/source/src/clientgame.cpp +++ b/source/src/clientgame.cpp @@ -74,6 +74,7 @@ void newname(const char *name) if(!player1->name[0]) s_strcpy(player1->name, "unarmed"); } else conoutf("your name is: %s", player1->name); + alias("curname", player1->name); } int smallerteam() @@ -535,6 +536,11 @@ void startmap(const char *name) // called just after a map load intermission = false; minutesremaining = -1; if(*clientmap) conoutf("game mode is \"%s\"", modestr(gamemode)); + if(firstrun && name && name[0]) + { + execfile("config/firstrun.cfg"); + firstrun = false; + } } void suicide() diff --git a/source/src/console.cpp b/source/src/console.cpp index af9497f0..2c26b169 100644 --- a/source/src/console.cpp +++ b/source/src/console.cpp @@ -49,11 +49,8 @@ struct console : consolebuffer }; console con; - +textinputbuffer cmdline; bool saycommandon = false; -string commandbuf; -int commandpos = -1; - void setconskip(int n) { con.setconskip(n); } COMMANDN(conskip, setconskip, ARG_1INT); @@ -78,9 +75,9 @@ void conoutf(const char *s, ...) void rendercommand(int x, int y) { - s_sprintfd(s)("> %s", commandbuf); - int offset = text_width(s, commandpos>=0 ? commandpos+2 : -1); - blendbox(x+offset, y, x+offset+char_width(commandpos>=0 ? commandbuf[commandpos] : '_'), y+FONTH, true); + s_sprintfd(s)("> %s", cmdline.buf); + int offset = text_width(s, cmdline.pos>=0 ? cmdline.pos+2 : -1); + blendbox(x+offset, y, x+offset+char_width(cmdline.pos>=0 ? cmdline.buf[cmdline.pos] : '_'), y+FONTH, true); draw_text(s, x, y); } @@ -152,8 +149,8 @@ void saycommand(char *init) // turns input to the comman SDL_EnableUNICODE(saycommandon = (init!=NULL)); setscope(false); if(!editmode) keyrepeat(saycommandon); - s_strcpy(commandbuf, init ? init : ""); - commandpos = -1; + s_strcpy(cmdline.buf, init ? init : ""); + cmdline.pos = -1; player1->stopmoving(); // prevent situations where player presses direction key, open command line, then releases key } @@ -167,13 +164,13 @@ COMMAND(mapmsg, ARG_1STR); #include #endif -void pasteconsole() +void pasteconsole(char *dst) { #ifdef WIN32 if(!IsClipboardFormatAvailable(CF_TEXT)) return; if(!OpenClipboard(NULL)) return; char *cb = (char *)GlobalLock(GetClipboardData(CF_TEXT)); - s_strcat(commandbuf, cb); + s_strcat(dst, cb); GlobalUnlock(cb); CloseClipboard(); #elif defined(__APPLE__) @@ -228,61 +225,6 @@ void keypress(int code, bool isdown, int cooked) { switch(code) { - case SDLK_RETURN: - case SDLK_KP_ENTER: - break; - - case SDLK_HOME: - if(strlen(commandbuf)) commandpos = 0; - break; - - case SDLK_END: - commandpos = -1; - break; - - case SDLK_DELETE: - { - int len = (int)strlen(commandbuf); - if(commandpos<0) break; - memmove(&commandbuf[commandpos], &commandbuf[commandpos+1], len - commandpos); - resetcomplete(); - if(commandpos>=len-1) commandpos = -1; - break; - } - - case SDLK_BACKSPACE: - { - int len = (int)strlen(commandbuf), i = commandpos>=0 ? commandpos : len; - if(i<1) break; - memmove(&commandbuf[i-1], &commandbuf[i], len - i + 1); - resetcomplete(); - if(commandpos>0) commandpos--; - else if(!commandpos && len<=1) commandpos = -1; - break; - } - - case SDLK_LEFT: - if(commandpos>0) commandpos--; - else if(commandpos<0) commandpos = (int)strlen(commandbuf)-1; - break; - - case SDLK_RIGHT: - if(commandpos>=0 && ++commandpos>=(int)strlen(commandbuf)) commandpos = -1; - break; - - case SDLK_UP: - if(histpos) s_strcpy(commandbuf, vhistory[--histpos]); - break; - - case SDLK_DOWN: - if(histpos=0 && commandpos>=(int)strlen(commandbuf)) commandpos = -1; - break; - case SDLK_F1: toggledoc(); break; @@ -295,40 +237,37 @@ void keypress(int code, bool isdown, int cooked) scrolldoc(4); break; - case SDLK_v: - if(SDL_GetModState()&(KMOD_LCTRL|KMOD_RCTRL)) { pasteconsole(); return; } + case SDLK_UP: + if(histpos) s_strcpy(cmdline.buf, vhistory[--histpos]); + break; + + case SDLK_DOWN: + if(histpos=0 && cmdline.pos>=(int)strlen(cmdline.buf)) cmdline.pos = -1; + break; default: resetcomplete(); - if(cooked) - { - size_t len = (int)strlen(commandbuf); - if(len+1=len-1) pos = -1; + break; + } + + case SDLK_BACKSPACE: + { + int len = (int)strlen(buf), i = pos>=0 ? pos : len; + if(i<1) break; + memmove(&buf[i-1], &buf[i], len - i + 1); + if(pos>0) pos--; + else if(!pos && len<=1) pos = -1; + break; + } + + case SDLK_LEFT: + if(pos > 0) pos--; + else if(pos < 0) pos = (int)strlen(buf)-1; + break; + + case SDLK_RIGHT: + if(pos>=0 && ++pos>=(int)strlen(buf)) pos = -1; + break; + + case SDLK_v: + extern void pasteconsole(char *dst); + if(SDL_GetModState()&(KMOD_LCTRL|KMOD_RCTRL)) { pasteconsole(buf); return; } + + default: + { + if(unicode) + { + size_t len = strlen(buf); + if(len+1 < sizeof(buf)) + { + if(pos < 0) buf[len] = unicode; + else + { + memmove(&buf[pos+1], &buf[pos], len - pos); + buf[pos++] = unicode; + } + buf[len+1] = '\0'; + } + } + break; + } + } + } +}; + diff --git a/source/src/docs.cpp b/source/src/docs.cpp index 1cdb332b..a921106e 100644 --- a/source/src/docs.cpp +++ b/source/src/docs.cpp @@ -347,19 +347,19 @@ void renderdoc(int x, int y) if(ident->arguments.length() > 0) // args { - extern int commandpos; + extern textinputbuffer cmdline; char *args = strchr(c, ' '); int arg = -1; if(args) { args++; - if(commandpos >= 0) + if(cmdline.pos >= 0) { - if(commandpos >= args-c) + if(cmdline.pos >= args-c) { string a; - s_strncpy(a, args, commandpos-(args-c)+1); + s_strncpy(a, args, cmdline.pos-(args-c)+1); args = a; arg = numargs(args); } diff --git a/source/src/main.cpp b/source/src/main.cpp index 204dc401..14a41c3d 100644 --- a/source/src/main.cpp +++ b/source/src/main.cpp @@ -211,6 +211,7 @@ void keyrepeat(bool on) VARF(gamespeed, 10, 100, 1000, if(multiplayer()) gamespeed = 100); +bool firstrun = false; static int clockrealbase = 0, clockvirtbase = 0; static void clockreset() { clockrealbase = SDL_GetTicks(); clockvirtbase = totalmillis; } VARFP(clockerror, 990000, 1000000, 1010000, clockreset()); @@ -422,7 +423,11 @@ int main(int argc, char **argv) gzclose(f); } - if(!execfile("config/saved.cfg")) exec("config/defaults.cfg"); + if(!execfile("config/saved.cfg")) + { + exec("config/defaults.cfg"); + firstrun = true; + } execfile("config/autoexec.cfg"); initlog("models"); diff --git a/source/src/menus.cpp b/source/src/menus.cpp index 9a714cd2..56e93042 100644 --- a/source/src/menus.cpp +++ b/source/src/menus.cpp @@ -8,16 +8,12 @@ gmenu *curmenu = NULL, *lastmenu = NULL; vector menustack; + void menuset(void *m) { if(curmenu==m) return; - curmenu = (gmenu *)m; - if(curmenu) - { - curmenu->inited = false; - if(curmenu->allowinput) player1->stopmoving(); - else curmenu->menusel = 0; - } + if(curmenu) curmenu->close(); + if((curmenu = (gmenu *)m)) curmenu->open(); } void showmenu(char *name) @@ -32,6 +28,28 @@ void showmenu(char *name) menuset(m); } +void menuselect(void *menu, int sel) +{ + gmenu &m = *(gmenu *)menu; + + if(sel<0) sel = m.items.length()>0 ? m.items.length()-1 : 0; + else if(sel>=m.items.length()) sel = 0; + + if(m.items.inrange(sel)) + { + int oldsel = m.menusel; + m.menusel = sel; + if(m.allowinput) + { + if(sel!=oldsel) + { + m.items[oldsel]->focus(false); + m.items[sel]->focus(true); + } + } + } +} + void drawarrow(int dir, int x, int y, int size, float r = 1.0f, float g = 1.0f, float b = 1.0f) { glDisable(GL_BLEND); @@ -49,13 +67,6 @@ void drawarrow(int dir, int x, int y, int size, float r = 1.0f, float g = 1.0f, glEnable(GL_BLEND); } -void drawmenubg(int x1, int y1, int x2, int y2, bool border) -{ - static Texture *tex = NULL; - if(!tex) tex = textureload("packages/textures/makke/menu.jpg"); - blendbox(x1, y1, x2, y2, border, tex->id); -} - #define MAXMENU 34 bool menuvisible() @@ -69,68 +80,433 @@ bool menuvisible() } void rendermenu() -{ +{ setscope(false); - gmenu &m = *curmenu; - if(m.refreshfunc) - { - (*m.refreshfunc)(curmenu, !m.inited); - m.inited = true; - if(m.menusel>=m.items.length()) m.menusel = max(m.items.length()-1, 0); - } - const char *title = m.title; - if(!title) { static string buf; s_sprintf(buf)("[ %s menu ]", m.name); title = buf; } - int hitems = (m.header ? 2 : 0) + (m.footer ? 2 : 0), + m.refresh(); + m.render(); +} + + +void gmenu::refresh() +{ + if(!refreshfunc) return; + (*refreshfunc)(this, !inited); + inited = true; + if(menusel>=items.length()) menusel = max(items.length()-1, 0); +} + +void gmenu::open() +{ + inited = false; + if(allowinput) player1->stopmoving(); + else menusel = 0; + if(items.inrange(menusel)) items[menusel]->focus(true); + loopv(items) items[i]->init(); +} + +void gmenu::close() +{ + if(items.inrange(menusel)) items[menusel]->focus(false); +} + +void gmenu::render() +{ + const char *t = title; + if(!t) { static string buf; s_sprintf(buf)("[ %s menu ]", name); t = buf; } + int hitems = (header ? 2 : 0) + (footer ? 2 : 0), pagesize = MAXMENU - hitems, - offset = m.menusel - (m.menusel%pagesize), - mdisp = min(m.items.length(), pagesize), - cdisp = min(m.items.length()-offset, pagesize); - if(m.title) text_startcolumns(); + offset = menusel - (menusel%pagesize), + mdisp = min(items.length(), pagesize), + cdisp = min(items.length()-offset, pagesize); + if(title) text_startcolumns(); int w = 0; - loopv(m.items) + loopv(items) { - int x = text_width(m.items[i].text); + int x = items[i]->width(); if(x>w) w = x; } - int tw = text_width(title); + int tw = text_width(t); if(tw>w) w = tw; - if(m.header) + if(header) { - int hw = text_width(m.header); + int hw = text_width(header); if(hw>w) w = hw; } + int step = (FONTH*5)/4; int h = (mdisp+hitems+2)*step; int y = (2*VIRTH-h)/2; int x = (2*VIRTW-w)/2; - drawmenubg(x-FONTH*3/2, y-FONTH, x+w+FONTH*3/2, y+h+FONTH, true); + renderbg(x-FONTH*3/2, y-FONTH, x+w+FONTH*3/2, y+h+FONTH, true); if(offset>0) drawarrow(1, x+w+FONTH*3/2-FONTH*5/6, y-FONTH*5/6, FONTH*2/3); - if(offset+pagesizerender(x, y, w); y += step; } - if(m.title) text_endcolumns(); - if(m.footer) + if(title) text_endcolumns(); + if(footer) { y += ((mdisp-cdisp)+1)*step; - draw_text(m.footer, x, y); + draw_text(footer, x, y); + } +} + +void gmenu::renderbg(int x1, int y1, int x2, int y2, bool border) +{ + static Texture *tex = NULL; + if(!tex) tex = textureload("packages/textures/makke/menu.jpg"); + blendbox(x1, y1, x2, y2, border, tex->id); +} + +void mitem::render(int x, int y, int w) +{ + if(bgcolor) renderbg(x, y, w); + else if(isselection()) blendbox(x-FONTH, y-FONTH/6, x+w+FONTH, y+FONTH+FONTH/6, false); +} + +void mitem::renderbg(int x, int y, int w) { blendbox(x-FONTH, y-FONTH/6, x+w+FONTH, y+FONTH+FONTH/6, false, -1, bgcolor); }; + +bool mitem::isselection() { return parent->items.inrange(parent->menusel) && parent->items[parent->menusel]==this; } + +// text item + +struct mitemtext : mitem +{ + char *text, *action, *hoveraction; + + mitemtext(gmenu *parent, char *text, char *action, char *hoveraction, color *bgcolor) : mitem(parent, bgcolor), text(text), action(action), hoveraction(hoveraction) {} + virtual ~mitemtext() + { + DELETEA(text); + DELETEA(action); + DELETEA(hoveraction); + } + + virtual int width() { return text_width(text); } + + virtual void render(int x, int y, int w) + { + mitem::render(x, y, w); + draw_text(text, x, y); + } + + virtual void focus(bool on) + { + if(on && hoveraction) execute(hoveraction); + } + + virtual void select() + { + if(action) + { + menustack.add(curmenu); + menuset(NULL); + execute(action); + } + } +}; + +// text input item + +struct mitemtextinput : mitemtext +{ + textinputbuffer input; + char *defaultvalueexp; + + mitemtextinput(gmenu *parent, char *text, char *value, char *action, char *hoveraction, color *bgcolor) : mitemtext(parent, text, action, hoveraction, bgcolor), defaultvalueexp(value) + { + s_strcpy(input.buf, value); + }; + + virtual ~mitemtextinput() { } + + virtual void select() { focus(false); focus(true); } // fixme + + virtual int width() { return text_width(input.buf) + text_width(text); } + + virtual void render(int x, int y, int w) + { + bool selection = isselection(); + int tw = text_width(text); + if(selection) blendbox(x+tw, y-FONTH/6, x+w+FONTH, y+FONTH+FONTH/6, false); + draw_text(text, x, y); + int offset = text_width(input.buf, input.pos>=0 ? input.pos : -1); + if(selection) blendbox(x+tw+offset, y, x+tw+offset+char_width(input.pos>=0 ? input.buf[input.pos] : '_'), y+FONTH, true); + draw_text(input.buf, x+tw, y); + } + + virtual void focus(bool on) + { + SDL_EnableUNICODE(on); + if(!strlen(input.buf)) setdefaultvalue(); + if(action) + { + alias("arg1", on ? "1" : "0"); + alias("arg2", input.buf); + execute(action); + } + } + + virtual bool key(int code, bool isdown, int unicode) + { + input.key(code, isdown, unicode); + return true; + } + + virtual void init() + { + setdefaultvalue(); + } + + void setdefaultvalue() + { + const char *p = defaultvalueexp; + s_strcpy(input.buf, parseword(p)); + } +}; + +// slider item + +struct mitemslider : mitem +{ + int min_, max_, step, value; + char *text, *valueexp, *display, *action; + + mitemslider(gmenu *parent, char *text, int min_, int max_, int step, char *value, char *display, char *action, color *bgcolor) : mitem(parent, bgcolor), min_(min_), max_(max_), step(step), text(text), valueexp(value), value(min_), display(display), action(action) + { + } + + virtual ~mitemslider() + { + DELETEA(text); + DELETEA(valueexp); + DELETEA(display); + DELETEA(action); + } + + virtual int width() { return text_width(text) + 600; } // fixme + + virtual void focus(bool on) + { + if(action) + { + alias("arg1", on ? "1" : "0"); + alias("arg2", "0"); + setvaluealias(); + execute(action); + } + } + + virtual void render(int x, int y, int w) + { + static color white1(0.2f, 0.2f, 0.2f), white2(1.0f, 1.0f, 1.0f); + int range = max_-min_; + int cval = value-min_; + + int tw = text_width(text); + if(isselection()) blendbox(x+tw, y-FONTH/6, x+w+FONTH, y+FONTH+FONTH/6, false); + draw_text(text, x, y); + + string v; + if(display) // extract display name from list + { + string disp, val; + s_strcpy(disp, display); + itoa(val, cval); + at(disp, val); // pass to script 'at' cmd + s_strcpy(v, getalias("s")); // grab result + } + else itoa(v, value); + int vw = text_width(v); + draw_text(v, x+w-vw, y); + + blendbox(x+tw+FONTH, y+FONTH/3, x+w, y+FONTH*2/3, false, -1, &white1); + + int sliderwidth = (x+w)-(x+tw+FONTH); + int offset = cval/(float)range*sliderwidth; + blendbox(x+tw+offset+FONTH, y, x+tw+offset+FONTH*1.2f, y+FONTH, false, -1, &white2); + } + + virtual bool key(int code, bool isdown, int unicode) + { + if(code == SDLK_LEFT) slide(false); + else if(code == SDLK_RIGHT) slide(true); + return true; + } + + virtual void init() + { + const char *p = valueexp; + char *v = parseword(p); + if(v) value = min(max_, max(min_, atoi(v))); + } + + void slide(bool right) + { + if(action) + { + value += right ? step : -step; + value = min(max_, max(min_, value)); + alias("arg1", "-1"); + alias("arg2", right ? "1" : "-1"); + setvaluealias(); + execute(action); + } + } + + void setvaluealias() + { + string v; + itoa(v, value); + alias("arg3", v); + } +}; + +// console iface + +void *addmenu(const char *name, const char *title, bool allowinput, void (__cdecl *refreshfunc)(void *, bool)) +{ + name = newstring(name); + gmenu &menu = menus[name]; + menu.name = name; + menu.title = title ? newstring(title) : NULL; + menu.header = menu.footer = NULL; + menu.menusel = 0; + menu.mdl = NULL; + menu.allowinput = allowinput; + menu.inited = false; + menu.refreshfunc = refreshfunc; + lastmenu = &menu; + return &menu; +} + +void newmenu(char *name) +{ + addmenu(name); +} + +void menumanual(void *menu, int n, char *text, char *action, color *bgcolor) +{ + gmenu &m = *(gmenu *)menu; + if(!n) m.items.setsize(0); + m.items.add(new mitemtext(&m, text, action, NULL, bgcolor)); +} + +void menuheader(void *menu, char *header, char *footer) +{ + gmenu &m = *(gmenu *)menu; + m.header = header && header[0] ? header : NULL; + m.footer = footer && footer[0] ? footer : NULL; +} + +void menuitem(char *text, char *action, char *hoveraction) +{ + if(!lastmenu) return; + char *t = newstring(text); + lastmenu->items.add(new mitemtext(lastmenu, t, action[0] ? newstring(action) : t, hoveraction[0] ? newstring(hoveraction) : NULL, NULL)); +} + +void menuitemtextinput(char *text, char *value, char *action, char *hoveraction) +{ + if(!lastmenu || !text || !value) return; + lastmenu->items.add(new mitemtextinput(lastmenu, newstring(text), newstring(value), action[0] ? newstring(action) : NULL, hoveraction[0] ? newstring(hoveraction) : NULL, NULL)); +} + +void menuitemslider(char *text, char *min_, char *max_, char *value, char *step, char *display, char *action) +{ + if(!lastmenu) return; + lastmenu->items.add(new mitemslider(lastmenu, newstring(text), atoi(min_), atoi(max_), atoi(step), value[0] ? newstring(value) : NULL, display[0] ? newstring(display) : NULL, action[0] ? newstring(action) : NULL, NULL)); +} + +void menumdl(char *mdl, char *anim, char *rotspeed, char *scale) +{ + if(!lastmenu || !mdl || !anim) return; + gmenu &menu = *lastmenu; + menu.mdl = newstring(mdl); + menu.anim = findanim(anim)|ANIM_LOOP; + menu.rotspeed = max(0, min(atoi(rotspeed), 100)); + menu.scale = max(0, min(atoi(scale), 100)); +} + +void chmenumdl(char *menu, char *mdl, char *anim, char *rotspeed, char *scale) +{ + if(!menu || !mdl || !menus.access(menu)) return; + gmenu &m = menus[menu]; + DELETEA(m.mdl); + m.mdl = newstring(mdl); + m.anim = findanim(anim)|ANIM_LOOP; + m.rotspeed = max(0, min(atoi(rotspeed), 100)); + m.scale = max(0, min(atoi(scale), 100)); +} + +COMMAND(menuitem, ARG_3STR); +COMMAND(menuitemtextinput, ARG_4STR); +COMMAND(menuitemslider, ARG_7STR); +COMMAND(showmenu, ARG_1STR); +COMMAND(newmenu, ARG_1STR); +COMMAND(menumdl, ARG_5STR); +COMMAND(chmenumdl, ARG_6STR); + +bool menukey(int code, bool isdown, int unicode) +{ + if(!curmenu) return false; + int n = curmenu->items.length(), menusel = curmenu->menusel; + if(isdown) + { + int pagesize = MAXMENU - (curmenu->header ? 2 : 0) - (curmenu->footer ? 2 : 0); + + switch(code) + { + case SDLK_PAGEUP: menusel -= pagesize; break; + case SDLK_PAGEDOWN: + if(menusel+pagesize>=n && menusel/pagesize!=(n-1)/pagesize) menusel = n-1; + else menusel += pagesize; + break; + case SDLK_ESCAPE: + case -3: + menuset(menustack.empty() ? NULL : menustack.pop()); + return true; + break; + case SDLK_UP: + case -4: + menusel--; + break; + case SDLK_DOWN: + case -5: + menusel++; + break; + default: + { + if(!curmenu->allowinput) return false; + mitem &m = *curmenu->items[menusel]; + return m.key(code, isdown, unicode); + } + } + + menuselect(curmenu, menusel); + return true; + } + else + { + if(!curmenu->allowinput) return false; + mitem &m = *curmenu->items[menusel]; + if(code==SDLK_RETURN || code==-1 || code==-2) + { + if(!curmenu->items.inrange(menusel)) { menuset(NULL); return true; } + m.select(); + return true; + } + return false; } } @@ -165,142 +541,4 @@ void rendermenumdl() rendermodel(isplayermodel ? (char *)"playermodels" : m.mdl, m.anim, tex, 0, pos, yaw, 0, 0, 0, NULL, isplayermodel ? (char*)"weapons/subgun/world" : NULL, m.scale ? m.scale/25.0f : 1.0f); glPopMatrix(); -} - -void *addmenu(const char *name, const char *title, bool allowinput, void (__cdecl *refreshfunc)(void *, bool)) -{ - name = newstring(name); - gmenu &menu = menus[name]; - menu.name = name; - menu.title = title ? newstring(title) : NULL; - menu.header = menu.footer = NULL; - menu.menusel = 0; - menu.mdl = NULL; - menu.allowinput = allowinput; - menu.inited = false; - menu.refreshfunc = refreshfunc; - lastmenu = &menu; - return &menu; -} - -void newmenu(char *name) -{ - addmenu(name); -} - -void menumanual(void *menu, int n, char *text, char *action, color *bgcolor) -{ - gmenu &m = *(gmenu *)menu; - if(!n) m.items.setsize(0); - mitem &mitem = m.items.add(); - mitem.text = text; - mitem.action = action; - mitem.hoveraction = NULL; - mitem.bgcolor = bgcolor; -} - -void menuheader(void *menu, char *header, char *footer) -{ - gmenu &m = *(gmenu *)menu; - m.header = header && header[0] ? header : NULL; - m.footer = footer && footer[0] ? footer : NULL; -} - -void menuitem(char *text, char *action, char *hoveraction) -{ - if(!lastmenu) return; - gmenu &menu = *lastmenu; - mitem &mi = menu.items.add(); - mi.text = newstring(text); - mi.action = action[0] ? newstring(action) : mi.text; - mi.hoveraction = hoveraction[0] ? newstring(hoveraction) : NULL; - mi.bgcolor = NULL; -} - -void menumdl(char *mdl, char *anim, char *rotspeed, char *scale) -{ - if(!lastmenu || !mdl || !anim) return; - gmenu &menu = *lastmenu; - menu.mdl = newstring(mdl); - menu.anim = findanim(anim)|ANIM_LOOP; - menu.rotspeed = max(0, min(atoi(rotspeed), 100)); - menu.scale = max(0, min(atoi(scale), 100)); -} - -void chmenumdl(char *menu, char *mdl, char *anim, char *rotspeed, char *scale) -{ - if(!menu || !mdl || !menus.access(menu)) return; - gmenu &m = menus[menu]; - DELETEA(m.mdl); - m.mdl = newstring(mdl); - m.anim = findanim(anim)|ANIM_LOOP; - m.rotspeed = max(0, min(atoi(rotspeed), 100)); - m.scale = max(0, min(atoi(scale), 100)); -} - -COMMAND(menuitem, ARG_3STR); -COMMAND(showmenu, ARG_1STR); -COMMAND(newmenu, ARG_1STR); -COMMAND(menumdl, ARG_5STR); -COMMAND(chmenumdl, ARG_6STR); - -void menuselect(void *menu, int sel) -{ - gmenu &m = *(gmenu *)menu; - - if(sel<0) sel = m.items.length()>0 ? m.items.length()-1 : 0; - else if(sel>=m.items.length()) sel = 0; - - if(m.items.inrange(sel)) - { - int oldsel = m.menusel; - m.menusel = sel; - if(m.allowinput) - { - char *haction = m.items[sel].hoveraction; - if(sel!=oldsel && haction) execute(haction); - } - } -} - -bool menukey(int code, bool isdown) -{ - if(!curmenu) return false; - int n = curmenu->items.length(), menusel = curmenu->menusel; - if(isdown) - { - int pagesize = MAXMENU - (curmenu->header ? 2 : 0) - (curmenu->footer ? 2 : 0); - if(code==SDLK_PAGEUP) menusel -= pagesize; - else if(code==SDLK_PAGEDOWN) - { - if(menusel+pagesize>=n && menusel/pagesize!=(n-1)/pagesize) menusel = n-1; - else menusel += pagesize; - } - else if(!curmenu->allowinput) return false; - - setscope(false); - - if(code==SDLK_ESCAPE || code==-3) - { - menuset(menustack.empty() ? NULL : menustack.pop()); - return true; - } - else if(code==SDLK_UP || code==-4) menusel--; - else if(code==SDLK_DOWN || code==-5) menusel++; - - menuselect(curmenu, menusel); - } - else - { - if(!curmenu->allowinput) return false; - if(code==SDLK_RETURN || code==-1 || code==-2) - { - if(!curmenu->items.inrange(menusel)) { menuset(NULL); return true; } - char *action = curmenu->items[menusel].action; - menustack.add(curmenu); - menuset(NULL); - if(action) execute(action); - } - } - return true; -} +} \ No newline at end of file diff --git a/source/src/protos.h b/source/src/protos.h index df5657a1..b43e2aa2 100644 --- a/source/src/protos.h +++ b/source/src/protos.h @@ -36,6 +36,8 @@ extern const char *getalias(const char *name); extern void writecfg(); extern void identnames(vector &names, bool builtinonly); extern void changescriptcontext(int newcontext); +extern void at(char *s, char *pos); +extern char *parseword(const char *&p); // console extern void keypress(int code, bool isdown, int cooked); @@ -44,6 +46,7 @@ extern void renderconsole(); extern char *getcurcommand(); extern char *addreleaseaction(const char *s); extern void writebinds(FILE *f); +extern void pasteconsole(char *dst); extern void conoutf(const char *s, ...); // menus @@ -51,29 +54,48 @@ extern void rendermenu(); extern bool menuvisible(); extern void menumanual(void *menu, int n, char *text, char *action = NULL, color *bgcolor = NULL); extern void menuheader(void *menu, char *header = NULL, char *footer = NULL); -extern bool menukey(int code, bool isdown); +extern bool menukey(int code, bool isdown, int unicode); extern void *addmenu(const char *name, const char *title = NULL, bool allowinput = true, void (__cdecl *refreshfunc)(void *, bool) = NULL); extern void rendermenumdl(); extern void menuset(void *m); extern void menuselect(void *menu, int sel); -extern void drawmenubg(int x1, int y1, int x2, int y2, bool border); +extern void showmenu(char *name); struct mitem { - char *text, *action, *hoveraction; color *bgcolor; + struct gmenu *parent; + + mitem(gmenu *parent, color *bgcolor) : parent(parent), bgcolor(bgcolor) {}; + virtual ~mitem() { delete bgcolor; } + + virtual void render(int x, int y, int w); + virtual int width() = 0; + virtual void select(){}; + virtual void focus(bool on) {}; + virtual bool key(int code, bool isdown, int unicode) { return false; } + virtual void init(){}; + bool isselection(); + void renderbg(int x, int y, int w); }; struct gmenu { const char *name, *title, *header, *footer; - vector items; + vector items; int mwidth; int menusel; const char *mdl; // (optional) md2 mdl int anim, rotspeed, scale; bool allowinput, inited; void (__cdecl *refreshfunc)(void *, bool); + + void render(); + void renderbg(int x1, int y1, int x2, int y2, bool border); + void rendermenumdl(); + void refresh(); + void open(); + void close(); }; // serverbrowser @@ -260,6 +282,7 @@ extern int isoccluded(float vx, float vy, float cx, float cy, float csize); // main extern void keyrepeat(bool on); extern bool initwarning(); +extern bool firstrun; // rendertext struct font diff --git a/source/src/sound.cpp b/source/src/sound.cpp index 0756d02d..88dd957a 100644 --- a/source/src/sound.cpp +++ b/source/src/sound.cpp @@ -155,7 +155,7 @@ void music(char *name, char *cmd) { if(nosound) return; stopsound(); - if(soundvol && musicvol && *name) + if(soundvol && *name) { if(cmd[0]) musicdonecmd = newstring(cmd); s_sprintfd(sn)("packages/audio/songs/%s", name); diff --git a/source/src/worldio.cpp b/source/src/worldio.cpp index c279c258..2b32ccf7 100644 --- a/source/src/worldio.cpp +++ b/source/src/worldio.cpp @@ -240,7 +240,7 @@ bool load_world(char *mname) // still supports all map formats that have loadingscreen(); gzread(f, &hdr, sizeof(header)-sizeof(int)*16); endianswap(&hdr.version, sizeof(int), 4); - if(strncmp(hdr.head, "CUBE", 4)!=0 && strncmp(hdr.head, "ACMP",4)!=0) fatal("while reading map: header malformatted"); + if(strncmp(hdr.head, "CUBE", 4)!=0 && strncmp(hdr.head, "ACMP",4)!=0) fatal("while reading map: header malformatted"); if(hdr.version>MAPVERSION) fatal("this map requires a newer version of cube"); if(hdr.sfactorLARGEST_FACTOR) fatal("illegal map size"); if(hdr.version>=4)