mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-27 22:42:57 +00:00
- Reworked a few options that previously depended on LEVEL_HEXENFORMAT
(actors being forced to the ground by instantly moving sectors, strife railing handling and shooting lines with a non-zero but unassigned tag.) With UDMF such semantics have to be handled diffently. - finalized UDMF 1.0 implementation. - Added Martin Howe's latest morph update. SVN r987 (trunk)
This commit is contained in:
parent
7160e09b04
commit
ab6b5e337e
28 changed files with 843 additions and 226 deletions
|
@ -1,3 +1,11 @@
|
|||
May 22, 2008 (Changes by Graf Zahl)
|
||||
- Reworked a few options that previously depended on LEVEL_HEXENFORMAT
|
||||
(actors being forced to the ground by instantly moving sectors, strife
|
||||
railing handling and shooting lines with a non-zero but unassigned tag.)
|
||||
With UDMF such semantics have to be handled diffently.
|
||||
- finalized UDMF 1.0 implementation.
|
||||
- Added Martin Howe's latest morph update.
|
||||
|
||||
May 21, 2008
|
||||
- Fixed: When R_DrawTiltedPlane() calculates the p vector, it can overflow
|
||||
if the view is near the bounds of the fixed point coordinate system. This
|
||||
|
|
|
@ -1123,7 +1123,7 @@ void G_PlayerFinishLevel (int player, EFinishLevelType mode, bool resetinventory
|
|||
|
||||
if (p->morphTics)
|
||||
{ // Undo morph
|
||||
P_UndoPlayerMorph (p, true);
|
||||
P_UndoPlayerMorph (p, p, true);
|
||||
}
|
||||
|
||||
// Clears the entire inventory and gives back the defaults for starting a game
|
||||
|
|
|
@ -34,7 +34,7 @@ bool AArtiTomeOfPower::Use (bool pickup)
|
|||
{
|
||||
if (Owner->player->morphTics && (Owner->player->MorphStyle & MORPH_UNDOBYTOMEOFPOWER))
|
||||
{ // Attempt to undo chicken
|
||||
if (!P_UndoPlayerMorph (Owner->player))
|
||||
if (!P_UndoPlayerMorph (Owner->player, Owner->player))
|
||||
{ // Failed
|
||||
if (!(Owner->player->MorphStyle & MORPH_FAILNOTELEFRAG))
|
||||
{
|
||||
|
|
|
@ -118,6 +118,8 @@
|
|||
#define LEVEL_FORCETEAMPLAYOFF UCONST64(0x8000000000000)
|
||||
|
||||
#define LEVEL_CONV_SINGLE_UNFREEZE UCONST64(0x10000000000000)
|
||||
#define LEVEL_RAILINGHACK UCONST64(0x20000000000000) // but UDMF requires them to be separate to have more control
|
||||
#define LEVEL_DUMMYSWITCHES UCONST64(0x40000000000000)
|
||||
|
||||
|
||||
struct acsdefered_s;
|
||||
|
|
|
@ -62,7 +62,7 @@ bool AArtiTeleport::Use (bool pickup)
|
|||
bool canlaugh = true;
|
||||
if (Owner->player->morphTics && (Owner->player->MorphStyle & MORPH_UNDOBYCHAOSDEVICE))
|
||||
{ // Teleporting away will undo any morph effects (pig)
|
||||
if (!P_UndoPlayerMorph (Owner->player) && (Owner->player->MorphStyle & MORPH_FAILNOLAUGH))
|
||||
if (!P_UndoPlayerMorph (Owner->player, Owner->player) && (Owner->player->MorphStyle & MORPH_FAILNOLAUGH))
|
||||
{
|
||||
canlaugh = false;
|
||||
}
|
||||
|
|
|
@ -1740,7 +1740,7 @@ void APowerMorph::Serialize (FArchive &arc)
|
|||
{
|
||||
Super::Serialize (arc);
|
||||
arc << PlayerClass << MorphStyle << MorphFlash << UnMorphFlash;
|
||||
arc << player;
|
||||
arc << Player;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -1761,7 +1761,7 @@ void APowerMorph::InitEffect( )
|
|||
{
|
||||
Owner = realplayer->mo; // Replace the new owner in our owner; safe because we are not attached to anything yet
|
||||
ItemFlags |= IF_CREATECOPYMOVED; // Let the caller know the "real" owner has changed (to the morphed actor)
|
||||
player = realplayer; // Store the player identity (morphing clears the unmorphed actor's "player" field)
|
||||
Player = realplayer; // Store the player identity (morphing clears the unmorphed actor's "player" field)
|
||||
}
|
||||
else // morph failed - give the caller an opportunity to fail the pickup completely
|
||||
{
|
||||
|
@ -1778,23 +1778,45 @@ void APowerMorph::InitEffect( )
|
|||
|
||||
void APowerMorph::EndEffect( )
|
||||
{
|
||||
if (Owner != NULL && player != NULL)
|
||||
// Abort if owner already destroyed
|
||||
if (Owner == NULL)
|
||||
{
|
||||
int savedMorphTics = player->morphTics;
|
||||
P_UndoPlayerMorph (player);
|
||||
if (player->morphTics /*failed*/)
|
||||
assert(Player == NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
// Abort if owner already unmorphed
|
||||
if (Player == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Abort if owner is dead; their Die() method will
|
||||
// take care of any required unmorphing on death.
|
||||
if (Player->health <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Unmorph if possible
|
||||
int savedMorphTics = Player->morphTics;
|
||||
P_UndoPlayerMorph (Player, Player);
|
||||
|
||||
// Abort if unmorph failed; in that case,
|
||||
// set the usual retry timer and return.
|
||||
if (Player->morphTics)
|
||||
{
|
||||
// Transfer retry timeout
|
||||
// to the powerup's timer.
|
||||
EffectTics = player->morphTics;
|
||||
EffectTics = Player->morphTics;
|
||||
// Reload negative morph tics;
|
||||
// use actual value; it may
|
||||
// be in use for animation.
|
||||
player->morphTics = savedMorphTics;
|
||||
}
|
||||
else // unmorph succeeded
|
||||
{
|
||||
player = NULL;
|
||||
}
|
||||
Player->morphTics = savedMorphTics;
|
||||
// Try again some time later
|
||||
return;
|
||||
}
|
||||
|
||||
// Unmorph suceeded
|
||||
Player = NULL;
|
||||
}
|
||||
|
|
|
@ -267,7 +267,7 @@ protected:
|
|||
void InitEffect ();
|
||||
void EndEffect ();
|
||||
// Variables
|
||||
player_s *player;
|
||||
player_s *Player;
|
||||
};
|
||||
|
||||
#endif //__A_ARTIFACTS_H__
|
||||
|
|
|
@ -63,6 +63,13 @@ bool P_MorphPlayer (player_t *activator, player_t *p, const PClass *spawntype, i
|
|||
|
||||
morphed = static_cast<APlayerPawn *>(Spawn (spawntype, actor->x, actor->y, actor->z, NO_REPLACE));
|
||||
DObject::StaticPointerSubstitution (actor, morphed);
|
||||
if ((actor->tid != 0) && (style & MORPH_NEWTIDBEHAVIOUR))
|
||||
{
|
||||
morphed->tid = actor->tid;
|
||||
morphed->AddToHash ();
|
||||
actor->RemoveFromHash ();
|
||||
actor->tid = 0;
|
||||
}
|
||||
morphed->angle = actor->angle;
|
||||
morphed->target = actor->target;
|
||||
morphed->tracer = actor;
|
||||
|
@ -159,7 +166,7 @@ bool P_MorphPlayer (player_t *activator, player_t *p, const PClass *spawntype, i
|
|||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
bool P_UndoPlayerMorph (player_t *player, bool force)
|
||||
bool P_UndoPlayerMorph (player_s *activator, player_t *player, bool force)
|
||||
{
|
||||
AWeapon *beastweap;
|
||||
APlayerPawn *mo;
|
||||
|
@ -177,11 +184,19 @@ bool P_UndoPlayerMorph (player_t *player, bool force)
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((pmo->flags2 & MF2_INVULNERABLE) && ((player != activator) || (!(player->MorphStyle & MORPH_WHENINVULNERABLE))))
|
||||
{ // Immune when invulnerable unless this is something we initiated.
|
||||
// If the WORLD is the initiator, the same player should be given
|
||||
// as the activator; WORLD initiated actions should always succeed.
|
||||
return false;
|
||||
}
|
||||
|
||||
mo = barrier_cast<APlayerPawn *>(pmo->tracer);
|
||||
mo->SetOrigin (pmo->x, pmo->y, pmo->z);
|
||||
mo->flags |= MF_SOLID;
|
||||
pmo->flags &= ~MF_SOLID;
|
||||
if (!force && P_TestMobjLocation (mo) == false)
|
||||
if (!force && !P_TestMobjLocation (mo))
|
||||
{ // Didn't fit
|
||||
mo->flags &= ~MF_SOLID;
|
||||
pmo->flags |= MF_SOLID;
|
||||
|
@ -192,6 +207,11 @@ bool P_UndoPlayerMorph (player_t *player, bool force)
|
|||
|
||||
mo->ObtainInventory (pmo);
|
||||
DObject::StaticPointerSubstitution (pmo, mo);
|
||||
if ((pmo->tid != 0) && (player->MorphStyle & MORPH_NEWTIDBEHAVIOUR))
|
||||
{
|
||||
mo->tid = pmo->tid;
|
||||
mo->AddToHash ();
|
||||
}
|
||||
mo->angle = pmo->angle;
|
||||
mo->player = player;
|
||||
mo->reactiontime = 18;
|
||||
|
@ -211,6 +231,7 @@ bool P_UndoPlayerMorph (player_t *player, bool force)
|
|||
|
||||
const PClass *exit_flash = player->MorphExitFlash;
|
||||
bool correctweapon = !!(player->MorphStyle & MORPH_LOSEACTUALWEAPON);
|
||||
bool undobydeathsaves = !!(player->MorphStyle & MORPH_UNDOBYDEATHSAVES);
|
||||
|
||||
player->morphTics = 0;
|
||||
player->MorphedPlayerClass = 0;
|
||||
|
@ -222,7 +243,16 @@ bool P_UndoPlayerMorph (player_t *player, bool force)
|
|||
{
|
||||
level2->Destroy ();
|
||||
}
|
||||
|
||||
if ((player->health > 0) || undobydeathsaves)
|
||||
{
|
||||
player->health = mo->health = mo->GetDefault()->health;
|
||||
}
|
||||
else // killed when morphed so stay dead
|
||||
{
|
||||
mo->health = player->health;
|
||||
}
|
||||
|
||||
player->mo = mo;
|
||||
if (player->camera == pmo)
|
||||
{
|
||||
|
@ -363,18 +393,17 @@ bool P_MorphMonster (AActor *actor, const PClass *spawntype, int duration, int s
|
|||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC P_UpdateMorphedMonster
|
||||
// FUNC P_UndoMonsterMorph
|
||||
//
|
||||
// Returns true if the monster unmorphs.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
bool P_UpdateMorphedMonster (AMorphedMonster *beast)
|
||||
bool P_UndoMonsterMorph (AMorphedMonster *beast, bool force)
|
||||
{
|
||||
AActor *actor;
|
||||
|
||||
if (beast->UnmorphTime == 0 ||
|
||||
beast->UnmorphTime > level.time ||
|
||||
beast->UnmorphedMe == NULL ||
|
||||
beast->flags3 & MF3_STAYMORPHED)
|
||||
{
|
||||
|
@ -384,7 +413,7 @@ bool P_UpdateMorphedMonster (AMorphedMonster *beast)
|
|||
actor->SetOrigin (beast->x, beast->y, beast->z);
|
||||
actor->flags |= MF_SOLID;
|
||||
beast->flags &= ~MF_SOLID;
|
||||
if (P_TestMobjLocation (actor) == false)
|
||||
if (!force && !P_TestMobjLocation (actor))
|
||||
{ // Didn't fit
|
||||
actor->flags &= ~MF_SOLID;
|
||||
beast->flags |= MF_SOLID;
|
||||
|
@ -417,6 +446,82 @@ bool P_UpdateMorphedMonster (AMorphedMonster *beast)
|
|||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC P_UpdateMorphedMonster
|
||||
//
|
||||
// Returns true if the monster unmorphs.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
bool P_UpdateMorphedMonster (AMorphedMonster *beast)
|
||||
{
|
||||
if (beast->UnmorphTime > level.time)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return P_UndoMonsterMorph (beast);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// FUNC P_MorphedDeath
|
||||
//
|
||||
// Unmorphs the actor if possible.
|
||||
// Returns the unmorphed actor, the style with which they were morphed and the
|
||||
// health (of the AActor, not the player_s) they last had before unmorphing.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
bool P_MorphedDeath(AActor *actor, AActor **morphed, int *morphedstyle, int *morphedhealth)
|
||||
{
|
||||
// May be a morphed player
|
||||
if ((actor->player) &&
|
||||
(actor->player->morphTics) &&
|
||||
(actor->player->MorphStyle & MORPH_UNDOBYDEATH) &&
|
||||
(actor->player->mo) &&
|
||||
(actor->player->mo->tracer))
|
||||
{
|
||||
AActor *realme = actor->player->mo->tracer;
|
||||
int realstyle = actor->player->MorphStyle;
|
||||
int realhealth = actor->health;
|
||||
if (P_UndoPlayerMorph(actor->player, actor->player, !!(actor->player->MorphStyle & MORPH_UNDOBYDEATHFORCED)))
|
||||
{
|
||||
*morphed = realme;
|
||||
*morphedstyle = realstyle;
|
||||
*morphedhealth = realhealth;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// May be a morphed monster
|
||||
if (actor->GetClass()->IsDescendantOf(RUNTIME_CLASS(AMorphedMonster)))
|
||||
{
|
||||
AMorphedMonster *fakeme = static_cast<AMorphedMonster *>(actor);
|
||||
if ((fakeme->UnmorphTime) &&
|
||||
(fakeme->MorphStyle & MORPH_UNDOBYDEATH) &&
|
||||
(fakeme->UnmorphedMe))
|
||||
{
|
||||
AActor *realme = fakeme->UnmorphedMe;
|
||||
int realstyle = fakeme->MorphStyle;
|
||||
int realhealth = fakeme->health;
|
||||
if (P_UndoMonsterMorph(fakeme, !!(fakeme->MorphStyle & MORPH_UNDOBYDEATHFORCED)))
|
||||
{
|
||||
*morphed = realme;
|
||||
*morphedstyle = realstyle;
|
||||
*morphedhealth = realhealth;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
fakeme->flags3 |= MF3_STAYMORPHED; // moved here from AMorphedMonster::Die()
|
||||
return false;
|
||||
}
|
||||
|
||||
// Not a morphed player or monster
|
||||
return false;
|
||||
}
|
||||
|
||||
// Base class for morphing projectiles --------------------------------------
|
||||
|
||||
IMPLEMENT_STATELESS_ACTOR(AMorphProjectile, Any, -1, 0)
|
||||
|
@ -479,7 +584,11 @@ void AMorphedMonster::Destroy ()
|
|||
void AMorphedMonster::Die (AActor *source, AActor *inflictor)
|
||||
{
|
||||
// Dead things don't unmorph
|
||||
flags3 |= MF3_STAYMORPHED;
|
||||
// flags3 |= MF3_STAYMORPHED;
|
||||
// [MH]
|
||||
// But they can now, so that line above has been
|
||||
// moved into P_MorphedDeath() and is now set by
|
||||
// that function if and only if it is needed.
|
||||
Super::Die (source, inflictor);
|
||||
if (UnmorphedMe != NULL && (UnmorphedMe->flags & MF_UNMORPHED))
|
||||
{
|
||||
|
|
|
@ -11,25 +11,32 @@
|
|||
enum
|
||||
{
|
||||
MORPH_OLDEFFECTS = 0x00000000, // Default to old Heretic/HeXen behaviour unless flags given
|
||||
MORPH_ADDSTAMINA = 0x00000001, // Power instead of curse (add stamina instead of limiting to health)
|
||||
MORPH_FULLHEALTH = 0x00000002, // New health semantics (!POWER => MaxHealth of animal, POWER => Normal health behaviour)
|
||||
MORPH_ADDSTAMINA = 0x00000001, // Player has a "power" instead of a "curse" (add stamina instead of limiting to health)
|
||||
MORPH_FULLHEALTH = 0x00000002, // Player uses new health semantics (!POWER => MaxHealth of animal, POWER => Normal health behaviour)
|
||||
MORPH_UNDOBYTOMEOFPOWER = 0x00000004, // Player unmorphs upon activating a Tome of Power
|
||||
MORPH_UNDOBYCHAOSDEVICE = 0x00000008, // Player unmorphs upon activating a Chaos Device
|
||||
MORPH_FAILNOTELEFRAG = 0x00000010, // Player stays morphed if unmorph by Tome of Power fails
|
||||
MORPH_FAILNOLAUGH = 0x00000020, // Player doesn't laugh if unmorph by Chaos Device fails
|
||||
MORPH_WHENINVULNERABLE = 0x00000040, // Player can morph when invulnerable but ONLY if doing it to themselves
|
||||
MORPH_LOSEACTUALWEAPON = 0X00000080 // Player loses specified morph weapon only (not "whichever they have when unmorphing")
|
||||
MORPH_WHENINVULNERABLE = 0x00000040, // Player can morph (or scripted unmorph) when invulnerable but ONLY if doing it to themselves
|
||||
MORPH_LOSEACTUALWEAPON = 0x00000080, // Player loses specified morph weapon only (not "whichever they have when unmorphing")
|
||||
MORPH_NEWTIDBEHAVIOUR = 0x00000100, // Actor TID is by default transferred from the old actor to the new actor
|
||||
MORPH_UNDOBYDEATH = 0x00000200, // Actor unmorphs when killed and (unless MORPH_UNDOBYDEATHSAVES) stays dead
|
||||
MORPH_UNDOBYDEATHFORCED = 0x00000400, // Actor (if unmorphed when killed) forces unmorph (not very useful with UNDOBYDEATHSAVES)
|
||||
MORPH_UNDOBYDEATHSAVES = 0x00000800, // Actor (if unmorphed when killed) regains their health and doesn't die
|
||||
};
|
||||
|
||||
struct PClass;
|
||||
class AActor;
|
||||
class player_s;
|
||||
class AMorphedMonster;
|
||||
|
||||
bool P_MorphPlayer (player_s *activator, player_s *player, const PClass *morphclass, int duration = 0, int style = 0,
|
||||
const PClass *enter_flash = NULL, const PClass *exit_flash = NULL);
|
||||
bool P_UndoPlayerMorph (player_s *player, bool force = false);
|
||||
bool P_UndoPlayerMorph (player_s *activator, player_s *player, bool force = false);
|
||||
bool P_MorphMonster (AActor *actor, const PClass *morphclass, int duration = 0, int style = 0,
|
||||
const PClass *enter_flash = NULL, const PClass *exit_flash = NULL);
|
||||
bool P_UndoMonsterMorph (AMorphedMonster *beast, bool force = false);
|
||||
bool P_UpdateMorphedMonster (AActor *actor);
|
||||
bool P_MorphedDeath(AActor *actor, AActor **morphed, int *morphedstyle, int *morphedhealth);
|
||||
|
||||
#endif //__A_MORPH__
|
||||
|
|
|
@ -291,7 +291,7 @@ void cht_DoCheat (player_t *player, int cheat)
|
|||
|
||||
if (player->morphTics > 0)
|
||||
{
|
||||
P_UndoPlayerMorph(player);
|
||||
P_UndoPlayerMorph(player, player);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -438,7 +438,7 @@ const char *cht_Morph (player_t *player, const PClass *morphclass, bool quickund
|
|||
|
||||
if (player->morphTics)
|
||||
{
|
||||
if (P_UndoPlayerMorph (player))
|
||||
if (P_UndoPlayerMorph (player, player))
|
||||
{
|
||||
if (!quickundo && oldclass != morphclass && P_MorphPlayer (player, player, morphclass, 0, style))
|
||||
{
|
||||
|
|
|
@ -249,7 +249,6 @@ xx(Sector)
|
|||
xx(Heightfloor)
|
||||
xx(Heightceiling)
|
||||
xx(Lightlevel)
|
||||
xx(Tag)
|
||||
xx(Texturefloor)
|
||||
xx(Textureceiling)
|
||||
|
||||
|
@ -305,7 +304,7 @@ xx(Twosided)
|
|||
xx(Dontpegtop)
|
||||
xx(Dontpegbottom)
|
||||
xx(Secret)
|
||||
xx(Soundblock)
|
||||
xx(Blocksound)
|
||||
xx(Dontdraw)
|
||||
xx(Mapped)
|
||||
xx(Monsteractivate)
|
||||
|
@ -321,6 +320,7 @@ xx(Checkswitchrange)
|
|||
xx(Firstsideonly)
|
||||
xx(Transparent)
|
||||
xx(Passuse)
|
||||
xx(Repeatspecial)
|
||||
|
||||
xx(Playercross)
|
||||
xx(Playeruse)
|
||||
|
|
121
src/p_acs.cpp
121
src/p_acs.cpp
|
@ -5351,6 +5351,127 @@ int DLevelScript::RunScript ()
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PCD_MORPHACTOR:
|
||||
{
|
||||
int tag = STACK(7);
|
||||
FName playerclass_name = FBehavior::StaticLookupString(STACK(6));
|
||||
const PClass *playerclass = PClass::FindClass (playerclass_name);
|
||||
FName monsterclass_name = FBehavior::StaticLookupString(STACK(5));
|
||||
const PClass *monsterclass = PClass::FindClass (monsterclass_name);
|
||||
int duration = STACK(4);
|
||||
int style = STACK(3);
|
||||
FName morphflash_name = FBehavior::StaticLookupString(STACK(2));
|
||||
const PClass *morphflash = PClass::FindClass (morphflash_name);
|
||||
FName unmorphflash_name = FBehavior::StaticLookupString(STACK(1));
|
||||
const PClass *unmorphflash = PClass::FindClass (unmorphflash_name);
|
||||
int changes = 0;
|
||||
|
||||
if (tag == 0)
|
||||
{
|
||||
if (activator->player)
|
||||
{
|
||||
if (P_MorphPlayer(activator->player, activator->player, playerclass, duration, style, morphflash, unmorphflash))
|
||||
{
|
||||
changes++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (P_MorphMonster(activator, monsterclass, duration, style, morphflash, unmorphflash))
|
||||
{
|
||||
changes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FActorIterator iterator (tag);
|
||||
AActor *actor;
|
||||
|
||||
while ( (actor = iterator.Next ()) )
|
||||
{
|
||||
if (actor->player)
|
||||
{
|
||||
if (P_MorphPlayer(activator->player, actor->player, playerclass, duration, style, morphflash, unmorphflash))
|
||||
{
|
||||
changes++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (P_MorphMonster(actor, monsterclass, duration, style, morphflash, unmorphflash))
|
||||
{
|
||||
changes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STACK(7) = changes;
|
||||
sp -= 6;
|
||||
}
|
||||
break;
|
||||
|
||||
case PCD_UNMORPHACTOR:
|
||||
{
|
||||
int tag = STACK(2);
|
||||
bool force = !!STACK(1);
|
||||
int changes = 0;
|
||||
|
||||
if (tag == 0)
|
||||
{
|
||||
if (activator->player)
|
||||
{
|
||||
if (P_UndoPlayerMorph(activator->player, activator->player, force))
|
||||
{
|
||||
changes++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (activator->GetClass()->IsDescendantOf(RUNTIME_CLASS(AMorphedMonster)))
|
||||
{
|
||||
AMorphedMonster *morphed_actor = barrier_cast<AMorphedMonster *>(activator);
|
||||
if (P_UndoMonsterMorph(morphed_actor, force))
|
||||
{
|
||||
changes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FActorIterator iterator (tag);
|
||||
AActor *actor;
|
||||
|
||||
while ( (actor = iterator.Next ()) )
|
||||
{
|
||||
if (actor->player)
|
||||
{
|
||||
if (P_UndoPlayerMorph(activator->player, actor->player, force))
|
||||
{
|
||||
changes++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (actor->GetClass()->IsDescendantOf(RUNTIME_CLASS(AMorphedMonster)))
|
||||
{
|
||||
AMorphedMonster *morphed_actor = static_cast<AMorphedMonster *>(actor);
|
||||
if (P_UndoMonsterMorph(morphed_actor, force))
|
||||
{
|
||||
changes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
STACK(2) = changes;
|
||||
sp -= 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -551,6 +551,8 @@ public:
|
|||
PCD_THINGCOUNTSECTOR,
|
||||
PCD_THINGCOUNTNAMESECTOR,
|
||||
PCD_CHECKPLAYERCAMERA, // [TN]
|
||||
PCD_MORPHACTOR, // [MH]
|
||||
PCD_UNMORPHACTOR, // [MH]
|
||||
|
||||
PCODE_COMMAND_COUNT
|
||||
};
|
||||
|
|
|
@ -236,6 +236,7 @@ static void LoadScriptFile (const char *name)
|
|||
lump = Wads.ReopenLumpNum (lumpnum);
|
||||
|
||||
LoadScriptFile(lump, Wads.LumpLength(lumpnum));
|
||||
delete lump;
|
||||
}
|
||||
|
||||
static void LoadScriptFile(FileReader *lump, int numnodes)
|
||||
|
@ -278,7 +279,6 @@ static void LoadScriptFile(FileReader *lump, int numnodes)
|
|||
}
|
||||
StrifeDialogues.Push (node);
|
||||
}
|
||||
delete lump;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
|
|
|
@ -317,8 +317,40 @@ void ClientObituary (AActor *self, AActor *inflictor, AActor *attacker)
|
|||
//
|
||||
EXTERN_CVAR (Int, fraglimit)
|
||||
|
||||
static int GibHealth(AActor *actor)
|
||||
{
|
||||
return -abs(
|
||||
actor->GetClass()->Meta.GetMetaInt (
|
||||
AMETA_GibHealth,
|
||||
gameinfo.gametype == GAME_Doom ?
|
||||
-actor->GetDefault()->health :
|
||||
-actor->GetDefault()->health/2));
|
||||
}
|
||||
|
||||
void AActor::Die (AActor *source, AActor *inflictor)
|
||||
{
|
||||
// Handle possible unmorph on death
|
||||
bool wasgibbed = (health < GibHealth(this));
|
||||
AActor *realthis = NULL;
|
||||
int realstyle = 0;
|
||||
int realhealth = 0;
|
||||
if (P_MorphedDeath(this, &realthis, &realstyle, &realhealth))
|
||||
{
|
||||
if (!(realstyle & MORPH_UNDOBYDEATHSAVES))
|
||||
{
|
||||
if (wasgibbed)
|
||||
{
|
||||
int realgibhealth = GibHealth(realthis);
|
||||
if (realthis->health >= realgibhealth)
|
||||
{
|
||||
realthis->health = realgibhealth -1; // if morphed was gibbed, so must original be (where allowed)
|
||||
}
|
||||
}
|
||||
realthis->Die(source, inflictor);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// [SO] 9/2/02 -- It's rather funny to see an exploded player body with the invuln sparkle active :)
|
||||
effects &= ~FX_RESPAWNINVUL;
|
||||
//flags &= ~MF_INVINCIBLE;
|
||||
|
@ -634,8 +666,7 @@ void AActor::Die (AActor *source, AActor *inflictor)
|
|||
{
|
||||
int flags4 = inflictor == NULL ? 0 : inflictor->flags4;
|
||||
|
||||
int gibhealth = -abs(GetClass()->Meta.GetMetaInt (AMETA_GibHealth,
|
||||
gameinfo.gametype == GAME_Doom ? -GetDefault()->health : -GetDefault()->health/2));
|
||||
int gibhealth = GibHealth(this);
|
||||
|
||||
// Don't pass on a damage type this actor cannot handle.
|
||||
// (most importantly, prevent barrels from passing on ice damage.)
|
||||
|
|
|
@ -564,9 +564,6 @@ enum
|
|||
PO_SPAWNHURT_TYPE
|
||||
};
|
||||
|
||||
#define PO_LINE_START 1 // polyobj line start special
|
||||
#define PO_LINE_EXPLICIT 5
|
||||
|
||||
extern polyobj_t *polyobjs; // list of all poly-objects on the level
|
||||
extern int po_NumPolyobjs;
|
||||
extern polyspawns_t *polyspawns; // [RH] list of polyobject things to spawn
|
||||
|
|
|
@ -608,8 +608,7 @@ bool PIT_CheckLine (line_t *ld, const FBoundingBox &box, FCheckPosition &tm)
|
|||
// better than Strife's handling of rails, which lets you jump into rails
|
||||
// from either side. How long until somebody reports this as a bug and I'm
|
||||
// forced to say, "It's not a bug. It's a feature?" Ugh.
|
||||
(gameinfo.gametype != GAME_Strife ||
|
||||
level.flags & LEVEL_HEXENFORMAT ||
|
||||
(!(level.flags & LEVEL_RAILINGHACK) ||
|
||||
open.bottom == tm.thing->Sector->floorplane.ZatPoint (sx, sy)))
|
||||
{
|
||||
open.bottom += 32*FRACUNIT;
|
||||
|
@ -3599,6 +3598,7 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b
|
|||
|
||||
struct FChangePosition
|
||||
{
|
||||
sector_t *sector;
|
||||
int moveamt;
|
||||
int crushchange;
|
||||
bool nofit;
|
||||
|
@ -3953,7 +3953,7 @@ void PIT_FloorDrop (AActor *thing, FChangePosition *cpos)
|
|||
P_CheckFakeFloorTriggers (thing, oldz);
|
||||
}
|
||||
else if ((thing->flags & MF_NOGRAVITY) ||
|
||||
((!(level.flags & LEVEL_HEXENFORMAT) || cpos->moveamt < 9*FRACUNIT)
|
||||
(((cpos->sector->Flags & SECF_FLOORDROP) || cpos->moveamt < 9*FRACUNIT)
|
||||
&& thing->z - thing->floorz <= cpos->moveamt))
|
||||
{
|
||||
thing->z = thing->floorz;
|
||||
|
@ -4104,6 +4104,7 @@ bool P_ChangeSector (sector_t *sector, int crunch, int amt, int floorOrCeil, boo
|
|||
cpos.crushchange = crunch;
|
||||
cpos.moveamt = abs (amt);
|
||||
cpos.movemidtex = false;
|
||||
cpos.sector = sector;
|
||||
|
||||
// [RH] Use different functions for the four different types of sector
|
||||
// movement. Also update the soundorg's z-coordinate for 3D sound.
|
||||
|
|
|
@ -370,6 +370,7 @@ MapData *P_OpenMapData(const char * mapname)
|
|||
else if (!stricmp(lumpname, "BEHAVIOR"))
|
||||
{
|
||||
index = ML_BEHAVIOR;
|
||||
map->HasBehavior = true;
|
||||
}
|
||||
else if (!stricmp(lumpname, "ENDMAP"))
|
||||
{
|
||||
|
@ -411,14 +412,16 @@ MapData *P_OpenMapData(const char * mapname)
|
|||
(*map->file) >> numentries >> dirofs;
|
||||
|
||||
map->file->Seek(dirofs, SEEK_SET);
|
||||
for(DWORD i = 0; i < numentries; i++)
|
||||
(*map->file) >> map->MapLumps[0].FilePos >> map->MapLumps[0].Size;
|
||||
map->file->Read(map->MapLumps[0].Name, 8);
|
||||
|
||||
for(DWORD i = 1; i < numentries; i++)
|
||||
{
|
||||
DWORD offset, size;
|
||||
char lumpname[8];
|
||||
|
||||
(*map->file) >> offset >> size;
|
||||
map->file->Read(lumpname, 8);
|
||||
|
||||
if (i == 1 && !strnicmp(lumpname, "TEXTMAP", 8))
|
||||
{
|
||||
map->isText = true;
|
||||
|
@ -432,28 +435,29 @@ MapData *P_OpenMapData(const char * mapname)
|
|||
{
|
||||
I_Error("Invalid map definition for %s", mapname);
|
||||
}
|
||||
else if (!stricmp(lumpname, "ZNODES"))
|
||||
else if (!strnicmp(lumpname, "ZNODES",8))
|
||||
{
|
||||
index = ML_GLZNODES;
|
||||
}
|
||||
else if (!stricmp(lumpname, "BLOCKMAP"))
|
||||
else if (!strnicmp(lumpname, "BLOCKMAP",8))
|
||||
{
|
||||
// there is no real point in creating a blockmap but let's use it anyway
|
||||
index = ML_BLOCKMAP;
|
||||
}
|
||||
else if (!stricmp(lumpname, "REJECT"))
|
||||
else if (!strnicmp(lumpname, "REJECT",8))
|
||||
{
|
||||
index = ML_REJECT;
|
||||
}
|
||||
else if (!stricmp(lumpname, "DIALOGUE"))
|
||||
else if (!strnicmp(lumpname, "DIALOGUE",8))
|
||||
{
|
||||
index = ML_CONVERSATION;
|
||||
}
|
||||
else if (!stricmp(lumpname, "BEHAVIOR"))
|
||||
else if (!strnicmp(lumpname, "BEHAVIOR",8))
|
||||
{
|
||||
index = ML_BEHAVIOR;
|
||||
map->HasBehavior = true;
|
||||
}
|
||||
else if (!stricmp(lumpname, "ENDMAP"))
|
||||
else if (!strnicmp(lumpname, "ENDMAP",8))
|
||||
{
|
||||
return map;
|
||||
}
|
||||
|
@ -1179,6 +1183,7 @@ void P_LoadSectors (MapData * map)
|
|||
for (i = 0; i < numsectors; i++, ss++, ms++)
|
||||
{
|
||||
ss->e = §ors[0].e[i];
|
||||
if (!map->HasBehavior) ss->Flags |= SECF_FLOORDROP;
|
||||
ss->floortexz = LittleShort(ms->floorheight)<<FRACBITS;
|
||||
ss->floorplane.d = -ss->floortexz;
|
||||
ss->floorplane.c = FRACUNIT;
|
||||
|
@ -3266,6 +3271,16 @@ void P_SetupLevel (char *lumpname, int position)
|
|||
}
|
||||
}
|
||||
|
||||
if (!map->HasBehavior && !map->isText)
|
||||
{
|
||||
// set compatibility flags
|
||||
if (gameinfo.gametype == GAME_Strife)
|
||||
{
|
||||
level.flags |= LEVEL_RAILINGHACK;
|
||||
}
|
||||
level.flags |= LEVEL_DUMMYSWITCHES;
|
||||
}
|
||||
|
||||
FBehavior::StaticLoadDefaultModules ();
|
||||
|
||||
P_LoadStrifeConversations (map, lumpname);
|
||||
|
|
|
@ -229,11 +229,12 @@ bool P_ActivateLine (line_t *line, AActor *mo, int side, int activationType)
|
|||
}
|
||||
// some old WADs use this method to create walls that change the texture when shot.
|
||||
else if (activationType == SPAC_Impact && // only for shootable triggers
|
||||
!(level.flags & LEVEL_HEXENFORMAT) && // only in Doom-format maps
|
||||
(level.flags & LEVEL_DUMMYSWITCHES) && // this is only a compatibility setting for an old hack!
|
||||
!repeat && // only non-repeatable triggers
|
||||
(special<Generic_Floor || special>Generic_Crusher) && // not for Boom's generalized linedefs
|
||||
special && // not for lines without a special
|
||||
line->id && // only if there's a tag (which is stored in the id field)
|
||||
line->args[0] == line->id && // Safety check: exclude edited UDMF linedefs or ones that don't map the tag to args[0]
|
||||
line->args[0] && // only if there's a tag (which is stored in the first arg)
|
||||
P_FindSectorFromTag (line->args[0], -1) == -1) // only if no sector is tagged to this linedef
|
||||
{
|
||||
P_ChangeSwitchTexture (&sides[line->sidenum[0]], repeat, special);
|
||||
|
|
558
src/p_udmf.cpp
558
src/p_udmf.cpp
|
@ -40,6 +40,67 @@
|
|||
#include "p_lnspec.h"
|
||||
#include "templates.h"
|
||||
#include "i_system.h"
|
||||
#include "gi.h"
|
||||
|
||||
// These tables define whichline an
|
||||
static char HexenLineSpecialOk[]={
|
||||
1,1,1,1,1,1,1,1,1,0, // 0-9
|
||||
1,1,1,1,0,0,0,0,0,0, // 10-19
|
||||
1,1,1,1,1,1,1,1,1,1, // 20-29
|
||||
1,1,1,0,0,1,1,0,0,0, // 30-39
|
||||
1,1,1,1,1,1,1,0,0,0, // 40-49
|
||||
0,0,0,0,0,0,0,0,0,0, // 50-59
|
||||
1,1,1,1,1,1,1,1,1,1, // 60-69
|
||||
1,1,1,1,1,1,0,0,0,0, // 70-79
|
||||
1,1,1,1,0,0,0,0,0,0, // 80-89
|
||||
1,1,1,1,1,1,1,0,0,0, // 90-99
|
||||
1,1,1,1,0,0,0,0,0,1, // 100-109
|
||||
1,1,1,1,1,1,1,0,0,0, // 110-119
|
||||
1,0,0,0,0,0,0,0,0,1, // 120-129
|
||||
1,1,1,1,1,1,1,1,1,0, // 130-139
|
||||
1
|
||||
// 140 is the highest valid special in Hexen.
|
||||
|
||||
};
|
||||
|
||||
static char HexenSectorSpecialOk[256]={
|
||||
1,1,1,1,1,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,1,1,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,1,1,
|
||||
1,1,1,1,1,1,1,1,1,1,
|
||||
1,1,1,1,1,
|
||||
};
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
Dm=1,
|
||||
Ht=2,
|
||||
Hx=4,
|
||||
St=8,
|
||||
Zd=16,
|
||||
Zdt=32,
|
||||
|
||||
// will be extended later. Unknown namespaces will always be treated like the base
|
||||
// namespace for each game
|
||||
};
|
||||
|
||||
|
||||
void P_ProcessSideTextures(bool checktranmap, side_t *sd, sector_t *sec, mapsidedef_t *msd, int special, int tag, short *alpha);
|
||||
void P_AdjustLine (line_t *ld);
|
||||
|
@ -49,12 +110,17 @@ extern bool ForceNodeBuild;
|
|||
extern TArray<FMapThing> MapThingsConverted;
|
||||
extern TArray<int> linemap;
|
||||
|
||||
|
||||
#define CHECK_N(f) if (!(namespace_bits&(f))) break;
|
||||
|
||||
struct UDMFParser
|
||||
{
|
||||
FScanner sc;
|
||||
FName namespc;
|
||||
int namespace_bits;
|
||||
bool isTranslated;
|
||||
bool isExtended;
|
||||
bool floordrop;
|
||||
|
||||
TArray<line_t> ParsedLines;
|
||||
TArray<side_t> ParsedSides;
|
||||
|
@ -70,60 +136,126 @@ struct UDMFParser
|
|||
fogMap = normMap = NULL;
|
||||
}
|
||||
|
||||
void Flag(DWORD &value, int mask, const FString &svalue)
|
||||
FName ParseKey()
|
||||
{
|
||||
if (!svalue.CompareNoCase("true"))
|
||||
sc.MustGetString();
|
||||
FName key = sc.String;
|
||||
sc.MustGetToken('=');
|
||||
|
||||
sc.Number = 0;
|
||||
sc.Float = 0;
|
||||
sc.MustGetAnyToken();
|
||||
|
||||
if (sc.TokenType == '+' || sc.TokenType == '-')
|
||||
{
|
||||
value |= mask;
|
||||
bool neg = (sc.TokenType == '-');
|
||||
sc.MustGetAnyToken();
|
||||
if (sc.TokenType != TK_IntConst && sc.TokenType != TK_FloatConst)
|
||||
{
|
||||
sc.ScriptMessage("Numeric constant expected");
|
||||
}
|
||||
else
|
||||
if (neg)
|
||||
{
|
||||
value &= ~mask;
|
||||
sc.Number = -sc.Number;
|
||||
sc.Float = -sc.Float;
|
||||
}
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
int CheckInt(const char *key)
|
||||
{
|
||||
if (sc.TokenType != TK_IntConst)
|
||||
{
|
||||
sc.ScriptMessage("Integer value expected for key '%s'", key);
|
||||
}
|
||||
return sc.Number;
|
||||
}
|
||||
|
||||
double CheckFloat(const char *key)
|
||||
{
|
||||
if (sc.TokenType != TK_IntConst && sc.TokenType != TK_FloatConst)
|
||||
{
|
||||
sc.ScriptMessage("Floatint point value expected for key '%s'", key);
|
||||
}
|
||||
return sc.Float;
|
||||
}
|
||||
|
||||
fixed_t CheckFixed(const char *key)
|
||||
{
|
||||
return FLOAT2FIXED(CheckFloat(key));
|
||||
}
|
||||
|
||||
bool CheckBool(const char *key)
|
||||
{
|
||||
if (sc.TokenType == TK_True) return true;
|
||||
if (sc.TokenType == TK_False) return false;
|
||||
sc.ScriptMessage("Boolean value expected for key '%s'", key);
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *CheckString(const char *key)
|
||||
{
|
||||
if (sc.TokenType != TK_StringConst)
|
||||
{
|
||||
sc.ScriptMessage("String value expected for key '%s'", key);
|
||||
}
|
||||
return sc.String;
|
||||
}
|
||||
|
||||
void Flag(DWORD &value, int mask, const char *key)
|
||||
{
|
||||
if (CheckBool(key)) value |= mask;
|
||||
else value &= ~mask;
|
||||
}
|
||||
|
||||
void ParseThing(FMapThing *th)
|
||||
{
|
||||
memset(th, 0, sizeof(*th));
|
||||
sc.MustGetStringName("{");
|
||||
while (!sc.CheckString("}"))
|
||||
sc.MustGetToken('{');
|
||||
while (!sc.CheckToken('}'))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FName key = sc.String;
|
||||
sc.MustGetStringName("=");
|
||||
sc.MustGetString();
|
||||
FString value = sc.String;
|
||||
sc.MustGetStringName(";");
|
||||
FName key = ParseKey();
|
||||
switch(key)
|
||||
{
|
||||
case NAME_TID:
|
||||
th->thingid = (WORD)strtol(value, NULL, 0);
|
||||
case NAME_Id:
|
||||
th->thingid = CheckInt(key);
|
||||
break;
|
||||
|
||||
case NAME_X:
|
||||
th->x = FLOAT2FIXED(strtod(value, NULL));
|
||||
th->x = CheckFixed(key);
|
||||
break;
|
||||
|
||||
case NAME_Y:
|
||||
th->y = FLOAT2FIXED(strtod(value, NULL));
|
||||
th->y = CheckFixed(key);
|
||||
break;
|
||||
|
||||
case NAME_Height:
|
||||
th->z = FLOAT2FIXED(strtod(value, NULL));
|
||||
th->z = CheckFixed(key);
|
||||
break;
|
||||
|
||||
case NAME_Angle:
|
||||
th->angle = (short)strtol(value, NULL, 0);
|
||||
th->angle = (short)CheckInt(key);
|
||||
break;
|
||||
|
||||
case NAME_Type:
|
||||
th->type = (short)strtol(value, NULL, 0);
|
||||
th->type = (short)CheckInt(key);
|
||||
break;
|
||||
|
||||
case NAME_Special:
|
||||
th->special = (short)strtol(value, NULL, 0);
|
||||
CHECK_N(Hx | Zd | Zdt)
|
||||
th->special = CheckInt(key);
|
||||
break;
|
||||
|
||||
case NAME_Arg0:
|
||||
case NAME_Arg1:
|
||||
case NAME_Arg2:
|
||||
case NAME_Arg3:
|
||||
case NAME_Arg4:
|
||||
th->args[int(key)-int(NAME_Arg0)] = strtol(value, NULL, 0);
|
||||
CHECK_N(Hx | Zd | Zdt)
|
||||
th->args[int(key)-int(NAME_Arg0)] = CheckInt(key);
|
||||
break;
|
||||
|
||||
case NAME_Skill1:
|
||||
case NAME_Skill2:
|
||||
case NAME_Skill3:
|
||||
|
@ -140,11 +272,10 @@ struct UDMFParser
|
|||
case NAME_Skill14:
|
||||
case NAME_Skill15:
|
||||
case NAME_Skill16:
|
||||
if (!value.CompareNoCase("true")) th->SkillFilter |= (1<<(int(key)-NAME_Skill1));
|
||||
if (CheckBool(key)) th->SkillFilter |= (1<<(int(key)-NAME_Skill1));
|
||||
else th->SkillFilter &= ~(1<<(int(key)-NAME_Skill1));
|
||||
break;
|
||||
|
||||
case NAME_Class0:
|
||||
case NAME_Class1:
|
||||
case NAME_Class2:
|
||||
case NAME_Class3:
|
||||
|
@ -161,43 +292,72 @@ struct UDMFParser
|
|||
case NAME_Class14:
|
||||
case NAME_Class15:
|
||||
case NAME_Class16:
|
||||
if (!value.CompareNoCase("true")) th->ClassFilter |= (1<<(int(key)-NAME_Class1));
|
||||
CHECK_N(Hx | Zd | Zdt)
|
||||
if (CheckBool(key)) th->ClassFilter |= (1<<(int(key)-NAME_Class1));
|
||||
else th->SkillFilter &= ~(1<<(int(key)-NAME_Class1));
|
||||
break;
|
||||
|
||||
case NAME_Ambush:
|
||||
Flag(th->flags, MTF_AMBUSH, value); break;
|
||||
Flag(th->flags, MTF_AMBUSH, key);
|
||||
break;
|
||||
|
||||
case NAME_Dormant:
|
||||
Flag(th->flags, MTF_DORMANT, value); break;
|
||||
CHECK_N(Hx | Zd | Zdt)
|
||||
Flag(th->flags, MTF_DORMANT, key);
|
||||
break;
|
||||
|
||||
case NAME_Single:
|
||||
Flag(th->flags, MTF_SINGLE, value); break;
|
||||
Flag(th->flags, MTF_SINGLE, key);
|
||||
break;
|
||||
|
||||
case NAME_Coop:
|
||||
Flag(th->flags, MTF_COOPERATIVE, value); break;
|
||||
Flag(th->flags, MTF_COOPERATIVE, key);
|
||||
break;
|
||||
|
||||
case NAME_Dm:
|
||||
Flag(th->flags, MTF_DEATHMATCH, value); break;
|
||||
Flag(th->flags, MTF_DEATHMATCH, key);
|
||||
break;
|
||||
|
||||
case NAME_Translucent:
|
||||
Flag(th->flags, MTF_SHADOW, value); break;
|
||||
CHECK_N(St | Zd | Zdt)
|
||||
Flag(th->flags, MTF_SHADOW, key);
|
||||
break;
|
||||
|
||||
case NAME_Invisible:
|
||||
Flag(th->flags, MTF_ALTSHADOW, value); break;
|
||||
case NAME_Friend:
|
||||
CHECK_N(St | Zd | Zdt)
|
||||
Flag(th->flags, MTF_ALTSHADOW, key);
|
||||
break;
|
||||
|
||||
case NAME_Friend: // This maps to Strife's friendly flag
|
||||
CHECK_N(Dm | Zd | Zdt)
|
||||
Flag(th->flags, MTF_FRIENDLY, key);
|
||||
break;
|
||||
|
||||
case NAME_Strifeally:
|
||||
Flag(th->flags, MTF_FRIENDLY, value); break;
|
||||
CHECK_N(St | Zd | Zdt)
|
||||
Flag(th->flags, MTF_FRIENDLY, key);
|
||||
break;
|
||||
|
||||
case NAME_Standing:
|
||||
Flag(th->flags, MTF_STANDSTILL, value); break;
|
||||
CHECK_N(St | Zd | Zdt)
|
||||
Flag(th->flags, MTF_STANDSTILL, key);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sc.MustGetToken(';');
|
||||
}
|
||||
if (isTranslated)
|
||||
// Thing specials are only valid in namespaces with Hexen-type specials
|
||||
// and in ZDoomTranslated - which will use the translator on them.
|
||||
if (namespc == NAME_ZDoomTranslated)
|
||||
{
|
||||
if (isExtended)
|
||||
{
|
||||
// NOTE: Handling of this is undefined in the UDMF spec
|
||||
// so it is only done for namespace ZDoomTranslated
|
||||
maplinedef_t mld;
|
||||
line_t ld;
|
||||
|
||||
if (th->special != 0) // if special is 0, keep the args (e.g. for bridge things)
|
||||
{
|
||||
// The trigger type is ignored here.
|
||||
mld.flags = 0;
|
||||
mld.special = th->special;
|
||||
mld.tag = th->args[0];
|
||||
|
@ -205,17 +365,18 @@ struct UDMFParser
|
|||
th->special = ld.special;
|
||||
memcpy(th->args, ld.args, sizeof (ld.args));
|
||||
}
|
||||
else // NULL the special
|
||||
}
|
||||
else if (isTranslated)
|
||||
{
|
||||
th->special = 0;
|
||||
memset(th->args, 0, sizeof (th->args));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ParseLinedef(line_t *ld)
|
||||
{
|
||||
bool passuse = false;
|
||||
bool strifetrans = false;
|
||||
|
||||
memset(ld, 0, sizeof(*ld));
|
||||
ld->Alpha = FRACUNIT;
|
||||
|
@ -224,72 +385,109 @@ struct UDMFParser
|
|||
if (level.flags & LEVEL_CLIPMIDTEX) ld->flags |= ML_CLIP_MIDTEX;
|
||||
if (level.flags & LEVEL_WRAPMIDTEX) ld->flags |= ML_WRAP_MIDTEX;
|
||||
if (level.flags & LEVEL_CHECKSWITCHRANGE) ld->flags |= ML_CHECKSWITCHRANGE;
|
||||
sc.MustGetStringName("{");
|
||||
while (!sc.CheckString("}"))
|
||||
|
||||
sc.MustGetToken('{');
|
||||
while (!sc.CheckToken('}'))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FName key = sc.String;
|
||||
sc.MustGetStringName("=");
|
||||
sc.MustGetString();
|
||||
FString value = sc.String;
|
||||
sc.MustGetStringName(";");
|
||||
FName key = ParseKey();
|
||||
|
||||
// This switch contains all keys of the UDMF base spec
|
||||
switch(key)
|
||||
{
|
||||
case NAME_V1:
|
||||
ld->v1 = (vertex_t*)(intptr_t)strtol(value, NULL, 0); // must be relocated later
|
||||
ld->v1 = (vertex_t*)(intptr_t)CheckInt(key); // must be relocated later
|
||||
break;
|
||||
|
||||
case NAME_V2:
|
||||
ld->v2 = (vertex_t*)(intptr_t)strtol(value, NULL, 0); // must be relocated later
|
||||
ld->v2 = (vertex_t*)(intptr_t)CheckInt(key); // must be relocated later
|
||||
break;
|
||||
|
||||
case NAME_Special:
|
||||
ld->special = strtol(value, NULL, 0);
|
||||
ld->special = CheckInt(key);
|
||||
if (namespc == NAME_Hexen)
|
||||
{
|
||||
if (ld->special < 0 || ld->special > 140 || !HexenLineSpecialOk[ld->special])
|
||||
ld->special = 0; // NULL all specials which don't exist in Hexen
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case NAME_Id:
|
||||
ld->id = strtol(value, NULL, 0);
|
||||
ld->id = CheckInt(key);
|
||||
break;
|
||||
|
||||
case NAME_Sidefront:
|
||||
ld->sidenum[0] = strtol(value, NULL, 0);
|
||||
ld->sidenum[0] = CheckInt(key);
|
||||
break;
|
||||
|
||||
case NAME_Sideback:
|
||||
ld->sidenum[1] = strtol(value, NULL, 0);
|
||||
ld->sidenum[1] = CheckInt(key);
|
||||
break;
|
||||
|
||||
case NAME_Arg0:
|
||||
case NAME_Arg1:
|
||||
case NAME_Arg2:
|
||||
case NAME_Arg3:
|
||||
case NAME_Arg4:
|
||||
ld->args[int(key)-int(NAME_Arg0)] = strtol(value, NULL, 0);
|
||||
ld->args[int(key)-int(NAME_Arg0)] = CheckInt(key);
|
||||
break;
|
||||
|
||||
case NAME_Blocking:
|
||||
Flag(ld->flags, ML_BLOCKING, value); break;
|
||||
Flag(ld->flags, ML_BLOCKING, key);
|
||||
break;
|
||||
|
||||
case NAME_Blockmonsters:
|
||||
Flag(ld->flags, ML_BLOCKMONSTERS, value); break;
|
||||
Flag(ld->flags, ML_BLOCKMONSTERS, key);
|
||||
break;
|
||||
|
||||
case NAME_Twosided:
|
||||
Flag(ld->flags, ML_TWOSIDED, value); break;
|
||||
Flag(ld->flags, ML_TWOSIDED, key);
|
||||
break;
|
||||
|
||||
case NAME_Dontpegtop:
|
||||
Flag(ld->flags, ML_DONTPEGTOP, value); break;
|
||||
Flag(ld->flags, ML_DONTPEGTOP, key);
|
||||
break;
|
||||
|
||||
case NAME_Dontpegbottom:
|
||||
Flag(ld->flags, ML_DONTPEGBOTTOM, value); break;
|
||||
Flag(ld->flags, ML_DONTPEGBOTTOM, key);
|
||||
break;
|
||||
|
||||
case NAME_Secret:
|
||||
Flag(ld->flags, ML_SECRET, value); break;
|
||||
case NAME_Soundblock:
|
||||
Flag(ld->flags, ML_SOUNDBLOCK, value); break;
|
||||
Flag(ld->flags, ML_SECRET, key);
|
||||
break;
|
||||
|
||||
case NAME_Blocksound:
|
||||
Flag(ld->flags, ML_SOUNDBLOCK, key);
|
||||
break;
|
||||
|
||||
case NAME_Dontdraw:
|
||||
Flag(ld->flags, ML_DONTDRAW, value); break;
|
||||
Flag(ld->flags, ML_DONTDRAW, key);
|
||||
break;
|
||||
|
||||
case NAME_Mapped:
|
||||
Flag(ld->flags, ML_MAPPED, value); break;
|
||||
case NAME_Monsteractivate:
|
||||
Flag(ld->flags, ML_MONSTERSCANACTIVATE, value); break;
|
||||
Flag(ld->flags, ML_MAPPED, key);
|
||||
break;
|
||||
|
||||
case NAME_Jumpover:
|
||||
Flag(ld->flags, ML_RAILING, value); break;
|
||||
CHECK_N(St | Zd | Zdt)
|
||||
Flag(ld->flags, ML_RAILING, key);
|
||||
break;
|
||||
|
||||
case NAME_Blockfloating:
|
||||
Flag(ld->flags, ML_BLOCK_FLOATERS, value); break;
|
||||
CHECK_N(St | Zd | Zdt)
|
||||
Flag(ld->flags, ML_BLOCK_FLOATERS, key);
|
||||
break;
|
||||
|
||||
case NAME_Transparent:
|
||||
ld->Alpha = !value.CompareNoCase("true")? FRACUNIT*3/4 : FRACUNIT; break;
|
||||
CHECK_N(St | Zd | Zdt)
|
||||
strifetrans = CheckBool(key);
|
||||
break;
|
||||
|
||||
case NAME_Passuse:
|
||||
passuse = !value.CompareNoCase("true"); break;
|
||||
CHECK_N(Dm | Zd | Zdt)
|
||||
passuse = CheckBool(key);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -298,48 +496,94 @@ struct UDMFParser
|
|||
if (!isTranslated) switch (key)
|
||||
{
|
||||
case NAME_Playercross:
|
||||
Flag(ld->activation, SPAC_Cross, value); break;
|
||||
Flag(ld->activation, SPAC_Cross, key);
|
||||
break;
|
||||
|
||||
case NAME_Playeruse:
|
||||
Flag(ld->activation, SPAC_Use, value); break;
|
||||
Flag(ld->activation, SPAC_Use, key);
|
||||
break;
|
||||
|
||||
case NAME_Monstercross:
|
||||
Flag(ld->activation, SPAC_MCross, value); break;
|
||||
Flag(ld->activation, SPAC_MCross, key);
|
||||
break;
|
||||
|
||||
case NAME_Impact:
|
||||
Flag(ld->activation, SPAC_Impact, value); break;
|
||||
Flag(ld->activation, SPAC_Impact, key);
|
||||
break;
|
||||
|
||||
case NAME_Playerpush:
|
||||
Flag(ld->activation, SPAC_Push, value); break;
|
||||
Flag(ld->activation, SPAC_Push, key);
|
||||
break;
|
||||
|
||||
case NAME_Missilecross:
|
||||
Flag(ld->activation, SPAC_PCross, value); break;
|
||||
Flag(ld->activation, SPAC_PCross, key);
|
||||
break;
|
||||
|
||||
case NAME_Monsteruse:
|
||||
Flag(ld->activation, SPAC_MUse, value); break;
|
||||
Flag(ld->activation, SPAC_MUse, key);
|
||||
break;
|
||||
|
||||
case NAME_Monsterpush:
|
||||
Flag(ld->activation, SPAC_MPush, value); break;
|
||||
Flag(ld->activation, SPAC_MPush, key);
|
||||
break;
|
||||
|
||||
case NAME_Repeatspecial:
|
||||
Flag(ld->flags, ML_REPEAT_SPECIAL, key);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// This switch contains all keys which are ZDoom specific
|
||||
if (isExtended) switch(key)
|
||||
if (namespace_bits & (Zd|Zdt)) switch(key)
|
||||
{
|
||||
case NAME_Anycross:
|
||||
Flag(ld->activation, SPAC_AnyCross, key);
|
||||
break;
|
||||
|
||||
case NAME_Monsteractivate:
|
||||
Flag(ld->flags, ML_MONSTERSCANACTIVATE, key);
|
||||
break;
|
||||
|
||||
case NAME_Blockplayers:
|
||||
Flag(ld->flags, ML_BLOCK_PLAYERS, value); break;
|
||||
Flag(ld->flags, ML_BLOCK_PLAYERS, key);
|
||||
break;
|
||||
|
||||
case NAME_Blockeverything:
|
||||
Flag(ld->flags, ML_BLOCKEVERYTHING, value); break;
|
||||
Flag(ld->flags, ML_BLOCKEVERYTHING, key);
|
||||
break;
|
||||
|
||||
case NAME_Zoneboundary:
|
||||
Flag(ld->flags, ML_ZONEBOUNDARY, value); break;
|
||||
Flag(ld->flags, ML_ZONEBOUNDARY, key);
|
||||
break;
|
||||
|
||||
case NAME_Clipmidtex:
|
||||
Flag(ld->flags, ML_CLIP_MIDTEX, value); break;
|
||||
Flag(ld->flags, ML_CLIP_MIDTEX, key);
|
||||
break;
|
||||
|
||||
case NAME_Wrapmidtex:
|
||||
Flag(ld->flags, ML_WRAP_MIDTEX, value); break;
|
||||
Flag(ld->flags, ML_WRAP_MIDTEX, key);
|
||||
break;
|
||||
|
||||
case NAME_Midtex3d:
|
||||
Flag(ld->flags, ML_3DMIDTEX, value); break;
|
||||
Flag(ld->flags, ML_3DMIDTEX, key);
|
||||
break;
|
||||
|
||||
case NAME_Checkswitchrange:
|
||||
Flag(ld->flags, ML_CHECKSWITCHRANGE, value); break;
|
||||
Flag(ld->flags, ML_CHECKSWITCHRANGE, key);
|
||||
break;
|
||||
|
||||
case NAME_Firstsideonly:
|
||||
Flag(ld->flags, ML_FIRSTSIDEONLY, value); break;
|
||||
Flag(ld->flags, ML_FIRSTSIDEONLY, key);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sc.MustGetToken(';');
|
||||
}
|
||||
|
||||
if (isTranslated)
|
||||
{
|
||||
int saved = ld->flags;
|
||||
|
@ -355,6 +599,10 @@ struct UDMFParser
|
|||
{
|
||||
ld->activation = (ld->activation & ~SPAC_Use) | SPAC_UseThrough;
|
||||
}
|
||||
if (strifetrans && ld->Alpha == FRACUNIT)
|
||||
{
|
||||
ld->Alpha = FRACUNIT * 3/4;
|
||||
}
|
||||
}
|
||||
|
||||
void ParseSidedef(side_t *sd, mapsidedef_t *sdt)
|
||||
|
@ -365,44 +613,41 @@ struct UDMFParser
|
|||
strncpy(sdt->bottomtexture, "-", 8);
|
||||
strncpy(sdt->toptexture, "-", 8);
|
||||
strncpy(sdt->midtexture, "-", 8);
|
||||
sc.MustGetStringName("{");
|
||||
while (!sc.CheckString("}"))
|
||||
|
||||
sc.MustGetToken('{');
|
||||
while (!sc.CheckToken('}'))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FName key = sc.String;
|
||||
sc.MustGetStringName("=");
|
||||
sc.MustGetString();
|
||||
FString value = sc.String;
|
||||
sc.MustGetStringName(";");
|
||||
FName key = ParseKey();
|
||||
switch(key)
|
||||
{
|
||||
case NAME_Offsetx:
|
||||
texofs[0] = strtol(value, NULL, 0) << FRACBITS;
|
||||
texofs[0] = CheckInt(key) << FRACBITS;
|
||||
break;
|
||||
|
||||
case NAME_Offsety:
|
||||
texofs[1] = strtol(value, NULL, 0) << FRACBITS;
|
||||
texofs[1] = CheckInt(key) << FRACBITS;
|
||||
break;
|
||||
|
||||
case NAME_Texturetop:
|
||||
strncpy(sdt->toptexture, value, 8);
|
||||
strncpy(sdt->toptexture, CheckString(key), 8);
|
||||
break;
|
||||
|
||||
case NAME_Texturebottom:
|
||||
strncpy(sdt->bottomtexture, value, 8);
|
||||
strncpy(sdt->bottomtexture, CheckString(key), 8);
|
||||
break;
|
||||
|
||||
case NAME_Texturemiddle:
|
||||
strncpy(sdt->midtexture, value, 8);
|
||||
strncpy(sdt->midtexture, CheckString(key), 8);
|
||||
break;
|
||||
|
||||
case NAME_Sector:
|
||||
sd->sector = (sector_t*)(intptr_t)strtol(value, NULL, 0);
|
||||
sd->sector = (sector_t*)(intptr_t)CheckInt(key);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sc.MustGetToken(';');
|
||||
}
|
||||
// initialization of these is delayed to allow separate offsets and add them with the global ones.
|
||||
sd->AddTextureXOffset(side_t::top, texofs[0]);
|
||||
|
@ -416,7 +661,7 @@ struct UDMFParser
|
|||
void ParseSector(sector_t *sec)
|
||||
{
|
||||
memset(sec, 0, sizeof(*sec));
|
||||
sec->lightlevel = 255;
|
||||
sec->lightlevel = 160;
|
||||
sec->floor_xscale = FRACUNIT; // [RH] floor and ceiling scaling
|
||||
sec->floor_yscale = FRACUNIT;
|
||||
sec->ceiling_xscale = FRACUNIT;
|
||||
|
@ -428,6 +673,7 @@ struct UDMFParser
|
|||
sec->nextsec = -1; //jff 2/26/98 add fields to support locking out
|
||||
sec->prevsec = -1; // stair retriggering until build completes
|
||||
sec->heightsec = NULL; // sector used to get floor and ceiling height
|
||||
if (floordrop) sec->Flags = SECF_FLOORDROP;
|
||||
// killough 3/7/98: end changes
|
||||
|
||||
sec->gravity = 1.f; // [RH] Default sector gravity of 1.0
|
||||
|
@ -437,49 +683,50 @@ struct UDMFParser
|
|||
sec->friction = ORIG_FRICTION;
|
||||
sec->movefactor = ORIG_FRICTION_FACTOR;
|
||||
|
||||
sc.MustGetStringName("{");
|
||||
while (!sc.CheckString("}"))
|
||||
sc.MustGetToken('{');
|
||||
while (!sc.CheckToken('}'))
|
||||
{
|
||||
sc.MustGetString();
|
||||
FName key = sc.String;
|
||||
sc.MustGetStringName("=");
|
||||
sc.MustGetString();
|
||||
FString value = sc.String;
|
||||
sc.MustGetStringName(";");
|
||||
FName key = ParseKey();
|
||||
switch(key)
|
||||
{
|
||||
case NAME_Heightfloor:
|
||||
sec->floortexz = strtol(value, NULL, 0) << FRACBITS;
|
||||
sec->floortexz = CheckInt(key) << FRACBITS;
|
||||
break;
|
||||
|
||||
case NAME_Heightceiling:
|
||||
sec->ceilingtexz = strtol(value, NULL, 0) << FRACBITS;
|
||||
sec->ceilingtexz = CheckInt(key) << FRACBITS;
|
||||
break;
|
||||
|
||||
case NAME_Texturefloor:
|
||||
sec->floorpic = TexMan.GetTexture (value, FTexture::TEX_Flat, FTextureManager::TEXMAN_Overridable);
|
||||
sec->floorpic = TexMan.GetTexture (CheckString(key), FTexture::TEX_Flat, FTextureManager::TEXMAN_Overridable);
|
||||
break;
|
||||
|
||||
case NAME_Textureceiling:
|
||||
sec->ceilingpic = TexMan.GetTexture (value, FTexture::TEX_Flat, FTextureManager::TEXMAN_Overridable);
|
||||
sec->ceilingpic = TexMan.GetTexture (CheckString(key), FTexture::TEX_Flat, FTextureManager::TEXMAN_Overridable);
|
||||
break;
|
||||
|
||||
case NAME_Lightlevel:
|
||||
sec->lightlevel = (BYTE)clamp<int>(strtol(value, NULL, 0), 0, 255);
|
||||
sec->lightlevel = (BYTE)clamp<int>(CheckInt(key), 0, 255);
|
||||
break;
|
||||
|
||||
case NAME_Special:
|
||||
sec->special = (short)strtol(value, NULL, 0);
|
||||
sec->special = (short)CheckInt(key);
|
||||
if (isTranslated) sec->special = P_TranslateSectorSpecial(sec->special);
|
||||
else if (namespc == NAME_Hexen)
|
||||
{
|
||||
if (sec->special < 0 || sec->special > 255 || !HexenSectorSpecialOk[sec->special])
|
||||
sec->special = 0; // NULL all unknown specials
|
||||
}
|
||||
break;
|
||||
|
||||
case NAME_Tag:
|
||||
sec->tag = (short)strtol(value, NULL, 0);
|
||||
case NAME_Id:
|
||||
sec->tag = (short)CheckInt(key);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sc.MustGetToken(';');
|
||||
}
|
||||
|
||||
sec->floorplane.d = -sec->floortexz;
|
||||
|
@ -603,7 +850,6 @@ struct UDMFParser
|
|||
char *buffer = new char[map->Size(ML_TEXTMAP)];
|
||||
|
||||
isTranslated = true;
|
||||
isExtended = false;
|
||||
|
||||
map->Read(ML_TEXTMAP, buffer);
|
||||
sc.OpenMem(Wads.GetLumpFullName(map->lumpnum), buffer, map->Size(ML_TEXTMAP));
|
||||
|
@ -613,34 +859,58 @@ struct UDMFParser
|
|||
sc.MustGetStringName("=");
|
||||
sc.MustGetString();
|
||||
namespc = sc.String;
|
||||
if (namespc == NAME_ZDoom)
|
||||
switch(namespc)
|
||||
{
|
||||
case NAME_ZDoom:
|
||||
namespace_bits = Zd;
|
||||
isTranslated = false;
|
||||
isExtended = true;
|
||||
}
|
||||
else if (namespc == NAME_Hexen)
|
||||
{
|
||||
break;
|
||||
case NAME_ZDoomTranslated:
|
||||
namespace_bits = Zdt;
|
||||
break;
|
||||
case NAME_Hexen:
|
||||
namespace_bits = Hx;
|
||||
isTranslated = false;
|
||||
}
|
||||
else if (namespc == NAME_ZDoomTranslated)
|
||||
{
|
||||
isExtended = true;
|
||||
}
|
||||
else if (namespc == NAME_Doom)
|
||||
{
|
||||
break;
|
||||
case NAME_Doom:
|
||||
namespace_bits = Dm;
|
||||
P_LoadTranslator("xlat/doom_base.txt");
|
||||
}
|
||||
else if (namespc == NAME_Heretic)
|
||||
{
|
||||
level.flags |= LEVEL_DUMMYSWITCHES;
|
||||
floordrop = true;
|
||||
break;
|
||||
case NAME_Heretic:
|
||||
namespace_bits = Ht;
|
||||
P_LoadTranslator("xlat/heretic_base.txt");
|
||||
}
|
||||
else if (namespc == NAME_Strife)
|
||||
{
|
||||
level.flags |= LEVEL_DUMMYSWITCHES;
|
||||
floordrop = true;
|
||||
break;
|
||||
case NAME_Strife:
|
||||
namespace_bits = St;
|
||||
P_LoadTranslator("xlat/strife_base.txt");
|
||||
}
|
||||
else
|
||||
level.flags |= LEVEL_DUMMYSWITCHES|LEVEL_RAILINGHACK;
|
||||
floordrop = true;
|
||||
break;
|
||||
default:
|
||||
Printf("Unknown namespace %s. Using defaults for %s\n", sc.String, GameNames[gameinfo.gametype]);
|
||||
switch (gameinfo.gametype)
|
||||
{
|
||||
Printf("Unknown namespace %s\n", sc.String);
|
||||
case GAME_Doom:
|
||||
namespace_bits = Dm;
|
||||
P_LoadTranslator("xlat/doom_base.txt");
|
||||
break;
|
||||
case GAME_Heretic:
|
||||
namespace_bits = Ht;
|
||||
P_LoadTranslator("xlat/heretic_base.txt");
|
||||
break;
|
||||
case GAME_Strife:
|
||||
namespace_bits = St;
|
||||
P_LoadTranslator("xlat/strife_base.txt");
|
||||
break;
|
||||
case GAME_Hexen:
|
||||
namespace_bits = Hx;
|
||||
isTranslated = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
sc.MustGetStringName(";");
|
||||
}
|
||||
|
@ -693,8 +963,8 @@ struct UDMFParser
|
|||
// Create the real sectors
|
||||
numsectors = ParsedSectors.Size();
|
||||
sectors = new sector_t[numsectors];
|
||||
sectors[0].e = new extsector_t[numsectors];
|
||||
memcpy(sectors, &ParsedSectors[0], numsectors * sizeof(*sectors));
|
||||
sectors[0].e = new extsector_t[numsectors];
|
||||
for(int i = 0; i < numsectors; i++)
|
||||
{
|
||||
sectors[i].e = §ors[0].e[i];
|
||||
|
|
|
@ -2202,7 +2202,7 @@ void P_PlayerThink (player_t *player)
|
|||
}
|
||||
if (!--player->morphTics)
|
||||
{ // Attempt to undo the chicken/pig
|
||||
P_UndoPlayerMorph (player);
|
||||
P_UndoPlayerMorph (player, player);
|
||||
}
|
||||
}
|
||||
// Cycle psprites
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "s_sndseq.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "r_main.h"
|
||||
#include "p_lnspec.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -1172,8 +1173,8 @@ static void InitSegLists ()
|
|||
if (segs[i].linedef != NULL)
|
||||
{
|
||||
SegListHead[segs[i].v1 - vertexes] = i;
|
||||
if ((segs[i].linedef->special == PO_LINE_START ||
|
||||
segs[i].linedef->special == PO_LINE_EXPLICIT))
|
||||
if ((segs[i].linedef->special == Polyobj_StartLine ||
|
||||
segs[i].linedef->special == Polyobj_ExplicitLine))
|
||||
{
|
||||
KnownPolySegs.Push (i);
|
||||
}
|
||||
|
@ -1265,7 +1266,7 @@ static void SpawnPolyobj (int index, int tag, int type)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (segs[i].linedef->special == PO_LINE_START &&
|
||||
if (segs[i].linedef->special == Polyobj_StartLine &&
|
||||
segs[i].linedef->args[0] == tag)
|
||||
{
|
||||
if (polyobjs[index].segs)
|
||||
|
@ -1306,7 +1307,7 @@ static void SpawnPolyobj (int index, int tag, int type)
|
|||
i = KnownPolySegs[ii];
|
||||
|
||||
if (i >= 0 &&
|
||||
segs[i].linedef->special == PO_LINE_EXPLICIT &&
|
||||
segs[i].linedef->special == Polyobj_ExplicitLine &&
|
||||
segs[i].linedef->args[0] == tag)
|
||||
{
|
||||
if (!segs[i].linedef->args[1])
|
||||
|
@ -1327,7 +1328,7 @@ static void SpawnPolyobj (int index, int tag, int type)
|
|||
{
|
||||
i = KnownPolySegs[ii];
|
||||
if (i >= 0 &&
|
||||
segs[i].linedef->special == PO_LINE_EXPLICIT &&
|
||||
segs[i].linedef->special == Polyobj_ExplicitLine &&
|
||||
segs[i].linedef->args[0] == tag && segs[i].linedef->args[1] == j)
|
||||
{
|
||||
segs[i].linedef->special = 0;
|
||||
|
@ -1344,7 +1345,7 @@ static void SpawnPolyobj (int index, int tag, int type)
|
|||
{
|
||||
i = KnownPolySegs[ii];
|
||||
if (i >= 0 &&
|
||||
segs[i].linedef->special == PO_LINE_EXPLICIT &&
|
||||
segs[i].linedef->special == Polyobj_ExplicitLine &&
|
||||
segs[i].linedef->args[0] == tag)
|
||||
{
|
||||
I_Error ("SpawnPolyobj: Missing explicit line %d for poly %d\n",
|
||||
|
|
|
@ -256,6 +256,7 @@ enum
|
|||
{
|
||||
SECF_SILENT = 1, // actors in sector make no noise
|
||||
SECF_NOFALLINGDAMAGE= 2, // No falling damage in this sector
|
||||
SECF_FLOORDROP = 4, // all actors standing on this floor will remain on it when it lowers very fast.
|
||||
};
|
||||
|
||||
struct FDynamicColormap;
|
||||
|
|
|
@ -982,6 +982,32 @@ void STACK_ARGS FScanner::ScriptError (const char *message, ...)
|
|||
AlreadyGot? AlreadyGotLine : Line, composed.GetChars());
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FScanner::ScriptError
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void STACK_ARGS FScanner::ScriptMessage (const char *message, ...)
|
||||
{
|
||||
FString composed;
|
||||
|
||||
if (message == NULL)
|
||||
{
|
||||
composed = "Bad syntax.";
|
||||
}
|
||||
else
|
||||
{
|
||||
va_list arglist;
|
||||
va_start (arglist, message);
|
||||
composed.VFormat (message, arglist);
|
||||
va_end (arglist);
|
||||
}
|
||||
|
||||
Printf ("Script error, \"%s\" line %d:\n%s\n", ScriptName.GetChars(),
|
||||
AlreadyGot? AlreadyGotLine : Line, composed.GetChars());
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FScanner :: CheckOpen
|
||||
|
|
|
@ -58,6 +58,7 @@ public:
|
|||
int MustMatchString(const char **strings);
|
||||
|
||||
void ScriptError(const char *message, ...);
|
||||
void ScriptMessage(const char *message, ...);
|
||||
|
||||
// Members ------------------------------------------------------
|
||||
char *String;
|
||||
|
|
|
@ -147,7 +147,7 @@ int FTextureManager::CheckForTexture (const char *name, int usetype, BITFIELD fl
|
|||
if ((flags & TEXMAN_TryAny) && usetype != FTexture::TEX_Any)
|
||||
{
|
||||
// Never return the index of NULL textures.
|
||||
if (firsttype == FTexture::TEX_Null) return 0;
|
||||
if (firstfound != -1 && firsttype == FTexture::TEX_Null) return 0;
|
||||
return firstfound;
|
||||
}
|
||||
|
||||
|
|
|
@ -756,11 +756,13 @@ static int ParseMorphStyle (FScanner &sc)
|
|||
{
|
||||
static const char * morphstyles[]={
|
||||
"MRF_ADDSTAMINA", "MRF_FULLHEALTH", "MRF_UNDOBYTOMEOFPOWER", "MRF_UNDOBYCHAOSDEVICE",
|
||||
"MRF_FAILNOTELEFRAG", "MRF_FAILNOLAUGH", "MRF_WHENINVULNERABLE", "MRF_LOSEACTUALWEAPON", NULL};
|
||||
"MRF_FAILNOTELEFRAG", "MRF_FAILNOLAUGH", "MRF_WHENINVULNERABLE", "MRF_LOSEACTUALWEAPON",
|
||||
"MRF_NEWTIDBEHAVIOUR", "MRF_UNDOBYDEATH", "MRF_UNDOBYDEATHFORCED", "MRF_UNDOBYDEATHSAVES", NULL};
|
||||
|
||||
static const int morphstyle_values[]={
|
||||
MORPH_ADDSTAMINA, MORPH_FULLHEALTH, MORPH_UNDOBYTOMEOFPOWER, MORPH_UNDOBYCHAOSDEVICE,
|
||||
MORPH_FAILNOTELEFRAG, MORPH_FAILNOLAUGH, MORPH_WHENINVULNERABLE, MORPH_LOSEACTUALWEAPON};
|
||||
MORPH_FAILNOTELEFRAG, MORPH_FAILNOLAUGH, MORPH_WHENINVULNERABLE, MORPH_LOSEACTUALWEAPON,
|
||||
MORPH_NEWTIDBEHAVIOUR, MORPH_UNDOBYDEATH, MORPH_UNDOBYDEATHFORCED, MORPH_UNDOBYDEATHSAVES};
|
||||
|
||||
// May be given flags by number...
|
||||
if (sc.CheckNumber())
|
||||
|
|
|
@ -115,13 +115,13 @@ struct XlatParseContext : public FParseContext
|
|||
{
|
||||
"arg2", "arg3", "arg4", "arg5", "bitmask", "clear",
|
||||
"define", "enum", "flags", "include", "lineid",
|
||||
"nobitmask", "sector", "tag", "maxlinespecial"
|
||||
"maxlinespecial", "nobitmask", "sector", "tag"
|
||||
};
|
||||
static const short types[] =
|
||||
{
|
||||
XLAT_ARG2, XLAT_ARG3, XLAT_ARG4, XLAT_ARG5, XLAT_BITMASK, XLAT_CLEAR,
|
||||
XLAT_DEFINE, XLAT_ENUM, XLAT_FLAGS, XLAT_INCLUDE, XLAT_TAG,
|
||||
XLAT_NOBITMASK, XLAT_SECTOR, XLAT_TAG, XLAT_MAXLINESPECIAL
|
||||
XLAT_MAXLINESPECIAL, XLAT_NOBITMASK, XLAT_SECTOR, XLAT_TAG
|
||||
};
|
||||
|
||||
int min = 0, max = countof(tokens) - 1;
|
||||
|
|
Loading…
Reference in a new issue