gzdoom-last-svn/src/p_user.cpp

2508 lines
62 KiB
C++
Raw Normal View History

// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// This source is available for distribution and/or modification
// only under the terms of the DOOM Source Code License as
// published by id Software. All rights reserved.
//
// The source is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
// for more details.
//
// $Log:$
//
// DESCRIPTION:
// Player related stuff.
// Bobbing POV/weapon, movement.
// Pending weapon.
//
//-----------------------------------------------------------------------------
#include "templates.h"
#include "doomdef.h"
#include "d_event.h"
#include "p_local.h"
#include "doomstat.h"
#include "s_sound.h"
#include "i_system.h"
#include "r_draw.h"
#include "gi.h"
#include "m_random.h"
#include "p_pspr.h"
#include "p_enemy.h"
#include "p_effect.h"
#include "s_sound.h"
#include "a_sharedglobal.h"
#include "a_keys.h"
#include "statnums.h"
#include "v_palette.h"
#include "v_video.h"
#include "w_wad.h"
#include "cmdlib.h"
#include "sbar.h"
#include "f_finale.h"
#include "c_console.h"
#include "doomdef.h"
#include "c_dispatch.h"
#include "tarray.h"
#include "thingdef/thingdef.h"
static FRandom pr_skullpop ("SkullPop");
CUSTOM_CVAR(Float, maxviewpitch, 90.f, CVAR_ARCHIVE|CVAR_SERVERINFO)
{
if (self>90.f) self=90.f;
else if (self<-90.f) self=-90.f;
}
// [RH] # of ticks to complete a turn180
#define TURN180_TICKS ((TICRATE / 4) + 1)
// Variables for prediction
CVAR (Bool, cl_noprediction, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
static player_t PredictionPlayerBackup;
static BYTE PredictionActorBackup[sizeof(AActor)];
static TArray<sector_t *> PredictionTouchingSectorsBackup;
// [GRB] Custom player classes
TArray<FPlayerClass> PlayerClasses;
FPlayerClass::FPlayerClass ()
{
Type = NULL;
Flags = 0;
}
FPlayerClass::FPlayerClass (const FPlayerClass &other)
{
Type = other.Type;
Flags = other.Flags;
Skins = other.Skins;
}
FPlayerClass::~FPlayerClass ()
{
}
bool FPlayerClass::CheckSkin (int skin)
{
for (unsigned int i = 0; i < Skins.Size (); i++)
{
if (Skins[i] == skin)
return true;
}
return false;
}
void SetupPlayerClasses ()
{
FPlayerClass newclass;
newclass.Flags = 0;
if (gameinfo.gametype == GAME_Doom)
{
newclass.Type = PClass::FindClass (NAME_DoomPlayer);
PlayerClasses.Push (newclass);
}
else if (gameinfo.gametype == GAME_Heretic)
{
newclass.Type = PClass::FindClass (NAME_HereticPlayer);
PlayerClasses.Push (newclass);
}
else if (gameinfo.gametype == GAME_Hexen)
{
newclass.Type = PClass::FindClass (NAME_FighterPlayer);
PlayerClasses.Push (newclass);
newclass.Type = PClass::FindClass (NAME_ClericPlayer);
PlayerClasses.Push (newclass);
newclass.Type = PClass::FindClass (NAME_MagePlayer);
PlayerClasses.Push (newclass);
}
else if (gameinfo.gametype == GAME_Strife)
{
newclass.Type = PClass::FindClass (NAME_StrifePlayer);
PlayerClasses.Push (newclass);
}
}
CCMD (clearplayerclasses)
{
if (ParsingKeyConf)
{
PlayerClasses.Clear ();
}
}
CCMD (addplayerclass)
{
if (ParsingKeyConf && argv.argc () > 1)
{
const PClass *ti = PClass::FindClass (argv[1]);
if (!ti)
{
Printf ("Unknown player class '%s'\n", argv[1]);
}
else if (!ti->IsDescendantOf (RUNTIME_CLASS (APlayerPawn)))
{
Printf ("Invalid player class '%s'\n", argv[1]);
}
else if (ti->Meta.GetMetaString (APMETA_DisplayName) == NULL)
{
Printf ("Missing displayname for player class '%s'\n", argv[1]);
}
else
{
FPlayerClass newclass;
newclass.Type = ti;
newclass.Flags = 0;
int arg = 2;
while (arg < argv.argc ())
{
if (!stricmp (argv[arg], "nomenu"))
{
newclass.Flags |= PCF_NOMENU;
}
else
{
Printf ("Unknown flag '%s' for player class '%s'\n", argv[arg], argv[1]);
}
arg++;
}
PlayerClasses.Push (newclass);
}
}
}
CCMD (playerclasses)
{
for (unsigned int i = 0; i < PlayerClasses.Size (); i++)
{
Printf ("% 3d %s\n", i,
PlayerClasses[i].Type->Meta.GetMetaString (APMETA_DisplayName));
}
}
//
// Movement.
//
// 16 pixels of bob
#define MAXBOB 0x100000
bool onground;
// The player_s constructor. Since LogText is not a POD, we cannot just
// memset it all to 0.
player_s::player_s()
: mo(0),
playerstate(0),
cls(0),
DesiredFOV(0),
FOV(0),
viewz(0),
viewheight(0),
deltaviewheight(0),
bob(0),
momx(0),
momy(0),
centering(0),
turnticks(0),
oldbuttons(0),
attackdown(0),
health(0),
inventorytics(0),
CurrentPlayerClass(0),
pieces(0),
backpack(0),
fragcount(0),
lastkilltime(0),
multicount(0),
spreecount(0),
ReadyWeapon(0),
PendingWeapon(0),
cheats(0),
refire(0),
inconsistant(0),
killcount(0),
itemcount(0),
secretcount(0),
damagecount(0),
bonuscount(0),
hazardcount(0),
poisoncount(0),
poisoner(0),
attacker(0),
extralight(0),
morphTics(0),
Update to ZDoom r894: - Eliminated all use of global variables used as output for P_CheckPosition and P_TryMove. Moved BlockingLine and BlockingMobj into AActor because the global variables can be easily overwritten with certain DECORATE constructs. - Removed some unnecessary morphing code. - Fixed some bugs in the HIRESTEX parser. - Added floating point support and #include and #define tokens to FParseContext Not used yet. - replaced the value scanning code in FParseContext::GetToken with calls to strtol. - Changed XlatParseContext::FindToken to do a binary search over the valid token names. - Fixed: The check arrays for BlockThingsIterators were not properly freed and each iterator allocated a new one as a result. - Split the Xlat parser context class into a generic part that can be used for other Lemon-based parsers in the future and a smaller Xlat-specific part. - Changed: P_TeleportMove now always sets BlockingLine to NULL and P_FindFloorCeiling doesn't set it at all. The way it was set in PIT_FindFloorCeiling didn't look correct. (Note: It's amazing how easy it is to break P_TryMove et.al. with DECORATE if you just know which combinations of code pointers will cause problems. This definitely needs to be addressed.) - Changed P_FindFloorCeiling so that it doesn't need global variables anymore. I also moved the code to set the calling actor's information into this function because that's all it is used for. This also fixes another bug: - AInventory::BecomePickup called P_FindFloorCeiling to get proper position values for the item but never set the item's information to the return value of this call. - Removed the check for Heretic when playing *evillaugh when using the Chaos Device. This sound is not defined by the other games so it won't play by default. - Added MORPH_UNDOMORPHBYTOMEOFPOWER and MORPH_UNDOMORPHBYCHAOSDEVICE flags for the morph style so that the special behavior of these two items can be switched on and off. - Added Martin Howe's morph system enhancement. - Removed PT_EARLYOUT from P_PathTraverse because it wasn't used anywhere. - Rewrote BlockThingsIterator code not to use callbacks anymore. - Fixed: PIT_FindFloorCeiling required tmx and tmy to be set but P_FindFloorCeiling never did that. - Merged Check_Sides and PIT_CrossLine into A_PainShootSkull. - Replaced P_BlockLinesIterator with FBlockLinesIterator in all places it was used. This also allowed to remove all the global variable saving in P_CreateSecNodeList. - Added a new FBlockLinesIterator class that doesn't need a callback function because debugging the previous bug proved to be a bit annoying because it involved a P_BlockLinesIterator loop. - Fixed: The MBF code to move monsters away from dropoffs did not work as intended due to some random decisions in P_DoNewChaseDir. When in the avoiding dropoff mode these are ignored now. This should cure the problem that monsters hanging over a dropoff tended to drop down. - Added a NOTIMEFREEZE flag that excludes actors from being affected by the time freezer powerup. - Changed: Empty pickup messages are no longer printed. - Changed secret sector drawing in automap so that lines with the ML_SECRET flag are only drawn as part of a secret sector if that secret has already been found, even if the option is set to always show secret sectors. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@88 b0f79afe-0144-0410-b225-9a4edf0717df
2008-04-08 22:32:52 +00:00
MorphedPlayerClass(0),
MorphStyle(0),
MorphExitFlash(0),
PremorphWeapon(0),
chickenPeck(0),
jumpTics(0),
respawn_time(0),
camera(0),
air_finished(0),
accuracy(0),
stamina(0),
savedyaw(0),
savedpitch(0),
angle(0),
dest(0),
prev(0),
enemy(0),
missile(0),
mate(0),
last_mate(0),
t_active(0),
t_respawn(0),
t_strafe(0),
t_react(0),
t_fight(0),
t_roam(0),
t_rocket(0),
isbot(0),
first_shot(0),
sleft(0),
allround(0),
oldx(0),
oldy(0),
BlendR(0),
BlendG(0),
BlendB(0),
BlendA(0),
LogText(),
crouching(0),
crouchdir(0),
crouchfactor(0),
crouchoffset(0),
- Update to ZDoom r858: - Added FMOD_OPENONLY to the callback version of CreateStream() to prevent it from doing prebuffering of the song. This was causing the Linux version to hang while waiting for input from the pipe, since Timidity hadn't been started yet. I tried using a select call in the FillStream() method, but it always seems to return the pipe as having nothing available. Unfortunately, the game still falls all over itself if Timidity isn't available. Instead of execvp failing nicely, X errors kill the game. I don't know why it's doing that. My advice for Linux music: Skip Timidity++ and get a DLS patch set (/WINDOWS/system32/drivers/gm.dls is probably the most common by far) and set the snd_midipatchset cvar to point to it. It's faster and also sounds a whole lot better than the crappy freepats Ubuntu wants to install with Timidity++ (thank goodness I have the official patches from a real GUS so I don't need to use them). - GCC fixes. - Fixed: After starting new music the music volume has to be reset so that the song's relative volume takes effect. - Removed the arbitrary 1024 bytes limit when the file being played is a MIDI file. I had a D_DM2TTL that's only 990 bytes. - Restructured I_RegisterSong so that $mididevice works again and also supports selecting FMOD. - Added Jim' Linux fix. - Added MartinHowe's fix for mugshot display in status bars. - The garbage collector is now run one last time just before exiting the game. - Removed movie volume from the sound menu and renamed some of the other options to give the MIDI device name more room to display itself. - Moved the midi device selection into the main sound menu. - Added FMOD as MIDI device -1, to replace the MIDI mapper. This is still the default device. By default, it uses exactly the same DLS instruments as the Microsoft GS Wavetable Synth. If you have another set DLS level 1 patch set you want to use, set the snd_midipatchset cvar to specify where it should load the instruments from. - Changed the ProduceMIDI function to store its output into a TArray<BYTE>. An overloaded version wraps around it to continue to supply file-writing support for external Timidity++ usage. - Added an FMOD credits banner to comply with their non-commercial license. - Reimplemented the snd_buffersize cvar for the FMOD Ex sound system. Rather than a time in ms, this is now the length in samples of the DSP buffer. Also added the snd_buffercount cvar to offer complete control over the call to FMOD::System::setDSPBufferSize(). Note that with any snd_samplerate below about 44kHz, you will need to set snd_buffersize to avoid long latencies. - Reimplemented the snd_output cvar for the FMOD Ex sound system. - Changed snd_samplerate default to 0. This now means to use the default sample rate. - Made snd_output, snd_output_format, snd_speakermode, snd_resampler, and snd_hrtf available through the menu. - Split the HRTF effect selection into its own cvar: snd_hrtf. - Removed 96000 Hz option from the menu. It's still available through the cvar, if desired. - Fixed: If Windows sound init failed, retry with DirectSound. (Apparently, WASAPI doesn't work with more than two speakers and PCM-Float output at the same time.) - Fixed: Area sounds only played from the front speakers once you got within the 2D panning area. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@79 b0f79afe-0144-0410-b225-9a4edf0717df
2008-03-27 18:31:46 +00:00
crouchviewdelta(0),
ConversationNPC(0),
ConversationPC(0),
ConversationNPCAngle(0),
ConversationFaceTalker(0)
{
memset (&cmd, 0, sizeof(cmd));
memset (&userinfo, 0, sizeof(userinfo));
memset (frags, 0, sizeof(frags));
memset (psprites, 0, sizeof(psprites));
memset (&skill, 0, sizeof(skill));
}
// This function supplements the pointer cleanup in dobject.cpp, because
// player_s is not derived from DObject. (I tried it, and DestroyScan was
// unable to properly determine the player object's type--possibly
// because it gets staticly allocated in an array.)
//
// This function checks all the DObject pointers in a player_s and NULLs any
// that match the pointer passed in. If you add any pointers that point to
// DObject (or a subclass), add them here too.
size_t player_s::FixPointers (const DObject *old, DObject *rep)
{
APlayerPawn *replacement = static_cast<APlayerPawn *>(rep);
size_t changed = 0;
if (mo == old) mo = replacement, changed++;
if (poisoner == old) poisoner = replacement, changed++;
if (attacker == old) attacker = replacement, changed++;
if (camera == old) camera = replacement, changed++;
if (dest == old) dest = replacement, changed++;
if (prev == old) prev = replacement, changed++;
if (enemy == old) enemy = replacement, changed++;
if (missile == old) missile = replacement, changed++;
if (mate == old) mate = replacement, changed++;
if (last_mate == old) last_mate = replacement, changed++;
if (ReadyWeapon == old) ReadyWeapon = static_cast<AWeapon *>(rep), changed++;
if (PendingWeapon == old) PendingWeapon = static_cast<AWeapon *>(rep), changed++;
- Update to ZDoom r858: - Added FMOD_OPENONLY to the callback version of CreateStream() to prevent it from doing prebuffering of the song. This was causing the Linux version to hang while waiting for input from the pipe, since Timidity hadn't been started yet. I tried using a select call in the FillStream() method, but it always seems to return the pipe as having nothing available. Unfortunately, the game still falls all over itself if Timidity isn't available. Instead of execvp failing nicely, X errors kill the game. I don't know why it's doing that. My advice for Linux music: Skip Timidity++ and get a DLS patch set (/WINDOWS/system32/drivers/gm.dls is probably the most common by far) and set the snd_midipatchset cvar to point to it. It's faster and also sounds a whole lot better than the crappy freepats Ubuntu wants to install with Timidity++ (thank goodness I have the official patches from a real GUS so I don't need to use them). - GCC fixes. - Fixed: After starting new music the music volume has to be reset so that the song's relative volume takes effect. - Removed the arbitrary 1024 bytes limit when the file being played is a MIDI file. I had a D_DM2TTL that's only 990 bytes. - Restructured I_RegisterSong so that $mididevice works again and also supports selecting FMOD. - Added Jim' Linux fix. - Added MartinHowe's fix for mugshot display in status bars. - The garbage collector is now run one last time just before exiting the game. - Removed movie volume from the sound menu and renamed some of the other options to give the MIDI device name more room to display itself. - Moved the midi device selection into the main sound menu. - Added FMOD as MIDI device -1, to replace the MIDI mapper. This is still the default device. By default, it uses exactly the same DLS instruments as the Microsoft GS Wavetable Synth. If you have another set DLS level 1 patch set you want to use, set the snd_midipatchset cvar to specify where it should load the instruments from. - Changed the ProduceMIDI function to store its output into a TArray<BYTE>. An overloaded version wraps around it to continue to supply file-writing support for external Timidity++ usage. - Added an FMOD credits banner to comply with their non-commercial license. - Reimplemented the snd_buffersize cvar for the FMOD Ex sound system. Rather than a time in ms, this is now the length in samples of the DSP buffer. Also added the snd_buffercount cvar to offer complete control over the call to FMOD::System::setDSPBufferSize(). Note that with any snd_samplerate below about 44kHz, you will need to set snd_buffersize to avoid long latencies. - Reimplemented the snd_output cvar for the FMOD Ex sound system. - Changed snd_samplerate default to 0. This now means to use the default sample rate. - Made snd_output, snd_output_format, snd_speakermode, snd_resampler, and snd_hrtf available through the menu. - Split the HRTF effect selection into its own cvar: snd_hrtf. - Removed 96000 Hz option from the menu. It's still available through the cvar, if desired. - Fixed: If Windows sound init failed, retry with DirectSound. (Apparently, WASAPI doesn't work with more than two speakers and PCM-Float output at the same time.) - Fixed: Area sounds only played from the front speakers once you got within the 2D panning area. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@79 b0f79afe-0144-0410-b225-9a4edf0717df
2008-03-27 18:31:46 +00:00
if (ConversationNPC == old) ConversationNPC = replacement, changed++;
if (ConversationPC == old) ConversationPC = replacement, changed++;
return changed;
}
size_t player_s::PropagateMark()
{
GC::Mark(mo);
GC::Mark(poisoner);
GC::Mark(attacker);
GC::Mark(camera);
GC::Mark(dest);
GC::Mark(prev);
GC::Mark(enemy);
GC::Mark(missile);
GC::Mark(mate);
GC::Mark(last_mate);
GC::Mark(ReadyWeapon);
- Update to ZDoom r858: - Added FMOD_OPENONLY to the callback version of CreateStream() to prevent it from doing prebuffering of the song. This was causing the Linux version to hang while waiting for input from the pipe, since Timidity hadn't been started yet. I tried using a select call in the FillStream() method, but it always seems to return the pipe as having nothing available. Unfortunately, the game still falls all over itself if Timidity isn't available. Instead of execvp failing nicely, X errors kill the game. I don't know why it's doing that. My advice for Linux music: Skip Timidity++ and get a DLS patch set (/WINDOWS/system32/drivers/gm.dls is probably the most common by far) and set the snd_midipatchset cvar to point to it. It's faster and also sounds a whole lot better than the crappy freepats Ubuntu wants to install with Timidity++ (thank goodness I have the official patches from a real GUS so I don't need to use them). - GCC fixes. - Fixed: After starting new music the music volume has to be reset so that the song's relative volume takes effect. - Removed the arbitrary 1024 bytes limit when the file being played is a MIDI file. I had a D_DM2TTL that's only 990 bytes. - Restructured I_RegisterSong so that $mididevice works again and also supports selecting FMOD. - Added Jim' Linux fix. - Added MartinHowe's fix for mugshot display in status bars. - The garbage collector is now run one last time just before exiting the game. - Removed movie volume from the sound menu and renamed some of the other options to give the MIDI device name more room to display itself. - Moved the midi device selection into the main sound menu. - Added FMOD as MIDI device -1, to replace the MIDI mapper. This is still the default device. By default, it uses exactly the same DLS instruments as the Microsoft GS Wavetable Synth. If you have another set DLS level 1 patch set you want to use, set the snd_midipatchset cvar to specify where it should load the instruments from. - Changed the ProduceMIDI function to store its output into a TArray<BYTE>. An overloaded version wraps around it to continue to supply file-writing support for external Timidity++ usage. - Added an FMOD credits banner to comply with their non-commercial license. - Reimplemented the snd_buffersize cvar for the FMOD Ex sound system. Rather than a time in ms, this is now the length in samples of the DSP buffer. Also added the snd_buffercount cvar to offer complete control over the call to FMOD::System::setDSPBufferSize(). Note that with any snd_samplerate below about 44kHz, you will need to set snd_buffersize to avoid long latencies. - Reimplemented the snd_output cvar for the FMOD Ex sound system. - Changed snd_samplerate default to 0. This now means to use the default sample rate. - Made snd_output, snd_output_format, snd_speakermode, snd_resampler, and snd_hrtf available through the menu. - Split the HRTF effect selection into its own cvar: snd_hrtf. - Removed 96000 Hz option from the menu. It's still available through the cvar, if desired. - Fixed: If Windows sound init failed, retry with DirectSound. (Apparently, WASAPI doesn't work with more than two speakers and PCM-Float output at the same time.) - Fixed: Area sounds only played from the front speakers once you got within the 2D panning area. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@79 b0f79afe-0144-0410-b225-9a4edf0717df
2008-03-27 18:31:46 +00:00
GC::Mark(ConversationNPC);
GC::Mark(ConversationPC);
if (PendingWeapon != WP_NOCHANGE)
{
GC::Mark(PendingWeapon);
}
return sizeof(*this);
}
void player_s::SetLogNumber (int num)
{
char lumpname[16];
int lumpnum;
sprintf (lumpname, "LOG%d", num);
lumpnum = Wads.CheckNumForName (lumpname);
if (lumpnum == -1)
{
// Leave the log message alone if this one doesn't exist.
//SetLogText (lumpname);
}
else
{
int length=Wads.LumpLength(lumpnum);
char *data= new char[length+1];
Wads.ReadLump (lumpnum, data);
data[length]=0;
SetLogText (data);
delete[] data;
// Print log text to console
AddToConsole(-1, TEXTCOLOR_GOLD);
AddToConsole(-1, LogText);
AddToConsole(-1, "\n");
}
}
void player_s::SetLogText (const char *text)
{
LogText = text;
}
int player_t::GetSpawnClass()
{
const PClass * type = PlayerClasses[CurrentPlayerClass].Type;
return static_cast<APlayerPawn*>(GetDefaultByType(type))->SpawnMask;
}
//===========================================================================
//
// APlayerPawn
//
//===========================================================================
IMPLEMENT_POINTY_CLASS (APlayerPawn)
DECLARE_POINTER(InvFirst)
DECLARE_POINTER(InvSel)
END_POINTERS
BEGIN_STATELESS_DEFAULTS (APlayerPawn, Any, -1, 0)
PROP_SpawnHealth (100)
PROP_RadiusFixed (16)
PROP_HeightFixed (56)
PROP_Mass (100)
PROP_PainChance (255)
PROP_SpeedFixed (1)
PROP_Flags (MF_SOLID|MF_SHOOTABLE|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH|MF_FRIENDLY)
PROP_Flags2 (MF2_SLIDE|MF2_PASSMOBJ|MF2_PUSHWALL|MF2_FLOORCLIP|MF2_WINDTHRUST|MF2_TELESTOMP)
PROP_Flags3 (MF3_NOBLOCKMONST)
PROP_PlayerPawn_AttackZOffset (8)
// [GRB]
PROP_PlayerPawn_JumpZ (8*FRACUNIT)
PROP_PlayerPawn_ViewHeight (41*FRACUNIT)
PROP_PlayerPawn_ForwardMove1 (FRACUNIT)
PROP_PlayerPawn_ForwardMove2 (FRACUNIT)
PROP_PlayerPawn_SideMove1 (FRACUNIT)
PROP_PlayerPawn_SideMove2 (FRACUNIT)
PROP_PlayerPawn_ColorRange (0, 0)
PROP_PlayerPawn_SoundClass ("player")
- Fixed: The players were not added to FS's list of spawned things. - Update to ZDoom r882 - Added the option to use $ as a prefix to a string table name everywhere in MAPINFO where 'lookup' could be specified so that there is one consistent way to do it. - Externalized all default episode definitions. Added an 'optional' keyword to handle M4 and 5 in Doom and Heretic. - Added P_CheckMapData function and replaced all calls to P_OpenMapData that only checked for a map's presence with it. - Added Martin Howe's player statusbar face submission. - Added an 'adddefaultmap' option for MAPINFO. This is the same as 'defaultmap' but keeps all existing information in the default and just adds to it. This is needed because Hexen and Strife set some information in their base MAPINFO and using 'defaultmap' in a PWAD would override that. - Fixed: Using MAPINFO's f1 option could cause memory leaks. - Added option to load lumps by full name to several places: * Finale texts loaded from a text lump * Demos * Local SNDINFOs * Local SNDSEQs * Image names in FONTDEFS * intermission script names - Changed the STCFN121 handling. The character is not an 'I' but a '|' so instead of discarding it it should be inserted at position 124. - Renamed indexfont.fon to indexfont so that I could remove a special case from V_GetFont that was just added for this one font. - Added a 'dumpspawnedthings' CVAR that enables a listing of all things in the map and the actor type they spawned. SBarInfo Update #16 - Added: fillzeros flag for drawnumber. When set the string will always have a length of the specified size and zeros will fill in for the missing places. If the number is negative the negative sign will take the place of the last digit. - Added: globalarray type to drawnumber which will display the value in a global array with the index set to the player's number. Untested. - Added: isselected command to SBarInfo. - Fixed: Bi and Tri colored numbers didn't work. - Fixed: Crash when using nullimage as the last image in drawswitchableimage. - Applied Graf suggestion to include the y coord when calulating heights to fix most of the gaps caused by round off errors. At least for now anyways and it is only applied for drawimage. - SBarInfo inventory bars have been converted to use screen->DrawTexture() - Increased limit for demon/melee to 4. - Fixed: P_CheckSwitchRange accessed invalid memory when testing a one-sided line. - Fixed: P_SpawnPuff assumed that all melee attacks have the same range (MELEERANGE) and didn't set the puff to its melee state if the range was different. Even worse, it checked a global variable for this so the behavior was undefined when P_SpawnPuff was called from anywhere else but P_LineAttack. To reduce the amount of parameters I combined this information with the hitthing and temporary parameters into one flags parameter. Also changed P_LineAttack so that it gets passed an additional parameter that specifies whether the attack is a melee attack or not and set this to true in all calls that are to be considered melee attacks. I couldn't use the damage type because A_CustomPunch and A_CustomMeleeAttack allow passing any damage type they want. - Added a sprite option as an alternative of particles for FX_ROCKET and FX_GRENADE. - Fixed: The minimum parameter count for ACS_Execute and ACS_ExecuteAlways for DECORATE was wrong (2 instead of 1.) - Changed: Hexen set every cluster to be a hub if it hadn't been defined before a level using this cluster. Now it will only do that if HexenHack is true, i.e. when original Hexen format MAPINFOs are parsed. For ZDoom format MAPINFOs it will now be the same as for the other games which means that 'hub' has to be declared explicitly. - Added an Idle state that is entered in place of the spawn state if a monster has to return to its inactive state if it can't find any more targets. - Added MF5_NOINTERACTION flag which completely disables all physics related code for any actor with this flag. Mostly useful for particle effects where the actors just move a certain distance and then disappear. - Removed the last remains of the antialias precalculation code from am_map.cpp because it was no longer used. - Fixed: Two-sided lines bordering a secret sector were not drawn in the proper color - Fixed: The automap didn't check ACS_LockedExecuteDoor for its lock color. - Switched sounds local to the listener from head-relative 3D sounds to 2D sounds so stereo sounds have full separation. I tried using set3DSpread, but that still caused some blending of the channels. - Changed FScanner so that opening a lump gives the complete wad+lump name rather than a generic one, so identifying errors among files that all have the same lump name no longer involves any degree of guesswork in determining exactly which file the error occurred in. - Added a check to S_ParseSndSeq() for SNDSEQ lumps with unterminated final sequences. - Fixed: Parts of s_sndseq.cpp that scan the Sequences array need NULL pointer checks, in case an improper sequence was encountered during parsing but not early enough to avoid creating a slot for it in the array. - Added support for dumping from RAW/DRO/IMF files, so now anything that can be played as OPL can also be dumped. - Removed the opl_enable cvar, since OPL playback is now selectable as just another MIDI device. - Added support for DRO playback and dual-chip RAW playback. - Removed MUS support from OPLMUSSong, since using the OPLMIDIDevice with MUSSong2 works just as well. There are still lots of leftover bits in the class that should probably be removed at some point, too. - Added dual-chip dumping support for the RAW format. - Added DosBox Raw OPL (.DRO) dumping support. For whatever reason, in_adlib calculates the song length for this format wrong, even though the exact length is stored right in the header. (But in_adlib seems buggy in general; too bad it's the only Windows version of Adplug that seems to exist.) - Rewrote the OPL dumper to work with MIDI as well as MUS. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@86 b0f79afe-0144-0410-b225-9a4edf0717df
2008-04-05 13:28:48 +00:00
PROP_PlayerPawn_Face ("None")
PROP_PlayerPawn_MorphWeapon ("None")
END_DEFAULTS
IMPLEMENT_STATELESS_ACTOR (APlayerChunk, Any, -1, 0)
PROP_Flags (MF_DROPOFF)
PROP_Flags2 (MF2_PASSMOBJ)
END_DEFAULTS
void APlayerPawn::Serialize (FArchive &arc)
{
Super::Serialize (arc);
arc << JumpZ
<< MaxHealth
<< RunHealth
<< SpawnMask
<< ForwardMove1
<< ForwardMove2
<< SideMove1
<< SideMove2
<< ScoreIcon
<< InvFirst
<< InvSel
<< MorphWeapon;
}
//===========================================================================
//
// APlayerPawn :: BeginPlay
//
//===========================================================================
void APlayerPawn::BeginPlay ()
{
Super::BeginPlay ();
ChangeStatNum (STAT_PLAYER);
// Check whether a PWADs normal sprite is to be combined with the base WADs
// crouch sprite. In such a case the sprites normally don't match and it is
// best to disable the crouch sprite.
if (crouchsprite > 0)
{
// This assumes that player sprites always exist in rotated form and
// that the front view is always a separate sprite. So far this is
// true for anything that exists.
FString normspritename = sprites[SpawnState->sprite.index].name;
FString crouchspritename = sprites[crouchsprite].name;
int spritenorm = Wads.CheckNumForName(normspritename + "A1", ns_sprites);
int spritecrouch = Wads.CheckNumForName(crouchspritename + "A1", ns_sprites);
if (spritenorm==-1 || spritecrouch ==-1)
{
// Sprites do not exist so it is best to disable the crouch sprite.
crouchsprite = 0;
return;
}
int wadnorm = Wads.GetLumpFile(spritenorm);
int wadcrouch = Wads.GetLumpFile(spritenorm);
if (wadnorm > FWadCollection::IWAD_FILENUM && wadcrouch <= FWadCollection::IWAD_FILENUM)
{
// Question: Add an option / disable crouching or do what?
crouchsprite = 0;
}
}
}
//===========================================================================
//
// APlayerPawn :: Tick
//
//===========================================================================
void APlayerPawn::Tick()
{
if (player != NULL && player->mo == this && player->morphTics == 0 && player->playerstate != PST_DEAD)
{
height = FixedMul(GetDefault()->height, player->crouchfactor);
}
else
{
if (health > 0) height = GetDefault()->height;
}
Super::Tick();
}
//===========================================================================
//
// APlayerPawn :: AddInventory
//
//===========================================================================
void APlayerPawn::AddInventory (AInventory *item)
{
// Adding inventory to a voodoo doll should add it to the real player instead.
if (player != NULL && player->mo != this && player->mo != NULL)
{
player->mo->AddInventory (item);
return;
}
Super::AddInventory (item);
// If nothing is selected, select this item.
if (InvSel == NULL && (item->ItemFlags & IF_INVBAR))
{
InvSel = item;
}
}
//===========================================================================
//
// APlayerPawn :: RemoveInventory
//
//===========================================================================
void APlayerPawn::RemoveInventory (AInventory *item)
{
bool pickWeap = false;
// Since voodoo dolls aren't supposed to have an inventory, there should be
// no need to redirect them to the real player here as there is with AddInventory.
// If the item removed is the selected one, select something else, either the next
// item, if there is one, or the previous item.
if (player != NULL)
{
if (InvSel == item)
{
InvSel = item->NextInv ();
if (InvSel == NULL)
{
InvSel = item->PrevInv ();
}
}
if (InvFirst == item)
{
InvFirst = item->NextInv ();
if (InvFirst == NULL)
{
InvFirst = item->PrevInv ();
}
}
if (item == player->PendingWeapon)
{
player->PendingWeapon = WP_NOCHANGE;
}
if (item == player->ReadyWeapon)
{
// If the current weapon is removed, clear the refire counter and pick a new one.
pickWeap = true;
player->ReadyWeapon = NULL;
player->refire = 0;
}
}
Super::RemoveInventory (item);
if (pickWeap && player->mo == this && player->PendingWeapon == WP_NOCHANGE)
{
PickNewWeapon (NULL);
}
}
//===========================================================================
//
// APlayerPawn :: UseInventory
//
//===========================================================================
bool APlayerPawn::UseInventory (AInventory *item)
{
const PClass *itemtype = item->GetClass();
if (player->cheats & CF_TOTALLYFROZEN)
{ // You can't use items if you're totally frozen
return false;
}
if (!Super::UseInventory (item))
{
// Heretic and Hexen advance the inventory cursor if the use failed.
// Should this behavior be retained?
return false;
}
if (player == &players[consoleplayer])
{
S_SoundID (this, CHAN_ITEM, item->UseSound, 1, ATTN_NORM);
StatusBar->FlashItem (itemtype);
}
return true;
}
//===========================================================================
//
// APlayerPawn :: BestWeapon
//
// Returns the best weapon a player has, possibly restricted to a single
// type of ammo.
//
//===========================================================================
AWeapon *APlayerPawn::BestWeapon (const PClass *ammotype)
{
AWeapon *bestMatch = NULL;
int bestOrder = INT_MAX;
AInventory *item;
AWeapon *weap;
bool tomed = NULL != FindInventory (RUNTIME_CLASS(APowerWeaponLevel2));
// Find the best weapon the player has.
for (item = Inventory; item != NULL; item = item->Inventory)
{
if (!item->IsKindOf (RUNTIME_CLASS(AWeapon)))
continue;
weap = static_cast<AWeapon *> (item);
// Don't select it if it's worse than what was already found.
if (weap->SelectionOrder > bestOrder)
continue;
// Don't select it if its primary fire doesn't use the desired ammo.
if (ammotype != NULL &&
(weap->Ammo1 == NULL ||
weap->Ammo1->GetClass() != ammotype))
continue;
// Don't select it if the Tome is active and this isn't the powered-up version.
if (tomed && weap->SisterWeapon != NULL && weap->SisterWeapon->WeaponFlags & WIF_POWERED_UP)
continue;
// Don't select it if it's powered-up and the Tome is not active.
if (!tomed && weap->WeaponFlags & WIF_POWERED_UP)
continue;
// Don't select it if there isn't enough ammo to use its primary fire.
if (!(weap->WeaponFlags & WIF_AMMO_OPTIONAL) &&
!weap->CheckAmmo (AWeapon::PrimaryFire, false))
continue;
// This weapon is usable!
bestOrder = weap->SelectionOrder;
bestMatch = weap;
}
return bestMatch;
}
//===========================================================================
//
// APlayerPawn :: PickNewWeapon
//
// Picks a new weapon for this player. Used mostly for running out of ammo,
// but it also works when an ACS script explicitly takes the ready weapon
// away or the player picks up some ammo they had previously run out of.
//
//===========================================================================
AWeapon *APlayerPawn::PickNewWeapon (const PClass *ammotype)
{
AWeapon *best = BestWeapon (ammotype);
if (best != NULL)
{
player->PendingWeapon = best;
if (player->ReadyWeapon != NULL)
{
P_SetPsprite (player, ps_weapon, player->ReadyWeapon->GetDownState());
}
else if (player->PendingWeapon != WP_NOCHANGE)
{
P_BringUpWeapon (player);
}
}
return best;
}
//===========================================================================
//
// APlayerPawn :: GiveDeathmatchInventory
//
// Gives players items they should have in addition to their default
// inventory when playing deathmatch. (i.e. all keys)
//
//===========================================================================
void APlayerPawn::GiveDeathmatchInventory()
{
for (unsigned int i = 0; i < PClass::m_Types.Size(); ++i)
{
if (PClass::m_Types[i]->IsDescendantOf (RUNTIME_CLASS(AKey)))
{
AKey *key = (AKey *)GetDefaultByType (PClass::m_Types[i]);
if (key->KeyNumber != 0)
{
key = static_cast<AKey *>(Spawn (PClass::m_Types[i], 0,0,0, NO_REPLACE));
if (!key->TryPickup (this))
{
key->Destroy ();
}
}
}
}
}
//===========================================================================
//
// APlayerPawn :: FilterCoopRespawnInventory
//
// When respawning in coop, this function is called to walk through the dead
// player's inventory and modify it according to the current game flags so
// that it can be transferred to the new live player. This player currently
// has the default inventory, and the oldplayer has the inventory at the time
// of death.
//
//===========================================================================
void APlayerPawn::FilterCoopRespawnInventory (APlayerPawn *oldplayer)
{
AInventory *item, *next, *defitem;
// If we're losing everything, this is really simple.
if (dmflags & DF_COOP_LOSE_INVENTORY)
{
oldplayer->DestroyAllInventory();
return;
}
// If we don't want to lose anything, then we don't need to bother checking
// the old inventory.
if (dmflags & (DF_COOP_LOSE_KEYS |
DF_COOP_LOSE_WEAPONS |
DF_COOP_LOSE_AMMO |
DF_COOP_HALVE_AMMO |
DF_COOP_LOSE_ARMOR |
DF_COOP_LOSE_POWERUPS))
{
// Walk through the old player's inventory and destroy or modify
// according to dmflags.
for (item = oldplayer->Inventory; item != NULL; item = next)
{
next = item->Inventory;
// If this item is part of the default inventory, we never want
// to destroy it, although we might want to copy the default
// inventory amount.
defitem = FindInventory (item->GetClass());
if ((dmflags & DF_COOP_LOSE_KEYS) &&
defitem == NULL &&
item->IsKindOf(RUNTIME_CLASS(AKey)))
{
item->Destroy();
}
else if ((dmflags & DF_COOP_LOSE_WEAPONS) &&
defitem == NULL &&
item->IsKindOf(RUNTIME_CLASS(AWeapon)))
{
item->Destroy();
}
else if ((dmflags & DF_COOP_LOSE_ARMOR) &&
defitem == NULL &&
item->IsKindOf(RUNTIME_CLASS(AArmor)))
{
item->Destroy();
}
else if ((dmflags & DF_COOP_LOSE_POWERUPS) &&
defitem == NULL &&
item->IsKindOf(RUNTIME_CLASS(APowerupGiver)))
{
item->Destroy();
}
else if ((dmflags & (DF_COOP_LOSE_AMMO | DF_COOP_HALVE_AMMO)) &&
item->IsKindOf(RUNTIME_CLASS(AAmmo)))
{
if (defitem == NULL)
{
if (dmflags & DF_COOP_LOSE_AMMO)
{
// Do NOT destroy the ammo, because a weapon might reference it.
item->Amount = 0;
}
else if (item->Amount > 1)
{
item->Amount /= 2;
}
}
else
{
// When set to lose ammo, you get to keep all your starting ammo.
// When set to halve ammo, you won't be left with less than your starting amount.
if (dmflags & DF_COOP_LOSE_AMMO)
{
item->Amount = defitem->Amount;
}
else if (item->Amount > 1)
{
item->Amount = MAX(item->Amount / 2, defitem->Amount);
}
}
}
}
}
// Now destroy the default inventory this player is holding and move
// over the old player's remaining inventory.
DestroyAllInventory();
ObtainInventory (oldplayer);
player->ReadyWeapon = NULL;
PickNewWeapon (NULL);
}
//===========================================================================
//
// APlayerPawn :: GetSoundClass
//
//===========================================================================
const char *APlayerPawn::GetSoundClass ()
{
if (player != NULL &&
(unsigned int)player->userinfo.skin >= PlayerClasses.Size () &&
(size_t)player->userinfo.skin < numskins)
{
return skins[player->userinfo.skin].name;
}
// [GRB]
const char *sclass = GetClass ()->Meta.GetMetaString (APMETA_SoundClass);
return sclass != NULL ? sclass : "player";
}
//===========================================================================
//
// APlayerPawn :: GetMaxHealth
//
// only needed because Boom screwed up Dehacked.
//
//===========================================================================
int APlayerPawn::GetMaxHealth() const
{
return MaxHealth > 0? MaxHealth : ((i_compatflags&COMPATF_DEHHEALTH)? 100 : deh.MaxHealth);
}
//===========================================================================
//
// APlayerPawn :: UpdateWaterLevel
//
// Plays surfacing and diving sounds, as appropriate.
//
//===========================================================================
bool APlayerPawn::UpdateWaterLevel (fixed_t oldz, bool splash)
{
int oldlevel = waterlevel;
bool retval = Super::UpdateWaterLevel (oldz, splash);
if (player != NULL)
{
if (oldlevel < 3 && waterlevel == 3)
{ // Our head just went under.
S_Sound (this, CHAN_VOICE, "*dive", 1, ATTN_NORM);
}
else if (oldlevel == 3 && waterlevel < 3)
{ // Our head just came up.
if (player->air_finished > level.time)
{ // We hadn't run out of air yet.
S_Sound (this, CHAN_VOICE, "*surface", 1, ATTN_NORM);
}
// If we were running out of air, then ResetAirSupply() will play *gasp.
}
}
return retval;
}
//===========================================================================
//
// APlayerPawn :: ResetAirSupply
//
// Gives the player a full "tank" of air. If they had previously completely
// run out of air, also plays the *gasp sound. Returns true if the player
// was drowning.
//
//===========================================================================
bool APlayerPawn::ResetAirSupply ()
{
bool wasdrowning = (player->air_finished < level.time);
if (wasdrowning)
{
S_Sound (this, CHAN_VOICE, "*gasp", 1, ATTN_NORM);
}
player->air_finished = level.time + level.airsupply;
return wasdrowning;
}
//===========================================================================
//
// Animations
//
//===========================================================================
void APlayerPawn::PlayIdle ()
{
if (InStateSequence(state, SeeState))
SetState (SpawnState);
}
void APlayerPawn::PlayRunning ()
{
if (InStateSequence(state, SpawnState) && SeeState != NULL)
SetState (SeeState);
}
void APlayerPawn::PlayAttacking ()
{
if (MissileState != NULL) SetState (MissileState);
}
void APlayerPawn::PlayAttacking2 ()
{
if (MeleeState != NULL) SetState (MeleeState);
}
void APlayerPawn::ThrowPoisonBag ()
{
}
//===========================================================================
//
// APlayerPawn :: GiveDefaultInventory
//
//===========================================================================
void APlayerPawn::GiveDefaultInventory ()
{
// [GRB] Give inventory specified in DECORATE
player->health = GetDefault ()->health;
// HexenArmor must always be the first item in the inventory because
// it provides player class based protection that should not affect
// any other protection item.
fixed_t hx[5];
for(int i=0;i<5;i++)
{
hx[i] = GetClass()->Meta.GetMetaFixed(APMETA_Hexenarmor0+i);
}
GiveInventoryType (RUNTIME_CLASS(AHexenArmor));
AHexenArmor *harmor = FindInventory<AHexenArmor>();
harmor->Slots[4] = hx[0];
harmor->SlotsIncrement[0] = hx[1];
harmor->SlotsIncrement[1] = hx[2];
harmor->SlotsIncrement[2] = hx[3];
harmor->SlotsIncrement[3] = hx[4];
// BasicArmor must come right after that. It should not affect any
// other protection item as well but needs to process the damage
// before the HexenArmor does.
ABasicArmor *barmor = Spawn<ABasicArmor> (0,0,0, NO_REPLACE);
barmor->BecomeItem ();
barmor->SavePercent = 0;
barmor->Amount = 0;
AddInventory (barmor);
// Now add the items from the DECORATE definition
FDropItem *di = GetDropItems(RUNTIME_TYPE(this));
while (di)
{
const PClass *ti = PClass::FindClass (di->Name);
if (ti)
{
AInventory *item = FindInventory (ti);
if (item != NULL)
{
item->Amount = clamp<int>(
item->Amount + (di->amount ? di->amount : ((AInventory *)item->GetDefault ())->Amount),
0, item->MaxAmount);
}
else
{
item = static_cast<AInventory *>(Spawn (ti, 0,0,0, NO_REPLACE));
item->ItemFlags|=IF_IGNORESKILL; // no skill multiplicators here
item->Amount = di->amount;
if (item->IsKindOf (RUNTIME_CLASS (AWeapon)))
{
// To allow better control any weapon is emptied of
// ammo before being given to the player.
static_cast<AWeapon*>(item)->AmmoGive1 =
static_cast<AWeapon*>(item)->AmmoGive2 = 0;
}
if (!item->TryPickup(this))
{
item->Destroy ();
item = NULL;
}
}
if (item != NULL && item->IsKindOf (RUNTIME_CLASS (AWeapon)) &&
static_cast<AWeapon*>(item)->CheckAmmo(AWeapon::EitherFire, false))
{
player->ReadyWeapon = player->PendingWeapon = static_cast<AWeapon *> (item);
}
}
di = di->Next;
}
}
void APlayerPawn::MorphPlayerThink ()
{
}
void APlayerPawn::ActivateMorphWeapon ()
{
const PClass *morphweapon = PClass::FindClass (MorphWeapon);
player->PendingWeapon = WP_NOCHANGE;
player->psprites[ps_weapon].sy = WEAPONTOP;
if (morphweapon == NULL || !morphweapon->IsDescendantOf (RUNTIME_CLASS(AWeapon)))
{ // No weapon at all while morphed!
player->ReadyWeapon = NULL;
P_SetPsprite (player, ps_weapon, NULL);
}
else
{
player->ReadyWeapon = static_cast<AWeapon *>(player->mo->FindInventory (morphweapon));
if (player->ReadyWeapon == NULL)
{
player->ReadyWeapon = static_cast<AWeapon *>(player->mo->GiveInventoryType (morphweapon));
Update to ZDoom r922: - Added Martin Howe's fixes for morphing and DECORATE function prototypes. - Minor fixes in texture code. - Fixed: The FMOD::System object was never released, only closed, so snd_reset would eventually run into the hard limit on the total number of FMOD::System objects that can be created concurrently (currently 15). - Added proper error checks to the FMOD initialization process. - Updated fmod_wrap.h for FMOD 4.14. - Set note velocity back to using a linear sounding volume curve, although it's now used to scale channel volume and expression, so recompute_amp() is still only doing one volume curve lookup. - Fixed: TimidityMIDIDevice caused a crash at the end of a non-looping song. - Made translation support for multipatch textures operational. - Added support for the GUS patch format's scale_frequency and scale_factor parameters. These seem to be used primarily to restrict percussion instruments to specific notes. - Changed note velocity to not use the volume curve in recompute_amp(), since this sounds closer to TiMidity++, although I don't believe it's correct MIDI behavior. Also changed expression so that it scales the channel volume before going through the curve. - Reworked load_instrument() to be less opaque. - Went through the TiMidity code and removed pretty much all of the SDL_mixer extensions. The only exception would be kill_others(), which I reworked into a kill_key_group() function, which should be useful for DLS instruments in the future. - Added translation support to multipatch textures. Not tested yet! - Added Martin Howe's morph weapon update. - Changed true color texture creation to use a newly defined Bitmap class instead of having the copy functions in the frame buffer class. - Fixed: The WolfSS didn't have its obituary defined. - Added submission for ACS CheckPlayerCamera ACS function. - Removed FRadiusThingsIterator after discovering that VC++ misoptimized it in P_CheckPosition. Now FBlockThingsIterator is used with the distance check being done manually. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@94 b0f79afe-0144-0410-b225-9a4edf0717df
2008-04-17 20:58:50 +00:00
if (player->ReadyWeapon != NULL)
{
player->ReadyWeapon->GivenAsMorphWeapon = true; // flag is used only by new beastweap semantics in P_UndoPlayerMorph
}
}
if (player->ReadyWeapon != NULL)
{
P_SetPsprite (player, ps_weapon, player->ReadyWeapon->GetReadyState());
}
else
{
P_SetPsprite (player, ps_weapon, NULL);
}
}
P_SetPsprite (player, ps_flash, NULL);
Update to ZDoom r905: - Added Martin Howe's morph system update. - Added support for defining composite textures in HIRESTEX. It is not fully tested and right now can't do much more than the old TEXTUREx method. - Added a few NULL pointer checks to the texture code. - Made duplicate class names in DECORATE non-fatal. There is really no stability concern here and the worst that can happen is that the wrong actor is spawned. This was a constant hassle when testing with WADs that contain duplicate resources. - Removed some GCC warnings. - Fixed: MinGW doesn't have _get_pgmptr(), so it couldn't compile i_main.cpp. - Fixed: MOD_WAVETABLE and MOD_SWSYNTH are not defined by w32api, so MinGW failed compiling the new MIDI code. - Fixed: LocalSndInfo and LocalSndSeq in S_Start() need to be const char pointers, since "" is a constant. - Fixed: parsecontext.h was missing a newline at the end of the file. - Fixed: Timidity::Channel::mono, rpn, and nrpn were not initialized. In particular, this meant that every channel was almost certainly in mono mode, which can sound pretty bad if the song isn't meant to be played that way. - Added bank numbers to the MIDI precaching for Timidity, since I guess I do need to care about banks, if even the Duke MIDIs use various banks. - Fixed: snd_midiprecache only exists in Win32 builds, so gameconfigfile.cpp shouldn't unconditionally link against it. - Fixed: pre_resample() was still disabled, and it left two samples at the end of the new wave data uninitialized. - Moved the xmap table from timidity/tables.cpp to playmidi.cpp. Now I can get rid of timidity/tables.cpp, which conflicts in name with the main Doom tables.cpp. (And interestingly, VC++ automatically renamed the object file, so I wasn't aware of the problem with GCC.) - Added a Gets function to the FileReader class which I planned to use to enable Timidity to read its config and sound patches from Zips. I put this on hold though after finding out that the sound quality isn't even near that of Timidity++. - GCC-Fixes (FString::GetChars() for Printf calls) - Added a dummy Weapon.NOLMS flag so that Skulltag weapons using this flag can be loaded - Changed the MIDIStreamer to send the all notes off controller to each channel when restarting the song, rather than emitting a single note off event which only has 1 in 127 chance of being for a note that's playing on that channel. Then I decided it would probably be a good idea to reset all the controllers as well. - Increasing the size of the internal Timidity stream buffer from 1/14 sec (copied from the OPL player) improved its sound dramatically, so apparently Timidity has issues with short stream buffers. It's now at 1/2 sec in length. However, there seems to be something weird going on with corazonazul_ff6boss.mid near the beginning where it stops and immediately restarts a guitar on the exact same note. - Added a new sound debugging cvar: snd_drawoutput, which can show various oscilloscopes and spectrums. - Eliminated some more global variables (onmobj, DoRipping, LastRipped, MissileActor, bulletpitch and linetarget.) - Internal TiMidity now plays music. Unfortunately, it doesn't sound right. :( - Changed the progdir global variable into an FString. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@90 b0f79afe-0144-0410-b225-9a4edf0717df
2008-04-12 18:59:23 +00:00
player->PendingWeapon = WP_NOCHANGE;
}
//===========================================================================
//
// APlayerPawn :: Die
//
//===========================================================================
void APlayerPawn::Die (AActor *source, AActor *inflictor)
{
Super::Die (source, inflictor);
if (player != NULL && player->mo == this) player->bonuscount = 0;
if (player != NULL && player->mo != this)
{ // Make the real player die, too
player->mo->Die (source, inflictor);
}
else
{
if (player != NULL && (dmflags2 & DF2_YES_WEAPONDROP))
{ // Voodoo dolls don't drop weapons
AWeapon *weap = player->ReadyWeapon;
if (weap != NULL)
{
AInventory *item;
if (weap->SpawnState != NULL &&
weap->SpawnState != &AActor::States[0] &&
weap->SpawnState != &AActor::States[AActor::S_NULL])
{
item = P_DropItem (this, weap->GetClass(), -1, 256);
if (item != NULL)
{
if (weap->AmmoGive1 && weap->Ammo1)
{
static_cast<AWeapon *>(item)->AmmoGive1 = weap->Ammo1->Amount;
}
if (weap->AmmoGive2 && weap->Ammo2)
{
static_cast<AWeapon *>(item)->AmmoGive2 = weap->Ammo2->Amount;
}
- Fixed: Fog for flooding floor textures into gaps created by missing wall textures didn't work since a parameter changes necessitated by ZDoom's render style 'enhancement'. Update to ZDoom r940: SBarInfo Update #18: - Simplified the DrawGraphic function in sbarinfo_display.cpp - Added xOffset, yOffset, and alpha to every drawing function in sbarinfo_display.cpp. So Strife popups can be handeled better and allow for other effects (translucent bars?). I'm thinking about making a struct for these five (also x and y) arguments so that the argument lists don't become a mess. - Changed DRAWIMAGE in sbarinfo_display.cpp to not use so many calls to DrawGraphic. - DrawKeyBar wasn't using screen->DrawTexture. - Added a Fade transition for popups. It takes two args fade in rate and fade out rate. Both are floats (1.0 = 1 tic to complete 0.5 = 2 tics to complete and so on). - Added a translucency arg to statusbars. 1.0 = opaque and 0.0 = invisible. - Fixed: When an instrument's envelope runs out, it does not immediately ramp to zero. Rather, it lets the remainder of the sample finish playing. - Fixed: When playing a MIDI file with EMIDI track designations to turn a track off, any ticks that had only events on the disabled track would cause the delay for that track to be thrown away, and the following notes on enabled tracks would play too soon. This could be heard quite clearly in xplasma.mid, where track 4 (FMGlass Drone 1) would interfere with the timing of tracks 13 and 14 (EP1 Melody and EP1 Echo). - Fixed: DFlashFader did some operations in its destructor that had to be moved to its Destroy method. - Fixed: Dropped weapons from dying players should not double ammo. - Fixed: When note_on() is called and another copy of the same note is already playing on the channel, it should stop it with finish_note(), not kill_note(). This can be clearly heard in the final cymbal crashes of D_DM2TTL where TiMidity cuts them off because the final cymbals are played with a velocity of 1 before the preceding cymbals have finished. (I wonder if I should be setting the self_nonexclusive flag for GUS patches to disable even this behavior, though, since gf1note.c doesn't turn off duplicate notes.) - Changed envelope handling to hopefully match the GUS player's. The most egregious mistake TiMidity makes is to treat bit 6 as an envelope enable bit. This is not what it does; every sample has an envelope. Rather, this is a "no sampled release" flag. Also, despite fiddling with the PATCH_SUSTAIN flag during instrument loading, TiMidity never actually used it. Nor did it do anything at all with the PATCH_FAST_REL flag. - Fixed: wbstartstruct's lump name fields were only 8 characters long and not properly zero-terminated when all 8 characters were used. - Fixed: Local sound sequence definitions caused a crash because a proper NULL check was missing. - Added translucent blending modes to FMultipatchTexture (not tested yet!) - Also changed all true color texture creation functions to use proper alpha values instead of inverted ones. - Changed FRemapTable so that all palette entries must contain proper alpha values. - Fixed: The F1 screen check in m_menu.cpp was missing a NULL pointer check. - Changed: The boss brain's explosions play weapons/rocklx which is an unlimited sound. This can become extremely loud. Replaced with a new sound which is just an alias to weapons/rocklx but has a limit of 4. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@98 b0f79afe-0144-0410-b225-9a4edf0717df
2008-04-25 10:00:54 +00:00
item->ItemFlags |= IF_IGNORESKILL;
}
}
else
{
item = P_DropItem (this, weap->AmmoType1, -1, 256);
if (item != NULL)
{
item->Amount = weap->Ammo1->Amount;
- Fixed: Fog for flooding floor textures into gaps created by missing wall textures didn't work since a parameter changes necessitated by ZDoom's render style 'enhancement'. Update to ZDoom r940: SBarInfo Update #18: - Simplified the DrawGraphic function in sbarinfo_display.cpp - Added xOffset, yOffset, and alpha to every drawing function in sbarinfo_display.cpp. So Strife popups can be handeled better and allow for other effects (translucent bars?). I'm thinking about making a struct for these five (also x and y) arguments so that the argument lists don't become a mess. - Changed DRAWIMAGE in sbarinfo_display.cpp to not use so many calls to DrawGraphic. - DrawKeyBar wasn't using screen->DrawTexture. - Added a Fade transition for popups. It takes two args fade in rate and fade out rate. Both are floats (1.0 = 1 tic to complete 0.5 = 2 tics to complete and so on). - Added a translucency arg to statusbars. 1.0 = opaque and 0.0 = invisible. - Fixed: When an instrument's envelope runs out, it does not immediately ramp to zero. Rather, it lets the remainder of the sample finish playing. - Fixed: When playing a MIDI file with EMIDI track designations to turn a track off, any ticks that had only events on the disabled track would cause the delay for that track to be thrown away, and the following notes on enabled tracks would play too soon. This could be heard quite clearly in xplasma.mid, where track 4 (FMGlass Drone 1) would interfere with the timing of tracks 13 and 14 (EP1 Melody and EP1 Echo). - Fixed: DFlashFader did some operations in its destructor that had to be moved to its Destroy method. - Fixed: Dropped weapons from dying players should not double ammo. - Fixed: When note_on() is called and another copy of the same note is already playing on the channel, it should stop it with finish_note(), not kill_note(). This can be clearly heard in the final cymbal crashes of D_DM2TTL where TiMidity cuts them off because the final cymbals are played with a velocity of 1 before the preceding cymbals have finished. (I wonder if I should be setting the self_nonexclusive flag for GUS patches to disable even this behavior, though, since gf1note.c doesn't turn off duplicate notes.) - Changed envelope handling to hopefully match the GUS player's. The most egregious mistake TiMidity makes is to treat bit 6 as an envelope enable bit. This is not what it does; every sample has an envelope. Rather, this is a "no sampled release" flag. Also, despite fiddling with the PATCH_SUSTAIN flag during instrument loading, TiMidity never actually used it. Nor did it do anything at all with the PATCH_FAST_REL flag. - Fixed: wbstartstruct's lump name fields were only 8 characters long and not properly zero-terminated when all 8 characters were used. - Fixed: Local sound sequence definitions caused a crash because a proper NULL check was missing. - Added translucent blending modes to FMultipatchTexture (not tested yet!) - Also changed all true color texture creation functions to use proper alpha values instead of inverted ones. - Changed FRemapTable so that all palette entries must contain proper alpha values. - Fixed: The F1 screen check in m_menu.cpp was missing a NULL pointer check. - Changed: The boss brain's explosions play weapons/rocklx which is an unlimited sound. This can become extremely loud. Replaced with a new sound which is just an alias to weapons/rocklx but has a limit of 4. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@98 b0f79afe-0144-0410-b225-9a4edf0717df
2008-04-25 10:00:54 +00:00
item->ItemFlags |= IF_IGNORESKILL;
}
item = P_DropItem (this, weap->AmmoType2, -1, 256);
if (item != NULL)
{
item->Amount = weap->Ammo2->Amount;
- Fixed: Fog for flooding floor textures into gaps created by missing wall textures didn't work since a parameter changes necessitated by ZDoom's render style 'enhancement'. Update to ZDoom r940: SBarInfo Update #18: - Simplified the DrawGraphic function in sbarinfo_display.cpp - Added xOffset, yOffset, and alpha to every drawing function in sbarinfo_display.cpp. So Strife popups can be handeled better and allow for other effects (translucent bars?). I'm thinking about making a struct for these five (also x and y) arguments so that the argument lists don't become a mess. - Changed DRAWIMAGE in sbarinfo_display.cpp to not use so many calls to DrawGraphic. - DrawKeyBar wasn't using screen->DrawTexture. - Added a Fade transition for popups. It takes two args fade in rate and fade out rate. Both are floats (1.0 = 1 tic to complete 0.5 = 2 tics to complete and so on). - Added a translucency arg to statusbars. 1.0 = opaque and 0.0 = invisible. - Fixed: When an instrument's envelope runs out, it does not immediately ramp to zero. Rather, it lets the remainder of the sample finish playing. - Fixed: When playing a MIDI file with EMIDI track designations to turn a track off, any ticks that had only events on the disabled track would cause the delay for that track to be thrown away, and the following notes on enabled tracks would play too soon. This could be heard quite clearly in xplasma.mid, where track 4 (FMGlass Drone 1) would interfere with the timing of tracks 13 and 14 (EP1 Melody and EP1 Echo). - Fixed: DFlashFader did some operations in its destructor that had to be moved to its Destroy method. - Fixed: Dropped weapons from dying players should not double ammo. - Fixed: When note_on() is called and another copy of the same note is already playing on the channel, it should stop it with finish_note(), not kill_note(). This can be clearly heard in the final cymbal crashes of D_DM2TTL where TiMidity cuts them off because the final cymbals are played with a velocity of 1 before the preceding cymbals have finished. (I wonder if I should be setting the self_nonexclusive flag for GUS patches to disable even this behavior, though, since gf1note.c doesn't turn off duplicate notes.) - Changed envelope handling to hopefully match the GUS player's. The most egregious mistake TiMidity makes is to treat bit 6 as an envelope enable bit. This is not what it does; every sample has an envelope. Rather, this is a "no sampled release" flag. Also, despite fiddling with the PATCH_SUSTAIN flag during instrument loading, TiMidity never actually used it. Nor did it do anything at all with the PATCH_FAST_REL flag. - Fixed: wbstartstruct's lump name fields were only 8 characters long and not properly zero-terminated when all 8 characters were used. - Fixed: Local sound sequence definitions caused a crash because a proper NULL check was missing. - Added translucent blending modes to FMultipatchTexture (not tested yet!) - Also changed all true color texture creation functions to use proper alpha values instead of inverted ones. - Changed FRemapTable so that all palette entries must contain proper alpha values. - Fixed: The F1 screen check in m_menu.cpp was missing a NULL pointer check. - Changed: The boss brain's explosions play weapons/rocklx which is an unlimited sound. This can become extremely loud. Replaced with a new sound which is just an alias to weapons/rocklx but has a limit of 4. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@98 b0f79afe-0144-0410-b225-9a4edf0717df
2008-04-25 10:00:54 +00:00
item->ItemFlags |= IF_IGNORESKILL;
}
}
}
}
if (!multiplayer && (level.flags & LEVEL_DEATHSLIDESHOW))
{
F_StartSlideshow ();
}
}
}
//===========================================================================
//
// APlayerPawn :: TweakSpeeds
//
//===========================================================================
void APlayerPawn::TweakSpeeds (int &forward, int &side)
{
// Strife's player can't run when its healh is below 10
if (health <= RunHealth)
{
forward = clamp(forward, -0x1900, 0x1900);
side = clamp(side, -0x1800, 0x1800);
}
// [GRB]
if ((unsigned int)(forward + 0x31ff) < 0x63ff)
{
forward = FixedMul (forward, ForwardMove1);
}
else
{
forward = FixedMul (forward, ForwardMove2);
}
if ((unsigned int)(side + 0x27ff) < 0x4fff)
{
side = FixedMul (side, SideMove1);
}
else
{
side = FixedMul (side, SideMove2);
}
if (!player->morphTics && Inventory != NULL)
{
fixed_t factor = Inventory->GetSpeedFactor ();
forward = FixedMul(forward, factor);
side = FixedMul(side, factor);
}
}
//===========================================================================
//
// A_PlayerScream
//
// try to find the appropriate death sound and use suitable
// replacements if necessary
//
//===========================================================================
void A_PlayerScream (AActor *self)
{
int sound = 0;
int chan = CHAN_VOICE;
if (self->player == NULL || self->DeathSound != 0)
{
S_SoundID (self, CHAN_VOICE, self->DeathSound, 1, ATTN_NORM);
return;
}
// Handle the different player death screams
if ((((level.flags >> 15) | (dmflags)) &
(DF_FORCE_FALLINGZD | DF_FORCE_FALLINGHX)) &&
self->momz <= -39*FRACUNIT)
{
sound = S_FindSkinnedSound (self, "*splat");
chan = CHAN_BODY;
}
if (!sound && self->special1<10)
{ // Wimpy death sound
sound = S_FindSkinnedSoundEx (self, "*wimpydeath", self->player->LastDamageType);
}
if (!sound && self->health <= -50)
{
if (self->health > -100)
{ // Crazy death sound
sound = S_FindSkinnedSoundEx (self, "*crazydeath", self->player->LastDamageType);
}
if (!sound)
{ // Extreme death sound
sound = S_FindSkinnedSoundEx (self, "*xdeath", self->player->LastDamageType);
if (!sound)
{
sound = S_FindSkinnedSoundEx (self, "*gibbed", self->player->LastDamageType);
chan = CHAN_BODY;
}
}
}
if (!sound)
{ // Normal death sound
sound = S_FindSkinnedSoundEx (self, "*death", self->player->LastDamageType);
}
if (chan != CHAN_VOICE)
{
for (int i = 0; i < 8; ++i)
{ // Stop most playing sounds from this player.
// This is mainly to stop *land from messing up *splat.
if (i != CHAN_WEAPON && i != CHAN_VOICE)
{
S_StopSound (self, i);
}
}
}
S_SoundID (self, chan, sound, 1, ATTN_NORM);
}
//----------------------------------------------------------------------------
//
// PROC A_SkullPop
//
//----------------------------------------------------------------------------
void A_SkullPop (AActor *actor)
{
APlayerPawn *mo;
player_t *player;
// [GRB] Parameterized version
const PClass *spawntype = NULL;
int index = CheckIndex (1, NULL);
if (index >= 0)
spawntype = PClass::FindClass((ENamedName)StateParameters[index]);
if (!spawntype || !spawntype->IsDescendantOf (RUNTIME_CLASS (APlayerChunk)))
{
spawntype = PClass::FindClass("BloodySkull");
if (spawntype == NULL) return;
}
actor->flags &= ~MF_SOLID;
mo = (APlayerPawn *)Spawn (spawntype, actor->x, actor->y, actor->z + 48*FRACUNIT, NO_REPLACE);
//mo->target = actor;
mo->momx = pr_skullpop.Random2() << 9;
mo->momy = pr_skullpop.Random2() << 9;
mo->momz = 2*FRACUNIT + (pr_skullpop() << 6);
// Attach player mobj to bloody skull
player = actor->player;
actor->player = NULL;
mo->ObtainInventory (actor);
mo->player = player;
mo->health = actor->health;
mo->angle = actor->angle;
if (player != NULL)
{
player->mo = mo;
if (player->camera == actor)
{
player->camera = mo;
}
player->damagecount = 32;
}
}
//----------------------------------------------------------------------------
//
// PROC A_CheckSkullDone
//
//----------------------------------------------------------------------------
void A_CheckPlayerDone (AActor *actor)
{
if (actor->player == NULL)
{
actor->Destroy ();
}
}
//===========================================================================
//
// P_CheckPlayerSprites
//
// Here's the place where crouching sprites are handled
// This must be called each frame before rendering
//
//===========================================================================
void P_CheckPlayerSprites()
{
for(int i=0; i<MAXPLAYERS; i++)
{
player_t * player = &players[i];
APlayerPawn * mo = player->mo;
if (playeringame[i] && mo != NULL)
{
int crouchspriteno;
fixed_t defscaleY = mo->GetDefault()->scaleY;
if (player->userinfo.skin != 0)
{
- Fixed: Warped textures didn't work anymore because the default speed was 0. - Fixed: When a suspended FraggleScript script was restarted all its variables were destroyed. Update to ZDoom r952: - Fixed: FString::StripRight() stripped the final character of the string if there were no designated characters to strip at the end of it. - Added support for Shoutcast/Icecast playlists. - Added an error message when a playlist could not be opened. - Added support for PLS format playlists, in addition to M3U. - Changed FPlayList to use an array of FStrings. - Fixed: Playlists required every song to be specified by an absolute path. - Fixed a copy-and-paste error in win32/i_main.cpp for 64-bit mode. - Tweaked OPL centering a little. - Added dynamic recentering for the OPL synth. The chip has four basic waveforms, and three of them are non-negative. This can cause a tendency for the resulting output waveform to go into very high ranges depending on the timbres used, and Heretic's exemplify this problem. - Reduced the OPL volume level slightly. - Fixed: The waveform view from snd_drawoutput was upside-down. - Various fixes for compiling working 64-bit binaries with Visual C++. The number of changes was pleasantly small, and a cursory check seems to show everything working alright. - Separated the skin scale values into separate X and Y values so that skins automatically generated for different player classes can use both the scaling values that can be set for the actor. - Fixed: Any MIDI ticks that contain only events that are interpreted by the MIDI parser and not passed on to the MIDI device would mess up timing for future events. - Changed EMIDI controller 110-113 handling to more accurately match the EMIDI specs: Track designations and exclusions should be ignored past the initial beat, and EMIDI program change and volume events should be ignored unless they were used in the initial beat. - Fixed: When FMOD::System::init() returns FMOD_ERR_OUTPUT_CREATEBUFFER, it could also be because the user selected PCM-Float output, but the driver doesn't support it (even if it claims to *cough*Audigy XP drivers*cough*). git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@101 b0f79afe-0144-0410-b225-9a4edf0717df
2008-05-01 21:45:22 +00:00
defscaleY = skins[player->userinfo.skin].ScaleY;
}
// Set the crouch sprite
if (player->crouchfactor < FRACUNIT*3/4)
{
if (mo->sprite == mo->SpawnState->sprite.index || mo->sprite == mo->crouchsprite)
{
crouchspriteno = mo->crouchsprite;
}
else if (mo->sprite == skins[player->userinfo.skin].sprite ||
mo->sprite == skins[player->userinfo.skin].crouchsprite)
{
crouchspriteno = skins[player->userinfo.skin].crouchsprite;
}
else
{
// no sprite -> squash the existing one
crouchspriteno = -1;
}
if (crouchspriteno > 0)
{
mo->sprite = crouchspriteno;
mo->scaleY = defscaleY;
}
else if (player->playerstate != PST_DEAD)
{
mo->scaleY = player->crouchfactor < FRACUNIT*3/4 ? defscaleY/2 : defscaleY;
}
}
else // Set the normal sprite
{
if (mo->sprite == mo->crouchsprite)
{
mo->sprite = mo->SpawnState->sprite.index;
}
else if (mo->sprite == skins[player->userinfo.skin].crouchsprite)
{
mo->sprite = skins[player->userinfo.skin].sprite;
}
mo->scaleY = defscaleY;
}
}
}
}
/*
==================
=
= P_Thrust
=
= moves the given origin along a given angle
=
==================
*/
void P_SideThrust (player_t *player, angle_t angle, fixed_t move)
{
angle = (angle - ANGLE_90) >> ANGLETOFINESHIFT;
player->mo->momx += FixedMul (move, finecosine[angle]);
player->mo->momy += FixedMul (move, finesine[angle]);
}
void P_ForwardThrust (player_t *player, angle_t angle, fixed_t move)
{
angle >>= ANGLETOFINESHIFT;
if ((player->mo->waterlevel || (player->mo->flags & MF_NOGRAVITY))
&& player->mo->pitch != 0)
{
angle_t pitch = (angle_t)player->mo->pitch >> ANGLETOFINESHIFT;
fixed_t zpush = FixedMul (move, finesine[pitch]);
if (player->mo->waterlevel && player->mo->waterlevel < 2 && zpush < 0)
zpush = 0;
player->mo->momz -= zpush;
move = FixedMul (move, finecosine[pitch]);
}
player->mo->momx += FixedMul (move, finecosine[angle]);
player->mo->momy += FixedMul (move, finesine[angle]);
}
//
// P_Bob
// Same as P_Thrust, but only affects bobbing.
//
// killough 10/98: We apply thrust separately between the real physical player
// and the part which affects bobbing. This way, bobbing only comes from player
// motion, nothing external, avoiding many problems, e.g. bobbing should not
// occur on conveyors, unless the player walks on one, and bobbing should be
// reduced at a regular rate, even on ice (where the player coasts).
//
void P_Bob (player_t *player, angle_t angle, fixed_t move)
{
angle >>= ANGLETOFINESHIFT;
player->momx += FixedMul(move,finecosine[angle]);
player->momy += FixedMul(move,finesine[angle]);
}
/*
==================
=
= P_CalcHeight
=
=
Calculate the walking / running height adjustment
=
==================
*/
void P_CalcHeight (player_t *player)
{
int angle;
fixed_t bob;
bool still = false;
// Regular movement bobbing
// (needs to be calculated for gun swing even if not on ground)
// killough 10/98: Make bobbing depend only on player-applied motion.
//
// Note: don't reduce bobbing here if on ice: if you reduce bobbing here,
// it causes bobbing jerkiness when the player moves from ice to non-ice,
// and vice-versa.
if ((player->mo->flags & MF_NOGRAVITY) && !onground)
{
player->bob = FRACUNIT / 2;
}
else
{
player->bob = DMulScale16 (player->momx, player->momx, player->momy, player->momy);
if (player->bob == 0)
{
still = true;
}
else
{
player->bob = FixedMul (player->bob, player->userinfo.MoveBob);
if (player->bob > MAXBOB)
player->bob = MAXBOB;
}
}
fixed_t defaultviewheight = player->mo->ViewHeight + player->crouchviewdelta;
if (player->cheats & CF_NOMOMENTUM)
{
player->viewz = player->mo->z + defaultviewheight;
if (player->viewz > player->mo->ceilingz-4*FRACUNIT)
player->viewz = player->mo->ceilingz-4*FRACUNIT;
return;
}
if (still)
{
if (player->health > 0)
{
angle = DivScale13 (level.time, 120*TICRATE/35) & FINEMASK;
bob = FixedMul (player->userinfo.StillBob, finesine[angle]);
}
else
{
bob = 0;
}
}
else
{
// DivScale 13 because FINEANGLES == (1<<13)
angle = DivScale13 (level.time, 20*TICRATE/35) & FINEMASK;
bob = FixedMul (player->bob>>(player->mo->waterlevel > 1 ? 2 : 1), finesine[angle]);
}
// move viewheight
if (player->playerstate == PST_LIVE)
{
player->viewheight += player->deltaviewheight;
if (player->viewheight > defaultviewheight)
{
player->viewheight = defaultviewheight;
player->deltaviewheight = 0;
}
else if (player->viewheight < (defaultviewheight>>1))
{
player->viewheight = defaultviewheight>>1;
if (player->deltaviewheight <= 0)
player->deltaviewheight = 1;
}
if (player->deltaviewheight)
{
player->deltaviewheight += FRACUNIT/4;
if (!player->deltaviewheight)
player->deltaviewheight = 1;
}
}
if (player->morphTics)
{
bob = 0;
}
player->viewz = player->mo->z + player->viewheight + bob;
if (player->mo->floorclip && player->playerstate != PST_DEAD
&& player->mo->z <= player->mo->floorz)
{
player->viewz -= player->mo->floorclip;
}
if (player->viewz > player->mo->ceilingz - 4*FRACUNIT)
{
player->viewz = player->mo->ceilingz - 4*FRACUNIT;
}
if (player->viewz < player->mo->floorz + 4*FRACUNIT)
{
player->viewz = player->mo->floorz + 4*FRACUNIT;
}
}
/*
=================
=
= P_MovePlayer
=
=================
*/
CUSTOM_CVAR (Float, sv_aircontrol, 0.00390625f, CVAR_SERVERINFO|CVAR_NOSAVE)
{
level.aircontrol = (fixed_t)(self * 65536.f);
G_AirControlChanged ();
}
void P_MovePlayer (player_t *player)
{
ticcmd_t *cmd = &player->cmd;
APlayerPawn *mo = player->mo;
// [RH] 180-degree turn overrides all other yaws
if (player->turnticks)
{
player->turnticks--;
mo->angle += (ANGLE_180 / TURN180_TICKS);
}
else
{
mo->angle += cmd->ucmd.yaw << 16;
}
onground = (mo->z <= mo->floorz) || (mo->flags2 & MF2_ONMOBJ);
// killough 10/98:
//
// We must apply thrust to the player and bobbing separately, to avoid
// anomalies. The thrust applied to bobbing is always the same strength on
// ice, because the player still "works just as hard" to move, while the
// thrust applied to the movement varies with 'movefactor'.
if (cmd->ucmd.forwardmove | cmd->ucmd.sidemove)
{
fixed_t forwardmove, sidemove;
int bobfactor;
int friction, movefactor;
int fm, sm;
movefactor = P_GetMoveFactor (mo, &friction);
bobfactor = friction < ORIG_FRICTION ? movefactor : ORIG_FRICTION_FACTOR;
if (!onground && !(player->mo->flags & MF_NOGRAVITY) && !player->mo->waterlevel)
{
// [RH] allow very limited movement if not on ground.
movefactor = FixedMul (movefactor, level.aircontrol);
bobfactor = FixedMul (bobfactor, level.aircontrol);
}
fm = cmd->ucmd.forwardmove;
sm = cmd->ucmd.sidemove;
mo->TweakSpeeds (fm, sm);
fm = FixedMul (fm, player->mo->Speed);
sm = FixedMul (sm, player->mo->Speed);
// When crouching speed and bobbing have to be reduced
if (player->morphTics==0 && player->crouchfactor != FRACUNIT)
{
fm = FixedMul(fm, player->crouchfactor);
sm = FixedMul(sm, player->crouchfactor);
bobfactor = FixedMul(bobfactor, player->crouchfactor);
}
forwardmove = Scale (fm, movefactor * 35, TICRATE << 8);
sidemove = Scale (sm, movefactor * 35, TICRATE << 8);
if (forwardmove)
{
P_Bob (player, mo->angle, (cmd->ucmd.forwardmove * bobfactor) >> 8);
P_ForwardThrust (player, mo->angle, forwardmove);
}
if (sidemove)
{
P_Bob (player, mo->angle-ANG90, (cmd->ucmd.sidemove * bobfactor) >> 8);
P_SideThrust (player, mo->angle, sidemove);
}
if (debugfile)
{
fprintf (debugfile, "move player for pl %d%c: (%d,%d,%d) (%d,%d) %d %d w%d [", int(player-players),
player->cheats&CF_PREDICTING?'p':' ',
player->mo->x, player->mo->y, player->mo->z,forwardmove, sidemove, movefactor, friction, player->mo->waterlevel);
msecnode_t *n = player->mo->touching_sectorlist;
while (n != NULL)
{
fprintf (debugfile, "%td ", n->m_sector-sectors);
n = n->m_tnext;
}
fprintf (debugfile, "]\n");
}
if (!(player->cheats & CF_PREDICTING) && (forwardmove|sidemove))
{
player->mo->PlayRunning ();
}
if (player->cheats & CF_REVERTPLEASE)
{
player->cheats &= ~CF_REVERTPLEASE;
player->camera = player->mo;
}
}
}
//==========================================================================
//
// P_FallingDamage
//
//==========================================================================
void P_FallingDamage (AActor *actor)
{
int damagestyle;
int damage;
fixed_t mom;
damagestyle = ((level.flags >> 15) | (dmflags)) &
(DF_FORCE_FALLINGZD | DF_FORCE_FALLINGHX);
if (damagestyle == 0)
return;
- Fixed: The hitscan tracer had the current sector point to a temporary variable when 3D floors were involved. Update to ZDoom r965: - Fixed: SPAC_AnyCross didn't work. - Fixed: Pushable doors must also check for SPAC_MPush. - Fixed: P_LoadThings2 did not adjust the byte order for the thingid field. - Changed: HIRESTEX 'define' textures now replace existing textures of type MiscPatch with the same name. - Added UDMF line trigger types MonsterUse and MonsterPush. - Separated skill and class filter bits from FMapThing::flags so that UDMF can define up to 16 of each. Also separated easy/baby and hard/nightmare and changed default MAPINFO definitions. - Fixed: FWadCollection::MergeLumps() did not initialize the flags for any marker lumps it inserted. - Fixed: Need write barriers when modifying SequenceListHead. - Added a new cvar: midi_timiditylike. This re-enables TiMidity handling of GUS patch flags, envelopes, and volume levels, while trying to be closer to TiMidity++ than original TiMidity. - Renamed timidity_config and timidity_voices to midi_config and midi_voices respectively. - Changed: Crosshair drawing uses the current player class's default health instead of 100 to calculate the color for the crosshair. - Added SECF_NOFALLINGDAMAGE flag plus Sector_ChangeFlags to set it. Also separated all user settable flags from MoreFlags into their own Flags variable. - Reduced volume, expression, and panning controllers back to 7 bits. - Added very basic Soundfont support to the internal TiMidity. Things missing: filter, LFOs, modulation envelope, chorus, reverb, and modulators. May or may not be compatible with TiMidity++'s soundfont extensions. - Changed all thing coordinates that were stored as shorts into fixed_t. - Separated mapthing2_t into mapthinghexen_t and the internal FMapThing so that it is easier to add new features in the UDMF map format. - Added some initial code to read UDMF maps. - Added support for quoted strings to the TiMidity config parser. - Split off the slope creation code from p_Setup.cpp into its own file. - Separated the linedef activation types into a bit mask that allows combination of all types on the same linedef. Also added a 'first side only' flag. This is not usable from Hexen or Doom format maps though but in preparation of the UDMF format discussed here: http://www.doomworld.com/vb/source-ports/43145-udmf-v0-99-specification-draft-aka-textmap/ - Changed linedef's alpha property from a byte to fixed point after seeing that 255 wasn't handled to be fully opaque. - fixed a GCC warning in fmodsound.cpp - Fixed: Warped textures didn't work anymore because the default speed was 0. - Fixed: I had instrument vibrato setting the tremolo_sweep_increment value in the instrument loader, effectively disabling vibrato. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@103 b0f79afe-0144-0410-b225-9a4edf0717df
2008-05-12 09:58:47 +00:00
if (actor->floorsector->Flags & SECF_NOFALLINGDAMAGE)
return;
mom = abs (actor->momz);
// Since Hexen falling damage is stronger than ZDoom's, it takes
// precedence. ZDoom falling damage may not be as strong, but it
// gets felt sooner.
switch (damagestyle)
{
case DF_FORCE_FALLINGHX: // Hexen falling damage
if (mom <= 23*FRACUNIT)
{ // Not fast enough to hurt
return;
}
if (mom >= 63*FRACUNIT)
{ // automatic death
damage = 1000000;
}
else
{
mom = FixedMul (mom, 16*FRACUNIT/23);
damage = ((FixedMul (mom, mom) / 10) >> FRACBITS) - 24;
if (actor->momz > -39*FRACUNIT && damage > actor->health
&& actor->health != 1)
{ // No-death threshold
damage = actor->health-1;
}
}
break;
case DF_FORCE_FALLINGZD: // ZDoom falling damage
if (mom <= 19*FRACUNIT)
{ // Not fast enough to hurt
return;
}
if (mom >= 84*FRACUNIT)
{ // automatic death
damage = 1000000;
}
else
{
damage = ((MulScale23 (mom, mom*11) >> FRACBITS) - 30) / 2;
if (damage < 1)
{
damage = 1;
}
}
break;
case DF_FORCE_FALLINGST: // Strife falling damage
if (mom <= 20*FRACUNIT)
{ // Not fast enough to hurt
return;
}
// The minimum amount of damage you take from falling in Strife
// is 52. Ouch!
damage = mom / 25000;
break;
default:
return;
}
if (actor->player)
{
S_Sound (actor, CHAN_AUTO, "*land", 1, ATTN_NORM);
P_NoiseAlert (actor, actor, true);
if (damage == 1000000 && (actor->player->cheats & CF_GODMODE))
{
damage = 999;
}
}
P_DamageMobj (actor, NULL, NULL, damage, NAME_Falling);
}
//==========================================================================
//
// P_DeathThink
//
//==========================================================================
void P_DeathThink (player_t *player)
{
int dir;
angle_t delta;
int lookDelta;
P_MovePsprites (player);
onground = (player->mo->z <= player->mo->floorz);
if (player->mo->IsKindOf (RUNTIME_CLASS(APlayerChunk)))
{ // Flying bloody skull or flying ice chunk
player->viewheight = 6 * FRACUNIT;
player->deltaviewheight = 0;
if (onground)
{
if (player->mo->pitch > -(int)ANGLE_1*19)
{
lookDelta = (-(int)ANGLE_1*19 - player->mo->pitch) / 8;
player->mo->pitch += lookDelta;
}
}
}
else if (!(player->mo->flags & MF_ICECORPSE))
{ // Fall to ground (if not frozen)
player->deltaviewheight = 0;
if (player->viewheight > 6*FRACUNIT)
{
player->viewheight -= FRACUNIT;
}
if (player->viewheight < 6*FRACUNIT)
{
player->viewheight = 6*FRACUNIT;
}
if (player->mo->pitch < 0)
{
player->mo->pitch += ANGLE_1*3;
}
else if (player->mo->pitch > 0)
{
player->mo->pitch -= ANGLE_1*3;
}
if (abs(player->mo->pitch) < ANGLE_1*3)
{
player->mo->pitch = 0;
}
}
P_CalcHeight (player);
if (player->attacker && player->attacker != player->mo)
{ // Watch killer
dir = P_FaceMobj (player->mo, player->attacker, &delta);
if (delta < ANGLE_1*10)
{ // Looking at killer, so fade damage and poison counters
if (player->damagecount)
{
player->damagecount--;
}
if (player->poisoncount)
{
player->poisoncount--;
}
}
delta /= 8;
if (delta > ANGLE_1*5)
{
delta = ANGLE_1*5;
}
if (dir)
{ // Turn clockwise
player->mo->angle += delta;
}
else
{ // Turn counter clockwise
player->mo->angle -= delta;
}
}
else
{
if (player->damagecount)
{
player->damagecount--;
}
if (player->poisoncount)
{
player->poisoncount--;
}
}
if ((player->cmd.ucmd.buttons & BT_USE ||
((deathmatch || alwaysapplydmflags) && (dmflags & DF_FORCE_RESPAWN))) && !(dmflags2 & DF2_NO_RESPAWN))
{
if (level.time >= player->respawn_time || ((player->cmd.ucmd.buttons & BT_USE) && !player->isbot))
{
player->cls = NULL; // Force a new class if the player is using a random class
player->playerstate = (multiplayer || (level.flags & LEVEL_ALLOWRESPAWN)) ? PST_REBORN : PST_ENTER;
if (player->mo->special1 > 2)
{
player->mo->special1 = 0;
}
}
}
}
//----------------------------------------------------------------------------
//
// PROC P_CrouchMove
//
//----------------------------------------------------------------------------
void P_CrouchMove(player_t * player, int direction)
{
fixed_t defaultheight = player->mo->GetDefault()->height;
fixed_t savedheight = player->mo->height;
fixed_t crouchspeed = direction * CROUCHSPEED;
fixed_t oldheight = player->viewheight;
player->crouchdir = (signed char) direction;
player->crouchfactor += crouchspeed;
// check whether the move is ok
player->mo->height = FixedMul(defaultheight, player->crouchfactor);
if (!P_TryMove(player->mo, player->mo->x, player->mo->y, false, false))
{
player->mo->height = savedheight;
if (direction > 0)
{
// doesn't fit
player->crouchfactor -= crouchspeed;
return;
}
}
player->mo->height = savedheight;
player->crouchfactor = clamp<fixed_t>(player->crouchfactor, FRACUNIT/2, FRACUNIT);
player->viewheight = FixedMul(player->mo->ViewHeight, player->crouchfactor);
player->crouchviewdelta = player->viewheight - player->mo->ViewHeight;
// Check for eyes going above/below fake floor due to crouching motion.
P_CheckFakeFloorTriggers(player->mo, player->mo->z + oldheight, true);
}
//----------------------------------------------------------------------------
//
// PROC P_PlayerThink
//
//----------------------------------------------------------------------------
void P_PlayerThink (player_t *player)
{
ticcmd_t *cmd;
if (player->mo == NULL)
{
I_Error ("No player %td start\n", player - players + 1);
}
if (debugfile && !(player->cheats & CF_PREDICTING))
{
fprintf (debugfile, "tic %d for pl %td: (%d, %d, %d, %u) b:%02x p:%d y:%d f:%d s:%d u:%d\n",
gametic, player-players, player->mo->x, player->mo->y, player->mo->z,
player->mo->angle>>ANGLETOFINESHIFT, player->cmd.ucmd.buttons,
player->cmd.ucmd.pitch, player->cmd.ucmd.yaw, player->cmd.ucmd.forwardmove,
player->cmd.ucmd.sidemove, player->cmd.ucmd.upmove);
}
// [RH] Zoom the player's FOV
if (player->FOV != player->DesiredFOV)
{
if (fabsf (player->FOV - player->DesiredFOV) < 7.f)
{
player->FOV = player->DesiredFOV;
}
else
{
float zoom = MAX(7.f, fabsf (player->FOV - player->DesiredFOV) * 0.025f);
if (player->FOV > player->DesiredFOV)
{
player->FOV = player->FOV - zoom;
}
else
{
player->FOV = player->FOV + zoom;
}
}
}
if (player->inventorytics)
{
player->inventorytics--;
}
// No-clip cheat
if (player->cheats & CF_NOCLIP)
{
player->mo->flags |= MF_NOCLIP;
}
else
{
player->mo->flags &= ~MF_NOCLIP;
}
cmd = &player->cmd;
if (player->mo->flags & MF_JUSTATTACKED)
{ // Chainsaw/Gauntlets attack auto forward motion
cmd->ucmd.yaw = 0;
cmd->ucmd.forwardmove = 0xc800/2;
cmd->ucmd.sidemove = 0;
player->mo->flags &= ~MF_JUSTATTACKED;
}
// [RH] Being totally frozen zeros out most input parameters.
if (player->cheats & CF_TOTALLYFROZEN || gamestate == GS_TITLELEVEL)
{
if (gamestate == GS_TITLELEVEL)
{
cmd->ucmd.buttons = 0;
}
else
{
cmd->ucmd.buttons &= BT_USE;
}
cmd->ucmd.pitch = 0;
cmd->ucmd.yaw = 0;
cmd->ucmd.roll = 0;
cmd->ucmd.forwardmove = 0;
cmd->ucmd.sidemove = 0;
cmd->ucmd.upmove = 0;
player->turnticks = 0;
}
else if (player->cheats & CF_FROZEN)
{
cmd->ucmd.forwardmove = 0;
cmd->ucmd.sidemove = 0;
cmd->ucmd.upmove = 0;
}
// Handle crouching
if (player->cmd.ucmd.buttons & BT_JUMP) player->cmd.ucmd.buttons &= ~BT_DUCK;
if (player->morphTics == 0 && player->health > 0 && level.IsCrouchingAllowed())
{
if (!(player->cheats & CF_TOTALLYFROZEN))
{
int crouchdir = player->crouching;
if (crouchdir==0)
{
crouchdir = (player->cmd.ucmd.buttons & BT_DUCK)? -1 : 1;
}
else if (player->cmd.ucmd.buttons & BT_DUCK)
{
player->crouching=0;
}
if (crouchdir == 1 && player->crouchfactor < FRACUNIT &&
player->mo->z + player->mo->height < player->mo->ceilingz)
{
P_CrouchMove(player, 1);
}
else if (crouchdir == -1 && player->crouchfactor > FRACUNIT/2)
{
P_CrouchMove(player, -1);
}
}
}
else
{
player->Uncrouch();
}
player->crouchoffset = -FixedMul(player->mo->ViewHeight, (FRACUNIT - player->crouchfactor));
if (player->playerstate == PST_DEAD)
{
player->Uncrouch();
P_DeathThink (player);
return;
}
if (player->jumpTics)
{
player->jumpTics--;
}
if (player->morphTics && !(player->cheats & CF_PREDICTING))
{
player->mo->MorphPlayerThink ();
}
// [RH] Look up/down stuff
if (!level.IsFreelookAllowed())
{
player->mo->pitch = 0;
}
else
{
int look = cmd->ucmd.pitch << 16;
// The player's view pitch is clamped between -32 and +56 degrees,
// which translates to about half a screen height up and (more than)
// one full screen height down from straight ahead when view panning
// is used.
if (look)
{
if (look == -32768 << 16)
{ // center view
player->mo->pitch = 0;
}
else
{
player->mo->pitch -= look;
if (look > 0)
{ // look up
if (player->mo->pitch < -ANGLE_1*MAX_UP_ANGLE)
player->mo->pitch = -ANGLE_1*MAX_UP_ANGLE;
}
else
{ // look down
if (player->mo->pitch > ANGLE_1*MAX_DN_ANGLE)
player->mo->pitch = ANGLE_1*MAX_DN_ANGLE;
}
}
}
}
// [RH] Check for fast turn around
if (cmd->ucmd.buttons & BT_TURN180 && !(player->oldbuttons & BT_TURN180))
{
player->turnticks = TURN180_TICKS;
}
// Handle movement
if (player->mo->reactiontime)
{ // Player is frozen
player->mo->reactiontime--;
}
else
{
P_MovePlayer (player);
// [RH] check for jump
if (cmd->ucmd.buttons & BT_JUMP)
{
if (player->crouchoffset!=0)
{
// Jumping while crouching will force an un-crouch but not jump
player->crouching = 1;
}
else
if (player->mo->waterlevel >= 2)
{
player->mo->momz = 4*FRACUNIT;
}
else if (player->mo->flags & MF_NOGRAVITY)
{
player->mo->momz = 3*FRACUNIT;
}
else if (level.IsJumpingAllowed() && onground && !player->jumpTics)
{
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;
}
}
if (cmd->ucmd.upmove == -32768)
{ // Only land if in the air
if ((player->mo->flags & MF_NOGRAVITY) && player->mo->waterlevel < 2)
{
//player->mo->flags2 &= ~MF2_FLY;
player->mo->flags &= ~MF_NOGRAVITY;
}
}
else if (cmd->ucmd.upmove != 0)
{
// Clamp the speed to some reasonable maximum.
int magnitude = abs (cmd->ucmd.upmove);
if (magnitude > 0x300)
{
cmd->ucmd.upmove = ksgn (cmd->ucmd.upmove) * 0x300;
}
if (player->mo->waterlevel >= 2 || (player->mo->flags2 & MF2_FLY))
{
player->mo->momz = cmd->ucmd.upmove << 9;
if (player->mo->waterlevel < 2 && !(player->mo->flags & MF_NOGRAVITY))
{
player->mo->flags2 |= MF2_FLY;
player->mo->flags |= MF_NOGRAVITY;
if (player->mo->momz <= -39*FRACUNIT)
{ // Stop falling scream
S_StopSound (player->mo, CHAN_VOICE);
}
}
}
else if (cmd->ucmd.upmove > 0 && !(player->cheats & CF_PREDICTING))
{
AInventory *fly = player->mo->FindInventory (NAME_ArtiFly);
if (fly != NULL)
{
player->mo->UseInventory (fly);
}
}
}
}
P_CalcHeight (player);
if (!(player->cheats & CF_PREDICTING))
{
P_PlayerOnSpecial3DFloor (player);
if (player->mo->Sector->special || player->mo->Sector->damage)
{
P_PlayerInSpecialSector (player);
}
P_PlayerOnSpecialFlat (player, P_GetThingFloorType (player->mo));
if (player->mo->momz <= -35*FRACUNIT &&
player->mo->momz >= -40*FRACUNIT && !player->morphTics &&
player->mo->waterlevel == 0)
{
int id = S_FindSkinnedSound (player->mo, "*falling");
if (id != 0 && !S_IsActorPlayingSomething (player->mo, CHAN_VOICE, id))
{
S_SoundID (player->mo, CHAN_VOICE, id, 1, ATTN_NORM);
}
}
// check for use
if ((cmd->ucmd.buttons & BT_USE) && !(player->oldbuttons & BT_USE))
{
P_UseLines (player);
}
// Morph counter
if (player->morphTics)
{
if (player->chickenPeck)
{ // Chicken attack counter
player->chickenPeck -= 3;
}
if (!--player->morphTics)
{ // Attempt to undo the chicken/pig
- Fixed: When walking on sloped 3D-floors, P_TryMove got the floor position from the sector's actual floor instead from the 3D-floor. - Fixed: Brightmaps were not disabled when fog was defined with a fadetable command in MAPINFO. Update to ZDoom r994: - Fixed: The compatibility searches for teleport destinations did not work properly when the teleporter had both a tid and a tag. Now, if a teleporter has a tag these are skipped because they are only present for Hexen compatibility. - Fixed: The first texture in a TEXTURE1 lump, although invalid when used elsewhere, must be usable as sky (see Requiem.wad's SKY3.) - Fixed: side_t::GetLightLevel relied on the global 'linedef' variable for automatic fake contrast. - Changed: Fake contrast now uses the WALLF_AUTOCONTRAST globally instead of manipulating the sides' light values individually. This allows changing the fake contrast at run time and also allows adding individual relative lighting on top of it which is a planned UDMF feature. - Fixed: ActorStencilColor() did not set the palette part of the actor's fill color, so it would always produce black for STYLE_Shaded. - Added volume reduction for stereo sounds played in 3D to obtain levels closer to FMOD 3, which downmixed all stereo sounds to mono before playing them in 3D. Also added experimental 3D spread for stereo sounds so that you can actually hear them in stereo. - Reworked a few options that previously depended on LEVEL_HEXENFORMAT (actors being forced to the ground by instantly moving sectors, strife railing handling and shooting lines with a non-zero but unassigned tag.) With UDMF such semantics have to be handled diffently. - finalized UDMF 1.0 implementation. - Added Martin Howe's latest morph update. - Fixed: When R_DrawTiltedPlane() calculates the p vector, it can overflow if the view is near the bounds of the fixed point coordinate system. This happens because it rotates the view position around (0,0) according to the current viewangle, so the resultant coordinate may be outside the bounds of fixed point. All important math in this function is now done entirely in floating point. - Fixed: Slopes didn't draw right on 64-bit platforms. - Fixed: With hardware 2D, the console and menu need not reimplement palette flashes to ensure their visibility. - Fixed: DFlashFader::Destroy() did not call its super method. - Fixed: If a player was morphed into a class with a taller view height, their perceived view height would not change until they walked up a step. - Since KDIZD is the only mapset I know of that used reverb, and it didn't define any new ones of its own, I'm pre-emptively renaming the SNDEAX lump to REVERBS to remove any possible misunderstanding that this is something that requires EAX hardware support. (Ideally, it would have been REVERBDEF, but that's 10 characters long.) The eaxedit console command has also been renamed to reverbedit for the same reason. - Fixed: The Palette part of FRemapTable was not initialized with alpha values other than 0. I'm not sure if it would be better to fix this in the game palette that it copies from or not, but right now, they get set unconditionally to 255. - Fixed: M_DrawSave() and M_DrawLoad() need to use GetScaledWidth(), in case the texture is high-res. - Replaced all instances of "flags +=" in sbarinfo_parser.cpp with "flags |=" so that using the same flag multiple times will not have unexpected results. (sbarinfo update #21) - Added: sigil image type to correctly draw the sigil's icon. - Added: Strife inventory bar style. This is the only style that is radically different from the others. First of all it changes the SELECTBO to be INVCURS and draws it before the icons. Each box is changed to have a width of 35 pixels instead of 31 pixels. And the INVCURS graphic is drawn at (x-6, y-2). - Added: whennnotzero flag to drawnumber which will cause it to draw nothing if the value is 0. - Fixed: New mugshot code would not leave the god state when it was supposed to enter the rampage state. - Fixed: The ouch state was mostly broken. (SBarInfo Update #20) - Added: hasweaponpiece command to check for custom weapon pieces. - Added: usessecondaryammo command to check if the current weapon has a second ammo type. - Most of SBarInfo's mugshot scripting can be used with the default Doom status bar. - Fixed: By default drawmugshot would never come out of normal god mode state. In addition the state change to and from god mode was not quite as responsive as the original code. - Fixed: When FTextureManager::CheckForTexture finds a matching NULL texture it should always return 0, not the actual texture's index. - Fixed coordinate checks for objects on 3DMidtex lines. - Fixed: All translucent blending operations for CopyColors must treat an alpha of 0 so that the pixel is not modified or texture composition as intended will not work. - Fixed: 3D hardware texture filling did not copy pixels with 0 alpha, preserving whatever was underneath in the texture box previously. - Fixed: s_sound.cpp had its own idea of whether or not sounds were paused and did not entirely keep it in sync with the sound system's. This meant that when starting a new game from the menu, all sounds were played as menu sounds until you did something to pause the game, because s_sound.cpp thought sounds were unpaused, while the FMOD system thought they were. - I finally managed to test the translucency options for composite texture definitions in HIRESTEX. The feature should be complete now. - Fixed: A_CheckTargetInLOS used BAM angles instead of degrees which is the DECORATE convention. - Added Snowkate709's A_CheckTargetInLOS addition. - Added listmaps CCMD. - Revised underwater effect now uses a lowpass filter in combination with an optional freeverb unit. - Removed ResetEnvironment hack, since with software reverb, losing the existing reverb when focus is lost isn't a problem. - Commented out the TiMidity FIXME messages. - Fixed: FBarShader::GetColumn() passed incorrect information to the software renderer for horizontal bars. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@107 b0f79afe-0144-0410-b225-9a4edf0717df
2008-05-23 17:58:17 +00:00
P_UndoPlayerMorph (player, player);
}
}
// Cycle psprites
P_MovePsprites (player);
// Other Counters
if (player->damagecount)
player->damagecount--;
if (player->bonuscount)
player->bonuscount--;
if (player->hazardcount)
{
player->hazardcount--;
if (!(level.time & 31) && player->hazardcount > 16*TICRATE)
P_DamageMobj (player->mo, NULL, NULL, 5, NAME_Slime);
}
if (player->poisoncount && !(level.time & 15))
{
player->poisoncount -= 5;
if (player->poisoncount < 0)
{
player->poisoncount = 0;
}
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 );
}
}
// Apply degeneration.
if (dmflags2 & DF2_YES_DEGENERATION)
{
if ((level.time % TICRATE) == 0 && player->health > deh.MaxHealth)
{
if (player->health - 5 < deh.MaxHealth)
player->health = deh.MaxHealth;
else
player->health--;
player->mo->health = player->health;
}
}
// Handle air supply
if (level.airsupply > 0)
{
if (player->mo->waterlevel < 3 ||
(player->mo->flags2 & MF2_INVULNERABLE) ||
(player->cheats & CF_GODMODE))
{
player->mo->ResetAirSupply ();
}
else if (player->air_finished <= level.time && !(level.time & 31))
{
P_DamageMobj (player->mo, NULL, NULL, 2 + ((level.time-player->air_finished)/TICRATE), NAME_Drowning);
}
}
}
// Save buttons
player->oldbuttons = cmd->ucmd.buttons;
}
void P_PredictPlayer (player_t *player)
{
int maxtic;
if (cl_noprediction ||
singletics ||
demoplayback ||
player->mo == NULL ||
player != &players[consoleplayer] ||
player->playerstate != PST_LIVE ||
!netgame ||
/*player->morphTics ||*/
(player->cheats & CF_PREDICTING))
{
return;
}
maxtic = maketic;
if (gametic == maxtic)
{
return;
}
// Save original values for restoration later
PredictionPlayerBackup = *player;
AActor *act = player->mo;
memcpy (PredictionActorBackup, &act->x, sizeof(AActor)-((BYTE *)&act->x-(BYTE *)act));
act->flags &= ~MF_PICKUP;
act->flags2 &= ~MF2_PUSHWALL;
player->cheats |= CF_PREDICTING;
// The ordering of the touching_sectorlist needs to remain unchanged
msecnode_t *mnode = act->touching_sectorlist;
PredictionTouchingSectorsBackup.Clear ();
while (mnode != NULL)
{
PredictionTouchingSectorsBackup.Push (mnode->m_sector);
mnode = mnode->m_tnext;
}
// Blockmap ordering also needs to stay the same, so unlink the block nodes
// without releasing them. (They will be used again in P_UnpredictPlayer).
FBlockNode *block = act->BlockNode;
while (block != NULL)
{
if (block->NextActor != NULL)
{
block->NextActor->PrevActor = block->PrevActor;
}
*(block->PrevActor) = block->NextActor;
block = block->NextBlock;
}
act->BlockNode = NULL;
for (int i = gametic; i < maxtic; ++i)
{
player->cmd = localcmds[i % LOCALCMDTICS];
P_PlayerThink (player);
player->mo->Tick ();
}
}
extern msecnode_t *P_AddSecnode (sector_t *s, AActor *thing, msecnode_t *nextnode);
void P_UnPredictPlayer ()
{
player_t *player = &players[consoleplayer];
if (player->cheats & CF_PREDICTING)
{
AActor *act = player->mo;
*player = PredictionPlayerBackup;
act->UnlinkFromWorld ();
memcpy (&act->x, PredictionActorBackup, sizeof(AActor)-((BYTE *)&act->x-(BYTE *)act));
// Make the sector_list match the player's touching_sectorlist before it got predicted.
P_DelSeclist (sector_list);
sector_list = NULL;
for (unsigned int i = PredictionTouchingSectorsBackup.Size (); i-- > 0; )
{
sector_list = P_AddSecnode (PredictionTouchingSectorsBackup[i], act, sector_list);
}
// The blockmap ordering needs to remain unchanged, too. Right now, act has the right
// pointers, so temporarily set its MF_NOBLOCKMAP flag so that LinkToWorld() does not
// mess with them.
act->flags |= MF_NOBLOCKMAP;
act->LinkToWorld ();
act->flags &= ~MF_NOBLOCKMAP;
// Now fix the pointers in the blocknode chain
FBlockNode *block = act->BlockNode;
while (block != NULL)
{
*(block->PrevActor) = block;
if (block->NextActor != NULL)
{
block->NextActor->PrevActor = &block->NextActor;
}
block = block->NextBlock;
}
}
}
void player_s::Serialize (FArchive &arc)
{
int i;
arc << cls
<< mo
<< camera
<< playerstate
<< cmd
<< userinfo
<< DesiredFOV << FOV
<< viewz
<< viewheight
<< deltaviewheight
<< bob
<< momx
<< momy
<< centering
<< health
<< inventorytics
<< pieces
<< backpack
<< fragcount
<< spreecount
<< multicount
<< lastkilltime
<< ReadyWeapon << PendingWeapon
<< cheats
<< refire
<< inconsistant
<< killcount
<< itemcount
<< secretcount
<< damagecount
<< bonuscount
<< hazardcount
<< poisoncount
<< poisoner
<< attacker
<< extralight
<< fixedcolormap
<< morphTics
Update to ZDoom r894: - Eliminated all use of global variables used as output for P_CheckPosition and P_TryMove. Moved BlockingLine and BlockingMobj into AActor because the global variables can be easily overwritten with certain DECORATE constructs. - Removed some unnecessary morphing code. - Fixed some bugs in the HIRESTEX parser. - Added floating point support and #include and #define tokens to FParseContext Not used yet. - replaced the value scanning code in FParseContext::GetToken with calls to strtol. - Changed XlatParseContext::FindToken to do a binary search over the valid token names. - Fixed: The check arrays for BlockThingsIterators were not properly freed and each iterator allocated a new one as a result. - Split the Xlat parser context class into a generic part that can be used for other Lemon-based parsers in the future and a smaller Xlat-specific part. - Changed: P_TeleportMove now always sets BlockingLine to NULL and P_FindFloorCeiling doesn't set it at all. The way it was set in PIT_FindFloorCeiling didn't look correct. (Note: It's amazing how easy it is to break P_TryMove et.al. with DECORATE if you just know which combinations of code pointers will cause problems. This definitely needs to be addressed.) - Changed P_FindFloorCeiling so that it doesn't need global variables anymore. I also moved the code to set the calling actor's information into this function because that's all it is used for. This also fixes another bug: - AInventory::BecomePickup called P_FindFloorCeiling to get proper position values for the item but never set the item's information to the return value of this call. - Removed the check for Heretic when playing *evillaugh when using the Chaos Device. This sound is not defined by the other games so it won't play by default. - Added MORPH_UNDOMORPHBYTOMEOFPOWER and MORPH_UNDOMORPHBYCHAOSDEVICE flags for the morph style so that the special behavior of these two items can be switched on and off. - Added Martin Howe's morph system enhancement. - Removed PT_EARLYOUT from P_PathTraverse because it wasn't used anywhere. - Rewrote BlockThingsIterator code not to use callbacks anymore. - Fixed: PIT_FindFloorCeiling required tmx and tmy to be set but P_FindFloorCeiling never did that. - Merged Check_Sides and PIT_CrossLine into A_PainShootSkull. - Replaced P_BlockLinesIterator with FBlockLinesIterator in all places it was used. This also allowed to remove all the global variable saving in P_CreateSecNodeList. - Added a new FBlockLinesIterator class that doesn't need a callback function because debugging the previous bug proved to be a bit annoying because it involved a P_BlockLinesIterator loop. - Fixed: The MBF code to move monsters away from dropoffs did not work as intended due to some random decisions in P_DoNewChaseDir. When in the avoiding dropoff mode these are ignored now. This should cure the problem that monsters hanging over a dropoff tended to drop down. - Added a NOTIMEFREEZE flag that excludes actors from being affected by the time freezer powerup. - Changed: Empty pickup messages are no longer printed. - Changed secret sector drawing in automap so that lines with the ML_SECRET flag are only drawn as part of a secret sector if that secret has already been found, even if the option is set to always show secret sectors. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@88 b0f79afe-0144-0410-b225-9a4edf0717df
2008-04-08 22:32:52 +00:00
<< MorphedPlayerClass
<< MorphStyle
<< MorphExitFlash
<< PremorphWeapon
<< chickenPeck
<< jumpTics
<< respawn_time
<< air_finished
<< turnticks
<< oldbuttons
<< isbot
<< BlendR
<< BlendG
<< BlendB
<< BlendA
<< accuracy << stamina
- Update to ZDoom r858: - Added FMOD_OPENONLY to the callback version of CreateStream() to prevent it from doing prebuffering of the song. This was causing the Linux version to hang while waiting for input from the pipe, since Timidity hadn't been started yet. I tried using a select call in the FillStream() method, but it always seems to return the pipe as having nothing available. Unfortunately, the game still falls all over itself if Timidity isn't available. Instead of execvp failing nicely, X errors kill the game. I don't know why it's doing that. My advice for Linux music: Skip Timidity++ and get a DLS patch set (/WINDOWS/system32/drivers/gm.dls is probably the most common by far) and set the snd_midipatchset cvar to point to it. It's faster and also sounds a whole lot better than the crappy freepats Ubuntu wants to install with Timidity++ (thank goodness I have the official patches from a real GUS so I don't need to use them). - GCC fixes. - Fixed: After starting new music the music volume has to be reset so that the song's relative volume takes effect. - Removed the arbitrary 1024 bytes limit when the file being played is a MIDI file. I had a D_DM2TTL that's only 990 bytes. - Restructured I_RegisterSong so that $mididevice works again and also supports selecting FMOD. - Added Jim' Linux fix. - Added MartinHowe's fix for mugshot display in status bars. - The garbage collector is now run one last time just before exiting the game. - Removed movie volume from the sound menu and renamed some of the other options to give the MIDI device name more room to display itself. - Moved the midi device selection into the main sound menu. - Added FMOD as MIDI device -1, to replace the MIDI mapper. This is still the default device. By default, it uses exactly the same DLS instruments as the Microsoft GS Wavetable Synth. If you have another set DLS level 1 patch set you want to use, set the snd_midipatchset cvar to specify where it should load the instruments from. - Changed the ProduceMIDI function to store its output into a TArray<BYTE>. An overloaded version wraps around it to continue to supply file-writing support for external Timidity++ usage. - Added an FMOD credits banner to comply with their non-commercial license. - Reimplemented the snd_buffersize cvar for the FMOD Ex sound system. Rather than a time in ms, this is now the length in samples of the DSP buffer. Also added the snd_buffercount cvar to offer complete control over the call to FMOD::System::setDSPBufferSize(). Note that with any snd_samplerate below about 44kHz, you will need to set snd_buffersize to avoid long latencies. - Reimplemented the snd_output cvar for the FMOD Ex sound system. - Changed snd_samplerate default to 0. This now means to use the default sample rate. - Made snd_output, snd_output_format, snd_speakermode, snd_resampler, and snd_hrtf available through the menu. - Split the HRTF effect selection into its own cvar: snd_hrtf. - Removed 96000 Hz option from the menu. It's still available through the cvar, if desired. - Fixed: If Windows sound init failed, retry with DirectSound. (Apparently, WASAPI doesn't work with more than two speakers and PCM-Float output at the same time.) - Fixed: Area sounds only played from the front speakers once you got within the 2D panning area. git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@79 b0f79afe-0144-0410-b225-9a4edf0717df
2008-03-27 18:31:46 +00:00
<< LogText
<< ConversationNPC
<< ConversationPC
<< ConversationNPCAngle
<< ConversationFaceTalker;
for (i = 0; i < MAXPLAYERS; i++)
arc << frags[i];
for (i = 0; i < NUMPSPRITES; i++)
arc << psprites[i];
arc << CurrentPlayerClass;
arc << crouchfactor
<< crouching
<< crouchdir
<< crouchviewdelta;
if (isbot)
{
arc << angle
<< dest
<< prev
<< enemy
<< missile
<< mate
<< last_mate
<< skill
<< t_active
<< t_respawn
<< t_strafe
<< t_react
<< t_fight
<< t_roam
<< t_rocket
<< first_shot
<< sleft
<< allround
<< oldx
<< oldy;
}
else
{
dest = prev = enemy = missile = mate = last_mate = NULL;
}
if (arc.IsLoading ())
{
// If the player reloaded because they pressed +use after dying, we
// don't want +use to still be down after the game is loaded.
oldbuttons = ~0;
}
}