# Conflicts:
#	wadsrc/static/menudef.txt
This commit is contained in:
Christoph Oelckers 2016-10-10 11:38:08 +02:00
commit 14a6e7989b
13 changed files with 279 additions and 74 deletions

View file

@ -2985,9 +2985,11 @@ static bool LoadDehSupp ()
void FinishDehPatch ()
{
unsigned int touchedIndex;
unsigned int nameindex = 0;
for (touchedIndex = 0; touchedIndex < TouchedActors.Size(); ++touchedIndex)
{
PClassActor *subclass;
PClassActor *type = TouchedActors[touchedIndex];
AActor *defaults1 = GetDefaultByType (type);
if (!(defaults1->flags & MF_SPECIAL))
@ -2997,9 +2999,16 @@ void FinishDehPatch ()
// Create a new class that will serve as the actual pickup
char typeNameBuilder[32];
mysnprintf (typeNameBuilder, countof(typeNameBuilder), "DehackedPickup%d", touchedIndex);
PClassActor *subclass = static_cast<PClassActor *>(RUNTIME_CLASS(ADehackedPickup)->
CreateDerivedClass(typeNameBuilder, sizeof(ADehackedPickup)));
//
do
{
// Retry until we find a free name. This is unlikely to happen but not impossible.
mysnprintf(typeNameBuilder, countof(typeNameBuilder), "DehackedPickup%d", nameindex++);
subclass = static_cast<PClassActor *>(RUNTIME_CLASS(ADehackedPickup)->
CreateDerivedClass(typeNameBuilder, sizeof(ADehackedPickup)));
}
while (subclass == nullptr);
AActor *defaults2 = GetDefaultByType (subclass);
memcpy ((void *)defaults2, (void *)defaults1, sizeof(AActor));

View file

@ -670,6 +670,20 @@ void PNamedType::GetTypeIDs(intptr_t &id1, intptr_t &id2) const
id2 = TypeName;
}
//==========================================================================
//
// PNamedType :: QualifiedName
//
//==========================================================================
FString PNamedType::QualifiedName() const
{
FString out;
if (Outer != nullptr) out = Outer->QualifiedName();
out << "::" << TypeName;
return out;
}
/* PInt *******************************************************************/
IMPLEMENT_CLASS(PInt)
@ -1752,7 +1766,7 @@ PEnum::PEnum()
//
//==========================================================================
PEnum::PEnum(FName name, DObject *outer)
PEnum::PEnum(FName name, PTypeBase *outer)
: PNamedType(name, outer), ValueType(NULL)
{
}
@ -1766,7 +1780,7 @@ PEnum::PEnum(FName name, DObject *outer)
//
//==========================================================================
PEnum *NewEnum(FName name, DObject *outer)
PEnum *NewEnum(FName name, PTypeBase *outer)
{
size_t bucket;
PType *etype = TypeTable.FindType(RUNTIME_CLASS(PEnum), (intptr_t)outer, (intptr_t)name, &bucket);
@ -2149,7 +2163,7 @@ PStruct::PStruct()
//
//==========================================================================
PStruct::PStruct(FName name, DObject *outer)
PStruct::PStruct(FName name, PTypeBase *outer)
: PNamedType(name, outer)
{
}
@ -2310,7 +2324,7 @@ size_t PStruct::PropagateMark()
//
//==========================================================================
PStruct *NewStruct(FName name, DObject *outer)
PStruct *NewStruct(FName name, PTypeBase *outer)
{
size_t bucket;
PType *stype = TypeTable.FindType(RUNTIME_CLASS(PStruct), (intptr_t)outer, (intptr_t)name, &bucket);
@ -2847,10 +2861,7 @@ void PClass::InsertIntoHash ()
found = TypeTable.FindType(RUNTIME_CLASS(PClass), (intptr_t)Outer, TypeName, &bucket);
if (found != NULL)
{ // This type has already been inserted
// ... but there is no need whatsoever to make it a fatal error!
if (!strictdecorate) Printf (TEXTCOLOR_RED"Tried to register class '%s' more than once.\n", TypeName.GetChars());
else I_Error("Tried to register class '%s' more than once.\n", TypeName.GetChars());
TypeTable.ReplaceType(this, found, bucket);
I_Error("Tried to register class '%s' more than once.\n", TypeName.GetChars());
}
else
{
@ -3015,15 +3026,23 @@ PClass *PClass::CreateDerivedClass(FName name, unsigned int size)
PClass *existclass = static_cast<PClass *>(TypeTable.FindType(RUNTIME_CLASS(PClass), /*FIXME:Outer*/0, name, &bucket));
// This is a placeholder so fill it in
if (existclass != NULL && (existclass->Size == TentativeClass))
if (existclass != nullptr)
{
type = const_cast<PClass*>(existclass);
if (!IsDescendantOf(type->ParentClass))
if (existclass->Size == TentativeClass)
{
I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars());
type = const_cast<PClass*>(existclass);
if (!IsDescendantOf(type->ParentClass))
{
I_Error("%s must inherit from %s but doesn't.", name.GetChars(), type->ParentClass->TypeName.GetChars());
}
DPrintf(DMSG_SPAMMY, "Defining placeholder class %s\n", name.GetChars());
notnew = true;
}
else
{
// a different class with the same name already exists. Let the calling code deal with this.
return nullptr;
}
DPrintf(DMSG_SPAMMY, "Defining placeholder class %s\n", name.GetChars());
notnew = true;
}
else
{
@ -3360,6 +3379,7 @@ CCMD(typetable)
// Symbol tables ------------------------------------------------------------
IMPLEMENT_ABSTRACT_CLASS(PTypeBase);
IMPLEMENT_ABSTRACT_CLASS(PSymbol);
IMPLEMENT_CLASS(PSymbolConst);
IMPLEMENT_CLASS(PSymbolConstNumeric);

View file

@ -22,12 +22,28 @@ typedef std::pair<const class PType *, unsigned> FTypeAndOffset;
// Symbol information -------------------------------------------------------
class PSymbol : public DObject
class PTypeBase : public DObject
{
DECLARE_ABSTRACT_CLASS(PSymbol, DObject);
DECLARE_ABSTRACT_CLASS(PTypeBase, DObject)
public:
virtual FString QualifiedName() const
{
return "";
}
};
class PSymbol : public PTypeBase
{
DECLARE_ABSTRACT_CLASS(PSymbol, PTypeBase);
public:
virtual ~PSymbol();
virtual FString QualifiedName() const
{
return SymbolName.GetChars();
}
FName SymbolName;
protected:
@ -153,13 +169,13 @@ extern PSymbolTable GlobalSymbols;
struct ZCC_ExprConstant;
class PClassType;
class PType : public DObject
class PType : public PTypeBase
{
//DECLARE_ABSTRACT_CLASS_WITH_META(PType, DObject, PClassType);
// We need to unravel the _WITH_META macro, since PClassType isn't defined yet,
// and we can't define it until we've defined PClass. But we can't define that
// without defining PType.
DECLARE_ABSTRACT_CLASS(PType, DObject)
DECLARE_ABSTRACT_CLASS(PType, PTypeBase)
HAS_OBJECT_POINTERS;
protected:
enum { MetaClassNum = CLASSREG_PClassType };
@ -332,14 +348,15 @@ class PNamedType : public PCompoundType
DECLARE_ABSTRACT_CLASS(PNamedType, PCompoundType);
HAS_OBJECT_POINTERS;
public:
DObject *Outer; // object this type is contained within
PTypeBase *Outer; // object this type is contained within
FName TypeName; // this type's name
PNamedType() : Outer(NULL) {}
PNamedType(FName name, DObject *outer) : Outer(outer), TypeName(name) {}
PNamedType(FName name, PTypeBase *outer) : Outer(outer), TypeName(name) {}
virtual bool IsMatch(intptr_t id1, intptr_t id2) const;
virtual void GetTypeIDs(intptr_t &id1, intptr_t &id2) const;
virtual FString QualifiedName() const;
};
// Basic types --------------------------------------------------------------
@ -533,7 +550,7 @@ class PEnum : public PNamedType
DECLARE_CLASS(PEnum, PNamedType);
HAS_OBJECT_POINTERS;
public:
PEnum(FName name, DObject *outer);
PEnum(FName name, PTypeBase *outer);
PType *ValueType;
TMap<FName, int> Values;
@ -610,7 +627,7 @@ class PStruct : public PNamedType
{
DECLARE_CLASS(PStruct, PNamedType);
public:
PStruct(FName name, DObject *outer);
PStruct(FName name, PTypeBase *outer);
TArray<PField *> Fields;
@ -822,8 +839,8 @@ PDynArray *NewDynArray(PType *type);
PPointer *NewPointer(PType *type);
PClassPointer *NewClassPointer(PClass *restrict);
PClassWaitingForParent *NewUnknownClass(FName myname, FName parentname);
PEnum *NewEnum(FName name, DObject *outer);
PStruct *NewStruct(FName name, DObject *outer);
PEnum *NewEnum(FName name, PTypeBase *outer);
PStruct *NewStruct(FName name, PTypeBase *outer);
PPrototype *NewPrototype(const TArray<PType *> &rettypes, const TArray<PType *> &argtypes);
// Built-in types -----------------------------------------------------------

View file

@ -23,8 +23,6 @@
#include "serializer.h"
static FRandom pr_restore ("RestorePos");
CVAR(Bool, r_pickupflash, true, CVAR_ARCHIVE);
IMPLEMENT_CLASS(PClassInventory)
@ -1091,7 +1089,7 @@ void AInventory::Touch (AActor *toucher)
if (player != NULL)
{
PlayPickupSound (player->mo);
if (!(ItemFlags & IF_NOSCREENFLASH) && r_pickupflash)
if (!(ItemFlags & IF_NOSCREENFLASH))
{
player->bonuscount = BONUSADD;
}

View file

@ -5821,43 +5821,54 @@ doplaysound: if (funcIndex == ACSF_PlayActorSound)
// [ZK] A_Warp in ACS
case ACSF_Warp:
{
int tid_dest = args[0];
int xofs = args[1];
int yofs = args[2];
int zofs = args[3];
int angle = args[4];
int flags = args[5];
const char *statename = argCount > 6 ? FBehavior::StaticLookupString(args[6]) : "";
bool exact = argCount > 7 ? !!args[7] : false;
int heightoffset = argCount > 8 ? args[8] : 0;
int radiusoffset = argCount > 9 ? args[9] : 0;
int pitch = argCount > 10 ? args[10] : 0;
FState *state = argCount > 6 ? activator->GetClass()->FindStateByString(statename, exact) : 0;
AActor *reference;
if((flags & WARPF_USEPTR) && tid_dest != AAPTR_DEFAULT)
if (nullptr == activator)
{
reference = COPY_AAPTR(activator, tid_dest);
}
else
{
reference = SingleActorFromTID(tid_dest, activator);
}
// If there is no activator or actor to warp to, fail.
if (activator == NULL || !reference)
return false;
if (P_Thing_Warp(activator, reference, ACSToDouble(xofs), ACSToDouble(yofs), ACSToDouble(zofs), ACSToAngle(angle), flags, ACSToDouble(heightoffset), ACSToDouble(radiusoffset), ACSToAngle(pitch)))
{
if (state && argCount > 6)
{
activator->SetState(state);
}
return true;
}
return false;
const int dest = args[0];
const int flags = args[5];
AActor* const reference = ((flags & WARPF_USEPTR) && (AAPTR_DEFAULT != dest))
? COPY_AAPTR(activator, dest)
: SingleActorFromTID(dest, activator);
if (nullptr == reference)
{
// there is no actor to warp to
return false;
}
const double xofs = ACSToDouble(args[1]);
const double yofs = ACSToDouble(args[2]);
const double zofs = ACSToDouble(args[3]);
const DAngle angle = ACSToAngle(args[4]);
const double heightoffset = argCount > 8 ? ACSToDouble(args[8]) : 0.0;
const double radiusoffset = argCount > 9 ? ACSToDouble(args[9]) : 0.0;
const DAngle pitch = ACSToAngle(argCount > 10 ? args[10] : 0);
if (!P_Thing_Warp(activator, reference, xofs, yofs, zofs, angle, flags, heightoffset, radiusoffset, pitch))
{
return false;
}
if (argCount > 6)
{
const char* const statename = FBehavior::StaticLookupString(args[6]);
if (nullptr != statename)
{
const bool exact = argCount > 7 && !!args[7];
FState* const state = activator->GetClass()->FindStateByString(statename, exact);
if (nullptr != state)
{
activator->SetState(state);
}
}
}
return true;
}
case ACSF_GetMaxInventory:
actor = SingleActorFromTID(args[0], activator);

View file

@ -1006,7 +1006,7 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayOffset)
PARAM_FLOAT_OPT(wx) { wx = 0.; }
PARAM_FLOAT_OPT(wy) { wy = 32.; }
PARAM_INT_OPT(flags) { flags = 0; }
A_OverlayOffset(self, layer, wx, wy, flags);
A_OverlayOffset(self, ((layer != 0) ? layer : stateinfo->mPSPIndex), wx, wy, flags);
return 0;
}
@ -1033,10 +1033,10 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayFlags)
PARAM_INT(flags);
PARAM_BOOL(set);
if (self->player == nullptr)
if (!ACTION_CALL_FROM_PSPRITE())
return 0;
DPSprite *pspr = self->player->FindPSprite(layer);
DPSprite *pspr = self->player->FindPSprite(((layer != 0) ? layer : stateinfo->mPSPIndex));
if (pspr == nullptr)
return 0;
@ -1049,6 +1049,52 @@ DEFINE_ACTION_FUNCTION(AActor, A_OverlayFlags)
return 0;
}
//---------------------------------------------------------------------------
//
// PROC OverlayX/Y
// Action function to return the X/Y of an overlay.
//---------------------------------------------------------------------------
static double GetOverlayPosition(AActor *self, int layer, bool gety)
{
if (layer)
{
DPSprite *pspr = self->player->FindPSprite(layer);
if (pspr != nullptr)
{
return gety ? (pspr->y) : (pspr->x);
}
}
return 0.;
}
DEFINE_ACTION_FUNCTION(AActor, OverlayX)
{
PARAM_ACTION_PROLOGUE;
PARAM_INT_OPT(layer) { layer = 0; }
if (ACTION_CALL_FROM_PSPRITE())
{
double res = GetOverlayPosition(self, ((layer != 0) ? layer : stateinfo->mPSPIndex), false);
ACTION_RETURN_FLOAT(res);
}
ACTION_RETURN_FLOAT(0.);
}
DEFINE_ACTION_FUNCTION(AActor, OverlayY)
{
PARAM_ACTION_PROLOGUE;
PARAM_INT_OPT(layer) { layer = 0; }
if (ACTION_CALL_FROM_PSPRITE())
{
double res = GetOverlayPosition(self, ((layer != 0) ? layer : stateinfo->mPSPIndex), true);
ACTION_RETURN_FLOAT(res);
}
ACTION_RETURN_FLOAT(0.);
}
//---------------------------------------------------------------------------
//
// PROC OverlayID

View file

@ -130,6 +130,53 @@ void Mac_I_FatalError(const char* const message)
}
static void I_DetectOS()
{
SInt32 majorVersion = 0;
Gestalt(gestaltSystemVersionMajor, &majorVersion);
SInt32 minorVersion = 0;
Gestalt(gestaltSystemVersionMinor, &minorVersion);
SInt32 bugFixVersion = 0;
Gestalt(gestaltSystemVersionBugFix, &bugFixVersion);
const char* name = "Unknown version";
if (10 == majorVersion) switch (minorVersion)
{
case 4: name = "Mac OS X Tiger"; break;
case 5: name = "Mac OS X Leopard"; break;
case 6: name = "Mac OS X Snow Leopard"; break;
case 7: name = "Mac OS X Lion"; break;
case 8: name = "OS X Mountain Lion"; break;
case 9: name = "OS X Mavericks"; break;
case 10: name = "OS X Yosemite"; break;
case 11: name = "OS X El Capitan"; break;
case 12: name = "macOS Sierra"; break;
}
char release[16] = {};
size_t size = sizeof release - 1;
sysctlbyname("kern.osversion", release, &size, nullptr, 0);
const char* const architecture =
#ifdef __i386__
"32-bit Intel";
#elif defined __x86_64__
"64-bit Intel";
#elif defined __ppc__
"32-bit PowerPC";
#elif defined __ppc64__
"64-bit PowerPC";
#else
"Unknown";
#endif
Printf("OS: %s %d.%d.%d (%s) %s\n", name, majorVersion, minorVersion, bugFixVersion, release, architecture);
}
DArgs* Args; // command line arguments
@ -165,6 +212,8 @@ void OriginalMainTry(int argc, char** argv)
progdir += "/";
C_InitConsole(80 * 8, 25 * 8, false);
I_DetectOS();
D_DoomMain();
}

View file

@ -140,6 +140,7 @@ DEFINE_CLASS_PROPERTY(respawns, 0, FakeInventory)
// Reads an old style decoration object
//
//==========================================================================
PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FName typeName);
void ParseOldDecoration(FScanner &sc, EDefinitionType def)
{
@ -154,7 +155,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
sc.MustGetString();
typeName = FName(sc.String);
type = static_cast<PClassActor *>(parent->CreateDerivedClass (typeName, parent->Size));
type = DecoDerivedClass(FScriptPosition(sc), parent, typeName);
ResetBaggage(&bag, parent);
bag.Info = type;
#ifdef _DEBUG

View file

@ -68,13 +68,44 @@
TDeletingArray<class FxExpression *> ActorDamageFuncs;
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
void InitThingdef();
void ParseDecorate (FScanner &sc);
void ParseDecorate(FScanner &ctx);
// STATIC FUNCTION PROTOTYPES --------------------------------------------
PClassActor *QuestItemClasses[31];
EXTERN_CVAR(Bool, strictdecorate);
PClassActor *DecoDerivedClass(const FScriptPosition &sc, PClassActor *parent, FName typeName)
{
PClassActor *type = static_cast<PClassActor *>(parent->CreateDerivedClass(typeName, parent->Size));
if (type == nullptr)
{
FString newname = typeName.GetChars();
FString sourcefile = sc.FileName;
sourcefile.Substitute(":", "@");
newname << '@' << sourcefile;
if (strictdecorate)
{
sc.Message(MSG_ERROR, "Tried to define class '%s' more than once.", typeName.GetChars());
}
else
{
// Due to backwards compatibility issues this cannot be an unconditional error.
sc.Message(MSG_WARNING, "Tried to define class '%s' more than once. Renaming class to '%s'", typeName.GetChars(), newname.GetChars());
}
type = static_cast<PClassActor *>(parent->CreateDerivedClass(newname, parent->Size));
if (type == nullptr)
{
// This we cannot handle cleanly anymore. Let's just abort and forget about the odd mod out that was this careless.
sc.Message(MSG_FATAL, "Tried to define class '%s' more than twice in the same file.", typeName.GetChars());
}
}
return type;
}
//==========================================================================
//
// Starts a new actor definition
@ -141,7 +172,7 @@ PClassActor *CreateNewActor(const FScriptPosition &sc, FName typeName, FName par
else
{
create:
ti = static_cast<PClassActor *>(parent->CreateDerivedClass (typeName, parent->Size));
ti = DecoDerivedClass(sc, parent, typeName);
}
ti->Replacee = ti->Replacement = NULL;
@ -428,6 +459,16 @@ void LoadActors ()
while ((lump = Wads.FindLump ("DECORATE", &lastlump)) != -1)
{
FScanner sc(lump);
if (Wads.GetLumpFile(lump) == 0)
{
// define namespace 'zdoom'
}
else
{
// use namespace 'zdoom'
}
ParseDecorate (sc);
}
FinishThingdef();

View file

@ -52,7 +52,8 @@
#include "v_palette.h"
#include "d_player.h"
CVAR( Float, blood_fade_scalar, 1.0f, CVAR_ARCHIVE ) // [SP] Pulled from Skulltag - changed default from 0.5 to 1.0
CVAR( Float, pickup_fade_scalar, 1.0f, CVAR_ARCHIVE ) // [SP] Uses same logic as blood_fade_scalar except for pickups
// [RH] Amount of red flash for up to 114 damage points. Calculated by hand
// using a logarithmic scale and my trusty HP48G.
@ -113,6 +114,9 @@ void V_AddPlayerBlend (player_t *CPlayer, float blend[4], float maxinvalpha, int
if (CPlayer->bonuscount)
{
cnt = CPlayer->bonuscount << 3;
// [SP] Allow player to tone down intensity of pickup flash.
cnt = (int)( cnt * pickup_fade_scalar );
V_AddBlend (RPART(gameinfo.pickupcolor)/255.f, GPART(gameinfo.pickupcolor)/255.f,
BPART(gameinfo.pickupcolor)/255.f, cnt > 128 ? 0.5f : cnt / 255.f, blend);
@ -124,7 +128,10 @@ void V_AddPlayerBlend (player_t *CPlayer, float blend[4], float maxinvalpha, int
if (painFlash.a != 0)
{
cnt = DamageToAlpha[MIN (113, CPlayer->damagecount * painFlash.a / 255)];
// [BC] Allow users to tone down the intensity of the blood on the screen.
cnt = (int)( cnt * blood_fade_scalar );
if (cnt)
{
if (cnt > maxpainblend)

View file

@ -58,6 +58,8 @@ ACTOR Actor native //: Thinker
native float GetSpriteRotation(int ptr = AAPTR_DEFAULT);
native int GetMissileDamage(int mask, int add, int ptr = AAPTR_DEFAULT);
action native int OverlayID();
action native float OverlayX(int layer = 0);
action native float OverlayY(int layer = 0);
// Action functions
// Meh, MBF redundant functions. Only for DeHackEd support.

View file

@ -1782,6 +1782,8 @@ DSPLYMNU_CAPFPS = "Rendering Interpolation";
DSPLYMNU_COLUMNMETHOD = "Column render mode";
DSPLYMNU_WIPETYPE = "Screen wipe style";
DSPLYMNU_SHOWENDOOM = "Show ENDOOM screen";
DSPLYMNU_BLOODFADE = "Blood Flash Intensity";
DSPLYMNU_PICKUPFADE = "Pickup Flash Intensity";
DSPLYMNU_PALLETEHACK = "DirectDraw palette hack"; // Not used
DSPLYMNU_ATTACHEDSURFACES = "Use attached surfaces"; // Not used
DSPLYMNU_STRETCHSKY = "Stretch short skies";
@ -1803,7 +1805,6 @@ DSPLYMNU_DIMCOLOR = "Dim color";
DSPLYMNU_MOVEBOB = "View bob amount while moving";
DSPLYMNU_STILLBOB = "View bob amount while not moving";
DSPLYMNU_BOBSPEED = "Weapon bob speed";
DSPLYMNU_PIFLASH = "Show pickup screen flash";
// HUD Options
HUDMNU_TITLE = "HUD Options";

View file

@ -674,6 +674,9 @@ OptionMenu "VideoOptions"
Option "$DSPLYMNU_VSYNC", "vid_vsync", "OnOff"
Option "$DSPLYMNU_CAPFPS", "cl_capfps", "OffOn"
Slider "$DSPLYMNU_BLOODFADE", "blood_fade_scalar", 0.0, 1.0, 0.05, 1
Slider "$DSPLYMNU_PICKUPFADE", "pickup_fade_scalar", 0.0, 1.0, 0.05, 1
Option "$DSPLYMNU_COLUMNMETHOD", "r_columnmethod", "ColumnMethods"
StaticText " "
Option "$DSPLYMNU_WIPETYPE", "wipetype", "Wipes"
@ -688,7 +691,6 @@ OptionMenu "VideoOptions"
Option "$DSPLYMNU_STRETCHSKY", "r_stretchsky", "OnOff"
Option "$DSPLYMNU_DRAWFUZZ", "r_drawfuzz", "Fuzziness"
Slider "$DSPLYMNU_TRANSSOUL", "transsouls", 0.25, 1.0, 0.05, 2
Option "$DSPLYMNU_PIFLASH", "r_pickupflash", "OnOff"
Option "$DSPLYMNU_FAKECONTRAST", "r_fakecontrast", "Contrast"
Option "$DSPLYMNU_ROCKETTRAILS", "cl_rockettrails", "RocketTrailTypes"
Option "$DSPLYMNU_BLOODTYPE", "cl_bloodtype", "BloodTypes"
@ -705,6 +707,7 @@ OptionMenu "VideoOptions"
Slider "$DSPLYMNU_MOVEBOB", "movebob", 0, 1.0, 0.05, 2
Slider "$DSPLYMNU_STILLBOB", "stillbob", 0, 1.0, 0.05, 2
Slider "$DSPLYMNU_BOBSPEED", "wbobspeed", 0, 2.0, 0.1, 2
}
//-------------------------------------------------------------------------------------------