diff --git a/src/sc_man_scanner.re b/src/sc_man_scanner.re index 9537f51b1..d1d05b929 100644 --- a/src/sc_man_scanner.re +++ b/src/sc_man_scanner.re @@ -186,6 +186,7 @@ std2: 'random2' { RET(TK_Random2); } 'frandom' { RET(TK_FRandom); } 'randompick' { RET(TK_RandomPick); } + 'frandompick' { RET(TK_FRandomPick); } L (L|D)* { RET(TK_Identifier); } diff --git a/src/sc_man_tokens.h b/src/sc_man_tokens.h index c7f9ec020..1665a1cae 100644 --- a/src/sc_man_tokens.h +++ b/src/sc_man_tokens.h @@ -117,7 +117,7 @@ xx(TK_Abs, "'abs'") xx(TK_Random, "'random'") xx(TK_Random2, "'random2'") xx(TK_FRandom, "'frandom'") -xx(TK_Pick, "'pick'") + xx(TK_Is, "'is'") xx(TK_Replaces, "'replaces'") xx(TK_Vector, "'vector'") @@ -126,7 +126,8 @@ xx(TK_Array, "'array'") xx(TK_In, "'in'") xx(TK_SizeOf, "'sizeof'") xx(TK_AlignOf, "'alignof'") -xx(TK_RandomPick, "'randompick'") +xx(TK_RandomPick, "'randompick'") +xx(TK_FRandomPick, "'frandompick'") xx(TK_States, "'states'") xx(TK_Loop, "'loop'") xx(TK_Fail, "'fail'") diff --git a/src/thingdef/thingdef_exp.cpp b/src/thingdef/thingdef_exp.cpp index 8064b910d..e198ec20b 100644 --- a/src/thingdef/thingdef_exp.cpp +++ b/src/thingdef/thingdef_exp.cpp @@ -369,8 +369,9 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) return new FxRandom(rng, min, max, sc); } - else if (sc.CheckToken(TK_RandomPick)) + else if (sc.CheckToken(TK_RandomPick) || sc.CheckToken(TK_FRandomPick)) { + bool floaty = sc.TokenType == TK_FRandomPick; FRandom *rng; TArray list; list.Clear(); @@ -396,7 +397,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, PClassActor *cls) break; sc.MustGetToken(','); } - return new FxRandomPick(rng, list, sc); + return new FxRandomPick(rng, list, floaty, sc); } else if (sc.CheckToken(TK_FRandom)) { diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index 7277d48bb..d1f7e75da 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -645,7 +645,7 @@ protected: public: - FxRandomPick(FRandom *, TArray &expr, const FScriptPosition &pos); + FxRandomPick(FRandom *, TArray &expr, bool floaty, const FScriptPosition &pos); ~FxRandomPick(); FxExpression *Resolve(FCompileContext&); diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index e8e3c2b67..9625d83ee 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -2069,17 +2069,25 @@ ExpEmit FxRandom::Emit(VMFunctionBuilder *build) // // //========================================================================== -FxRandomPick::FxRandomPick(FRandom *r, TArray &expr, const FScriptPosition &pos) +FxRandomPick::FxRandomPick(FRandom *r, TArray &expr, bool floaty, const FScriptPosition &pos) : FxExpression(pos) { assert(expr.Size() > 0); choices.Resize(expr.Size()); for (unsigned int index = 0; index < expr.Size(); index++) { - choices[index] = new FxIntCast(expr[index]); + if (floaty) + { + choices[index] = new FxFloatCast(expr[index]); + } + else + { + choices[index] = new FxIntCast(expr[index]); + } + } rng = r; - ValueType = VAL_Int; + ValueType = floaty ? VAL_Float : VAL_Int; } //========================================================================== @@ -2132,6 +2140,7 @@ FxExpression *FxRandomPick::Resolve(FCompileContext &ctx) ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build) { +#pragma message("FxRandomPick::Emit: Floating point part needs reviewing!") unsigned i; assert(choices.Size() > 0); @@ -2171,8 +2180,16 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build) build->BackpatchToHere(jumptable + i); if (choices[i]->isConstant()) { - int val = static_cast(choices[i])->GetValue().GetInt(); - build->EmitLoadInt(resultreg.RegNum, val); + if (ValueType == VAL_Int) + { + int val = static_cast(choices[i])->GetValue().GetInt(); + build->EmitLoadInt(resultreg.RegNum, val); + } + else + { + double val = static_cast(choices[i])->GetValue().GetFloat(); + build->Emit(OP_PARAM, 0, REGT_FLOAT | REGT_KONST, build->GetConstantFloat(val)); + } } else { @@ -2182,7 +2199,14 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build) // was expected. Copy it to the one we wanted. resultreg.Reuse(build); // This is really just for the assert in Reuse() - build->Emit(OP_MOVE, resultreg.RegNum, casereg.RegNum, 0); + if (ValueType == VAL_Int) + { + build->Emit(OP_MOVE, resultreg.RegNum, casereg.RegNum, 0); + } + else + { + build->Emit(OP_MOVEF, resultreg.RegNum, casereg.RegNum, 0); + } resultreg.Free(build); } // Free this register so the remaining cases can use it. @@ -2201,7 +2225,7 @@ ExpEmit FxRandomPick::Emit(VMFunctionBuilder *build) build->BackpatchToHere(finishes[i]); } // The result register needs to be in-use when we return. - // It should have been freed earlier, so restore it's in-use flag. + // It should have been freed earlier, so restore its in-use flag. resultreg.Reuse(build); return resultreg; }