- 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:
Christoph Oelckers 2009-05-11 21:05:40 +00:00
commit 571d28281b
16 changed files with 540 additions and 1493 deletions

View file

@ -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;

View file

@ -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:
{

View file

@ -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 ();

View file

@ -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;
}
}
}
}

View file

@ -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);
}
}
//

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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

View file

@ -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);
}

View file

@ -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;

View file

@ -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);
}
}
*/