diff --git a/src/g_hexen/a_clericstaff.cpp b/src/g_hexen/a_clericstaff.cpp index aa8b94d742..ecce09d345 100644 --- a/src/g_hexen/a_clericstaff.cpp +++ b/src/g_hexen/a_clericstaff.cpp @@ -71,22 +71,24 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck) if (linetarget) { P_LineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, PClass::FindClass ("CStaffPuff"), false, &linetarget); - pmo->angle = R_PointToAngle2 (pmo->x, pmo->y, - linetarget->x, linetarget->y); - if (((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0))|| linetarget->flags3&MF3_ISMONSTER) - && (!(linetarget->flags2&(MF2_DORMANT+MF2_INVULNERABLE)))) + if (linetarget != NULL) { - newLife = player->health+(damage>>3); - newLife = newLife > max ? max : newLife; - if (newLife > player->health) + pmo->angle = R_PointToAngle2 (pmo->x, pmo->y, linetarget->x, linetarget->y); + if (((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0))|| linetarget->flags3&MF3_ISMONSTER) + && (!(linetarget->flags2&(MF2_DORMANT+MF2_INVULNERABLE)))) { - pmo->health = player->health = newLife; + newLife = player->health+(damage>>3); + newLife = newLife > max ? max : newLife; + if (newLife > player->health) + { + pmo->health = player->health = newLife; + } + P_SetPsprite (player, ps_weapon, weapon->FindState ("Drain")); + } + if (weapon != NULL) + { + weapon->DepleteAmmo (weapon->bAltFire, false); } - P_SetPsprite (player, ps_weapon, weapon->FindState ("Drain")); - } - if (weapon != NULL) - { - weapon->DepleteAmmo (weapon->bAltFire, false); } break; } @@ -95,16 +97,21 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck) if (linetarget) { P_LineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, PClass::FindClass ("CStaffPuff"), false, &linetarget); - pmo->angle = R_PointToAngle2 (pmo->x, pmo->y, - linetarget->x, linetarget->y); - if ((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0)) || linetarget->flags3&MF3_ISMONSTER) + if (linetarget != NULL) { - newLife = player->health+(damage>>4); - newLife = newLife > max ? max : newLife; - pmo->health = player->health = newLife; - P_SetPsprite (player, ps_weapon, weapon->FindState ("Drain")); + pmo->angle = R_PointToAngle2 (pmo->x, pmo->y, linetarget->x, linetarget->y); + if ((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0)) || linetarget->flags3&MF3_ISMONSTER) + { + newLife = player->health+(damage>>4); + newLife = newLife > max ? max : newLife; + pmo->health = player->health = newLife; + P_SetPsprite (player, ps_weapon, weapon->FindState ("Drain")); + } + if (weapon != NULL) + { + weapon->DepleteAmmo (weapon->bAltFire, false); + } } - weapon->DepleteAmmo (weapon->bAltFire, false); break; } } diff --git a/src/g_shared/a_quake.cpp b/src/g_shared/a_quake.cpp index 5cce4c3716..e1b340f279 100644 --- a/src/g_shared/a_quake.cpp +++ b/src/g_shared/a_quake.cpp @@ -45,7 +45,7 @@ DEarthquake::DEarthquake (AActor *center, int intensityX, int intensityY, int in m_IntensityX = intensityX; m_IntensityY = intensityY; m_IntensityZ = intensityZ; - m_CountdownStart = (double)duration; + m_CountdownStart = duration; m_Countdown = duration; m_Flags = flags; } @@ -151,6 +151,48 @@ void DEarthquake::Tick () } } +//========================================================================== +// +// DEarthquake :: GetModIntensity +// +// Given a base intensity, modify it according to the quake's flags. +// +//========================================================================== + +fixed_t DEarthquake::GetModIntensity(int intensity) const +{ + assert(m_CountdownStart >= m_Countdown); + intensity += intensity; // always doubled + if (m_Flags & (QF_SCALEDOWN | QF_SCALEUP)) + { + int scalar; + if ((m_Flags & (QF_SCALEDOWN | QF_SCALEUP)) == (QF_SCALEDOWN | QF_SCALEUP)) + { + scalar = (m_Flags & QF_MAX) ? MAX(m_Countdown, m_CountdownStart - m_Countdown) + : MIN(m_Countdown, m_CountdownStart - m_Countdown); + if (m_Flags & QF_FULLINTENSITY) + { + scalar *= 2; + } + } + else if (m_Flags & QF_SCALEDOWN) + { + scalar = m_Countdown; + } + else // QF_SCALEUP + { + scalar = m_CountdownStart - m_Countdown; + } + assert(m_CountdownStart > 0); + intensity = intensity * (scalar << FRACBITS) / m_CountdownStart; + } + else + { + intensity <<= FRACBITS; + } + return intensity; +} + //========================================================================== // // DEarthquake::StaticGetQuakeIntensity @@ -160,14 +202,15 @@ void DEarthquake::Tick () // //========================================================================== -int DEarthquake::StaticGetQuakeIntensities(AActor *victim, quakeInfo &qprop) +int DEarthquake::StaticGetQuakeIntensities(AActor *victim, + fixed_t &intensityX, fixed_t &intensityY, fixed_t &intensityZ, + fixed_t &relIntensityX, fixed_t &relIntensityY, fixed_t &relIntensityZ) { if (victim->player != NULL && (victim->player->cheats & CF_NOCLIP)) { return 0; } - qprop.isScalingDown = qprop.isScalingUp = qprop.preferMaximum = qprop.fullIntensity = false; - qprop.intensityX = qprop.intensityY = qprop.intensityZ = qprop.relIntensityX = qprop.relIntensityY = qprop.relIntensityZ = 0; + intensityX = intensityY = intensityZ = relIntensityX = relIntensityY = relIntensityZ = 0; TThinkerIterator iterator(STAT_EARTHQUAKE); DEarthquake *quake; @@ -182,30 +225,20 @@ int DEarthquake::StaticGetQuakeIntensities(AActor *victim, quakeInfo &qprop) if (dist < quake->m_TremorRadius) { ++count; + fixed_t x = quake->GetModIntensity(quake->m_IntensityX); + fixed_t y = quake->GetModIntensity(quake->m_IntensityY); + fixed_t z = quake->GetModIntensity(quake->m_IntensityZ); if (quake->m_Flags & QF_RELATIVE) { - qprop.relIntensityX = MAX(qprop.relIntensityX, quake->m_IntensityX); - qprop.relIntensityY = MAX(qprop.relIntensityY, quake->m_IntensityY); - qprop.relIntensityZ = MAX(qprop.relIntensityZ, quake->m_IntensityZ); + relIntensityX = MAX(relIntensityX, x); + relIntensityY = MAX(relIntensityY, y); + relIntensityZ = MAX(relIntensityZ, z); } else { - qprop.intensityX = MAX(qprop.intensityX, quake->m_IntensityX); - qprop.intensityY = MAX(qprop.intensityY, quake->m_IntensityY); - qprop.intensityZ = MAX(qprop.intensityZ, quake->m_IntensityZ); - } - if (quake->m_Flags) - { - qprop.scaleDownStart = quake->m_CountdownStart; - qprop.scaleDown = quake->m_Countdown; - qprop.isScalingDown = (quake->m_Flags & QF_SCALEDOWN) ? true : false; - qprop.isScalingUp = (quake->m_Flags & QF_SCALEUP) ? true : false; - qprop.preferMaximum = (quake->m_Flags & QF_MAX) ? true : false; - qprop.fullIntensity = (quake->m_Flags & QF_FULLINTENSITY) ? true : false; - } - else - { - qprop.scaleDownStart = qprop.scaleDown = 0.0; + intensityX = MAX(intensityX, x); + intensityY = MAX(intensityY, y); + intensityZ = MAX(intensityZ, z); } } } diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index 00247c224d..02ba94036b 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -140,13 +140,6 @@ enum QF_FULLINTENSITY = 1 << 4, }; -struct quakeInfo -{ - int intensityX, intensityY, intensityZ, relIntensityX, relIntensityY, relIntensityZ; - double scaleDown, scaleDownStart; - bool isScalingDown, isScalingUp, preferMaximum, fullIntensity; -}; - class DEarthquake : public DThinker { DECLARE_CLASS (DEarthquake, DThinker) @@ -159,12 +152,16 @@ public: TObjPtr m_Spot; fixed_t m_TremorRadius, m_DamageRadius; int m_Countdown; - double m_CountdownStart; + int m_CountdownStart; FSoundID m_QuakeSFX; int m_Flags; int m_IntensityX, m_IntensityY, m_IntensityZ; - static int StaticGetQuakeIntensities(AActor *viewer, quakeInfo &qprop); + fixed_t GetModIntensity(int intensity) const; + + static int StaticGetQuakeIntensities(AActor *viewer, + fixed_t &intensityX, fixed_t &intensityY, fixed_t &intensityZ, + fixed_t &relIntensityX, fixed_t &relIntensityY, fixed_t &relIntensityZ); private: DEarthquake (); diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index 541d7d3960..f0fb796906 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -343,17 +343,14 @@ int GetUDMFInt(int type, int index, const char *key) { assert(type >=0 && type <=3); - if (index > 0) - { - FUDMFKeys *pKeys = UDMFKeys[type].CheckKey(index); + FUDMFKeys *pKeys = UDMFKeys[type].CheckKey(index); - if (pKeys != NULL) + if (pKeys != NULL) + { + FUDMFKey *pKey = pKeys->Find(key); + if (pKey != NULL) { - FUDMFKey *pKey = pKeys->Find(key); - if (pKey != NULL) - { - return pKey->IntVal; - } + return pKey->IntVal; } } return 0; @@ -363,17 +360,14 @@ fixed_t GetUDMFFixed(int type, int index, const char *key) { assert(type >=0 && type <=3); - if (index > 0) - { - FUDMFKeys *pKeys = UDMFKeys[type].CheckKey(index); + FUDMFKeys *pKeys = UDMFKeys[type].CheckKey(index); - if (pKeys != NULL) + if (pKeys != NULL) + { + FUDMFKey *pKey = pKeys->Find(key); + if (pKey != NULL) { - FUDMFKey *pKey = pKeys->Find(key); - if (pKey != NULL) - { - return FLOAT2FIXED(pKey->FloatVal); - } + return FLOAT2FIXED(pKey->FloatVal); } } return 0; @@ -1109,6 +1103,7 @@ public: sdt->midtexture = "-"; sd->SetTextureXScale(FRACUNIT); sd->SetTextureYScale(FRACUNIT); + sd->Index = index; sc.MustGetToken('{'); while (!sc.CheckToken('}')) diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 8c01a1c3eb..8cab342302 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -1512,11 +1512,11 @@ void R_DrawNormalPlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske yscale = pl->yscale << (16 - ds_ybits); if (planeang != 0) { - fixed_t cosine = finecosine[planeang >> ANGLETOFINESHIFT]; - fixed_t sine = finesine[planeang >> ANGLETOFINESHIFT]; + double rad = bam2rad(planeang); + double cosine = cos(rad), sine = sin(rad); - pviewx = pl->xoffs + FixedMul (viewx, cosine) - FixedMul (viewy, sine); - pviewy = pl->yoffs - FixedMul (viewx, sine) - FixedMul (viewy, cosine); + pviewx = xs_RoundToInt(pl->xoffs + viewx * cosine - viewy * sine); + pviewy = xs_RoundToInt(pl->yoffs - viewx * sine - viewy * cosine); } else { diff --git a/src/r_utility.cpp b/src/r_utility.cpp index ebcff8af56..c82216e742 100644 --- a/src/r_utility.cpp +++ b/src/r_utility.cpp @@ -770,45 +770,9 @@ bool R_GetViewInterpolationStatus() // //========================================================================== -static fixed_t QuakePower(double factor, int intensity, quakeInfo quake) +static fixed_t QuakePower(fixed_t factor, fixed_t intensity) { - double scaleDownStart = quake.scaleDownStart; - double scaleDown = quake.scaleDown; - if (intensity == 0) - { - return 0; - } - else - { - double ss = (double)((pr_torchflicker() % (intensity << 2)) - (intensity << 1)); - double mtp = (quake.fullIntensity) ? 2.0 : 1.0; - if (quake.isScalingDown || quake.isScalingUp) - { - fixed_t result; - if (scaleDownStart == 0) scaleDownStart = 1; - - if (quake.isScalingDown && quake.isScalingUp) - { - if (quake.preferMaximum) - result = FLOAT2FIXED((factor * ss) * MAX(((scaleDown*mtp) / scaleDownStart), ((scaleDownStart - scaleDown)*mtp) / scaleDownStart)); - else - result = FLOAT2FIXED((factor * ss) * MIN(((scaleDown*mtp) / scaleDownStart), ((scaleDownStart - scaleDown)*mtp) / scaleDownStart)); - } - else if (quake.isScalingDown) - result = FLOAT2FIXED((factor * ss) * (scaleDown / scaleDownStart)); - else if (quake.isScalingUp) - result = FLOAT2FIXED((factor * ss) * ((scaleDownStart - scaleDown) / scaleDownStart)); - else - result = FLOAT2FIXED(factor * ss); - - return result; - } - else - { - return FLOAT2FIXED(factor * ss); - } - } - + return FixedMul(factor, pr_torchflicker(intensity * 2) - intensity); } //========================================================================== @@ -921,38 +885,40 @@ void R_SetupFrame (AActor *actor) if (!paused) { - quakeInfo quake; - if (DEarthquake::StaticGetQuakeIntensities(camera, quake) > 0) + fixed_t intensityX, intensityY, intensityZ, relIntensityX, relIntensityY, relIntensityZ; + if (DEarthquake::StaticGetQuakeIntensities(camera, + intensityX, intensityY, intensityZ, + relIntensityX, relIntensityY, relIntensityZ) > 0) { - double quakefactor = r_quakeintensity; + fixed_t quakefactor = FLOAT2FIXED(r_quakeintensity); - if (quake.relIntensityX != 0) + if (relIntensityX != 0) { int ang = (camera->angle) >> ANGLETOFINESHIFT; - fixed_t power = QuakePower(quakefactor, quake.relIntensityX, quake); + fixed_t power = QuakePower(quakefactor, relIntensityX); viewx += FixedMul(finecosine[ang], power); viewy += FixedMul(finesine[ang], power); } - if (quake.relIntensityY != 0) + if (relIntensityY != 0) { int ang = (camera->angle + ANG90) >> ANGLETOFINESHIFT; - fixed_t power = QuakePower(quakefactor, quake.relIntensityY, quake); + fixed_t power = QuakePower(quakefactor, relIntensityY); viewx += FixedMul(finecosine[ang], power); viewy += FixedMul(finesine[ang], power); } - if (quake.intensityX != 0) + if (intensityX != 0) { - viewx += QuakePower(quakefactor, quake.intensityX, quake); + viewx += QuakePower(quakefactor, intensityX); } - if (quake.intensityY != 0) + if (intensityY != 0) { - viewy += QuakePower(quakefactor, quake.intensityY, quake); + viewy += QuakePower(quakefactor, intensityY); } // FIXME: Relative Z is not relative - quake.intensityZ = MAX(quake.intensityZ, quake.relIntensityZ); - if (quake.intensityZ != 0) + intensityZ = MAX(intensityZ, relIntensityZ); + if (intensityZ != 0) { - viewz += QuakePower(quakefactor, quake.intensityZ, quake); + viewz += QuakePower(quakefactor, intensityZ); } } } diff --git a/src/sc_man_scanner.re b/src/sc_man_scanner.re index 52a5d9f61a..519ee4a1e7 100644 --- a/src/sc_man_scanner.re +++ b/src/sc_man_scanner.re @@ -159,6 +159,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 22f6e9cd40..afceaa856c 100644 --- a/src/sc_man_tokens.h +++ b/src/sc_man_tokens.h @@ -122,5 +122,6 @@ 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'") #undef xx diff --git a/src/thingdef/thingdef_exp.cpp b/src/thingdef/thingdef_exp.cpp index 7bd10b38da..5422d1a7c1 100644 --- a/src/thingdef/thingdef_exp.cpp +++ b/src/thingdef/thingdef_exp.cpp @@ -371,8 +371,9 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *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(); @@ -398,7 +399,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *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 d3ee57345b..40f5d4dc76 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -314,6 +314,25 @@ public: }; +//========================================================================== +// +// +// +//========================================================================== + +class FxFloatCast : public FxExpression +{ + FxExpression *basex; + +public: + + FxFloatCast(FxExpression *x); + ~FxFloatCast(); + FxExpression *Resolve(FCompileContext&); + + ExpVal EvalExpression (AActor *self); +}; + //========================================================================== // // FxSign @@ -568,7 +587,7 @@ protected: public: - FxRandomPick(FRandom *, TArray mi, const FScriptPosition &pos); + FxRandomPick(FRandom *, TArray mi, bool floaty, const FScriptPosition &pos); ~FxRandomPick(); FxExpression *Resolve(FCompileContext&); diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 0011f4d95a..3746a6ca7e 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -446,6 +446,82 @@ ExpVal FxIntCast::EvalExpression (AActor *self) } +//========================================================================== +// +// +// +//========================================================================== + +FxFloatCast::FxFloatCast(FxExpression *x) +: FxExpression(x->ScriptPosition) +{ + basex = x; + ValueType = VAL_Float; +} + +//========================================================================== +// +// +// +//========================================================================== + +FxFloatCast::~FxFloatCast() +{ + SAFE_DELETE(basex); +} + +//========================================================================== +// +// +// +//========================================================================== + +FxExpression *FxFloatCast::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(basex, ctx); + + if (basex->ValueType == VAL_Float) + { + FxExpression *x = basex; + basex = NULL; + delete this; + return x; + } + else if (basex->ValueType == VAL_Int) + { + if (basex->isConstant()) + { + ExpVal constval = basex->EvalExpression(NULL); + FxExpression *x = new FxConstant(constval.GetFloat(), ScriptPosition); + delete this; + return x; + } + return this; + } + else + { + ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return NULL; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +ExpVal FxFloatCast::EvalExpression (AActor *self) +{ + ExpVal baseval = basex->EvalExpression(self); + baseval.Float = baseval.GetFloat(); + baseval.Type = VAL_Float; + return baseval; +} + + //========================================================================== // // @@ -1698,15 +1774,24 @@ ExpVal FxRandom::EvalExpression (AActor *self) // // //========================================================================== -FxRandomPick::FxRandomPick(FRandom * r, TArray mi, const FScriptPosition &pos) +FxRandomPick::FxRandomPick(FRandom * r, TArray mi, bool floaty, const FScriptPosition &pos) : FxExpression(pos) { for (unsigned int index = 0; index < mi.Size(); index++) { - min.Push(new FxIntCast(mi[index])); + FxExpression *casted; + if (floaty) + { + casted = new FxFloatCast(mi[index]); + } + else + { + casted = new FxIntCast(mi[index]); + } + min.Push(casted); } rng = r; - ValueType = VAL_Int; + ValueType = floaty ? VAL_Float : VAL_Int; } //========================================================================== @@ -1746,17 +1831,25 @@ FxExpression *FxRandomPick::Resolve(FCompileContext &ctx) ExpVal FxRandomPick::EvalExpression(AActor *self) { ExpVal val; - val.Type = VAL_Int; int max = min.Size(); if (max > 0) { int select = (*rng)(max); - val.Int = min[select]->EvalExpression(self).GetInt(); + val = min[select]->EvalExpression(self); + } + /* Is a default even important when the parser requires at least one + * choice? Why do we do this? */ + else if (ValueType == VAL_Int) + { + val.Type = VAL_Int; + val.Int = (*rng)(); } else { - val.Int = (*rng)(); + val.Type = VAL_Float; + val.Float = (*rng)(0x40000000) / double(0x40000000); } + assert(val.Type == ValueType.Type); return val; }