Lots of M32script tweaks:

* fix breaking out of 'switch' blocks and compilation of the 'default' case
* Have a way of assigning 'special function' menu [' F] entries to script states. Writing a string literal after the state name will register the state under that name. Menu names are limited to 24 characters and it's possible to have up to 16 of them.
* new branching command 'ifinteractive', true if a state runs from the menu mentioned above.
* new command: getnumberfromuser <<retvar>> "query_string" <maxnum> <flags>

See 'state collect_teleporting_sectors' in a.m32 for a combined usage of the new functionality.

git-svn-id: https://svn.eduke32.com/eduke32@1955 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2011-08-03 17:22:25 +00:00
parent cbf122fa80
commit aa8b2e4e05
7 changed files with 381 additions and 139 deletions

View file

@ -7722,21 +7722,26 @@ int32_t getnumber_autocomplete(const char *namestart, char ch, int32_t *danum, i
return 0; return 0;
} }
// sign is now used for more than one flag: // sign is now used for more than one flag (also _getnumber256):
// 1: sign // 1: sign
// 2: autocomplete names // 2: autocomplete names
// 4: autocomplete taglabels // 4: autocomplete taglabels
// 8: return -1 if cancelled // 8: return -1 if cancelled
int32_t _getnumber16(const char *namestart, int32_t num, int32_t maxnumber, char sign, void *(func)(int32_t)) int32_t _getnumber16(const char *namestart, int32_t num, int32_t maxnumber, char sign, void *(func)(int32_t))
{ {
char buffer[80], ch; char buffer[80], ournamestart[80-17], ch;
int32_t n, danum, oldnum; int32_t n, danum, oldnum;
uint8_t flags = (sign>>1)&7; uint8_t flags = (sign&(2|4|8))>>1;
sign &= 1; sign &= 1;
danum = num; danum = num;
oldnum = danum; oldnum = danum;
// need to have 4+11+2==17 chars room at the end
// ("^011", max. string length of an int32, "_ ")
Bstrncpy(ournamestart, namestart, sizeof(ournamestart));
ournamestart[sizeof(ournamestart)-1] = 0;
bflushchars(); bflushchars();
while (keystatus[0x1] == 0) while (keystatus[0x1] == 0)
{ {
@ -7746,14 +7751,16 @@ int32_t _getnumber16(const char *namestart, int32_t num, int32_t maxnumber, char
idle(); idle();
ch = bgetchar(); ch = bgetchar();
Bsprintf(buffer,"%s^011%d", namestart, danum); Bsprintf(buffer, "%s^011%d", ournamestart, danum);
n = Bstrlen(buffer); n = Bstrlen(buffer); // maximum is 62+4+11 == 77
if (totalclock & 32) Bstrcat(buffer,"_ "); if (totalclock & 32)
Bstrcat(buffer,"_ ");
// max strlen now 79
_printmessage16("%s", buffer); _printmessage16("%s", buffer);
if (func != NULL) if (func != NULL)
{ {
Bsprintf(buffer, "%s", (char *)func(danum)); Bsnprintf(buffer, sizeof(buffer), "%s", (char *)func(danum));
// printext16(200L-24, ydim-STATUS2DSIZ+20L, editorcolors[9], editorcolors[0], buffer, 0); // printext16(200L-24, ydim-STATUS2DSIZ+20L, editorcolors[9], editorcolors[0], buffer, 0);
printext16(n<<3, ydim-STATUS2DSIZ+128, editorcolors[11], -1, buffer,0); printext16(n<<3, ydim-STATUS2DSIZ+128, editorcolors[11], -1, buffer,0);
} }
@ -7762,7 +7769,7 @@ int32_t _getnumber16(const char *namestart, int32_t num, int32_t maxnumber, char
n = 0; n = 0;
if (getnumber_internal1(ch, &danum, maxnumber, sign) || if (getnumber_internal1(ch, &danum, maxnumber, sign) ||
(n=getnumber_autocomplete(namestart, ch, &danum, flags))) (n=getnumber_autocomplete(ournamestart, ch, &danum, flags&(1+2))))
{ {
if (flags==1 || n==0) if (flags==1 || n==0)
printmessage16("%s", buffer); printmessage16("%s", buffer);
@ -7794,14 +7801,19 @@ static void getnumber_clearline(void)
// sign: |16: don't draw scene // sign: |16: don't draw scene
int32_t _getnumber256(const char *namestart, int32_t num, int32_t maxnumber, char sign, void *(func)(int32_t)) int32_t _getnumber256(const char *namestart, int32_t num, int32_t maxnumber, char sign, void *(func)(int32_t))
{ {
char buffer[80], ch; char buffer[80], ournamestart[80-13], ch;
int32_t danum, oldnum; int32_t danum, oldnum;
uint8_t flags = (sign>>1)&(3|8); uint8_t flags = (sign&(2|4|8|16))>>1;
sign &= 1; sign &= 1;
danum = num; danum = num;
oldnum = danum; oldnum = danum;
// need to have 11+2==13 chars room at the end
// (max. string length of an int32, "_ ")
Bstrncpy(ournamestart, namestart, sizeof(ournamestart));
ournamestart[sizeof(ournamestart)-1] = 0;
bflushchars(); bflushchars();
while (keystatus[0x1] == 0) while (keystatus[0x1] == 0)
{ {
@ -7842,19 +7854,22 @@ int32_t _getnumber256(const char *namestart, int32_t num, int32_t maxnumber, cha
getnumber_clearline(); getnumber_clearline();
Bsprintf(buffer,"%s%d",namestart,danum); Bsprintf(buffer,"%s%d",ournamestart,danum);
if (totalclock & 32) Bstrcat(buffer,"_ "); // max strlen now 66+11==77
if (totalclock & 32)
Bstrcat(buffer,"_ ");
// max strlen now 79
printmessage256(0, 0, buffer); printmessage256(0, 0, buffer);
if (func != NULL) if (func != NULL)
{ {
Bsprintf(buffer, "%s", (char *)func(danum)); Bsnprintf(buffer, sizeof(buffer), "%s", (char *)func(danum));
printmessage256(0, 9, buffer); printmessage256(0, 9, buffer);
} }
showframe(1); showframe(1);
if (getnumber_internal1(ch, &danum, maxnumber, sign) || if (getnumber_internal1(ch, &danum, maxnumber, sign) ||
getnumber_autocomplete(namestart, ch, &danum, flags&(1+2))) getnumber_autocomplete(ournamestart, ch, &danum, flags&(1+2)))
{ {
if (danum != oldnum) if (danum != oldnum)
asksave = 1; asksave = 1;
@ -7863,6 +7878,9 @@ int32_t _getnumber256(const char *namestart, int32_t num, int32_t maxnumber, cha
} }
} }
if (keystatus[0x1] && (flags&4))
oldnum = -1;
clearkeys(); clearkeys();
lockclock = totalclock; //Reset timing lockclock = totalclock; //Reset timing
@ -9172,7 +9190,7 @@ void _printmessage16(const char *fmt, ...)
va_list va; va_list va;
va_start(va, fmt); va_start(va, fmt);
Bvsnprintf(tmpstr, 156, fmt, va); Bvsnprintf(tmpstr, sizeof(tmpstr), fmt, va);
va_end(va); va_end(va);
i = 0; i = 0;

View file

@ -86,6 +86,7 @@ gamearray parm 8
// prints out maphack light definitions based on SE lights in map // prints out maphack light definitions based on SE lights in map
defstate printlights defstate printlights
"Print Polymer lights"
var flags var flags
print "--PRLIGHTS--" print "--PRLIGHTS--"
@ -119,6 +120,7 @@ defstate printlights
ends ends
defstate insertlights defstate insertlights
"Insert active SE lights"
var sectnum var sectnum
set k 0 set k 0
@ -204,8 +206,7 @@ defstate fiddlewithlights
ifeitherctrl mul j 10 ifeitherctrl mul j 10
switch k switch k
// "break" breaks too far or there's something wrong with the switch -- needs to be looked at case 0: break;
// case 0: break;
case 1: case 1:
{ {
set k pr_parallaxscale set k pr_parallaxscale
@ -250,7 +251,7 @@ defstate fiddlewithlights
ifeitherctrl mul j 10 ifeitherctrl mul j 10
switch k switch k
// case 0: break; case 0: break;
case 3: case 3:
{ {
set k pr_specularfactor set k pr_specularfactor
@ -500,7 +501,16 @@ defstate try_nextsector
ends ends
defstate collect_teleporting_sectors // (sec) defstate collect_teleporting_sectors // (sec)
"Collect telep. sectors"
var numsects var numsects
set numsects numsectors, sub numsects 1
ifinteractive
{
getnumberfromuser sec "starting sectnum: " numsects 8
ifl sec 0, return
}
collectsectors collectedsectors sec numsects try_nextsector collectsectors collectedsectors sec numsects try_nextsector
for i range numsects for i range numsects
sethighlightsector collectedsectors[i] 1 sethighlightsector collectedsectors[i] 1
@ -1186,6 +1196,7 @@ defstate chselshade
ends ends
defstate correctslopes defstate correctslopes
"Correct cstat&2/heinum"
for i allsectors for i allsectors
{ {
set j sector[i].ceilingstat, and j 2 set j sector[i].ceilingstat, and j 2

View file

@ -25,6 +25,7 @@ ends
// various tests of m32-script features // various tests of m32-script features
defstate arraytest defstate arraytest
"Array test"
getarraysize ar tmp getarraysize ar tmp
resizearray ar 65536 resizearray ar 65536
getticks parm[2] getticks parm[2]
@ -42,6 +43,7 @@ defstate arraytest
ends ends
defstate itertest defstate itertest
"Iteration test"
var gi gj gk var gi gj gk
// iteration and break test // iteration and break test
@ -82,6 +84,7 @@ define MIN_CONSTANT -2147483648
// tests various combinations of constants and labels // tests various combinations of constants and labels
defstate consttest defstate consttest
"Constants test"
quote " --- Constants test ---", quote " " quote " --- Constants test ---", quote " "
quote "Should be 0:" quote "Should be 0:"
@ -154,6 +157,7 @@ defstate consttest
ends ends
defstate anmtest defstate anmtest
"Sprite yoffsets"
var yo var yo
for i range MAXTILES for i range MAXTILES
@ -175,3 +179,67 @@ defstate anmtest
} }
} }
ends ends
// switch/break/default regression test, inspired by
// http://forums.duke4.net/topic/1348-mapster32-problems-and-bugs/page__view__findpost__p__101510
defstate switchtest
"'switch' test"
set i 3622
whilevarn i 3779
{
// test for many things at once:
// sorting of key values
switch i
case 3625 set j 666 /* fall-through */
default set j -1 break
case 3622 set j 3919 break
case 3626 set j -100
case 3623 set j 3685 break
case 3627 set j 1234 break
endswitch
// 'break' should always lead us here
ifle i 3627
{
qsprintf TQUOTE "j=%d" j
quote TQUOTE
}
add i 1
}
quote "----"
// same thing, slightly different syntax
set i 3622
whilevarn i 3779
{
switch i
{
case 3625 set j 666
default set j -1 break
case 3622 set j 3919 break
case 3626 set j -100
case 3623 set j 3685 break
case 3627 set j 1234 break
}
endswitch
ifle i 3627
{
qsprintf TQUOTE "j=%d" j
quote TQUOTE
}
add i 1
}
// correct output:
// j=3919
// j=3685
// j=-1
// j=-1
// j=3685
// j=1234
ends

View file

@ -9133,7 +9133,7 @@ static int32_t osdcmd_do(const osdfuncparm_t *parm)
{ {
intptr_t oscrofs; intptr_t oscrofs;
char *tp; char *tp;
int32_t i, j, slen, ofs; int32_t i, j, slen, ofs, dontsavehist;
int32_t onumconstants=g_numSavedConstants; int32_t onumconstants=g_numSavedConstants;
if (parm->numparms==0) if (parm->numparms==0)
@ -9147,6 +9147,10 @@ static int32_t osdcmd_do(const osdfuncparm_t *parm)
if (!tp) goto OUTOFMEM; if (!tp) goto OUTOFMEM;
Bmemcpy(tp, parm->raw+ofs, slen); Bmemcpy(tp, parm->raw+ofs, slen);
// explicitly typed space at beginning of command (really? not eaten by OSD
// code?) or M32script call from 'special functions' menu
dontsavehist = (slen==0 || tp[0]==' ');
// needed so that subsequent commands won't execute old stuff. // needed so that subsequent commands won't execute old stuff.
tp[slen] = '\n'; tp[slen] = '\n';
tp[slen+1] = '\0'; tp[slen+1] = '\0';
@ -9184,23 +9188,17 @@ static int32_t osdcmd_do(const osdfuncparm_t *parm)
vm.g_sp = &sprite[vm.g_i]; vm.g_sp = &sprite[vm.g_i];
} }
// If OSD is down, that would interfere with user input, so don't consider
// m32script executed from the console as 'interactive'. Which leaves only
// that from the 'special functions' menu
if (OSD_GetRowsCur() < 0)
vm.miscflags |= VMFLAG_MISC_INTERACTIVE;
VM_Execute(0); VM_Execute(0);
if (vm.updatehighlight) M32_PostScriptExec();
{
update_highlight();
vm.updatehighlight = 0;
}
if (vm.updatehighlightsector) if (!(vm.flags&VMFLAG_ERROR) && !dontsavehist)
{
update_highlightsector();
if (qsetmode != 200)
ovh_whiteoutgrab(1);
vm.updatehighlightsector = 0;
}
if (!(vm.flags&VMFLAG_ERROR))
{ {
int32_t idx, dosave=1; int32_t idx, dosave=1;
@ -12507,9 +12505,10 @@ static void GenericSpriteSearch(void)
keystatus[KEYSC_ESC] = 0; keystatus[KEYSC_ESC] = 0;
} }
// Build edit ////////// SPECIAL FUNCTIONS MENU //////////
static const char *FuncMenuStrings[] = static int32_t numMenuFunctions = 8;
static char *funcMenuStrings[8*3] =
{ {
"Replace invalid tiles", "Replace invalid tiles",
"Delete all spr of tile #", "Delete all spr of tile #",
@ -12519,38 +12518,111 @@ static const char *FuncMenuStrings[] =
"Resize selection", "Resize selection",
"Global shade divide", "Global shade divide",
"Global visibility divide" "Global visibility divide"
// dynamic menu entries start here
}; };
static ofstype funcMenuStatenum[8*2];
void registerMenuFunction(const char *funcname, int32_t stateidx)
{
char fn[25];
int32_t i;
if (funcname == NULL) // unregister stateidx
{
int32_t j;
for (i=8; i<numMenuFunctions; i++)
if (funcMenuStatenum[i-8]==stateidx)
{
Bfree(funcMenuStrings[i]);
for (j=i; j<numMenuFunctions-1; j++)
{
funcMenuStatenum[j] = funcMenuStatenum[j+1];
funcMenuStrings[j] = funcMenuStrings[j+1];
}
funcMenuStatenum[j] = 0;
funcMenuStrings[j] = NULL;
numMenuFunctions--;
break;
}
return;
}
// register menu entry named FUNCNAME to call the M32script
// state with index STATEIDX
Bstrncpy(fn, funcname, sizeof(fn));
fn[sizeof(fn)-1] = 0;
for (i=8; i<numMenuFunctions; i++)
{
if (funcMenuStatenum[i-8]==stateidx)
{
// same stateidx, different name
Bfree(funcMenuStrings[i]);
funcMenuStrings[i] = Bstrdup(fn);
return;
}
else if (!Bstrcmp(funcMenuStrings[i], fn))
{
// same name, different stateidx
funcMenuStatenum[i-8] = stateidx;
return;
}
}
if (numMenuFunctions == 3*8)
return; // max reached
funcMenuStrings[numMenuFunctions] = Bstrdup(fn);
funcMenuStatenum[numMenuFunctions-8] = stateidx;
numMenuFunctions++;
}
#define MENU_Y_SPACING 8 #define MENU_Y_SPACING 8
#define MENU_BASE_Y ydim-STATUS2DSIZ+32 #define MENU_BASE_Y ydim-STATUS2DSIZ+32
static int32_t correct_picnum(int16_t *picnumptr)
{
int32_t picnum = *picnumptr;
if ((unsigned)picnum >= MAXTILES || tilesizx[picnum] <= 0)
{
*picnumptr = 0;
return 1;
}
return 0;
}
static void FuncMenuOpts(void) static void FuncMenuOpts(void)
{ {
int32_t x = 8; int32_t x = 8;
int32_t y = MENU_BASE_Y+16; int32_t y = MENU_BASE_Y+16;
int32_t i = 0; int32_t i;
// int32_t x2 = 0;
// static int32_t x2_max = 0;
int32_t numopts = (sizeof(FuncMenuStrings)/sizeof(FuncMenuStrings[0])); for (i=0; i<numMenuFunctions; i++)
do
{ {
// x2 = if (i==8 || i==16)
printext16(x,y,editorcolors[11],editorcolors[0],FuncMenuStrings[i],0); {
// if (x2 > x2_max) x2_max = x2; x += 208;
y = MENU_BASE_Y+16;
}
printext16(x,y,editorcolors[11],editorcolors[0],funcMenuStrings[i],0);
y += MENU_Y_SPACING; y += MENU_Y_SPACING;
} }
while (++i < numopts);
// drawline16(x-1,y,x2_max+1,y,1);
// drawline16(x-1,MENU_BASE_Y-4,x-1,y,1);
// x2 = printext16(numMenuFunctions>8 ? 216 : 8, MENU_BASE_Y,
printext16(x,MENU_BASE_Y,editorcolors[11],-1,"Special functions",0); editorcolors[11], -1, "Special functions", 0);
// drawline16(x-1,MENU_BASE_Y-4,x2+1,MENU_BASE_Y-4,1);
// drawline16(x2_max+1,MENU_BASE_Y+16-4,x2_max+1,y-1,1); clearkeys();
//drawline16(x2+1,MENU_BASE_Y+16-1,x2_max+1,MENU_BASE_Y+16-1,1);
} }
static void FuncMenu(void) static void FuncMenu(void)
@ -12558,6 +12630,15 @@ static void FuncMenu(void)
char disptext[80]; char disptext[80];
int32_t col=0, row=0, rowmax=7, dispwidth = 24, editval = 0, i = -1, j; int32_t col=0, row=0, rowmax=7, dispwidth = 24, editval = 0, i = -1, j;
int32_t xpos = 8, ypos = MENU_BASE_Y+16; int32_t xpos = 8, ypos = MENU_BASE_Y+16;
int32_t crowmax[3] = {7, -1, -1};
if (numMenuFunctions > 16)
{
crowmax[2] = numMenuFunctions-16-1;
crowmax[1] = 7;
}
else if (numMenuFunctions > 8)
crowmax[1] = numMenuFunctions-8-1;
drawgradient(); drawgradient();
@ -12589,27 +12670,15 @@ static void FuncMenu(void)
row--; row--;
} }
} }
#if 0 #if 1
if (PRESSED_KEYSC(LEFT)) if (PRESSED_KEYSC(LEFT))
{ {
/* if (col == 2) if (col==1 || col==2)
{
printext16(xpos,ypos+row*8,editorcolors[11],0,disptext,0);
col = 1;
xpos = 200;
rowmax = 6;
dispwidth = 24;
disptext[dispwidth] = 0;
if (row > rowmax) row = rowmax;
}
else */
if (col == 1)
{ {
printext16(xpos,ypos+row*8,editorcolors[11],0,disptext,0); printext16(xpos,ypos+row*8,editorcolors[11],0,disptext,0);
col = 0; col--;
xpos = 8; xpos -= 208;
rowmax = 7; rowmax = crowmax[col];
dispwidth = 24;
disptext[dispwidth] = 0; disptext[dispwidth] = 0;
if (row > rowmax) row = rowmax; if (row > rowmax) row = rowmax;
} }
@ -12617,26 +12686,15 @@ static void FuncMenu(void)
if (PRESSED_KEYSC(RIGHT)) if (PRESSED_KEYSC(RIGHT))
{ {
if (col == 0) if ((col==0 || col==1) && crowmax[col+1]>=0)
{ {
printext16(xpos,ypos+row*8,editorcolors[11],0,disptext,0); printext16(xpos,ypos+row*8,editorcolors[11],0,disptext,0);
col = 1; col++;
xpos = 200; xpos += 208;
rowmax = 0; rowmax = crowmax[col];
dispwidth = 24;
disptext[dispwidth] = 0; disptext[dispwidth] = 0;
if (row > rowmax) row = rowmax; if (row > rowmax) row = rowmax;
} }
/* else if (col == 1)
{
printext16(xpos,ypos+row*8,editorcolors[11],0,disptext,0);
col = 2;
xpos = 400;
rowmax = 6;
dispwidth = 26;
disptext[dispwidth] = 0;
if (row > rowmax) row = rowmax;
} */
} }
#endif #endif
if (PRESSED_KEYSC(ENTER)) if (PRESSED_KEYSC(ENTER))
@ -12644,33 +12702,60 @@ static void FuncMenu(void)
switch (col) switch (col)
{ {
case 1:
case 2:
{
for (i=Bsnprintf(disptext,dispwidth,"%s",funcMenuStrings[col*8 + row]); i < dispwidth; i++)
disptext[i] = ' ';
if (editval)
{
char *statename = statesinfo[funcMenuStatenum[(col-1)*8 + row]].name;
int32_t snlen = Bstrlen(statename);
char *tmpscript = Bmalloc(1+5+1+snlen+1);
if (!tmpscript)
break;
tmpscript[0] = ' '; // don't save in history
Bmemcpy(&tmpscript[1], "state", 5);
tmpscript[1+5] = ' ';
Bmemcpy(&tmpscript[1+5+1], statename, snlen);
tmpscript[1+5+1+snlen] = 0;
M32RunScript(tmpscript);
Bfree(tmpscript);
if (vm.flags&VMFLAG_ERROR)
printmessage16("There were errors while executing the menu function");
else
printmessage16("Menu function executed successfully");
}
break;
}
case 0: case 0:
switch (row) switch (row)
{ {
case 0: case 0:
{ {
for (i=Bsprintf(disptext,"%s",FuncMenuStrings[row]); i < dispwidth; i++) disptext[i] = ' '; for (i=Bsprintf(disptext,"%s",funcMenuStrings[row]); i < dispwidth; i++) disptext[i] = ' ';
if (editval) if (editval)
{ {
j = 0; j = 0;
for (i=0; i<MAXSECTORS; i++) for (i=0; i<MAXSECTORS; i++)
{ {
if (tilesizx[sector[i].ceilingpicnum] <= 0) j += correct_picnum(&sector[i].ceilingpicnum);
sector[i].ceilingpicnum = 0,j++; j += correct_picnum(&sector[i].floorpicnum);
if (tilesizx[sector[i].floorpicnum] <= 0)
sector[i].floorpicnum = 0,j++;
} }
for (i=0; i<MAXWALLS; i++) for (i=0; i<MAXWALLS; i++)
{ {
if (tilesizx[wall[i].picnum] <= 0) j += correct_picnum(&wall[i].picnum);
wall[i].picnum = 0,j++; j += correct_picnum(&wall[i].overpicnum);
if (tilesizx[wall[i].overpicnum] <= 0)
wall[i].overpicnum = 0,j++;
} }
for (i=0; i<MAXSPRITES; i++) for (i=0; i<MAXSPRITES; i++)
{ {
if (tilesizx[sprite[i].picnum] <= 0) j += correct_picnum(&sprite[i].picnum);
sprite[i].picnum = 0,j++;
} }
printmessage16("Replaced %d invalid tiles",j); printmessage16("Replaced %d invalid tiles",j);
} }
@ -12678,7 +12763,7 @@ static void FuncMenu(void)
break; break;
case 1: case 1:
{ {
for (i=Bsprintf(disptext,"%s",FuncMenuStrings[row]); i < dispwidth; i++) disptext[i] = ' '; for (i=Bsprintf(disptext,"%s",funcMenuStrings[row]); i < dispwidth; i++) disptext[i] = ' ';
if (editval) if (editval)
{ {
Bsprintf(tempbuf,"Delete all sprites of tile #: "); Bsprintf(tempbuf,"Delete all sprites of tile #: ");
@ -12697,7 +12782,7 @@ static void FuncMenu(void)
break; break;
case 2: case 2:
{ {
for (i=Bsprintf(disptext,"%s",FuncMenuStrings[row]); i < dispwidth; i++) disptext[i] = ' '; for (i=Bsprintf(disptext,"%s",funcMenuStrings[row]); i < dispwidth; i++) disptext[i] = ' ';
if (editval) if (editval)
{ {
j=getnumber16("Set map sky shade: ",0,128,1); j=getnumber16("Set map sky shade: ",0,128,1);
@ -12713,7 +12798,7 @@ static void FuncMenu(void)
break; break;
case 3: case 3:
{ {
for (i=Bsprintf(disptext,"%s",FuncMenuStrings[row]); i < dispwidth; i++) disptext[i] = ' '; for (i=Bsprintf(disptext,"%s",funcMenuStrings[row]); i < dispwidth; i++) disptext[i] = ' ';
if (editval) if (editval)
{ {
j=getnumber16("Set map sky height: ",0,16777216,1); j=getnumber16("Set map sky height: ",0,16777216,1);
@ -12732,7 +12817,7 @@ static void FuncMenu(void)
break; break;
case 4: case 4:
{ {
for (i=Bsprintf(disptext,"%s",FuncMenuStrings[row]); i < dispwidth; i++) disptext[i] = ' '; for (i=Bsprintf(disptext,"%s",funcMenuStrings[row]); i < dispwidth; i++) disptext[i] = ' ';
if (editval) if (editval)
{ {
j=getnumber16("Z offset: ",0,16777216,1); j=getnumber16("Z offset: ",0,16777216,1);
@ -12753,7 +12838,7 @@ static void FuncMenu(void)
break; break;
case 5: case 5:
{ {
for (i=Bsprintf(disptext,"%s",FuncMenuStrings[row]); i < dispwidth; i++) disptext[i] = ' '; for (i=Bsprintf(disptext,"%s",funcMenuStrings[row]); i < dispwidth; i++) disptext[i] = ' ';
if (editval) if (editval)
{ {
j=getnumber16("Percentage of original: ",100,1000,0); j=getnumber16("Percentage of original: ",100,1000,0);
@ -12794,7 +12879,7 @@ static void FuncMenu(void)
break; break;
case 6: case 6:
{ {
for (i=Bsprintf(disptext,"%s",FuncMenuStrings[row]); i < dispwidth; i++) disptext[i] = ' '; for (i=Bsprintf(disptext,"%s",funcMenuStrings[row]); i < dispwidth; i++) disptext[i] = ' ';
if (editval) if (editval)
{ {
j=getnumber16("Shade divisor: ",1,128,1); j=getnumber16("Shade divisor: ",1,128,1);
@ -12817,7 +12902,7 @@ static void FuncMenu(void)
break; break;
case 7: case 7:
{ {
for (i=Bsprintf(disptext,"%s",FuncMenuStrings[row]); i < dispwidth; i++) disptext[i] = ' '; for (i=Bsprintf(disptext,"%s",funcMenuStrings[row]); i < dispwidth; i++) disptext[i] = ' ';
if (editval) if (editval)
{ {
j=getnumber16("Visibility divisor: ",1,128,0); j=getnumber16("Visibility divisor: ",1,128,0);
@ -12838,6 +12923,7 @@ static void FuncMenu(void)
} }
break; break;
} }
printext16(xpos,ypos+row*MENU_Y_SPACING,editorcolors[11],editorcolors[1],disptext,0); printext16(xpos,ypos+row*MENU_Y_SPACING,editorcolors[11],editorcolors[1],disptext,0);
showframe(1); showframe(1);

View file

@ -300,6 +300,7 @@ const char *keyw[] =
"ifaimingsprite", "ifaimingsprite",
"ifaimingwall", "ifaimingwall",
"ifaimingsector", "ifaimingsector",
"ifinteractive",
// BUILD functions // BUILD functions
"resetkey", "resetkey",
@ -359,6 +360,7 @@ const char *keyw[] =
"drawlabel", "drawlabel",
"getnumber16", "getnumber16",
"getnumber256", "getnumber256",
"getnumberfromuser",
"qsprintf", "qsprintf",
"qstrcat", "qstrcat",
"qstrcpy", "qstrcpy",
@ -953,7 +955,7 @@ static int32_t parse_integer_literal(int32_t *num)
long lnum; long lnum;
errno = 0; errno = 0;
lnum = Bstrtol(textptr, NULL, 10); lnum = Bstrtol(textptr, NULL, 10);
if (errno || (sizeof(long)>4 && (lnum<INT_MIN || lnum>INT_MAX))) if (errno || (sizeof(long)>4 && (lnum<INT32_MIN || lnum>INT32_MAX)))
{ {
C_CUSTOMERROR("integer literal exceeds bitwidth."); C_CUSTOMERROR("integer literal exceeds bitwidth.");
return 1; return 1;
@ -1828,6 +1830,29 @@ static int32_t C_ParseCommand(void)
statesinfo[j].numlocals = 0; statesinfo[j].numlocals = 0;
Bsprintf(g_szCurrentBlockName, "%s", statesinfo[j].name); Bsprintf(g_szCurrentBlockName, "%s", statesinfo[j].name);
if (C_GetKeyword() < 0)
{
ofstype *oscriptptr = g_scriptPtr;
if (C_GetNextVarOrString() == 1) // inline string
{
const char *menufuncname = (const char *)(oscriptptr+1);
registerMenuFunction(menufuncname, j);
g_scriptPtr = oscriptptr;
}
else
{
C_CUSTOMERROR("expected inline string to be used as menu name.");
return 1;
}
}
else if (j != g_stateCount)
{
// unregister that state with the menu if redefining and no menu name
registerMenuFunction(NULL, j);
}
return 0; return 0;
} }
@ -2380,7 +2405,7 @@ repeatcase:
C_CUSTOMERROR("found `default' statement when not in switch"); C_CUSTOMERROR("found `default' statement when not in switch");
return 1; return 1;
} }
if (cs.caseScriptPtr && cs.caseScriptPtr[0]!=0) if (cs.caseScriptPtr && cs.caseScriptPtr[0]!=-1)
{ {
C_CUSTOMERROR("multiple `default' statements found in switch"); C_CUSTOMERROR("multiple `default' statements found in switch");
} }
@ -2934,6 +2959,7 @@ repeatcase:
case CON_IFAIMINGSPRITE: case CON_IFAIMINGSPRITE:
case CON_IFAIMINGWALL: case CON_IFAIMINGWALL:
case CON_IFAIMINGSECTOR: case CON_IFAIMINGSECTOR:
case CON_IFINTERACTIVE:
{ {
ofstype offset; ofstype offset;
ofstype lastScriptOfs = (g_scriptPtr-script-1); ofstype lastScriptOfs = (g_scriptPtr-script-1);
@ -3272,10 +3298,13 @@ repeatcase:
case CON_GETNUMBER16: case CON_GETNUMBER16:
case CON_GETNUMBER256: case CON_GETNUMBER256:
case CON_GETNUMBERFROMUSER: // <<retvar>> "quote" <max> <flags>(1|2|4|8|(16))
C_GetNextVarType(GV_WRITABLE); C_GetNextVarType(GV_WRITABLE);
if (C_GetNextVarOrString()==-1) if (C_GetNextVarOrString()==-1)
return 1; return 1;
C_GetNextVar(); C_GetNextVar();
if (tw==CON_GETNUMBERFROMUSER)
C_GetNextVar();
return 0; return 0;
case CON_QSPRINTF: case CON_QSPRINTF:

View file

@ -56,6 +56,9 @@ extern instype *g_scriptPtr;
void C_Compile(const char *filenameortext, int32_t isfilename); void C_Compile(const char *filenameortext, int32_t isfilename);
void C_CompilationInfo(void); void C_CompilationInfo(void);
void registerMenuFunction(const char *funcname, ofstype scriptofs);
void M32_PostScriptExec(void);
typedef struct typedef struct
{ {
int32_t ofs; // offset into script[] int32_t ofs; // offset into script[]
@ -89,6 +92,19 @@ typedef struct {
extern const tokenmap_t iter_tokens[]; extern const tokenmap_t iter_tokens[];
enum vmflags
{
VMFLAG_RETURN = 1,
VMFLAG_BREAK = 2,
VMFLAG_ERROR = 4,
};
enum miscvmflags
{
VMFLAG_MISC_UPDATEHL = 1,
VMFLAG_MISC_UPDATEHLSECT = 2,
VMFLAG_MISC_INTERACTIVE = 4,
};
typedef struct { typedef struct {
int32_t g_i; int32_t g_i;
@ -97,13 +113,10 @@ typedef struct {
int32_t g_st; int32_t g_st;
spritetype *g_sp; spritetype *g_sp;
uint32_t flags; //g_errorFlag, g_returnFlag; uint32_t flags; //g_errorFlag, g_returnFlag;
uint32_t updatehighlight;
uint32_t updatehighlightsector;
} vmstate_t;
#define VMFLAG_RETURN 1 // 1:updatehighlight, 2:updatehighlightsector, 4:interactive (from menu)?
#define VMFLAG_BREAK 2 uint32_t miscflags;
#define VMFLAG_ERROR 4 } vmstate_t;
extern vmstate_t vm; extern vmstate_t vm;
extern vmstate_t vm_default; extern vmstate_t vm_default;
@ -434,6 +447,7 @@ enum ScriptKeywords_t
CON_IFAIMINGSPRITE, CON_IFAIMINGSPRITE,
CON_IFAIMINGWALL, CON_IFAIMINGWALL,
CON_IFAIMINGSECTOR, CON_IFAIMINGSECTOR,
CON_IFINTERACTIVE,
// BUILD functions // BUILD functions
CON_RESETKEY, CON_RESETKEY,
@ -495,6 +509,7 @@ enum ScriptKeywords_t
CON_DRAWLABEL, CON_DRAWLABEL,
CON_GETNUMBER16, CON_GETNUMBER16,
CON_GETNUMBER256, CON_GETNUMBER256,
CON_GETNUMBERFROMUSER,
CON_QSPRINTF, CON_QSPRINTF,
CON_QSTRCAT, CON_QSTRCAT,
CON_QSTRCPY, CON_QSTRCPY,

View file

@ -38,12 +38,11 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
vmstate_t vm; vmstate_t vm;
vmstate_t vm_default = vmstate_t vm_default =
{ {
-1, -1, // g_i
0, 0, // g_st
NULL, NULL, // g_sp
0, 0, // flags
0, 0, // miscflags
0
}; };
int32_t g_errorLineNum, g_tw; int32_t g_errorLineNum, g_tw;
@ -135,6 +134,23 @@ void VM_ScriptInfo(void)
} }
} }
void M32_PostScriptExec(void)
{
if (vm.miscflags&VMFLAG_MISC_UPDATEHL)
{
update_highlight();
vm.miscflags &= ~VMFLAG_MISC_UPDATEHL;
}
if (vm.miscflags&VMFLAG_MISC_UPDATEHLSECT)
{
update_highlightsector();
if (qsetmode != 200)
ovh_whiteoutgrab(1);
vm.miscflags &= ~VMFLAG_MISC_UPDATEHLSECT;
}
}
void VM_OnEvent(register int32_t iEventID, register int32_t iActor) void VM_OnEvent(register int32_t iEventID, register int32_t iActor)
{ {
if (iEventID < 0 || iEventID >= MAXEVENTS) if (iEventID < 0 || iEventID >= MAXEVENTS)
@ -188,19 +204,7 @@ void VM_OnEvent(register int32_t iEventID, register int32_t iActor)
message("ERROR executing %s. Event disabled.", label+(iEventID*MAXLABELLEN)); message("ERROR executing %s. Event disabled.", label+(iEventID*MAXLABELLEN));
} }
if (vm.updatehighlight) M32_PostScriptExec();
{
update_highlight();
vm.updatehighlight = 0;
}
if (vm.updatehighlightsector)
{
update_highlightsector();
if (qsetmode != 200)
ovh_whiteoutgrab(1);
vm.updatehighlightsector = 0;
}
// restore old values... // restore old values...
Bmemcpy(&vm, &vm_backup, sizeof(vmstate_t)); Bmemcpy(&vm, &vm_backup, sizeof(vmstate_t));
@ -461,6 +465,7 @@ skip_check:
// } // }
} }
insptr = (instype *)(lCodeInsPtr + lEnd); insptr = (instype *)(lCodeInsPtr + lEnd);
vm.flags &= ~VMFLAG_BREAK;
//Bsprintf(g_szBuf,"insptr=%d. ", (int32_t)insptr); AddLog(g_szBuf); //Bsprintf(g_szBuf,"insptr=%d. ", (int32_t)insptr); AddLog(g_szBuf);
//AddLog("Done Processing Switch"); //AddLog("Done Processing Switch");
continue; continue;
@ -1776,7 +1781,7 @@ badindex:
int64_t dax=Gv_GetVarX(*insptr++), day=Gv_GetVarX(*insptr++); int64_t dax=Gv_GetVarX(*insptr++), day=Gv_GetVarX(*insptr++);
int64_t hypsq = dax*dax + day*day; int64_t hypsq = dax*dax + day*day;
if (hypsq > (int64_t)INT_MAX) if (hypsq > (int64_t)INT32_MAX)
Gv_SetVarX(retvar, (int32_t)sqrt((double)hypsq)); Gv_SetVarX(retvar, (int32_t)sqrt((double)hypsq));
else else
Gv_SetVarX(retvar, ksqrt((int32_t)hypsq)); Gv_SetVarX(retvar, ksqrt((int32_t)hypsq));
@ -2204,7 +2209,7 @@ badindex:
show2dwall[index>>3] &= ~(1<<(index&7)); show2dwall[index>>3] &= ~(1<<(index&7));
} }
vm.updatehighlight = 1; vm.miscflags |= VMFLAG_MISC_UPDATEHL;
continue; continue;
} }
@ -2227,7 +2232,7 @@ badindex:
else else
hlsectorbitmap[index>>3] &= ~(1<<(index&7)); hlsectorbitmap[index>>3] &= ~(1<<(index&7));
vm.updatehighlightsector = 1; vm.miscflags |= VMFLAG_MISC_UPDATEHLSECT;
continue; continue;
} }
@ -2368,8 +2373,9 @@ badindex:
OSD_Printf("%s", ScriptQuotes[*insptr++]); OSD_Printf("%s", ScriptQuotes[*insptr++]);
continue; continue;
case CON_GETNUMBER16: case CON_GETNUMBER16: /* deprecated */
case CON_GETNUMBER256: case CON_GETNUMBER256: /* deprecated */
case CON_GETNUMBERFROMUSER:
insptr++; insptr++;
{ {
int32_t var=*insptr++, quote=*insptr++; int32_t var=*insptr++, quote=*insptr++;
@ -2378,18 +2384,24 @@ badindex:
continue; continue;
{ {
int32_t max=Gv_GetVarX(*insptr++), sign=(max<=0); int32_t max=Gv_GetVarX(*insptr++);
int32_t sign = (tw==CON_GETNUMBERFROMUSER) ? Gv_GetVarX(*insptr++) : (max<=0);
char buf[64]; // buffers in getnumber* are 80 bytes long char buf[64]; // buffers in getnumber* are 80 bytes long
// no danger of accessing unallocated memory since we took care in C_SetScriptSize() Bstrncpy(buf, quotetext, sizeof(buf));
Bmemcpy(buf, quotetext, sizeof(buf));
buf[sizeof(buf)-1]='\0'; buf[sizeof(buf)-1]='\0';
if (max==0) if (max==0)
max = INT_MAX; max = INT32_MAX;
//OSD_Printf("max:%d, sign:%d\n", max, sign); //OSD_Printf("max:%d, sign:%d\n", max, sign);
if (tw==CON_GETNUMBER16) if (tw==CON_GETNUMBERFROMUSER)
{
Gv_SetVarX(var, (qsetmode==200) ?
getnumber256(quotetext, Gv_GetVarX(var), max, sign) :
getnumber16(quotetext, Gv_GetVarX(var), max, sign));
}
else if (tw==CON_GETNUMBER16)
Gv_SetVarX(var, getnumber16(quotetext, Gv_GetVarX(var), max, sign)); Gv_SetVarX(var, getnumber16(quotetext, Gv_GetVarX(var), max, sign));
else else
Gv_SetVarX(var, getnumber256(quotetext, Gv_GetVarX(var), max, sign)); Gv_SetVarX(var, getnumber256(quotetext, Gv_GetVarX(var), max, sign));
@ -2995,6 +3007,9 @@ dodefault:
case CON_IFAIMINGSECTOR: case CON_IFAIMINGSECTOR:
VM_DoConditional(AIMING_AT_CEILING_OR_FLOOR); VM_DoConditional(AIMING_AT_CEILING_OR_FLOOR);
continue; continue;
case CON_IFINTERACTIVE:
VM_DoConditional(vm.miscflags&VMFLAG_MISC_INTERACTIVE);
continue;
case CON_GETSOUNDFLAGS: case CON_GETSOUNDFLAGS:
insptr++; insptr++;