diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index 8d2fa10a2..7eaecb82d 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -3643,11 +3643,30 @@ ExpEmit FxArrayElement::Emit(VMFunctionBuilder *build) // //========================================================================== -FxFunctionCall::FxFunctionCall(FName methodname, FArgumentList *args, const FScriptPosition &pos) +FxFunctionCall::FxFunctionCall(FName methodname, FName rngname, FArgumentList *args, const FScriptPosition &pos) : FxExpression(pos) { MethodName = methodname; + RNG = nullptr; ArgList = args; + if (rngname != NAME_None) + { + switch (MethodName) + { + case NAME_Random: + case NAME_FRandom: + case NAME_RandomPick: + case NAME_FRandomPick: + case NAME_Random2: + RNG = FRandom::StaticFindRNG(rngname.GetChars()); + break; + + default: + pos.Message(MSG_ERROR, "Cannot use named RNGs with %s", MethodName.GetChars()); + break; + + } + } } //========================================================================== @@ -3749,7 +3768,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) return x->Resolve(ctx); } - // Last but not least: Check builtins. The random functions will have to be duplicated for the case where an RNG is specified. + // Last but not least: Check builtins. The random functions can take a named RNG if specified. // Note that for all builtins the used arguments have to be nulled in the ArgList so that they won't get deleted before they get used. FxExpression *func = nullptr; @@ -3759,7 +3778,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_Random: if (CheckArgSize(NAME_Random, ArgList, 2, 2, ScriptPosition)) { - func = new FxRandom(nullptr, (*ArgList)[0], (*ArgList)[1], ScriptPosition, ctx.FromDecorate); + func = new FxRandom(RNG, (*ArgList)[0], (*ArgList)[1], ScriptPosition, ctx.FromDecorate); (*ArgList)[0] = (*ArgList)[1] = nullptr; } break; @@ -3767,7 +3786,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_FRandom: if (CheckArgSize(NAME_FRandom, ArgList, 2, 2, ScriptPosition)) { - func = new FxFRandom(nullptr, (*ArgList)[0], (*ArgList)[1], ScriptPosition); + func = new FxFRandom(RNG, (*ArgList)[0], (*ArgList)[1], ScriptPosition); (*ArgList)[0] = (*ArgList)[1] = nullptr; } break; @@ -3776,7 +3795,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_FRandomPick: if (CheckArgSize(MethodName, ArgList, 1, -1, ScriptPosition)) { - func = new FxRandomPick(nullptr, *ArgList, MethodName == NAME_FRandomPick, ScriptPosition, ctx.FromDecorate); + func = new FxRandomPick(RNG, *ArgList, MethodName == NAME_FRandomPick, ScriptPosition, ctx.FromDecorate); for (auto &i : *ArgList) i = nullptr; // Ownership of items is transferred to FxMinMax but not ownership of the array itself, so Clear cannot be called here. } break; @@ -3784,7 +3803,7 @@ FxExpression *FxFunctionCall::Resolve(FCompileContext& ctx) case NAME_Random2: if (CheckArgSize(NAME_Random2, ArgList, 1, 1, ScriptPosition)) { - func = new FxRandom2(nullptr, (*ArgList)[0], ScriptPosition, ctx.FromDecorate); + func = new FxRandom2(RNG, (*ArgList)[0], ScriptPosition, ctx.FromDecorate); (*ArgList)[0] = nullptr; } break; diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 6645d8c8a..213fe388a 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -894,11 +894,12 @@ typedef TDeletingArray FArgumentList; class FxFunctionCall : public FxExpression { FName MethodName; + FRandom *RNG; FArgumentList *ArgList; public: - FxFunctionCall(FName methodname, FArgumentList *args, const FScriptPosition &pos); + FxFunctionCall(FName methodname, FName rngname, FArgumentList *args, const FScriptPosition &pos); ~FxFunctionCall(); FxExpression *Resolve(FCompileContext&); }; diff --git a/src/scripting/decorate/thingdef_exp.cpp b/src/scripting/decorate/thingdef_exp.cpp index c10ef9ad8..5be69390e 100644 --- a/src/scripting/decorate/thingdef_exp.cpp +++ b/src/scripting/decorate/thingdef_exp.cpp @@ -548,7 +548,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) while (sc.CheckToken(',')); sc.MustGetToken(')'); } - return new FxFunctionCall(identifier, args, sc); + return new FxFunctionCall(identifier, NAME_None, args, sc); } catch (...) { diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 26964381b..e9e806907 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2290,7 +2290,7 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) auto fcall = static_cast(ast); assert(fcall->Function->NodeType == AST_ExprID); // of course this cannot remain. Right now nothing more complex can come along but later this will have to be decomposed into 'self' and the actual function name. auto fname = static_cast(fcall->Function)->Identifier; - return new FxFunctionCall(fname, ConvertNodeList(fcall->Parameters), *ast); + return new FxFunctionCall(fname, NAME_None, ConvertNodeList(fcall->Parameters), *ast); //return ConvertFunctionCall(fcall->Function, ConvertNodeList(fcall->Parameters), ConvertClass, *ast); }