diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 2b3ace08f..2c88821d2 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -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. diff --git a/src/actionspecials.h b/src/actionspecials.h index b185a7fa0..ec8aef9cf 100644 --- a/src/actionspecials.h +++ b/src/actionspecials.h @@ -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) diff --git a/src/actor.h b/src/actor.h index 3e59c86b4..5c94eec6f 100644 --- a/src/actor.h +++ b/src/actor.h @@ -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 target; // thing being chased/attacked (or NULL) // also the originator for missiles - TObjPtr lastenemy; // Last known enemy -- killogh 2/15/98 + TObjPtr lastenemy; // Last known enemy -- killough 2/15/98 TObjPtr 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 tracer; // Thing being chased/attacked for tracers TObjPtr 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(AActor::StaticSpawn (RUNTIME_CLASS(T), x, y, z, allowreplacement)); } +void PrintMiscActorInfo(AActor * query); + #define S_FREETARGMOBJ 1 #endif // __P_MOBJ_H__ diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index b1d95215a..3cddb6d52 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -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"); +} + //----------------------------------------------------------------------------- // // diff --git a/src/d_net.cpp b/src/d_net.cpp index 80c8de130..f916721b4 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -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: diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index 9cc4b14a6..c395681ce 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -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); } } diff --git a/src/d_protocol.h b/src/d_protocol.h index 9f8bde657..eae1f4aa9 100644 --- a/src/d_protocol.h +++ b/src/d_protocol.h @@ -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 diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index 71ae8cb96..fcd6ea3a0 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -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 +} diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index 8292b199f..bcaa6c730 100644 --- a/src/g_shared/a_artifacts.cpp +++ b/src/g_shared/a_artifacts.cpp @@ -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((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(item)->OwnersNormalStyle; + OwnersNormalAlpha = static_cast(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((/*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(item)->InitEffect(); + static_cast(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((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((/*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)) diff --git a/src/g_shared/a_artifacts.h b/src/g_shared/a_artifacts.h index 14b312399..1272de60d 100644 --- a/src/g_shared/a_artifacts.h +++ b/src/g_shared/a_artifacts.h @@ -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 diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index 2753a750b..045e5bf92 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -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; +} + diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index f1a38afbb..6ccc8cd5e 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -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__ diff --git a/src/info.cpp b/src/info.cpp index a811054ff..aeb89e8c9 100644 --- a/src/info.cpp +++ b/src/info.cpp @@ -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); diff --git a/src/namedef.h b/src/namedef.h index 8564d7036..ea4aaa4c2 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -25,8 +25,11 @@ xx(Ghost) xx(Reflective) // Invisibility types +xx(Additive) xx(Cumulative) xx(Fuzzy) +xx(Opaque) +xx(Stencil) // Healingradius types xx(Mana) diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 5db1ac32c..4dcf1c2a8 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -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; } } diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 30306188e..1d8ebc114 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -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; diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index a0d53c1f5..d48b6e8d6 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -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); diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index b34ed4878..7e535756f 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -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)"; +} \ No newline at end of file diff --git a/src/p_lnspec.h b/src/p_lnspec.h index 495947243..05f305520 100644 --- a/src/p_lnspec.h +++ b/src/p_lnspec.h @@ -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__ diff --git a/src/p_local.h b/src/p_local.h index 2332eb8db..3ed7c8725 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -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); diff --git a/src/p_map.cpp b/src/p_map.cpp index 3a2a88ae7..144091d0c 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -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, diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 70cb731c8..9161a5a09 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -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(const_cast(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<flags2); + for (flagi = 0; flagi < 31; flagi++) + if (query->flags2 & 1<flags3); + for (flagi = 0; flagi < 31; flagi++) + if (query->flags3 & 1<flags4); + for (flagi = 0; flagi < 31; flagi++) + if (query->flags4 & 1<flags5); + for (flagi = 0; flagi < 31; flagi++) + if (query->flags5 & 1<flags6); + for (flagi = 0; flagi < 31; flagi++) + if (query->flags6 & 1<bouncefactor), + FIXED2FLOAT(query->wallbouncefactor), query->BounceFlags); + for (flagi = 0; flagi < 31; flagi++) + if (query->BounceFlags & 1<alpha), query->renderflags); + /* + for (flagi = 0; flagi < 31; flagi++) + if (query->renderflags & 1<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))); + } +} diff --git a/src/p_user.cpp b/src/p_user.cpp index fe65f55bf..0f7d480a1 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -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++) diff --git a/src/sc_man.cpp b/src/sc_man.cpp index e8bcffdb5..b69aa1ce0 100644 --- a/src/sc_man.cpp +++ b/src/sc_man.cpp @@ -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; diff --git a/src/thingdef/thingdef.h b/src/thingdef/thingdef.h index 95ce02222..b60f0f422 100644 --- a/src/thingdef/thingdef.h +++ b/src/thingdef/thingdef.h @@ -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); diff --git a/src/thingdef/thingdef_codeptr.cpp b/src/thingdef/thingdef_codeptr.cpp index 83bd9bba2..0975dac1e 100644 --- a/src/thingdef/thingdef_codeptr.cpp +++ b/src/thingdef/thingdef_codeptr.cpp @@ -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< 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; +} + diff --git a/src/thingdef/thingdef_data.cpp b/src/thingdef/thingdef_data.cpp index b99f6e38a..8ef4ca640 100644 --- a/src/thingdef/thingdef_data.cpp +++ b/src/thingdef/thingdef_data.cpp @@ -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; iname, B->name); } - //========================================================================== // // Initialization diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 2c58464a5..bcb630826 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -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; } } diff --git a/src/thingdef/thingdef_properties.cpp b/src/thingdef/thingdef_properties.cpp index 8ebf70d93..263b55a7c 100644 --- a/src/thingdef/thingdef_properties.cpp +++ b/src/thingdef/thingdef_properties.cpp @@ -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); } //========================================================================== diff --git a/src/vectors.h b/src/vectors.h index 213afb505..f3b154aa2 100644 --- a/src/vectors.h +++ b/src/vectors.h @@ -67,7 +67,7 @@ struct TVector2 } TVector2 (double a, double b) - : X(a), Y(b) + : X(vec_t(a)), Y(vec_t(b)) { } diff --git a/src/version.h b/src/version.h index a6b02e748..7a298c42a 100644 --- a/src/version.h +++ b/src/version.h @@ -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. diff --git a/wadsrc/static/actors/actor.txt b/wadsrc/static/actors/actor.txt index c1dacde2c..c41c062f9 100644 --- a/wadsrc/static/actors/actor.txt +++ b/wadsrc/static/actors/actor.txt @@ -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 spraytype = "BFGExtra", int numrays = 40, int damagecount = 15); @@ -186,6 +187,8 @@ ACTOR Actor native //: Thinker action native A_SpawnItem(class itemtype, float distance = 0, float zheight = 0, bool useammo = true, bool transfer_translation = false); action native A_SpawnItemEx(class 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 missiletype, float spawnheight, int damage, sound meleesound = "", name damagetype = "none", bool bleed = true); action native A_Burst(class 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 p1, class p2, class 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 { diff --git a/wadsrc/static/actors/shared/inventory.txt b/wadsrc/static/actors/shared/inventory.txt index acda21f8f..ca73cab29 100644 --- a/wadsrc/static/actors/shared/inventory.txt +++ b/wadsrc/static/actors/shared/inventory.txt @@ -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" diff --git a/wadsrc/static/actors/shared/sharedmisc.txt b/wadsrc/static/actors/shared/sharedmisc.txt index da0ff3edb..a51ab52ae 100644 --- a/wadsrc/static/actors/shared/sharedmisc.txt +++ b/wadsrc/static/actors/shared/sharedmisc.txt @@ -137,6 +137,7 @@ ACTOR RandomSpawner native +NOBLOCKMAP +NOSECTOR +NOGRAVITY + +THRUACTORS } // Fast projectiles -----------------------------------------------------------