diff --git a/docs/rh-log.txt b/docs/rh-log.txt index a5f979076..14b4faaeb 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,4 +1,27 @@ +May 9, 2007 (Changes by Graf Zahl) +- added Skulltag's custom F1 help screen MAPINFO option. + +May 4, 2007 (Changes by Graf Zahl) +- Fixed: Resurrecting a player must restore all flags words, not just the first one. +- Fixed: APowerWeaponLevel2::EndEffect must check PendingWeapon for WP_NOCHANGE. + +May 3, 2007 (Changes by Graf Zahl) +- added Skulltag's high jump rune as a powerup + +May 2, 2007 (Changes by Graf Zahl) +- Added Skulltag's Drain and Regeneration runes as powerups and used specific player + sounds for their sound effects instead of using misc/i_pkup. + (If I ever decide to implement runes it will be in a way that can use the regular + powerups instead of having to define specific classes for them.) +- Added Skulltag's PowerQuadDamage and PowerQuarterDamage as more customizable + PowerDamage and PowerProtection. These new powerups allow free customization of + the damage modification per damage type by inheriting from these classes and + setting specific values. Such derived damage/protection powerups will be considered + as separate powers so that for example a QuadDamage and a DoubleDamage item can be + stacked which would result in 8x damage. + May 1, 2007 (Changes by Graf Zahl) +- merged player_t::cheats and player_t::Powers into one variable. - Fixed: player_t::Powers was not saved in a savegame. - Removed all unused PW_* player power flags. - Added Skulltag's TimeFreezer powerup. diff --git a/src/d_player.h b/src/d_player.h index 3f57f3dc6..df59b5569 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -146,33 +146,34 @@ typedef enum // typedef enum { - CF_NOCLIP = 1, // No clipping, walk through barriers. - CF_GODMODE = 2, // No damage, no health loss. - CF_NOMOMENTUM = 4, // Not really a cheat, just a debug aid. - CF_NOTARGET = 8, // [RH] Monsters don't target - CF_FLY = 16, // [RH] Flying player - CF_CHASECAM = 32, // [RH] Put camera behind player - CF_FROZEN = 64, // [RH] Don't let the player move - CF_REVERTPLEASE = 128, // [RH] Stick camera in player's head if (s)he moves - CF_STEPLEFT = 512, // [RH] Play left footstep sound next time - CF_FRIGHTENING = 1024, // [RH] Scare monsters away - CF_INSTANTWEAPSWITCH= 2048, // [RH] Switch weapons instantly - CF_TOTALLYFROZEN = 4096, // [RH] All players can do is press +use - CF_PREDICTING = 8192, // [RH] Player movement is being predicted - CF_WEAPONREADY = 16384,// [RH] Weapon is in the ready state, so bob it when walking + CF_NOCLIP = 1, // No clipping, walk through barriers. + CF_GODMODE = 2, // No damage, no health loss. + CF_NOMOMENTUM = 4, // Not really a cheat, just a debug aid. + CF_NOTARGET = 8, // [RH] Monsters don't target + CF_FLY = 16, // [RH] Flying player + CF_CHASECAM = 32, // [RH] Put camera behind player + CF_FROZEN = 64, // [RH] Don't let the player move + CF_REVERTPLEASE = 128, // [RH] Stick camera in player's head if (s)he moves + CF_STEPLEFT = 512, // [RH] Play left footstep sound next time + CF_FRIGHTENING = 1024, // [RH] Scare monsters away + CF_INSTANTWEAPSWITCH= 2048, // [RH] Switch weapons instantly + CF_TOTALLYFROZEN = 4096, // [RH] All players can do is press +use + CF_PREDICTING = 8192, // [RH] Player movement is being predicted + CF_WEAPONREADY = 16384, // [RH] Weapon is in the ready state, so bob it when walking + CF_TIMEFREEZE = 32768, // Player has an active time freezer + CF_DRAIN = 65536, // Player owns a drain powerup + CF_SPEED = 0x20000, // Player owns a speed artifact + CF_REGENERATION = 0x40000, // Player owns a regeneration artifact + CF_HIGHJUMP = 0x80000, // more Skulltag flags. Implemetation not guaranteed though. ;) + CF_REFLECTION = 0x100000, + CF_PROSPERITY = 0x200000, + CF_DOUBLEFIRINGSPEED= 0x400000, } cheat_t; #define WPIECE1 1 #define WPIECE2 2 #define WPIECE3 4 -enum -{ - PW_SPEED = 1, - PW_TIMEFREEZE = 2, -// -}; - #define WP_NOCHANGE ((AWeapon*)~0) // @@ -232,7 +233,6 @@ public: AWeapon *PendingWeapon; // WP_NOCHANGE if not changing int cheats; // bit flags - BITFIELD Powers; // powers short refire; // refired shots are less accurate short inconsistant; int killcount, itemcount, secretcount; // for intermission diff --git a/src/g_level.cpp b/src/g_level.cpp index 88914ab7c..0cea81b59 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -155,7 +155,8 @@ static level_info_t TheDefaultLevelInfo = unnamed, // level_name "COLORMAP", // fadetable +8, // WallVertLight - -8 // WallHorizLight + -8, // WallHorizLight + "", // [RC] F1 }; static cluster_info_t TheDefaultClusterInfo = { 0 }; @@ -281,7 +282,7 @@ static const char *MapInfoMapLevel[] = "compat_dropoff", "compat_boomscroll", "bordertexture", - + "f1", // [RC] F1 help NULL }; @@ -307,6 +308,7 @@ enum EMIType MITYPE_REDIRECT, MITYPE_SPECIALACTION, MITYPE_COMPATFLAG, + MITYPE_F1, // [RC] F1 help }; struct MapInfoHandler @@ -414,6 +416,7 @@ MapHandlers[] = { MITYPE_COMPATFLAG, COMPATF_DROPOFF}, { MITYPE_COMPATFLAG, COMPATF_BOOMSCROLL}, { MITYPE_LUMPNAME, lioffset(bordertexture), 0 }, + { MITYPE_F1, lioffset(f1), 0, }, }; static const char *MapInfoClusterLevel[] = @@ -656,6 +659,10 @@ static void G_DoParseMapInfo (int lump) { strcpy (levelinfo->skypic2, levelinfo->skypic1); } + if (levelinfo->f1 != NULL) + { + levelinfo->f1 = copystring (levelinfo->f1); + } SetLevelNum (levelinfo, levelinfo->levelnum); // Wipe out matching levelnums from other maps. if (levelinfo->pname[0] != 0) { @@ -992,6 +999,18 @@ static void ParseMapInfoLower (MapInfoHandler *handlers, ReplaceString ((char **)(info + handler->data1), sc_String); break; + case MITYPE_F1: + SC_MustGetString (); + { + char *colon = strchr (sc_String, ':'); + if (colon) + { + *colon = 0; + } + ReplaceString ((char **)(info + handler->data1), sc_String); + } + break; + case MITYPE_MUSIC: SC_MustGetString (); { @@ -2256,6 +2275,7 @@ void G_InitLevelLocals () level.levelnum = info->levelnum; level.music = info->music; level.musicorder = info->musicorder; + level.f1 = info->f1; // [RC] And import the f1 name strncpy (level.level_name, info->level_name, 63); G_MaybeLookupLevelName (NULL); diff --git a/src/g_level.h b/src/g_level.h index 992e36fdd..205303206 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -134,6 +134,7 @@ struct level_info_s char *level_name; char fadetable[9]; SBYTE WallVertLight, WallHorizLight; + char *f1; // TheDefaultLevelInfo initializes everything above this line. int musicorder; FCompressedMemFile *snapshot; @@ -231,6 +232,8 @@ struct level_locals_s SBYTE WallVertLight; // Light diffs for vert/horiz walls SBYTE WallHorizLight; + + char *f1; }; typedef struct level_locals_s level_locals_t; diff --git a/src/g_shared/a_armor.cpp b/src/g_shared/a_armor.cpp index fedfcba1b..fdd2efeb8 100644 --- a/src/g_shared/a_armor.cpp +++ b/src/g_shared/a_armor.cpp @@ -159,6 +159,7 @@ void ABasicArmor::AbsorbDamage (int damage, FName damageType, int &newdamage) Owner->UseInventory (best); } } + damage = newdamage; } if (Inventory != NULL) { @@ -477,6 +478,7 @@ void AHexenArmor::AbsorbDamage (int damage, FName damageType, int &newdamage) saved = savedPercent >> (FRACBITS-1); } newdamage -= saved; + damage = newdamage; } } if (Inventory != NULL) diff --git a/src/g_shared/a_artifacts.cpp b/src/g_shared/a_artifacts.cpp index da5baccb4..edd72c8f5 100644 --- a/src/g_shared/a_artifacts.cpp +++ b/src/g_shared/a_artifacts.cpp @@ -1117,7 +1117,7 @@ void APowerWeaponLevel2::EndEffect () { player->ReadyWeapon->EndPowerup (); } - if (player->PendingWeapon != NULL && + if (player->PendingWeapon != NULL && player->PendingWeapon != WP_NOCHANGE && player->PendingWeapon->WeaponFlags & WIF_POWERED_UP && player->PendingWeapon->SisterWeapon != NULL) { @@ -1175,7 +1175,7 @@ END_DEFAULTS void APowerSpeed::InitEffect () { - Owner->player->Powers |= PW_SPEED; + Owner->player->cheats |= CF_SPEED; } //=========================================================================== @@ -1229,7 +1229,7 @@ void APowerSpeed::EndEffect () { if (Owner != NULL && Owner->player != NULL) { - Owner->player->Powers &= ~PW_SPEED; + Owner->player->cheats &= ~CF_SPEED; } } @@ -1382,7 +1382,7 @@ void APowerTimeFreezer::InitEffect( ) S_PauseSound( false ); // Give the player and his teammates the power to move when time is frozen. - Owner->player->Powers |= PW_TIMEFREEZE; + Owner->player->cheats |= CF_TIMEFREEZE; for ( ulIdx = 0; ulIdx < MAXPLAYERS; ulIdx++ ) { if ( playeringame[ulIdx] && @@ -1390,7 +1390,7 @@ void APowerTimeFreezer::InitEffect( ) players[ulIdx].mo->IsTeammate( Owner ) ) { - players[ulIdx].Powers |= PW_TIMEFREEZE; + players[ulIdx].cheats |= CF_TIMEFREEZE; } } @@ -1439,7 +1439,7 @@ void APowerTimeFreezer::EndEffect( ) } // Take away the time freeze power, and his teammates. - Owner->player->Powers &= ~PW_TIMEFREEZE; + Owner->player->cheats &= ~CF_TIMEFREEZE; for ( ulIdx = 0; ulIdx < MAXPLAYERS; ulIdx++ ) { if ( playeringame[ulIdx] && @@ -1447,8 +1447,221 @@ void APowerTimeFreezer::EndEffect( ) players[ulIdx].mo->IsTeammate( Owner ) ) { - players[ulIdx].Powers &= ~PW_TIMEFREEZE; + players[ulIdx].cheats &= ~CF_TIMEFREEZE; } } } +// Damage powerup ------------------------------------------------------ + +IMPLEMENT_STATELESS_ACTOR( APowerDamage, Any, -1, 0 ) + PROP_Powerup_EffectTics( 25*TICRATE ) +END_DEFAULTS + +//=========================================================================== +// +// APowerDamage :: InitEffect +// +//=========================================================================== + +void APowerDamage::InitEffect( ) +{ + // Use sound channel 5 to avoid interference with other actions. + if (Owner != NULL) S_SoundID(Owner, 5, SeeSound, 1.0f, ATTN_SURROUND); +} + +//=========================================================================== +// +// APowerDamage :: EndEffect +// +//=========================================================================== + +void APowerDamage::EndEffect( ) +{ + // Use sound channel 5 to avoid interference with other actions. + if (Owner != NULL) S_SoundID(Owner, 5, DeathSound, 1.0f, ATTN_SURROUND); +} + +//=========================================================================== +// +// APowerDamage :: AbsorbDamage +// +//=========================================================================== + +void APowerDamage::ModifyDamage(int damage, FName damageType, int &newdamage, bool passive) +{ + static const fixed_t def = 4*FRACUNIT; + if (!passive && damage > 0) + { + DmgFactors * df = GetClass()->ActorInfo->DamageFactors; + if (df != NULL) + { + const fixed_t * pdf = df->CheckKey(damageType); + if (pdf== NULL && damageType != NAME_None) pdf = df->CheckKey(NAME_None); + if (pdf == NULL) pdf = &def; + + damage = newdamage = FixedMul(damage, *pdf); + if (*pdf > 0 && damage == 0) damage = newdamage = 1; // don't allow zero damage as result of an underflow + if (Owner != NULL && *pdf > FRACUNIT) S_SoundID(Owner, 5, ActiveSound, 1.0f, ATTN_SURROUND); + } + } + if (Inventory != NULL) Inventory->ModifyDamage(damage, damageType, newdamage, passive); +} + +// Quarter damage powerup ------------------------------------------------------ + +IMPLEMENT_STATELESS_ACTOR( APowerProtection, Any, -1, 0 ) + PROP_Powerup_EffectTics( 25*TICRATE ) +END_DEFAULTS + +//=========================================================================== +// +// APowerProtection :: InitEffect +// +//=========================================================================== + +void APowerProtection::InitEffect( ) +{ + // Use sound channel 5 to avoid interference with other actions. + if (Owner != NULL) S_SoundID(Owner, 5, SeeSound, 1.0f, ATTN_SURROUND); +} + +//=========================================================================== +// +// APowerProtection :: EndEffect +// +//=========================================================================== + +void APowerProtection::EndEffect( ) +{ + // Use sound channel 5 to avoid interference with other actions. + if (Owner != NULL) S_SoundID(Owner, 5, DeathSound, 1.0f, ATTN_SURROUND); +} + +//=========================================================================== +// +// APowerProtection :: AbsorbDamage +// +//=========================================================================== + +void APowerProtection::ModifyDamage(int damage, FName damageType, int &newdamage, bool passive) +{ + static const fixed_t def = FRACUNIT/4; + if (passive && damage > 0) + { + DmgFactors * df = GetClass()->ActorInfo->DamageFactors; + if (df != NULL) + { + const fixed_t * pdf = df->CheckKey(damageType); + if (pdf== NULL && damageType != NAME_None) pdf = df->CheckKey(NAME_None); + if (pdf == NULL) pdf = &def; + + damage = newdamage = FixedMul(damage, *pdf); + if (Owner != NULL && *pdf < FRACUNIT) S_SoundID(Owner, 5, ActiveSound, 1.0f, ATTN_SURROUND); + } + } + if (Inventory != NULL) Inventory->ModifyDamage(damage, damageType, newdamage, passive); +} + +// Drain rune ------------------------------------------------------- + +IMPLEMENT_STATELESS_ACTOR( APowerDrain, Any, -1, 0 ) + PROP_Powerup_EffectTics( 60*TICRATE ) +END_DEFAULTS + +//=========================================================================== +// +// ARuneDrain :: InitEffect +// +//=========================================================================== + +void APowerDrain::InitEffect( ) +{ + // Give the player the power to drain life from opponents when he damages them. + Owner->player->cheats |= CF_DRAIN; +} + +//=========================================================================== +// +// ARuneDrain :: EndEffect +// +//=========================================================================== + +void APowerDrain::EndEffect( ) +{ + // Nothing to do if there's no owner. + if (Owner != NULL && Owner->player != NULL) + { + // Take away the drain power. + Owner->player->cheats &= ~CF_DRAIN; + } +} + + +// Regeneration rune ------------------------------------------------------- + +IMPLEMENT_STATELESS_ACTOR( APowerRegeneration, Any, -1, 0 ) + PROP_Powerup_EffectTics( 120*TICRATE ) +END_DEFAULTS + +//=========================================================================== +// +// ARuneRegeneration :: InitEffect +// +//=========================================================================== + +void APowerRegeneration::InitEffect( ) +{ + // Give the player the power to regnerate lost life. + Owner->player->cheats |= CF_REGENERATION; +} + +//=========================================================================== +// +// ARuneRegeneration :: EndEffect +// +//=========================================================================== + +void APowerRegeneration::EndEffect( ) +{ + // Nothing to do if there's no owner. + if (Owner != NULL && Owner->player != NULL) + { + // Take away the regeneration power. + Owner->player->cheats &= ~CF_REGENERATION; + } +} + +// High jump rune ------------------------------------------------------- + +IMPLEMENT_STATELESS_ACTOR( APowerHighJump, Any, -1, 0 ) +END_DEFAULTS + +//=========================================================================== +// +// ARuneHighJump :: InitEffect +// +//=========================================================================== + +void APowerHighJump::InitEffect( ) +{ + // Give the player the power to jump much higher. + Owner->player->cheats |= CF_HIGHJUMP; +} + +//=========================================================================== +// +// ARuneHighJump :: EndEffect +// +//=========================================================================== + +void APowerHighJump::EndEffect( ) +{ + // Nothing to do if there's no owner. + if (Owner != NULL && Owner->player != NULL) + { + // Take away the high jump power. + Owner->player->cheats &= ~CF_HIGHJUMP; + } +} + diff --git a/src/g_shared/a_artifacts.h b/src/g_shared/a_artifacts.h index 25c2f6cde..027a4ce2c 100644 --- a/src/g_shared/a_artifacts.h +++ b/src/g_shared/a_artifacts.h @@ -213,6 +213,49 @@ protected: void EndEffect( ); }; +class APowerDamage : public APowerup +{ + DECLARE_STATELESS_ACTOR( APowerDamage, APowerup ) +protected: + void InitEffect (); + void EndEffect (); + virtual void ModifyDamage (int damage, FName damageType, int &newdamage, bool passive); +}; + +class APowerProtection : public APowerup +{ + DECLARE_STATELESS_ACTOR( APowerProtection, APowerup ) +protected: + void InitEffect (); + void EndEffect (); + virtual void ModifyDamage (int damage, FName damageType, int &newdamage, bool passive); +}; + +class APowerDrain : public APowerup +{ + DECLARE_STATELESS_ACTOR( APowerDrain, APowerup ) +protected: + void InitEffect( ); + void EndEffect( ); +}; + +class APowerRegeneration : public APowerup +{ + DECLARE_STATELESS_ACTOR( APowerRegeneration, APowerup ) +protected: + void InitEffect( ); + void EndEffect( ); +}; + +class APowerHighJump : public APowerup +{ + DECLARE_STATELESS_ACTOR( APowerHighJump, APowerup ) +protected: + void InitEffect( ); + void EndEffect( ); +}; + + class player_s; diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index ec0d91bdc..dec3fa83c 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -760,6 +760,29 @@ void AInventory::AbsorbDamage (int damage, FName damageType, int &newdamage) } } +//=========================================================================== +// +// AInventory :: ModifyDamage +// +// Allows inventory items to manipulate the amount of damage +// inflicted. Damage is the amount of damage that would be done without manipulation, +// and newdamage is the amount that should be done after the item has changed +// it. +// 'active' means it is called by the inflictor, 'passive' by the target. +// It may seem that this is redundant and AbsorbDamage is the same. However, +// AbsorbDamage is called only for players and also depends on other settings +// which are undesirable for a protection artifact. +// +//=========================================================================== + +void AInventory::ModifyDamage (int damage, FName damageType, int &newdamage, bool passive) +{ + if (Inventory != NULL) + { + Inventory->ModifyDamage (damage, damageType, newdamage, passive); + } +} + //=========================================================================== // // AInventory :: AlterWeaponSprite diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 3d7582f63..69a561451 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -152,6 +152,7 @@ public: virtual void OwnerDied (); virtual void AbsorbDamage (int damage, FName damageType, int &newdamage); + virtual void ModifyDamage (int damage, FName damageType, int &newdamage, bool passive); virtual int AlterWeaponSprite (vissprite_t *vis); virtual PalEntry GetBlend (); diff --git a/src/m_cheat.cpp b/src/m_cheat.cpp index 2c771414b..ae46a7d4d 100644 --- a/src/m_cheat.cpp +++ b/src/m_cheat.cpp @@ -271,6 +271,10 @@ void cht_DoCheat (player_t *player, int cheat) player->health = player->mo->health = player->mo->GetDefault()->health; player->viewheight = ((APlayerPawn *)player->mo->GetDefault())->ViewHeight; player->mo->flags = player->mo->GetDefault()->flags; + player->mo->flags2 = player->mo->GetDefault()->flags2; + player->mo->flags3 = player->mo->GetDefault()->flags3; + player->mo->flags4 = player->mo->GetDefault()->flags4; + player->mo->flags5 = player->mo->GetDefault()->flags5; player->mo->height = player->mo->GetDefault()->height; player->mo->SetState (player->mo->SpawnState); player->mo->Translation = TRANSLATION(TRANSLATION_Players, BYTE(player-players)); diff --git a/src/m_menu.cpp b/src/m_menu.cpp index c9994b05f..258fffc7a 100644 --- a/src/m_menu.cpp +++ b/src/m_menu.cpp @@ -1427,6 +1427,13 @@ void M_DrawReadThis () else { tex = TexMan[gameinfo.info.infoPage[InfoType-1]]; + // Did the mapper choose a custom help page via MAPINFO? + if((level.f1 != NULL) && (strcmp(level.f1, "") != 0)) { + if(TexMan.CheckForTexture(level.f1,0,0) == -1) + TexMan.AddPatch(level.f1); // Needs to be marked as a patch. + tex = TexMan[level.f1]; + } + if (InfoType > 1) { prevpic = TexMan[gameinfo.info.infoPage[InfoType-2]]; diff --git a/src/p_interaction.cpp b/src/p_interaction.cpp index 801885848..b73836bf4 100644 --- a/src/p_interaction.cpp +++ b/src/p_interaction.cpp @@ -56,6 +56,7 @@ #include "gi.h" #include "templates.h" #include "sbar.h" +#include "s_sound.h" static FRandom pr_obituary ("Obituary"); static FRandom pr_botrespawn ("BotRespawn"); @@ -886,32 +887,50 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage } } - // to be removed and replaced by an actual damage factor - // once the actors using it are converted to DECORATE. - if (mod == NAME_Fire && target->flags4 & MF4_FIRERESIST) - { - damage /= 2; - } - else - { - DmgFactors * df = target->GetClass()->ActorInfo->DamageFactors; - if (df != NULL) - { - fixed_t * pdf = df->CheckKey(mod); - if (pdf != NULL) - { - damage = FixedMul(damage, *pdf); - if (damage <= 0) return; - } - } - } damage = inflictor->DoSpecialDamage (target, damage); if (damage == -1) { return; } + + // Handle active damage modifiers (e.g. PowerDamage) + if (inflictor->Inventory != NULL) + { + int olddam = damage; + inflictor->Inventory->ModifyDamage(olddam, mod, damage, false); + if (olddam != damage && damage <= 0) return; + } } + // Handle passive damage modifiers (e.g. PowerProtection) + if (target->Inventory != NULL) + { + int olddam = damage; + target->Inventory->ModifyDamage(olddam, mod, damage, true); + if (olddam != damage && damage <= 0) return; + } + + // to be removed and replaced by an actual damage factor + // once the actors using it are converted to DECORATE. + if (mod == NAME_Fire && target->flags4 & MF4_FIRERESIST) + { + damage /= 2; + } + else + { + DmgFactors * df = target->GetClass()->ActorInfo->DamageFactors; + if (df != NULL) + { + fixed_t * pdf = df->CheckKey(mod); + if (pdf != NULL) + { + damage = FixedMul(damage, *pdf); + if (damage <= 0) return; + } + } + } + damage = target->TakeSpecialDamage (inflictor, source, damage, mod); + if (damage == -1) { return; @@ -1061,6 +1080,21 @@ void P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage // // the damage has been dealt; now deal with the consequences // + + // If the damaging player has the power of drain, give the player 50% of the damage + // done in health. + if ( source && source->player && source->player->cheats & CF_DRAIN) + { + if (!target->player || target->player != source->player) + { + if ( P_GiveBody( source, damage / 2 )) + { + S_Sound( source, CHAN_ITEM, "*drainhealth", 1, ATTN_NORM ); + } + } + } + + if (target->health <= 0) { // Death target->special1 = damage; diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 961cc066b..1de60f892 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -2535,7 +2535,7 @@ void AActor::Tick () } // Apply freeze mode. - if (( level.flags & LEVEL_FROZEN ) && ( player == NULL || !( player->Powers & PW_TIMEFREEZE ))) + if (( level.flags & LEVEL_FROZEN ) && ( player == NULL || !( player->cheats & CF_TIMEFREEZE ))) { return; } diff --git a/src/p_teleport.cpp b/src/p_teleport.cpp index 1995e58fa..95e8ba868 100644 --- a/src/p_teleport.cpp +++ b/src/p_teleport.cpp @@ -306,7 +306,7 @@ bool P_Teleport (AActor *thing, fixed_t x, fixed_t y, fixed_t z, angle_t angle, if (thing->player && (useFog || !keepOrientation)) { // Freeze player for about .5 sec - if (!(thing->player->Powers & PW_SPEED)) + if (!(thing->player->cheats & CF_SPEED)) thing->reactiontime = 18; } if (thing->flags & MF_MISSILE) diff --git a/src/p_tick.cpp b/src/p_tick.cpp index 8e6ecb343..5e4b0a74a 100644 --- a/src/p_tick.cpp +++ b/src/p_tick.cpp @@ -80,7 +80,7 @@ void P_Ticker (void) // off the music. for (i = 0; i < MAXPLAYERS; i++ ) { - if (playeringame[i] && players[i].Powers & PW_TIMEFREEZE) + if (playeringame[i] && players[i].cheats & CF_TIMEFREEZE) break; } diff --git a/src/p_user.cpp b/src/p_user.cpp index ceb143c28..6b5955cc7 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -229,7 +229,6 @@ player_s::player_s() ReadyWeapon(0), PendingWeapon(0), cheats(0), - Powers(0), refire(0), inconsistant(0), killcount(0), @@ -1121,7 +1120,7 @@ void APlayerPawn::TweakSpeeds (int &forward, int &side) side = FixedMul (side, SideMove2); } - if ((player->Powers & PW_SPEED) && !player->morphTics) + if ((player->cheats & CF_SPEED) && !player->morphTics) { // Adjust for a player with a speed artifact forward = (3*forward)>>1; side = (3*side)>>1; @@ -2062,7 +2061,12 @@ void P_PlayerThink (player_t *player) } else if (!(dmflags & DF_NO_JUMP) && onground && !player->jumpTics) { - player->mo->momz += player->mo->JumpZ * 35 / TICRATE; + fixed_t jumpmomz = player->mo->JumpZ * 35 / TICRATE; + + // [BC] If the player has the high jump power, double his jump velocity. + if ( player->cheats & CF_HIGHJUMP ) jumpmomz *= 2; + + player->mo->momz += jumpmomz; S_Sound (player->mo, CHAN_BODY, "*jump", 1, ATTN_NORM); player->mo->flags2 &= ~MF2_ONMOBJ; player->jumpTics = 18*TICRATE/35; @@ -2172,6 +2176,15 @@ void P_PlayerThink (player_t *player) P_PoisonDamage (player, player->poisoner, 1, true); } + // [BC] Apply regeneration. + if (( level.time & 31 ) == 0 && ( player->cheats & CF_REGENERATION ) && ( player->health )) + { + if ( P_GiveBody( player->mo, 5 )) + { + S_Sound(player->mo, CHAN_ITEM, "*regenerate", 1, ATTN_NORM ); + } + } + // Handle air supply if (level.airsupply > 0) { @@ -2359,8 +2372,7 @@ void player_s::Serialize (FArchive &arc) << BlendB << BlendA << accuracy << stamina - << LogText - << Powers; + << LogText; for (i = 0; i < MAXPLAYERS; i++) arc << frags[i]; diff --git a/src/r_main.cpp b/src/r_main.cpp index 9aad0b3dc..ce1d0a5fe 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1073,7 +1073,7 @@ void R_SetupFrame (AActor *actor) iview->oviewangle = iview->nviewangle; } - if (player != NULL && + if (player != NULL && gamestate != GS_TITLELEVEL && ((player->cheats & CF_CHASECAM) || (r_deathcamera && camera->health <= 0)) && (camera->RenderStyle != STYLE_None) && !(camera->renderflags & RF_INVISIBLE) &&