mirror of
https://github.com/ZDoom/raze-gles.git
synced 2025-01-11 18:50:46 +00:00
Rednukem: Readd gamevars from eduke32 for WW2GI support
# Conflicts: # platform/Windows/rednukem.vcxproj # platform/Windows/rednukem.vcxproj.filters # source/rr/src/events_defs.h # source/rr/src/gamedef.h # source/rr/src/gamevars.cpp # source/rr/src/savegame.cpp
This commit is contained in:
parent
7909f29691
commit
47572cc01a
10 changed files with 912 additions and 55 deletions
|
@ -6684,6 +6684,9 @@ static void G_Cleanup(void)
|
|||
|
||||
// Xfree(MusicPtr);
|
||||
|
||||
Gv_Clear();
|
||||
|
||||
hash_free(&h_gamevars);
|
||||
hash_free(&h_labels);
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
|
||||
BEGIN_RR_NS
|
||||
|
||||
#define LINE_NUMBER (g_lineNumber << 12)
|
||||
|
||||
int32_t g_scriptVersion = 14; // 13 = 1.3D-style CON files, 14 = 1.4/1.5 style CON files
|
||||
|
||||
char g_scriptFileName[BMAX_PATH] = "(none)"; // file we're currently compiling
|
||||
|
@ -61,7 +63,11 @@ static int32_t g_numBraces = 0;
|
|||
static int32_t C_ParseCommand(int32_t loop);
|
||||
static int32_t C_SetScriptSize(int32_t size);
|
||||
|
||||
static intptr_t apScriptGameEventEnd[MAXEVENTS];
|
||||
static intptr_t g_parsingActorPtr;
|
||||
static intptr_t g_scriptEventBreakOffset;
|
||||
static intptr_t g_scriptEventChainOffset;
|
||||
static intptr_t g_scriptEventOffset;
|
||||
static char *textptr;
|
||||
|
||||
int32_t g_errorCnt,g_warningCnt;
|
||||
|
@ -99,8 +105,12 @@ static tokenmap_t const vm_keywords[] =
|
|||
{ "addammo", CON_ADDAMMO },
|
||||
{ "addinventory", CON_ADDINVENTORY },
|
||||
{ "addkills", CON_ADDKILLS },
|
||||
{ "addlog", CON_ADDLOGVAR },
|
||||
{ "addlogvar", CON_ADDLOGVAR },
|
||||
{ "addphealth", CON_ADDPHEALTH },
|
||||
{ "addstrength", CON_ADDSTRENGTH },
|
||||
{ "addvar", CON_ADDVAR },
|
||||
{ "addvarvar", CON_ADDVARVAR },
|
||||
{ "addweapon", CON_ADDWEAPON },
|
||||
{ "ai", CON_AI },
|
||||
{ "betaname", CON_BETANAME },
|
||||
|
@ -121,12 +131,14 @@ static tokenmap_t const vm_keywords[] =
|
|||
{ "destroyit", CON_DESTROYIT },
|
||||
{ "else", CON_ELSE },
|
||||
{ "enda", CON_ENDA },
|
||||
{ "endevent", CON_ENDEVENT },
|
||||
{ "endofgame", CON_ENDOFGAME },
|
||||
{ "ends", CON_ENDS },
|
||||
{ "fakebubba", CON_FAKEBUBBA },
|
||||
{ "fall", CON_FALL },
|
||||
{ "feathers", CON_MAIL },
|
||||
{ "gamestartup", CON_GAMESTARTUP },
|
||||
{ "gamevar", CON_GAMEVAR },
|
||||
{ "garybanjo", CON_GARYBANJO },
|
||||
{ "getlastpal", CON_GETLASTPAL },
|
||||
{ "globalsound", CON_GLOBALSOUND },
|
||||
|
@ -185,6 +197,12 @@ static tokenmap_t const vm_keywords[] =
|
|||
{ "ifsquished", CON_IFSQUISHED },
|
||||
{ "ifstrength", CON_IFSTRENGTH },
|
||||
{ "iftipcow", CON_IFTIPCOW },
|
||||
{ "ifvare", CON_IFVARE },
|
||||
{ "ifvarg", CON_IFVARG },
|
||||
{ "ifvarl", CON_IFVARL },
|
||||
{ "ifvarvare", CON_IFVARVARE },
|
||||
{ "ifvarvarg", CON_IFVARVARG },
|
||||
{ "ifvarvarl", CON_IFVARVARL },
|
||||
{ "ifwasweapon", CON_IFWASWEAPON },
|
||||
{ "ifwind", CON_IFWIND },
|
||||
{ "include", CON_INCLUDE },
|
||||
|
@ -205,6 +223,7 @@ static tokenmap_t const vm_keywords[] =
|
|||
{ "music", CON_MUSIC },
|
||||
{ "newpic", CON_NEWPIC },
|
||||
{ "nullop", CON_NULLOP },
|
||||
{ "onevent", CON_ONEVENT },
|
||||
{ "operate", CON_OPERATE },
|
||||
{ "palfrom", CON_PALFROM },
|
||||
{ "paper", CON_PAPER },
|
||||
|
@ -216,6 +235,8 @@ static tokenmap_t const vm_keywords[] =
|
|||
{ "resetplayer", CON_RESETPLAYER },
|
||||
{ "respawnhitag", CON_RESPAWNHITAG },
|
||||
{ "rndmove", CON_RNDMOVE },
|
||||
{ "setvar", CON_SETVAR },
|
||||
{ "setvarvar", CON_SETVARVAR },
|
||||
{ "sizeat", CON_SIZEAT },
|
||||
{ "sizeto", CON_SIZETO },
|
||||
{ "slapplayer", CON_SLAPPLAYER },
|
||||
|
@ -243,6 +264,22 @@ static tokenmap_t const vm_keywords[] =
|
|||
{ "}", CON_RIGHTBRACE },
|
||||
};
|
||||
|
||||
static const vec2_t varvartable[] =
|
||||
{
|
||||
{ CON_IFVARVARE, CON_IFVARE },
|
||||
{ CON_IFVARVARG, CON_IFVARG },
|
||||
{ CON_IFVARVARL, CON_IFVARL },
|
||||
|
||||
{ CON_ADDVARVAR, CON_ADDVAR },
|
||||
{ CON_SETVARVAR, CON_SETVAR },
|
||||
};
|
||||
|
||||
static inthashtable_t h_varvar = { NULL, INTHASH_SIZE(ARRAY_SIZE(varvartable)) };
|
||||
|
||||
static inthashtable_t *const inttables[] = {
|
||||
&h_varvar,
|
||||
};
|
||||
|
||||
char const * VM_GetKeywordForID(int32_t id)
|
||||
{
|
||||
// could be better but this is only called for diagnostics, ayy lmao
|
||||
|
@ -258,12 +295,13 @@ char *bitptr; // pointer to bitmap of which bytecode positions contain pointers
|
|||
#define BITPTR_CLEAR(x) (bitptr[(x)>>3] &= ~(1<<((x)&7)))
|
||||
#define BITPTR_IS_POINTER(x) (bitptr[(x)>>3] & (1<<((x) &7)))
|
||||
|
||||
hashtable_t h_labels = { 11264>>1, NULL };
|
||||
hashtable_t h_gamevars = { MAXGAMEVARS >> 1, NULL };
|
||||
hashtable_t h_labels = { 11264>>1, NULL };
|
||||
|
||||
static hashtable_t h_keywords = { CON_END>>1, NULL };;
|
||||
|
||||
static hashtable_t * const tables[] = {
|
||||
&h_labels, &h_keywords
|
||||
&h_labels, &h_keywords, &h_gamevars
|
||||
};
|
||||
|
||||
static hashtable_t * const tables_free [] = {
|
||||
|
@ -276,8 +314,14 @@ void C_InitHashes()
|
|||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i=0; i < ARRAY_SIZE(tables); i++)
|
||||
hash_init(tables[i]);
|
||||
for (auto table : tables)
|
||||
hash_init(table);
|
||||
|
||||
for (auto table : inttables)
|
||||
inthash_init(table);
|
||||
|
||||
for (auto &varvar : varvartable)
|
||||
inthash_add(&h_varvar, varvar.x, varvar.y, 0);
|
||||
|
||||
//inithashnames();
|
||||
initsoundhashnames();
|
||||
|
@ -290,7 +334,7 @@ void C_InitHashes()
|
|||
|
||||
// "magic" number for { and }, overrides line number in compiled code for later detection
|
||||
#define IFELSE_MAGIC 31337
|
||||
static int32_t g_ifElseAborted;
|
||||
static int32_t g_skipBranch;
|
||||
|
||||
static int32_t C_SetScriptSize(int32_t newsize)
|
||||
{
|
||||
|
@ -458,6 +502,9 @@ static int32_t C_SkipComments(void)
|
|||
while (1);
|
||||
}
|
||||
|
||||
static inline int GetDefID(char const *label) { return hash_find(&h_gamevars, label); }
|
||||
|
||||
#define LAST_LABEL (label+(g_labelCnt<<6))
|
||||
static inline int32_t isaltok(const char c)
|
||||
{
|
||||
return (isalnum(c) || c == '{' || c == '}' || c == '/' || c == '\\' || c == '*' || c == '-' || c == '_' ||
|
||||
|
@ -502,6 +549,25 @@ static void C_GetNextLabelName(void)
|
|||
initprintf("%s:%d: debug: label `%s'.\n",g_scriptFileName,g_lineNumber,label+(g_labelCnt<<6));
|
||||
}
|
||||
|
||||
static inline void scriptWriteValue(int32_t const value)
|
||||
{
|
||||
BITPTR_CLEAR(g_scriptPtr-apScript);
|
||||
*g_scriptPtr++ = value;
|
||||
}
|
||||
|
||||
// addresses passed to these functions must be within the block of memory pointed to by apScript
|
||||
static inline void scriptWriteAtOffset(int32_t const value, intptr_t * const addr)
|
||||
{
|
||||
BITPTR_CLEAR(addr-apScript);
|
||||
*(addr) = value;
|
||||
}
|
||||
|
||||
static inline void scriptWritePointer(intptr_t const value, intptr_t * const addr)
|
||||
{
|
||||
BITPTR_SET(addr-apScript);
|
||||
*(addr) = value;
|
||||
}
|
||||
|
||||
static int32_t C_GetKeyword(void)
|
||||
{
|
||||
int32_t i;
|
||||
|
@ -549,12 +615,10 @@ static int32_t C_GetNextKeyword(void) //Returns its code #
|
|||
if (EDUKE32_PREDICT_TRUE((i = hash_find(&h_keywords,tempbuf)) >= 0))
|
||||
{
|
||||
if (i == CON_LEFTBRACE || i == CON_RIGHTBRACE || i == CON_NULLOP)
|
||||
*g_scriptPtr = i + (IFELSE_MAGIC<<12);
|
||||
else *g_scriptPtr = i + (g_lineNumber<<12);
|
||||
scriptWriteValue(i | (VM_IFELSE_MAGIC<<12));
|
||||
else scriptWriteValue(i | LINE_NUMBER);
|
||||
|
||||
BITPTR_CLEAR(g_scriptPtr-apScript);
|
||||
textptr += l;
|
||||
g_scriptPtr++;
|
||||
|
||||
if (!(g_errorCnt || g_warningCnt) && g_scriptDebug)
|
||||
initprintf("%s:%d: debug: keyword `%s'.\n", g_scriptFileName, g_lineNumber, tempbuf);
|
||||
|
@ -620,6 +684,115 @@ static int32_t parse_hex_constant(const char *hexnum)
|
|||
return x;
|
||||
}
|
||||
|
||||
static void C_GetNextVarType(int32_t type)
|
||||
{
|
||||
int32_t id = 0;
|
||||
int32_t flags = 0;
|
||||
|
||||
auto varptr = g_scriptPtr;
|
||||
|
||||
C_SkipComments();
|
||||
|
||||
if (!type && !g_labelsOnly && (isdigit(*textptr) || ((*textptr == '-') && (isdigit(*(textptr+1))))))
|
||||
{
|
||||
scriptWriteValue(GV_FLAG_CONSTANT);
|
||||
|
||||
if (tolower(textptr[1])=='x') // hex constants
|
||||
scriptWriteValue(parse_hex_constant(textptr+2));
|
||||
else
|
||||
scriptWriteValue(parse_decimal_number());
|
||||
|
||||
if (!(g_errorCnt || g_warningCnt) && g_scriptDebug)
|
||||
initprintf("%s:%d: debug: constant %ld in place of gamevar.\n", g_scriptFileName, g_lineNumber, (long)(g_scriptPtr[-1]));
|
||||
#if 1
|
||||
while (!ispecial(*textptr) && *textptr != ']') textptr++;
|
||||
#else
|
||||
C_GetNextLabelName();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
else if (*textptr == '-'/* && !isdigit(*(textptr+1))*/)
|
||||
{
|
||||
if (EDUKE32_PREDICT_FALSE(type))
|
||||
{
|
||||
g_errorCnt++;
|
||||
C_ReportError(ERROR_SYNTAXERROR);
|
||||
C_GetNextLabelName();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(g_errorCnt || g_warningCnt) && g_scriptDebug)
|
||||
initprintf("%s:%d: debug: flagging gamevar as negative.\n", g_scriptFileName, g_lineNumber); //,Batol(textptr));
|
||||
|
||||
flags = GV_FLAG_NEGATIVE;
|
||||
textptr++;
|
||||
}
|
||||
|
||||
C_GetNextLabelName();
|
||||
|
||||
if (EDUKE32_PREDICT_FALSE(hash_find(&h_keywords,LAST_LABEL)>=0))
|
||||
{
|
||||
g_errorCnt++;
|
||||
C_ReportError(ERROR_ISAKEYWORD);
|
||||
return;
|
||||
}
|
||||
|
||||
C_SkipComments();
|
||||
|
||||
id=GetDefID(LAST_LABEL);
|
||||
if (id<0) //gamevar not found
|
||||
{
|
||||
if (EDUKE32_PREDICT_TRUE(!type && !g_labelsOnly))
|
||||
{
|
||||
//try looking for a define instead
|
||||
Bstrcpy(tempbuf,LAST_LABEL);
|
||||
id = hash_find(&h_labels,tempbuf);
|
||||
|
||||
if (EDUKE32_PREDICT_TRUE(id>=0 && labeltype[id] & LABEL_DEFINE))
|
||||
{
|
||||
if (!(g_errorCnt || g_warningCnt) && g_scriptDebug)
|
||||
initprintf("%s:%d: debug: label `%s' in place of gamevar.\n",g_scriptFileName,g_lineNumber,label+(id<<6));
|
||||
|
||||
scriptWriteValue(GV_FLAG_CONSTANT);
|
||||
scriptWriteValue(labelcode[id]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
g_errorCnt++;
|
||||
C_ReportError(ERROR_NOTAGAMEVAR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (EDUKE32_PREDICT_FALSE(type == GAMEVAR_READONLY && aGameVars[id].flags & GAMEVAR_READONLY))
|
||||
{
|
||||
g_errorCnt++;
|
||||
C_ReportError(ERROR_VARREADONLY);
|
||||
return;
|
||||
}
|
||||
else if (EDUKE32_PREDICT_FALSE(aGameVars[id].flags & type))
|
||||
{
|
||||
g_errorCnt++;
|
||||
C_ReportError(ERROR_VARTYPEMISMATCH);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_scriptDebug > 1 && !g_errorCnt && !g_warningCnt)
|
||||
initprintf("%s:%d: debug: gamevar `%s'.\n",g_scriptFileName,g_lineNumber,LAST_LABEL);
|
||||
|
||||
scriptWriteValue(id|flags);
|
||||
}
|
||||
|
||||
#define C_GetNextVar() C_GetNextVarType(0)
|
||||
|
||||
static FORCE_INLINE void C_GetManyVarsType(int32_t type, int num)
|
||||
{
|
||||
for (; num>0; --num)
|
||||
C_GetNextVarType(type);
|
||||
}
|
||||
|
||||
#define C_GetManyVars(num) C_GetManyVarsType(0,num)
|
||||
|
||||
// returns:
|
||||
// -1 on EOF or wrong type or error
|
||||
// 0 if literal value
|
||||
|
@ -742,7 +915,7 @@ static int32_t C_CheckMalformedBranch(intptr_t lastScriptPtr)
|
|||
case CON_ENDS:
|
||||
case CON_ELSE:
|
||||
g_scriptPtr = lastScriptPtr + &apScript[0];
|
||||
g_ifElseAborted = 1;
|
||||
g_skipBranch = 1;
|
||||
C_ReportError(-1);
|
||||
g_warningCnt++;
|
||||
initprintf("%s:%d: warning: malformed `%s' branch\n",g_scriptFileName,g_lineNumber,
|
||||
|
@ -759,14 +932,14 @@ static int32_t C_CheckEmptyBranch(int32_t tw, intptr_t lastScriptPtr)
|
|||
tw == CON_IFRND || tw == CON_IFHITWEAPON || tw == CON_IFCANSEE || tw == CON_IFCANSEETARGET ||
|
||||
tw == CON_IFPDISTL || tw == CON_IFPDISTG || tw == CON_IFGOTWEAPONCE)
|
||||
{
|
||||
g_ifElseAborted = 0;
|
||||
g_skipBranch = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((*(g_scriptPtr) & VM_INSTMASK) != CON_NULLOP || *(g_scriptPtr)>>12 != IFELSE_MAGIC)
|
||||
g_ifElseAborted = 0;
|
||||
g_skipBranch = 0;
|
||||
|
||||
if (EDUKE32_PREDICT_FALSE(g_ifElseAborted))
|
||||
if (EDUKE32_PREDICT_FALSE(g_skipBranch))
|
||||
{
|
||||
C_ReportError(-1);
|
||||
g_warningCnt++;
|
||||
|
@ -942,6 +1115,22 @@ static inline void C_FinishBitOr(int32_t value)
|
|||
*g_scriptPtr++ = value;
|
||||
}
|
||||
|
||||
static void scriptUpdateOpcodeForVariableType(intptr_t *ins)
|
||||
{
|
||||
int opcode = -1;
|
||||
|
||||
if (opcode != -1)
|
||||
{
|
||||
if (g_scriptDebug > 1 && !g_errorCnt && !g_warningCnt)
|
||||
{
|
||||
initprintf("%s:%d: %s -> %s for var %s\n", g_scriptFileName, g_lineNumber,
|
||||
VM_GetKeywordForID(*ins & VM_INSTMASK), VM_GetKeywordForID(opcode), aGameVars[ins[1] & (MAXGAMEVARS-1)].szLabel);
|
||||
}
|
||||
|
||||
scriptWriteAtOffset(opcode | LINE_NUMBER, ins);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t C_ParseCommand(int32_t loop)
|
||||
{
|
||||
int32_t i, j=0, k=0, tw;
|
||||
|
@ -1042,6 +1231,60 @@ static int32_t C_ParseCommand(int32_t loop)
|
|||
}
|
||||
continue;
|
||||
|
||||
case CON_GAMEVAR:
|
||||
{
|
||||
// syntax: gamevar <var1> <initial value> <flags>
|
||||
// defines var1 and sets initial value.
|
||||
// flags are used to define usage
|
||||
// (see top of this files for flags)
|
||||
|
||||
if (EDUKE32_PREDICT_FALSE(isdigit(*textptr) || (*textptr == '-')))
|
||||
{
|
||||
g_errorCnt++;
|
||||
C_ReportError(ERROR_SYNTAXERROR);
|
||||
C_NextLine();
|
||||
continue;
|
||||
}
|
||||
|
||||
g_scriptPtr--;
|
||||
|
||||
C_GetNextLabelName();
|
||||
|
||||
if (EDUKE32_PREDICT_FALSE(hash_find(&h_keywords, LAST_LABEL)>=0))
|
||||
{
|
||||
g_warningCnt++;
|
||||
C_ReportError(WARNING_VARMASKSKEYWORD);
|
||||
hash_delete(&h_keywords, LAST_LABEL);
|
||||
}
|
||||
|
||||
int32_t defaultValue = 0;
|
||||
int32_t varFlags = 0;
|
||||
|
||||
if (C_GetKeyword() == -1)
|
||||
{
|
||||
C_GetNextValue(LABEL_DEFINE); // get initial value
|
||||
defaultValue = *(--g_scriptPtr);
|
||||
|
||||
j = 0;
|
||||
|
||||
while (C_GetKeyword() == -1)
|
||||
C_BitOrNextValue(&j);
|
||||
|
||||
C_FinishBitOr(j);
|
||||
varFlags = *(--g_scriptPtr);
|
||||
|
||||
if (EDUKE32_PREDICT_FALSE((*(g_scriptPtr)&GAMEVAR_USER_MASK)==(GAMEVAR_PERPLAYER|GAMEVAR_PERACTOR)))
|
||||
{
|
||||
g_warningCnt++;
|
||||
varFlags ^= GAMEVAR_PERPLAYER;
|
||||
C_ReportError(WARNING_BADGAMEVAR);
|
||||
}
|
||||
}
|
||||
|
||||
Gv_NewVar(LAST_LABEL, defaultValue, varFlags);
|
||||
continue;
|
||||
}
|
||||
|
||||
case CON_DEFINE:
|
||||
{
|
||||
C_GetNextLabelName();
|
||||
|
@ -1461,6 +1704,54 @@ static int32_t C_ParseCommand(int32_t loop)
|
|||
g_checkingIfElse = 0;
|
||||
continue;
|
||||
|
||||
case CON_ONEVENT:
|
||||
if (EDUKE32_PREDICT_FALSE(g_processingState || g_parsingActorPtr))
|
||||
{
|
||||
C_ReportError(ERROR_FOUNDWITHIN);
|
||||
g_errorCnt++;
|
||||
}
|
||||
|
||||
g_numBraces = 0;
|
||||
g_scriptPtr--;
|
||||
g_scriptEventOffset = g_parsingActorPtr = g_scriptPtr - apScript;
|
||||
|
||||
C_SkipComments();
|
||||
j = 0;
|
||||
while (isaltok(*(textptr+j)))
|
||||
{
|
||||
g_szCurrentBlockName[j] = textptr[j];
|
||||
j++;
|
||||
}
|
||||
g_szCurrentBlockName[j] = 0;
|
||||
// g_labelsOnly = 1;
|
||||
C_GetNextValue(LABEL_EVENT);
|
||||
g_labelsOnly = 0;
|
||||
g_scriptPtr--;
|
||||
j= *g_scriptPtr; // type of event
|
||||
g_currentEvent = j;
|
||||
//Bsprintf(g_szBuf,"Adding Event for %d at %lX",j, g_parsingEventPtr);
|
||||
//AddLog(g_szBuf);
|
||||
if (EDUKE32_PREDICT_FALSE((unsigned)j > MAXEVENTS-1))
|
||||
{
|
||||
initprintf("%s:%d: error: invalid event ID.\n",g_scriptFileName,g_lineNumber);
|
||||
g_errorCnt++;
|
||||
continue;
|
||||
}
|
||||
// if event has already been declared then store previous script location
|
||||
if (!apScriptEvents[j])
|
||||
{
|
||||
apScriptEvents[j] = g_scriptEventOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_scriptEventChainOffset = apScriptEvents[j];
|
||||
apScriptEvents[j] = g_scriptEventOffset;
|
||||
}
|
||||
|
||||
g_checkingIfElse = 0;
|
||||
|
||||
continue;
|
||||
|
||||
case CON_CSTAT:
|
||||
C_GetNextValue(LABEL_DEFINE);
|
||||
|
||||
|
@ -1551,7 +1842,7 @@ static int32_t C_ParseCommand(int32_t loop)
|
|||
|
||||
intptr_t const lastScriptPtr = g_scriptPtr - apScript - 1;
|
||||
|
||||
g_ifElseAborted = 0;
|
||||
g_skipBranch = 0;
|
||||
g_checkingIfElse--;
|
||||
|
||||
if (C_CheckMalformedBranch(lastScriptPtr))
|
||||
|
@ -1573,6 +1864,143 @@ static int32_t C_ParseCommand(int32_t loop)
|
|||
|
||||
continue;
|
||||
}
|
||||
case CON_ADDLOGVAR:
|
||||
g_labelsOnly = 1;
|
||||
C_GetNextVar();
|
||||
g_labelsOnly = 0;
|
||||
continue;
|
||||
case CON_ADDVAR:
|
||||
case CON_SETVAR:
|
||||
setvar:
|
||||
{
|
||||
auto ins = &g_scriptPtr[-1];
|
||||
|
||||
C_GetNextVarType(GAMEVAR_READONLY);
|
||||
C_GetNextValue(LABEL_DEFINE);
|
||||
// replace instructions with special versions for specific var types
|
||||
scriptUpdateOpcodeForVariableType(ins);
|
||||
continue;
|
||||
}
|
||||
case CON_ADDVARVAR:
|
||||
case CON_SETVARVAR:
|
||||
{
|
||||
setvarvar:
|
||||
auto ins = &g_scriptPtr[-1];
|
||||
auto tptr = textptr;
|
||||
int const lnum = g_lineNumber;
|
||||
|
||||
C_GetNextVarType(GAMEVAR_READONLY);
|
||||
C_GetNextVar();
|
||||
|
||||
int const opcode = inthash_find(&h_varvar, *ins & VM_INSTMASK);
|
||||
|
||||
if (ins[2] == GV_FLAG_CONSTANT && opcode != -1)
|
||||
{
|
||||
if (g_scriptDebug > 1 && !g_errorCnt && !g_warningCnt)
|
||||
{
|
||||
initprintf("%s:%d: %s -> %s\n", g_scriptFileName, g_lineNumber,
|
||||
VM_GetKeywordForID(*ins & VM_INSTMASK), VM_GetKeywordForID(opcode));
|
||||
}
|
||||
|
||||
tw = opcode;
|
||||
scriptWriteAtOffset(opcode | LINE_NUMBER, ins);
|
||||
g_scriptPtr = &ins[1];
|
||||
textptr = tptr;
|
||||
g_lineNumber = lnum;
|
||||
goto setvar;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
case CON_IFVARVARE:
|
||||
case CON_IFVARVARG:
|
||||
case CON_IFVARVARL:
|
||||
{
|
||||
auto const ins = &g_scriptPtr[-1];
|
||||
auto const lastScriptPtr = &g_scriptPtr[-1] - apScript;
|
||||
auto const lasttextptr = textptr;
|
||||
int const lnum = g_lineNumber;
|
||||
|
||||
g_skipBranch = false;
|
||||
|
||||
C_GetNextVar();
|
||||
auto const var = g_scriptPtr;
|
||||
C_GetNextVar();
|
||||
|
||||
if (*var == GV_FLAG_CONSTANT)
|
||||
{
|
||||
int const opcode = inthash_find(&h_varvar, tw);
|
||||
|
||||
if (opcode != -1)
|
||||
{
|
||||
if (g_scriptDebug > 1 && !g_errorCnt && !g_warningCnt)
|
||||
{
|
||||
initprintf("%s:%d: replacing %s with %s\n", g_scriptFileName, g_lineNumber,
|
||||
VM_GetKeywordForID(*ins & VM_INSTMASK), VM_GetKeywordForID(opcode));
|
||||
}
|
||||
|
||||
scriptWriteAtOffset(opcode | LINE_NUMBER, ins);
|
||||
tw = opcode;
|
||||
g_scriptPtr = &ins[1];
|
||||
textptr = lasttextptr;
|
||||
g_lineNumber = lnum;
|
||||
goto ifvar;
|
||||
}
|
||||
}
|
||||
|
||||
if (C_CheckMalformedBranch(lastScriptPtr))
|
||||
continue;
|
||||
|
||||
auto const offset = g_scriptPtr - apScript;
|
||||
g_scriptPtr++; // Leave a spot for the fail location
|
||||
|
||||
C_ParseCommand(0);
|
||||
|
||||
if (C_CheckEmptyBranch(tw, lastScriptPtr))
|
||||
continue;
|
||||
|
||||
auto const tempscrptr = apScript + offset;
|
||||
scriptWritePointer((intptr_t)g_scriptPtr, tempscrptr);
|
||||
continue;
|
||||
}
|
||||
|
||||
case CON_IFVARE:
|
||||
case CON_IFVARG:
|
||||
case CON_IFVARL:
|
||||
{
|
||||
ifvar:
|
||||
auto const ins = &g_scriptPtr[-1];
|
||||
auto const lastScriptPtr = &g_scriptPtr[-1] - apScript;
|
||||
|
||||
g_skipBranch = false;
|
||||
|
||||
C_GetNextVar();
|
||||
C_GetNextValue(LABEL_DEFINE);
|
||||
|
||||
if (C_CheckMalformedBranch(lastScriptPtr))
|
||||
continue;
|
||||
|
||||
scriptUpdateOpcodeForVariableType(ins);
|
||||
|
||||
auto const offset = g_scriptPtr - apScript;
|
||||
g_scriptPtr++; //Leave a spot for the fail location
|
||||
|
||||
C_ParseCommand(0);
|
||||
|
||||
if (C_CheckEmptyBranch(tw, lastScriptPtr))
|
||||
continue;
|
||||
|
||||
auto const tempscrptr = apScript + offset;
|
||||
scriptWritePointer((intptr_t)g_scriptPtr, tempscrptr);
|
||||
|
||||
j = C_GetKeyword();
|
||||
|
||||
if (j == CON_ELSE)
|
||||
g_checkingIfElse++;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
case CON_IFRND:
|
||||
case CON_IFPDISTL:
|
||||
|
@ -1603,7 +2031,7 @@ static int32_t C_ParseCommand(int32_t loop)
|
|||
intptr_t offset;
|
||||
intptr_t lastScriptPtr = (g_scriptPtr-&apScript[0]-1);
|
||||
|
||||
g_ifElseAborted = 0;
|
||||
g_skipBranch = 0;
|
||||
|
||||
switch (tw)
|
||||
{
|
||||
|
@ -1696,7 +2124,7 @@ static int32_t C_ParseCommand(int32_t loop)
|
|||
intptr_t offset;
|
||||
intptr_t lastScriptPtr = (g_scriptPtr-&apScript[0]-1);
|
||||
|
||||
g_ifElseAborted = 0;
|
||||
g_skipBranch = 0;
|
||||
|
||||
if (C_CheckMalformedBranch(lastScriptPtr))
|
||||
continue;
|
||||
|
@ -1745,8 +2173,8 @@ static int32_t C_ParseCommand(int32_t loop)
|
|||
g_scriptPtr -= 2;
|
||||
|
||||
if (C_GetKeyword() != CON_ELSE && (*(g_scriptPtr-2) & VM_INSTMASK) != CON_ELSE)
|
||||
g_ifElseAborted = 1;
|
||||
else g_ifElseAborted = 0;
|
||||
g_skipBranch = 1;
|
||||
else g_skipBranch = 0;
|
||||
|
||||
j = C_GetKeyword();
|
||||
|
||||
|
@ -2076,7 +2504,7 @@ static int32_t C_ParseCommand(int32_t loop)
|
|||
g_warningCnt++;
|
||||
initprintf("%s:%d: warning: `nullop' found without `else'\n",g_scriptFileName,g_lineNumber);
|
||||
g_scriptPtr--;
|
||||
g_ifElseAborted = 1;
|
||||
g_skipBranch = 1;
|
||||
}
|
||||
continue;
|
||||
|
||||
|
@ -2190,6 +2618,9 @@ void C_PrintStats(void)
|
|||
|
||||
void C_Compile(const char *fileName)
|
||||
{
|
||||
Bmemset(apScriptEvents, 0, sizeof(apScriptEvents));
|
||||
Bmemset(apScriptGameEventEnd, 0, sizeof(apScriptGameEventEnd));
|
||||
|
||||
for (int i=0; i<MAXTILES; i++)
|
||||
{
|
||||
Bmemset(&g_tile[i], 0, sizeof(tiledata_t));
|
||||
|
@ -2197,6 +2628,7 @@ void C_Compile(const char *fileName)
|
|||
}
|
||||
|
||||
C_InitHashes();
|
||||
Gv_Init();
|
||||
|
||||
auto kFile = fileSystem.OpenFileReader(fileName,0);
|
||||
|
||||
|
@ -2312,15 +2744,33 @@ void C_ReportError(int32_t iError)
|
|||
case ERROR_OPENBRACKET:
|
||||
initprintf("%s:%d: error: found more `{' than `}' before `%s'.\n",g_scriptFileName,g_lineNumber,tempbuf);
|
||||
break;
|
||||
case ERROR_NOTAGAMEVAR:
|
||||
initprintf("%s:%d: error: symbol `%s' is not a variable.\n",g_scriptFileName,g_lineNumber,LAST_LABEL);
|
||||
break;
|
||||
case ERROR_PARAMUNDEFINED:
|
||||
initprintf("%s:%d: error: parameter `%s' is undefined.\n",g_scriptFileName,g_lineNumber,tempbuf);
|
||||
break;
|
||||
case ERROR_SYNTAXERROR:
|
||||
initprintf("%s:%d: error: syntax error.\n",g_scriptFileName,g_lineNumber);
|
||||
break;
|
||||
case ERROR_VARREADONLY:
|
||||
initprintf("%s:%d: error: variable `%s' is read-only.\n",g_scriptFileName,g_lineNumber,LAST_LABEL);
|
||||
break;
|
||||
case ERROR_VARTYPEMISMATCH:
|
||||
initprintf("%s:%d: error: variable `%s' is of the wrong type.\n",g_scriptFileName,g_lineNumber,LAST_LABEL);
|
||||
break;
|
||||
case WARNING_BADGAMEVAR:
|
||||
initprintf("%s:%d: warning: variable `%s' should be either per-player OR per-actor, not both.\n",g_scriptFileName,g_lineNumber,LAST_LABEL);
|
||||
break;
|
||||
case WARNING_DUPLICATEDEFINITION:
|
||||
initprintf("%s:%d: warning: duplicate definition `%s' ignored.\n",g_scriptFileName,g_lineNumber,LAST_LABEL);
|
||||
break;
|
||||
case WARNING_LABELSONLY:
|
||||
initprintf("%s:%d: warning: expected a label, found a constant.\n",g_scriptFileName,g_lineNumber);
|
||||
break;
|
||||
case WARNING_VARMASKSKEYWORD:
|
||||
initprintf("%s:%d: warning: variable `%s' masks keyword.\n", g_scriptFileName, g_lineNumber, LAST_LABEL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,12 +40,16 @@ enum
|
|||
LABEL_ACTION = 8,
|
||||
LABEL_AI = 16,
|
||||
LABEL_MOVE = 32,
|
||||
LABEL_EVENT = 0x40,
|
||||
};
|
||||
|
||||
#define LABEL_HASPARM2 1
|
||||
#define LABEL_ISSTRING 2
|
||||
|
||||
// "magic" number for { and }, overrides line number in compiled code for later detection
|
||||
#define VM_IFELSE_MAGIC 31337
|
||||
#define VM_INSTMASK 0xfff
|
||||
#define VM_DECODE_LINE_NUMBER(xxx) ((int)((xxx) >> 12))
|
||||
|
||||
#define C_CUSTOMERROR(Text, ...) \
|
||||
do \
|
||||
|
@ -66,8 +70,19 @@ enum
|
|||
extern intptr_t const * insptr;
|
||||
extern void VM_ScriptInfo(intptr_t const *ptr, int range);
|
||||
|
||||
extern hashtable_t h_gamevars;
|
||||
extern hashtable_t h_labels;
|
||||
|
||||
extern int32_t g_aimAngleVarID; // var ID of "AUTOAIMANGLE"
|
||||
extern int32_t g_angRangeVarID; // var ID of "ANGRANGE"
|
||||
extern int32_t g_returnVarID; // var ID of "RETURN"
|
||||
extern int32_t g_weaponVarID; // var ID of "WEAPON"
|
||||
extern int32_t g_worksLikeVarID; // var ID of "WORKSLIKE"
|
||||
extern int32_t g_zRangeVarID; // var ID of "ZRANGE"
|
||||
|
||||
#include "events_defs.h"
|
||||
extern intptr_t apScriptEvents[MAXEVENTS];
|
||||
|
||||
extern char g_scriptFileName[BMAX_PATH];
|
||||
|
||||
extern const uint32_t CheatFunctionFlags[];
|
||||
|
@ -151,9 +166,15 @@ enum ScriptError_t
|
|||
ERROR_FOUNDWITHIN,
|
||||
ERROR_ISAKEYWORD,
|
||||
ERROR_OPENBRACKET,
|
||||
ERROR_NOTAGAMEVAR,
|
||||
ERROR_PARAMUNDEFINED,
|
||||
ERROR_SYNTAXERROR,
|
||||
WARNING_LABELSONLY
|
||||
ERROR_VARREADONLY,
|
||||
ERROR_VARTYPEMISMATCH,
|
||||
WARNING_BADGAMEVAR,
|
||||
WARNING_DUPLICATEDEFINITION,
|
||||
WARNING_LABELSONLY,
|
||||
WARNING_VARMASKSKEYWORD,
|
||||
};
|
||||
|
||||
enum ScriptKeywords_t
|
||||
|
@ -306,6 +327,20 @@ enum ScriptKeywords_t
|
|||
CON_MOTOLOOPSND, // 145
|
||||
CON_IFSIZEDOWN, // 146
|
||||
CON_RNDMOVE, // 147
|
||||
CON_GAMEVAR, // 148
|
||||
CON_IFVARL, // 149
|
||||
CON_IFVARG, // 150
|
||||
CON_SETVARVAR, // 151
|
||||
CON_SETVAR, // 152
|
||||
CON_ADDVARVAR, // 153
|
||||
CON_ADDVAR, // 154
|
||||
CON_IFVARVARL, // 155
|
||||
CON_IFVARVARG, // 156
|
||||
CON_ADDLOGVAR, // 157
|
||||
CON_ONEVENT, // 158
|
||||
CON_ENDEVENT, // 159
|
||||
CON_IFVARE, // 160
|
||||
CON_IFVARVARE, // 161
|
||||
CON_END
|
||||
};
|
||||
// KEEPINSYNC with the keyword list in lunatic/con_lang.lua
|
||||
|
|
|
@ -57,10 +57,18 @@ enum vmflags_t
|
|||
};
|
||||
|
||||
int32_t g_tw;
|
||||
int32_t g_currentEvent = -1;
|
||||
int32_t g_errorLineNum;
|
||||
|
||||
intptr_t const *insptr;
|
||||
|
||||
int32_t g_returnVarID = -1; // var ID of "RETURN"
|
||||
int32_t g_weaponVarID = -1; // var ID of "WEAPON"
|
||||
int32_t g_worksLikeVarID = -1; // var ID of "WORKSLIKE"
|
||||
int32_t g_zRangeVarID = -1; // var ID of "ZRANGE"
|
||||
int32_t g_angRangeVarID = -1; // var ID of "ANGRANGE"
|
||||
int32_t g_aimAngleVarID = -1; // var ID of "AUTOAIMANGLE"
|
||||
|
||||
// for timing events and actors
|
||||
uint32_t g_actorCalls[MAXTILES];
|
||||
double g_actorTotalMs[MAXTILES], g_actorMinMs[MAXTILES], g_actorMaxMs[MAXTILES];
|
||||
|
@ -122,6 +130,8 @@ static void VM_DeleteSprite(int const spriteNum, int const playerNum)
|
|||
A_DeleteSprite(spriteNum);
|
||||
}
|
||||
|
||||
intptr_t apScriptEvents[MAXEVENTS];
|
||||
|
||||
static int32_t VM_CheckSquished(void)
|
||||
{
|
||||
if (RR)
|
||||
|
@ -1188,7 +1198,8 @@ GAMEEXEC_STATIC void VM_Execute(native_t loop)
|
|||
{
|
||||
case CON_ENDA:
|
||||
case CON_BREAK:
|
||||
case CON_ENDS: return;
|
||||
case CON_ENDS:
|
||||
case CON_ENDEVENT: return;
|
||||
|
||||
case CON_IFRND: VM_CONDITIONAL(rnd(*(++insptr))); continue;
|
||||
|
||||
|
@ -2515,6 +2526,128 @@ GAMEEXEC_STATIC void VM_Execute(native_t loop)
|
|||
continue;
|
||||
|
||||
case CON_IFNOSOUNDS: VM_CONDITIONAL(!A_CheckAnySoundPlaying(vm.spriteNum)); continue;
|
||||
|
||||
|
||||
case CON_IFVARG:
|
||||
insptr++;
|
||||
tw = Gv_GetVar(*insptr++);
|
||||
VM_CONDITIONAL(tw > *insptr);
|
||||
continue;
|
||||
|
||||
case CON_IFVARL:
|
||||
insptr++;
|
||||
tw = Gv_GetVar(*insptr++);
|
||||
VM_CONDITIONAL(tw < *insptr);
|
||||
continue;
|
||||
|
||||
case CON_SETVARVAR:
|
||||
insptr++;
|
||||
{
|
||||
tw = *insptr++;
|
||||
int const nValue = Gv_GetVar(*insptr++);
|
||||
|
||||
if ((aGameVars[tw].flags & (GAMEVAR_USER_MASK | GAMEVAR_PTR_MASK)) == 0)
|
||||
aGameVars[tw].global = nValue;
|
||||
else
|
||||
Gv_SetVar(tw, nValue);
|
||||
}
|
||||
continue;
|
||||
|
||||
case CON_SETVAR:
|
||||
Gv_SetVar(insptr[1], insptr[2]);
|
||||
insptr += 3;
|
||||
continue;
|
||||
|
||||
case CON_ADDVARVAR:
|
||||
insptr++;
|
||||
tw = *insptr++;
|
||||
Gv_AddVar(tw, Gv_GetVar(*insptr++));
|
||||
continue;
|
||||
|
||||
case CON_ADDVAR:
|
||||
Gv_AddVar(insptr[1], insptr[2]);
|
||||
insptr += 3;
|
||||
continue;
|
||||
|
||||
case CON_IFVARVARL:
|
||||
insptr++;
|
||||
tw = Gv_GetVar(*insptr++);
|
||||
tw = (tw < Gv_GetVar(*insptr++));
|
||||
insptr--;
|
||||
VM_CONDITIONAL(tw);
|
||||
continue;
|
||||
|
||||
case CON_IFVARVARG:
|
||||
insptr++;
|
||||
tw = Gv_GetVar(*insptr++);
|
||||
tw = (tw > Gv_GetVar(*insptr++));
|
||||
insptr--;
|
||||
VM_CONDITIONAL(tw);
|
||||
continue;
|
||||
|
||||
case CON_ADDLOGVAR:
|
||||
insptr++;
|
||||
{
|
||||
int32_t m = 1;
|
||||
char szBuf[256];
|
||||
int32_t lVarID = *insptr;
|
||||
|
||||
if ((lVarID >= g_gameVarCount) || lVarID < 0)
|
||||
{
|
||||
if (*insptr == MAXGAMEVARS) // addlogvar for a constant? Har.
|
||||
insptr++;
|
||||
else if (EDUKE32_PREDICT_TRUE(*insptr & GV_FLAG_NEGATIVE))
|
||||
{
|
||||
m = -m;
|
||||
lVarID ^= GV_FLAG_NEGATIVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// invalid varID
|
||||
CON_ERRPRINTF("invalid variable\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Bsprintf(tempbuf, "CONLOGVAR: L=%d %s ", VM_DECODE_LINE_NUMBER(g_tw), aGameVars[lVarID].szLabel);
|
||||
|
||||
if (aGameVars[lVarID].flags & GAMEVAR_READONLY)
|
||||
{
|
||||
Bsprintf(szBuf, " (read-only)");
|
||||
Bstrcat(tempbuf, szBuf);
|
||||
}
|
||||
if (aGameVars[lVarID].flags & GAMEVAR_PERPLAYER)
|
||||
{
|
||||
Bsprintf(szBuf, " (Per Player. Player=%d)", vm.playerNum);
|
||||
}
|
||||
else if (aGameVars[lVarID].flags & GAMEVAR_PERACTOR)
|
||||
{
|
||||
Bsprintf(szBuf, " (Per Actor. Actor=%d)", vm.spriteNum);
|
||||
}
|
||||
else
|
||||
{
|
||||
Bsprintf(szBuf, " (Global)");
|
||||
}
|
||||
Bstrcat(tempbuf, szBuf);
|
||||
Bsprintf(szBuf, " =%d\n", Gv_GetVar(lVarID) * m);
|
||||
Bstrcat(tempbuf, szBuf);
|
||||
initprintf(OSDTEXT_GREEN "%s", tempbuf);
|
||||
insptr++;
|
||||
continue;
|
||||
}
|
||||
|
||||
case CON_IFVARE:
|
||||
insptr++;
|
||||
tw = Gv_GetVar(*insptr++);
|
||||
VM_CONDITIONAL(tw >= *insptr);
|
||||
continue;
|
||||
|
||||
case CON_IFVARVARE:
|
||||
insptr++;
|
||||
tw = Gv_GetVar(*insptr++);
|
||||
tw = (tw == Gv_GetVar(*insptr++));
|
||||
insptr--;
|
||||
VM_CONDITIONAL(tw);
|
||||
continue;
|
||||
|
||||
default: // you aren't supposed to be here!
|
||||
if (RR && ud.recstat == 2)
|
||||
|
@ -2537,37 +2670,6 @@ GAMEEXEC_STATIC void VM_Execute(native_t loop)
|
|||
}
|
||||
}
|
||||
|
||||
// NORECURSE
|
||||
void A_LoadActor(int32_t spriteNum)
|
||||
{
|
||||
vm.spriteNum = spriteNum; // Sprite ID
|
||||
vm.pSprite = &sprite[spriteNum]; // Pointer to sprite structure
|
||||
vm.pActor = &actor[spriteNum];
|
||||
|
||||
if (g_tile[vm.pSprite->picnum].loadPtr == NULL)
|
||||
return;
|
||||
|
||||
vm.pData = &actor[spriteNum].t_data[0]; // Sprite's 'extra' data
|
||||
vm.playerNum = -1; // Player ID
|
||||
vm.playerDist = -1; // Distance
|
||||
vm.pPlayer = g_player[0].ps;
|
||||
|
||||
vm.flags &= ~(VM_RETURN | VM_KILL | VM_NOEXECUTE);
|
||||
|
||||
if ((unsigned)vm.pSprite->sectnum >= MAXSECTORS)
|
||||
{
|
||||
A_DeleteSprite(vm.spriteNum);
|
||||
return;
|
||||
}
|
||||
|
||||
insptr = g_tile[vm.pSprite->picnum].loadPtr;
|
||||
VM_Execute(1);
|
||||
insptr = NULL;
|
||||
|
||||
if (vm.flags & VM_KILL)
|
||||
A_DeleteSprite(vm.spriteNum);
|
||||
}
|
||||
|
||||
void VM_UpdateAnim(int spriteNum, int32_t *pData)
|
||||
{
|
||||
size_t const actionofs = AC_ACTION_ID(pData);
|
||||
|
|
|
@ -34,10 +34,9 @@ extern int32_t ticrandomseed;
|
|||
|
||||
extern vmstate_t vm;
|
||||
extern int32_t g_tw;
|
||||
extern int32_t g_currentEvent;
|
||||
extern int32_t g_errorLineNum;
|
||||
|
||||
void A_LoadActor(int32_t spriteNum);
|
||||
|
||||
extern uint32_t g_actorCalls[MAXTILES];
|
||||
extern double g_actorTotalMs[MAXTILES], g_actorMinMs[MAXTILES], g_actorMaxMs[MAXTILES];
|
||||
|
||||
|
|
|
@ -23,10 +23,124 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|||
#ifndef gamevars_h_
|
||||
#define gamevars_h_
|
||||
|
||||
#define MAXGAMEVARS 2048 // must be a power of two
|
||||
#define MAXVARLABEL 26
|
||||
|
||||
#define GV_FLAG_CONSTANT (MAXGAMEVARS)
|
||||
#define GV_FLAG_NEGATIVE (MAXGAMEVARS<<1)
|
||||
|
||||
// store global game definitions
|
||||
enum GamevarFlags_t
|
||||
{
|
||||
GAMEVAR_PERPLAYER = 0x00000001, // per-player variable
|
||||
GAMEVAR_PERACTOR = 0x00000002, // per-actor variable
|
||||
GAMEVAR_USER_MASK = (GAMEVAR_PERPLAYER | GAMEVAR_PERACTOR),
|
||||
GAMEVAR_RESET = 0x00000008, // INTERNAL, don't use
|
||||
GAMEVAR_DEFAULT = 0x00000100, // UNUSED, but always cleared for user-defined gamevars
|
||||
GAMEVAR_NODEFAULT = 0x00000400, // don't reset on actor spawn
|
||||
GAMEVAR_SYSTEM = 0x00000800, // cannot change mode flags...(only default value)
|
||||
GAMEVAR_READONLY = 0x00001000, // values are read-only (no setvar allowed)
|
||||
GAMEVAR_INT32PTR = 0x00002000, // plValues is a pointer to an int32_t
|
||||
GAMEVAR_INT16PTR = 0x00008000, // plValues is a pointer to a short
|
||||
GAMEVAR_NORESET = 0x00020000, // var values are not reset when restoring map state
|
||||
GAMEVAR_SPECIAL = 0x00040000, // flag for structure member shortcut vars
|
||||
GAMEVAR_NOMULTI = 0x00080000, // don't attach to multiplayer packets
|
||||
GAMEVAR_Q16PTR = 0x00100000, // plValues is a pointer to a q16.16
|
||||
GAMEVAR_SERIALIZE = 0x00200000, // write into permasaves
|
||||
|
||||
GAMEVAR_RAWQ16PTR = GAMEVAR_Q16PTR | GAMEVAR_SPECIAL, // plValues is a pointer to a q16.16 but we don't want conversion
|
||||
GAMEVAR_PTR_MASK = GAMEVAR_INT32PTR | GAMEVAR_INT16PTR | GAMEVAR_Q16PTR | GAMEVAR_RAWQ16PTR,
|
||||
};
|
||||
|
||||
// Alignments for per-player and per-actor variables.
|
||||
#define PLAYER_VAR_ALIGNMENT (sizeof(intptr_t))
|
||||
#define ACTOR_VAR_ALIGNMENT 16
|
||||
|
||||
#define ARRAY_ALIGNMENT 16
|
||||
|
||||
#pragma pack(push,1)
|
||||
typedef struct
|
||||
{
|
||||
union {
|
||||
intptr_t global;
|
||||
intptr_t *pValues; // array of values when 'per-player', or 'per-actor'
|
||||
};
|
||||
intptr_t defaultValue;
|
||||
uintptr_t flags;
|
||||
char * szLabel;
|
||||
} gamevar_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
extern gamevar_t aGameVars[MAXGAMEVARS];
|
||||
extern int32_t g_gameVarCount;
|
||||
|
||||
int __fastcall Gv_GetVar(int const gameVar, int const spriteNum, int const playerNum);
|
||||
void __fastcall Gv_SetVar(int const gameVar, int const newValue, int const spriteNum, int const playerNum);
|
||||
int __fastcall Gv_GetVar(int const gameVar);
|
||||
void __fastcall Gv_GetManyVars(int const numVars, int32_t * const outBuf);
|
||||
void __fastcall Gv_SetVar(int const gameVar, int const newValue);
|
||||
|
||||
template <typename T>
|
||||
static FORCE_INLINE void Gv_FillWithVars(T & rv)
|
||||
{
|
||||
EDUKE32_STATIC_ASSERT(sizeof(T) % sizeof(int32_t) == 0);
|
||||
EDUKE32_STATIC_ASSERT(sizeof(T) > sizeof(int32_t));
|
||||
Gv_GetManyVars(sizeof(T)/sizeof(int32_t), (int32_t *)&rv);
|
||||
}
|
||||
|
||||
int Gv_GetVarByLabel(const char *szGameLabel,int defaultValue,int spriteNum,int playerNum);
|
||||
void Gv_NewVar(const char *pszLabel,intptr_t lValue,uint32_t dwFlags);
|
||||
|
||||
static FORCE_INLINE void A_ResetVars(int const spriteNum)
|
||||
{
|
||||
for (auto &gv : aGameVars)
|
||||
{
|
||||
if ((gv.flags & (GAMEVAR_PERACTOR|GAMEVAR_NODEFAULT)) == GAMEVAR_PERACTOR)
|
||||
gv.pValues[spriteNum] = gv.defaultValue;
|
||||
}
|
||||
}
|
||||
void Gv_DumpValues(void);
|
||||
void Gv_InitWeaponPointers(void);
|
||||
void Gv_RefreshPointers(void);
|
||||
void Gv_ResetVars(void);
|
||||
int Gv_ReadSave(buildvfs_kfd kFile);
|
||||
void Gv_WriteSave(buildvfs_FILE fil);
|
||||
void Gv_Clear(void);
|
||||
|
||||
void Gv_ResetSystemDefaults(void);
|
||||
void Gv_Init(void);
|
||||
void Gv_FinalizeWeaponDefaults(void);
|
||||
|
||||
#define VM_GAMEVAR_OPERATOR(func, operator) \
|
||||
static FORCE_INLINE ATTRIBUTE((flatten)) void __fastcall func(int const id, int32_t const operand) \
|
||||
{ \
|
||||
auto &var = aGameVars[id]; \
|
||||
\
|
||||
switch (var.flags & (GAMEVAR_USER_MASK | GAMEVAR_PTR_MASK)) \
|
||||
{ \
|
||||
default: \
|
||||
var.global operator operand; \
|
||||
break; \
|
||||
case GAMEVAR_PERPLAYER: \
|
||||
var.pValues[vm.playerNum & (MAXPLAYERS-1)] operator operand; \
|
||||
break; \
|
||||
case GAMEVAR_PERACTOR: \
|
||||
var.pValues[vm.spriteNum & (MAXSPRITES-1)] operator operand; \
|
||||
break; \
|
||||
case GAMEVAR_INT32PTR: *(int32_t *)var.pValues operator(int32_t) operand; break; \
|
||||
case GAMEVAR_INT16PTR: *(int16_t *)var.pValues operator(int16_t) operand; break; \
|
||||
case GAMEVAR_Q16PTR: \
|
||||
{ \
|
||||
Fix16 *pfix = (Fix16 *)var.global; \
|
||||
*pfix operator fix16_from_int(operand); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
VM_GAMEVAR_OPERATOR(Gv_AddVar, +=)
|
||||
VM_GAMEVAR_OPERATOR(Gv_SubVar, -=)
|
||||
|
||||
#undef VM_GAMEVAR_OPERATOR
|
||||
|
||||
#endif
|
||||
|
|
|
@ -56,6 +56,24 @@ extern int32_t PHEIGHT;
|
|||
|
||||
#define MAX_WEAPON_RECS 256
|
||||
|
||||
enum weaponflags_t {
|
||||
WEAPON_SPAWNTYPE1 = 0x00000000, // just spawn
|
||||
WEAPON_HOLSTER_CLEARS_CLIP = 0x00000001, // 'holstering' clears the current clip
|
||||
WEAPON_GLOWS = 0x00000002, // weapon 'glows' (shrinker and grower)
|
||||
WEAPON_AUTOMATIC = 0x00000004, // automatic fire (continues while 'fire' is held down
|
||||
WEAPON_FIREEVERYOTHER = 0x00000008, // during 'hold time' fire every frame
|
||||
WEAPON_FIREEVERYTHIRD = 0x00000010, // during 'hold time' fire every third frame
|
||||
WEAPON_RANDOMRESTART = 0x00000020, // restart for automatic is 'randomized' by RND 3
|
||||
WEAPON_AMMOPERSHOT = 0x00000040, // uses ammo for each shot (for automatic)
|
||||
WEAPON_BOMB_TRIGGER = 0x00000080, // weapon is the 'bomb' trigger
|
||||
WEAPON_NOVISIBLE = 0x00000100, // weapon use does not cause user to become 'visible'
|
||||
WEAPON_THROWIT = 0x00000200, // weapon 'throws' the 'shoots' item...
|
||||
WEAPON_CHECKATRELOAD = 0x00000400, // check weapon availability at 'reload' time
|
||||
WEAPON_STANDSTILL = 0x00000800, // player stops jumping before actual fire (like tripbomb in duke)
|
||||
WEAPON_SPAWNTYPE2 = 0x00001000, // spawn like shotgun shells
|
||||
WEAPON_SPAWNTYPE3 = 0x00002000, // spawn like chaingun shells
|
||||
};
|
||||
|
||||
enum gamemode_t {
|
||||
MODE_MENU = 0x00000001,
|
||||
MODE_DEMO = 0x00000002,
|
||||
|
@ -223,6 +241,51 @@ typedef struct {
|
|||
} playerdata_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
// KEEPINSYNC lunatic/con_lang.lua
|
||||
typedef struct
|
||||
{
|
||||
// NOTE: the member names must be identical to aplWeapon* suffixes.
|
||||
int32_t WorksLike; // What the original works like
|
||||
int32_t Clip; // number of items in magazine
|
||||
int32_t Reload; // delay to reload (include fire)
|
||||
int32_t FireDelay; // delay to fire
|
||||
int32_t TotalTime; // The total time the weapon is cycling before next fire.
|
||||
int32_t HoldDelay; // delay after release fire button to fire (0 for none)
|
||||
int32_t Flags; // Flags for weapon
|
||||
int32_t Shoots; // what the weapon shoots
|
||||
int32_t SpawnTime; // the frame at which to spawn an item
|
||||
int32_t Spawn; // the item to spawn
|
||||
int32_t ShotsPerBurst; // number of shots per 'burst' (one ammo per 'burst')
|
||||
int32_t InitialSound; // Sound made when weapon starts firing. zero for no sound
|
||||
int32_t FireSound; // Sound made when firing (each time for automatic)
|
||||
int32_t Sound2Time; // Alternate sound time
|
||||
int32_t Sound2Sound; // Alternate sound sound ID
|
||||
int32_t FlashColor; // Muzzle flash color
|
||||
} weapondata_t;
|
||||
|
||||
#ifdef LUNATIC
|
||||
# define PWEAPON(Player, Weapon, Wmember) (g_playerWeapon[Player][Weapon].Wmember)
|
||||
extern weapondata_t g_playerWeapon[MAXPLAYERS][MAX_WEAPONS];
|
||||
#else
|
||||
# define PWEAPON(Player, Weapon, Wmember) (aplWeapon ## Wmember [Weapon][Player])
|
||||
extern intptr_t *aplWeaponClip[MAX_WEAPONS]; // number of items in clip
|
||||
extern intptr_t *aplWeaponReload[MAX_WEAPONS]; // delay to reload (include fire)
|
||||
extern intptr_t *aplWeaponFireDelay[MAX_WEAPONS]; // delay to fire
|
||||
extern intptr_t *aplWeaponHoldDelay[MAX_WEAPONS]; // delay after release fire button to fire (0 for none)
|
||||
extern intptr_t *aplWeaponTotalTime[MAX_WEAPONS]; // The total time the weapon is cycling before next fire.
|
||||
extern intptr_t *aplWeaponFlags[MAX_WEAPONS]; // Flags for weapon
|
||||
extern intptr_t *aplWeaponShoots[MAX_WEAPONS]; // what the weapon shoots
|
||||
extern intptr_t *aplWeaponSpawnTime[MAX_WEAPONS]; // the frame at which to spawn an item
|
||||
extern intptr_t *aplWeaponSpawn[MAX_WEAPONS]; // the item to spawn
|
||||
extern intptr_t *aplWeaponShotsPerBurst[MAX_WEAPONS]; // number of shots per 'burst' (one ammo per 'burst'
|
||||
extern intptr_t *aplWeaponWorksLike[MAX_WEAPONS]; // What original the weapon works like
|
||||
extern intptr_t *aplWeaponInitialSound[MAX_WEAPONS]; // Sound made when initialy firing. zero for no sound
|
||||
extern intptr_t *aplWeaponFireSound[MAX_WEAPONS]; // Sound made when firing (each time for automatic)
|
||||
extern intptr_t *aplWeaponSound2Time[MAX_WEAPONS]; // Alternate sound time
|
||||
extern intptr_t *aplWeaponSound2Sound[MAX_WEAPONS]; // Alternate sound sound ID
|
||||
extern intptr_t *aplWeaponFlashColor[MAX_WEAPONS]; // Color for polymer muzzle flash
|
||||
#endif
|
||||
|
||||
// KEEPINSYNC lunatic/_defs_game.lua
|
||||
typedef struct {
|
||||
int32_t cur, count; // "cur" is the only member that is *used*
|
||||
|
|
|
@ -1935,6 +1935,11 @@ end_vol4a:
|
|||
pPlayer->gm = 0;
|
||||
M_ClearMenus();
|
||||
|
||||
Gv_ResetVars();
|
||||
Gv_InitWeaponPointers();
|
||||
Gv_RefreshPointers();
|
||||
Gv_ResetSystemDefaults();
|
||||
|
||||
//AddLog("Newgame");
|
||||
|
||||
for (bssize_t i=0; i<(MAXVOLUMES*MAXLEVELS); i++)
|
||||
|
|
|
@ -348,6 +348,19 @@ typedef struct dataspec_
|
|||
intptr_t cnt;
|
||||
} dataspec_t;
|
||||
|
||||
typedef struct dataspec_gv_
|
||||
{
|
||||
uint32_t flags;
|
||||
void * ptr;
|
||||
uint32_t size;
|
||||
intptr_t cnt;
|
||||
} dataspec_gv_t;
|
||||
|
||||
#define SV_DEFAULTCOMPRTHRES 8
|
||||
static uint8_t savegame_diffcompress; // 0:none, 1:Ken's LZW in cache1d.c
|
||||
static uint8_t savegame_comprthres;
|
||||
|
||||
|
||||
#define DS_DYNAMIC 1 // dereference .ptr one more time
|
||||
#define DS_STRING 2
|
||||
#define DS_CMP 4
|
||||
|
@ -970,6 +983,7 @@ static const dataspec_t svgm_anmisc[] =
|
|||
{ DS_END, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static dataspec_gv_t *svgm_vars=NULL;
|
||||
static uint8_t *dosaveplayer2(FileWriter *fil, uint8_t *mem);
|
||||
static int32_t doloadplayer2(FileReader &fil, uint8_t **memptr);
|
||||
static void postloadplayer(int32_t savegamep);
|
||||
|
@ -983,6 +997,46 @@ static uint8_t *svdiff;
|
|||
|
||||
#include "gamedef.h"
|
||||
|
||||
#define SV_SKIPMASK (/*GAMEVAR_SYSTEM|*/ GAMEVAR_READONLY | GAMEVAR_PTR_MASK | /*GAMEVAR_NORESET |*/ GAMEVAR_SPECIAL)
|
||||
|
||||
static char svgm_vars_string [] = "blK:vars";
|
||||
// setup gamevar data spec for snapshotting and diffing... gamevars must be loaded when called
|
||||
static void sv_makevarspec()
|
||||
{
|
||||
int vcnt = 0;
|
||||
|
||||
for (int i = 0; i < g_gameVarCount; i++)
|
||||
vcnt += (aGameVars[i].flags & SV_SKIPMASK) ? 0 : 1;
|
||||
|
||||
svgm_vars = (dataspec_gv_t *)Xrealloc(svgm_vars, (vcnt + 2) * sizeof(dataspec_gv_t));
|
||||
|
||||
svgm_vars[0].flags = DS_STRING;
|
||||
svgm_vars[0].ptr = svgm_vars_string;
|
||||
svgm_vars[0].cnt = 1;
|
||||
|
||||
vcnt = 1;
|
||||
|
||||
for (int i = 0; i < g_gameVarCount; i++)
|
||||
{
|
||||
if (aGameVars[i].flags & SV_SKIPMASK)
|
||||
continue;
|
||||
|
||||
unsigned const per = aGameVars[i].flags & GAMEVAR_USER_MASK;
|
||||
|
||||
svgm_vars[vcnt].flags = 0;
|
||||
svgm_vars[vcnt].ptr = (per == 0) ? &aGameVars[i].global : aGameVars[i].pValues;
|
||||
svgm_vars[vcnt].size = sizeof(intptr_t);
|
||||
svgm_vars[vcnt].cnt = (per == 0) ? 1 : (per == GAMEVAR_PERPLAYER ? MAXPLAYERS : MAXSPRITES);
|
||||
|
||||
++vcnt;
|
||||
}
|
||||
|
||||
svgm_vars[vcnt].flags = DS_END;
|
||||
svgm_vars[vcnt].ptr = NULL;
|
||||
svgm_vars[vcnt].size = 0;
|
||||
svgm_vars[vcnt].cnt = 0;
|
||||
}
|
||||
|
||||
void sv_freemem()
|
||||
{
|
||||
DO_FREE_AND_NULL(svsnapshot);
|
||||
|
@ -1007,7 +1061,9 @@ int32_t sv_saveandmakesnapshot(FileWriter &fil, int8_t spot, bool isAutoSave)
|
|||
savehead_t h;
|
||||
|
||||
// calculate total snapshot size
|
||||
svsnapsiz = calcsz(svgm_udnetw) + calcsz(svgm_secwsp) + calcsz(svgm_script) + calcsz(svgm_anmisc);
|
||||
sv_makevarspec();
|
||||
svsnapsiz = calcsz((const dataspec_t *)svgm_vars);
|
||||
svsnapsiz += calcsz(svgm_udnetw) + calcsz(svgm_secwsp) + calcsz(svgm_script) + calcsz(svgm_anmisc);
|
||||
|
||||
|
||||
// create header
|
||||
|
@ -1225,6 +1281,7 @@ uint32_t sv_writediff(FileWriter *fil)
|
|||
cmpspecdata(svgm_secwsp, &p, &d);
|
||||
cmpspecdata(svgm_script, &p, &d);
|
||||
cmpspecdata(svgm_anmisc, &p, &d);
|
||||
cmpspecdata((const dataspec_t *)svgm_vars, &p, &d);
|
||||
|
||||
if (p != svsnapshot+svsnapsiz)
|
||||
OSD_Printf("sv_writediff: dump+siz=%p, p=%p!\n", svsnapshot+svsnapsiz, p);
|
||||
|
@ -1256,6 +1313,7 @@ int32_t sv_readdiff(FileReader &fil)
|
|||
if (applydiff(svgm_secwsp, &p, &d)) return -4;
|
||||
if (applydiff(svgm_script, &p, &d)) return -5;
|
||||
if (applydiff(svgm_anmisc, &p, &d)) return -6;
|
||||
if (applydiff((const dataspec_t *)svgm_vars, &p, &d)) return -7;
|
||||
|
||||
int i = 0;
|
||||
|
||||
|
@ -1369,6 +1427,9 @@ static uint8_t *dosaveplayer2(FileWriter *fil, uint8_t *mem)
|
|||
PRINTSIZE("script");
|
||||
mem=writespecdata(svgm_anmisc, fil, mem); // animates, quotes & misc.
|
||||
PRINTSIZE("animisc");
|
||||
Gv_WriteSave(fil); // gamevars
|
||||
mem=writespecdata((const dataspec_t *)svgm_vars, 0, mem);
|
||||
PRINTSIZE("vars");
|
||||
|
||||
return mem;
|
||||
}
|
||||
|
@ -1389,6 +1450,23 @@ static int32_t doloadplayer2(FileReader &fil, uint8_t **memptr)
|
|||
if (readspecdata(svgm_anmisc, &fil, &mem)) return -6;
|
||||
PRINTSIZE("animisc");
|
||||
|
||||
int i;
|
||||
|
||||
if ((i = Gv_ReadSave(fil))) return i;
|
||||
|
||||
if (mem)
|
||||
{
|
||||
int32_t i;
|
||||
|
||||
sv_makevarspec();
|
||||
for (i=1; svgm_vars[i].flags!=DS_END; i++)
|
||||
{
|
||||
Bmemcpy(mem, svgm_vars[i].ptr, svgm_vars[i].size*svgm_vars[i].cnt); // careful! works because there are no DS_DYNAMIC's!
|
||||
mem += svgm_vars[i].size*svgm_vars[i].cnt;
|
||||
}
|
||||
}
|
||||
PRINTSIZE("vars");
|
||||
|
||||
if (memptr)
|
||||
*memptr = mem;
|
||||
return 0;
|
||||
|
@ -1405,6 +1483,7 @@ int32_t sv_updatestate(int32_t frominit)
|
|||
if (readspecdata(svgm_secwsp, nullptr, &p)) return -4;
|
||||
if (readspecdata(svgm_script, nullptr, &p)) return -5;
|
||||
if (readspecdata(svgm_anmisc, nullptr, &p)) return -6;
|
||||
if (readspecdata((const dataspec_t *)svgm_vars, -1, &p)) return -8;
|
||||
|
||||
if (p != pbeg+svsnapsiz)
|
||||
{
|
||||
|
@ -1529,6 +1608,12 @@ static void postloadplayer(int32_t savegamep)
|
|||
// if (savegamep) ?
|
||||
G_ResetTimers(0);
|
||||
|
||||
#ifdef USE_STRUCT_TRACKERS
|
||||
Bmemset(sectorchanged, 0, sizeof(sectorchanged));
|
||||
Bmemset(spritechanged, 0, sizeof(spritechanged));
|
||||
Bmemset(wallchanged, 0, sizeof(wallchanged));
|
||||
#endif
|
||||
|
||||
#ifdef POLYMER
|
||||
//9
|
||||
if (videoGetRenderMode() == REND_POLYMER)
|
||||
|
|
|
@ -88,6 +88,7 @@ typedef struct {
|
|||
#ifndef NEW_MAP_FORMAT
|
||||
wallext_t wallext[MAXWALLS];
|
||||
#endif
|
||||
intptr_t *vars[MAXGAMEVARS];
|
||||
#ifdef YAX_ENABLE
|
||||
int32_t numyaxbunches;
|
||||
# if !defined NEW_MAP_FORMAT
|
||||
|
|
Loading…
Reference in a new issue