- Fixed: The save percentage for Doom's green armor was slightly too low

which caused roundoff errors that made it less than 1/3 effective.
- Added support for "RRGGBB" strings to V_GetColor.
- Fixed: Desaturation maps for the TEXTURES lump were calculated incorrectly.
- Changed GetSpriteIndex to cache the last used sprite name so that the code
  using this function doesn't have to do it itself.
- Moved some more code for the state parser into p_states.cpp.
- Fixed: TDeletingArray should not try to delete NULL pointers.

SVN r1312 (trunk)
This commit is contained in:
Christoph Oelckers 2008-12-07 12:11:59 +00:00
parent 238de9cda1
commit 081658d3d5
24 changed files with 2428 additions and 2351 deletions

View file

@ -1,3 +1,13 @@
December 7, 2008 (Changes by Graf Zahl)
- Fixed: The save percentage for Doom's green armor was slightly too low
which caused roundoff errors that made it less than 1/3 effective.
- Added support for "RRGGBB" strings to V_GetColor.
- Fixed: Desaturation maps for the TEXTURES lump were calculated incorrectly.
- Changed GetSpriteIndex to cache the last used sprite name so that the code
using this function doesn't have to do it itself.
- Moved some more code for the state parser into p_states.cpp.
- Fixed: TDeletingArray should not try to delete NULL pointers.
December 6, 2008
- Added binary (b) and hexadecimal (x) cast types for ACS's various print
statements.

View file

@ -820,31 +820,31 @@ static int PatchThing (int thingy)
}
if (!strnicmp (Line1, "Initial", 7))
statedef.AddState("Spawn", state ? state : GetDefault<AActor>()->SpawnState);
statedef.SetStateLabel("Spawn", state ? state : GetDefault<AActor>()->SpawnState);
else if (!strnicmp (Line1, "First moving", 12))
statedef.AddState("See", state);
statedef.SetStateLabel("See", state);
else if (!strnicmp (Line1, "Injury", 6))
statedef.AddState("Pain", state);
statedef.SetStateLabel("Pain", state);
else if (!strnicmp (Line1, "Close attack", 12))
{
if (thingy != 1) // Not for players!
{
statedef.AddState("Melee", state);
statedef.SetStateLabel("Melee", state);
}
}
else if (!strnicmp (Line1, "Far attack", 10))
{
if (thingy != 1) // Not for players!
{
statedef.AddState("Missile", state);
statedef.SetStateLabel("Missile", state);
}
}
else if (!strnicmp (Line1, "Death", 5))
statedef.AddState("Death", state);
statedef.SetStateLabel("Death", state);
else if (!strnicmp (Line1, "Exploding", 9))
statedef.AddState("XDeath", state);
statedef.SetStateLabel("XDeath", state);
else if (!strnicmp (Line1, "Respawn", 7))
statedef.AddState("Raise", state);
statedef.SetStateLabel("Raise", state);
}
else if (stricmp (Line1 + linelen - 6, " sound") == 0)
{
@ -1394,15 +1394,15 @@ static int PatchWeapon (int weapNum)
}
if (strnicmp (Line1, "Deselect", 8) == 0)
statedef.AddState("Select", state);
statedef.SetStateLabel("Select", state);
else if (strnicmp (Line1, "Select", 6) == 0)
statedef.AddState("Deselect", state);
statedef.SetStateLabel("Deselect", state);
else if (strnicmp (Line1, "Bobbing", 7) == 0)
statedef.AddState("Ready", state);
statedef.SetStateLabel("Ready", state);
else if (strnicmp (Line1, "Shooting", 8) == 0)
statedef.AddState("Fire", state);
statedef.SetStateLabel("Fire", state);
else if (strnicmp (Line1, "Firing", 6) == 0)
statedef.AddState("Flash", state);
statedef.SetStateLabel("Flash", state);
}
else if (stricmp (Line1, "Ammo type") == 0)
{

View file

@ -58,6 +58,9 @@ extern void LoadActors ();
int GetSpriteIndex(const char * spritename)
{
static char lastsprite[5];
static int lastindex;
// Make sure that the string is upper case and 4 characters long
char upper[5]={0,0,0,0,0};
for (int i = 0; spritename[i] != 0 && i < 4; i++)
@ -65,18 +68,25 @@ int GetSpriteIndex(const char * spritename)
upper[i] = toupper (spritename[i]);
}
// cache the name so if the next one is the same the function doesn't have to perform a search.
if (!strcmp(upper, lastsprite))
{
return lastindex;
}
strcpy(lastsprite, upper);
for (unsigned i = 0; i < sprites.Size (); ++i)
{
if (strcmp (sprites[i].name, spritename) == 0)
if (strcmp (sprites[i].name, upper) == 0)
{
return (int)i;
return (lastindex = (int)i);
}
}
spritedef_t temp;
strcpy (temp.name, upper);
temp.numframes = 0;
temp.spriteframes = 0;
return (int)sprites.Push (temp);
return (lastindex = (int)sprites.Push (temp));
}

View file

@ -29,37 +29,6 @@
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
** Important restrictions because of the way FState is structured:
**
** The range of Frame is [0,63]. Since sprite naming conventions
** are even more restrictive than this, this isn't something to
** really worry about.
**
** The range of Tics is [-1,65534]. If Misc1 is important, then
** the range of Tics is reduced to [-1,254], because Misc1 also
** doubles as the high byte of the tic.
**
** The range of Misc1 is [-128,127] and Misc2's range is [0,255].
**
** When compiled with Visual C++, this struct is 16 bytes. With
** any other compiler (assuming a 32-bit architecture), it is 20 bytes.
** This is because with VC++, I can use the charizing operator to
** initialize the name array to exactly 4 chars. If GCC would
** compile something like char t = "PLYR"[0]; as char t = 'P'; then GCC
** could also use the 16-byte version. Unfortunately, GCC compiles it
** more like:
**
** char t;
** void initializer () {
** static const char str[]="PLYR";
** t = str[0];
** }
**
** While this does allow the use of a 16-byte FState, the additional
** code amounts to more than 4 bytes.
**
** If C++ would allow char name[4] = "PLYR"; without an error (as C does),
** I could just initialize the name as a regular string and be done with it.
*/
#ifndef __INFO_H__

View file

@ -366,17 +366,33 @@ FStateDefine * FStateDefinitions::FindStateAddress(const char *name)
//==========================================================================
//
// Adds a new state tp the curremt list
// Adds a new state to the curremt list
//
//==========================================================================
void FStateDefinitions::AddState (const char *statename, FState *state, BYTE defflags)
void FStateDefinitions::SetStateLabel (const char *statename, FState *state, BYTE defflags)
{
FStateDefine *std = FindStateAddress(statename);
std->State = state;
std->DefineFlags = defflags;
}
//==========================================================================
//
// Adds a new state to the curremt list
//
//==========================================================================
void FStateDefinitions::AddStateLabel (const char *statename)
{
intptr_t index = StateArray.Size();
FStateDefine *std = FindStateAddress(statename);
std->State = (FState *)(index+1);
std->DefineFlags = SDF_INDEX;
laststate = NULL;
lastlabel = index;
}
//==========================================================================
//
// Finds the state associated with the given name
@ -457,7 +473,7 @@ void FStateDefinitions::InstallStates(FActorInfo *info, AActor *defaults)
if (state == NULL)
{
// A NULL spawn state will crash the engine so set it to something valid.
AddState("Spawn", GetDefault<AActor>()->SpawnState);
SetStateLabel("Spawn", GetDefault<AActor>()->SpawnState);
}
if (info->StateList != NULL)
@ -505,13 +521,17 @@ void FStateDefinitions::MakeStateList(const FStateLabels *list, TArray<FStateDef
void FStateDefinitions::MakeStateDefines(const PClass *cls)
{
if (cls->ActorInfo && cls->ActorInfo->StateList)
StateArray.Clear();
laststate = NULL;
lastlabel = -1;
if (cls != NULL && cls->ActorInfo != NULL && cls->ActorInfo->StateList != NULL)
{
MakeStateList(cls->ActorInfo->StateList, StateLabels);
}
else
{
ClearStateLabels();
StateLabels.Clear();
}
}
@ -559,7 +579,7 @@ void FStateDefinitions::RetargetStatePointers (intptr_t count, const char *targe
{
for(unsigned i = 0;i<statelist.Size(); i++)
{
if (statelist[i].State == (FState*)count)
if (statelist[i].State == (FState*)count && statelist[i].DefineFlags == SDF_INDEX)
{
if (target == NULL)
{
@ -709,6 +729,118 @@ void FStateDefinitions::ResolveGotoLabels (FActorInfo *actor, AActor *defaults,
}
//==========================================================================
//
// SetGotoLabel
//
// sets a jump at the current state or retargets a label
//
//==========================================================================
bool FStateDefinitions::SetGotoLabel(const char *string)
{
// copy the text - this must be resolved later!
if (laststate != NULL)
{ // Following a state definition: Modify it.
laststate->NextState = (FState*)copystring(string);
laststate->DefineFlags = SDF_LABEL;
return true;
}
else if (lastlabel >= 0)
{ // Following a label: Retarget it.
RetargetStates (lastlabel+1, string);
return true;
}
return false;
}
//==========================================================================
//
// SetStop
//
// sets a stop operation
//
//==========================================================================
bool FStateDefinitions::SetStop()
{
if (laststate != NULL)
{
laststate->DefineFlags = SDF_STOP;
return true;
}
else if (lastlabel >=0)
{
RetargetStates (lastlabel+1, NULL);
return true;
}
return false;
}
//==========================================================================
//
// SetWait
//
// sets a wait or fail operation
//
//==========================================================================
bool FStateDefinitions::SetWait()
{
if (laststate != NULL)
{
laststate->DefineFlags = SDF_WAIT;
return true;
}
return false;
}
//==========================================================================
//
// SetLoop
//
// sets a loop operation
//
//==========================================================================
bool FStateDefinitions::SetLoop()
{
if (laststate != NULL)
{
laststate->DefineFlags = SDF_INDEX;
laststate->NextState = (FState*)(lastlabel+1);
return true;
}
return false;
}
//==========================================================================
//
// AddStates
// adds some state to the current definition set
//
//==========================================================================
bool FStateDefinitions::AddStates(FState *state, const char *framechars)
{
bool error = false;
while (*framechars)
{
int frame=((*framechars++)&223)-'A';
if (frame<0 || frame>28)
{
frame = 0;
error = true;
}
state->Frame=(state->Frame&(SF_FULLBRIGHT))|frame;
StateArray.Push(*state);
}
laststate = &StateArray[StateArray.Size() - 1];
return !error;
}
//==========================================================================
//
// FinishStates
@ -716,7 +848,7 @@ void FStateDefinitions::ResolveGotoLabels (FActorInfo *actor, AActor *defaults,
//
//==========================================================================
int FStateDefinitions::FinishStates (FActorInfo *actor, AActor *defaults, TArray<FState> &StateArray)
int FStateDefinitions::FinishStates (FActorInfo *actor, AActor *defaults)
{
static int c=0;
int count = StateArray.Size();
@ -770,6 +902,12 @@ int FStateDefinitions::FinishStates (FActorInfo *actor, AActor *defaults, TArray
}
//==========================================================================
//
// Prints all state label info to the logfile
//
//==========================================================================
void DumpStateHelper(FStateLabels *StateList, const FString &prefix)
{
for (int i = 0; i < StateList->NumLabels; i++)

View file

@ -911,12 +911,12 @@ FString FScanner::TokenName (int token, const char *string)
"'global'",
"'self'",
"'stop'",
"'pickup'",
"'breakable'",
"'projectile'",
"'#include'",
"'fixed_t'",
"'angle_t'",
"'abs'",
"'random'",
"'random2'"
};
FString work;

View file

@ -29,7 +29,7 @@ public:
const SavedPos SavePos();
void RestorePos(const SavedPos &pos);
FString TokenName(int token, const char *string=NULL);
static FString TokenName(int token, const char *string=NULL);
bool GetString();
void MustGetString();
@ -203,14 +203,12 @@ enum
TK_Global,
TK_Self,
TK_Stop,
TK_Eval,
TK_EvalNot,
TK_Pickup,
TK_Breakable,
TK_Projectile,
TK_Include,
TK_Fixed_t,
TK_Angle_t,
TK_Abs,
TK_Random,
TK_Random2,
TK_LastToken
};

File diff suppressed because it is too large Load diff

View file

@ -142,11 +142,11 @@ std2:
/* other DECORATE top level keywords */
'#include' { RET(TK_Include); }
'pickup' { RET(TK_Pickup); }
'breakable' { RET(TK_Breakable); }
'projectile' { RET(TK_Projectile); }
'fixed_t' { RET(TK_Fixed_t); }
'angle_t' { RET(TK_Angle_t); }
'abs' { RET(TK_Abs); }
'random' { RET(TK_Random); }
'random2' { RET(TK_Random2); }
L (L|D)* { RET(TK_Identifier); }

View file

@ -299,6 +299,7 @@ public:
{
for (unsigned int i = 0; i < TArray<T,TT>::Size(); ++i)
{
if ((*this)[i] != NULL)
delete (*this)[i];
}
}

View file

@ -443,7 +443,7 @@ BYTE * GetBlendMap(PalEntry blend, BYTE *blendwork)
default:
if (blend.r >= BLEND_DESATURATE1 && blend.r <= BLEND_DESATURATE31)
{
return DesaturateColormap[blend - BLEND_DESATURATE1];
return DesaturateColormap[blend.r - BLEND_DESATURATE1];
}
else
{
@ -509,7 +509,7 @@ void FMultiPatchTexture::MakeTexture ()
trans = NullMap;
hasTranslucent = true;
}
else if (Parts[i].Blend != BLEND_NONE)
else if (Parts[i].Blend != 0)
{
trans = GetBlendMap(Parts[i].Blend, blendwork);
}

View file

@ -102,7 +102,7 @@ IMPLEMENT_CLASS (AFakeInventory)
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
FExtraInfo &extra, EDefinitionType def, FScanner &sc);
FExtraInfo &extra, EDefinitionType def, FScanner &sc, TArray<FState> &StateArray);
static void ParseSpriteFrames (FActorInfo *info, TArray<FState> &states, FScanner &sc);
// PRIVATE DATA DEFINITIONS ------------------------------------------------
@ -134,6 +134,7 @@ static const char *RenderStyles[] =
void ParseOldDecoration(FScanner &sc, EDefinitionType def)
{
Baggage bag;
TArray<FState> StateArray;
FExtraInfo extra;
FActorInfo *info;
PClass *type;
@ -156,9 +157,9 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
sc.MustGetStringName("{");
memset (&extra, 0, sizeof(extra));
ParseInsideDecoration (bag, (AActor *)(type->Defaults), extra, def, sc);
ParseInsideDecoration (bag, (AActor *)(type->Defaults), extra, def, sc, StateArray);
bag.Info->NumOwnedStates = bag.StateArray.Size();
bag.Info->NumOwnedStates = StateArray.Size();
if (bag.Info->NumOwnedStates == 0)
{
sc.ScriptError ("%s does not define any animation frames", typeName.GetChars() );
@ -179,13 +180,13 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
if (extra.IceDeathEnd != 0)
{
// Make a copy of the final frozen frame for A_FreezeDeathChunks
FState icecopy = bag.StateArray[extra.IceDeathEnd-1];
bag.StateArray.Push (icecopy);
FState icecopy = StateArray[extra.IceDeathEnd-1];
StateArray.Push (icecopy);
info->NumOwnedStates += 1;
}
info->OwnedStates = new FState[info->NumOwnedStates];
memcpy (info->OwnedStates, &bag.StateArray[0], info->NumOwnedStates * sizeof(info->OwnedStates[0]));
memcpy (info->OwnedStates, &StateArray[0], info->NumOwnedStates * sizeof(info->OwnedStates[0]));
if (info->NumOwnedStates == 1)
{
info->OwnedStates->Tics = -1;
@ -246,7 +247,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
if (extra.DeathHeight == 0) extra.DeathHeight = ((AActor*)(type->Defaults))->height;
info->Class->Meta.SetMetaFixed (AMETA_DeathHeight, extra.DeathHeight);
}
bag.statedef.AddState("Death", &info->OwnedStates[extra.DeathStart]);
bag.statedef.SetStateLabel("Death", &info->OwnedStates[extra.DeathStart]);
}
// Burn states are the same as death states, except they can optionally terminate
@ -284,7 +285,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
if (extra.BurnHeight == 0) extra.BurnHeight = ((AActor*)(type->Defaults))->height;
type->Meta.SetMetaFixed (AMETA_BurnHeight, extra.BurnHeight);
bag.statedef.AddState("Burn", &info->OwnedStates[extra.FireDeathStart]);
bag.statedef.SetStateLabel("Burn", &info->OwnedStates[extra.FireDeathStart]);
}
// Ice states are similar to burn and death, except their final frame enters
@ -305,11 +306,11 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
info->OwnedStates[i].Tics = 1;
info->OwnedStates[i].Misc1 = 0;
info->OwnedStates[i].SetAction(FindGlobalActionFunction("A_FreezeDeathChunks"));
bag.statedef.AddState("Ice", &info->OwnedStates[extra.IceDeathStart]);
bag.statedef.SetStateLabel("Ice", &info->OwnedStates[extra.IceDeathStart]);
}
else if (extra.bGenericIceDeath)
{
bag.statedef.AddState("Ice", RUNTIME_CLASS(AActor)->ActorInfo->FindState(NAME_GenericFreezeDeath));
bag.statedef.SetStateLabel("Ice", RUNTIME_CLASS(AActor)->ActorInfo->FindState(NAME_GenericFreezeDeath));
}
}
if (def == DEF_BreakableDecoration)
@ -320,7 +321,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
{
((AActor *)(type->Defaults))->flags |= MF_DROPOFF|MF_MISSILE;
}
bag.statedef.AddState("Spawn", &info->OwnedStates[extra.SpawnStart]);
bag.statedef.SetStateLabel("Spawn", &info->OwnedStates[extra.SpawnStart]);
bag.statedef.InstallStates (info, ((AActor *)(type->Defaults)));
}
@ -333,7 +334,7 @@ void ParseOldDecoration(FScanner &sc, EDefinitionType def)
//==========================================================================
static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
FExtraInfo &extra, EDefinitionType def, FScanner &sc)
FExtraInfo &extra, EDefinitionType def, FScanner &sc, TArray<FState> &StateArray)
{
AFakeInventory *const inv = static_cast<AFakeInventory *>(defaults);
char sprite[5] = "TNT1";
@ -382,31 +383,31 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
else if (sc.Compare ("Frames"))
{
sc.MustGetString ();
extra.SpawnStart = bag.StateArray.Size();
ParseSpriteFrames (bag.Info, bag.StateArray, sc);
extra.SpawnEnd = bag.StateArray.Size();
extra.SpawnStart = StateArray.Size();
ParseSpriteFrames (bag.Info, StateArray, sc);
extra.SpawnEnd = StateArray.Size();
}
else if ((def == DEF_BreakableDecoration || def == DEF_Projectile) &&
sc.Compare ("DeathFrames"))
{
sc.MustGetString ();
extra.DeathStart = bag.StateArray.Size();
ParseSpriteFrames (bag.Info, bag.StateArray, sc);
extra.DeathEnd = bag.StateArray.Size();
extra.DeathStart = StateArray.Size();
ParseSpriteFrames (bag.Info, StateArray, sc);
extra.DeathEnd = StateArray.Size();
}
else if (def == DEF_BreakableDecoration && sc.Compare ("IceDeathFrames"))
{
sc.MustGetString ();
extra.IceDeathStart = bag.StateArray.Size();
ParseSpriteFrames (bag.Info, bag.StateArray, sc);
extra.IceDeathEnd = bag.StateArray.Size();
extra.IceDeathStart = StateArray.Size();
ParseSpriteFrames (bag.Info, StateArray, sc);
extra.IceDeathEnd = StateArray.Size();
}
else if (def == DEF_BreakableDecoration && sc.Compare ("BurnDeathFrames"))
{
sc.MustGetString ();
extra.FireDeathStart = bag.StateArray.Size();
ParseSpriteFrames (bag.Info, bag.StateArray, sc);
extra.FireDeathEnd = bag.StateArray.Size();
extra.FireDeathStart = StateArray.Size();
ParseSpriteFrames (bag.Info, StateArray, sc);
extra.FireDeathEnd = StateArray.Size();
}
else if (def == DEF_BreakableDecoration && sc.Compare ("GenericIceDeath"))
{
@ -587,16 +588,16 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults,
unsigned int i;
int spr = GetSpriteIndex(sprite);
for (i = 0; i < bag.StateArray.Size(); ++i)
for (i = 0; i < StateArray.Size(); ++i)
{
bag.StateArray[i].sprite = spr;
StateArray[i].sprite = spr;
}
if (extra.DeathSprite[0] && extra.DeathEnd != 0)
{
int spr = GetSpriteIndex(extra.DeathSprite);
for (i = extra.DeathStart; i < extra.DeathEnd; ++i)
{
bag.StateArray[i].sprite = spr;
StateArray[i].sprite = spr;
}
}
}

View file

@ -78,8 +78,7 @@ PSymbolTable GlobalSymbols;
// Starts a new actor definition
//
//==========================================================================
FActorInfo *CreateNewActor(const FScriptPosition &sc, FName typeName, FName parentName, FName replaceName,
int DoomEdNum, bool native)
FActorInfo *CreateNewActor(FName typeName, FName parentName, bool native)
{
const PClass *replacee = NULL;
PClass *ti = NULL;
@ -93,31 +92,15 @@ FActorInfo *CreateNewActor(const FScriptPosition &sc, FName typeName, FName pare
if (parent == NULL)
{
sc.Message(MSG_FATAL, "Parent type '%s' not found in %s", parentName.GetChars(), typeName.GetChars());
I_Error( "Parent type '%s' not found in %s", parentName.GetChars(), typeName.GetChars());
}
else if (!parent->IsDescendantOf(RUNTIME_CLASS(AActor)))
{
sc.Message(MSG_FATAL, "Parent type '%s' is not an actor in %s", parentName.GetChars(), typeName.GetChars());
I_Error( "Parent type '%s' is not an actor in %s", parentName.GetChars(), typeName.GetChars());
}
else if (parent->ActorInfo == NULL)
{
sc.Message(MSG_FATAL, "uninitialized parent type '%s' in %s", parentName.GetChars(), typeName.GetChars());
}
}
// Check for "replaces"
if (replaceName != NAME_None)
{
// Get actor name
replacee = PClass::FindClass (replaceName);
if (replacee == NULL)
{
sc.Message(MSG_FATAL, "Replaced type '%s' not found in %s", replaceName.GetChars(), typeName.GetChars());
}
else if (replacee->ActorInfo == NULL)
{
sc.Message(MSG_FATAL, "Replaced type '%s' is not an actor in %s", replaceName.GetChars(), typeName.GetChars());
I_Error( "uninitialized parent type '%s' in %s", parentName.GetChars(), typeName.GetChars());
}
}
@ -126,15 +109,15 @@ FActorInfo *CreateNewActor(const FScriptPosition &sc, FName typeName, FName pare
ti = (PClass*)PClass::FindClass(typeName);
if (ti == NULL)
{
sc.Message(MSG_FATAL, "Unknown native class '%s'", typeName.GetChars());
I_Error( "Unknown native class '%s'", typeName.GetChars());
}
else if (ti != RUNTIME_CLASS(AActor) && ti->ParentClass->NativeClass() != parent->NativeClass())
{
sc.Message(MSG_FATAL, "Native class '%s' does not inherit from '%s'", typeName.GetChars(), parentName.GetChars());
I_Error( "Native class '%s' does not inherit from '%s'", typeName.GetChars(), parentName.GetChars());
}
else if (ti->ActorInfo != NULL)
{
sc.Message(MSG_FATAL, "Redefinition of internal class '%s'", typeName.GetChars());
I_Error( "Redefinition of internal class '%s'", typeName.GetChars());
}
ti->InitializeActorInfo();
info = ti->ActorInfo;
@ -145,7 +128,6 @@ FActorInfo *CreateNewActor(const FScriptPosition &sc, FName typeName, FName pare
info = ti->ActorInfo;
}
info->DoomEdNum = -1;
if (parent->ActorInfo->DamageFactors != NULL)
{
// copy damage factors from parent
@ -158,15 +140,40 @@ FActorInfo *CreateNewActor(const FScriptPosition &sc, FName typeName, FName pare
info->PainChances = new PainChanceList;
*info->PainChances = *parent->ActorInfo->PainChances;
}
info->Replacee = info->Replacement = NULL;
info->DoomEdNum = -1;
return info;
}
//==========================================================================
//
//
//
//==========================================================================
void SetReplacement(FActorInfo *info, FName replaceName)
{
// Check for "replaces"
if (replaceName != NAME_None)
{
// Get actor name
const PClass *replacee = PClass::FindClass (replaceName);
if (replacee == NULL)
{
I_Error ("Replaced type '%s' not found in %s", replaceName.GetChars(), info->Class->TypeName.GetChars());
}
else if (replacee->ActorInfo == NULL)
{
I_Error ("Replaced type '%s' is not an actor in %s", replaceName.GetChars(), info->Class->TypeName.GetChars());
}
if (replacee != NULL)
{
replacee->ActorInfo->Replacement = ti->ActorInfo;
ti->ActorInfo->Replacee = replacee->ActorInfo;
replacee->ActorInfo->Replacement = info;
info->Replacee = replacee->ActorInfo;
}
}
if (DoomEdNum > 0) info->DoomEdNum = DoomEdNum;
return info;
}
//==========================================================================
@ -181,14 +188,14 @@ void FinishActor(const FScriptPosition &sc, FActorInfo *info, Baggage &bag)
try
{
bag.statedef.FinishStates (info, defaults, bag.StateArray);
bag.statedef.FinishStates (info, defaults);
}
catch (CRecoverableError &err)
{
sc.Message(MSG_FATAL, "%s", err.GetMessage());
}
bag.statedef.InstallStates (info, defaults);
bag.StateArray.Clear ();
bag.statedef.MakeStateDefines(NULL);
if (bag.DropItemSet)
{
if (bag.DropItemList == NULL)

View file

@ -82,6 +82,9 @@ struct FStateDefine
class FStateDefinitions
{
TArray<FStateDefine> StateLabels;
FState *laststate;
intptr_t lastlabel;
TArray<FState> StateArray;
static FStateDefine *FindStateLabelInList(TArray<FStateDefine> &list, FName name, bool create);
static FStateLabels *CreateStateLabelList(TArray<FStateDefine> &statelist);
@ -96,20 +99,28 @@ class FStateDefinitions
public:
void ClearStateLabels()
FStateDefinitions()
{
StateLabels.Clear();
laststate = NULL;
lastlabel = -1;
}
void AddState (const char * statename, FState * state, BYTE defflags = SDF_STATE);
void SetStateLabel (const char * statename, FState * state, BYTE defflags = SDF_STATE);
void AddStateLabel (const char * statename);
void InstallStates(FActorInfo *info, AActor *defaults);
int FinishStates (FActorInfo *actor, AActor *defaults, TArray<FState> &StateArray);
int FinishStates (FActorInfo *actor, AActor *defaults);
void MakeStateDefines(const PClass *cls);
void AddStateDefines(const FStateLabels *list);
void RetargetStates (intptr_t count, const char *target);
bool SetGotoLabel(const char *string);
bool SetStop();
bool SetWait();
bool SetLoop();
bool AddStates(FState *state, const char *framechars);
int GetStateCount() const { return StateArray.Size(); }
};
//==========================================================================
@ -162,9 +173,10 @@ struct Baggage
int CurrentState;
int Lumpnum;
FStateDefinitions statedef;
TArray<FState> StateArray;
FDropItem *DropItemList;
FScriptPosition ScriptPosition;
};
inline void ResetBaggage (Baggage *bag, const PClass *stateclass)
@ -173,7 +185,6 @@ inline void ResetBaggage (Baggage *bag, const PClass *stateclass)
bag->DropItemSet = false;
bag->CurrentState = 0;
bag->StateSet = false;
bag->StateArray.Clear();
bag->statedef.MakeStateDefines(stateclass);
}
@ -193,7 +204,7 @@ AFuncDesc * FindFunction(const char * string);
int ParseStates(FScanner &sc, FActorInfo *actor, AActor *defaults, Baggage &bag);
void ParseStates(FScanner &sc, FActorInfo *actor, AActor *defaults, Baggage &bag);
PSymbolActionFunction *FindGlobalActionFunction(const char *name);
@ -203,8 +214,8 @@ PSymbolActionFunction *FindGlobalActionFunction(const char *name);
//
//==========================================================================
FActorInfo *CreateNewActor(const FScriptPosition &sc, FName typeName, FName parentName, FName replaceName,
int DoomEdNum, bool native);
FActorInfo *CreateNewActor(FName typeName, FName parentName, bool native);
void SetReplacement(FActorInfo *info, FName replaceName);
void HandleActorFlag(FScanner &sc, Baggage &bag, const char *part1, const char *part2, int mod);
void FinishActor(const FScriptPosition &sc, FActorInfo *info, Baggage &bag);
@ -276,7 +287,7 @@ union FPropParam
const char *s;
};
typedef void (*PropHandler)(AActor *defaults, Baggage &bag, FPropParam *params);
typedef void (*PropHandler)(AActor *defaults, FActorInfo *info, Baggage &bag, FPropParam *params);
enum ECategory
{
@ -307,18 +318,18 @@ int MatchString (const char *in, const char **strings);
#define DEFINE_PROPERTY_BASE(name, paramlist, clas, cat) \
static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, Baggage &bag, FPropParam *params); \
static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, FActorInfo *info, Baggage &bag, FPropParam *params); \
static FPropertyInfo Prop_##name##_##paramlist##_##clas = \
{ #name, #paramlist, RUNTIME_CLASS(A##clas), (PropHandler)Handler_##name##_##paramlist##_##clas, cat }; \
MSVC_PSEG FPropertyInfo *infoptr_##name##_##paramlist##_##clas GCC_PSEG = &Prop_##name##_##paramlist##_##clas; \
static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, Baggage &bag, FPropParam *params)
static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, FActorInfo *info, Baggage &bag, FPropParam *params)
#define DEFINE_PREFIXED_PROPERTY_BASE(prefix, name, paramlist, clas, cat) \
static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, Baggage &bag, FPropParam *params); \
static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, FActorInfo *info, Baggage &bag, FPropParam *params); \
static FPropertyInfo Prop_##name##_##paramlist##_##clas = \
{ #prefix"."#name, #paramlist, RUNTIME_CLASS(A##clas), (PropHandler)Handler_##name##_##paramlist##_##clas, cat }; \
MSVC_PSEG FPropertyInfo *infoptr_##name##_##paramlist##_##clas GCC_PSEG = &Prop_##name##_##paramlist##_##clas; \
static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, Baggage &bag, FPropParam *params)
static void Handler_##name##_##paramlist##_##clas(A##clas *defaults, FActorInfo *info, Baggage &bag, FPropParam *params)
#define DEFINE_PROPERTY(name, paramlist, clas) DEFINE_PROPERTY_BASE(name, paramlist, clas, CAT_PROPERTY)

View file

@ -336,12 +336,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls)
{
return new FxConstant(sc.Float, scpos);
}
else if (sc.CheckToken(TK_Identifier))
{
FName identifier = FName(sc.String);
switch (identifier)
{
case NAME_Random:
else if (sc.CheckToken(TK_Random))
{
FRandom *rng;
@ -364,9 +359,7 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls)
return new FxRandom(rng, min, max, sc);
}
break;
case NAME_Random2:
else if (sc.CheckToken(TK_Random2))
{
FRandom *rng;
@ -392,17 +385,16 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls)
}
return new FxRandom2(rng, mask, sc);
}
break;
case NAME_Abs:
else if (sc.CheckToken(TK_Abs))
{
sc.MustGetToken('(');
FxExpression *x = ParseExpressionM (sc, cls);
sc.MustGetToken(')');
return new FxAbs(x);
}
default:
else if (sc.CheckToken(TK_Identifier))
{
FName identifier = FName(sc.String);
if (sc.CheckToken('('))
{
FArgumentList *args = NULL;
@ -432,7 +424,6 @@ static FxExpression *ParseExpression0 (FScanner &sc, const PClass *cls)
return new FxIdentifier(identifier, sc);
}
}
}
else
{
FString tokname = sc.TokenName(sc.TokenType, sc.String);

View file

@ -1601,9 +1601,13 @@ ExpVal FxAbs::EvalExpression (AActor *self)
FxRandom::FxRandom(FRandom * r, FxExpression *mi, FxExpression *ma, const FScriptPosition &pos)
: FxExpression(pos)
{
rng = r;
if (mi != NULL && ma != NULL)
{
min = new FxIntCast(mi);
max = new FxIntCast(ma);
}
else min = max = NULL;
rng = r;
ValueType = VAL_Int;
}
@ -1646,11 +1650,14 @@ FxExpression *FxRandom::Resolve(FCompileContext &ctx)
ExpVal FxRandom::EvalExpression (AActor *self)
{
ExpVal val;
val.Type = VAL_Int;
if (min != NULL && max != NULL)
{
int minval = min->EvalExpression (self).GetInt();
int maxval = max->EvalExpression (self).GetInt();
ExpVal val;
val.Type = VAL_Int;
if (maxval < minval)
{
@ -1658,6 +1665,11 @@ ExpVal FxRandom::EvalExpression (AActor *self)
}
val.Int = (*rng)(maxval - minval + 1) + minval;
}
else
{
val.Int = (*rng)();
}
return val;
}

View file

@ -145,6 +145,8 @@ FxExpression *ParseParameter(FScanner &sc, PClass *cls, char type, bool constant
case 'X':
case 'x':
case 'Y':
case 'y':
x = ParseExpression (sc, cls);
if (constant && !x->isConstant())
{
@ -190,7 +192,7 @@ static void ParseConstant (FScanner &sc, PSymbolTable * symt, PClass *cls)
else
{
sym->ValueType = VAL_Float;
sym->Value = val.GetFloat();
sym->Float = val.GetFloat();
}
if (symt->AddSymbol (sym) == NULL)
{
@ -654,7 +656,7 @@ static bool ParsePropertyParams(FScanner &sc, FPropertyInfo *prop, AActor *defau
// call the handler
try
{
prop->Handler(defaults, bag, &params[0]);
prop->Handler(defaults, bag.Info, bag, &params[0]);
}
catch (CRecoverableError &error)
{
@ -713,7 +715,7 @@ static void ParseActorProperty(FScanner &sc, Baggage &bag)
}
else if (MatchString(propname, statenames) != -1)
{
bag.statedef.AddState(propname, CheckState (sc, bag.Info->Class));
bag.statedef.SetStateLabel(propname, CheckState (sc, bag.Info->Class));
}
else
{
@ -782,10 +784,13 @@ static void ParseActionDef (FScanner &sc, PClass *cls)
{
case TK_Bool:
case TK_Int:
case TK_Float:
type = 'x';
break;
case TK_Float:
type = 'y';
break;
case TK_Sound: type = 's'; break;
case TK_String: type = 't'; break;
case TK_Name: type = 't'; break;
@ -940,7 +945,10 @@ static FActorInfo *ParseActorHeader(FScanner &sc, Baggage *bag)
try
{
FActorInfo *info = CreateNewActor(sc, typeName, parentName, replaceName, DoomEdNum, native);
FActorInfo *info = CreateNewActor(typeName, parentName, native);
info->DoomEdNum = DoomEdNum > 0? DoomEdNum : -1;
SetReplacement(info, replaceName);
ResetBaggage (bag, info->Class->ParentClass);
bag->Info = info;
bag->Lumpnum = sc.LumpNum;
@ -989,8 +997,6 @@ static void ParseActor(FScanner &sc)
break;
case TK_Identifier:
// other identifier related checks here
case TK_Projectile: // special case: both keyword and property name
ParseActorProperty(sc, bag);
break;
@ -1047,18 +1053,6 @@ void ParseDecorate (FScanner &sc)
ParseEnum (sc, &GlobalSymbols, NULL);
break;
case TK_Pickup:
ParseOldDecoration (sc, DEF_Pickup);
break;
case TK_Breakable:
ParseOldDecoration (sc, DEF_BreakableDecoration);
break;
case TK_Projectile:
ParseOldDecoration (sc, DEF_Projectile);
break;
case TK_Native:
ParseVariable(sc, &GlobalSymbols, NULL);
break;
@ -1079,7 +1073,18 @@ void ParseDecorate (FScanner &sc)
ParseActor (sc);
break;
}
else if (sc.Compare("PICKUP"))
{
ParseOldDecoration (sc, DEF_Pickup);
}
else if (sc.Compare("BREAKABLE"))
{
ParseOldDecoration (sc, DEF_BreakableDecoration);
}
else if (sc.Compare("PROJECTILE"))
{
ParseOldDecoration (sc, DEF_Projectile);
}
default:
// without the option of game filters following, anything but an opening brace
// here means a syntax error.

View file

@ -152,31 +152,31 @@ DEFINE_INFO_PROPERTY(game, T, Actor)
PROP_STRING_PARM(str, 0);
if (!stricmp(str, "Doom"))
{
bag.Info->GameFilter |= GAME_Doom;
info->GameFilter |= GAME_Doom;
}
else if (!stricmp(str, "Heretic"))
{
bag.Info->GameFilter |= GAME_Heretic;
info->GameFilter |= GAME_Heretic;
}
else if (!stricmp(str, "Hexen"))
{
bag.Info->GameFilter |= GAME_Hexen;
info->GameFilter |= GAME_Hexen;
}
else if (!stricmp(str, "Raven"))
{
bag.Info->GameFilter |= GAME_Raven;
info->GameFilter |= GAME_Raven;
}
else if (!stricmp(str, "Strife"))
{
bag.Info->GameFilter |= GAME_Strife;
info->GameFilter |= GAME_Strife;
}
else if (!stricmp(str, "Chex"))
{
bag.Info->GameFilter |= GAME_Chex;
info->GameFilter |= GAME_Chex;
}
else if (!stricmp(str, "Any"))
{
bag.Info->GameFilter = GAME_Any;
info->GameFilter = GAME_Any;
}
else
{
@ -194,7 +194,7 @@ DEFINE_INFO_PROPERTY(spawnid, I, Actor)
{
I_Error ("SpawnID must be in the range [0,255]");
}
else bag.Info->SpawnID=(BYTE)id;
else info->SpawnID=(BYTE)id;
}
//==========================================================================
@ -222,7 +222,7 @@ DEFINE_INFO_PROPERTY(conversationid, IiI, Actor)
{
I_Error ("ConversationID must be in the range [0,1000]");
}
else StrifeTypes[convid] = bag.Info->Class;
else StrifeTypes[convid] = info->Class;
}
//==========================================================================
@ -236,9 +236,16 @@ DEFINE_INFO_PROPERTY(conversationid, IiI, Actor)
//==========================================================================
DEFINE_PROPERTY(skip_super, 0, Actor)
{
if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(AInventory)))
if (info->Class->IsDescendantOf(RUNTIME_CLASS(AInventory)))
{
Printf("'skip_super' in definition of inventory item '%s' ignored.", bag.Info->Class->TypeName.GetChars() );
bag.ScriptPosition.Message(MSG_WARNING,
"'skip_super' in definition of inventory item '%s' ignored.", info->Class->TypeName.GetChars() );
return;
}
if (bag.StateSet)
{
bag.ScriptPosition.Message(MSG_WARNING,
"'skip_super' must appear before any state definitions.");
return;
}
@ -256,7 +263,7 @@ DEFINE_PROPERTY(skip_super, 0, Actor)
DEFINE_PROPERTY(tag, S, Actor)
{
PROP_STRING_PARM(str, 0);
bag.Info->Class->Meta.SetMetaString(AMETA_StrifeName, str);
info->Class->Meta.SetMetaString(AMETA_StrifeName, str);
}
//==========================================================================
@ -274,7 +281,7 @@ DEFINE_PROPERTY(health, I, Actor)
DEFINE_PROPERTY(gibhealth, I, Actor)
{
PROP_INT_PARM(id, 0);
bag.Info->Class->Meta.SetMetaInt (AMETA_GibHealth, id);
info->Class->Meta.SetMetaInt (AMETA_GibHealth, id);
}
//==========================================================================
@ -283,7 +290,7 @@ DEFINE_PROPERTY(gibhealth, I, Actor)
DEFINE_PROPERTY(woundhealth, I, Actor)
{
PROP_INT_PARM(id, 0);
bag.Info->Class->Meta.SetMetaInt (AMETA_WoundHealth, id);
info->Class->Meta.SetMetaInt (AMETA_WoundHealth, id);
}
//==========================================================================
@ -312,8 +319,8 @@ DEFINE_PROPERTY(painchance, ZI, Actor)
if (!stricmp(str, "Normal")) painType = NAME_None;
else painType=str;
if (bag.Info->PainChances == NULL) bag.Info->PainChances=new PainChanceList;
(*bag.Info->PainChances)[painType] = (BYTE)id;
if (info->PainChances == NULL) info->PainChances=new PainChanceList;
(*info->PainChances)[painType] = (BYTE)id;
}
}
@ -478,7 +485,7 @@ DEFINE_PROPERTY(activesound, S, Actor)
DEFINE_PROPERTY(howlsound, S, Actor)
{
PROP_STRING_PARM(str, 0);
bag.Info->Class->Meta.SetMetaInt (AMETA_HowlSound, S_FindSound(str));
info->Class->Meta.SetMetaInt (AMETA_HowlSound, S_FindSound(str));
}
//==========================================================================
@ -559,7 +566,7 @@ DEFINE_PROPERTY(alpha, F, Actor)
DEFINE_PROPERTY(obituary, S, Actor)
{
PROP_STRING_PARM(str, 0);
bag.Info->Class->Meta.SetMetaString (AMETA_Obituary, str);
info->Class->Meta.SetMetaString (AMETA_Obituary, str);
}
//==========================================================================
@ -568,7 +575,7 @@ DEFINE_PROPERTY(obituary, S, Actor)
DEFINE_PROPERTY(hitobituary, S, Actor)
{
PROP_STRING_PARM(str, 0);
bag.Info->Class->Meta.SetMetaString (AMETA_HitObituary, str);
info->Class->Meta.SetMetaString (AMETA_HitObituary, str);
}
//==========================================================================
@ -576,7 +583,7 @@ DEFINE_PROPERTY(hitobituary, S, Actor)
//==========================================================================
DEFINE_PROPERTY(donthurtshooter, 0, Actor)
{
bag.Info->Class->Meta.SetMetaInt (ACMETA_DontHurtShooter, true);
info->Class->Meta.SetMetaInt (ACMETA_DontHurtShooter, true);
}
//==========================================================================
@ -585,7 +592,7 @@ DEFINE_PROPERTY(donthurtshooter, 0, Actor)
DEFINE_PROPERTY(explosionradius, I, Actor)
{
PROP_INT_PARM(id, 0);
bag.Info->Class->Meta.SetMetaInt (ACMETA_ExplosionRadius, id);
info->Class->Meta.SetMetaInt (ACMETA_ExplosionRadius, id);
}
//==========================================================================
@ -594,7 +601,7 @@ DEFINE_PROPERTY(explosionradius, I, Actor)
DEFINE_PROPERTY(explosiondamage, I, Actor)
{
PROP_INT_PARM(id, 0);
bag.Info->Class->Meta.SetMetaInt (ACMETA_ExplosionDamage, id);
info->Class->Meta.SetMetaInt (ACMETA_ExplosionDamage, id);
}
//==========================================================================
@ -605,7 +612,7 @@ DEFINE_PROPERTY(deathheight, F, Actor)
PROP_FIXED_PARM(h, 0);
// AActor::Die() uses a height of 0 to mean "cut the height to 1/4",
// so if a height of 0 is desired, store it as -1.
bag.Info->Class->Meta.SetMetaFixed (AMETA_DeathHeight, h <= 0 ? -1 : h);
info->Class->Meta.SetMetaFixed (AMETA_DeathHeight, h <= 0 ? -1 : h);
}
//==========================================================================
@ -615,7 +622,7 @@ DEFINE_PROPERTY(burnheight, F, Actor)
{
PROP_FIXED_PARM(h, 0);
// The note above for AMETA_DeathHeight also applies here.
bag.Info->Class->Meta.SetMetaFixed (AMETA_BurnHeight, h <= 0 ? -1 : h);
info->Class->Meta.SetMetaFixed (AMETA_BurnHeight, h <= 0 ? -1 : h);
}
//==========================================================================
@ -642,7 +649,7 @@ DEFINE_PROPERTY(meleethreshold, F, Actor)
DEFINE_PROPERTY(meleedamage, I, Actor)
{
PROP_INT_PARM(id, 0);
bag.Info->Class->Meta.SetMetaInt (ACMETA_MeleeDamage, id);
info->Class->Meta.SetMetaInt (ACMETA_MeleeDamage, id);
}
//==========================================================================
@ -660,7 +667,7 @@ DEFINE_PROPERTY(meleerange, F, Actor)
DEFINE_PROPERTY(meleesound, S, Actor)
{
PROP_STRING_PARM(str, 0);
bag.Info->Class->Meta.SetMetaInt (ACMETA_MeleeSound, S_FindSound(str));
info->Class->Meta.SetMetaInt (ACMETA_MeleeSound, S_FindSound(str));
}
//==========================================================================
@ -669,7 +676,7 @@ DEFINE_PROPERTY(meleesound, S, Actor)
DEFINE_PROPERTY(missiletype, S, Actor)
{
PROP_STRING_PARM(str, 0);
bag.Info->Class->Meta.SetMetaInt (ACMETA_MissileName, FName(str));
info->Class->Meta.SetMetaInt (ACMETA_MissileName, FName(str));
}
//==========================================================================
@ -678,7 +685,7 @@ DEFINE_PROPERTY(missiletype, S, Actor)
DEFINE_PROPERTY(missileheight, F, Actor)
{
PROP_FIXED_PARM(id, 0);
bag.Info->Class->Meta.SetMetaFixed (ACMETA_MissileHeight, id);
info->Class->Meta.SetMetaFixed (ACMETA_MissileHeight, id);
}
//==========================================================================
@ -691,7 +698,7 @@ DEFINE_PROPERTY(translation, L, Actor)
if (type == 0)
{
PROP_INT_PARM(trans, 1);
int max = (gameinfo.gametype==GAME_Strife || (bag.Info->GameFilter&GAME_Strife)) ? 6:2;
int max = (gameinfo.gametype==GAME_Strife || (info->GameFilter&GAME_Strife)) ? 6:2;
if (trans < 0 || trans > max)
{
I_Error ("Translation must be in the range [0,%d]", max);
@ -739,7 +746,7 @@ DEFINE_PROPERTY(bloodcolor, C, Actor)
PalEntry pe = color;
pe.a = CreateBloodTranslation(pe);
bag.Info->Class->Meta.SetMetaInt (AMETA_BloodColor, pe);
info->Class->Meta.SetMetaInt (AMETA_BloodColor, pe);
}
@ -754,21 +761,21 @@ DEFINE_PROPERTY(bloodtype, Sss, Actor)
FName blood = str;
// normal blood
bag.Info->Class->Meta.SetMetaInt (AMETA_BloodType, blood);
info->Class->Meta.SetMetaInt (AMETA_BloodType, blood);
if (PROP_PARM_COUNT > 1)
{
blood = str1;
}
// blood splatter
bag.Info->Class->Meta.SetMetaInt (AMETA_BloodType2, blood);
info->Class->Meta.SetMetaInt (AMETA_BloodType2, blood);
if (PROP_PARM_COUNT > 2)
{
blood = str2;
}
// axe blood
bag.Info->Class->Meta.SetMetaInt (AMETA_BloodType3, blood);
info->Class->Meta.SetMetaInt (AMETA_BloodType3, blood);
}
//==========================================================================
@ -825,13 +832,13 @@ DEFINE_PROPERTY(damagefactor, SF, Actor)
PROP_STRING_PARM(str, 0);
PROP_FIXED_PARM(id, 1);
if (bag.Info->DamageFactors == NULL) bag.Info->DamageFactors=new DmgFactors;
if (info->DamageFactors == NULL) info->DamageFactors=new DmgFactors;
FName dmgType;
if (!stricmp(str, "Normal")) dmgType = NAME_None;
else dmgType=str;
(*bag.Info->DamageFactors)[dmgType]=id;
(*info->DamageFactors)[dmgType]=id;
}
//==========================================================================
@ -867,7 +874,7 @@ DEFINE_PROPERTY(maxdropoffheight, F, Actor)
DEFINE_PROPERTY(poisondamage, I, Actor)
{
PROP_INT_PARM(i, 0);
bag.Info->Class->Meta.SetMetaInt (AMETA_PoisonDamage, i);
info->Class->Meta.SetMetaInt (AMETA_PoisonDamage, i);
}
//==========================================================================
@ -876,7 +883,7 @@ DEFINE_PROPERTY(poisondamage, I, Actor)
DEFINE_PROPERTY(fastspeed, F, Actor)
{
PROP_FIXED_PARM(i, 0);
bag.Info->Class->Meta.SetMetaFixed (AMETA_FastSpeed, i);
info->Class->Meta.SetMetaFixed (AMETA_FastSpeed, i);
}
//==========================================================================
@ -885,7 +892,7 @@ DEFINE_PROPERTY(fastspeed, F, Actor)
DEFINE_PROPERTY(radiusdamagefactor, F, Actor)
{
PROP_FIXED_PARM(i, 0);
bag.Info->Class->Meta.SetMetaFixed (AMETA_RDFactor, i);
info->Class->Meta.SetMetaFixed (AMETA_RDFactor, i);
}
//==========================================================================
@ -894,7 +901,7 @@ DEFINE_PROPERTY(radiusdamagefactor, F, Actor)
DEFINE_PROPERTY(cameraheight, F, Actor)
{
PROP_FIXED_PARM(i, 0);
bag.Info->Class->Meta.SetMetaFixed (AMETA_CameraHeight, i);
info->Class->Meta.SetMetaFixed (AMETA_CameraHeight, i);
}
//==========================================================================
@ -980,7 +987,7 @@ DEFINE_CLASS_PROPERTY(backpackmaxamount, I, Ammo)
DEFINE_CLASS_PROPERTY(dropamount, I, Ammo)
{
PROP_INT_PARM(i, 0);
bag.Info->Class->Meta.SetMetaInt (AIMETA_DropAmount, i);
info->Class->Meta.SetMetaInt (AIMETA_DropAmount, i);
}
//==========================================================================
@ -1018,11 +1025,11 @@ DEFINE_CLASS_PROPERTY(saveamount, I, Armor)
PROP_INT_PARM(i, 0);
// Special case here because this property has to work for 2 unrelated classes
if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
if (info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
{
((ABasicArmorPickup*)defaults)->SaveAmount=i;
}
else if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
else if (info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
{
((ABasicArmorBonus*)defaults)->SaveAmount=i;
}
@ -1039,18 +1046,19 @@ DEFINE_CLASS_PROPERTY(savepercent, F, Armor)
{
PROP_FIXED_PARM(i, 0);
i = clamp(i, 0, 100*FRACUNIT)/100;
// Special case here because this property has to work for 2 unrelated classes
if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
if (info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
{
((ABasicArmorPickup*)defaults)->SavePercent=i;
((ABasicArmorPickup*)defaults)->SavePercent = i;
}
else if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
else if (info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
{
((ABasicArmorBonus*)defaults)->SavePercent=i;
((ABasicArmorBonus*)defaults)->SavePercent = i;
}
else
{
I_Error("\"Armor.SavePercent\" requires an actor of type \"Armor\"");
I_Error("\"Armor.SavePercent\" requires an actor of type \"Armor\"\n");
}
}
@ -1062,11 +1070,11 @@ DEFINE_CLASS_PROPERTY(maxabsorb, I, Armor)
PROP_INT_PARM(i, 0);
// Special case here because this property has to work for 2 unrelated classes
if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
if (info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
{
((ABasicArmorPickup*)defaults)->MaxAbsorb = i;
}
else if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
else if (info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
{
((ABasicArmorBonus*)defaults)->MaxAbsorb = i;
}
@ -1084,11 +1092,11 @@ DEFINE_CLASS_PROPERTY(maxfullabsorb, I, Armor)
PROP_INT_PARM(i, 0);
// Special case here because this property has to work for 2 unrelated classes
if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
if (info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorPickup)))
{
((ABasicArmorPickup*)defaults)->MaxFullAbsorb = i;
}
else if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
else if (info->Class->IsDescendantOf(RUNTIME_CLASS(ABasicArmorBonus)))
{
((ABasicArmorBonus*)defaults)->MaxFullAbsorb = i;
}
@ -1119,10 +1127,11 @@ DEFINE_CLASS_PROPERTY(icon, S, Inventory)
{
// Don't print warnings if the item is for another game or if this is a shareware IWAD.
// Strife's teaser doesn't contain all the icon graphics of the full game.
if ((bag.Info->GameFilter == GAME_Any || bag.Info->GameFilter & gameinfo.gametype) &&
if ((info->GameFilter == GAME_Any || info->GameFilter & gameinfo.gametype) &&
!(gameinfo.flags&GI_SHAREWARE) && Wads.GetLumpFile(bag.Lumpnum) != 0)
{
Printf("Icon '%s' for '%s' not found\n", i, bag.Info->Class->TypeName.GetChars());
bag.ScriptPosition.Message(MSG_WARNING,
"Icon '%s' for '%s' not found\n", i, info->Class->TypeName.GetChars());
}
}
}
@ -1160,7 +1169,7 @@ DEFINE_CLASS_PROPERTY(pickupflash, S, Inventory)
DEFINE_CLASS_PROPERTY(pickupmessage, S, Inventory)
{
PROP_STRING_PARM(str, 0);
bag.Info->Class->Meta.SetMetaString(AIMETA_PickupMessage, str);
info->Class->Meta.SetMetaString(AIMETA_PickupMessage, str);
}
//==========================================================================
@ -1196,7 +1205,7 @@ DEFINE_CLASS_PROPERTY(usesound, S, Inventory)
DEFINE_CLASS_PROPERTY(givequest, I, Inventory)
{
PROP_INT_PARM(i, 0);
bag.Info->Class->Meta.SetMetaInt(AIMETA_GiveQuest, i);
info->Class->Meta.SetMetaInt(AIMETA_GiveQuest, i);
}
//==========================================================================
@ -1206,8 +1215,8 @@ DEFINE_CLASS_PROPERTY(lowmessage, IS, Health)
{
PROP_INT_PARM(i, 0);
PROP_STRING_PARM(str, 1);
bag.Info->Class->Meta.SetMetaInt(AIMETA_LowHealth, i);
bag.Info->Class->Meta.SetMetaString(AIMETA_LowHealthMessage, str);
info->Class->Meta.SetMetaInt(AIMETA_LowHealth, i);
info->Class->Meta.SetMetaString(AIMETA_LowHealthMessage, str);
}
//==========================================================================
@ -1225,7 +1234,7 @@ DEFINE_CLASS_PROPERTY(number, I, PuzzleItem)
DEFINE_CLASS_PROPERTY(failmessage, S, PuzzleItem)
{
PROP_STRING_PARM(str, 0);
bag.Info->Class->Meta.SetMetaString(AIMETA_PuzzFailMessage, str);
info->Class->Meta.SetMetaString(AIMETA_PuzzFailMessage, str);
}
//==========================================================================
@ -1399,11 +1408,11 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, color, C_f, Inventory)
int alpha;
PalEntry * pBlendColor;
if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(APowerup)))
if (info->Class->IsDescendantOf(RUNTIME_CLASS(APowerup)))
{
pBlendColor = &((APowerup*)defaults)->BlendColor;
}
else if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)))
else if (info->Class->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)))
{
pBlendColor = &((APowerupGiver*)defaults)->BlendColor;
}
@ -1463,11 +1472,11 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, duration, I, Inventory)
{
int *pEffectTics;
if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(APowerup)))
if (info->Class->IsDescendantOf(RUNTIME_CLASS(APowerup)))
{
pEffectTics = &((APowerup*)defaults)->EffectTics;
}
else if (bag.Info->Class->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)))
else if (info->Class->IsDescendantOf(RUNTIME_CLASS(APowerupGiver)))
{
pEffectTics = &((APowerupGiver*)defaults)->EffectTics;
}
@ -1511,7 +1520,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(powerup, type, S, PowerupGiver)
DEFINE_CLASS_PROPERTY_PREFIX(player, displayname, S, PlayerPawn)
{
PROP_STRING_PARM(str, 0);
bag.Info->Class->Meta.SetMetaString (APMETA_DisplayName, str);
info->Class->Meta.SetMetaString (APMETA_DisplayName, str);
}
//==========================================================================
@ -1523,7 +1532,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, soundclass, S, PlayerPawn)
FString tmp = str;
tmp.ReplaceChars (' ', '_');
bag.Info->Class->Meta.SetMetaString (APMETA_SoundClass, tmp);
info->Class->Meta.SetMetaString (APMETA_SoundClass, tmp);
}
//==========================================================================
@ -1537,8 +1546,9 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, face, S, PlayerPawn)
tmp.ToUpper();
if (tmp.Len() != 3)
{
Printf("Invalid face '%s' for '%s';\nSTF replacement codes must be 3 characters.\n",
tmp.GetChars(), bag.Info->Class->TypeName.GetChars ());
bag.ScriptPosition.Message(MSG_WARNING,
"Invalid face '%s' for '%s';\nSTF replacement codes must be 3 characters.\n",
tmp.GetChars(), info->Class->TypeName.GetChars ());
}
bool valid = (
@ -1548,11 +1558,12 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, face, S, PlayerPawn)
);
if (!valid)
{
Printf("Invalid face '%s' for '%s';\nSTF replacement codes must be alphanumeric.\n",
tmp.GetChars(), bag.Info->Class->TypeName.GetChars ());
bag.ScriptPosition.Message(MSG_WARNING,
"Invalid face '%s' for '%s';\nSTF replacement codes must be alphanumeric.\n",
tmp.GetChars(), info->Class->TypeName.GetChars ());
}
bag.Info->Class->Meta.SetMetaString (APMETA_Face, tmp);
info->Class->Meta.SetMetaString (APMETA_Face, tmp);
}
//==========================================================================
@ -1566,7 +1577,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, colorrange, I_I, PlayerPawn)
if (start > end)
swap (start, end);
bag.Info->Class->Meta.SetMetaInt (APMETA_ColorRange, (start & 255) | ((end & 255) << 8));
info->Class->Meta.SetMetaInt (APMETA_ColorRange, (start & 255) | ((end & 255) << 8));
}
//==========================================================================
@ -1691,7 +1702,8 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, scoreicon, S, PlayerPawn)
defaults->ScoreIcon = TexMan.CheckForTexture(z, FTexture::TEX_MiscPatch);
if (!defaults->ScoreIcon.isValid())
{
Printf("Icon '%s' for '%s' not found\n", z, bag.Info->Class->TypeName.GetChars ());
bag.ScriptPosition.Message(MSG_WARNING,
"Icon '%s' for '%s' not found\n", z, info->Class->TypeName.GetChars ());
}
}
@ -1751,7 +1763,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, startitem, S_i, PlayerPawn)
DEFINE_CLASS_PROPERTY_PREFIX(player, invulnerabilitymode, S, PlayerPawn)
{
PROP_STRING_PARM(str, 0);
bag.Info->Class->Meta.SetMetaInt (APMETA_InvulMode, (FName)str);
info->Class->Meta.SetMetaInt (APMETA_InvulMode, (FName)str);
}
//==========================================================================
@ -1760,7 +1772,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, invulnerabilitymode, S, PlayerPawn)
DEFINE_CLASS_PROPERTY_PREFIX(player, healradiustype, S, PlayerPawn)
{
PROP_STRING_PARM(str, 0);
bag.Info->Class->Meta.SetMetaInt (APMETA_HealingRadius, (FName)str);
info->Class->Meta.SetMetaInt (APMETA_HealingRadius, (FName)str);
}
//==========================================================================
@ -1771,7 +1783,7 @@ DEFINE_CLASS_PROPERTY_PREFIX(player, hexenarmor, FFFFF, PlayerPawn)
for (int i=0;i<5;i++)
{
PROP_FIXED_PARM(val, i);
bag.Info->Class->Meta.SetMetaFixed (APMETA_Hexenarmor0+i, val);
info->Class->Meta.SetMetaFixed (APMETA_Hexenarmor0+i, val);
}
}

View file

@ -63,7 +63,7 @@
// creates an empty parameter list for a parameterized function call
//
//==========================================================================
static int PrepareStateParameters(FState * state, int numparams, const PClass *cls)
int PrepareStateParameters(FState * state, int numparams, const PClass *cls)
{
int paramindex=StateParams.Reserve(numparams, cls);
state->ParameterIndex = paramindex+1;
@ -76,7 +76,7 @@ static int PrepareStateParameters(FState * state, int numparams, const PClass *c
// handles action specials as code pointers
//
//==========================================================================
bool DoActionSpecials(FScanner &sc, FState & state, bool multistate, int * statecount, Baggage &bag)
bool DoActionSpecials(FScanner &sc, FState & state, Baggage &bag)
{
int i;
int min_args, max_args;
@ -150,15 +150,10 @@ static FString ParseStateString(FScanner &sc)
// parses a state block
//
//==========================================================================
int ParseStates(FScanner &sc, FActorInfo * actor, AActor * defaults, Baggage &bag)
void ParseStates(FScanner &sc, FActorInfo * actor, AActor * defaults, Baggage &bag)
{
FString statestring;
intptr_t count = 0;
FState state;
FState * laststate = NULL;
intptr_t lastlabel = -1;
int minrequiredstate = -1;
int spriteindex = 0;
char lastsprite[5]="";
sc.MustGetStringName ("{");
@ -177,17 +172,7 @@ do_goto:
statestring += '+';
statestring += sc.String;
}
// copy the text - this must be resolved later!
if (laststate != NULL)
{ // Following a state definition: Modify it.
laststate->NextState = (FState*)copystring(statestring);
laststate->DefineFlags = SDF_LABEL;
}
else if (lastlabel >= 0)
{ // Following a label: Retarget it.
bag.statedef.RetargetStates (count+1, statestring);
}
else
if (!bag.statedef.SetGotoLabel(statestring))
{
sc.ScriptError("GOTO before first state");
}
@ -195,15 +180,7 @@ do_goto:
else if (!statestring.CompareNoCase("STOP"))
{
do_stop:
if (laststate!=NULL)
{
laststate->DefineFlags = SDF_STOP;
}
else if (lastlabel >=0)
{
bag.statedef.RetargetStates (count+1, NULL);
}
else
if (!bag.statedef.SetStop())
{
sc.ScriptError("STOP before first state");
continue;
@ -211,35 +188,28 @@ do_stop:
}
else if (!statestring.CompareNoCase("WAIT") || !statestring.CompareNoCase("FAIL"))
{
if (!laststate)
if (!bag.statedef.SetWait())
{
sc.ScriptError("%s before first state", sc.String);
continue;
}
laststate->DefineFlags = SDF_WAIT;
}
else if (!statestring.CompareNoCase("LOOP"))
{
if (!laststate)
if (!bag.statedef.SetLoop())
{
sc.ScriptError("LOOP before first state");
continue;
}
laststate->NextState=(FState*)(lastlabel+1);
laststate->DefineFlags = SDF_INDEX;
}
else
{
const char * statestrp;
sc.MustGetString();
if (sc.Compare (":"))
{
laststate = NULL;
do
{
lastlabel = count;
bag.statedef.AddState(statestring, (FState *) (count+1), SDF_INDEX);
bag.statedef.AddStateLabel(statestring);
statestring = ParseStateString(sc);
if (!statestring.CompareNoCase("GOTO"))
{
@ -261,25 +231,11 @@ do_stop:
sc.ScriptError ("Sprite names must be exactly 4 characters\n");
}
statestring.ToUpper();
if (strcmp(statestring, lastsprite))
{
strcpy(lastsprite, statestring);
spriteindex = GetSpriteIndex(lastsprite);
}
state.sprite = spriteindex;
state.sprite = GetSpriteIndex(statestring);
state.Misc1 = state.Misc2 = 0;
state.ParameterIndex = 0;
sc.MustGetString();
statestring = (sc.String+1);
statestrp = statestring;
state.Frame = (*sc.String & 223)-'A';
if ((*sc.String & 223)<'A' || (*sc.String & 223)>']')
{
sc.ScriptError ("Frames must be A-Z, [, \\, or ]");
state.Frame=0;
}
statestring = sc.String;
sc.MustGetNumber();
state.Tics = clamp<int>(sc.Number, -1, 32767);
@ -307,10 +263,8 @@ do_stop:
// Make the action name lowercase to satisfy the gperf hashers
strlwr (sc.String);
int minreq = count;
if (DoActionSpecials(sc, state, !statestring.IsEmpty(), &minreq, bag))
if (DoActionSpecials(sc, state, bag))
{
if (minreq>minrequiredstate) minrequiredstate=minreq;
goto endofstate;
}
@ -360,7 +314,7 @@ do_stop:
if ((*params == 'l' || *params == 'L') && sc.CheckNumber())
{
// Special case: State label as an offset
if (sc.Number > 0 && strlen(statestring)>0)
if (sc.Number > 0 && statestring.Len() > 1)
{
sc.ScriptError("You cannot use state jumps commands with a jump offset on multistate definitions\n");
}
@ -371,7 +325,7 @@ do_stop:
sc.ScriptError("Negative jump offsets are not allowed");
}
x = new FxStateByIndex(count+v, sc);
x = new FxStateByIndex(bag.statedef.GetStateCount() + v, sc);
}
else
{
@ -420,26 +374,12 @@ do_stop:
}
sc.UnGet();
endofstate:
bag.StateArray.Push(state);
while (*statestrp)
if (!bag.statedef.AddStates(&state, statestring))
{
int frame=((*statestrp++)&223)-'A';
if (frame<0 || frame>28)
{
sc.ScriptError ("Frames must be A-Z, [, \\, or ]");
frame=0;
sc.ScriptError ("Invalid frame character string '%s'", statestring.GetChars());
}
state.Frame=(state.Frame&(SF_FULLBRIGHT))|frame;
bag.StateArray.Push(state);
count++;
}
laststate=&bag.StateArray[count];
count++;
}
}
sc.SetEscape(true); // re-enable escape sequences
return count;
}

View file

@ -441,9 +441,9 @@ void InitPalette ()
shade = DesaturateColormap[m];
for (c = 0; c < 256; c++)
{
intensity = GPalette.BaseColors[c].r * 77 +
intensity = (GPalette.BaseColors[c].r * 77 +
GPalette.BaseColors[c].g * 143 +
GPalette.BaseColors[c].b * 37;
GPalette.BaseColors[c].b * 37) / 255;
int r = (GPalette.BaseColors[c].r * (31-m) + intensity *m) / 31;
int g = (GPalette.BaseColors[c].g * (31-m) + intensity *m) / 31;

View file

@ -34,7 +34,7 @@
#ifndef __V_PALETTE_H__
#define __V_PALETTE_H__
#include "basictypes.h"
#include "doomtype.h"
#define MAKERGB(r,g,b) DWORD(((r)<<16)|((g)<<8)|(b))
#define MAKEARGB(a,r,g,b) DWORD(((a)<<24)|((r)<<16)|((g)<<8)|(b))

View file

@ -453,6 +453,20 @@ int V_GetColorFromString (const DWORD *palette, const char *cstr)
}
}
else
{
if (strlen(cstr) == 6)
{
char *p;
int color = strtol(cstr, &p, 16);
if (*p == 0)
{
// RRGGBB string
c[0] = (color & 0xff0000) >> 16;
c[1] = (color & 0xff00) >> 8;
c[2] = (color & 0xff);
}
}
else
{
// Treat it as a space-delemited hexadecimal string
for (i = 0; i < 3; ++i)
@ -484,6 +498,7 @@ int V_GetColorFromString (const DWORD *palette, const char *cstr)
}
}
}
}
if (palette)
return ColorMatcher.Pick (c[0], c[1], c[2]);
else

View file

@ -32,8 +32,8 @@ Actor GreenArmor : BasicArmorPickup 2018
Height 16
Inventory.Pickupmessage "$GOTARMOR"
Inventory.Icon "ARM1A0"
Armor.Savepercent 33.33333
Armor.Saveamount 100
Armor.SavePercent 33.335
Armor.SaveAmount 100
States
{
Spawn:

View file

@ -37,7 +37,7 @@ ACTOR LeatherArmor : BasicArmorPickup 2018
Inventory.Icon "I_ARM2"
Inventory.PickupMessage "$TXT_LEATHERARMOR"
Armor.SaveAmount 100
Armor.SavePercent 33.33333
Armor.SavePercent 33.335
Tag "Leather_Armor"
States
{