This commit is contained in:
Christoph Oelckers 2015-02-23 20:35:58 +01:00
commit 4e7cfef0e0
11 changed files with 250 additions and 137 deletions

View file

@ -71,22 +71,24 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck)
if (linetarget) if (linetarget)
{ {
P_LineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, PClass::FindClass ("CStaffPuff"), false, &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, if (linetarget != NULL)
linetarget->x, linetarget->y);
if (((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0))|| linetarget->flags3&MF3_ISMONSTER)
&& (!(linetarget->flags2&(MF2_DORMANT+MF2_INVULNERABLE))))
{ {
newLife = player->health+(damage>>3); pmo->angle = R_PointToAngle2 (pmo->x, pmo->y, linetarget->x, linetarget->y);
newLife = newLife > max ? max : newLife; if (((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0))|| linetarget->flags3&MF3_ISMONSTER)
if (newLife > player->health) && (!(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; break;
} }
@ -95,16 +97,21 @@ DEFINE_ACTION_FUNCTION(AActor, A_CStaffCheck)
if (linetarget) if (linetarget)
{ {
P_LineAttack (pmo, angle, fixed_t(1.5*MELEERANGE), slope, damage, NAME_Melee, PClass::FindClass ("CStaffPuff"), false, &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, if (linetarget != NULL)
linetarget->x, linetarget->y);
if ((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0)) || linetarget->flags3&MF3_ISMONSTER)
{ {
newLife = player->health+(damage>>4); pmo->angle = R_PointToAngle2 (pmo->x, pmo->y, linetarget->x, linetarget->y);
newLife = newLife > max ? max : newLife; if ((linetarget->player && (!linetarget->IsTeammate (pmo) || level.teamdamage != 0)) || linetarget->flags3&MF3_ISMONSTER)
pmo->health = player->health = newLife; {
P_SetPsprite (player, ps_weapon, weapon->FindState ("Drain")); 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; break;
} }
} }

View file

@ -45,7 +45,7 @@ DEarthquake::DEarthquake (AActor *center, int intensityX, int intensityY, int in
m_IntensityX = intensityX; m_IntensityX = intensityX;
m_IntensityY = intensityY; m_IntensityY = intensityY;
m_IntensityZ = intensityZ; m_IntensityZ = intensityZ;
m_CountdownStart = (double)duration; m_CountdownStart = duration;
m_Countdown = duration; m_Countdown = duration;
m_Flags = flags; 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 // 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)) if (victim->player != NULL && (victim->player->cheats & CF_NOCLIP))
{ {
return 0; return 0;
} }
qprop.isScalingDown = qprop.isScalingUp = qprop.preferMaximum = qprop.fullIntensity = false; intensityX = intensityY = intensityZ = relIntensityX = relIntensityY = relIntensityZ = 0;
qprop.intensityX = qprop.intensityY = qprop.intensityZ = qprop.relIntensityX = qprop.relIntensityY = qprop.relIntensityZ = 0;
TThinkerIterator<DEarthquake> iterator(STAT_EARTHQUAKE); TThinkerIterator<DEarthquake> iterator(STAT_EARTHQUAKE);
DEarthquake *quake; DEarthquake *quake;
@ -182,30 +225,20 @@ int DEarthquake::StaticGetQuakeIntensities(AActor *victim, quakeInfo &qprop)
if (dist < quake->m_TremorRadius) if (dist < quake->m_TremorRadius)
{ {
++count; ++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) if (quake->m_Flags & QF_RELATIVE)
{ {
qprop.relIntensityX = MAX(qprop.relIntensityX, quake->m_IntensityX); relIntensityX = MAX(relIntensityX, x);
qprop.relIntensityY = MAX(qprop.relIntensityY, quake->m_IntensityY); relIntensityY = MAX(relIntensityY, y);
qprop.relIntensityZ = MAX(qprop.relIntensityZ, quake->m_IntensityZ); relIntensityZ = MAX(relIntensityZ, z);
} }
else else
{ {
qprop.intensityX = MAX(qprop.intensityX, quake->m_IntensityX); intensityX = MAX(intensityX, x);
qprop.intensityY = MAX(qprop.intensityY, quake->m_IntensityY); intensityY = MAX(intensityY, y);
qprop.intensityZ = MAX(qprop.intensityZ, quake->m_IntensityZ); intensityZ = MAX(intensityZ, z);
}
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;
} }
} }
} }

View file

@ -140,13 +140,6 @@ enum
QF_FULLINTENSITY = 1 << 4, 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 class DEarthquake : public DThinker
{ {
DECLARE_CLASS (DEarthquake, DThinker) DECLARE_CLASS (DEarthquake, DThinker)
@ -159,12 +152,16 @@ public:
TObjPtr<AActor> m_Spot; TObjPtr<AActor> m_Spot;
fixed_t m_TremorRadius, m_DamageRadius; fixed_t m_TremorRadius, m_DamageRadius;
int m_Countdown; int m_Countdown;
double m_CountdownStart; int m_CountdownStart;
FSoundID m_QuakeSFX; FSoundID m_QuakeSFX;
int m_Flags; int m_Flags;
int m_IntensityX, m_IntensityY, m_IntensityZ; 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: private:
DEarthquake (); DEarthquake ();

View file

@ -343,17 +343,14 @@ int GetUDMFInt(int type, int index, const char *key)
{ {
assert(type >=0 && type <=3); 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); return pKey->IntVal;
if (pKey != NULL)
{
return pKey->IntVal;
}
} }
} }
return 0; return 0;
@ -363,17 +360,14 @@ fixed_t GetUDMFFixed(int type, int index, const char *key)
{ {
assert(type >=0 && type <=3); 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); return FLOAT2FIXED(pKey->FloatVal);
if (pKey != NULL)
{
return FLOAT2FIXED(pKey->FloatVal);
}
} }
} }
return 0; return 0;
@ -1109,6 +1103,7 @@ public:
sdt->midtexture = "-"; sdt->midtexture = "-";
sd->SetTextureXScale(FRACUNIT); sd->SetTextureXScale(FRACUNIT);
sd->SetTextureYScale(FRACUNIT); sd->SetTextureYScale(FRACUNIT);
sd->Index = index;
sc.MustGetToken('{'); sc.MustGetToken('{');
while (!sc.CheckToken('}')) while (!sc.CheckToken('}'))

View file

@ -1512,11 +1512,11 @@ void R_DrawNormalPlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske
yscale = pl->yscale << (16 - ds_ybits); yscale = pl->yscale << (16 - ds_ybits);
if (planeang != 0) if (planeang != 0)
{ {
fixed_t cosine = finecosine[planeang >> ANGLETOFINESHIFT]; double rad = bam2rad(planeang);
fixed_t sine = finesine[planeang >> ANGLETOFINESHIFT]; double cosine = cos(rad), sine = sin(rad);
pviewx = pl->xoffs + FixedMul (viewx, cosine) - FixedMul (viewy, sine); pviewx = xs_RoundToInt(pl->xoffs + viewx * cosine - viewy * sine);
pviewy = pl->yoffs - FixedMul (viewx, sine) - FixedMul (viewy, cosine); pviewy = xs_RoundToInt(pl->yoffs - viewx * sine - viewy * cosine);
} }
else else
{ {

View file

@ -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; return FixedMul(factor, pr_torchflicker(intensity * 2) - intensity);
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);
}
}
} }
//========================================================================== //==========================================================================
@ -921,38 +885,40 @@ void R_SetupFrame (AActor *actor)
if (!paused) if (!paused)
{ {
quakeInfo quake; fixed_t intensityX, intensityY, intensityZ, relIntensityX, relIntensityY, relIntensityZ;
if (DEarthquake::StaticGetQuakeIntensities(camera, quake) > 0) 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; int ang = (camera->angle) >> ANGLETOFINESHIFT;
fixed_t power = QuakePower(quakefactor, quake.relIntensityX, quake); fixed_t power = QuakePower(quakefactor, relIntensityX);
viewx += FixedMul(finecosine[ang], power); viewx += FixedMul(finecosine[ang], power);
viewy += FixedMul(finesine[ang], power); viewy += FixedMul(finesine[ang], power);
} }
if (quake.relIntensityY != 0) if (relIntensityY != 0)
{ {
int ang = (camera->angle + ANG90) >> ANGLETOFINESHIFT; 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); viewx += FixedMul(finecosine[ang], power);
viewy += FixedMul(finesine[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 // FIXME: Relative Z is not relative
quake.intensityZ = MAX(quake.intensityZ, quake.relIntensityZ); intensityZ = MAX(intensityZ, relIntensityZ);
if (quake.intensityZ != 0) if (intensityZ != 0)
{ {
viewz += QuakePower(quakefactor, quake.intensityZ, quake); viewz += QuakePower(quakefactor, intensityZ);
} }
} }
} }

View file

@ -159,6 +159,7 @@ std2:
'random2' { RET(TK_Random2); } 'random2' { RET(TK_Random2); }
'frandom' { RET(TK_FRandom); } 'frandom' { RET(TK_FRandom); }
'randompick' { RET(TK_RandomPick); } 'randompick' { RET(TK_RandomPick); }
'frandompick' { RET(TK_FRandomPick); }
L (L|D)* { RET(TK_Identifier); } L (L|D)* { RET(TK_Identifier); }

View file

@ -123,4 +123,5 @@ xx(TK_In, "'in'")
xx(TK_SizeOf, "'sizeof'") xx(TK_SizeOf, "'sizeof'")
xx(TK_AlignOf, "'alignof'") xx(TK_AlignOf, "'alignof'")
xx(TK_RandomPick, "'randompick'") xx(TK_RandomPick, "'randompick'")
xx(TK_FRandomPick, "'frandompick'")
#undef xx #undef xx

View file

@ -371,8 +371,9 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls)
return new FxRandom(rng, min, max, sc); 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; FRandom *rng;
TArray<FxExpression*> list; TArray<FxExpression*> list;
list.Clear(); list.Clear();
@ -398,7 +399,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls)
break; break;
sc.MustGetToken(','); sc.MustGetToken(',');
} }
return new FxRandomPick(rng, list, sc); return new FxRandomPick(rng, list, floaty, sc);
} }
else if (sc.CheckToken(TK_FRandom)) else if (sc.CheckToken(TK_FRandom))
{ {

View file

@ -314,6 +314,25 @@ public:
}; };
//==========================================================================
//
//
//
//==========================================================================
class FxFloatCast : public FxExpression
{
FxExpression *basex;
public:
FxFloatCast(FxExpression *x);
~FxFloatCast();
FxExpression *Resolve(FCompileContext&);
ExpVal EvalExpression (AActor *self);
};
//========================================================================== //==========================================================================
// //
// FxSign // FxSign
@ -568,7 +587,7 @@ protected:
public: public:
FxRandomPick(FRandom *, TArray<FxExpression*> mi, const FScriptPosition &pos); FxRandomPick(FRandom *, TArray<FxExpression*> mi, bool floaty, const FScriptPosition &pos);
~FxRandomPick(); ~FxRandomPick();
FxExpression *Resolve(FCompileContext&); FxExpression *Resolve(FCompileContext&);

View file

@ -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<FxExpression*> mi, const FScriptPosition &pos) FxRandomPick::FxRandomPick(FRandom * r, TArray<FxExpression*> mi, bool floaty, const FScriptPosition &pos)
: FxExpression(pos) : FxExpression(pos)
{ {
for (unsigned int index = 0; index < mi.Size(); index++) 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; 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 FxRandomPick::EvalExpression(AActor *self)
{ {
ExpVal val; ExpVal val;
val.Type = VAL_Int;
int max = min.Size(); int max = min.Size();
if (max > 0) if (max > 0)
{ {
int select = (*rng)(max); 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 else
{ {
val.Int = (*rng)(); val.Type = VAL_Float;
val.Float = (*rng)(0x40000000) / double(0x40000000);
} }
assert(val.Type == ValueType.Type);
return val; return val;
} }