- Added handling for UDMF user keys.
- Added support for ACS functions that can be defined without recompiling ACC. - Fixed: The short lump name for embedded files must be cleared so that they are not found by a normal lump search. - Added AProp_Notarget actor property. - Fixed: TraceBleed was missing a NULL pointer check, - Fixed: P_RandomChaseDir could crash for friendly monsters that belong to a player which left the game. - Changed A_PodGrow so that it plays the generator's attack sound instead of "misc/podgrow". SVN r1575 (trunk)
This commit is contained in:
parent
b224765351
commit
571d28281b
16 changed files with 540 additions and 1493 deletions
|
|
@ -116,7 +116,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_MakePod)
|
|||
}
|
||||
mo->SetState (mo->FindState("Grow"));
|
||||
P_ThrustMobj (mo, pr_makepod()<<24, (fixed_t)(4.5*FRACUNIT));
|
||||
S_Sound (mo, CHAN_BODY, "world/podgrow", 1, ATTN_IDLE);
|
||||
S_Sound (mo, CHAN_BODY, self->AttackSound, 1, ATTN_IDLE);
|
||||
self->special1++; // Increment generated pod count
|
||||
mo->master = self; // Link the generator to the pod
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@
|
|||
#include "sbarinfo.h"
|
||||
#include "cmdlib.h"
|
||||
#include "m_png.h"
|
||||
#include "p_setup.h"
|
||||
|
||||
extern FILE *Logfile;
|
||||
|
||||
|
|
@ -2405,6 +2406,7 @@ enum
|
|||
APROP_Friendly = 16,
|
||||
APROP_SpawnHealth = 17,
|
||||
APROP_Dropped = 18,
|
||||
APROP_Notarget = 19,
|
||||
};
|
||||
|
||||
// These are needed for ACS's APROP_RenderStyle
|
||||
|
|
@ -2492,6 +2494,10 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value)
|
|||
if (value) actor->flags2 |= MF2_INVULNERABLE; else actor->flags2 &= ~MF2_INVULNERABLE;
|
||||
break;
|
||||
|
||||
case APROP_Notarget:
|
||||
if (value) actor->flags3 |= MF3_NOTARGET; else actor->flags3 &= ~MF3_NOTARGET;
|
||||
break;
|
||||
|
||||
case APROP_JumpZ:
|
||||
if (actor->IsKindOf (RUNTIME_CLASS (APlayerPawn)))
|
||||
static_cast<APlayerPawn *>(actor)->JumpZ = value;
|
||||
|
|
@ -2595,6 +2601,7 @@ int DLevelScript::GetActorProperty (int tid, int property)
|
|||
case APROP_ChaseGoal: return !!(actor->flags5 & MF5_CHASEGOAL);
|
||||
case APROP_Frightened: return !!(actor->flags4 & MF4_FRIGHTENED);
|
||||
case APROP_Friendly: return !!(actor->flags & MF_FRIENDLY);
|
||||
case APROP_Notarget: return !!(actor->flags3 & MF3_NOTARGET);
|
||||
case APROP_SpawnHealth: if (actor->IsKindOf (RUNTIME_CLASS (APlayerPawn)))
|
||||
{
|
||||
return static_cast<APlayerPawn *>(actor)->MaxHealth;
|
||||
|
|
@ -2772,8 +2779,80 @@ int DLevelScript::DoClassifyActor(int tid)
|
|||
return classify;
|
||||
}
|
||||
|
||||
enum EACSFunctions
|
||||
{
|
||||
GetLineUDMFInt=1,
|
||||
GetLineUDMFFixed,
|
||||
GetThingUDMFInt,
|
||||
GetThingUDMFFixed,
|
||||
GetSectorUDMFInt,
|
||||
GetSectorUDMFFixed,
|
||||
GetSideUDMFInt,
|
||||
GetSideUDMFFixed,
|
||||
};
|
||||
|
||||
int DLevelScript::SideFromID(int id, int side)
|
||||
{
|
||||
if (side != 0 && side != 1) return -1;
|
||||
|
||||
if (id == 0)
|
||||
{
|
||||
if (activationline == NULL) return -1;
|
||||
if (activationline->sidenum[side] == NO_SIDE) return -1;
|
||||
return sides[activationline->sidenum[side]].Index;
|
||||
}
|
||||
else
|
||||
{
|
||||
int line = P_FindLineFromID(id, -1);
|
||||
if (line == -1) return -1;
|
||||
if (lines[line].sidenum[side] == NO_SIDE) return -1;
|
||||
return sides[lines[line].sidenum[side]].Index;
|
||||
}
|
||||
}
|
||||
|
||||
int DLevelScript::LineFromID(int id)
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
if (activationline == NULL) return -1;
|
||||
return int(activationline - lines);
|
||||
}
|
||||
else
|
||||
{
|
||||
return P_FindLineFromID(id, -1);
|
||||
}
|
||||
}
|
||||
|
||||
int DLevelScript::CallFunction(int argCount, int funcIndex, SDWORD *args)
|
||||
{
|
||||
switch(funcIndex)
|
||||
{
|
||||
case GetLineUDMFInt:
|
||||
return GetUDMFInt(UDMF_Line, LineFromID(args[0]), FBehavior::StaticLookupString(args[1]));
|
||||
case GetLineUDMFFixed:
|
||||
return GetUDMFFixed(UDMF_Line, LineFromID(args[0]), FBehavior::StaticLookupString(args[1]));
|
||||
case GetThingUDMFInt:
|
||||
case GetThingUDMFFixed:
|
||||
return 0; // Not implemented yet
|
||||
case GetSectorUDMFInt:
|
||||
return GetUDMFInt(UDMF_Sector, P_FindSectorFromTag(args[0], -1), FBehavior::StaticLookupString(args[1]));
|
||||
case GetSectorUDMFFixed:
|
||||
return GetUDMFFixed(UDMF_Sector, P_FindSectorFromTag(args[0], -1), FBehavior::StaticLookupString(args[1]));
|
||||
case GetSideUDMFInt:
|
||||
return GetUDMFInt(UDMF_Side, SideFromID(args[0], args[1]), FBehavior::StaticLookupString(args[2]));
|
||||
case GetSideUDMFFixed:
|
||||
return GetUDMFFixed(UDMF_Side, SideFromID(args[0], args[1]), FBehavior::StaticLookupString(args[2]));
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#define NEXTWORD (LittleLong(*pc++))
|
||||
#define NEXTBYTE (fmt==ACS_LittleEnhanced?getbyte(pc):NEXTWORD)
|
||||
#define NEXTSHORT (fmt==ACS_LittleEnhanced?getshort(pc):NEXTWORD)
|
||||
#define STACK(a) (Stack[sp - (a)])
|
||||
#define PushToStack(a) (Stack[sp++] = (a))
|
||||
|
||||
|
|
@ -2784,6 +2863,13 @@ inline int getbyte (int *&pc)
|
|||
return res;
|
||||
}
|
||||
|
||||
inline int getshort (int *&pc)
|
||||
{
|
||||
int res = LittleShort( *(SWORD *)pc);
|
||||
pc = (int *)((BYTE *)pc+2);
|
||||
return res;
|
||||
}
|
||||
|
||||
int DLevelScript::RunScript ()
|
||||
{
|
||||
DACSThinker *controller = DACSThinker::ActiveThinker;
|
||||
|
|
@ -3064,6 +3150,17 @@ int DLevelScript::RunScript ()
|
|||
pc = (int *)((BYTE *)pc + 6);
|
||||
break;
|
||||
|
||||
case PCD_CALLFUNC:
|
||||
{
|
||||
int argCount = NEXTBYTE;
|
||||
int funcIndex = NEXTSHORT;
|
||||
|
||||
int retval = CallFunction(argCount, funcIndex, &STACK(argCount));
|
||||
sp -= argCount-1;
|
||||
STACK(1) = retval;
|
||||
}
|
||||
break;
|
||||
|
||||
case PCD_CALL:
|
||||
case PCD_CALLDISCARD:
|
||||
{
|
||||
|
|
|
|||
|
|
@ -586,6 +586,7 @@ public:
|
|||
PCD_CLASSIFYACTOR,
|
||||
PCD_PRINTBINARY,
|
||||
/*350*/ PCD_PRINTHEX,
|
||||
PCD_CALLFUNC,
|
||||
|
||||
/*351*/ PCODE_COMMAND_COUNT
|
||||
};
|
||||
|
|
@ -715,6 +716,7 @@ protected:
|
|||
static int DoSpawnSpot (int type, int spot, int tid, int angle);
|
||||
static int DoSpawnSpotFacing (int type, int spot, int tid);
|
||||
int DoClassifyActor (int tid);
|
||||
int CallFunction(int argCount, int funcIndex, SDWORD *args);
|
||||
|
||||
void DoFadeTo (int r, int g, int b, int a, fixed_t time);
|
||||
void DoFadeRange (int r1, int g1, int b1, int a1,
|
||||
|
|
@ -725,6 +727,9 @@ protected:
|
|||
int GetActorProperty (int tid, int property);
|
||||
int GetPlayerInput (int playernum, int inputnum);
|
||||
|
||||
int LineFromID(int id);
|
||||
int SideFromID(int id, int side);
|
||||
|
||||
private:
|
||||
DLevelScript ();
|
||||
|
||||
|
|
|
|||
|
|
@ -846,60 +846,62 @@ void P_RandomChaseDir (AActor *actor)
|
|||
}
|
||||
player = players[i].mo;
|
||||
}
|
||||
|
||||
if (pr_newchasedir() & 1 || !P_CheckSight (actor, player))
|
||||
if (player != NULL && playeringame[i])
|
||||
{
|
||||
deltax = player->x - actor->x;
|
||||
deltay = player->y - actor->y;
|
||||
|
||||
if (deltax>128*FRACUNIT)
|
||||
d[1]= DI_EAST;
|
||||
else if (deltax<-128*FRACUNIT)
|
||||
d[1]= DI_WEST;
|
||||
else
|
||||
d[1]=DI_NODIR;
|
||||
|
||||
if (deltay<-128*FRACUNIT)
|
||||
d[2]= DI_SOUTH;
|
||||
else if (deltay>128*FRACUNIT)
|
||||
d[2]= DI_NORTH;
|
||||
else
|
||||
d[2]=DI_NODIR;
|
||||
|
||||
// try direct route
|
||||
if (d[1] != DI_NODIR && d[2] != DI_NODIR)
|
||||
if (pr_newchasedir() & 1 || !P_CheckSight (actor, player))
|
||||
{
|
||||
actor->movedir = diags[((deltay<0)<<1) + (deltax>0)];
|
||||
if (actor->movedir != turnaround && P_TryWalk(actor))
|
||||
return;
|
||||
}
|
||||
deltax = player->x - actor->x;
|
||||
deltay = player->y - actor->y;
|
||||
|
||||
// try other directions
|
||||
if (pr_newchasedir() > 200 || abs(deltay) > abs(deltax))
|
||||
{
|
||||
swap (d[1], d[2]);
|
||||
}
|
||||
if (deltax>128*FRACUNIT)
|
||||
d[1]= DI_EAST;
|
||||
else if (deltax<-128*FRACUNIT)
|
||||
d[1]= DI_WEST;
|
||||
else
|
||||
d[1]=DI_NODIR;
|
||||
|
||||
if (d[1] == turnaround)
|
||||
d[1] = DI_NODIR;
|
||||
if (d[2] == turnaround)
|
||||
d[2] = DI_NODIR;
|
||||
|
||||
if (d[1] != DI_NODIR)
|
||||
{
|
||||
actor->movedir = d[1];
|
||||
if (P_TryWalk (actor))
|
||||
if (deltay<-128*FRACUNIT)
|
||||
d[2]= DI_SOUTH;
|
||||
else if (deltay>128*FRACUNIT)
|
||||
d[2]= DI_NORTH;
|
||||
else
|
||||
d[2]=DI_NODIR;
|
||||
|
||||
// try direct route
|
||||
if (d[1] != DI_NODIR && d[2] != DI_NODIR)
|
||||
{
|
||||
// either moved forward or attacked
|
||||
return;
|
||||
actor->movedir = diags[((deltay<0)<<1) + (deltax>0)];
|
||||
if (actor->movedir != turnaround && P_TryWalk(actor))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (d[2] != DI_NODIR)
|
||||
{
|
||||
actor->movedir = d[2];
|
||||
if (P_TryWalk (actor))
|
||||
return;
|
||||
// try other directions
|
||||
if (pr_newchasedir() > 200 || abs(deltay) > abs(deltax))
|
||||
{
|
||||
swap (d[1], d[2]);
|
||||
}
|
||||
|
||||
if (d[1] == turnaround)
|
||||
d[1] = DI_NODIR;
|
||||
if (d[2] == turnaround)
|
||||
d[2] = DI_NODIR;
|
||||
|
||||
if (d[1] != DI_NODIR)
|
||||
{
|
||||
actor->movedir = d[1];
|
||||
if (P_TryWalk (actor))
|
||||
{
|
||||
// either moved forward or attacked
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (d[2] != DI_NODIR)
|
||||
{
|
||||
actor->movedir = d[2];
|
||||
if (P_TryWalk (actor))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3393,11 +3393,14 @@ void P_TraceBleed (int damage, AActor *target, AActor *missile)
|
|||
|
||||
void P_TraceBleed (int damage, AActor *target)
|
||||
{
|
||||
fixed_t one = pr_tracebleed() << 24;
|
||||
fixed_t two = (pr_tracebleed()-128) << 16;
|
||||
if (target != NULL)
|
||||
{
|
||||
fixed_t one = pr_tracebleed() << 24;
|
||||
fixed_t two = (pr_tracebleed()-128) << 16;
|
||||
|
||||
P_TraceBleed (damage, target->x, target->y, target->z + target->height/2,
|
||||
target, one, two);
|
||||
P_TraceBleed (damage, target->x, target->y, target->z + target->height/2,
|
||||
target, one, two);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -382,6 +382,8 @@ void P_SerializeWorld (FArchive &arc)
|
|||
<< si->Flags
|
||||
<< si->LeftSide
|
||||
<< si->RightSide;
|
||||
if (SaveVersion >= 1575)
|
||||
arc << si->Index;
|
||||
DBaseDecal::SerializeChain (arc, &si->AttachedDecals);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@
|
|||
void P_SpawnSlopeMakers (FMapThing *firstmt, FMapThing *lastmt);
|
||||
void P_SetSlopes ();
|
||||
void BloodCrypt (void *data, int key, int len);
|
||||
void P_ClearUDMFKeys();
|
||||
|
||||
extern AActor *P_SpawnMapThing (FMapThing *mthing, int position);
|
||||
extern bool P_LoadBuildMap (BYTE *mapdata, size_t len, FMapThing **things, int *numthings);
|
||||
|
|
@ -2331,6 +2332,7 @@ void P_LoadSideDefs2 (MapData * map)
|
|||
sd->SetTextureYOffset(LittleShort(msd->rowoffset)<<FRACBITS);
|
||||
sd->linenum = NO_INDEX;
|
||||
sd->Flags = 0;
|
||||
sd->Index = i;
|
||||
|
||||
// killough 4/4/98: allow sidedef texture names to be overloaded
|
||||
// killough 4/11/98: refined to allow colormaps to work as wall
|
||||
|
|
@ -3281,6 +3283,7 @@ void P_FreeLevelData ()
|
|||
delete[] level.Scrolls;
|
||||
level.Scrolls = NULL;
|
||||
}
|
||||
P_ClearUDMFKeys();
|
||||
}
|
||||
|
||||
extern msecnode_t *headsecnode;
|
||||
|
|
|
|||
|
|
@ -108,4 +108,7 @@ void P_LoadTranslator(const char *lumpname);
|
|||
void P_TranslateLineDef (line_t *ld, maplinedef_t *mld);
|
||||
int P_TranslateSectorSpecial (int);
|
||||
|
||||
int GetUDMFInt(int type, int index, const char *key);
|
||||
fixed_t GetUDMFFixed(int type, int index, const char *key);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
383
src/p_udmf.cpp
383
src/p_udmf.cpp
|
|
@ -123,6 +123,116 @@ extern TArray<int> linemap;
|
|||
|
||||
#define CHECK_N(f) if (!(namespace_bits&(f))) break;
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Storage of UDMF user properties
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
typedef TMap<int, FUDMFKeys> FUDMFKeyMap;
|
||||
|
||||
|
||||
static FUDMFKeyMap UDMFKeys[4];
|
||||
// Things must be handled differently
|
||||
|
||||
void P_ClearUDMFKeys()
|
||||
{
|
||||
for(int i=0;i<4;i++)
|
||||
{
|
||||
UDMFKeys[i].Clear();
|
||||
}
|
||||
}
|
||||
|
||||
static int STACK_ARGS udmfcmp(const void *a, const void *b)
|
||||
{
|
||||
FUDMFKey *A = (FUDMFKey*)a;
|
||||
FUDMFKey *B = (FUDMFKey*)b;
|
||||
|
||||
return int(A->Key) - int(B->Key);
|
||||
}
|
||||
|
||||
void FUDMFKeys::Sort()
|
||||
{
|
||||
qsort(&(*this)[0], Size(), sizeof(FUDMFKey), udmfcmp);
|
||||
}
|
||||
|
||||
FUDMFKey *FUDMFKeys::Find(FName key)
|
||||
{
|
||||
int min = 0, max = Size()-1;
|
||||
|
||||
while (min <= max)
|
||||
{
|
||||
int mid = (min + max) / 2;
|
||||
if ((*this)[mid].Key == key)
|
||||
{
|
||||
return &(*this)[mid];
|
||||
}
|
||||
else if ((*this)[mid].Key <= key)
|
||||
{
|
||||
min = mid + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
max = mid - 1;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Retrieves UDMF user properties
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
int GetUDMFInt(int type, int index, const char *key)
|
||||
{
|
||||
assert(type >=0 && type <=3);
|
||||
|
||||
if (index > 0)
|
||||
{
|
||||
FUDMFKeys *pKeys = UDMFKeys[type].CheckKey(index);
|
||||
|
||||
if (pKeys != NULL)
|
||||
{
|
||||
FUDMFKey *pKey = pKeys->Find(key);
|
||||
if (pKey != NULL)
|
||||
{
|
||||
return FLOAT2FIXED(pKey->IntVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
fixed_t GetUDMFFixed(int type, int index, const char *key)
|
||||
{
|
||||
assert(type >=0 && type <=3);
|
||||
|
||||
if (index > 0)
|
||||
{
|
||||
FUDMFKeys *pKeys = UDMFKeys[type].CheckKey(index);
|
||||
|
||||
if (pKeys != NULL)
|
||||
{
|
||||
FUDMFKey *pKey = pKeys->Find(key);
|
||||
if (pKey != NULL)
|
||||
{
|
||||
return FLOAT2FIXED(pKey->FloatVal);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// UDMF parser
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
struct UDMFParser
|
||||
{
|
||||
FScanner sc;
|
||||
|
|
@ -131,6 +241,7 @@ struct UDMFParser
|
|||
bool isTranslated;
|
||||
bool isExtended;
|
||||
bool floordrop;
|
||||
FString parsedString;
|
||||
|
||||
TArray<line_t> ParsedLines;
|
||||
TArray<side_t> ParsedSides;
|
||||
|
|
@ -148,7 +259,7 @@ struct UDMFParser
|
|||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parses a 'key = value' line of the map but doesn't read the semicolon
|
||||
// Parses a 'key = value' line of the map
|
||||
//
|
||||
//===========================================================================
|
||||
|
||||
|
|
@ -176,6 +287,13 @@ struct UDMFParser
|
|||
sc.Float = -sc.Float;
|
||||
}
|
||||
}
|
||||
if (sc.TokenType == TK_StringConst)
|
||||
{
|
||||
parsedString = sc.String;
|
||||
}
|
||||
int savedtoken = sc.TokenType;
|
||||
sc.MustGetToken(';');
|
||||
sc.TokenType = savedtoken;
|
||||
return key;
|
||||
}
|
||||
|
||||
|
|
@ -227,7 +345,7 @@ struct UDMFParser
|
|||
{
|
||||
sc.ScriptMessage("String value expected for key '%s'", key);
|
||||
}
|
||||
return sc.String;
|
||||
return parsedString;
|
||||
}
|
||||
|
||||
void Flag(DWORD &value, int mask, const char *key)
|
||||
|
|
@ -236,6 +354,61 @@ struct UDMFParser
|
|||
else value &= ~mask;
|
||||
}
|
||||
|
||||
|
||||
void AddUserKey(FName key, int kind, int index)
|
||||
{
|
||||
FUDMFKeys &keyarray = UDMFKeys[kind][index];
|
||||
|
||||
for(unsigned i=0; i < keyarray.Size(); i++)
|
||||
{
|
||||
if (keyarray[i].Key == key)
|
||||
{
|
||||
switch (sc.TokenType)
|
||||
{
|
||||
case TK_Int:
|
||||
keyarray[i] = sc.Number;
|
||||
break;
|
||||
case TK_Float:
|
||||
keyarray[i] = sc.Float;
|
||||
break;
|
||||
default:
|
||||
case TK_String:
|
||||
keyarray[i] = parsedString;
|
||||
break;
|
||||
case TK_True:
|
||||
keyarray[i] = 1;
|
||||
break;
|
||||
case TK_False:
|
||||
keyarray[i] = 0;
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
FUDMFKey ukey;
|
||||
ukey.Key = key;
|
||||
switch (sc.TokenType)
|
||||
{
|
||||
case TK_Int:
|
||||
ukey = sc.Number;
|
||||
break;
|
||||
case TK_Float:
|
||||
ukey = sc.Float;
|
||||
break;
|
||||
default:
|
||||
case TK_String:
|
||||
ukey = parsedString;
|
||||
break;
|
||||
case TK_True:
|
||||
ukey = 1;
|
||||
break;
|
||||
case TK_False:
|
||||
ukey = 0;
|
||||
break;
|
||||
}
|
||||
keyarray.Push(ukey);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//
|
||||
// Parse a thing block
|
||||
|
|
@ -377,9 +550,12 @@ struct UDMFParser
|
|||
break;
|
||||
|
||||
default:
|
||||
if (!strnicmp("user_", key.GetChars(), 5))
|
||||
{
|
||||
// Custom user key - handle later
|
||||
}
|
||||
break;
|
||||
}
|
||||
sc.MustGetToken(';');
|
||||
}
|
||||
// Thing specials are only valid in namespaces with Hexen-type specials
|
||||
// and in ZDoomTranslated - which will use the translator on them.
|
||||
|
|
@ -412,7 +588,7 @@ struct UDMFParser
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
void ParseLinedef(line_t *ld)
|
||||
void ParseLinedef(line_t *ld, int index)
|
||||
{
|
||||
bool passuse = false;
|
||||
bool strifetrans = false;
|
||||
|
|
@ -435,11 +611,11 @@ struct UDMFParser
|
|||
{
|
||||
case NAME_V1:
|
||||
ld->v1 = (vertex_t*)(intptr_t)CheckInt(key); // must be relocated later
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_V2:
|
||||
ld->v2 = (vertex_t*)(intptr_t)CheckInt(key); // must be relocated later
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Special:
|
||||
ld->special = CheckInt(key);
|
||||
|
|
@ -449,19 +625,19 @@ struct UDMFParser
|
|||
ld->special = 0; // NULL all specials which don't exist in Hexen
|
||||
}
|
||||
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Id:
|
||||
ld->id = CheckInt(key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Sidefront:
|
||||
ld->sidenum[0] = CheckInt(key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Sideback:
|
||||
ld->sidenum[1] = CheckInt(key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Arg0:
|
||||
case NAME_Arg1:
|
||||
|
|
@ -469,63 +645,63 @@ struct UDMFParser
|
|||
case NAME_Arg3:
|
||||
case NAME_Arg4:
|
||||
ld->args[int(key)-int(NAME_Arg0)] = CheckInt(key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Blocking:
|
||||
Flag(ld->flags, ML_BLOCKING, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Blockmonsters:
|
||||
Flag(ld->flags, ML_BLOCKMONSTERS, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Twosided:
|
||||
Flag(ld->flags, ML_TWOSIDED, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Dontpegtop:
|
||||
Flag(ld->flags, ML_DONTPEGTOP, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Dontpegbottom:
|
||||
Flag(ld->flags, ML_DONTPEGBOTTOM, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Secret:
|
||||
Flag(ld->flags, ML_SECRET, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Blocksound:
|
||||
Flag(ld->flags, ML_SOUNDBLOCK, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Dontdraw:
|
||||
Flag(ld->flags, ML_DONTDRAW, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Mapped:
|
||||
Flag(ld->flags, ML_MAPPED, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Jumpover:
|
||||
CHECK_N(St | Zd | Zdt | Va)
|
||||
Flag(ld->flags, ML_RAILING, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Blockfloating:
|
||||
CHECK_N(St | Zd | Zdt | Va)
|
||||
Flag(ld->flags, ML_BLOCK_FLOATERS, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Transparent:
|
||||
CHECK_N(St | Zd | Zdt | Va)
|
||||
strifetrans = CheckBool(key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Passuse:
|
||||
CHECK_N(Dm | Zd | Zdt | Va)
|
||||
passuse = CheckBool(key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
|
@ -536,39 +712,39 @@ struct UDMFParser
|
|||
{
|
||||
case NAME_Playercross:
|
||||
Flag(ld->activation, SPAC_Cross, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Playeruse:
|
||||
Flag(ld->activation, SPAC_Use, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Monstercross:
|
||||
Flag(ld->activation, SPAC_MCross, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Impact:
|
||||
Flag(ld->activation, SPAC_Impact, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Playerpush:
|
||||
Flag(ld->activation, SPAC_Push, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Missilecross:
|
||||
Flag(ld->activation, SPAC_PCross, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Monsteruse:
|
||||
Flag(ld->activation, SPAC_MUse, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Monsterpush:
|
||||
Flag(ld->activation, SPAC_MPush, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Repeatspecial:
|
||||
Flag(ld->flags, ML_REPEAT_SPECIAL, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
|
@ -579,7 +755,7 @@ struct UDMFParser
|
|||
{
|
||||
case NAME_Alpha:
|
||||
ld->Alpha = CheckFixed(key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Renderstyle:
|
||||
{
|
||||
|
|
@ -587,61 +763,65 @@ struct UDMFParser
|
|||
if (!stricmp(str, "translucent")) ld->flags &= ~ML_ADDTRANS;
|
||||
else if (!stricmp(str, "add")) ld->flags |= ML_ADDTRANS;
|
||||
else sc.ScriptMessage("Unknown value \"%s\" for 'renderstyle'\n", str);
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
case NAME_Anycross:
|
||||
Flag(ld->activation, SPAC_AnyCross, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Monsteractivate:
|
||||
Flag(ld->flags, ML_MONSTERSCANACTIVATE, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Blockplayers:
|
||||
Flag(ld->flags, ML_BLOCK_PLAYERS, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Blockeverything:
|
||||
Flag(ld->flags, ML_BLOCKEVERYTHING, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Zoneboundary:
|
||||
Flag(ld->flags, ML_ZONEBOUNDARY, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Clipmidtex:
|
||||
Flag(ld->flags, ML_CLIP_MIDTEX, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Wrapmidtex:
|
||||
Flag(ld->flags, ML_WRAP_MIDTEX, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Midtex3d:
|
||||
Flag(ld->flags, ML_3DMIDTEX, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Checkswitchrange:
|
||||
Flag(ld->flags, ML_CHECKSWITCHRANGE, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Firstsideonly:
|
||||
Flag(ld->flags, ML_FIRSTSIDEONLY, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_blockprojectiles:
|
||||
Flag(ld->flags, ML_BLOCKPROJECTILE, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_blockuse:
|
||||
Flag(ld->flags, ML_BLOCKUSE, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sc.MustGetToken(';');
|
||||
|
||||
if (!strnicmp("user_", key.GetChars(), 5))
|
||||
{
|
||||
AddUserKey(key, UDMF_Line, index);
|
||||
}
|
||||
}
|
||||
|
||||
if (isTranslated)
|
||||
|
|
@ -671,7 +851,7 @@ struct UDMFParser
|
|||
//
|
||||
//===========================================================================
|
||||
|
||||
void ParseSidedef(side_t *sd, mapsidedef_t *sdt)
|
||||
void ParseSidedef(side_t *sd, mapsidedef_t *sdt, int index)
|
||||
{
|
||||
fixed_t texofs[2]={0,0};
|
||||
|
||||
|
|
@ -688,27 +868,27 @@ struct UDMFParser
|
|||
{
|
||||
case NAME_Offsetx:
|
||||
texofs[0] = CheckInt(key) << FRACBITS;
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Offsety:
|
||||
texofs[1] = CheckInt(key) << FRACBITS;
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Texturetop:
|
||||
strncpy(sdt->toptexture, CheckString(key), 8);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Texturebottom:
|
||||
strncpy(sdt->bottomtexture, CheckString(key), 8);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Texturemiddle:
|
||||
strncpy(sdt->midtexture, CheckString(key), 8);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Sector:
|
||||
sd->sector = (sector_t*)(intptr_t)CheckInt(key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
|
@ -718,53 +898,55 @@ struct UDMFParser
|
|||
{
|
||||
case NAME_offsetx_top:
|
||||
sd->SetTextureXOffset(side_t::top, CheckFixed(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_offsety_top:
|
||||
sd->SetTextureYOffset(side_t::top, CheckFixed(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_offsetx_mid:
|
||||
sd->SetTextureXOffset(side_t::mid, CheckFixed(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_offsety_mid:
|
||||
sd->SetTextureYOffset(side_t::mid, CheckFixed(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_offsetx_bottom:
|
||||
sd->SetTextureXOffset(side_t::bottom, CheckFixed(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_offsety_bottom:
|
||||
sd->SetTextureYOffset(side_t::bottom, CheckFixed(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_light:
|
||||
sd->SetLight(CheckInt(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_lightabsolute:
|
||||
if (CheckBool(key)) sd->Flags |= WALLF_ABSLIGHTING;
|
||||
else sd->Flags &= ~WALLF_ABSLIGHTING;
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_nofakecontrast:
|
||||
if (CheckBool(key)) sd->Flags |= WALLF_NOFAKECONTRAST;
|
||||
else sd->Flags &= WALLF_NOFAKECONTRAST;
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_smoothlighting:
|
||||
if (CheckBool(key)) sd->Flags |= WALLF_SMOOTHLIGHTING;
|
||||
else sd->Flags &= ~WALLF_SMOOTHLIGHTING;
|
||||
break;
|
||||
continue;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
sc.MustGetToken(';');
|
||||
if (!strnicmp("user_", key.GetChars(), 5))
|
||||
{
|
||||
AddUserKey(key, UDMF_Side, index);
|
||||
}
|
||||
}
|
||||
// initialization of these is delayed to allow separate offsets and add them with the global ones.
|
||||
sd->AddTextureXOffset(side_t::top, texofs[0]);
|
||||
|
|
@ -818,23 +1000,23 @@ struct UDMFParser
|
|||
{
|
||||
case NAME_Heightfloor:
|
||||
sec->SetPlaneTexZ(sector_t::floor, CheckInt(key) << FRACBITS);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Heightceiling:
|
||||
sec->SetPlaneTexZ(sector_t::ceiling, CheckInt(key) << FRACBITS);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Texturefloor:
|
||||
SetTexture(sec, index, sector_t::floor, CheckString(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Textureceiling:
|
||||
SetTexture(sec, index, sector_t::ceiling, CheckString(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Lightlevel:
|
||||
sec->lightlevel = (BYTE)clamp<int>(CheckInt(key), 0, 255);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Special:
|
||||
sec->special = (short)CheckInt(key);
|
||||
|
|
@ -844,11 +1026,11 @@ struct UDMFParser
|
|||
if (sec->special < 0 || sec->special > 255 || !HexenSectorSpecialOk[sec->special])
|
||||
sec->special = 0; // NULL all unknown specials
|
||||
}
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Id:
|
||||
sec->tag = (short)CheckInt(key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
|
@ -858,99 +1040,102 @@ struct UDMFParser
|
|||
{
|
||||
case NAME_Xpanningfloor:
|
||||
sec->SetXOffset(sector_t::floor, CheckFixed(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Ypanningfloor:
|
||||
sec->SetYOffset(sector_t::floor, CheckFixed(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Xpanningceiling:
|
||||
sec->SetXOffset(sector_t::ceiling, CheckFixed(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Ypanningceiling:
|
||||
sec->SetYOffset(sector_t::ceiling, CheckFixed(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Xscalefloor:
|
||||
sec->SetXScale(sector_t::floor, CheckFixed(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Yscalefloor:
|
||||
sec->SetYScale(sector_t::floor, CheckFixed(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Xscaleceiling:
|
||||
sec->SetXScale(sector_t::ceiling, CheckFixed(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Yscaleceiling:
|
||||
sec->SetYScale(sector_t::ceiling, CheckFixed(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Rotationfloor:
|
||||
sec->SetAngle(sector_t::floor, CheckAngle(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Rotationceiling:
|
||||
sec->SetAngle(sector_t::ceiling, CheckAngle(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Lightfloor:
|
||||
sec->SetPlaneLight(sector_t::floor, CheckInt(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Lightceiling:
|
||||
sec->SetPlaneLight(sector_t::ceiling, CheckInt(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Lightfloorabsolute:
|
||||
if (CheckBool(key)) sec->ChangeFlags(sector_t::floor, 0, SECF_ABSLIGHTING);
|
||||
else sec->ChangeFlags(sector_t::floor, SECF_ABSLIGHTING, 0);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Lightceilingabsolute:
|
||||
if (CheckBool(key)) sec->ChangeFlags(sector_t::ceiling, 0, SECF_ABSLIGHTING);
|
||||
else sec->ChangeFlags(sector_t::ceiling, SECF_ABSLIGHTING, 0);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Gravity:
|
||||
sec->gravity = float(CheckFloat(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Lightcolor:
|
||||
lightcolor = CheckInt(key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Fadecolor:
|
||||
fadecolor = CheckInt(key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Desaturation:
|
||||
desaturation = int(255*CheckFloat(key));
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Silent:
|
||||
Flag(sec->Flags, SECF_SILENT, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_NoRespawn:
|
||||
Flag(sec->Flags, SECF_NORESPAWN, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Nofallingdamage:
|
||||
Flag(sec->Flags, SECF_NOFALLINGDAMAGE, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
case NAME_Dropactors:
|
||||
Flag(sec->Flags, SECF_FLOORDROP, key);
|
||||
break;
|
||||
continue;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
sc.MustGetToken(';');
|
||||
if (!strnicmp("user_", key.GetChars(), 5))
|
||||
{
|
||||
AddUserKey(key, UDMF_Sector, index);
|
||||
}
|
||||
}
|
||||
|
||||
sec->floorplane.d = -sec->GetPlaneTexZ(sector_t::floor);
|
||||
|
|
@ -1196,14 +1381,14 @@ struct UDMFParser
|
|||
else if (sc.Compare("linedef"))
|
||||
{
|
||||
line_t li;
|
||||
ParseLinedef(&li);
|
||||
ParseLinedef(&li, ParsedLines.Size());
|
||||
ParsedLines.Push(li);
|
||||
}
|
||||
else if (sc.Compare("sidedef"))
|
||||
{
|
||||
side_t si;
|
||||
mapsidedef_t st;
|
||||
ParseSidedef(&si, &st);
|
||||
ParseSidedef(&si, &st, ParsedSides.Size());
|
||||
ParsedSides.Push(si);
|
||||
ParsedSideTextures.Push(st);
|
||||
}
|
||||
|
|
|
|||
65
src/r_defs.h
65
src/r_defs.h
|
|
@ -85,6 +85,70 @@ class FBitmap;
|
|||
struct FCopyInfo;
|
||||
class DInterpolation;
|
||||
|
||||
enum
|
||||
{
|
||||
UDMF_Line,
|
||||
UDMF_Side,
|
||||
UDMF_Sector,
|
||||
UDMF_Thing
|
||||
};
|
||||
|
||||
|
||||
struct FUDMFKey
|
||||
{
|
||||
enum
|
||||
{
|
||||
UDMF_Int,
|
||||
UDMF_Float,
|
||||
UDMF_String
|
||||
};
|
||||
|
||||
FName Key;
|
||||
int Type;
|
||||
int IntVal;
|
||||
double FloatVal;
|
||||
FString StringVal;
|
||||
|
||||
FUDMFKey()
|
||||
{
|
||||
}
|
||||
|
||||
FUDMFKey& operator =(int val)
|
||||
{
|
||||
Type = UDMF_Int;
|
||||
IntVal = val;
|
||||
FloatVal = val;
|
||||
StringVal = "";
|
||||
return *this;
|
||||
}
|
||||
|
||||
FUDMFKey& operator =(double val)
|
||||
{
|
||||
Type = UDMF_Float;
|
||||
IntVal = int(val);
|
||||
FloatVal = val;
|
||||
StringVal = "";
|
||||
return *this;
|
||||
}
|
||||
|
||||
FUDMFKey& operator =(const FString &val)
|
||||
{
|
||||
Type = UDMF_String;
|
||||
IntVal = strtol(val, NULL, 0);
|
||||
FloatVal = strtod(val, NULL);
|
||||
StringVal = val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class FUDMFKeys : public TArray<FUDMFKey>
|
||||
{
|
||||
public:
|
||||
void Sort();
|
||||
FUDMFKey *Find(FName key);
|
||||
};
|
||||
|
||||
//
|
||||
// The SECTORS record, at runtime.
|
||||
// Stores things/mobjs.
|
||||
|
|
@ -663,6 +727,7 @@ struct side_t
|
|||
WORD TexelLength;
|
||||
SWORD Light;
|
||||
BYTE Flags;
|
||||
int Index; // needed to access custom UDMF fields which are stored in loading order.
|
||||
|
||||
int GetLightLevel (bool foggy, int baselight) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -147,6 +147,12 @@ void FResourceLump::LumpNameSetup(char *iname)
|
|||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Checks for embedded resource files
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FResourceLump::CheckEmbedded()
|
||||
{
|
||||
// Checks for embedded archives
|
||||
|
|
@ -155,6 +161,7 @@ void FResourceLump::CheckEmbedded()
|
|||
{
|
||||
// Mark all embedded WADs
|
||||
Flags |= LUMPF_EMBEDDED;
|
||||
memset(Name, 0, 8);
|
||||
}
|
||||
/* later
|
||||
else
|
||||
|
|
@ -162,10 +169,12 @@ void FResourceLump::CheckEmbedded()
|
|||
if (c==NULL) c = strstr(Name, ".zip");
|
||||
if (c==NULL) c = strstr(Name, ".pk3");
|
||||
if (c==NULL) c = strstr(Name, ".7z");
|
||||
if (c==NULL) c = strstr(Name, ".pak");
|
||||
if (c && strlen(c) <= 4)
|
||||
{
|
||||
// Mark all embedded archives in any directory
|
||||
Flags |= LUMPF_EMBEDDED;
|
||||
memset(Name, 0, 8);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue