diff --git a/source/duke3d/src/gamedef.cpp b/source/duke3d/src/gamedef.cpp index e157f86bb..0c27bfc66 100644 --- a/source/duke3d/src/gamedef.cpp +++ b/source/duke3d/src/gamedef.cpp @@ -499,6 +499,7 @@ static tokenmap_t const vm_keywords[] = { "subvar", CON_SUBVAR }, { "subvarvar", CON_SUBVARVAR }, { "switch", CON_SWITCH }, + { "swaparrays", CON_SWAPARRAYS }, { "swaptrackslot", CON_SWAPTRACKSLOT }, { "time", CON_TIME }, { "tip", CON_TIP }, @@ -4473,8 +4474,9 @@ DO_DEFSTATE: if (aGameArrays[i].flags & (GAMEARRAY_READONLY|GAMEARRAY_SYSTEM)) { + g_errorCnt++; C_ReportError(-1); - initprintf("can't resize system array `%s'.", label+(g_labelCnt<<6)); + initprintf("%s:%d: error: can't resize system array `%s'.\n", g_scriptFileName, g_lineNumber, label+(g_labelCnt<<6)); return 1; } @@ -4482,6 +4484,43 @@ DO_DEFSTATE: C_GetNextVarType(0); continue; + case CON_SWAPARRAYS: + i = C_GetNextGameArrayName(); + if (EDUKE32_PREDICT_FALSE(i < 0)) + return 1; + + if (aGameArrays[i].flags & (GAMEARRAY_READONLY|GAMEARRAY_SYSTEM|GAMEARRAY_VARSIZE)) + { + g_errorCnt++; + C_ReportError(-1); + initprintf("%s:%d: error: can't swap system array `%s'.\n", g_scriptFileName, g_lineNumber, label+(g_labelCnt<<6)); + return 1; + } + + C_SkipComments(); + + tw = C_GetNextGameArrayName(); + if (EDUKE32_PREDICT_FALSE(tw < 0)) + return 1; + + if (aGameArrays[tw].flags & (GAMEARRAY_READONLY|GAMEARRAY_SYSTEM|GAMEARRAY_VARSIZE)) + { + g_errorCnt++; + C_ReportError(-1); + initprintf("%s:%d: error: can't swap system array `%s'.\n", g_scriptFileName, g_lineNumber, label+(g_labelCnt<<6)); + return 1; + } + + if ((aGameArrays[i].flags & GAMEARRAY_STORAGE_MASK) != (aGameArrays[tw].flags & GAMEARRAY_STORAGE_MASK)) + { + g_errorCnt++; + C_ReportError(-1); + initprintf("%s:%d: error: can't swap arrays of different storage classes.\n", g_scriptFileName, g_lineNumber); + return 1; + } + + continue; + case CON_SMAXAMMO: case CON_ADDWEAPONVAR: case CON_ACTIVATEBYSECTOR: diff --git a/source/duke3d/src/gamedef.h b/source/duke3d/src/gamedef.h index bd8e2cf4f..1bed3a250 100644 --- a/source/duke3d/src/gamedef.h +++ b/source/duke3d/src/gamedef.h @@ -1252,6 +1252,7 @@ enum ScriptKeywords_t CON_SPAWNWALLGLASS, // 431 CON_SPAWNWALLSTAINEDGLASS, // 432 CON_SPAWNCEILINGGLASS, // 433 + CON_SWAPARRAYS, // 434 CON_END }; // KEEPINSYNC with the keyword list in lunatic/con_lang.lua diff --git a/source/duke3d/src/gameexec.cpp b/source/duke3d/src/gameexec.cpp index cc501dd50..b8b894d16 100644 --- a/source/duke3d/src/gameexec.cpp +++ b/source/duke3d/src/gameexec.cpp @@ -5132,6 +5132,18 @@ GAMEEXEC_STATIC void VM_Execute(native_t loop) continue; } + case CON_SWAPARRAYS: + insptr++; + { + uint32_t const array1 = *insptr++; + uint32_t const array2 = *insptr++; + + swap(&aGameArrays[array1].size, &aGameArrays[array2].size); + swap(&aGameArrays[array1].pValues, &aGameArrays[array2].pValues); + + continue; + } + case CON_RANDVAR: insptr++; Gv_SetVarX(*insptr, mulscale16(krand(), *(insptr + 1) + 1)); diff --git a/source/duke3d/src/gamevars.h b/source/duke3d/src/gamevars.h index 7c713f994..b6c090093 100644 --- a/source/duke3d/src/gamevars.h +++ b/source/duke3d/src/gamevars.h @@ -79,6 +79,7 @@ enum GamearrayFlags_t GAMEARRAY_WARN = 0x00200000, GAMEARRAY_SIZE_MASK = GAMEARRAY_INT8 | GAMEARRAY_INT16 | GAMEARRAY_BITMAP, + GAMEARRAY_STORAGE_MASK = GAMEARRAY_INT8 | GAMEARRAY_INT16 | GAMEARRAY_BITMAP | GAMEARRAY_STRIDE2, GAMEARRAY_TYPE_MASK = GAMEARRAY_UNSIGNED | GAMEARRAY_INT8 | GAMEARRAY_INT16 | GAMEARRAY_BITMAP, };