- More things from Gez's experimental build:

* info CCMD to print extended actor information (not fully implemented yet)
  * summonmbf CCMD.
  * Beta BFG code pointer (but not the related missiles yet.)
  * PowerInvisibility enhancements.
  * ScoreItem with one significant change: Added a score variable that can be
    checked through ACS and DECORATE. The engine itself will do nothing with it.
  * Nailgun option for A_Explode.
  * A_PrintBold and A_Log.
  * A_SetSpecial.


SVN r1819 (trunk)
This commit is contained in:
Christoph Oelckers 2009-09-14 19:44:14 +00:00
parent 914d993aa1
commit 238d4c3fac
34 changed files with 564 additions and 110 deletions

View file

@ -1,5 +1,14 @@
September 14, 2009 (Changes by Graf Zahl)
- Added a few things from Gez's experimental build:
* info CCMD to print extended actor information (not fully implemented yet)
* summonmbf CCMD.
* Beta BFG code pointer (but not the related missiles yet.)
* PowerInvisibility enhancements.
* ScoreItem with one significant change: Added a score variable that can be
checked through ACS and DECORATE. The engine itself will do nothing with it.
* Nailgun option for A_Explode.
* A_PrintBold and A_Log.
* A_SetSpecial.
* Beta Lost Soul (added DoomEdNum 9037 to it)
* A_Mushroom extensions
* Vavoom compatible MAPINFO keynames.

View file

@ -7,13 +7,13 @@ DEFINE_SPECIAL(Polyobj_ExplicitLine, 5, -1, -1, 5)
DEFINE_SPECIAL(Polyobj_MoveTimes8, 6, 4, 4, 4)
DEFINE_SPECIAL(Polyobj_DoorSwing, 7, 4, 4, 4)
DEFINE_SPECIAL(Polyobj_DoorSlide, 8, 5, 5, 5)
DEFINE_SPECIAL(Line_Horizon, 9, -1, 0, 0) // [RH] draw one-sided wall at horizon
DEFINE_SPECIAL(Line_Horizon, 9, -1, 0, 0) // [RH] draw one-sided wall at horizon
DEFINE_SPECIAL(Door_Close, 10, 2, 3, 3)
DEFINE_SPECIAL(Door_Open, 11, 2, 3, 3)
DEFINE_SPECIAL(Door_Raise, 12, 3, 4, 4)
DEFINE_SPECIAL(Door_LockedRaise, 13, 4, 5, 5)
DEFINE_SPECIAL(Door_Animated, 14, 3, 3, 3)
DEFINE_SPECIAL(Autosave, 15, 0, 0, 0) // [RH] Save the game *now*
DEFINE_SPECIAL(Autosave, 15, 0, 0, 0) // [RH] Save the game *now*
DEFINE_SPECIAL(Transfer_WallLight, 16, -1, -1, 2)
DEFINE_SPECIAL(Thing_Raise, 17, 1, 1, 1)
DEFINE_SPECIAL(StartConversation, 18, 1, 2, 2)
@ -31,13 +31,13 @@ DEFINE_SPECIAL(Pillar_Build, 29, 3, 3, 3)
DEFINE_SPECIAL(Pillar_Open, 30, 4, 4, 4)
DEFINE_SPECIAL(Stairs_BuildDownSync, 31, 4, 4, 4)
DEFINE_SPECIAL(Stairs_BuildUpSync, 32, 4, 4, 4)
DEFINE_SPECIAL(ForceField, 33, 0, 0, 0) // [RH] Strife's forcefield special (148)
DEFINE_SPECIAL(ClearForceField, 34, 1, 1, 1) // [RH] Remove Strife's forcefield from tagged sectors
DEFINE_SPECIAL(ForceField, 33, 0, 0, 0) // [RH] Strife's forcefield special (148)
DEFINE_SPECIAL(ClearForceField, 34, 1, 1, 1) // [RH] Remove Strife's forcefield from tagged sectors
DEFINE_SPECIAL(Floor_RaiseByValueTimes8, 35, 3, 3, 3)
DEFINE_SPECIAL(Floor_LowerByValueTimes8, 36, 3, 3, 3)
DEFINE_SPECIAL(Floor_MoveToValue, 37, 3, 4, 4)
DEFINE_SPECIAL(Ceiling_Waggle, 38, 5, 5, 4) // [RH] Complement of Floor_Waggle
DEFINE_SPECIAL(Teleport_ZombieChanger, 39, 2, 2, 2) // [RH] Needed for Strife
DEFINE_SPECIAL(Ceiling_Waggle, 38, 5, 5, 4) // [RH] Complement of Floor_Waggle
DEFINE_SPECIAL(Teleport_ZombieChanger, 39, 2, 2, 2) // [RH] Needed for Strife
DEFINE_SPECIAL(Ceiling_LowerByValue, 40, 3, 3, 3)
DEFINE_SPECIAL(Ceiling_RaiseByValue, 41, 3, 3, 3)
DEFINE_SPECIAL(Ceiling_CrushAndRaise, 42, 3, 4, 4)
@ -105,9 +105,8 @@ DEFINE_SPECIAL(Light_Strobe, 116, 5, 5, 5)
DEFINE_SPECIAL(Light_Stop, 117, 1, 1, 1)
DEFINE_SPECIAL(Thing_Damage, 119, 2, 3, 3)
DEFINE_SPECIAL(Radius_Quake, 120, 5, 5, 5) // Earthquake
DEFINE_SPECIAL(Radius_Quake, 120, 5, 5, 5) // Earthquake
DEFINE_SPECIAL(Line_SetIdentification, 121, -1, -1, 5)
#if 0 // Skull Tag specials that might be added later
Thing_SetGravity, 122, -1, -1)
Thing_ReverseGravity, 123, -1, -1)
@ -140,7 +139,7 @@ DEFINE_SPECIAL(Teleport_NoStop, 154, 2, 3, 3)
DEFINE_SPECIAL(FS_Execute, 158, 1, 4, 4)
DEFINE_SPECIAL(Sector_SetPlaneReflection, 159, 3, 3, 3)
DEFINE_SPECIAL(Sector_Set3DFloor, 160, -1, -1, 5)
DEFINE_SPECIAL(Sector_SetContents, 161, -1, -1, 5) // It probably doesn't use 5 args. Oh well.
DEFINE_SPECIAL(Sector_SetContents, 161, -1, -1, 3)
// [RH] Begin new specials for ZDoom
DEFINE_SPECIAL(Generic_Crusher2, 169, 5, 5, 5)

View file

@ -262,6 +262,8 @@ enum
MF4_FRIGHTENED = 0x40000000, // Monster runs away from player
/* = 0x80000000, */
// --- mobj.flags5 ---
MF5_FASTER = 0x00000001, // moves faster when DF_FAST_MONSTERS or nightmare is on.
MF5_FASTMELEE = 0x00000002, // has a faster melee attack when DF_FAST_MONSTERS or nightmare is on.
MF5_NODROPOFF = 0x00000004, // cannot drop off under any circumstances.
@ -296,6 +298,8 @@ enum
MF5_PAINLESS = 0x40000000, // Actor always inflicts painless damage.
MF5_MOVEWITHSECTOR = 0x80000000, // P_ChangeSector() will still process this actor if it has MF_NOBLOCKMAP
// --- mobj.flags6 ---
MF6_NOBOSSRIP = 0x00000001, // For rippermissiles: Don't rip through bosses.
MF6_THRUSPECIES = 0x00000002, // Actors passes through other of the same species.
MF6_MTHRUSPECIES = 0x00000004, // Missile passes through actors of its shooter's species.
@ -369,7 +373,7 @@ enum replace_t
ALLOW_REPLACE = 1
};
enum EBounceType
enum EBounceFlags
{
BOUNCE_Walls = 1<<0, // bounces off of walls
BOUNCE_Floors = 1<<1, // bounces off of floors
@ -377,7 +381,7 @@ enum EBounceType
BOUNCE_Actors = 1<<3, // bounces off of some actors
BOUNCE_AllActors = 1<<4, // bounces off of all actors (requires BOUNCE_Actors to be set, too)
BOUNCE_AutoOff = 1<<5, // when bouncing off a floor, if the new Z velocity is below 3.0, disable further bouncing
BOUNCE_HereticType = 1<<6, // only works with floors and ceilings; you probably don't want to use it
BOUNCE_HereticType = 1<<6, // goes into Death state when bouncing on floors or ceilings
BOUNCE_UseSeeSound = 1<<7, // compatibility fallback. This will only be set by
// the compatibility handlers for the old bounce flags.
@ -385,6 +389,9 @@ enum EBounceType
BOUNCE_Quiet = 1<<9, // Strife's grenades don't make a bouncing sound
BOUNCE_ExplodeOnWater = 1<<10, // explodes when hitting a water surface
BOUNCE_CanBounceWater = 1<<11, // can bounce on water
// MBF bouncing is a bit different from other modes as Killough coded many special behavioral cases
// for them that are not present in ZDoom, so it is necessary to identify it properly.
BOUNCE_MBF = 1<<12, // This in itself is not a valid mode, but replaces MBF's MF_BOUNCE flag.
BOUNCE_TypeMask = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors | BOUNCE_AutoOff | BOUNCE_HereticType,
@ -398,6 +405,9 @@ enum EBounceType
BOUNCE_Heretic = BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_HereticType,
BOUNCE_Doom = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors | BOUNCE_AutoOff,
BOUNCE_Hexen = BOUNCE_Walls | BOUNCE_Floors | BOUNCE_Ceilings | BOUNCE_Actors,
BOUNCE_Grenade = BOUNCE_MBF | BOUNCE_Doom, // Bounces on walls and flats like ZDoom bounce.
BOUNCE_Classic = BOUNCE_MBF | BOUNCE_Floors | BOUNCE_Ceilings, // Bounces on flats only, but
// does not die when bouncing.
// combined types
BOUNCE_DoomCompat = BOUNCE_Doom | BOUNCE_UseSeeSound,
@ -411,6 +421,20 @@ enum EBounceType
// being "Doom" or "Hexen" and BOUNCE_AllActors was the separate
// MF5_BOUNCEONACTORS, you must set BOUNCE_Actors for BOUNCE_AllActors to have
// an effect.
};
// Used to affect the logic for MF5_USESPECIAL and MF6_BUMPSPECIAL
// "thing" refers to what has the flag and the special, "trigger" refers to what used or bumped it
enum EThingSpecialActivationType
{
THINGSPEC_Default = 0, // Normal behavior: a player must be the trigger, and is the activator
THINGSPEC_ThingActs = 1, // The thing itself is the activator of the special
THINGSPEC_ThingTargets = 2, // The thing changes its target to the trigger
THINGSPEC_TriggerTargets = 4, // The trigger changes its target to the thing
THINGSPEC_MonsterTrigger = 8, // The thing can be triggered by a monster
THINGSPEC_MissileTrigger = 16, // The thing can be triggered by a projectile
};
// [RH] Like msecnode_t, but for the blockmap
@ -680,6 +704,10 @@ public:
bool CanSeek(AActor *target) const;
fixed_t GetGravity() const;
bool IsSentient() const;
// info for drawing
// NOTE: The first member variable *must* be x.
fixed_t x,y,z;
@ -726,7 +754,7 @@ public:
SWORD movecount; // when 0, select a new dir
TObjPtr<AActor> target; // thing being chased/attacked (or NULL)
// also the originator for missiles
TObjPtr<AActor> lastenemy; // Last known enemy -- killogh 2/15/98
TObjPtr<AActor> lastenemy; // Last known enemy -- killough 2/15/98
TObjPtr<AActor> LastHeard; // [RH] Last actor this one heard
SDWORD reactiontime; // if non 0, don't attack yet; used by
// player to freeze a bit after teleporting
@ -738,7 +766,7 @@ public:
WORD SpawnAngle;
int skillrespawncount;
int TIDtoHate; // TID of things to hate (0 if none)
FNameNoInit Species;
FNameNoInit Species; // For monster families
TObjPtr<AActor> tracer; // Thing being chased/attacked for tracers
TObjPtr<AActor> master; // Thing which spawned this one (prevents mutual attacks)
fixed_t floorclip; // value to use for floor clipping
@ -766,6 +794,8 @@ public:
int FastChaseStrafeCount;
fixed_t pushfactor;
int lastpush;
int activationtype; // How the thing behaves when activated with USESPECIAL or BUMPSPECIAL
int Score; // manipulated by score items, ACS or DECORATE. The engine doesn't use this itself for anything.
AActor *BlockingMobj; // Actor that blocked the last move
line_t *BlockingLine; // Line that blocked the last move
@ -941,6 +971,8 @@ inline T *Spawn (fixed_t x, fixed_t y, fixed_t z, replace_t allowreplacement)
return static_cast<T *>(AActor::StaticSpawn (RUNTIME_CLASS(T), x, y, z, allowreplacement));
}
void PrintMiscActorInfo(AActor * query);
#define S_FREETARGMOBJ 1
#endif // __P_MOBJ_H__

View file

@ -778,10 +778,31 @@ CCMD(linetarget)
linetarget->GetClass()->TypeName.GetChars(),
linetarget->health,
linetarget->SpawnHealth());
PrintMiscActorInfo(linetarget);
}
else Printf("No target found\n");
}
// As linetarget, but also give info about non-shootable actors
CCMD(info)
{
AActor *linetarget;
if (CheckCheatmode () || players[consoleplayer].mo == NULL) return;
P_AimLineAttack(players[consoleplayer].mo,players[consoleplayer].mo->angle,MISSILERANGE, &linetarget, 0,
false, false, true);
if (linetarget)
{
Printf("Target=%s, Health=%d, Spawnhealth=%d\n",
linetarget->GetClass()->TypeName.GetChars(),
linetarget->health,
linetarget->SpawnHealth());
PrintMiscActorInfo(linetarget);
}
else Printf("No target found. Info cannot find actors that have\
the NOBLOCKMAP flag or have height/radius of 0.\n");
}
//-----------------------------------------------------------------------------
//
//

View file

@ -2094,6 +2094,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
case DEM_SUMMON:
case DEM_SUMMONFRIEND:
case DEM_SUMMONFOE:
case DEM_SUMMONMBF:
case DEM_SUMMON2:
case DEM_SUMMONFRIEND2:
case DEM_SUMMONFOE2:
@ -2132,7 +2133,7 @@ void Net_DoCommand (int type, BYTE **stream, int player)
source->z + 8 * FRACUNIT, ALLOW_REPLACE);
if (spawned != NULL)
{
if (type == DEM_SUMMONFRIEND || type == DEM_SUMMONFRIEND2)
if (type == DEM_SUMMONFRIEND || type == DEM_SUMMONFRIEND2 || type == DEM_SUMMONMBF)
{
if (spawned->CountsAsKill())
{
@ -2142,6 +2143,8 @@ void Net_DoCommand (int type, BYTE **stream, int player)
spawned->flags |= MF_FRIENDLY;
spawned->LastHeard = players[player].mo;
spawned->health = spawned->SpawnHealth();
if (type == DEM_SUMMONMBF)
spawned->flags3 |= MF3_NOBLOCKMONST;
}
else if (type == DEM_SUMMONFOE || type == DEM_SUMMONFOE2)
{
@ -2440,6 +2443,7 @@ void Net_SkipCommand (int type, BYTE **stream)
case DEM_SUMMON:
case DEM_SUMMONFRIEND:
case DEM_SUMMONFOE:
case DEM_SUMMONMBF:
case DEM_SPRAY:
case DEM_MORPHEX:
case DEM_KILLCLASSCHEAT:

View file

@ -839,5 +839,6 @@ CCMD (playerinfo)
Printf ("PlayerClass: %s (%d)\n",
ui->PlayerClass == -1 ? "Random" : PlayerClasses[ui->PlayerClass].Type->Meta.GetMetaString (APMETA_DisplayName),
ui->PlayerClass);
PrintMiscActorInfo(players[i].mo);
}
}

View file

@ -154,6 +154,7 @@ enum EDemoCommand
DEM_ADDSLOTDEFAULT, // 55
DEM_ADDSLOT, // 56
DEM_SETSLOT, // 57
DEM_SUMMONMBF,
};
// The following are implemented by cht_DoCheat in m_cheat.cpp

View file

@ -21,6 +21,7 @@ static FRandom pr_fireshotgun2 ("FireSG2");
static FRandom pr_fireplasma ("FirePlasma");
static FRandom pr_firerail ("FireRail");
static FRandom pr_bfgspray ("BFGSpray");
static FRandom pr_oldbfg ("OldBFG");
//
// A_Punch
@ -553,3 +554,48 @@ DEFINE_ACTION_FUNCTION(AActor, A_BFGsound)
S_Sound (self, CHAN_WEAPON, "weapons/bfgf", 1, ATTN_NORM);
}
//
// A_FireOldBFG
//
// This function emulates Doom's Pre-Beta BFG
// By Lee Killough 6/6/98, 7/11/98, 7/19/98, 8/20/98
//
// This code may not be used in other mods without appropriate credit given.
// Code leeches will be telefragged.
DEFINE_ACTION_FUNCTION(AActor, A_FireOldBFG)
{
const PClass * plasma[] = {PClass::FindClass("PlasmaBall1"), PClass::FindClass("PlasmaBall2")};
AActor * mo = NULL;
player_t *player;
if (NULL == (player = self->player))
{
return;
}
AWeapon *weapon = self->player->ReadyWeapon;
if (weapon != NULL)
{
if (!weapon->DepleteAmmo (weapon->bAltFire))
return;
}
self->player->extralight = 2;
// Save values temporarily
angle_t SavedPlayerAngle = self->angle;
fixed_t SavedPlayerPitch = self->pitch;
bool doesautoaim = !(self->player->ReadyWeapon->WeaponFlags & WIF_NOAUTOAIM);
self->player->ReadyWeapon->WeaponFlags |= WIF_NOAUTOAIM; // No autoaiming that gun
for (int i = 0; i < 2; i++) // Spawn two plasma balls in sequence
{
self->angle += ((pr_oldbfg()&127) - 64) * (ANG90/768);
self->pitch += ((pr_oldbfg()&127) - 64) * (ANG90/640);
mo = P_SpawnPlayerMissile (self, plasma[i]);
// Restore saved values
self->angle = SavedPlayerAngle;
self->pitch = SavedPlayerPitch;
}
if (doesautoaim) self->player->ReadyWeapon->WeaponFlags &= ~WIF_NOAUTOAIM; // Restore autoaim setting
}

View file

@ -553,7 +553,7 @@ void APowerStrength::Tick ()
PalEntry APowerStrength::GetBlend ()
{
// slowly fade the berzerk out
// slowly fade the berserk out
int cnt = 12 - (EffectTics >> 6);
if (cnt > 0)
@ -570,35 +570,10 @@ PalEntry APowerStrength::GetBlend ()
IMPLEMENT_CLASS (APowerInvisibility)
IMPLEMENT_CLASS (APowerShadow)
//===========================================================================
//
// APowerInvisibility :: CommonInit
//
// stuff that's done for all subclasses
//
//===========================================================================
void APowerInvisibility::CommonInit()
{
if (Owner != NULL)
{
Owner->flags |= MF_SHADOW;
fixed_t ts = MIN(Strength * (special1 + 1), FRACUNIT);
Owner->alpha = clamp<fixed_t>((OPAQUE - ts), 0, OPAQUE);
Owner->RenderStyle = (Mode == NAME_Fuzzy ? STYLE_OptFuzzy : STYLE_Translucent);
// CommonInit() is called every tic by DoEffect, so the flag trick must happen only once!
if (special2 == 0)
{
// transfer seeker missile blocking (but only if the owner does not already have this flag
if (!(Owner->flags5 & MF5_CANTSEEK) && (flags5 & MF5_CANTSEEK)) Owner->flags5 |= MF5_CANTSEEK;
else flags5 &= ~MF5_CANTSEEK;
// transfer ghost flag likewise
if (!(Owner->flags3 & MF3_GHOST) && (flags3 & MF3_GHOST)) Owner->flags3 |= MF3_GHOST;
else flags3 &= ~MF3_GHOST;
special2 = 1;
}
}
}
// Invisibility flag combos
#define INVISIBILITY_FLAGS1 (MF_SHADOW | MF_STEALTH)
#define INVISIBILITY_FLAGS3 (MF3_GHOST)
#define INVISIBILITY_FLAGS5 (MF5_CANTSEEK)
//===========================================================================
//
@ -608,7 +583,39 @@ void APowerInvisibility::CommonInit()
void APowerInvisibility::InitEffect ()
{
CommonInit();
// This used to call CommonInit(), which used to contain all the code that's repeated every
// tic, plus the following code that needs to happen once and only once.
// The CommonInit() code has been moved to DoEffect(), so this now ends with a call to DoEffect(),
// and DoEffect() no longer needs to call InitEffect(). CommonInit() has been removed for being redundant.
if (Owner != NULL)
{
flags &= ~(Owner->flags & INVISIBILITY_FLAGS1);
Owner->flags |= flags & INVISIBILITY_FLAGS1;
flags3 &= ~(Owner->flags3 & INVISIBILITY_FLAGS3);
Owner->flags3 |= flags3 & INVISIBILITY_FLAGS3;
flags5 &= ~(Owner->flags5 & INVISIBILITY_FLAGS5);
Owner->flags5 |= flags5 & INVISIBILITY_FLAGS5;
// Finds out what's the normal alpha and render style for the owner.
// First assume it's what it currently is.
//OwnersNormalStyle = Owner->RenderStyle;
//OwnersNormalAlpha = Owner->alpha;
// Then look if there aren't active invis powerups and look what they're saying.
/*AInventory *item = Owner->Inventory;
while (item != NULL)
{
if (item->IsKindOf(RUNTIME_CLASS(APowerInvisibility)) && item != this)
{
OwnersNormalStyle = static_cast<APowerInvisibility*>(item)->OwnersNormalStyle;
OwnersNormalAlpha = static_cast<APowerInvisibility*>(item)->OwnersNormalAlpha;
item = NULL; // No need to look further
}
else item = item->Inventory;
}
Printf("Owner's normal style is found to be %i, normal alpha is found to be %i.\n",
OwnersNormalStyle, OwnersNormalAlpha>>FRACBITS);*/
DoEffect();
}
}
//===========================================================================
@ -621,7 +628,31 @@ void APowerInvisibility::DoEffect ()
Super::DoEffect();
// Due to potential interference with other PowerInvisibility items
// the effect has to be refreshed each tic.
InitEffect();
fixed_t ts = Strength * (special1 + 1); if (ts > FRACUNIT) ts = FRACUNIT;
Owner->alpha = clamp<fixed_t>((/*OwnersNormalAlpha*/OPAQUE - ts), 0, OPAQUE);
switch (Mode)
{
case (NAME_Fuzzy):
Owner->RenderStyle = STYLE_OptFuzzy;
break;
case (NAME_Opaque):
Owner->RenderStyle = STYLE_Normal;
break;
case (NAME_Additive):
Owner->RenderStyle = STYLE_Add;
break;
case (NAME_Stencil):
Owner->RenderStyle = STYLE_Stencil;
break;
case (NAME_None):
case (NAME_Translucent):
Owner->RenderStyle = STYLE_Translucent;
break;
default: // Something's wrong
Owner->RenderStyle = STYLE_Normal;
Owner->alpha = OPAQUE;
break;
}
}
//===========================================================================
@ -634,11 +665,12 @@ void APowerInvisibility::EndEffect ()
{
if (Owner != NULL)
{
if (flags5 & MF5_CANTSEEK) Owner->flags5 &= ~MF5_CANTSEEK;
if (flags3 & MF3_GHOST) Owner->flags3 &= ~MF3_GHOST;
Owner->flags &= ~MF_SHADOW;
Owner->RenderStyle = STYLE_Normal;
Owner->alpha = OPAQUE;
Owner->flags &= ~(flags & INVISIBILITY_FLAGS1);
Owner->flags3 &= ~(flags3 & INVISIBILITY_FLAGS3);
Owner->flags5 &= ~(flags5 & INVISIBILITY_FLAGS5);
Owner->RenderStyle = STYLE_Normal;//OwnersNormalStyle;
Owner->alpha = OPAQUE;//OwnersNormalAlpha;
// Check whether there are other invisibility items and refresh their effect.
// If this isn't done there will be one incorrectly drawn frame when this
@ -648,7 +680,7 @@ void APowerInvisibility::EndEffect ()
{
if (item->IsKindOf(RUNTIME_CLASS(APowerInvisibility)) && item != this)
{
static_cast<APowerInvisibility*>(item)->InitEffect();
static_cast<APowerInvisibility*>(item)->DoEffect();
}
item = item->Inventory;
}
@ -667,16 +699,36 @@ int APowerInvisibility::AlterWeaponSprite (vissprite_t *vis)
// Blink if the powerup is wearing off
if (changed == 0 && EffectTics < 4*32 && !(EffectTics & 8))
{
vis->RenderStyle = STYLE_Normal;
vis->alpha = OPAQUE;
vis->RenderStyle = STYLE_Normal;//OwnersNormalStyle;
vis->alpha = OPAQUE;//OwnersNormalAlpha;
return 1;
}
else if (changed == 1)
{
// something else set the weapon sprite back to opaque but this item is still active.
fixed_t ts = MIN(Strength * (special1 + 1), FRACUNIT);
vis->alpha = clamp<fixed_t>((OPAQUE - ts), 0, OPAQUE);
vis->RenderStyle = (Mode == NAME_Fuzzy ? STYLE_OptFuzzy : STYLE_Translucent);
fixed_t ts = Strength * (special1 + 1); if (ts > FRACUNIT) ts = FRACUNIT;
vis->alpha = clamp<fixed_t>((/*OwnersNormalAlpha*/OPAQUE - ts), 0, OPAQUE);
switch (Mode)
{
case (NAME_Fuzzy):
vis->RenderStyle = STYLE_OptFuzzy;
break;
case (NAME_Opaque):
vis->RenderStyle = STYLE_Normal;
break;
case (NAME_Additive):
vis->RenderStyle = STYLE_Add;
break;
case (NAME_Stencil):
vis->RenderStyle = STYLE_Stencil;
break;
case (NAME_None):
case (NAME_Cumulative):
case (NAME_Translucent):
default:
vis->RenderStyle = STYLE_Translucent;
break;
}
}
// Handling of Strife-like cumulative invisibility powerups, the weapon itself shouldn't become invisible
if ((vis->alpha < TRANSLUC25 && special1 > 0) || (vis->alpha == 0))

View file

@ -81,11 +81,12 @@ class APowerInvisibility : public APowerup
DECLARE_CLASS (APowerInvisibility, APowerup)
protected:
bool HandlePickup (AInventory *item);
void CommonInit ();
void InitEffect ();
void DoEffect ();
void EndEffect ();
int AlterWeaponSprite (vissprite_t *vis);
// FRenderStyle OwnersNormalStyle;
// fixed_t OwnersNormalAlpha;
};
// Needed only for m_cheat.cpp now

View file

@ -1728,3 +1728,30 @@ bool AMapRevealer::TryPickup (AActor *&toucher)
return true;
}
//===========================================================================
//
// AScoreItem
//
//===========================================================================
IMPLEMENT_CLASS(AScoreItem)
//===========================================================================
//
// AScoreItem :: TryPickup
//
// This function does nothing much. Theoretically, the player could have a
// score property which would be incremented by the score items' own score
// property (probably using the Amount property for that), but that is not
// needed for the moment.
//
//===========================================================================
bool AScoreItem::TryPickup (AActor *&toucher)
{
toucher->Score += Amount;
GoAwayAndDie();
return true;
}

View file

@ -475,4 +475,16 @@ public:
bool bDepleted;
};
// A score item is picked up without being added to the inventory.
// Contrarily to FakeInventory, it does nothing.
class AScoreItem : public AInventory
{
DECLARE_CLASS (AScoreItem, AInventory)
public:
bool TryPickup(AActor *&toucher);
};
#endif //__A_PICKUPS_H__

View file

@ -211,7 +211,9 @@ FActorInfo *FActorInfo::GetReplacement (bool lookskill)
FActorInfo *FActorInfo::GetReplacee (bool lookskill)
{
FName skillrepname = AllSkills[gameskill].GetReplacedBy(this->Class->TypeName); if (skillrepname != NAME_None && PClass::FindClass(skillrepname) == NULL) {
FName skillrepname = AllSkills[gameskill].GetReplacedBy(this->Class->TypeName);
if (skillrepname != NAME_None && PClass::FindClass(skillrepname) == NULL)
{
Printf("Warning: incorrect actor name in definition of skill %s: \
inexistent class %s is replaced by class %s\n\
Skill replacement will be ignored for this actor.\n",
@ -229,7 +231,12 @@ FActorInfo *FActorInfo::GetReplacee (bool lookskill)
// potential infinite recursion.
FActorInfo *savedrep = Replacee;
Replacee = NULL;
FActorInfo *rep = savedrep; if (lookskill && (skillrepname != NAME_None) && (PClass::FindClass(skillrepname) != NULL)) { rep = PClass::FindClass(skillrepname)->ActorInfo; } rep = rep->GetReplacee (false); Replacee = savedrep;
FActorInfo *rep = savedrep;
if (lookskill && (skillrepname != NAME_None) && (PClass::FindClass(skillrepname) != NULL))
{
rep = PClass::FindClass(skillrepname)->ActorInfo;
}
rep = rep->GetReplacee (false); Replacee = savedrep;
return rep;
}
@ -445,6 +452,11 @@ CCMD (summonfriend)
SummonActor (DEM_SUMMONFRIEND, DEM_SUMMONFRIEND2, argv);
}
CCMD (summonmbf)
{
SummonActor (DEM_SUMMONMBF, DEM_SUMMONFRIEND2, argv);
}
CCMD (summonfoe)
{
SummonActor (DEM_SUMMONFOE, DEM_SUMMONFOE2, argv);

View file

@ -25,8 +25,11 @@ xx(Ghost)
xx(Reflective)
// Invisibility types
xx(Additive)
xx(Cumulative)
xx(Fuzzy)
xx(Opaque)
xx(Stencil)
// Healingradius types
xx(Mana)

View file

@ -2426,6 +2426,8 @@ enum
APROP_Dropped = 18,
APROP_Notarget = 19,
APROP_Species = 20,
// APROP_Nametag
APROP_Score = 22,
};
// These are needed for ACS's APROP_RenderStyle
@ -2578,6 +2580,10 @@ void DLevelScript::DoSetActorProperty (AActor *actor, int property, int value)
case APROP_Species:
actor->Species = FBehavior::StaticLookupString(value);
break;
case APROP_Score:
actor->Score = value;
break;
}
}
@ -2642,6 +2648,7 @@ int DLevelScript::GetActorProperty (int tid, int property)
{
return 0;
}
case APROP_Score: return actor->Score;
default: return 0;
}
}

View file

@ -376,15 +376,19 @@ bool P_Move (AActor *actor)
fixed_t tryx, tryy, deltax, deltay, origx, origy;
bool try_ok;
int speed;
int speed = actor->Speed;
int movefactor = ORIG_FRICTION_FACTOR;
int friction = ORIG_FRICTION;
if (actor->flags2 & MF2_BLASTED)
{
return true;
}
if (actor->movedir == DI_NODIR)
{
return false;
}
// [RH] Instead of yanking non-floating monsters to the ground,
// let gravity drop them down, unless they're moving down a step.
@ -490,6 +494,7 @@ bool P_Move (AActor *actor)
else
actor->z -= actor->FloatSpeed;
// [RH] Check to make sure there's nothing in the way of the float
if (P_TestMobjZ (actor))
{
@ -500,7 +505,9 @@ bool P_Move (AActor *actor)
}
if (!spechit.Size ())
{
return false;
}
// open any specials
actor->movedir = DI_NODIR;
@ -684,7 +691,7 @@ void P_DoNewChaseDir (AActor *actor, fixed_t deltax, fixed_t deltay)
return;
}
actor->movedir = DI_NODIR; // can not move
actor->movedir = DI_NODIR; // cannot move
}
@ -2315,7 +2322,7 @@ void A_Chase(AActor *self)
// A_FaceTarget
//
//=============================================================================
void A_FaceTarget(AActor *self)
void A_FaceTarget (AActor *self)
{
if (!self->target)
return;

View file

@ -1017,13 +1017,12 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
damage = target->TakeSpecialDamage (inflictor, source, damage, mod);
}
if (damage == -1)
{
return;
}
// Push the target unless the source's weapon's kickback is 0.
// (i.e. Guantlets/Chainsaw)
// (i.e. Gauntlets/Chainsaw)
if (inflictor && inflictor != target // [RH] Not if hurting own self
&& !(target->flags & MF_NOCLIP)
&& !(inflictor->flags2 & MF2_NODMGTHRUST)
@ -1047,13 +1046,13 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage
// Calculate this as float to avoid overflows so that the
// clamping that had to be done here can be removed.
double fltthrust;
double fltthrust;
fltthrust = mod == NAME_MDK ? 10 : 32;
if (target->Mass > 0)
{
fltthrust = clamp((damage * 0.125 * kickback) / target->Mass, 0., fltthrust);
}
fltthrust = mod == NAME_MDK ? 10 : 32;
if (target->Mass > 0)
{
fltthrust = clamp((damage * 0.125 * kickback) / target->Mass, 0., fltthrust);
}
thrust = FLOAT2FIXED(fltthrust);

View file

@ -3250,3 +3250,13 @@ int P_FindLineSpecial (const char *string, int *min_args, int *max_args)
}
return 0;
}
const char *GetSpecialName(int num)
{
for(int i = 0; i < countof(LineSpecialNames); i++)
{
if (LineSpecialNames[i].number == num)
return LineSpecialNames[i].name;
}
return "(unknown)";
}

View file

@ -196,5 +196,6 @@ typedef int (*lnSpecFunc)(struct line_t *line,
extern lnSpecFunc LineSpecials[256];
int P_FindLineSpecial (const char *string, int *min_args=NULL, int *max_args=NULL);
const char *GetSpecialName(int num);
#endif //__P_LNSPEC_H__

View file

@ -392,7 +392,7 @@ void P_FindFloorCeiling (AActor *actor, bool onlymidtex = false);
bool P_ChangeSector (sector_t* sector, int crunch, int amt, int floorOrCeil, bool isreset);
fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget = NULL, fixed_t vrange=0, bool forcenosmart=false, bool check3d = false);
fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget = NULL, fixed_t vrange=0, bool forcenosmart=false, bool check3d = false, bool checknonshootable = false);
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, const PClass *pufftype, bool ismelee = false);
AActor *P_LineAttack (AActor *t1, angle_t angle, fixed_t distance, int pitch, int damage, FName damageType, FName pufftype, bool ismelee = false);
void P_TraceBleed (int damage, fixed_t x, fixed_t y, fixed_t z, AActor *target, angle_t angle, int pitch);

View file

@ -1314,7 +1314,8 @@ bool P_CheckPosition (AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm)
while ((ld = it.Next()))
{
if (!PIT_CheckLine(ld, box, tm)) return false;
if (!PIT_CheckLine(ld, box, tm))
return false;
}
if (tm.ceilingz - tm.floorz < thing->height)
@ -2667,7 +2668,7 @@ struct aim_t
bool AimTraverse3DFloors(const divline_t &trace, intercept_t * in);
#endif
void AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy);
void AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy, bool checknonshootable = false);
};
@ -2784,7 +2785,7 @@ bool aim_t::AimTraverse3DFloors(const divline_t &trace, intercept_t * in)
//
//============================================================================
void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy)
void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t endy, bool checknonshootable)
{
FPathTraverse it(startx, starty, endx, endy, PT_ADDLINES|PT_ADDTHINGS);
intercept_t *in;
@ -2839,18 +2840,20 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e
if (th == shootthing)
continue; // can't shoot self
if (!(th->flags&MF_SHOOTABLE))
continue; // corpse or something
// check for physical attacks on a ghost
if ((th->flags3 & MF3_GHOST) &&
shootthing->player && // [RH] Be sure shootthing is a player
shootthing->player->ReadyWeapon &&
(shootthing->player->ReadyWeapon->flags2 & MF2_THRUGHOST))
if (!checknonshootable) // For info CCMD, ignore stuff about GHOST and SHOOTABLE flags
{
continue;
if (!(th->flags&MF_SHOOTABLE))
continue; // corpse or something
// check for physical attacks on a ghost
if ((th->flags3 & MF3_GHOST) &&
shootthing->player && // [RH] Be sure shootthing is a player
shootthing->player->ReadyWeapon &&
(shootthing->player->ReadyWeapon->flags2 & MF2_THRUGHOST))
{
continue;
}
}
dist = FixedMul (attackrange, in->frac);
#ifdef _3DFLOORS
@ -2974,6 +2977,11 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e
aimpitch=thingpitch;
return;
}
if (checknonshootable)
{
linetarget=th;
aimpitch=thingpitch;
}
}
}
@ -2982,7 +2990,7 @@ void aim_t::AimTraverse (fixed_t startx, fixed_t starty, fixed_t endx, fixed_t e
// P_AimLineAttack
//
//============================================================================
fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget, fixed_t vrange, bool forcenosmart, bool check3d)
fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **pLineTarget, fixed_t vrange, bool forcenosmart, bool check3d, bool checknonshootable)
{
fixed_t x2;
fixed_t y2;
@ -3051,7 +3059,7 @@ fixed_t P_AimLineAttack (AActor *t1, angle_t angle, fixed_t distance, AActor **p
}
#endif
aim.AimTraverse (t1->x, t1->y, x2, y2);
aim.AimTraverse (t1->x, t1->y, x2, y2, checknonshootable);
if (!aim.linetarget)
{
@ -4124,7 +4132,6 @@ void P_RadiusAttack (AActor *bombspot, AActor *bombsource, int bombdamage, int b
}
}
//
// SECTOR HEIGHT CHANGING
// After modifying a sector's floor or ceiling height,

View file

@ -325,6 +325,9 @@ void AActor::Serialize (FArchive &arc)
<< pushfactor
<< Species;
if (SaveVersion >= 1819)
arc << Score;
if (arc.IsStoring ())
{
int convnum = 0;
@ -1845,7 +1848,7 @@ fixed_t P_XYMovement (AActor *mo, fixed_t scrollx, fixed_t scrolly)
BlockingMobj->y,
mo->x, mo->y);
// Change angle for deflection/reflection
// Change angle for deflection/reflection
if (mo->AdjustReflectionAngle (BlockingMobj, angle))
{
goto explode;
@ -2054,12 +2057,13 @@ void P_MonsterFallingDamage (AActor *mo)
//
// P_ZMovement
//
void P_ZMovement (AActor *mo, fixed_t oldfloorz)
{
fixed_t dist;
fixed_t delta;
fixed_t oldz = mo->z;
fixed_t oldz = mo->z;
//
// check for smooth step up
//
@ -2084,8 +2088,7 @@ void P_ZMovement (AActor *mo, fixed_t oldfloorz)
if (!mo->waterlevel || mo->flags & MF_CORPSE || (mo->player &&
!(mo->player->cmd.ucmd.forwardmove | mo->player->cmd.ucmd.sidemove)))
{
fixed_t grav = (fixed_t)(level.gravity * mo->Sector->gravity *
FIXED2FLOAT(mo->gravity) * 81.92);
fixed_t grav = mo->GetGravity();
// [RH] Double gravity only if running off a ledge. Coming down from
// an upward thrust (e.g. a jump) should not double it.
@ -3404,7 +3407,7 @@ AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t
AActor *actor;
actor = static_cast<AActor *>(const_cast<PClass *>(type)->CreateNew ());
actor->x = actor->PrevX = ix;
@ -5347,6 +5350,7 @@ int AActor::SpawnHealth()
return (adj <= 0) ? 1 : adj;
}
}
FDropItem *AActor::GetDropItems()
{
unsigned int index = GetClass()->Meta.GetMetaInt (ACMETA_DropItems) - 1;
@ -5358,6 +5362,21 @@ FDropItem *AActor::GetDropItems()
return NULL;
}
fixed_t AActor::GetGravity() const
{
if (flags & MF_NOGRAVITY) return 0;
return fixed_t(level.gravity * Sector->gravity * FIXED2FLOAT(gravity) * 81.92);
}
// killough 11/98:
// Whether an object is "sentient" or not. Used for environmental influences.
// (left precisely the same as MBF even though it doesn't make much sense.)
bool AActor::IsSentient() const
{
return health > 0 || SeeState != NULL;
}
//----------------------------------------------------------------------------
//
// DropItem handling
@ -5388,3 +5407,68 @@ int StoreDropItemChain(FDropItem *chain)
return DropItemList.Push (chain) + 1;
}
void PrintMiscActorInfo(AActor * query)
{
if (query)
{
int flagi;
int querystyle = STYLE_Count;
for (int style = STYLE_None; style < STYLE_Count; ++style)
{ // Check for a legacy render style that matches.
if (LegacyRenderStyles[style] == query->RenderStyle)
{
querystyle = style;
break;
}
}
static const char * renderstyles[]= {"None", "Normal", "Fuzzy", "SoulTrans",
"OptFuzzy", "Stencil", "Translucent", "Add", "Shaded", "TranslucentStencil"};
/*
Printf("%s %x has the following flags:\n\tflags1: %x",
query->GetNameTag().GetChars(), query, query->flags);
*/
for (flagi = 0; flagi < 31; flagi++)
if (query->flags & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags));
Printf("\n\tflags2: %x", query->flags2);
for (flagi = 0; flagi < 31; flagi++)
if (query->flags2 & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags2));
Printf("\n\tflags3: %x", query->flags3);
for (flagi = 0; flagi < 31; flagi++)
if (query->flags3 & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags3));
Printf("\n\tflags4: %x", query->flags4);
for (flagi = 0; flagi < 31; flagi++)
if (query->flags4 & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags4));
Printf("\n\tflags5: %x", query->flags5);
for (flagi = 0; flagi < 31; flagi++)
if (query->flags5 & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags5));
Printf("\n\tflags6: %x", query->flags6);
for (flagi = 0; flagi < 31; flagi++)
if (query->flags6 & 1<<flagi) Printf(" %s", FLAG_NAME(1<<flagi, flags6));
/*
Printf("\nIts bounce style and factors are %s and f:%f, w:%f; its bounce flags are:\n\tflagsb: %x",
bouncestyles[bt], FIXED2FLOAT(query->bouncefactor),
FIXED2FLOAT(query->wallbouncefactor), query->BounceFlags);
for (flagi = 0; flagi < 31; flagi++)
if (query->BounceFlags & 1<<flagi) Printf(" %s", flagnamesb[flagi]);
*/
Printf("\nIts render style is %i:%s with alpha %f and the following render flags:\n\tflagsr: %x",
querystyle, (querystyle < STYLE_Count ? renderstyles[querystyle] : "Unknown"),
FIXED2FLOAT(query->alpha), query->renderflags);
/*
for (flagi = 0; flagi < 31; flagi++)
if (query->renderflags & 1<<flagi) Printf(" %s", flagnamesr[flagi]);
*/
Printf("\nIts thing special and arguments are %s(%i, %i, %i, %i, %i), and its specials are %i and %i.",
GetSpecialName(query->special), query->args[0], query->args[1],
query->args[2], query->args[3], query->args[4],
query->special1, query->special2);
Printf("\nIts coordinates are x: %f, y: %f, z:%f, floor:%f, ceiling:%f.",
FIXED2FLOAT(query->x), FIXED2FLOAT(query->y), FIXED2FLOAT(query->z),
FIXED2FLOAT(query->floorz), FIXED2FLOAT(query->ceilingz));
Printf("\nIts speed is %f and velocity is x:%f, y:%f, z:%f, combined:%f.\n",
FIXED2FLOAT(query->Speed), FIXED2FLOAT(query->velx), FIXED2FLOAT(query->vely), FIXED2FLOAT(query->velz),
sqrt(pow(FIXED2FLOAT(query->velx), 2) + pow(FIXED2FLOAT(query->vely), 2) + pow(FIXED2FLOAT(query->velz), 2)));
}
}

View file

@ -2535,7 +2535,7 @@ void player_t::Serialize (FArchive &arc)
<< ConversationPC
<< ConversationNPCAngle
<< ConversationFaceTalker;
for (i = 0; i < MAXPLAYERS; i++)
arc << frags[i];
for (i = 0; i < NUMPSPRITES; i++)

View file

@ -704,8 +704,7 @@ bool FScanner::GetFloat ()
Float = (float)strtod (String, &stopper);
if (*stopper != 0)
{
I_Error ("SC_GetFloat: Bad numeric constant \"%s\".\n"
"Script %s, Line %d\n", String, ScriptName.GetChars(), Line);
ScriptError ("SC_GetFloat: Bad numeric constant \"%s\".", String);
}
Number = (int)Float;
return true;

View file

@ -5,6 +5,7 @@
#include "info.h"
#include "s_sound.h"
#include "sc_man.h"
#include "cmdlib.h"
class FScanner;
@ -25,6 +26,9 @@ struct FFlagDef
FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2);
void HandleDeprecatedFlags(AActor *defaults, FActorInfo *info, bool set, int index);
const char *GetFlagName(int flagnum, int flagoffset);
#define FLAG_NAME(flagnum, flagvar) GetFlagName(flagnum, myoffsetof(AActor, flagvar))
//==========================================================================
@ -120,7 +124,7 @@ public:
~FStateExpressions();
int Add(FxExpression *x, const PClass *o, bool c);
int Reserve(int num, const PClass *cls);
void Set(int num, FxExpression *x);
void Set(int num, FxExpression *x, bool cloned = false);
void Copy(int dest, int src, int cnt);
int ResolveAll();
FxExpression *Get(int no);

View file

@ -560,12 +560,14 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_JumpIfArmorType)
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode)
{
ACTION_PARAM_START(5);
ACTION_PARAM_START(7);
ACTION_PARAM_INT(damage, 0);
ACTION_PARAM_INT(distance, 1);
ACTION_PARAM_BOOL(hurtSource, 2);
ACTION_PARAM_BOOL(alert, 3);
ACTION_PARAM_INT(fulldmgdistance, 4);
ACTION_PARAM_INT(nails, 5);
ACTION_PARAM_INT(naildamage, 6);
if (damage < 0) // get parameters from metadata
{
@ -578,6 +580,21 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Explode)
{
if (distance <= 0) distance = damage;
}
// NailBomb effect, from SMMU but not from its source code: instead it was implemented and
// generalized from the documentation at http://www.doomworld.com/eternity/engine/codeptrs.html
if (nails)
{
angle_t ang;
for (int i = 0; i < nails; i++)
{
ang = i*(ANGLE_MAX/nails);
// Comparing the results of a test wad with Eternity, it seems A_NailBomb does not aim
P_LineAttack (self, ang, MISSILERANGE, 0,
//P_AimLineAttack (self, ang, MISSILERANGE),
naildamage, NAME_None, NAME_BulletPuff);
}
}
P_RadiusAttack (self, self->target, damage, distance, self->DamageType, hurtSource, true, fulldmgdistance);
if (self->z <= self->floorz + (distance<<FRACBITS))
@ -1675,6 +1692,47 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Print)
}
}
//===========================================================================
//
// A_PrintBold
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_PrintBold)
{
ACTION_PARAM_START(3);
ACTION_PARAM_STRING(text, 0);
ACTION_PARAM_FLOAT(time, 1);
ACTION_PARAM_NAME(fontname, 2);
float saved = con_midtime;
FFont *font = NULL;
if (fontname != NAME_None)
{
font = V_GetFont(fontname);
}
if (time > 0)
{
con_midtime = time;
}
C_MidPrintBold(font != NULL ? font : SmallFont, text);
con_midtime = saved;
}
//===========================================================================
//
// A_Log
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Log)
{
ACTION_PARAM_START(1);
ACTION_PARAM_STRING(text, 0);
Printf("%s\n", text);
}
//===========================================================================
//
@ -2769,3 +2827,28 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetArg)
self->args[pos] = value;
}
}
//===========================================================================
//
// A_SetSpecial
//
//===========================================================================
DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_SetSpecial)
{
ACTION_PARAM_START(6);
ACTION_PARAM_INT(spec, 0);
ACTION_PARAM_INT(arg0, 1);
ACTION_PARAM_INT(arg1, 2);
ACTION_PARAM_INT(arg2, 3);
ACTION_PARAM_INT(arg3, 4);
ACTION_PARAM_INT(arg4, 5);
self->special = spec;
self->args[0] = arg0;
self->args[1] = arg1;
self->args[2] = arg2;
self->args[3] = arg3;
self->args[4] = arg4;
}

View file

@ -391,6 +391,24 @@ FFlagDef *FindFlag (const PClass *type, const char *part1, const char *part2)
}
//==========================================================================
//
// Gets the name of an actor flag
//
//==========================================================================
const char *GetFlagName(int flagnum, int flagoffset)
{
for(int i=0; i<countof(ActorFlags); i++)
{
if (ActorFlags[i].flagbit == flagnum && ActorFlags[i].structoffset == flagoffset)
{
return ActorFlags[i].name;
}
}
return "(unknown)"; // return something printable
}
//==========================================================================
//
// Find a property by name using a binary search
@ -534,7 +552,6 @@ static int STACK_ARGS varcmp(const void * a, const void * b)
return stricmp(A->name, B->name);
}
//==========================================================================
//
// Initialization

View file

@ -75,6 +75,7 @@ DEFINE_MEMBER_VARIABLE_ALIAS(momx, velx, AActor)
DEFINE_MEMBER_VARIABLE_ALIAS(momy, vely, AActor)
DEFINE_MEMBER_VARIABLE_ALIAS(momz, velz, AActor)
DEFINE_MEMBER_VARIABLE(Damage, AActor)
DEFINE_MEMBER_VARIABLE(Score, AActor)
//==========================================================================
//
@ -2812,13 +2813,13 @@ int FStateExpressions::Reserve(int num, const PClass *cls)
//
//==========================================================================
void FStateExpressions::Set(int num, FxExpression *x)
void FStateExpressions::Set(int num, FxExpression *x, bool cloned)
{
if (num >= 0 && num < int(Size()))
{
assert(expressions[num].expr == NULL || expressions[num].cloned);
expressions[num].expr = x;
expressions[num].cloned = false;
expressions[num].cloned = cloned;
}
}

View file

@ -849,10 +849,11 @@ DEFINE_PROPERTY(bloodtype, Sss, Actor)
//==========================================================================
DEFINE_PROPERTY(bouncetype, S, Actor)
{
static const char *names[] = { "None", "Doom", "Heretic", "Hexen", "DoomCompat", "HereticCompat", "HexenCompat", NULL };
static const BYTE flags[] = { BOUNCE_None,
static const char *names[] = { "None", "Doom", "Heretic", "Hexen", "DoomCompat", "HereticCompat", "HexenCompat", "Grenade", "Classic", NULL };
static const int flags[] = { BOUNCE_None,
BOUNCE_Doom, BOUNCE_Heretic, BOUNCE_Hexen,
BOUNCE_DoomCompat, BOUNCE_HereticCompat, BOUNCE_HexenCompat };
BOUNCE_DoomCompat, BOUNCE_HereticCompat, BOUNCE_HexenCompat,
BOUNCE_Grenade, BOUNCE_Classic, };
PROP_STRING_PARM(id, 0);
int match = MatchString(id, names);
if (match < 0)
@ -1294,7 +1295,6 @@ DEFINE_CLASS_PROPERTY(pickupsound, S, Inventory)
//==========================================================================
DEFINE_CLASS_PROPERTY(pickupannouncerentry, S, Inventory)
{
PROP_STRING_PARM(str, 0);
}
//==========================================================================

View file

@ -67,7 +67,7 @@ struct TVector2
}
TVector2 (double a, double b)
: X(a), Y(b)
: X(vec_t(a)), Y(vec_t(b))
{
}

View file

@ -64,7 +64,7 @@
// Protocol version used in demos.
// Bump it if you change existing DEM_ commands or add new ones.
// Otherwise, it should be safe to leave it alone.
#define DEMOGAMEVERSION 0x211
#define DEMOGAMEVERSION 0x212
// Minimum demo version we can play.
// Bump it whenever you change or remove existing DEM_ commands.

View file

@ -44,6 +44,7 @@ ACTOR Actor native //: Thinker
native fixed_t momx; // alias for velx
native fixed_t momy; // alias for vely
native fixed_t momz; // alias for velz
native int score;
action native A_MonsterRail();
action native A_BFGSpray(class<Actor> spraytype = "BFGExtra", int numrays = 40, int damagecount = 15);
@ -186,6 +187,8 @@ ACTOR Actor native //: Thinker
action native A_SpawnItem(class<Actor> itemtype, float distance = 0, float zheight = 0, bool useammo = true, bool transfer_translation = false);
action native A_SpawnItemEx(class<Actor> itemtype, float xofs = 0, float yofs = 0, float zofs = 0, float xvel = 0, float yvel = 0, float zvel = 0, float angle = 0, int flags = 0, int failchance = 0);
action native A_Print(string whattoprint, float time = 0, string fontname = "");
action native A_PrintBold(string whattoprint, float time = 0, string fontname = "");
action native A_Log(string whattoprint);
action native A_SetTranslucent(float alpha, int style = 0);
action native A_FadeIn(float reduce = 0.1);
action native A_FadeOut(float reduce = 0.1, bool remove = true);
@ -220,7 +223,7 @@ ACTOR Actor native //: Thinker
action native A_CustomComboAttack(class<Actor> missiletype, float spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true);
action native A_Burst(class<Actor> chunktype);
action native A_RadiusThrust(int force = 128, int distance = -1, bool affectsource = true);
action native A_Explode(int damage = -1, int distance = -1, bool hurtsource = true, bool alert = false, int fulldamagedistance = 0);
action native A_Explode(int damage = -1, int distance = -1, bool hurtsource = true, bool alert = false, int fulldamagedistance = 0, int nails = 0, int naildamage = 10);
action native A_Stop();
action native A_Respawn(bool fog = true);
action native A_BarrelDestroy();
@ -246,11 +249,12 @@ ACTOR Actor native //: Thinker
action native A_DropWeaponPieces(class<Actor> p1, class<Actor> p2, class<Actor> p3);
action native A_PigPain ();
action native A_MonsterRefire(int chance, state label);
action native A_SetAngle(float angle);
action native A_SetAngle(float angle = 0);
action native A_SetPitch(float pitch);
action native A_ScaleVelocity(float scale);
action native A_ChangeVelocity(float x = 0, float y = 0, float z = 0, int flags = 0);
action native A_SetArg(int pos, int value);
action native A_SetSpecial(int spec, int arg0, int arg1, int arg2, int arg3, int arg4);
States
{

View file

@ -35,6 +35,7 @@ ACTOR Inventory native
action native A_RailWait();
action native A_BFGsound();
action native A_FireBFG();
action native A_FireOldBFG();
action native A_ReFire();
action native A_ClearReFire();
action native A_CheckReload();
@ -70,6 +71,14 @@ ACTOR Inventory native
}
}
Actor ScoreItem : Inventory native
{
Height 10
+COUNTITEM
Inventory.Amount 1
+Inventory.ALWAYSPICKUP
}
Actor Ammo : Inventory native
{
+INVENTORY.KEEPDEPLETED
@ -161,6 +170,7 @@ ACTOR PowerStrength : Powerup native
ACTOR PowerInvisibility : Powerup native
{
+SHADOW
Powerup.Duration -60
Powerup.Strength 80
Powerup.Mode "Fuzzy"

View file

@ -137,6 +137,7 @@ ACTOR RandomSpawner native
+NOBLOCKMAP
+NOSECTOR
+NOGRAVITY
+THRUACTORS
}
// Fast projectiles -----------------------------------------------------------