mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-04-22 02:00:11 +00:00
Merge branch 'master' into new-menus
This commit is contained in:
commit
107622968e
250 changed files with 2531 additions and 47145 deletions
|
|
@ -1,21 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ImportGroup Label="PropertySheets" />
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<IncludePath>$(SolutionDir)libs\fmodex\inc;$(IncludePath)</IncludePath>
|
||||
<LibraryPath>$(SolutionDir)libs\fmodex\lib;$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup />
|
||||
<ItemDefinitionGroup Condition="'$(PlatformTarget)'=='x64'">
|
||||
<Link>
|
||||
<AdditionalDependencies>fmodexL64_vc.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(PlatformTarget)'=='x86'">
|
||||
<Link>
|
||||
<AdditionalDependencies>fmodexL_vc.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup />
|
||||
</Project>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
|
@ -1,159 +0,0 @@
|
|||
/* ==================================================================================================== */
|
||||
/* FMOD Ex - codec development header file. Copyright (c), Firelight Technologies Pty, Ltd. 2004-2011. */
|
||||
/* */
|
||||
/* Use this header if you are wanting to develop your own file format plugin to use with */
|
||||
/* FMOD's codec system. With this header you can make your own fileformat plugin that FMOD */
|
||||
/* can register and use. See the documentation and examples on how to make a working plugin. */
|
||||
/* */
|
||||
/* ==================================================================================================== */
|
||||
|
||||
#ifndef _FMOD_CODEC_H
|
||||
#define _FMOD_CODEC_H
|
||||
|
||||
typedef struct FMOD_CODEC_STATE FMOD_CODEC_STATE;
|
||||
typedef struct FMOD_CODEC_WAVEFORMAT FMOD_CODEC_WAVEFORMAT;
|
||||
|
||||
/*
|
||||
Codec callbacks
|
||||
*/
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_OPENCALLBACK) (FMOD_CODEC_STATE *codec_state, FMOD_MODE usermode, FMOD_CREATESOUNDEXINFO *userexinfo);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_CLOSECALLBACK) (FMOD_CODEC_STATE *codec_state);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_READCALLBACK) (FMOD_CODEC_STATE *codec_state, void *buffer, unsigned int sizebytes, unsigned int *bytesread);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_GETLENGTHCALLBACK) (FMOD_CODEC_STATE *codec_state, unsigned int *length, FMOD_TIMEUNIT lengthtype);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_SETPOSITIONCALLBACK) (FMOD_CODEC_STATE *codec_state, int subsound, unsigned int position, FMOD_TIMEUNIT postype);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_GETPOSITIONCALLBACK) (FMOD_CODEC_STATE *codec_state, unsigned int *position, FMOD_TIMEUNIT postype);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_SOUNDCREATECALLBACK) (FMOD_CODEC_STATE *codec_state, int subsound, FMOD_SOUND *sound);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_METADATACALLBACK) (FMOD_CODEC_STATE *codec_state, FMOD_TAGTYPE tagtype, char *name, void *data, unsigned int datalen, FMOD_TAGDATATYPE datatype, int unique);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_CODEC_GETWAVEFORMAT) (FMOD_CODEC_STATE *codec_state, int index, FMOD_CODEC_WAVEFORMAT *waveformat);
|
||||
|
||||
|
||||
/*
|
||||
[STRUCTURE]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
When creating a codec, declare one of these and provide the relevant callbacks and name for FMOD to use when it opens and reads a file.
|
||||
|
||||
[REMARKS]
|
||||
Members marked with [in] mean the variable can be written to. The user can set the value.
|
||||
Members marked with [out] mean the variable is modified by FMOD and is for reading purposes only. Do not change this value.
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
FMOD_CODEC_STATE
|
||||
]
|
||||
*/
|
||||
typedef struct FMOD_CODEC_DESCRIPTION
|
||||
{
|
||||
const char *name; /* [in] Name of the codec. */
|
||||
unsigned int version; /* [in] Plugin writer's version number. */
|
||||
int defaultasstream; /* [in] Tells FMOD to open the file as a stream when calling System::createSound, and not a static sample. Should normally be 0 (FALSE), because generally the user wants to decode the file into memory when using System::createSound. Mainly used for formats that decode for a very long time, or could use large amounts of memory when decoded. Usually sequenced formats such as mod/s3m/xm/it/midi fall into this category. It is mainly to stop users that don't know what they're doing from getting FMOD_ERR_MEMORY returned from createSound when they should have in fact called System::createStream or used FMOD_CREATESTREAM in System::createSound. */
|
||||
FMOD_TIMEUNIT timeunits; /* [in] When setposition codec is called, only these time formats will be passed to the codec. Use bitwise OR to accumulate different types. */
|
||||
FMOD_CODEC_OPENCALLBACK open; /* [in] Open callback for the codec for when FMOD tries to open a sound using this codec. */
|
||||
FMOD_CODEC_CLOSECALLBACK close; /* [in] Close callback for the codec for when FMOD tries to close a sound using this codec. */
|
||||
FMOD_CODEC_READCALLBACK read; /* [in] Read callback for the codec for when FMOD tries to read some data from the file to the destination format (specified in the open callback). */
|
||||
FMOD_CODEC_GETLENGTHCALLBACK getlength; /* [in] Callback to return the length of the song in whatever format required when Sound::getLength is called. */
|
||||
FMOD_CODEC_SETPOSITIONCALLBACK setposition; /* [in] Seek callback for the codec for when FMOD tries to seek within the file with Channel::setPosition. */
|
||||
FMOD_CODEC_GETPOSITIONCALLBACK getposition; /* [in] Tell callback for the codec for when FMOD tries to get the current position within the with Channel::getPosition. */
|
||||
FMOD_CODEC_SOUNDCREATECALLBACK soundcreate; /* [in] Sound creation callback for the codec when FMOD finishes creating the sound. (So the codec can set more parameters for the related created sound, ie loop points/mode or 3D attributes etc). */
|
||||
FMOD_CODEC_GETWAVEFORMAT getwaveformat; /* [in] Callback to tell FMOD about the waveformat of a particular subsound. This is to save memory, rather than saving 1000 FMOD_CODEC_WAVEFORMAT structures in the codec, the codec might have a more optimal way of storing this information. */
|
||||
} FMOD_CODEC_DESCRIPTION;
|
||||
|
||||
|
||||
/*
|
||||
[STRUCTURE]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Set these values marked 'in' to tell fmod what sort of sound to create.
|
||||
The format, channels and frequency tell FMOD what sort of hardware buffer to create when you initialize your code. So if you wrote an MP3 codec that decoded to stereo 16bit integer PCM, you would specify FMOD_SOUND_FORMAT_PCM16, and channels would be equal to 2.
|
||||
Members marked as 'out' are set by fmod. Do not modify these. Simply specify 0 for these values when declaring the structure, FMOD will fill in the values for you after creation with the correct function pointers.
|
||||
|
||||
[REMARKS]
|
||||
Members marked with [in] mean the variable can be written to. The user can set the value.
|
||||
Members marked with [out] mean the variable is modified by FMOD and is for reading purposes only. Do not change this value.
|
||||
|
||||
An FMOD file might be from disk, memory or network, however the file may be opened by the user.
|
||||
|
||||
'numsubsounds' should be 0 if the file is a normal single sound stream or sound. Examples of this would be .WAV, .WMA, .MP3, .AIFF.
|
||||
'numsubsounds' should be 1+ if the file is a container format, and does not contain wav data itself. Examples of these types would be CDDA (multiple CD tracks), FSB (contains multiple sounds), MIDI/MOD/S3M/XM/IT (contain instruments).
|
||||
The arrays of format, channel, frequency, length and blockalign should point to arrays of information based on how many subsounds are in the format. If the number of subsounds is 0 then it should point to 1 of each attribute, the same as if the number of subsounds was 1. If subsounds was 100 for example, each pointer should point to an array of 100 of each attribute.
|
||||
When a sound has 1 or more subsounds, you must play the individual sounds specified by first obtaining the subsound with Sound::getSubSound.
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
FMOD_SOUND_FORMAT
|
||||
FMOD_FILE_READCALLBACK
|
||||
FMOD_FILE_SEEKCALLBACK
|
||||
FMOD_CODEC_METADATACALLBACK
|
||||
Sound::getSubSound
|
||||
Sound::getNumSubSounds
|
||||
]
|
||||
*/
|
||||
struct FMOD_CODEC_WAVEFORMAT
|
||||
{
|
||||
char name[256]; /* [in] Name of sound.*/
|
||||
FMOD_SOUND_FORMAT format; /* [in] Format for (decompressed) codec output, ie FMOD_SOUND_FORMAT_PCM8, FMOD_SOUND_FORMAT_PCM16.*/
|
||||
int channels; /* [in] Number of channels used by codec, ie mono = 1, stereo = 2. */
|
||||
int frequency; /* [in] Default frequency in hz of the codec, ie 44100. */
|
||||
unsigned int lengthbytes; /* [in] Length in bytes of the source data. */
|
||||
unsigned int lengthpcm; /* [in] Length in decompressed, PCM samples of the file, ie length in seconds * frequency. Used for Sound::getLength and for memory allocation of static decompressed sample data. */
|
||||
int blockalign; /* [in] Blockalign in decompressed, PCM samples of the optimal decode chunk size for this format. The codec read callback will be called in multiples of this value. */
|
||||
int loopstart; /* [in] Loopstart in decompressed, PCM samples of file. */
|
||||
int loopend; /* [in] Loopend in decompressed, PCM samples of file. */
|
||||
FMOD_MODE mode; /* [in] Mode to determine whether the sound should by default load as looping, non looping, 2d or 3d. */
|
||||
unsigned int channelmask; /* [in] Microsoft speaker channel mask, as defined for WAVEFORMATEXTENSIBLE and is found in ksmedia.h. Leave at 0 to play in natural speaker order. */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
[STRUCTURE]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Codec plugin structure that is passed into each callback.
|
||||
|
||||
Set these numsubsounds and waveformat members when called in FMOD_CODEC_OPENCALLBACK to tell fmod what sort of sound to create.
|
||||
|
||||
The format, channels and frequency tell FMOD what sort of hardware buffer to create when you initialize your code. So if you wrote an MP3 codec that decoded to stereo 16bit integer PCM, you would specify FMOD_SOUND_FORMAT_PCM16, and channels would be equal to 2.
|
||||
|
||||
[REMARKS]
|
||||
Members marked with [in] mean the variable can be written to. The user can set the value.
|
||||
Members marked with [out] mean the variable is modified by FMOD and is for reading purposes only. Do not change this value.
|
||||
|
||||
An FMOD file might be from disk, memory or internet, however the file may be opened by the user.
|
||||
|
||||
'numsubsounds' should be 0 if the file is a normal single sound stream or sound. Examples of this would be .WAV, .WMA, .MP3, .AIFF.
|
||||
'numsubsounds' should be 1+ if the file is a container format, and does not contain wav data itself. Examples of these types would be CDDA (multiple CD tracks), FSB (contains multiple sounds), DLS (contain instruments).
|
||||
The arrays of format, channel, frequency, length and blockalign should point to arrays of information based on how many subsounds are in the format. If the number of subsounds is 0 then it should point to 1 of each attribute, the same as if the number of subsounds was 1. If subsounds was 100 for example, each pointer should point to an array of 100 of each attribute.
|
||||
When a sound has 1 or more subsounds, you must play the individual sounds specified by first obtaining the subsound with Sound::getSubSound.
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
FMOD_SOUND_FORMAT
|
||||
FMOD_FILE_READCALLBACK
|
||||
FMOD_FILE_SEEKCALLBACK
|
||||
FMOD_CODEC_METADATACALLBACK
|
||||
Sound::getSubSound
|
||||
Sound::getNumSubSounds
|
||||
]
|
||||
*/
|
||||
struct FMOD_CODEC_STATE
|
||||
{
|
||||
int numsubsounds; /* [in] Number of 'subsounds' in this sound. Anything other than 0 makes it a 'container' format (ie CDDA/DLS/FSB etc which contain 1 or more su bsounds). For most normal, single sound codec such as WAV/AIFF/MP3, this should be 0 as they are not a container for subsounds, they are the sound by itself. */
|
||||
FMOD_CODEC_WAVEFORMAT *waveformat; /* [in] Pointer to an array of format structures containing information about each sample. Can be 0 or NULL if FMOD_CODEC_GETWAVEFORMAT callback is preferred. The number of entries here must equal the number of subsounds defined in the subsound parameter. If numsubsounds = 0 then there should be 1 instance of this structure. */
|
||||
void *plugindata; /* [in] Plugin writer created data the codec author wants to attach to this object. */
|
||||
|
||||
void *filehandle; /* [out] This will return an internal FMOD file handle to use with the callbacks provided. */
|
||||
unsigned int filesize; /* [out] This will contain the size of the file in bytes. */
|
||||
FMOD_FILE_READCALLBACK fileread; /* [out] This will return a callable FMOD file function to use from codec. */
|
||||
FMOD_FILE_SEEKCALLBACK fileseek; /* [out] This will return a callable FMOD file function to use from codec. */
|
||||
FMOD_CODEC_METADATACALLBACK metadata; /* [out] This will return a callable FMOD metadata function to use from codec. */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -1,743 +0,0 @@
|
|||
/* ========================================================================================== */
|
||||
/* FMOD Ex - DSP header file. Copyright (c), Firelight Technologies Pty, Ltd. 2004-2011. */
|
||||
/* */
|
||||
/* Use this header if you are interested in delving deeper into the FMOD software mixing / */
|
||||
/* DSP engine. In this header you can find parameter structures for FMOD system reigstered */
|
||||
/* DSP effects and generators. */
|
||||
/* Also use this header if you are wanting to develop your own DSP plugin to use with FMOD's */
|
||||
/* dsp system. With this header you can make your own DSP plugin that FMOD can */
|
||||
/* register and use. See the documentation and examples on how to make a working plugin. */
|
||||
/* */
|
||||
/* ========================================================================================== */
|
||||
|
||||
#ifndef _FMOD_DSP_H
|
||||
#define _FMOD_DSP_H
|
||||
|
||||
typedef struct FMOD_DSP_STATE FMOD_DSP_STATE;
|
||||
|
||||
/*
|
||||
DSP callbacks
|
||||
*/
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_DSP_CREATECALLBACK) (FMOD_DSP_STATE *dsp_state);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_DSP_RELEASECALLBACK) (FMOD_DSP_STATE *dsp_state);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_DSP_RESETCALLBACK) (FMOD_DSP_STATE *dsp_state);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_DSP_READCALLBACK) (FMOD_DSP_STATE *dsp_state, float *inbuffer, float *outbuffer, unsigned int length, int inchannels, int outchannels);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_DSP_SETPOSITIONCALLBACK)(FMOD_DSP_STATE *dsp_state, unsigned int pos);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_DSP_SETPARAMCALLBACK) (FMOD_DSP_STATE *dsp_state, int index, float value);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_DSP_GETPARAMCALLBACK) (FMOD_DSP_STATE *dsp_state, int index, float *value, char *valuestr);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_DSP_DIALOGCALLBACK) (FMOD_DSP_STATE *dsp_state, void *hwnd, int show);
|
||||
|
||||
/*
|
||||
[ENUM]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
These definitions can be used for creating FMOD defined special effects or DSP units.
|
||||
|
||||
[REMARKS]
|
||||
To get them to be active, first create the unit, then add it somewhere into the DSP network, either at the front of the network near the soundcard unit to affect the global output (by using System::getDSPHead), or on a single channel (using Channel::getDSPHead).
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
System::createDSPByType
|
||||
]
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FMOD_DSP_TYPE_UNKNOWN, /* This unit was created via a non FMOD plugin so has an unknown purpose. */
|
||||
FMOD_DSP_TYPE_MIXER, /* This unit does nothing but take inputs and mix them together then feed the result to the soundcard unit. */
|
||||
FMOD_DSP_TYPE_OSCILLATOR, /* This unit generates sine/square/saw/triangle or noise tones. */
|
||||
FMOD_DSP_TYPE_LOWPASS, /* This unit filters sound using a high quality, resonant lowpass filter algorithm but consumes more CPU time. */
|
||||
FMOD_DSP_TYPE_ITLOWPASS, /* This unit filters sound using a resonant lowpass filter algorithm that is used in Impulse Tracker, but with limited cutoff range (0 to 8060hz). */
|
||||
FMOD_DSP_TYPE_HIGHPASS, /* This unit filters sound using a resonant highpass filter algorithm. */
|
||||
FMOD_DSP_TYPE_ECHO, /* This unit produces an echo on the sound and fades out at the desired rate. */
|
||||
FMOD_DSP_TYPE_FLANGE, /* This unit produces a flange effect on the sound. */
|
||||
FMOD_DSP_TYPE_DISTORTION, /* This unit distorts the sound. */
|
||||
FMOD_DSP_TYPE_NORMALIZE, /* This unit normalizes or amplifies the sound to a certain level. */
|
||||
FMOD_DSP_TYPE_PARAMEQ, /* This unit attenuates or amplifies a selected frequency range. */
|
||||
FMOD_DSP_TYPE_PITCHSHIFT, /* This unit bends the pitch of a sound without changing the speed of playback. */
|
||||
FMOD_DSP_TYPE_CHORUS, /* This unit produces a chorus effect on the sound. */
|
||||
FMOD_DSP_TYPE_VSTPLUGIN, /* This unit allows the use of Steinberg VST plugins */
|
||||
FMOD_DSP_TYPE_WINAMPPLUGIN, /* This unit allows the use of Nullsoft Winamp plugins */
|
||||
FMOD_DSP_TYPE_ITECHO, /* This unit produces an echo on the sound and fades out at the desired rate as is used in Impulse Tracker. */
|
||||
FMOD_DSP_TYPE_COMPRESSOR, /* This unit implements dynamic compression (linked multichannel, wideband) */
|
||||
FMOD_DSP_TYPE_SFXREVERB, /* This unit implements SFX reverb */
|
||||
FMOD_DSP_TYPE_LOWPASS_SIMPLE, /* This unit filters sound using a simple lowpass with no resonance, but has flexible cutoff and is fast. */
|
||||
FMOD_DSP_TYPE_DELAY, /* This unit produces different delays on individual channels of the sound. */
|
||||
FMOD_DSP_TYPE_TREMOLO, /* This unit produces a tremolo / chopper effect on the sound. */
|
||||
FMOD_DSP_TYPE_LADSPAPLUGIN, /* This unit allows the use of LADSPA standard plugins. */
|
||||
FMOD_DSP_TYPE_HIGHPASS_SIMPLE, /* This unit filters sound using a simple highpass with no resonance, but has flexible cutoff and is fast. */
|
||||
FMOD_DSP_TYPE_HARDWARE = 1000, /* Offset that platform specific FMOD_HARDWARE DSPs will start at. */
|
||||
FMOD_DSP_TYPE_FORCEINT = 65536 /* Makes sure this enum is signed 32bit. */
|
||||
} FMOD_DSP_TYPE;
|
||||
|
||||
|
||||
/*
|
||||
[STRUCTURE]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Structure to define a parameter for a DSP unit.
|
||||
|
||||
[REMARKS]
|
||||
Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only. Do not change this value.
|
||||
Members marked with [w] mean the variable can be written to. The user can set the value.
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
System::createDSP
|
||||
DSP::setParameter
|
||||
]
|
||||
*/
|
||||
typedef struct FMOD_DSP_PARAMETERDESC
|
||||
{
|
||||
float min; /* [w] Minimum value of the parameter (ie 100.0). */
|
||||
float max; /* [w] Maximum value of the parameter (ie 22050.0). */
|
||||
float defaultval; /* [w] Default value of parameter. */
|
||||
char name[16]; /* [w] Name of the parameter to be displayed (ie "Cutoff frequency"). */
|
||||
char label[16]; /* [w] Short string to be put next to value to denote the unit type (ie "hz"). */
|
||||
const char *description; /* [w] Description of the parameter to be displayed as a help item / tooltip for this parameter. */
|
||||
} FMOD_DSP_PARAMETERDESC;
|
||||
|
||||
|
||||
/*
|
||||
[STRUCTURE]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
When creating a DSP unit, declare one of these and provide the relevant callbacks and name for FMOD to use when it creates and uses a DSP unit of this type.
|
||||
|
||||
[REMARKS]
|
||||
Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only. Do not change this value.
|
||||
Members marked with [w] mean the variable can be written to. The user can set the value.
|
||||
|
||||
There are 2 different ways to change a parameter in this architecture.
|
||||
One is to use DSP::setParameter / DSP::getParameter. This is platform independant and is dynamic, so new unknown plugins can have their parameters enumerated and used.
|
||||
The other is to use DSP::showConfigDialog. This is platform specific and requires a GUI, and will display a dialog box to configure the plugin.
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
System::createDSP
|
||||
FMOD_DSP_STATE
|
||||
]
|
||||
*/
|
||||
typedef struct FMOD_DSP_DESCRIPTION
|
||||
{
|
||||
char name[32]; /* [w] Name of the unit to be displayed in the network. */
|
||||
unsigned int version; /* [w] Plugin writer's version number. */
|
||||
int channels; /* [w] Number of channels. Use 0 to process whatever number of channels is currently in the network. >0 would be mostly used if the unit is a unit that only generates sound. */
|
||||
FMOD_DSP_CREATECALLBACK create; /* [w] Create callback. This is called when DSP unit is created. Can be null. */
|
||||
FMOD_DSP_RELEASECALLBACK release; /* [w] Release callback. This is called just before the unit is freed so the user can do any cleanup needed for the unit. Can be null. */
|
||||
FMOD_DSP_RESETCALLBACK reset; /* [w] Reset callback. This is called by the user to reset any history buffers that may need resetting for a filter, when it is to be used or re-used for the first time to its initial clean state. Use to avoid clicks or artifacts. */
|
||||
FMOD_DSP_READCALLBACK read; /* [w] Read callback. Processing is done here. Can be null. */
|
||||
FMOD_DSP_SETPOSITIONCALLBACK setposition; /* [w] Set position callback. This is called if the unit wants to update its position info but not process data, or reset a cursor position internally if it is reading data from a certain source. Can be null. */
|
||||
|
||||
int numparameters; /* [w] Number of parameters used in this filter. The user finds this with DSP::getNumParameters */
|
||||
FMOD_DSP_PARAMETERDESC *paramdesc; /* [w] Variable number of parameter structures. */
|
||||
FMOD_DSP_SETPARAMCALLBACK setparameter; /* [w] This is called when the user calls DSP::setParameter. Can be null. */
|
||||
FMOD_DSP_GETPARAMCALLBACK getparameter; /* [w] This is called when the user calls DSP::getParameter. Can be null. */
|
||||
FMOD_DSP_DIALOGCALLBACK config; /* [w] This is called when the user calls DSP::showConfigDialog. Can be used to display a dialog to configure the filter. Can be null. */
|
||||
int configwidth; /* [w] Width of config dialog graphic if there is one. 0 otherwise.*/
|
||||
int configheight; /* [w] Height of config dialog graphic if there is one. 0 otherwise.*/
|
||||
void *userdata; /* [w] Optional. Specify 0 to ignore. This is user data to be attached to the DSP unit during creation. Access via DSP::getUserData. */
|
||||
} FMOD_DSP_DESCRIPTION;
|
||||
|
||||
|
||||
/*
|
||||
[STRUCTURE]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
DSP plugin structure that is passed into each callback.
|
||||
|
||||
[REMARKS]
|
||||
Members marked with [r] mean the variable is modified by FMOD and is for reading purposes only. Do not change this value.
|
||||
Members marked with [w] mean the variable can be written to. The user can set the value.
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
FMOD_DSP_DESCRIPTION
|
||||
]
|
||||
*/
|
||||
struct FMOD_DSP_STATE
|
||||
{
|
||||
FMOD_DSP *instance; /* [r] Handle to the DSP hand the user created. Not to be modified. C++ users cast to FMOD::DSP to use. */
|
||||
void *plugindata; /* [w] Plugin writer created data the output author wants to attach to this object. */
|
||||
unsigned short speakermask; /* [w] Specifies which speakers the DSP effect is active on */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
===================================================================================================
|
||||
|
||||
FMOD built in effect parameters.
|
||||
Use DSP::setParameter with these enums for the 'index' parameter.
|
||||
|
||||
===================================================================================================
|
||||
*/
|
||||
|
||||
/*
|
||||
[ENUM]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Parameter types for the FMOD_DSP_TYPE_OSCILLATOR filter.
|
||||
|
||||
[REMARKS]
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
DSP::setParameter
|
||||
DSP::getParameter
|
||||
FMOD_DSP_TYPE
|
||||
]
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FMOD_DSP_OSCILLATOR_TYPE, /* Waveform type. 0 = sine. 1 = square. 2 = sawup. 3 = sawdown. 4 = triangle. 5 = noise. */
|
||||
FMOD_DSP_OSCILLATOR_RATE /* Frequency of the sinewave in hz. 1.0 to 22000.0. Default = 220.0. */
|
||||
} FMOD_DSP_OSCILLATOR;
|
||||
|
||||
|
||||
/*
|
||||
[ENUM]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Parameter types for the FMOD_DSP_TYPE_LOWPASS filter.
|
||||
|
||||
[REMARKS]
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
DSP::setParameter
|
||||
DSP::getParameter
|
||||
FMOD_DSP_TYPE
|
||||
]
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FMOD_DSP_LOWPASS_CUTOFF, /* Lowpass cutoff frequency in hz. 10.0 to 22000.0. Default = 5000.0. */
|
||||
FMOD_DSP_LOWPASS_RESONANCE /* Lowpass resonance Q value. 1.0 to 10.0. Default = 1.0. */
|
||||
} FMOD_DSP_LOWPASS;
|
||||
|
||||
|
||||
/*
|
||||
[ENUM]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Parameter types for the FMOD_DSP_TYPE_ITLOWPASS filter.
|
||||
This is different to the default FMOD_DSP_TYPE_ITLOWPASS filter in that it uses a different quality algorithm and is
|
||||
the filter used to produce the correct sounding playback in .IT files.
|
||||
FMOD Ex's .IT playback uses this filter.
|
||||
|
||||
[REMARKS]
|
||||
Note! This filter actually has a limited cutoff frequency below the specified maximum, due to its limited design,
|
||||
so for a more open range filter use FMOD_DSP_LOWPASS or if you don't mind not having resonance,
|
||||
FMOD_DSP_LOWPASS_SIMPLE.
|
||||
The effective maximum cutoff is about 8060hz.
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
DSP::setParameter
|
||||
DSP::getParameter
|
||||
FMOD_DSP_TYPE
|
||||
]
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FMOD_DSP_ITLOWPASS_CUTOFF, /* Lowpass cutoff frequency in hz. 1.0 to 22000.0. Default = 5000.0/ */
|
||||
FMOD_DSP_ITLOWPASS_RESONANCE /* Lowpass resonance Q value. 0.0 to 127.0. Default = 1.0. */
|
||||
} FMOD_DSP_ITLOWPASS;
|
||||
|
||||
|
||||
/*
|
||||
[ENUM]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Parameter types for the FMOD_DSP_TYPE_HIGHPASS filter.
|
||||
|
||||
[REMARKS]
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
DSP::setParameter
|
||||
DSP::getParameter
|
||||
FMOD_DSP_TYPE
|
||||
]
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FMOD_DSP_HIGHPASS_CUTOFF, /* Highpass cutoff frequency in hz. 1.0 to output 22000.0. Default = 5000.0. */
|
||||
FMOD_DSP_HIGHPASS_RESONANCE /* Highpass resonance Q value. 1.0 to 10.0. Default = 1.0. */
|
||||
} FMOD_DSP_HIGHPASS;
|
||||
|
||||
|
||||
/*
|
||||
[ENUM]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Parameter types for the FMOD_DSP_TYPE_ECHO filter.
|
||||
|
||||
[REMARKS]
|
||||
Note. Every time the delay is changed, the plugin re-allocates the echo buffer. This means the echo will dissapear at that time while it refills its new buffer.
|
||||
Larger echo delays result in larger amounts of memory allocated.
|
||||
|
||||
'<i>maxchannels</i>' also dictates the amount of memory allocated. By default, the maxchannels value is 0. If FMOD is set to stereo, the echo unit will allocate enough memory for 2 channels. If it is 5.1, it will allocate enough memory for a 6 channel echo, etc.
|
||||
If the echo effect is only ever applied to the global mix (ie it was added with System::addDSP), then 0 is the value to set as it will be enough to handle all speaker modes.
|
||||
When the echo is added to a channel (ie Channel::addDSP) then the channel count that comes in could be anything from 1 to 8 possibly. It is only in this case where you might want to increase the channel count above the output's channel count.
|
||||
If a channel echo is set to a lower number than the sound's channel count that is coming in, it will not echo the sound.
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
DSP::setParameter
|
||||
DSP::getParameter
|
||||
FMOD_DSP_TYPE
|
||||
]
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FMOD_DSP_ECHO_DELAY, /* Echo delay in ms. 10 to 5000. Default = 500. */
|
||||
FMOD_DSP_ECHO_DECAYRATIO, /* Echo decay per delay. 0 to 1. 1.0 = No decay, 0.0 = total decay (ie simple 1 line delay). Default = 0.5. */
|
||||
FMOD_DSP_ECHO_MAXCHANNELS, /* Maximum channels supported. 0 to 16. 0 = same as fmod's default output polyphony, 1 = mono, 2 = stereo etc. See remarks for more. Default = 0. It is suggested to leave at 0! */
|
||||
FMOD_DSP_ECHO_DRYMIX, /* Volume of original signal to pass to output. 0.0 to 1.0. Default = 1.0. */
|
||||
FMOD_DSP_ECHO_WETMIX /* Volume of echo signal to pass to output. 0.0 to 1.0. Default = 1.0. */
|
||||
} FMOD_DSP_ECHO;
|
||||
|
||||
|
||||
/*
|
||||
[ENUM]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Parameter types for the FMOD_DSP_TYPE_DELAY filter.
|
||||
|
||||
[REMARKS]
|
||||
Note. Every time MaxDelay is changed, the plugin re-allocates the delay buffer. This means the delay will dissapear at that time while it refills its new buffer.
|
||||
A larger MaxDelay results in larger amounts of memory allocated.
|
||||
Channel delays above MaxDelay will be clipped to MaxDelay and the delay buffer will not be resized.
|
||||
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
DSP::setParameter
|
||||
DSP::getParameter
|
||||
FMOD_DSP_TYPE
|
||||
]
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FMOD_DSP_DELAY_CH0, /* Channel #0 Delay in ms. 0 to 10000. Default = 0. */
|
||||
FMOD_DSP_DELAY_CH1, /* Channel #1 Delay in ms. 0 to 10000. Default = 0. */
|
||||
FMOD_DSP_DELAY_CH2, /* Channel #2 Delay in ms. 0 to 10000. Default = 0. */
|
||||
FMOD_DSP_DELAY_CH3, /* Channel #3 Delay in ms. 0 to 10000. Default = 0. */
|
||||
FMOD_DSP_DELAY_CH4, /* Channel #4 Delay in ms. 0 to 10000. Default = 0. */
|
||||
FMOD_DSP_DELAY_CH5, /* Channel #5 Delay in ms. 0 to 10000. Default = 0. */
|
||||
FMOD_DSP_DELAY_CH6, /* Channel #6 Delay in ms. 0 to 10000. Default = 0. */
|
||||
FMOD_DSP_DELAY_CH7, /* Channel #7 Delay in ms. 0 to 10000. Default = 0. */
|
||||
FMOD_DSP_DELAY_CH8, /* Channel #8 Delay in ms. 0 to 10000. Default = 0. */
|
||||
FMOD_DSP_DELAY_CH9, /* Channel #9 Delay in ms. 0 to 10000. Default = 0. */
|
||||
FMOD_DSP_DELAY_CH10, /* Channel #10 Delay in ms. 0 to 10000. Default = 0. */
|
||||
FMOD_DSP_DELAY_CH11, /* Channel #11 Delay in ms. 0 to 10000. Default = 0. */
|
||||
FMOD_DSP_DELAY_CH12, /* Channel #12 Delay in ms. 0 to 10000. Default = 0. */
|
||||
FMOD_DSP_DELAY_CH13, /* Channel #13 Delay in ms. 0 to 10000. Default = 0. */
|
||||
FMOD_DSP_DELAY_CH14, /* Channel #14 Delay in ms. 0 to 10000. Default = 0. */
|
||||
FMOD_DSP_DELAY_CH15, /* Channel #15 Delay in ms. 0 to 10000. Default = 0. */
|
||||
FMOD_DSP_DELAY_MAXDELAY /* Maximum delay in ms. 0 to 10000. Default = 10. */
|
||||
} FMOD_DSP_DELAY;
|
||||
|
||||
|
||||
/*
|
||||
[ENUM]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Parameter types for the FMOD_DSP_TYPE_FLANGE filter.
|
||||
|
||||
[REMARKS]
|
||||
Flange is an effect where the signal is played twice at the same time, and one copy slides back and forth creating a whooshing or flanging effect.
|
||||
As there are 2 copies of the same signal, by default each signal is given 50% mix, so that the total is not louder than the original unaffected signal.
|
||||
|
||||
Flange depth is a percentage of a 10ms shift from the original signal. Anything above 10ms is not considered flange because to the ear it begins to 'echo' so 10ms is the highest value possible.
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
DSP::setParameter
|
||||
DSP::getParameter
|
||||
FMOD_DSP_TYPE
|
||||
]
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FMOD_DSP_FLANGE_DRYMIX, /* Volume of original signal to pass to output. 0.0 to 1.0. Default = 0.45. */
|
||||
FMOD_DSP_FLANGE_WETMIX, /* Volume of flange signal to pass to output. 0.0 to 1.0. Default = 0.55. */
|
||||
FMOD_DSP_FLANGE_DEPTH, /* Flange depth (percentage of 40ms delay). 0.01 to 1.0. Default = 1.0. */
|
||||
FMOD_DSP_FLANGE_RATE /* Flange speed in hz. 0.0 to 20.0. Default = 0.1. */
|
||||
} FMOD_DSP_FLANGE;
|
||||
|
||||
|
||||
/*
|
||||
[ENUM]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Parameter types for the FMOD_DSP_TYPE_TREMOLO filter.
|
||||
|
||||
[REMARKS]
|
||||
The tremolo effect varies the amplitude of a sound. Depending on the settings, this unit can produce a tremolo, chopper or auto-pan effect.
|
||||
|
||||
The shape of the LFO (low freq. oscillator) can morphed between sine, triangle and sawtooth waves using the FMOD_DSP_TREMOLO_SHAPE and FMOD_DSP_TREMOLO_SKEW parameters.
|
||||
FMOD_DSP_TREMOLO_DUTY and FMOD_DSP_TREMOLO_SQUARE are useful for a chopper-type effect where the first controls the on-time duration and second controls the flatness of the envelope.
|
||||
FMOD_DSP_TREMOLO_SPREAD varies the LFO phase between channels to get an auto-pan effect. This works best with a sine shape LFO.
|
||||
The LFO can be synchronized using the FMOD_DSP_TREMOLO_PHASE parameter which sets its instantaneous phase.
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
DSP::setParameter
|
||||
DSP::getParameter
|
||||
FMOD_DSP_TYPE
|
||||
]
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FMOD_DSP_TREMOLO_FREQUENCY, /* LFO frequency in Hz. 0.1 to 20. Default = 4. */
|
||||
FMOD_DSP_TREMOLO_DEPTH, /* Tremolo depth. 0 to 1. Default = 0. */
|
||||
FMOD_DSP_TREMOLO_SHAPE, /* LFO shape morph between triangle and sine. 0 to 1. Default = 0. */
|
||||
FMOD_DSP_TREMOLO_SKEW, /* Time-skewing of LFO cycle. -1 to 1. Default = 0. */
|
||||
FMOD_DSP_TREMOLO_DUTY, /* LFO on-time. 0 to 1. Default = 0.5. */
|
||||
FMOD_DSP_TREMOLO_SQUARE, /* Flatness of the LFO shape. 0 to 1. Default = 0. */
|
||||
FMOD_DSP_TREMOLO_PHASE, /* Instantaneous LFO phase. 0 to 1. Default = 0. */
|
||||
FMOD_DSP_TREMOLO_SPREAD /* Rotation / auto-pan effect. -1 to 1. Default = 0. */
|
||||
} FMOD_DSP_TREMOLO;
|
||||
|
||||
|
||||
/*
|
||||
[ENUM]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Parameter types for the FMOD_DSP_TYPE_DISTORTION filter.
|
||||
|
||||
[REMARKS]
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
DSP::setParameter
|
||||
DSP::getParameter
|
||||
FMOD_DSP_TYPE
|
||||
]
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FMOD_DSP_DISTORTION_LEVEL /* Distortion value. 0.0 to 1.0. Default = 0.5. */
|
||||
} FMOD_DSP_DISTORTION;
|
||||
|
||||
|
||||
/*
|
||||
[ENUM]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Parameter types for the FMOD_DSP_TYPE_NORMALIZE filter.
|
||||
|
||||
[REMARKS]
|
||||
Normalize amplifies the sound based on the maximum peaks within the signal.
|
||||
For example if the maximum peaks in the signal were 50% of the bandwidth, it would scale the whole sound by 2.
|
||||
The lower threshold value makes the normalizer ignores peaks below a certain point, to avoid over-amplification if a loud signal suddenly came in, and also to avoid amplifying to maximum things like background hiss.
|
||||
|
||||
Because FMOD is a realtime audio processor, it doesn't have the luxury of knowing the peak for the whole sound (ie it can't see into the future), so it has to process data as it comes in.
|
||||
To avoid very sudden changes in volume level based on small samples of new data, fmod fades towards the desired amplification which makes for smooth gain control. The fadetime parameter can control this.
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
DSP::setParameter
|
||||
DSP::getParameter
|
||||
FMOD_DSP_TYPE
|
||||
]
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FMOD_DSP_NORMALIZE_FADETIME, /* Time to ramp the silence to full in ms. 0.0 to 20000.0. Default = 5000.0. */
|
||||
FMOD_DSP_NORMALIZE_THRESHHOLD, /* Lower volume range threshold to ignore. 0.0 to 1.0. Default = 0.1. Raise higher to stop amplification of very quiet signals. */
|
||||
FMOD_DSP_NORMALIZE_MAXAMP /* Maximum amplification allowed. 1.0 to 100000.0. Default = 20.0. 1.0 = no amplifaction, higher values allow more boost. */
|
||||
} FMOD_DSP_NORMALIZE;
|
||||
|
||||
|
||||
/*
|
||||
[ENUM]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Parameter types for the FMOD_DSP_TYPE_PARAMEQ filter.
|
||||
|
||||
[REMARKS]
|
||||
Parametric EQ is a bandpass filter that attenuates or amplifies a selected frequency and its neighbouring frequencies.
|
||||
|
||||
To create a multi-band EQ create multiple FMOD_DSP_TYPE_PARAMEQ units and set each unit to different frequencies, for example 1000hz, 2000hz, 4000hz, 8000hz, 16000hz with a range of 1 octave each.
|
||||
|
||||
When a frequency has its gain set to 1.0, the sound will be unaffected and represents the original signal exactly.
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
DSP::setParameter
|
||||
DSP::getParameter
|
||||
FMOD_DSP_TYPE
|
||||
]
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FMOD_DSP_PARAMEQ_CENTER, /* Frequency center. 20.0 to 22000.0. Default = 8000.0. */
|
||||
FMOD_DSP_PARAMEQ_BANDWIDTH, /* Octave range around the center frequency to filter. 0.2 to 5.0. Default = 1.0. */
|
||||
FMOD_DSP_PARAMEQ_GAIN /* Frequency Gain. 0.05 to 3.0. Default = 1.0. */
|
||||
} FMOD_DSP_PARAMEQ;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
[ENUM]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Parameter types for the FMOD_DSP_TYPE_PITCHSHIFT filter.
|
||||
|
||||
[REMARKS]
|
||||
This pitch shifting unit can be used to change the pitch of a sound without speeding it up or slowing it down.
|
||||
It can also be used for time stretching or scaling, for example if the pitch was doubled, and the frequency of the sound was halved, the pitch of the sound would sound correct but it would be twice as slow.
|
||||
|
||||
<b>Warning!</b> This filter is very computationally expensive! Similar to a vocoder, it requires several overlapping FFT and IFFT's to produce smooth output, and can require around 440mhz for 1 stereo 48khz signal using the default settings.
|
||||
Reducing the signal to mono will half the cpu usage.
|
||||
Reducing this will lower audio quality, but what settings to use are largely dependant on the sound being played. A noisy polyphonic signal will need higher fft size compared to a speaking voice for example.
|
||||
|
||||
This pitch shifter is based on the pitch shifter code at http://www.dspdimension.com, written by Stephan M. Bernsee.
|
||||
The original code is COPYRIGHT 1999-2003 Stephan M. Bernsee <smb@dspdimension.com>.
|
||||
|
||||
'<i>maxchannels</i>' dictates the amount of memory allocated. By default, the maxchannels value is 0. If FMOD is set to stereo, the pitch shift unit will allocate enough memory for 2 channels. If it is 5.1, it will allocate enough memory for a 6 channel pitch shift, etc.
|
||||
If the pitch shift effect is only ever applied to the global mix (ie it was added with System::addDSP), then 0 is the value to set as it will be enough to handle all speaker modes.
|
||||
When the pitch shift is added to a channel (ie Channel::addDSP) then the channel count that comes in could be anything from 1 to 8 possibly. It is only in this case where you might want to increase the channel count above the output's channel count.
|
||||
If a channel pitch shift is set to a lower number than the sound's channel count that is coming in, it will not pitch shift the sound.
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
DSP::setParameter
|
||||
DSP::getParameter
|
||||
FMOD_DSP_TYPE
|
||||
]
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FMOD_DSP_PITCHSHIFT_PITCH, /* Pitch value. 0.5 to 2.0. Default = 1.0. 0.5 = one octave down, 2.0 = one octave up. 1.0 does not change the pitch. */
|
||||
FMOD_DSP_PITCHSHIFT_FFTSIZE, /* FFT window size. 256, 512, 1024, 2048, 4096. Default = 1024. Increase this to reduce 'smearing'. This effect is a warbling sound similar to when an mp3 is encoded at very low bitrates. */
|
||||
FMOD_DSP_PITCHSHIFT_OVERLAP, /* Removed. Do not use. FMOD now uses 4 overlaps and cannot be changed. */
|
||||
FMOD_DSP_PITCHSHIFT_MAXCHANNELS /* Maximum channels supported. 0 to 16. 0 = same as fmod's default output polyphony, 1 = mono, 2 = stereo etc. See remarks for more. Default = 0. It is suggested to leave at 0! */
|
||||
} FMOD_DSP_PITCHSHIFT;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
[ENUM]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Parameter types for the FMOD_DSP_TYPE_CHORUS filter.
|
||||
|
||||
[REMARKS]
|
||||
Chrous is an effect where the sound is more 'spacious' due to 1 to 3 versions of the sound being played along side the original signal but with the pitch of each copy modulating on a sine wave.
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
DSP::setParameter
|
||||
DSP::getParameter
|
||||
FMOD_DSP_TYPE
|
||||
]
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FMOD_DSP_CHORUS_DRYMIX, /* Volume of original signal to pass to output. 0.0 to 1.0. Default = 0.5. */
|
||||
FMOD_DSP_CHORUS_WETMIX1, /* Volume of 1st chorus tap. 0.0 to 1.0. Default = 0.5. */
|
||||
FMOD_DSP_CHORUS_WETMIX2, /* Volume of 2nd chorus tap. This tap is 90 degrees out of phase of the first tap. 0.0 to 1.0. Default = 0.5. */
|
||||
FMOD_DSP_CHORUS_WETMIX3, /* Volume of 3rd chorus tap. This tap is 90 degrees out of phase of the second tap. 0.0 to 1.0. Default = 0.5. */
|
||||
FMOD_DSP_CHORUS_DELAY, /* Chorus delay in ms. 0.1 to 100.0. Default = 40.0 ms. */
|
||||
FMOD_DSP_CHORUS_RATE, /* Chorus modulation rate in hz. 0.0 to 20.0. Default = 0.8 hz. */
|
||||
FMOD_DSP_CHORUS_DEPTH /* Chorus modulation depth. 0.0 to 1.0. Default = 0.03. */
|
||||
} FMOD_DSP_CHORUS;
|
||||
|
||||
|
||||
/*
|
||||
[ENUM]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Parameter types for the FMOD_DSP_TYPE_ITECHO filter.
|
||||
This is effectively a software based echo filter that emulates the DirectX DMO echo effect. Impulse tracker files can support this, and FMOD will produce the effect on ANY platform, not just those that support DirectX effects!
|
||||
|
||||
[REMARKS]
|
||||
Note. Every time the delay is changed, the plugin re-allocates the echo buffer. This means the echo will dissapear at that time while it refills its new buffer.
|
||||
Larger echo delays result in larger amounts of memory allocated.
|
||||
|
||||
As this is a stereo filter made mainly for IT playback, it is targeted for stereo signals.
|
||||
With mono signals only the FMOD_DSP_ITECHO_LEFTDELAY is used.
|
||||
For multichannel signals (>2) there will be no echo on those channels.
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
DSP::SetParameter
|
||||
DSP::GetParameter
|
||||
FMOD_DSP_TYPE
|
||||
System::addDSP
|
||||
]
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FMOD_DSP_ITECHO_WETDRYMIX, /* Ratio of wet (processed) signal to dry (unprocessed) signal. Must be in the range from 0.0 through 100.0 (all wet). The default value is 50. */
|
||||
FMOD_DSP_ITECHO_FEEDBACK, /* Percentage of output fed back into input, in the range from 0.0 through 100.0. The default value is 50. */
|
||||
FMOD_DSP_ITECHO_LEFTDELAY, /* Delay for left channel, in milliseconds, in the range from 1.0 through 2000.0. The default value is 500 ms. */
|
||||
FMOD_DSP_ITECHO_RIGHTDELAY, /* Delay for right channel, in milliseconds, in the range from 1.0 through 2000.0. The default value is 500 ms. */
|
||||
FMOD_DSP_ITECHO_PANDELAY /* Value that specifies whether to swap left and right delays with each successive echo. The default value is zero, meaning no swap. Possible values are defined as 0.0 (equivalent to FALSE) and 1.0 (equivalent to TRUE). CURRENTLY NOT SUPPORTED. */
|
||||
} FMOD_DSP_ITECHO;
|
||||
|
||||
/*
|
||||
[ENUM]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Parameter types for the FMOD_DSP_TYPE_COMPRESSOR unit.
|
||||
This is a simple linked multichannel software limiter that is uniform across the whole spectrum.
|
||||
|
||||
[REMARKS]
|
||||
The limiter is not guaranteed to catch every peak above the threshold level,
|
||||
because it cannot apply gain reduction instantaneously - the time delay is
|
||||
determined by the attack time. However setting the attack time too short will
|
||||
distort the sound, so it is a compromise. High level peaks can be avoided by
|
||||
using a short attack time - but not too short, and setting the threshold a few
|
||||
decibels below the critical level.
|
||||
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
DSP::SetParameter
|
||||
DSP::GetParameter
|
||||
FMOD_DSP_TYPE
|
||||
System::addDSP
|
||||
]
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FMOD_DSP_COMPRESSOR_THRESHOLD, /* Threshold level (dB) in the range from -60 through 0. The default value is 0. */
|
||||
FMOD_DSP_COMPRESSOR_ATTACK, /* Gain reduction attack time (milliseconds), in the range from 10 through 200. The default value is 50. */
|
||||
FMOD_DSP_COMPRESSOR_RELEASE, /* Gain reduction release time (milliseconds), in the range from 20 through 1000. The default value is 50. */
|
||||
FMOD_DSP_COMPRESSOR_GAINMAKEUP /* Make-up gain (dB) applied after limiting, in the range from 0 through 30. The default value is 0. */
|
||||
} FMOD_DSP_COMPRESSOR;
|
||||
|
||||
/*
|
||||
[ENUM]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Parameter types for the FMOD_DSP_TYPE_SFXREVERB unit.
|
||||
|
||||
[REMARKS]
|
||||
This is a high quality I3DL2 based reverb.
|
||||
On top of the I3DL2 property set, "Dry Level" is also included to allow the dry mix to be changed.
|
||||
|
||||
These properties can be set with presets in FMOD_REVERB_PRESETS.
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
DSP::SetParameter
|
||||
DSP::GetParameter
|
||||
FMOD_DSP_TYPE
|
||||
System::addDSP
|
||||
FMOD_REVERB_PRESETS
|
||||
]
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FMOD_DSP_SFXREVERB_DRYLEVEL, /* Dry Level : Mix level of dry signal in output in mB. Ranges from -10000.0 to 0.0. Default is 0. */
|
||||
FMOD_DSP_SFXREVERB_ROOM, /* Room : Room effect level at low frequencies in mB. Ranges from -10000.0 to 0.0. Default is -10000.0. */
|
||||
FMOD_DSP_SFXREVERB_ROOMHF, /* Room HF : Room effect high-frequency level re. low frequency level in mB. Ranges from -10000.0 to 0.0. Default is 0.0. */
|
||||
FMOD_DSP_SFXREVERB_DECAYTIME, /* Decay Time : Reverberation decay time at low-frequencies in seconds. Ranges from 0.1 to 20.0. Default is 1.0. */
|
||||
FMOD_DSP_SFXREVERB_DECAYHFRATIO, /* Decay HF Ratio : High-frequency to low-frequency decay time ratio. Ranges from 0.1 to 2.0. Default is 0.5. */
|
||||
FMOD_DSP_SFXREVERB_REFLECTIONSLEVEL, /* Reflections : Early reflections level relative to room effect in mB. Ranges from -10000.0 to 1000.0. Default is -10000.0. */
|
||||
FMOD_DSP_SFXREVERB_REFLECTIONSDELAY, /* Reflect Delay : Delay time of first reflection in seconds. Ranges from 0.0 to 0.3. Default is 0.02. */
|
||||
FMOD_DSP_SFXREVERB_REVERBLEVEL, /* Reverb : Late reverberation level relative to room effect in mB. Ranges from -10000.0 to 2000.0. Default is 0.0. */
|
||||
FMOD_DSP_SFXREVERB_REVERBDELAY, /* Reverb Delay : Late reverberation delay time relative to first reflection in seconds. Ranges from 0.0 to 0.1. Default is 0.04. */
|
||||
FMOD_DSP_SFXREVERB_DIFFUSION, /* Diffusion : Reverberation diffusion (echo density) in percent. Ranges from 0.0 to 100.0. Default is 100.0. */
|
||||
FMOD_DSP_SFXREVERB_DENSITY, /* Density : Reverberation density (modal density) in percent. Ranges from 0.0 to 100.0. Default is 100.0. */
|
||||
FMOD_DSP_SFXREVERB_HFREFERENCE, /* HF Reference : Reference high frequency in Hz. Ranges from 20.0 to 20000.0. Default is 5000.0. */
|
||||
FMOD_DSP_SFXREVERB_ROOMLF, /* Room LF : Room effect low-frequency level in mB. Ranges from -10000.0 to 0.0. Default is 0.0. */
|
||||
FMOD_DSP_SFXREVERB_LFREFERENCE /* LF Reference : Reference low-frequency in Hz. Ranges from 20.0 to 1000.0. Default is 250.0. */
|
||||
} FMOD_DSP_SFXREVERB;
|
||||
|
||||
/*
|
||||
[ENUM]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Parameter types for the FMOD_DSP_TYPE_LOWPASS_SIMPLE filter.
|
||||
This is a very simple low pass filter, based on two single-pole RC time-constant modules.
|
||||
The emphasis is on speed rather than accuracy, so this should not be used for task requiring critical filtering.
|
||||
|
||||
[REMARKS]
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
DSP::setParameter
|
||||
DSP::getParameter
|
||||
FMOD_DSP_TYPE
|
||||
]
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FMOD_DSP_LOWPASS_SIMPLE_CUTOFF /* Lowpass cutoff frequency in hz. 10.0 to 22000.0. Default = 5000.0 */
|
||||
} FMOD_DSP_LOWPASS_SIMPLE;
|
||||
|
||||
/*
|
||||
[ENUM]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Parameter types for the FMOD_DSP_TYPE_HIGHPASS_SIMPLE filter.
|
||||
This is a very simple single-order high pass filter.
|
||||
The emphasis is on speed rather than accuracy, so this should not be used for task requiring critical filtering.
|
||||
|
||||
[REMARKS]
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
DSP::setParameter
|
||||
DSP::getParameter
|
||||
FMOD_DSP_TYPE
|
||||
]
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FMOD_DSP_HIGHPASS_SIMPLE_CUTOFF /* Highpass cutoff frequency in hz. 10.0 to 22000.0. Default = 1000.0 */
|
||||
} FMOD_DSP_HIGHPASS_SIMPLE;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
|
||||
/* ============================================================================================== */
|
||||
/* FMOD Ex - Error string header file. Copyright (c), Firelight Technologies Pty, Ltd. 2004-2011. */
|
||||
/* */
|
||||
/* Use this header if you want to store or display a string version / english explanation of */
|
||||
/* the FMOD error codes. */
|
||||
/* */
|
||||
/* ============================================================================================== */
|
||||
|
||||
#ifndef _FMOD_ERRORS_H
|
||||
#define _FMOD_ERRORS_H
|
||||
|
||||
#include "fmod.h"
|
||||
|
||||
#ifdef __GNUC__
|
||||
static const char *FMOD_ErrorString(FMOD_RESULT errcode) __attribute__((unused));
|
||||
#endif
|
||||
|
||||
static const char *FMOD_ErrorString(FMOD_RESULT errcode)
|
||||
{
|
||||
switch (errcode)
|
||||
{
|
||||
case FMOD_ERR_ALREADYLOCKED: return "Tried to call lock a second time before unlock was called. ";
|
||||
case FMOD_ERR_BADCOMMAND: return "Tried to call a function on a data type that does not allow this type of functionality (ie calling Sound::lock on a streaming sound). ";
|
||||
case FMOD_ERR_CDDA_DRIVERS: return "Neither NTSCSI nor ASPI could be initialised. ";
|
||||
case FMOD_ERR_CDDA_INIT: return "An error occurred while initialising the CDDA subsystem. ";
|
||||
case FMOD_ERR_CDDA_INVALID_DEVICE: return "Couldn't find the specified device. ";
|
||||
case FMOD_ERR_CDDA_NOAUDIO: return "No audio tracks on the specified disc. ";
|
||||
case FMOD_ERR_CDDA_NODEVICES: return "No CD/DVD devices were found. ";
|
||||
case FMOD_ERR_CDDA_NODISC: return "No disc present in the specified drive. ";
|
||||
case FMOD_ERR_CDDA_READ: return "A CDDA read error occurred. ";
|
||||
case FMOD_ERR_CHANNEL_ALLOC: return "Error trying to allocate a channel. ";
|
||||
case FMOD_ERR_CHANNEL_STOLEN: return "The specified channel has been reused to play another sound. ";
|
||||
case FMOD_ERR_COM: return "A Win32 COM related error occured. COM failed to initialize or a QueryInterface failed meaning a Windows codec or driver was not installed properly. ";
|
||||
case FMOD_ERR_DMA: return "DMA Failure. See debug output for more information. ";
|
||||
case FMOD_ERR_DSP_CONNECTION: return "DSP connection error. Connection possibly caused a cyclic dependancy. Or tried to connect a tree too many units deep (more than 128). ";
|
||||
case FMOD_ERR_DSP_FORMAT: return "DSP Format error. A DSP unit may have attempted to connect to this network with the wrong format. ";
|
||||
case FMOD_ERR_DSP_NOTFOUND: return "DSP connection error. Couldn't find the DSP unit specified. ";
|
||||
case FMOD_ERR_DSP_RUNNING: return "DSP error. Cannot perform this operation while the network is in the middle of running. This will most likely happen if a connection or disconnection is attempted in a DSP callback. ";
|
||||
case FMOD_ERR_DSP_TOOMANYCONNECTIONS: return "DSP connection error. The unit being connected to or disconnected should only have 1 input or output. ";
|
||||
case FMOD_ERR_EVENT_ALREADY_LOADED: return "The specified project or bank has already been loaded. Having multiple copies of the same project loaded simultaneously is forbidden. ";
|
||||
case FMOD_ERR_EVENT_FAILED: return "An Event failed to be retrieved, most likely due to 'just fail' being specified as the max playbacks behavior. ";
|
||||
case FMOD_ERR_EVENT_GUIDCONFLICT: return "An event with the same GUID already exists. ";
|
||||
case FMOD_ERR_EVENT_INFOONLY: return "Can't execute this command on an EVENT_INFOONLY event. ";
|
||||
case FMOD_ERR_EVENT_INTERNAL: return "An error occured that wasn't supposed to. See debug log for reason. ";
|
||||
case FMOD_ERR_EVENT_MAXSTREAMS: return "Event failed because 'Max streams' was hit when FMOD_EVENT_INIT_FAIL_ON_MAXSTREAMS was specified. ";
|
||||
case FMOD_ERR_EVENT_MISMATCH: return "FSB mismatches the FEV it was compiled with, the stream/sample mode it was meant to be created with was different, or the FEV was built for a different platform. ";
|
||||
case FMOD_ERR_EVENT_NAMECONFLICT: return "A category with the same name already exists. ";
|
||||
case FMOD_ERR_EVENT_NEEDSSIMPLE: return "Tried to call a function on a complex event that's only supported by simple events. ";
|
||||
case FMOD_ERR_EVENT_NOTFOUND: return "The requested event, event group, event category or event property could not be found. ";
|
||||
case FMOD_ERR_FILE_BAD: return "Error loading file. ";
|
||||
case FMOD_ERR_FILE_COULDNOTSEEK: return "Couldn't perform seek operation. This is a limitation of the medium (ie netstreams) or the file format. ";
|
||||
case FMOD_ERR_FILE_DISKEJECTED: return "Media was ejected while reading. ";
|
||||
case FMOD_ERR_FILE_EOF: return "End of file unexpectedly reached while trying to read essential data (truncated data?). ";
|
||||
case FMOD_ERR_FILE_NOTFOUND: return "File not found. ";
|
||||
case FMOD_ERR_FILE_UNWANTED: return "Unwanted file access occured. ";
|
||||
case FMOD_ERR_FORMAT: return "Unsupported file or audio format. ";
|
||||
case FMOD_ERR_HTTP: return "A HTTP error occurred. This is a catch-all for HTTP errors not listed elsewhere. ";
|
||||
case FMOD_ERR_HTTP_ACCESS: return "The specified resource requires authentication or is forbidden. ";
|
||||
case FMOD_ERR_HTTP_PROXY_AUTH: return "Proxy authentication is required to access the specified resource. ";
|
||||
case FMOD_ERR_HTTP_SERVER_ERROR: return "A HTTP server error occurred. ";
|
||||
case FMOD_ERR_HTTP_TIMEOUT: return "The HTTP request timed out. ";
|
||||
case FMOD_ERR_INITIALIZATION: return "FMOD was not initialized correctly to support this function. ";
|
||||
case FMOD_ERR_INITIALIZED: return "Cannot call this command after System::init. ";
|
||||
case FMOD_ERR_INTERNAL: return "An error occured that wasn't supposed to. Contact support. ";
|
||||
case FMOD_ERR_INVALID_ADDRESS: return "On Xbox 360, this memory address passed to FMOD must be physical, (ie allocated with XPhysicalAlloc.) ";
|
||||
case FMOD_ERR_INVALID_FLOAT: return "Value passed in was a NaN, Inf or denormalized float. ";
|
||||
case FMOD_ERR_INVALID_HANDLE: return "An invalid object handle was used. ";
|
||||
case FMOD_ERR_INVALID_PARAM: return "An invalid parameter was passed to this function. ";
|
||||
case FMOD_ERR_INVALID_POSITION: return "An invalid seek position was passed to this function. ";
|
||||
case FMOD_ERR_INVALID_SPEAKER: return "An invalid speaker was passed to this function based on the current speaker mode. ";
|
||||
case FMOD_ERR_INVALID_SYNCPOINT: return "The syncpoint did not come from this sound handle. ";
|
||||
case FMOD_ERR_INVALID_VECTOR: return "The vectors passed in are not unit length, or perpendicular. ";
|
||||
case FMOD_ERR_MAXAUDIBLE: return "Reached maximum audible playback count for this sound's soundgroup. ";
|
||||
case FMOD_ERR_MEMORY: return "Not enough memory or resources. ";
|
||||
case FMOD_ERR_MEMORY_CANTPOINT: return "Can't use FMOD_OPENMEMORY_POINT on non PCM source data, or non mp3/xma/adpcm data if FMOD_CREATECOMPRESSEDSAMPLE was used. ";
|
||||
case FMOD_ERR_MEMORY_SRAM: return "Not enough memory or resources on console sound ram. ";
|
||||
case FMOD_ERR_MUSIC_NOCALLBACK: return "The music callback is required, but it has not been set. ";
|
||||
case FMOD_ERR_MUSIC_NOTFOUND: return "The requested music entity could not be found. ";
|
||||
case FMOD_ERR_MUSIC_UNINITIALIZED: return "Music system is not initialized probably because no music data is loaded. ";
|
||||
case FMOD_ERR_NEEDS2D: return "Tried to call a command on a 3d sound when the command was meant for 2d sound. ";
|
||||
case FMOD_ERR_NEEDS3D: return "Tried to call a command on a 2d sound when the command was meant for 3d sound. ";
|
||||
case FMOD_ERR_NEEDSHARDWARE: return "Tried to use a feature that requires hardware support. (ie trying to play a GCADPCM compressed sound in software on Wii). ";
|
||||
case FMOD_ERR_NEEDSSOFTWARE: return "Tried to use a feature that requires the software engine. Software engine has either been turned off, or command was executed on a hardware channel which does not support this feature. ";
|
||||
case FMOD_ERR_NET_CONNECT: return "Couldn't connect to the specified host. ";
|
||||
case FMOD_ERR_NET_SOCKET_ERROR: return "A socket error occurred. This is a catch-all for socket-related errors not listed elsewhere. ";
|
||||
case FMOD_ERR_NET_URL: return "The specified URL couldn't be resolved. ";
|
||||
case FMOD_ERR_NET_WOULD_BLOCK: return "Operation on a non-blocking socket could not complete immediately. ";
|
||||
case FMOD_ERR_NOTREADY: return "Operation could not be performed because specified sound/DSP connection is not ready. ";
|
||||
case FMOD_ERR_OUTPUT_ALLOCATED: return "Error initializing output device, but more specifically, the output device is already in use and cannot be reused. ";
|
||||
case FMOD_ERR_OUTPUT_CREATEBUFFER: return "Error creating hardware sound buffer. ";
|
||||
case FMOD_ERR_OUTPUT_DRIVERCALL: return "A call to a standard soundcard driver failed, which could possibly mean a bug in the driver or resources were missing or exhausted. ";
|
||||
case FMOD_ERR_OUTPUT_ENUMERATION: return "Error enumerating the available driver list. List may be inconsistent due to a recent device addition or removal. ";
|
||||
case FMOD_ERR_OUTPUT_FORMAT: return "Soundcard does not support the minimum features needed for this soundsystem (16bit stereo output). ";
|
||||
case FMOD_ERR_OUTPUT_INIT: return "Error initializing output device. ";
|
||||
case FMOD_ERR_OUTPUT_NOHARDWARE: return "FMOD_HARDWARE was specified but the sound card does not have the resources necessary to play it. ";
|
||||
case FMOD_ERR_OUTPUT_NOSOFTWARE: return "Attempted to create a software sound but no software channels were specified in System::init. ";
|
||||
case FMOD_ERR_PAN: return "Panning only works with mono or stereo sound sources. ";
|
||||
case FMOD_ERR_PLUGIN: return "An unspecified error has been returned from a 3rd party plugin. ";
|
||||
case FMOD_ERR_PLUGIN_INSTANCES: return "The number of allowed instances of a plugin has been exceeded. ";
|
||||
case FMOD_ERR_PLUGIN_MISSING: return "A requested output, dsp unit type or codec was not available. ";
|
||||
case FMOD_ERR_PLUGIN_RESOURCE: return "A resource that the plugin requires cannot be found. (ie the DLS file for MIDI playback or other DLLs that it needs to load) ";
|
||||
case FMOD_ERR_PRELOADED: return "The specified sound is still in use by the event system, call EventSystem::unloadFSB before trying to release it. ";
|
||||
case FMOD_ERR_PROGRAMMERSOUND: return "The specified sound is still in use by the event system, wait for the event which is using it finish with it. ";
|
||||
case FMOD_ERR_RECORD: return "An error occured trying to initialize the recording device. ";
|
||||
case FMOD_ERR_REVERB_INSTANCE: return "Specified instance in FMOD_REVERB_PROPERTIES couldn't be set. Most likely because it is an invalid instance number or the reverb doesnt exist. ";
|
||||
case FMOD_ERR_SUBSOUNDS: return "The error occured because the sound referenced contains subsounds when it shouldn't have, or it doesn't contain subsounds when it should have. The operation may also not be able to be performed on a parent sound, or a parent sound was played without setting up a sentence first. ";
|
||||
case FMOD_ERR_SUBSOUND_ALLOCATED: return "This subsound is already being used by another sound, you cannot have more than one parent to a sound. Null out the other parent's entry first. ";
|
||||
case FMOD_ERR_SUBSOUND_CANTMOVE: return "Shared subsounds cannot be replaced or moved from their parent stream, such as when the parent stream is an FSB file. ";
|
||||
case FMOD_ERR_SUBSOUND_MODE: return "The subsound's mode bits do not match with the parent sound's mode bits. See documentation for function that it was called with. ";
|
||||
case FMOD_ERR_TAGNOTFOUND: return "The specified tag could not be found or there are no tags. ";
|
||||
case FMOD_ERR_TOOMANYCHANNELS: return "The sound created exceeds the allowable input channel count. This can be increased using the maxinputchannels parameter in System::setSoftwareFormat. ";
|
||||
case FMOD_ERR_UNIMPLEMENTED: return "Something in FMOD hasn't been implemented when it should be! contact support! ";
|
||||
case FMOD_ERR_UNINITIALIZED: return "This command failed because System::init or System::setDriver was not called. ";
|
||||
case FMOD_ERR_UNSUPPORTED: return "A command issued was not supported by this object. Possibly a plugin without certain callbacks specified. ";
|
||||
case FMOD_ERR_UPDATE: return "An error caused by System::update occured. ";
|
||||
case FMOD_ERR_VERSION: return "The version number of this file format is not supported. ";
|
||||
case FMOD_OK: return "No errors.";
|
||||
default : return "Unknown error.";
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,201 +0,0 @@
|
|||
/* ============================================================================================= */
|
||||
/* FMOD Ex - Memory info header file. Copyright (c), Firelight Technologies Pty, Ltd. 2008-2011. */
|
||||
/* */
|
||||
/* Use this header if you are interested in getting detailed information on FMOD's memory */
|
||||
/* usage. See the documentation for more details. */
|
||||
/* */
|
||||
/* ============================================================================================= */
|
||||
|
||||
#ifndef _FMOD_MEMORYINFO_H
|
||||
#define _FMOD_MEMORYINFO_H
|
||||
|
||||
/*
|
||||
[STRUCTURE]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Structure to be filled with detailed memory usage information of an FMOD object
|
||||
|
||||
[REMARKS]
|
||||
Every public FMOD class has a getMemoryInfo function which can be used to get detailed information on what memory resources are associated with the object in question.
|
||||
On return from getMemoryInfo, each member of this structure will hold the amount of memory used for its type in bytes.
|
||||
|
||||
Members marked with [in] mean the user sets the value before passing it to the function.
|
||||
Members marked with [out] mean FMOD sets the value to be used after the function exits.
|
||||
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
System::getMemoryInfo
|
||||
EventSystem::getMemoryInfo
|
||||
FMOD_MEMBITS
|
||||
FMOD_EVENT_MEMBITS
|
||||
]
|
||||
*/
|
||||
typedef struct FMOD_MEMORY_USAGE_DETAILS
|
||||
{
|
||||
unsigned int other; /* [out] Memory not accounted for by other types */
|
||||
unsigned int string; /* [out] String data */
|
||||
unsigned int system; /* [out] System object and various internals */
|
||||
unsigned int plugins; /* [out] Plugin objects and internals */
|
||||
unsigned int output; /* [out] Output module object and internals */
|
||||
unsigned int channel; /* [out] Channel related memory */
|
||||
unsigned int channelgroup; /* [out] ChannelGroup objects and internals */
|
||||
unsigned int codec; /* [out] Codecs allocated for streaming */
|
||||
unsigned int file; /* [out] File buffers and structures */
|
||||
unsigned int sound; /* [out] Sound objects and internals */
|
||||
unsigned int secondaryram; /* [out] Sound data stored in secondary RAM */
|
||||
unsigned int soundgroup; /* [out] SoundGroup objects and internals */
|
||||
unsigned int streambuffer; /* [out] Stream buffer memory */
|
||||
unsigned int dspconnection; /* [out] DSPConnection objects and internals */
|
||||
unsigned int dsp; /* [out] DSP implementation objects */
|
||||
unsigned int dspcodec; /* [out] Realtime file format decoding DSP objects */
|
||||
unsigned int profile; /* [out] Profiler memory footprint. */
|
||||
unsigned int recordbuffer; /* [out] Buffer used to store recorded data from microphone */
|
||||
unsigned int reverb; /* [out] Reverb implementation objects */
|
||||
unsigned int reverbchannelprops; /* [out] Reverb channel properties structs */
|
||||
unsigned int geometry; /* [out] Geometry objects and internals */
|
||||
unsigned int syncpoint; /* [out] Sync point memory. */
|
||||
unsigned int eventsystem; /* [out] EventSystem and various internals */
|
||||
unsigned int musicsystem; /* [out] MusicSystem and various internals */
|
||||
unsigned int fev; /* [out] Definition of objects contained in all loaded projects e.g. events, groups, categories */
|
||||
unsigned int memoryfsb; /* [out] Data loaded with preloadFSB */
|
||||
unsigned int eventproject; /* [out] EventProject objects and internals */
|
||||
unsigned int eventgroupi; /* [out] EventGroup objects and internals */
|
||||
unsigned int soundbankclass; /* [out] Objects used to manage wave banks */
|
||||
unsigned int soundbanklist; /* [out] Data used to manage lists of wave bank usage */
|
||||
unsigned int streaminstance; /* [out] Stream objects and internals */
|
||||
unsigned int sounddefclass; /* [out] Sound definition objects */
|
||||
unsigned int sounddefdefclass; /* [out] Sound definition static data objects */
|
||||
unsigned int sounddefpool; /* [out] Sound definition pool data */
|
||||
unsigned int reverbdef; /* [out] Reverb definition objects */
|
||||
unsigned int eventreverb; /* [out] Reverb objects */
|
||||
unsigned int userproperty; /* [out] User property objects */
|
||||
unsigned int eventinstance; /* [out] Event instance base objects */
|
||||
unsigned int eventinstance_complex; /* [out] Complex event instance objects */
|
||||
unsigned int eventinstance_simple; /* [out] Simple event instance objects */
|
||||
unsigned int eventinstance_layer; /* [out] Event layer instance objects */
|
||||
unsigned int eventinstance_sound; /* [out] Event sound instance objects */
|
||||
unsigned int eventenvelope; /* [out] Event envelope objects */
|
||||
unsigned int eventenvelopedef; /* [out] Event envelope definition objects */
|
||||
unsigned int eventparameter; /* [out] Event parameter objects */
|
||||
unsigned int eventcategory; /* [out] Event category objects */
|
||||
unsigned int eventenvelopepoint; /* [out] Event envelope point objects */
|
||||
unsigned int eventinstancepool; /* [out] Event instance pool memory */
|
||||
} FMOD_MEMORY_USAGE_DETAILS;
|
||||
|
||||
|
||||
/*
|
||||
[DEFINE]
|
||||
[
|
||||
[NAME]
|
||||
FMOD_MEMBITS
|
||||
|
||||
[DESCRIPTION]
|
||||
Bitfield used to request specific memory usage information from the getMemoryInfo function of every public FMOD Ex class.
|
||||
Use with the "memorybits" parameter of getMemoryInfo to get information on FMOD Ex memory usage.
|
||||
|
||||
[REMARKS]
|
||||
Every public FMOD class has a getMemoryInfo function which can be used to get detailed information on what memory resources are associated with the object in question.
|
||||
The FMOD_MEMBITS defines can be OR'd together to specify precisely what memory usage you'd like to get information on. See System::getMemoryInfo for an example.
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
FMOD_EVENT_MEMBITS
|
||||
System::getMemoryInfo
|
||||
]
|
||||
*/
|
||||
#define FMOD_MEMBITS_OTHER 0x00000001 /* Memory not accounted for by other types */
|
||||
#define FMOD_MEMBITS_STRING 0x00000002 /* String data */
|
||||
|
||||
#define FMOD_MEMBITS_SYSTEM 0x00000004 /* System object and various internals */
|
||||
#define FMOD_MEMBITS_PLUGINS 0x00000008 /* Plugin objects and internals */
|
||||
#define FMOD_MEMBITS_OUTPUT 0x00000010 /* Output module object and internals */
|
||||
#define FMOD_MEMBITS_CHANNEL 0x00000020 /* Channel related memory */
|
||||
#define FMOD_MEMBITS_CHANNELGROUP 0x00000040 /* ChannelGroup objects and internals */
|
||||
#define FMOD_MEMBITS_CODEC 0x00000080 /* Codecs allocated for streaming */
|
||||
#define FMOD_MEMBITS_FILE 0x00000100 /* Codecs allocated for streaming */
|
||||
#define FMOD_MEMBITS_SOUND 0x00000200 /* Sound objects and internals */
|
||||
#define FMOD_MEMBITS_SOUND_SECONDARYRAM 0x00000400 /* Sound data stored in secondary RAM */
|
||||
#define FMOD_MEMBITS_SOUNDGROUP 0x00000800 /* SoundGroup objects and internals */
|
||||
#define FMOD_MEMBITS_STREAMBUFFER 0x00001000 /* Stream buffer memory */
|
||||
#define FMOD_MEMBITS_DSPCONNECTION 0x00002000 /* DSPConnection objects and internals */
|
||||
#define FMOD_MEMBITS_DSP 0x00004000 /* DSP implementation objects */
|
||||
#define FMOD_MEMBITS_DSPCODEC 0x00008000 /* Realtime file format decoding DSP objects */
|
||||
#define FMOD_MEMBITS_PROFILE 0x00010000 /* Profiler memory footprint. */
|
||||
#define FMOD_MEMBITS_RECORDBUFFER 0x00020000 /* Buffer used to store recorded data from microphone */
|
||||
#define FMOD_MEMBITS_REVERB 0x00040000 /* Reverb implementation objects */
|
||||
#define FMOD_MEMBITS_REVERBCHANNELPROPS 0x00080000 /* Reverb channel properties structs */
|
||||
#define FMOD_MEMBITS_GEOMETRY 0x00100000 /* Geometry objects and internals */
|
||||
#define FMOD_MEMBITS_SYNCPOINT 0x00200000 /* Sync point memory. */
|
||||
#define FMOD_MEMBITS_ALL 0xffffffff /* All memory used by FMOD Ex */
|
||||
/* [DEFINE_END] */
|
||||
|
||||
|
||||
/*
|
||||
[DEFINE]
|
||||
[
|
||||
[NAME]
|
||||
FMOD_EVENT_MEMBITS
|
||||
|
||||
[DESCRIPTION]
|
||||
Bitfield used to request specific memory usage information from the getMemoryInfo function of every public FMOD Event System class.
|
||||
Use with the "event_memorybits" parameter of getMemoryInfo to get information on FMOD Event System memory usage.
|
||||
|
||||
[REMARKS]
|
||||
Every public FMOD Event System class has a getMemoryInfo function which can be used to get detailed information on what memory resources are associated with the object in question.
|
||||
The FMOD_EVENT_MEMBITS defines can be OR'd together to specify precisely what memory usage you'd like to get information on. See EventSystem::getMemoryInfo for an example.
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
FMOD_MEMBITS
|
||||
System::getMemoryInfo
|
||||
]
|
||||
*/
|
||||
#define FMOD_EVENT_MEMBITS_EVENTSYSTEM 0x00000001 /* EventSystem and various internals */
|
||||
#define FMOD_EVENT_MEMBITS_MUSICSYSTEM 0x00000002 /* MusicSystem and various internals */
|
||||
#define FMOD_EVENT_MEMBITS_FEV 0x00000004 /* Definition of objects contained in all loaded projects e.g. events, groups, categories */
|
||||
#define FMOD_EVENT_MEMBITS_MEMORYFSB 0x00000008 /* Data loaded with preloadFSB */
|
||||
#define FMOD_EVENT_MEMBITS_EVENTPROJECT 0x00000010 /* EventProject objects and internals */
|
||||
#define FMOD_EVENT_MEMBITS_EVENTGROUPI 0x00000020 /* EventGroup objects and internals */
|
||||
#define FMOD_EVENT_MEMBITS_SOUNDBANKCLASS 0x00000040 /* Objects used to manage wave banks */
|
||||
#define FMOD_EVENT_MEMBITS_SOUNDBANKLIST 0x00000080 /* Data used to manage lists of wave bank usage */
|
||||
#define FMOD_EVENT_MEMBITS_STREAMINSTANCE 0x00000100 /* Stream objects and internals */
|
||||
#define FMOD_EVENT_MEMBITS_SOUNDDEFCLASS 0x00000200 /* Sound definition objects */
|
||||
#define FMOD_EVENT_MEMBITS_SOUNDDEFDEFCLASS 0x00000400 /* Sound definition static data objects */
|
||||
#define FMOD_EVENT_MEMBITS_SOUNDDEFPOOL 0x00000800 /* Sound definition pool data */
|
||||
#define FMOD_EVENT_MEMBITS_REVERBDEF 0x00001000 /* Reverb definition objects */
|
||||
#define FMOD_EVENT_MEMBITS_EVENTREVERB 0x00002000 /* Reverb objects */
|
||||
#define FMOD_EVENT_MEMBITS_USERPROPERTY 0x00004000 /* User property objects */
|
||||
#define FMOD_EVENT_MEMBITS_EVENTINSTANCE 0x00008000 /* Event instance base objects */
|
||||
#define FMOD_EVENT_MEMBITS_EVENTINSTANCE_COMPLEX 0x00010000 /* Complex event instance objects */
|
||||
#define FMOD_EVENT_MEMBITS_EVENTINSTANCE_SIMPLE 0x00020000 /* Simple event instance objects */
|
||||
#define FMOD_EVENT_MEMBITS_EVENTINSTANCE_LAYER 0x00040000 /* Event layer instance objects */
|
||||
#define FMOD_EVENT_MEMBITS_EVENTINSTANCE_SOUND 0x00080000 /* Event sound instance objects */
|
||||
#define FMOD_EVENT_MEMBITS_EVENTENVELOPE 0x00100000 /* Event envelope objects */
|
||||
#define FMOD_EVENT_MEMBITS_EVENTENVELOPEDEF 0x00200000 /* Event envelope definition objects */
|
||||
#define FMOD_EVENT_MEMBITS_EVENTPARAMETER 0x00400000 /* Event parameter objects */
|
||||
#define FMOD_EVENT_MEMBITS_EVENTCATEGORY 0x00800000 /* Event category objects */
|
||||
#define FMOD_EVENT_MEMBITS_EVENTENVELOPEPOINT 0x01000000 /* Event envelope point object+s */
|
||||
#define FMOD_EVENT_MEMBITS_EVENTINSTANCEPOOL 0x02000000 /* Event instance pool data */
|
||||
#define FMOD_EVENT_MEMBITS_ALL 0xffffffff /* All memory used by FMOD Event System */
|
||||
|
||||
/* All event instance memory */
|
||||
#define FMOD_EVENT_MEMBITS_EVENTINSTANCE_GROUP (FMOD_EVENT_MEMBITS_EVENTINSTANCE | \
|
||||
FMOD_EVENT_MEMBITS_EVENTINSTANCE_COMPLEX | \
|
||||
FMOD_EVENT_MEMBITS_EVENTINSTANCE_SIMPLE | \
|
||||
FMOD_EVENT_MEMBITS_EVENTINSTANCE_LAYER | \
|
||||
FMOD_EVENT_MEMBITS_EVENTINSTANCE_SOUND)
|
||||
|
||||
/* All sound definition memory */
|
||||
#define FMOD_EVENT_MEMBITS_SOUNDDEF_GROUP (FMOD_EVENT_MEMBITS_SOUNDDEFCLASS | \
|
||||
FMOD_EVENT_MEMBITS_SOUNDDEFDEFCLASS | \
|
||||
FMOD_EVENT_MEMBITS_SOUNDDEFPOOL)
|
||||
/* [DEFINE_END] */
|
||||
|
||||
#endif
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
/* ==================================================================================================== */
|
||||
/* FMOD Ex - output development header file. Copyright (c), Firelight Technologies Pty, Ltd. 2004-2011. */
|
||||
/* */
|
||||
/* Use this header if you are wanting to develop your own output plugin to use with */
|
||||
/* FMOD's output system. With this header you can make your own output plugin that FMOD */
|
||||
/* can register and use. See the documentation and examples on how to make a working plugin. */
|
||||
/* */
|
||||
/* ==================================================================================================== */
|
||||
|
||||
#ifndef _FMOD_OUTPUT_H
|
||||
#define _FMOD_OUTPUT_H
|
||||
|
||||
#include "fmod.h"
|
||||
|
||||
typedef struct FMOD_OUTPUT_STATE FMOD_OUTPUT_STATE;
|
||||
|
||||
/*
|
||||
Output callbacks
|
||||
*/
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_GETNUMDRIVERSCALLBACK)(FMOD_OUTPUT_STATE *output_state, int *numdrivers);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_GETDRIVERNAMECALLBACK)(FMOD_OUTPUT_STATE *output_state, int id, char *name, int namelen);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_GETDRIVERCAPSCALLBACK)(FMOD_OUTPUT_STATE *output_state, int id, FMOD_CAPS *caps);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_INITCALLBACK) (FMOD_OUTPUT_STATE *output_state, int selecteddriver, FMOD_INITFLAGS flags, int *outputrate, int outputchannels, FMOD_SOUND_FORMAT *outputformat, int dspbufferlength, int dspnumbuffers, void *extradriverdata);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_CLOSECALLBACK) (FMOD_OUTPUT_STATE *output_state);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_UPDATECALLBACK) (FMOD_OUTPUT_STATE *output_state);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_GETHANDLECALLBACK) (FMOD_OUTPUT_STATE *output_state, void **handle);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_GETPOSITIONCALLBACK) (FMOD_OUTPUT_STATE *output_state, unsigned int *pcm);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_LOCKCALLBACK) (FMOD_OUTPUT_STATE *output_state, unsigned int offset, unsigned int length, void **ptr1, void **ptr2, unsigned int *len1, unsigned int *len2);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_UNLOCKCALLBACK) (FMOD_OUTPUT_STATE *output_state, void *ptr1, void *ptr2, unsigned int len1, unsigned int len2);
|
||||
typedef FMOD_RESULT (F_CALLBACK *FMOD_OUTPUT_READFROMMIXER) (FMOD_OUTPUT_STATE *output_state, void *buffer, unsigned int length);
|
||||
|
||||
|
||||
/*
|
||||
[STRUCTURE]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
When creating an output, declare one of these and provide the relevant callbacks and name for FMOD to use when it opens and reads a file of this type.
|
||||
|
||||
[REMARKS]
|
||||
Members marked with [in] mean the variable can be written to. The user can set the value.
|
||||
Members marked with [out] mean the variable is modified by FMOD and is for reading purposes only. Do not change this value.
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
FMOD_OUTPUT_STATE
|
||||
]
|
||||
*/
|
||||
typedef struct FMOD_OUTPUT_DESCRIPTION
|
||||
{
|
||||
const char *name; /* [in] Name of the output. */
|
||||
unsigned int version; /* [in] Plugin writer's version number. */
|
||||
int polling; /* [in] If TRUE (non zero), this tells FMOD to start a thread and call getposition / lock / unlock for feeding data. If 0, the output is probably callback based, so all the plugin needs to do is call readfrommixer to the appropriate pointer. */
|
||||
FMOD_OUTPUT_GETNUMDRIVERSCALLBACK getnumdrivers; /* [in] For sound device enumeration. This callback is to give System::getNumDrivers somthing to return. */
|
||||
FMOD_OUTPUT_GETDRIVERNAMECALLBACK getdrivername; /* [in] For sound device enumeration. This callback is to give System::getDriverName somthing to return. */
|
||||
FMOD_OUTPUT_GETDRIVERCAPSCALLBACK getdrivercaps; /* [in] For sound device enumeration. This callback is to give System::getDriverCaps somthing to return. */
|
||||
FMOD_OUTPUT_INITCALLBACK init; /* [in] Initialization function for the output device. This is called from System::init. */
|
||||
FMOD_OUTPUT_CLOSECALLBACK close; /* [in] Cleanup / close down function for the output device. This is called from System::close. */
|
||||
FMOD_OUTPUT_UPDATECALLBACK update; /* [in] Update function that is called once a frame by the user. This is called from System::update. */
|
||||
FMOD_OUTPUT_GETHANDLECALLBACK gethandle; /* [in] This is called from System::getOutputHandle. This is just to return a pointer to the internal system device object that the system may be using.*/
|
||||
FMOD_OUTPUT_GETPOSITIONCALLBACK getposition; /* [in] This is called from the FMOD software mixer thread if 'polling' = true. This returns a position value in samples so that FMOD knows where and when to fill its buffer. */
|
||||
FMOD_OUTPUT_LOCKCALLBACK lock; /* [in] This is called from the FMOD software mixer thread if 'polling' = true. This function provides a pointer to data that FMOD can write to when software mixing. */
|
||||
FMOD_OUTPUT_UNLOCKCALLBACK unlock; /* [in] This is called from the FMOD software mixer thread if 'polling' = true. This optional function accepts the data that has been mixed and copies it or does whatever it needs to before sending it to the hardware. */
|
||||
} FMOD_OUTPUT_DESCRIPTION;
|
||||
|
||||
|
||||
/*
|
||||
[STRUCTURE]
|
||||
[
|
||||
[DESCRIPTION]
|
||||
Output plugin structure that is passed into each callback.
|
||||
|
||||
[REMARKS]
|
||||
Members marked with [in] mean the variable can be written to. The user can set the value.
|
||||
Members marked with [out] mean the variable is modified by FMOD and is for reading purposes only. Do not change this value.
|
||||
|
||||
[PLATFORMS]
|
||||
Win32, Win64, Linux, Linux64, Macintosh, Xbox360, PlayStation Portable, PlayStation 3, Wii, iPhone, 3GS, NGP, Android
|
||||
|
||||
[SEE_ALSO]
|
||||
FMOD_OUTPUT_DESCRIPTION
|
||||
]
|
||||
*/
|
||||
struct FMOD_OUTPUT_STATE
|
||||
{
|
||||
void *plugindata; /* [in] Plugin writer created data the output author wants to attach to this object. */
|
||||
FMOD_OUTPUT_READFROMMIXER readfrommixer; /* [out] Function to update mixer and write the result to the provided pointer. Used from callback based output only. Polling based output uses lock/unlock/getposition. */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,28 +0,0 @@
|
|||
Which library do I link?
|
||||
------------------------
|
||||
|
||||
If you want to use fmodex.dll:
|
||||
|
||||
Visual Studio users - fmodex_vc.lib.
|
||||
Metrowerks Codewarrior users - fmodex_vc.lib.
|
||||
Borland users - fmodex_bc.lib.
|
||||
LCC-Win32 users - fmodex_lcc.lib.
|
||||
Dev-C++, MinGW and CygWin users - libfmodex.a.
|
||||
|
||||
If you want to use fmodexL.dll: (same as fmodex.dll but with debug logging enabled)
|
||||
|
||||
Visual Studio users - fmodexL_vc.lib.
|
||||
Metrowerks Codewarrior users - fmodexL_vc.lib.
|
||||
Borland users - fmodexL_bc.lib.
|
||||
LCC-Win32 users - fmodexL_lcc.lib.
|
||||
Dev-C++, MinGW and CygWin users - libfmodexL.a.
|
||||
|
||||
If you want to use fmodex64.dll: (same as fmodex.dll but for 64bit machines)
|
||||
|
||||
Visual Studio users - fmodex64_vc.lib.
|
||||
|
||||
If you want to use fmodexL64.dll: (same as fmodex64.dll but with debug logging enabled)
|
||||
|
||||
Visual Studio users - fmodexL64_vc.lib.
|
||||
|
||||
No other compilers are supported for 64bit libraries.
|
||||
|
|
@ -301,13 +301,25 @@ target_compile_definitions(SRB2SDL2 PRIVATE -DCMAKECONFIG)
|
|||
# ${SRB2_BLUA_HEADERS}
|
||||
#)
|
||||
|
||||
## strip debug symbols into separate file when using gcc.
|
||||
## to be consistent with Makefile, don't generate for OS X.
|
||||
if((CMAKE_COMPILER_IS_GNUCC) AND NOT (${CMAKE_SYSTEM} MATCHES Darwin))
|
||||
if((${CMAKE_BUILD_TYPE} MATCHES Debug) OR (${CMAKE_BUILD_TYPE} MATCHES RelWithDebInfo))
|
||||
if(${CMAKE_BUILD_TYPE} MATCHES Debug)
|
||||
set(OBJCOPY_ONLY_KEEP_DEBUG "--only-keep-debug")
|
||||
endif()
|
||||
message(STATUS "Will make separate debug symbols in *.debug")
|
||||
add_custom_command(TARGET SRB2SDL2 POST_BUILD
|
||||
COMMAND ${OBJCOPY} ${OBJCOPY_ONLY_KEEP_DEBUG} $<TARGET_FILE:SRB2SDL2> $<TARGET_FILE:SRB2SDL2>.debug
|
||||
COMMAND ${OBJCOPY} --strip-debug $<TARGET_FILE:SRB2SDL2>
|
||||
COMMAND ${OBJCOPY} --add-gnu-debuglink=$<TARGET_FILE:SRB2SDL2>.debug $<TARGET_FILE:SRB2SDL2>
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory(sdl)
|
||||
add_subdirectory(objects)
|
||||
|
||||
if(${CMAKE_SYSTEM} MATCHES Windows)
|
||||
add_subdirectory(win32)
|
||||
endif()
|
||||
|
||||
if(NOT ${SRB2_SDL2_AVAILABLE})
|
||||
message(FATAL_ERROR "There are no targets available to build an SRB2Kart executable. :(")
|
||||
endif()
|
||||
|
|
|
|||
20
src/Makefile
20
src/Makefile
|
|
@ -193,6 +193,9 @@ nasm_format:=
|
|||
# also defines the name as a macro to the compiler.
|
||||
passthru_opts:=
|
||||
|
||||
# separate suffix with an underscore
|
||||
exesuffix:=$(call _,$(EXESUFFIX))
|
||||
|
||||
include Makefile.d/platform.mk
|
||||
include Makefile.d/features.mk
|
||||
include Makefile.d/versions.mk
|
||||
|
|
@ -230,17 +233,22 @@ endif
|
|||
objects:=$(addprefix $(objdir)/,$(objects))
|
||||
|
||||
ifdef DEBUGMODE
|
||||
bin:=../bin/debug
|
||||
EXEDIR?=../bin/debug
|
||||
else
|
||||
bin:=../bin
|
||||
EXEDIR?=../bin
|
||||
endif
|
||||
|
||||
# append branch name by default
|
||||
ifndef EXENAME
|
||||
base:=ringracers
|
||||
branch:=$(shell git symbolic-ref -q --short HEAD)
|
||||
EXENAME:=$(base)$(call _,$(filter-out master,$(branch)))$(exesuffix)
|
||||
endif
|
||||
|
||||
# default EXENAME (usually set by platform)
|
||||
EXENAME?=ringracers
|
||||
DBGNAME?=$(EXENAME).debug
|
||||
|
||||
exe:=$(bin)/$(EXENAME)
|
||||
dbg:=$(bin)/$(DBGNAME)
|
||||
exe:=$(EXEDIR)/$(EXENAME)
|
||||
dbg:=$(EXEDIR)/$(DBGNAME)
|
||||
|
||||
build_done==== Build is done, look for \
|
||||
$(<F) at $(abspath $(<D)) ===
|
||||
|
|
|
|||
|
|
@ -91,3 +91,6 @@ endif
|
|||
endif
|
||||
|
||||
.=$(call Ifndef,ECHO,@)
|
||||
|
||||
# prepends an underscore if not empty
|
||||
_=$(if $(1),_$(1))
|
||||
|
|
|
|||
|
|
@ -2,11 +2,7 @@
|
|||
# Mingw, if you don't know, that's Win32/Win64
|
||||
#
|
||||
|
||||
ifndef MINGW64
|
||||
EXENAME?=ringracers.exe
|
||||
else
|
||||
EXENAME?=ringracers64.exe
|
||||
endif
|
||||
exesuffix:=$(exesuffix)$(if $(MINGW64),64).exe
|
||||
|
||||
# disable dynamicbase if under msys2
|
||||
ifdef MSYSTEM
|
||||
|
|
|
|||
|
|
@ -1641,34 +1641,14 @@ void CV_SaveVars(UINT8 **p, boolean in_demo)
|
|||
// the client will reset all netvars to default before loading
|
||||
WRITEUINT16(*p, 0x0000);
|
||||
for (cvar = consvar_vars; cvar; cvar = cvar->next)
|
||||
if (((cvar->flags & CV_NETVAR) && !CV_IsSetToDefault(cvar)) || (in_demo && cvar->netid == cv_numlaps.netid))
|
||||
if ((cvar->flags & CV_NETVAR) && !CV_IsSetToDefault(cvar))
|
||||
{
|
||||
if (in_demo)
|
||||
WRITESTRING(*p, cvar->name);
|
||||
else
|
||||
WRITEUINT16(*p, cvar->netid);
|
||||
|
||||
// UGLY HACK: Save proper lap count in net replays
|
||||
if (in_demo && cvar->netid == cv_numlaps.netid)
|
||||
{
|
||||
if (cv_basenumlaps.value &&
|
||||
(!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE)
|
||||
|| (mapheaderinfo[gamemap - 1]->numlaps > cv_basenumlaps.value))
|
||||
)
|
||||
{
|
||||
WRITESTRING(*p, cv_basenumlaps.string);
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf[9];
|
||||
sprintf(buf, "%d", mapheaderinfo[gamemap - 1]->numlaps);
|
||||
WRITESTRING(*p, buf);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WRITESTRING(*p, cvar->string);
|
||||
}
|
||||
WRITESTRING(*p, cvar->string);
|
||||
|
||||
WRITEUINT8(*p, false);
|
||||
++count;
|
||||
|
|
@ -2052,6 +2032,7 @@ void CV_AddValue(consvar_t *var, INT32 increment)
|
|||
if (var->PossibleValue[max].value == var->value)
|
||||
currentindice = max;
|
||||
|
||||
// The following options will NOT handle netsyncing.
|
||||
if (var == &cv_chooseskin)
|
||||
{
|
||||
// Special case for the chooseskin variable, used only directly from the menu
|
||||
|
|
@ -2103,28 +2084,7 @@ void CV_AddValue(consvar_t *var, INT32 increment)
|
|||
}
|
||||
else if (var == &cv_kartspeed)
|
||||
{
|
||||
INT32 maxspeed = (M_SecretUnlocked(SECRET_HARDSPEED) ? 2 : 1);
|
||||
// Special case for the kartspeed variable, used only directly from the menu to prevent selecting hard mode
|
||||
if (increment > 0) // Going up!
|
||||
{
|
||||
newvalue = var->value + 1;
|
||||
if (newvalue > maxspeed)
|
||||
newvalue = -1;
|
||||
var->value = newvalue;
|
||||
var->string = var->PossibleValue[var->value].strvalue;
|
||||
var->func();
|
||||
return;
|
||||
}
|
||||
else if (increment < 0) // Going down!
|
||||
{
|
||||
newvalue = var->value - 1;
|
||||
if (newvalue < -1)
|
||||
newvalue = maxspeed;
|
||||
var->value = newvalue;
|
||||
var->string = var->PossibleValue[var->value].strvalue;
|
||||
var->func();
|
||||
return;
|
||||
}
|
||||
max = (M_SecretUnlocked(SECRET_HARDSPEED) ? 3 : 2);
|
||||
}
|
||||
#ifdef PARANOIA
|
||||
if (currentindice == -1)
|
||||
|
|
|
|||
|
|
@ -3287,7 +3287,7 @@ void D_QuitNetGame(void)
|
|||
if (nodeingame[i])
|
||||
HSendPacket(i, true, 0, 0);
|
||||
#ifdef MASTERSERVER
|
||||
if (serverrunning && cv_advertise.value)
|
||||
if (serverrunning && netgame && cv_advertise.value) // see mserv.c Online()
|
||||
UnregisterServer();
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -899,7 +899,11 @@ void D_SRB2Loop(void)
|
|||
if (!singletics)
|
||||
{
|
||||
INT64 elapsed = (INT64)(finishprecise - enterprecise);
|
||||
if (elapsed > 0 && (INT64)capbudget > elapsed)
|
||||
|
||||
// in the case of "match refresh rate" + vsync, don't sleep at all
|
||||
const boolean vsync_with_match_refresh = cv_vidwait.value && cv_fpscap.value == 0;
|
||||
|
||||
if (elapsed > 0 && (INT64)capbudget > elapsed && !vsync_with_match_refresh)
|
||||
{
|
||||
I_SleepDuration(capbudget - (finishprecise - enterprecise));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,7 +102,6 @@ static void Got_DiscordInfo(UINT8 **cp, INT32 playernum);
|
|||
static void PointLimit_OnChange(void);
|
||||
static void TimeLimit_OnChange(void);
|
||||
static void NumLaps_OnChange(void);
|
||||
static void BaseNumLaps_OnChange(void);
|
||||
static void Mute_OnChange(void);
|
||||
|
||||
static void AutoBalance_OnChange(void);
|
||||
|
|
@ -141,7 +140,6 @@ static void Color4_OnChange(void);
|
|||
static void DummyConsvar_OnChange(void);
|
||||
static void SoundTest_OnChange(void);
|
||||
|
||||
static void BaseNumLaps_OnChange(void);
|
||||
static void KartFrantic_OnChange(void);
|
||||
static void KartSpeed_OnChange(void);
|
||||
static void KartEncore_OnChange(void);
|
||||
|
|
@ -489,10 +487,9 @@ static CV_PossibleValue_t pointlimit_cons_t[] = {{1, "MIN"}, {MAXSCORE, "MAX"},
|
|||
consvar_t cv_pointlimit = CVAR_INIT ("pointlimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, pointlimit_cons_t, PointLimit_OnChange);
|
||||
static CV_PossibleValue_t timelimit_cons_t[] = {{1, "MIN"}, {30, "MAX"}, {0, "None"}, {0, NULL}};
|
||||
consvar_t cv_timelimit = CVAR_INIT ("timelimit", "None", CV_SAVE|CV_NETVAR|CV_CALL|CV_NOINIT, timelimit_cons_t, TimeLimit_OnChange);
|
||||
static CV_PossibleValue_t numlaps_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_numlaps = CVAR_INIT ("numlaps", "3", CV_NETVAR|CV_CALL|CV_NOINIT, numlaps_cons_t, NumLaps_OnChange);
|
||||
static CV_PossibleValue_t basenumlaps_cons_t[] = {{1, "MIN"}, {99, "MAX"}, {0, "Map default"}, {0, NULL}};
|
||||
consvar_t cv_basenumlaps = CVAR_INIT ("basenumlaps", "Map default", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, basenumlaps_cons_t, BaseNumLaps_OnChange);
|
||||
|
||||
static CV_PossibleValue_t numlaps_cons_t[] = {{1, "MIN"}, {MAX_LAPS, "MAX"}, {0, "Map default"}, {0, NULL}};
|
||||
consvar_t cv_numlaps = CVAR_INIT ("numlaps", "Map default", CV_SAVE|CV_NETVAR|CV_CALL|CV_CHEAT, numlaps_cons_t, NumLaps_OnChange);
|
||||
|
||||
// Point and time limits for every gametype
|
||||
INT32 pointlimits[NUMGAMETYPES];
|
||||
|
|
@ -707,7 +704,6 @@ void D_RegisterServerCommands(void)
|
|||
// misc
|
||||
CV_RegisterVar(&cv_pointlimit);
|
||||
CV_RegisterVar(&cv_numlaps);
|
||||
CV_RegisterVar(&cv_basenumlaps);
|
||||
|
||||
CV_RegisterVar(&cv_autobalance);
|
||||
CV_RegisterVar(&cv_teamscramble);
|
||||
|
|
@ -3570,6 +3566,8 @@ static void Got_Teamchange(UINT8 **cp, INT32 playernum)
|
|||
|
||||
if (players[playernum].mo)
|
||||
players[playernum].mo->health = 1;
|
||||
|
||||
K_StripItems(&players[playernum]);
|
||||
}
|
||||
|
||||
K_CheckBumpers(); // SRB2Kart
|
||||
|
|
@ -4505,24 +4503,6 @@ static void PointLimit_OnChange(void)
|
|||
CONS_Printf(M_GetText("Point limit disabled\n"));
|
||||
}
|
||||
|
||||
static void NumLaps_OnChange(void)
|
||||
{
|
||||
if (K_CanChangeRules() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if ((mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE)
|
||||
&& (cv_numlaps.value > mapheaderinfo[gamemap - 1]->numlaps))
|
||||
{
|
||||
CV_StealthSetValue(&cv_numlaps, mapheaderinfo[gamemap - 1]->numlaps);
|
||||
}
|
||||
|
||||
// Just don't be verbose
|
||||
if (gametyperules & GTR_CIRCUIT)
|
||||
CONS_Printf(M_GetText("Number of laps set to %d\n"), cv_numlaps.value);
|
||||
}
|
||||
|
||||
static void NetTimeout_OnChange(void)
|
||||
{
|
||||
connectiontimeout = (tic_t)cv_nettimeout.value;
|
||||
|
|
@ -5330,7 +5310,6 @@ static void Follower_OnChange(void)
|
|||
{
|
||||
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
|
||||
INT32 num;
|
||||
char set[10]; // This isn't Lua and mixed declarations in the middle of code make caveman compilers scream.
|
||||
|
||||
// there is a slight chance that we will actually use a string instead so...
|
||||
// let's investigate the string...
|
||||
|
|
@ -5355,8 +5334,8 @@ static void Follower_OnChange(void)
|
|||
if (num == -1) // that's an error.
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
|
||||
|
||||
sprintf(set, "%d", num);
|
||||
CV_StealthSet(&cv_follower[0], set); // set it to a number. It's easier for us to send later :)
|
||||
CV_StealthSet(&cv_follower[0], str);
|
||||
cv_follower[0].value = num;
|
||||
}
|
||||
|
||||
if (!Playing())
|
||||
|
|
@ -5384,7 +5363,6 @@ static void Follower2_OnChange(void)
|
|||
{
|
||||
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
|
||||
INT32 num;
|
||||
char set[10]; // This isn't Lua and mixed declarations in the middle of code make caveman compilers scream.
|
||||
|
||||
// there is a slight chance that we will actually use a string instead so...
|
||||
// let's investigate the string...
|
||||
|
|
@ -5409,8 +5387,8 @@ static void Follower2_OnChange(void)
|
|||
if (num == -1) // that's an error.
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
|
||||
|
||||
sprintf(set, "%d", num);
|
||||
CV_StealthSet(&cv_follower[1], set); // set it to a number. It's easier for us to send later :)
|
||||
CV_StealthSet(&cv_follower[1], str);
|
||||
cv_follower[1].value = num;
|
||||
}
|
||||
|
||||
if (!Playing())
|
||||
|
|
@ -5435,7 +5413,6 @@ static void Follower3_OnChange(void)
|
|||
{
|
||||
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
|
||||
INT32 num;
|
||||
char set[10]; // This isn't Lua and mixed declarations in the middle of code make caveman compilers scream.
|
||||
|
||||
// there is a slight chance that we will actually use a string instead so...
|
||||
// let's investigate the string...
|
||||
|
|
@ -5460,8 +5437,8 @@ static void Follower3_OnChange(void)
|
|||
if (num == -1) // that's an error.
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
|
||||
|
||||
sprintf(set, "%d", num);
|
||||
CV_StealthSet(&cv_follower[2], set); // set it to a number. It's easier for us to send later :)
|
||||
CV_StealthSet(&cv_follower[2], str);
|
||||
cv_follower[2].value = num;
|
||||
}
|
||||
|
||||
if (!Playing())
|
||||
|
|
@ -5486,7 +5463,6 @@ static void Follower4_OnChange(void)
|
|||
{
|
||||
char str[SKINNAMESIZE+1], cpy[SKINNAMESIZE+1];
|
||||
INT32 num;
|
||||
char set[10]; // This isn't Lua and mixed declarations in the middle of code make caveman compilers scream.
|
||||
|
||||
// there is a slight chance that we will actually use a string instead so...
|
||||
// let's investigate the string...
|
||||
|
|
@ -5511,8 +5487,8 @@ static void Follower4_OnChange(void)
|
|||
if (num == -1) // that's an error.
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Follower '%s' not found\n"), str);
|
||||
|
||||
sprintf(set, "%d", num);
|
||||
CV_StealthSet(&cv_follower[3], set); // set it to a number. It's easier for us to send later :)
|
||||
CV_StealthSet(&cv_follower[3], str);
|
||||
cv_follower[3].value = num;
|
||||
}
|
||||
|
||||
if (!Playing())
|
||||
|
|
@ -5789,22 +5765,24 @@ static void Command_ShowTime_f(void)
|
|||
}
|
||||
|
||||
// SRB2Kart: On change messages
|
||||
static void BaseNumLaps_OnChange(void)
|
||||
static void NumLaps_OnChange(void)
|
||||
{
|
||||
if (K_CanChangeRules() == true)
|
||||
if (K_CanChangeRules() == false)
|
||||
{
|
||||
const char *str = va("%d", cv_basenumlaps.value);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cv_basenumlaps.value == 0)
|
||||
{
|
||||
str = "map defaults";
|
||||
}
|
||||
|
||||
CONS_Printf(M_GetText("Number of laps will be changed to %s next round.\n"), str);
|
||||
if (leveltime < starttime)
|
||||
{
|
||||
CONS_Printf(M_GetText("Number of laps have been set to %d.\n"), cv_numlaps.value);
|
||||
numlaps = (UINT8)cv_numlaps.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf(M_GetText("Number of laps will be set to %d next round.\n"), cv_numlaps.value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void KartFrantic_OnChange(void)
|
||||
{
|
||||
if (K_CanChangeRules() == false)
|
||||
|
|
|
|||
|
|
@ -55,7 +55,6 @@ extern consvar_t cv_itemrespawn;
|
|||
extern consvar_t cv_pointlimit;
|
||||
extern consvar_t cv_timelimit;
|
||||
extern consvar_t cv_numlaps;
|
||||
extern consvar_t cv_basenumlaps;
|
||||
extern UINT32 timelimitintics;
|
||||
extern consvar_t cv_allowexitlevel;
|
||||
|
||||
|
|
|
|||
|
|
@ -258,6 +258,7 @@ typedef enum
|
|||
#define TRICKDELAY (TICRATE/4)
|
||||
|
||||
#define TUMBLEBOUNCES 3
|
||||
#define TUMBLEGRAVITY (4*FRACUNIT)
|
||||
|
||||
//}
|
||||
|
||||
|
|
@ -281,6 +282,7 @@ typedef struct respawnvars_s
|
|||
tic_t airtimer; // Time spent in the air before respawning
|
||||
UINT32 distanceleft; // How far along the course to respawn you
|
||||
tic_t dropdash; // Drop Dash charge timer
|
||||
boolean truedeath; // Your soul has left your body
|
||||
} respawnvars_t;
|
||||
|
||||
// player_t struct for all bot variables
|
||||
|
|
@ -290,6 +292,9 @@ typedef struct botvars_s
|
|||
UINT8 diffincrease; // In GP: bot difficulty will increase this much next round
|
||||
boolean rival; // If true, they're the GP rival
|
||||
|
||||
fixed_t rubberband; // Bot rubberband value
|
||||
UINT16 controller; // Special bot controller linedef ID
|
||||
|
||||
tic_t itemdelay; // Delay before using item at all
|
||||
tic_t itemconfirm; // When high enough, they will use their item
|
||||
|
||||
|
|
@ -533,6 +538,7 @@ typedef struct player_s
|
|||
INT16 totalring; // Total number of rings obtained for GP
|
||||
tic_t realtime; // integer replacement for leveltime
|
||||
UINT8 laps; // Number of laps (optional)
|
||||
UINT8 latestlap;
|
||||
INT32 starpostnum; // The number of the last starpost you hit
|
||||
|
||||
UINT8 ctfteam; // 0 == Spectator, 1 == Red, 2 == Blue
|
||||
|
|
|
|||
|
|
@ -186,6 +186,27 @@ static inline int lib_freeslot(lua_State *L)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (fastcmp(type, "PRECIP"))
|
||||
{
|
||||
// Search if we already have a PRECIP by that name...
|
||||
preciptype_t i;
|
||||
for (i = PRECIP_FIRSTFREESLOT; i < precip_freeslot; i++)
|
||||
if (fastcmp(word, precipprops[i].name))
|
||||
break;
|
||||
|
||||
// We don't, so allocate a new one.
|
||||
if (i >= precip_freeslot) {
|
||||
if (precip_freeslot < MAXPRECIP)
|
||||
{
|
||||
CONS_Printf("Weather PRECIP_%s allocated.\n",word);
|
||||
precipprops[i].name = Z_StrDup(word);
|
||||
lua_pushinteger(L, precip_freeslot);
|
||||
r++;
|
||||
precip_freeslot++;
|
||||
} else
|
||||
CONS_Alert(CONS_WARNING, "Ran out of free PRECIP slots!\n");
|
||||
}
|
||||
}
|
||||
Z_Free(s);
|
||||
lua_remove(L, 1);
|
||||
continue;
|
||||
|
|
@ -465,6 +486,21 @@ static inline int lib_getenum(lua_State *L)
|
|||
if (mathlib) return luaL_error(L, "NiGHTS grade '%s' could not be found.\n", word);
|
||||
return 0;
|
||||
}
|
||||
else if (fastncmp("PRECIP_",word,7)) {
|
||||
p = word+7;
|
||||
for (i = 0; i < MAXPRECIP; i++)
|
||||
{
|
||||
if (precipprops[i].name == NULL)
|
||||
break;
|
||||
|
||||
if (fastcmp(p, precipprops[i].name))
|
||||
{
|
||||
lua_pushinteger(L, PRECIP_NONE + i);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return luaL_error(L, "weather type '%s' does not exist.\n", word);
|
||||
}
|
||||
else if (!mathlib && fastncmp("A_",word,2)) {
|
||||
char *caps;
|
||||
// Try to get a Lua action first.
|
||||
|
|
|
|||
111
src/deh_soc.c
111
src/deh_soc.c
|
|
@ -287,6 +287,25 @@ void readfreeslots(MYFILE *f)
|
|||
lastcustomtol <<= 1;
|
||||
}
|
||||
}
|
||||
else if (fastcmp(type, "PRECIP"))
|
||||
{
|
||||
// Search if we already have a PRECIP by that name...
|
||||
for (i = PRECIP_FIRSTFREESLOT; i < (int)precip_freeslot; i++)
|
||||
if (fastcmp(word, precipprops[i].name))
|
||||
break;
|
||||
|
||||
// We found it? Then don't allocate another one.
|
||||
if (i < (int)precip_freeslot)
|
||||
continue;
|
||||
|
||||
// We don't, so allocate a new one.
|
||||
if (precip_freeslot < MAXPRECIP)
|
||||
{
|
||||
precipprops[i].name = Z_StrDup(word);
|
||||
precip_freeslot++;
|
||||
} else
|
||||
deh_warning("Ran out of free PRECIP slots!\n");
|
||||
}
|
||||
else
|
||||
deh_warning("Freeslots: unknown enum class '%s' for '%s_%s'", type, type, word);
|
||||
}
|
||||
|
|
@ -1333,7 +1352,7 @@ void readlevelheader(MYFILE *f, INT32 num)
|
|||
strlwr(mapheaderinfo[num-1]->forcecharacter); // skin names are lowercase
|
||||
}
|
||||
else if (fastcmp(word, "WEATHER"))
|
||||
mapheaderinfo[num-1]->weather = (UINT8)get_number(word2);
|
||||
mapheaderinfo[num-1]->weather = get_precip(word2);
|
||||
else if (fastcmp(word, "SKYTEXTURE"))
|
||||
deh_strlcpy(mapheaderinfo[num-1]->skytexture, word2,
|
||||
sizeof(mapheaderinfo[num-1]->skytexture), va("Level header %d: sky texture", num));
|
||||
|
|
@ -1371,6 +1390,23 @@ void readlevelheader(MYFILE *f, INT32 num)
|
|||
mapheaderinfo[num-1]->mobj_scale = get_number(word2);
|
||||
else if (fastcmp(word, "DEFAULTWAYPOINTRADIUS"))
|
||||
mapheaderinfo[num-1]->default_waypoint_radius = get_number(word2);
|
||||
else if (fastcmp(word, "LIGHTCONTRAST"))
|
||||
{
|
||||
mapheaderinfo[num-1]->light_contrast = (UINT8)i;
|
||||
}
|
||||
else if (fastcmp(word, "LIGHTANGLE"))
|
||||
{
|
||||
if (fastcmp(word2, "EVEN"))
|
||||
{
|
||||
mapheaderinfo[num-1]->use_light_angle = false;
|
||||
mapheaderinfo[num-1]->light_angle = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mapheaderinfo[num-1]->use_light_angle = true;
|
||||
mapheaderinfo[num-1]->light_angle = FixedAngle(FloatToFixed(atof(word2)));
|
||||
}
|
||||
}
|
||||
// Individual triggers for level flags, for ease of use (and 2.0 compatibility)
|
||||
else if (fastcmp(word, "SCRIPTISFILE"))
|
||||
{
|
||||
|
|
@ -3692,6 +3728,61 @@ if (!followers[numfollowers].field) \
|
|||
Z_Free(s);
|
||||
}
|
||||
|
||||
void readweather(MYFILE *f, INT32 num)
|
||||
{
|
||||
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
|
||||
char *word;
|
||||
char *word2;
|
||||
char *tmp;
|
||||
|
||||
do
|
||||
{
|
||||
if (myfgets(s, MAXLINELEN, f))
|
||||
{
|
||||
if (s[0] == '\n')
|
||||
break;
|
||||
|
||||
// First remove trailing newline, if there is one
|
||||
tmp = strchr(s, '\n');
|
||||
if (tmp)
|
||||
*tmp = '\0';
|
||||
|
||||
tmp = strchr(s, '#');
|
||||
if (tmp)
|
||||
*tmp = '\0';
|
||||
if (s == tmp)
|
||||
continue; // Skip comment lines, but don't break.
|
||||
|
||||
// Set / reset word
|
||||
word = s;
|
||||
|
||||
// Get the part before the " = "
|
||||
tmp = strchr(s, '=');
|
||||
if (tmp)
|
||||
*(tmp-1) = '\0';
|
||||
else
|
||||
break;
|
||||
strupr(word);
|
||||
|
||||
// Now get the part after
|
||||
word2 = tmp += 2;
|
||||
|
||||
if (fastcmp(word, "TYPE"))
|
||||
{
|
||||
precipprops[num].type = get_mobjtype(word2);
|
||||
}
|
||||
else if (fastcmp(word, "EFFECTS"))
|
||||
{
|
||||
precipprops[num].effects = get_number(word2);
|
||||
}
|
||||
else
|
||||
deh_warning("Weather %d : unknown word '%s'", num, word);
|
||||
}
|
||||
} while (!myfeof(f));
|
||||
|
||||
Z_Free(s);
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
|
@ -3814,6 +3905,24 @@ sfxenum_t get_sfx(const char *word)
|
|||
return GT_COOP;
|
||||
}*/
|
||||
|
||||
preciptype_t get_precip(const char *word)
|
||||
{ // Returns the value of PRECIP_ enumerations
|
||||
preciptype_t i;
|
||||
if (*word >= '0' && *word <= '9')
|
||||
return atoi(word);
|
||||
if (fastncmp("PRECIP_",word,4))
|
||||
word += 7; // take off the PRECIP_
|
||||
for (i = 0; i < MAXPRECIP; i++)
|
||||
{
|
||||
if (precipprops[i].name == NULL)
|
||||
break;
|
||||
if (fasticmp(word, precipprops[i].name))
|
||||
return i;
|
||||
}
|
||||
deh_warning("Couldn't find weather type named 'PRECIP_%s'",word);
|
||||
return PRECIP_RAIN;
|
||||
}
|
||||
|
||||
/// \todo Make ANY of this completely over-the-top math craziness obey the order of operations.
|
||||
static fixed_t op_mul(fixed_t a, fixed_t b) { return a*b; }
|
||||
static fixed_t op_div(fixed_t a, fixed_t b) { return a/b; }
|
||||
|
|
|
|||
|
|
@ -83,5 +83,7 @@ void clear_conditionsets(void);
|
|||
|
||||
void readcupheader(MYFILE *f, cupheader_t *cup);
|
||||
void readfollower(MYFILE *f);
|
||||
preciptype_t get_precip(const char *word);
|
||||
void readweather(MYFILE *f, INT32 num);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2541,6 +2541,13 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
"S_GREYSPRING3",
|
||||
"S_GREYSPRING4",
|
||||
|
||||
// Orange Spring (Pogo)
|
||||
"S_POGOSPRING1",
|
||||
"S_POGOSPRING2",
|
||||
"S_POGOSPRING2B",
|
||||
"S_POGOSPRING3",
|
||||
"S_POGOSPRING4",
|
||||
|
||||
// Yellow Diagonal Spring
|
||||
"S_YDIAG1",
|
||||
"S_YDIAG2",
|
||||
|
|
@ -4631,6 +4638,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
|||
"MT_REDSPRING",
|
||||
"MT_BLUESPRING",
|
||||
"MT_GREYSPRING",
|
||||
"MT_POGOSPRING",
|
||||
"MT_YELLOWDIAG", // Yellow Diagonal Spring
|
||||
"MT_REDDIAG", // Red Diagonal Spring
|
||||
"MT_BLUEDIAG", // Blue Diagonal Spring
|
||||
|
|
@ -6645,6 +6653,11 @@ struct int_const_s const INT_CONST[] = {
|
|||
{"SPOT_WEAK",SPOT_WEAK},
|
||||
{"SPOT_BUMP",SPOT_BUMP},
|
||||
|
||||
// precipeffect_t
|
||||
{"PRECIPFX_THUNDER",PRECIPFX_THUNDER},
|
||||
{"PRECIPFX_LIGHTNING",PRECIPFX_LIGHTNING},
|
||||
{"PRECIPFX_WATERPARTICLES",PRECIPFX_WATERPARTICLES},
|
||||
|
||||
{NULL,0}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -554,6 +554,18 @@ static void DEH_LoadDehackedFile(MYFILE *f, boolean mainfile)
|
|||
|
||||
readcupheader(f, cup);
|
||||
}
|
||||
else if (fastcmp(word, "WEATHER") || fastcmp(word, "PRECIP") || fastcmp(word, "PRECIPITATION"))
|
||||
{
|
||||
if (i == 0 && word2[0] != '0') // If word2 isn't a number
|
||||
i = get_precip(word2); // find a weather type by name
|
||||
if (i < MAXPRECIP && i > 0)
|
||||
readweather(f, i);
|
||||
else
|
||||
{
|
||||
deh_warning("Weather number %d out of range (1 - %d)", i, MAXPRECIP-1);
|
||||
ignorelines(f);
|
||||
}
|
||||
}
|
||||
else if (fastcmp(word, "RINGRACERS"))
|
||||
{
|
||||
if (isdigit(word2[0]))
|
||||
|
|
|
|||
|
|
@ -41,8 +41,7 @@ extern UINT32 mapmusresume;
|
|||
// Use other bits if necessary.
|
||||
|
||||
extern UINT32 maptol;
|
||||
extern UINT8 globalweather;
|
||||
extern UINT8 curWeather;
|
||||
|
||||
extern INT32 cursaveslot;
|
||||
//extern INT16 lastmapsaved;
|
||||
extern INT16 lastmaploaded;
|
||||
|
|
@ -64,31 +63,44 @@ extern tic_t marathontime;
|
|||
extern UINT8 numgameovers;
|
||||
extern SINT8 startinglivesbalance[maxgameovers+1];
|
||||
|
||||
#define NUMPRECIPFREESLOTS 64
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PRECIP_NONE = 0,
|
||||
|
||||
PRECIP_RAIN,
|
||||
PRECIP_SNOW,
|
||||
PRECIP_BLIZZARD,
|
||||
PRECIP_STORM,
|
||||
PRECIP_STORM_NORAIN,
|
||||
PRECIP_STORM_NOSTRIKES,
|
||||
|
||||
PRECIP_FIRSTFREESLOT,
|
||||
PRECIP_LASTFREESLOT = PRECIP_FIRSTFREESLOT + NUMPRECIPFREESLOTS - 1,
|
||||
|
||||
MAXPRECIP
|
||||
} preciptype_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PRECIPFX_THUNDER = 1,
|
||||
PRECIPFX_LIGHTNING = 1<<1
|
||||
PRECIPFX_LIGHTNING = 1<<1,
|
||||
PRECIPFX_WATERPARTICLES = 1<<2
|
||||
} precipeffect_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *name;
|
||||
mobjtype_t type;
|
||||
precipeffect_t effects;
|
||||
} precipprops_t;
|
||||
|
||||
extern precipprops_t precipprops[MAXPRECIP];
|
||||
extern preciptype_t precip_freeslot;
|
||||
|
||||
extern preciptype_t globalweather;
|
||||
extern preciptype_t curWeather;
|
||||
|
||||
// Set if homebrew PWAD stuff has been added.
|
||||
extern boolean modifiedgame;
|
||||
|
|
@ -385,6 +397,10 @@ typedef struct
|
|||
fixed_t mobj_scale; ///< Replacement for TOL_ERZ3
|
||||
fixed_t default_waypoint_radius; ///< 0 is a special value for DEFAULT_WAYPOINT_RADIUS, but scaled with mobjscale
|
||||
|
||||
UINT8 light_contrast; ///< Range of wall lighting. 0 is no lighting.
|
||||
boolean use_light_angle; ///< When false, wall lighting is evenly distributed. When true, wall lighting is directional.
|
||||
angle_t light_angle; ///< Angle of directional wall lighting.
|
||||
|
||||
// Music stuff.
|
||||
UINT32 musinterfadeout; ///< Fade out level music on intermission screen in milliseconds
|
||||
char musintername[7]; ///< Intermission screen music.
|
||||
|
|
@ -665,6 +681,13 @@ extern tic_t racecountdown, exitcountdown;
|
|||
extern fixed_t gravity;
|
||||
extern fixed_t mapobjectscale;
|
||||
|
||||
extern struct maplighting
|
||||
{
|
||||
UINT8 contrast;
|
||||
boolean directional;
|
||||
angle_t angle;
|
||||
} maplighting;
|
||||
|
||||
//for CTF balancing
|
||||
extern INT16 autobalance;
|
||||
extern INT16 teamscramble;
|
||||
|
|
@ -676,6 +699,7 @@ extern INT16 scramblecount; //for CTF team scramble
|
|||
extern INT32 cheats;
|
||||
|
||||
// SRB2kart
|
||||
extern UINT8 numlaps;
|
||||
extern UINT8 gamespeed;
|
||||
extern boolean franticitems;
|
||||
extern boolean encoremode, prevencoremode;
|
||||
|
|
|
|||
22
src/g_demo.c
22
src/g_demo.c
|
|
@ -53,8 +53,13 @@
|
|||
#include "k_color.h"
|
||||
#include "k_follower.h"
|
||||
|
||||
#ifdef TESTERS
|
||||
static CV_PossibleValue_t recordmultiplayerdemos_cons_t[] = {{2, "Auto Save"}, {0, NULL}};
|
||||
consvar_t cv_recordmultiplayerdemos = CVAR_INIT ("netdemo_record", "Auto Save", CV_SAVE, recordmultiplayerdemos_cons_t, NULL);
|
||||
#else
|
||||
static CV_PossibleValue_t recordmultiplayerdemos_cons_t[] = {{0, "Disabled"}, {1, "Manual Save"}, {2, "Auto Save"}, {0, NULL}};
|
||||
consvar_t cv_recordmultiplayerdemos = CVAR_INIT ("netdemo_record", "Manual Save", CV_SAVE, recordmultiplayerdemos_cons_t, NULL);
|
||||
#endif
|
||||
|
||||
static CV_PossibleValue_t netdemosyncquality_cons_t[] = {{1, "MIN"}, {35, "MAX"}, {0, NULL}};
|
||||
consvar_t cv_netdemosyncquality = CVAR_INIT ("netdemo_syncquality", "1", CV_SAVE, netdemosyncquality_cons_t, NULL);
|
||||
|
|
@ -1994,6 +1999,7 @@ void G_BeginRecording(void)
|
|||
|
||||
WRITEUINT8(demo_p, demoflags);
|
||||
WRITEUINT8(demo_p, gametype & 0xFF);
|
||||
WRITEUINT8(demo_p, numlaps);
|
||||
|
||||
// file list
|
||||
m = demo_p;/* file count */
|
||||
|
|
@ -2424,6 +2430,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
p += 16; // map md5
|
||||
flags = READUINT8(p); // demoflags
|
||||
p++; // gametype
|
||||
p++; // numlaps
|
||||
G_SkipDemoExtraFiles(&p);
|
||||
|
||||
aflags = flags & (DF_TIMEATTACK|DF_BREAKTHECAPSULES);
|
||||
|
|
@ -2481,6 +2488,7 @@ UINT8 G_CmpDemoTime(char *oldname, char *newname)
|
|||
p += 16; // mapmd5
|
||||
flags = READUINT8(p);
|
||||
p++; // gametype
|
||||
p++; // numlaps
|
||||
G_SkipDemoExtraFiles(&p);
|
||||
if (!(flags & aflags))
|
||||
{
|
||||
|
|
@ -2595,6 +2603,7 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
|
|||
}
|
||||
|
||||
pdemo->gametype = READUINT8(info_p);
|
||||
pdemo->numlaps = READUINT8(info_p);
|
||||
|
||||
pdemo->addonstatus = G_CheckDemoExtraFiles(&info_p, true);
|
||||
info_p += 4; // RNG seed
|
||||
|
|
@ -2621,20 +2630,11 @@ void G_LoadDemoInfo(menudemo_t *pdemo)
|
|||
if (!stricmp(kartspeed_cons_t[j].strvalue, svalue))
|
||||
pdemo->kartspeed = kartspeed_cons_t[j].value;
|
||||
}
|
||||
else if (netid == cv_basenumlaps.netid && pdemo->gametype == GT_RACE)
|
||||
pdemo->numlaps = atoi(svalue);
|
||||
}
|
||||
|
||||
if (pdemoflags & DF_ENCORE)
|
||||
pdemo->kartspeed |= DF_ENCORE;
|
||||
|
||||
/*// Temporary info until this is actually present in replays.
|
||||
(void)extrainfo_p;
|
||||
sprintf(pdemo->winnername, "transrights420");
|
||||
pdemo->winnerskin = 1;
|
||||
pdemo->winnercolor = SKINCOLOR_MOONSET;
|
||||
pdemo->winnertime = 6666;*/
|
||||
|
||||
// Read standings!
|
||||
count = 0;
|
||||
|
||||
|
|
@ -2830,6 +2830,7 @@ void G_DoPlayDemo(char *defdemoname)
|
|||
demoflags = READUINT8(demo_p);
|
||||
gametype = READUINT8(demo_p);
|
||||
G_SetGametype(gametype);
|
||||
numlaps = READUINT8(demo_p);
|
||||
|
||||
if (demo.title) // Titledemos should always play and ought to always be compatible with whatever wadlist is running.
|
||||
G_SkipDemoExtraFiles(&demo_p);
|
||||
|
|
@ -3253,6 +3254,7 @@ void G_AddGhost(char *defdemoname)
|
|||
}
|
||||
|
||||
p++; // gametype
|
||||
p++; // numlaps
|
||||
G_SkipDemoExtraFiles(&p); // Don't wanna modify the file list for ghosts.
|
||||
|
||||
switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT)
|
||||
|
|
@ -3470,7 +3472,7 @@ void G_UpdateStaffGhostName(lumpnum_t l)
|
|||
}
|
||||
|
||||
p++; // Gametype
|
||||
|
||||
p++; // numlaps
|
||||
G_SkipDemoExtraFiles(&p);
|
||||
|
||||
switch ((flags & DF_ATTACKMASK)>>DF_ATTACKSHIFT)
|
||||
|
|
|
|||
35
src/g_game.c
35
src/g_game.c
|
|
@ -93,20 +93,22 @@ UINT32 mapmusresume;
|
|||
INT16 gamemap = 1;
|
||||
UINT32 maptol;
|
||||
|
||||
UINT8 globalweather = PRECIP_NONE;
|
||||
UINT8 curWeather = PRECIP_NONE;
|
||||
preciptype_t globalweather = PRECIP_NONE;
|
||||
preciptype_t curWeather = PRECIP_NONE;
|
||||
|
||||
precipprops_t precipprops[MAXPRECIP] =
|
||||
{
|
||||
{MT_NULL, 0}, // PRECIP_NONE
|
||||
{MT_RAIN, 0}, // PRECIP_RAIN
|
||||
{MT_SNOWFLAKE, 0}, // PRECIP_SNOW
|
||||
{MT_BLIZZARDSNOW, 0}, // PRECIP_BLIZZARD
|
||||
{MT_RAIN, PRECIPFX_THUNDER|PRECIPFX_LIGHTNING}, // PRECIP_STORM
|
||||
{MT_NULL, PRECIPFX_THUNDER|PRECIPFX_LIGHTNING}, // PRECIP_STORM_NORAIN
|
||||
{MT_RAIN, PRECIPFX_THUNDER} // PRECIP_STORM_NOSTRIKES
|
||||
{"NONE", MT_NULL, 0}, // PRECIP_NONE
|
||||
{"RAIN", MT_RAIN, 0}, // PRECIP_RAIN
|
||||
{"SNOW", MT_SNOWFLAKE, 0}, // PRECIP_SNOW
|
||||
{"BLIZZARD", MT_BLIZZARDSNOW, 0}, // PRECIP_BLIZZARD
|
||||
{"STORM", MT_RAIN, PRECIPFX_THUNDER|PRECIPFX_LIGHTNING}, // PRECIP_STORM
|
||||
{"STORM_NORAIN", MT_NULL, PRECIPFX_THUNDER|PRECIPFX_LIGHTNING}, // PRECIP_STORM_NORAIN
|
||||
{"STORM_NOSTRIKES", MT_RAIN, PRECIPFX_THUNDER} // PRECIP_STORM_NOSTRIKES
|
||||
};
|
||||
|
||||
preciptype_t precip_freeslot = PRECIP_FIRSTFREESLOT;
|
||||
|
||||
INT32 cursaveslot = 0; // Auto-save 1p savegame slot
|
||||
//INT16 lastmapsaved = 0; // Last map we auto-saved at
|
||||
INT16 lastmaploaded = 0; // Last map the game loaded
|
||||
|
|
@ -287,6 +289,8 @@ tic_t racecountdown, exitcountdown; // for racing
|
|||
fixed_t gravity;
|
||||
fixed_t mapobjectscale;
|
||||
|
||||
struct maplighting maplighting;
|
||||
|
||||
INT16 autobalance; //for CTF team balance
|
||||
INT16 teamscramble; //for CTF team scramble
|
||||
INT16 scrambleplayers[MAXPLAYERS]; //for CTF team scramble
|
||||
|
|
@ -298,6 +302,7 @@ INT32 cheats; //for multiplayer cheat commands
|
|||
|
||||
// SRB2Kart
|
||||
// Cvars that we don't want changed mid-game
|
||||
UINT8 numlaps; // Removed from Cvar hell
|
||||
UINT8 gamespeed; // Game's current speed (or difficulty, or cc, or etc); 0 for easy, 1 for normal, 2 for hard
|
||||
boolean encoremode = false; // Encore Mode currently enabled?
|
||||
boolean prevencoremode;
|
||||
|
|
@ -2134,6 +2139,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
INT32 khudcardanimation;
|
||||
INT16 totalring;
|
||||
UINT8 laps;
|
||||
UINT8 latestlap;
|
||||
UINT16 skincolor;
|
||||
INT32 skin;
|
||||
UINT32 availabilities;
|
||||
|
|
@ -2220,6 +2226,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
khudfault = 0;
|
||||
nocontrol = 0;
|
||||
laps = 0;
|
||||
latestlap = 0;
|
||||
totalring = 0;
|
||||
roundscore = 0;
|
||||
exiting = 0;
|
||||
|
|
@ -2260,6 +2267,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
nocontrol = players[player].nocontrol;
|
||||
|
||||
laps = players[player].laps;
|
||||
latestlap = players[player].latestlap;
|
||||
|
||||
totalring = players[player].totalring;
|
||||
roundscore = players[player].roundscore;
|
||||
|
||||
|
|
@ -2316,6 +2325,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
p->karthud[khud_cardanimation] = khudcardanimation;
|
||||
|
||||
p->laps = laps;
|
||||
p->latestlap = latestlap;
|
||||
p->totalring = totalring;
|
||||
|
||||
p->bot = bot;
|
||||
|
|
@ -2342,6 +2352,9 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
p->kickstartaccel = kickstartaccel;
|
||||
p->tripWireState = TRIP_NONE;
|
||||
|
||||
p->botvars.rubberband = FRACUNIT;
|
||||
p->botvars.controller = UINT16_MAX;
|
||||
|
||||
memcpy(&p->respawn, &respawn, sizeof (p->respawn));
|
||||
|
||||
if (follower)
|
||||
|
|
@ -3542,11 +3555,14 @@ static void G_DoCompleted(void)
|
|||
wipegamestate = GS_NULL;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i])
|
||||
{
|
||||
// SRB2Kart: exitlevel shouldn't get you the points
|
||||
if (!players[i].exiting && !(players[i].pflags & PF_NOCONTEST))
|
||||
{
|
||||
clientPowerAdd[i] = 0;
|
||||
|
||||
if (players[i].bot)
|
||||
{
|
||||
K_FakeBotResults(&players[i]);
|
||||
|
|
@ -3564,6 +3580,7 @@ static void G_DoCompleted(void)
|
|||
|
||||
G_PlayerFinishLevel(i); // take away cards and stuff
|
||||
}
|
||||
}
|
||||
|
||||
// play some generic music if there's no win/cool/lose music going on (for exitlevel commands)
|
||||
if ((gametyperules & GTR_CIRCUIT) && ((multiplayer && demo.playback) || j == r_splitscreen+1) && (cv_inttime.value > 0))
|
||||
|
|
|
|||
|
|
@ -285,84 +285,31 @@ UINT8 HWR_FogBlockAlpha(INT32 light, extracolormap_t *colormap) // Let's see if
|
|||
return surfcolor.s.alpha;
|
||||
}
|
||||
|
||||
static FUINT HWR_CalcWallLight(FUINT lightnum, fixed_t v1x, fixed_t v1y, fixed_t v2x, fixed_t v2y)
|
||||
static FUINT HWR_CalcWallLight(FUINT lightnum, seg_t *seg)
|
||||
{
|
||||
INT16 finallight = lightnum;
|
||||
|
||||
if (cv_glfakecontrast.value != 0)
|
||||
if (seg != NULL && P_ApplyLightOffsetFine(lightnum))
|
||||
{
|
||||
const UINT8 contrast = 8;
|
||||
fixed_t extralight = 0;
|
||||
finallight += seg->hwLightOffset;
|
||||
|
||||
if (cv_glfakecontrast.value == 2) // Smooth setting
|
||||
{
|
||||
extralight = (-(contrast<<FRACBITS) +
|
||||
FixedDiv(AngleFixed(R_PointToAngle2(0, 0,
|
||||
abs(v1x - v2x),
|
||||
abs(v1y - v2y))), 90<<FRACBITS)
|
||||
* (contrast * 2)) >> FRACBITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (v1y == v2y)
|
||||
extralight = -contrast;
|
||||
else if (v1x == v2x)
|
||||
extralight = contrast;
|
||||
}
|
||||
|
||||
if (extralight != 0)
|
||||
{
|
||||
finallight += extralight;
|
||||
|
||||
if (finallight < 0)
|
||||
finallight = 0;
|
||||
if (finallight > 255)
|
||||
finallight = 255;
|
||||
}
|
||||
if (finallight > 255) finallight = 255;
|
||||
if (finallight < 0) finallight = 0;
|
||||
}
|
||||
|
||||
return (FUINT)finallight;
|
||||
}
|
||||
|
||||
static FUINT HWR_CalcSlopeLight(FUINT lightnum, angle_t dir, fixed_t delta)
|
||||
static FUINT HWR_CalcSlopeLight(FUINT lightnum, pslope_t *slope)
|
||||
{
|
||||
INT16 finallight = lightnum;
|
||||
|
||||
if (cv_glfakecontrast.value != 0 && cv_glslopecontrast.value != 0)
|
||||
if (slope != NULL && P_ApplyLightOffsetFine(lightnum))
|
||||
{
|
||||
const UINT8 contrast = 8;
|
||||
fixed_t extralight = 0;
|
||||
finallight += slope->hwLightOffset;
|
||||
|
||||
if (cv_glfakecontrast.value == 2) // Smooth setting
|
||||
{
|
||||
fixed_t dirmul = abs(FixedDiv(AngleFixed(dir) - (180<<FRACBITS), 180<<FRACBITS));
|
||||
|
||||
extralight = -(contrast<<FRACBITS) + (dirmul * (contrast * 2));
|
||||
|
||||
extralight = FixedMul(extralight, delta*4) >> FRACBITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
dir = ((dir + ANGLE_45) / ANGLE_90) * ANGLE_90;
|
||||
|
||||
if (dir == ANGLE_180)
|
||||
extralight = -contrast;
|
||||
else if (dir == 0)
|
||||
extralight = contrast;
|
||||
|
||||
if (delta >= FRACUNIT/2)
|
||||
extralight *= 2;
|
||||
}
|
||||
|
||||
if (extralight != 0)
|
||||
{
|
||||
finallight += extralight;
|
||||
|
||||
if (finallight < 0)
|
||||
finallight = 0;
|
||||
if (finallight > 255)
|
||||
finallight = 255;
|
||||
}
|
||||
if (finallight > 255) finallight = 255;
|
||||
if (finallight < 0) finallight = 0;
|
||||
}
|
||||
|
||||
return (FUINT)finallight;
|
||||
|
|
@ -573,9 +520,7 @@ static void HWR_RenderPlane(subsector_t *subsector, extrasubsector_t *xsub, bool
|
|||
for (i = 0, v3d = planeVerts; i < nrPlaneVerts; i++,v3d++,pv++)
|
||||
SETUP3DVERT(v3d, pv->x, pv->y);
|
||||
|
||||
if (slope)
|
||||
lightlevel = HWR_CalcSlopeLight(lightlevel, R_PointToAngle2(0, 0, slope->normal.x, slope->normal.y), abs(slope->zdelta));
|
||||
|
||||
lightlevel = HWR_CalcSlopeLight(lightlevel, slope);
|
||||
HWR_Lighting(&Surf, lightlevel, planecolormap);
|
||||
|
||||
if (PolyFlags & (PF_Translucent|PF_Additive|PF_Subtractive|PF_Fog))
|
||||
|
|
@ -894,7 +839,7 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum,
|
|||
INT32 solid, i;
|
||||
lightlist_t * list = sector->lightlist;
|
||||
const UINT8 alpha = Surf->PolyColor.s.alpha;
|
||||
FUINT lightnum = HWR_CalcWallLight(sector->lightlevel, v1x, v1y, v2x, v2y);
|
||||
FUINT lightnum = sector->lightlevel;
|
||||
extracolormap_t *colormap = NULL;
|
||||
|
||||
realtop = top = wallVerts[3].y;
|
||||
|
|
@ -918,12 +863,12 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum,
|
|||
{
|
||||
if (pfloor && (pfloor->flags & FF_FOG))
|
||||
{
|
||||
lightnum = HWR_CalcWallLight(pfloor->master->frontsector->lightlevel, v1x, v1y, v2x, v2y);
|
||||
lightnum = pfloor->master->frontsector->lightlevel;
|
||||
colormap = pfloor->master->frontsector->extra_colormap;
|
||||
}
|
||||
else
|
||||
{
|
||||
lightnum = HWR_CalcWallLight(*list[i].lightlevel, v1x, v1y, v2x, v2y);
|
||||
lightnum = *list[i].lightlevel;
|
||||
colormap = *list[i].extra_colormap;
|
||||
}
|
||||
}
|
||||
|
|
@ -1006,11 +951,11 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum,
|
|||
wallVerts[1].y = endbot;
|
||||
|
||||
if (polyflags & PF_Fog)
|
||||
HWR_AddTransparentWall(wallVerts, Surf, texnum, polyflags, true, lightnum, colormap);
|
||||
HWR_AddTransparentWall(wallVerts, Surf, texnum, polyflags, true, HWR_CalcWallLight(lightnum, gl_curline), colormap);
|
||||
else if (polyflags & (PF_Translucent|PF_Additive|PF_Subtractive|PF_Environment))
|
||||
HWR_AddTransparentWall(wallVerts, Surf, texnum, polyflags, false, lightnum, colormap);
|
||||
HWR_AddTransparentWall(wallVerts, Surf, texnum, polyflags, false, HWR_CalcWallLight(lightnum, gl_curline), colormap);
|
||||
else
|
||||
HWR_ProjectWall(wallVerts, Surf, polyflags, lightnum, colormap);
|
||||
HWR_ProjectWall(wallVerts, Surf, polyflags, HWR_CalcWallLight(lightnum, gl_curline), colormap);
|
||||
|
||||
top = bot;
|
||||
endtop = endbot;
|
||||
|
|
@ -1035,11 +980,11 @@ static void HWR_SplitWall(sector_t *sector, FOutVector *wallVerts, INT32 texnum,
|
|||
wallVerts[1].y = endbot;
|
||||
|
||||
if (polyflags & PF_Fog)
|
||||
HWR_AddTransparentWall(wallVerts, Surf, texnum, polyflags, true, lightnum, colormap);
|
||||
HWR_AddTransparentWall(wallVerts, Surf, texnum, polyflags, true, HWR_CalcWallLight(lightnum, gl_curline), colormap);
|
||||
else if (polyflags & (PF_Translucent|PF_Additive|PF_Subtractive|PF_Environment))
|
||||
HWR_AddTransparentWall(wallVerts, Surf, texnum, polyflags, false, lightnum, colormap);
|
||||
HWR_AddTransparentWall(wallVerts, Surf, texnum, polyflags, false, HWR_CalcWallLight(lightnum, gl_curline), colormap);
|
||||
else
|
||||
HWR_ProjectWall(wallVerts, Surf, polyflags, lightnum, colormap);
|
||||
HWR_ProjectWall(wallVerts, Surf, polyflags, HWR_CalcWallLight(lightnum, gl_curline), colormap);
|
||||
}
|
||||
|
||||
// HWR_DrawSkyWall
|
||||
|
|
@ -1083,7 +1028,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
|
|||
fixed_t h, l; // 3D sides and 2s middle textures
|
||||
fixed_t hS, lS;
|
||||
|
||||
FUINT lightnum = 0; // shut up compiler
|
||||
FUINT lightnum = 255; // shut up compiler
|
||||
extracolormap_t *colormap;
|
||||
FSurfaceInfo Surf;
|
||||
|
||||
|
|
@ -1126,7 +1071,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
|
|||
cliphigh = (float)(texturehpeg + (gl_curline->flength*FRACUNIT));
|
||||
}
|
||||
|
||||
lightnum = HWR_CalcWallLight(gl_frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y);
|
||||
lightnum = HWR_CalcWallLight(gl_frontsector->lightlevel, gl_curline);
|
||||
colormap = gl_frontsector->extra_colormap;
|
||||
|
||||
if (gl_frontsector)
|
||||
|
|
@ -1801,7 +1746,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
|
|||
|
||||
blendmode = PF_Fog|PF_NoTexture;
|
||||
|
||||
lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y);
|
||||
lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, gl_curline);
|
||||
colormap = rover->master->frontsector->extra_colormap;
|
||||
|
||||
Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap);
|
||||
|
|
@ -1927,7 +1872,7 @@ static void HWR_ProcessSeg(void) // Sort of like GLWall::Process in GZDoom
|
|||
|
||||
blendmode = PF_Fog|PF_NoTexture;
|
||||
|
||||
lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, vs.x, vs.y, ve.x, ve.y);
|
||||
lightnum = HWR_CalcWallLight(rover->master->frontsector->lightlevel, gl_curline);
|
||||
colormap = rover->master->frontsector->extra_colormap;
|
||||
|
||||
Surf.PolyColor.s.alpha = HWR_FogBlockAlpha(rover->master->frontsector->lightlevel, rover->master->frontsector->extra_colormap);
|
||||
|
|
@ -2384,9 +2329,9 @@ static void HWR_AddLine(seg_t * line)
|
|||
// PrBoom: use REAL clipping math YAYYYYYYY!!!
|
||||
|
||||
if (!gld_clipper_SafeCheckRange(angle2, angle1))
|
||||
{
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
checkforemptylines = true;
|
||||
#else
|
||||
|
|
@ -2474,11 +2419,11 @@ static void HWR_AddLine(seg_t * line)
|
|||
|
||||
#ifdef NEWCLIP
|
||||
if (!line->backsector)
|
||||
{
|
||||
{
|
||||
gld_clipper_SafeAddClipRange(angle2, angle1);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
boolean bothceilingssky = false, bothfloorssky = false;
|
||||
|
||||
gl_backsector = R_FakeFlat(gl_backsector, &tempsec, NULL, NULL, true);
|
||||
|
|
@ -2511,7 +2456,7 @@ static void HWR_AddLine(seg_t * line)
|
|||
// and no middle texture.
|
||||
if (checkforemptylines && R_IsEmptyLine(line, gl_frontsector, gl_backsector))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
HWR_ProcessSeg(); // Doesn't need arguments because they're defined globally :D
|
||||
return;
|
||||
|
|
@ -5619,6 +5564,7 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
float x1, x2;
|
||||
float z1, z2;
|
||||
float rightsin, rightcos;
|
||||
float this_scale;
|
||||
spritedef_t *sprdef;
|
||||
spriteframe_t *sprframe;
|
||||
size_t lumpoff;
|
||||
|
|
@ -5641,6 +5587,8 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
R_InterpolatePrecipMobjState(thing, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
this_scale = FIXED_TO_FLOAT(interp.scale);
|
||||
|
||||
// transform the origin point
|
||||
tr_x = FIXED_TO_FLOAT(interp.x) - gl_viewx;
|
||||
tr_y = FIXED_TO_FLOAT(interp.y) - gl_viewy;
|
||||
|
|
@ -5693,6 +5641,9 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
x2 = FIXED_TO_FLOAT(spritecachedinfo[lumpoff].width - spritecachedinfo[lumpoff].offset);
|
||||
}
|
||||
|
||||
x1 *= this_scale;
|
||||
x2 *= this_scale;
|
||||
|
||||
z1 = tr_y + x1 * rightsin;
|
||||
z2 = tr_y - x2 * rightsin;
|
||||
x1 = tr_x + x1 * rightcos;
|
||||
|
|
@ -5720,8 +5671,8 @@ static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
#endif
|
||||
|
||||
// set top/bottom coords
|
||||
vis->gzt = FIXED_TO_FLOAT(interp.z + spritecachedinfo[lumpoff].topoffset);
|
||||
vis->gz = vis->gzt - FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height);
|
||||
vis->gzt = FIXED_TO_FLOAT(interp.z) + (FIXED_TO_FLOAT(spritecachedinfo[lumpoff].topoffset) * this_scale);
|
||||
vis->gz = vis->gzt - (FIXED_TO_FLOAT(spritecachedinfo[lumpoff].height) * this_scale);
|
||||
|
||||
vis->precip = true;
|
||||
|
||||
|
|
@ -6574,7 +6525,6 @@ static CV_PossibleValue_t glshaders_cons_t[] = {{HWD_SHADEROPTION_OFF, "Off"}, {
|
|||
#ifdef BAD_MODEL_OPTIONS
|
||||
static CV_PossibleValue_t glmodelinterpolation_cons_t[] = {{0, "Off"}, {1, "Sometimes"}, {2, "Always"}, {0, NULL}};
|
||||
#endif
|
||||
static CV_PossibleValue_t glfakecontrast_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Smooth"}, {0, NULL}};
|
||||
static CV_PossibleValue_t glshearing_cons_t[] = {{0, "Off"}, {1, "On"}, {2, "Third-person"}, {0, NULL}};
|
||||
|
||||
static void CV_glfiltermode_OnChange(void);
|
||||
|
|
@ -6609,8 +6559,6 @@ consvar_t cv_glmodellighting = CVAR_INIT ("gr_modellighting", "Off", CV_SAVE, CV
|
|||
consvar_t cv_glshearing = CVAR_INIT ("gr_shearing", "Off", CV_SAVE, glshearing_cons_t, NULL);
|
||||
consvar_t cv_glspritebillboarding = CVAR_INIT ("gr_spritebillboarding", "On", CV_SAVE, CV_OnOff, NULL);
|
||||
consvar_t cv_glskydome = CVAR_INIT ("gr_skydome", "On", CV_SAVE, CV_OnOff, NULL);
|
||||
consvar_t cv_glfakecontrast = CVAR_INIT ("gr_fakecontrast", "Smooth", CV_SAVE, glfakecontrast_cons_t, NULL);
|
||||
consvar_t cv_glslopecontrast = CVAR_INIT ("gr_slopecontrast", "Off", CV_SAVE, CV_OnOff, NULL);
|
||||
|
||||
consvar_t cv_glfiltermode = CVAR_INIT ("gr_filtermode", "Nearest", CV_SAVE|CV_CALL, glfiltermode_cons_t, CV_glfiltermode_OnChange);
|
||||
consvar_t cv_glanisotropicmode = CVAR_INIT ("gr_anisotropicmode", "1", CV_CALL, glanisotropicmode_cons_t, CV_glanisotropic_OnChange);
|
||||
|
|
@ -6652,7 +6600,6 @@ void HWR_AddCommands(void)
|
|||
|
||||
CV_RegisterVar(&cv_glskydome);
|
||||
CV_RegisterVar(&cv_glspritebillboarding);
|
||||
CV_RegisterVar(&cv_glfakecontrast);
|
||||
CV_RegisterVar(&cv_glshearing);
|
||||
CV_RegisterVar(&cv_glshaders);
|
||||
CV_RegisterVar(&cv_glallowshaders);
|
||||
|
|
|
|||
|
|
@ -113,8 +113,6 @@ extern consvar_t cv_glsolvetjoin;
|
|||
extern consvar_t cv_glshearing;
|
||||
extern consvar_t cv_glspritebillboarding;
|
||||
extern consvar_t cv_glskydome;
|
||||
extern consvar_t cv_glfakecontrast;
|
||||
extern consvar_t cv_glslopecontrast;
|
||||
|
||||
extern consvar_t cv_glbatching;
|
||||
|
||||
|
|
|
|||
|
|
@ -1381,10 +1381,6 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
R_InterpolateMobjState(spr->mobj, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
fixed_t interpx = R_InterpolateFixed(spr->mobj->old_x, spr->mobj->x);
|
||||
fixed_t interpy = R_InterpolateFixed(spr->mobj->old_y, spr->mobj->y);
|
||||
fixed_t interpz = R_InterpolateFixed(spr->mobj->old_z, spr->mobj->z);
|
||||
|
||||
// hitlag vibrating
|
||||
if (spr->mobj->hitlag > 0 && (spr->mobj->eflags & MFE_DAMAGEHITLAG))
|
||||
{
|
||||
|
|
@ -1395,15 +1391,15 @@ boolean HWR_DrawModel(gl_vissprite_t *spr)
|
|||
mul = -mul;
|
||||
}
|
||||
|
||||
interpx += FixedMul(spr->mobj->momx, mul);
|
||||
interpy += FixedMul(spr->mobj->momy, mul);
|
||||
interpy += FixedMul(spr->mobj->momz, mul);
|
||||
interp.x += FixedMul(spr->mobj->momx, mul);
|
||||
interp.y += FixedMul(spr->mobj->momy, mul);
|
||||
interp.z += FixedMul(spr->mobj->momz, mul);
|
||||
}
|
||||
|
||||
// sprite offset
|
||||
interpx += spr->mobj->sprxoff;
|
||||
interpy += spr->mobj->spryoff;
|
||||
interpz += spr->mobj->sprzoff;
|
||||
interp.x += spr->mobj->sprxoff;
|
||||
interp.y += spr->mobj->spryoff;
|
||||
interp.z += spr->mobj->sprzoff;
|
||||
|
||||
// Apparently people don't like jump frames like that, so back it goes
|
||||
//if (tics > durs)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ Documentation available here.
|
|||
#include "doomdef.h"
|
||||
#include "d_clisrv.h"
|
||||
#include "command.h"
|
||||
#include "console.h"
|
||||
#include "m_argv.h"
|
||||
#include "k_menu.h"
|
||||
#include "mserv.h"
|
||||
|
|
@ -81,6 +82,19 @@ Contact_error (void)
|
|||
);
|
||||
}
|
||||
|
||||
static void
|
||||
Printf_url (const char *url)
|
||||
{
|
||||
boolean startup;
|
||||
|
||||
I_lock_mutex(&con_mutex);
|
||||
startup = con_startup;
|
||||
I_unlock_mutex(con_mutex);
|
||||
|
||||
(startup ? I_OutputMsg : CONS_Printf)(
|
||||
"HMS: connecting '%s'...\n", url);
|
||||
}
|
||||
|
||||
static size_t
|
||||
HMS_on_read (char *s, size_t _1, size_t n, void *userdata)
|
||||
{
|
||||
|
|
@ -180,7 +194,7 @@ HMS_connect (const char *format, ...)
|
|||
if (quack_token)
|
||||
sprintf(&url[seek], "&token=%s", quack_token);
|
||||
|
||||
CONS_Printf("HMS: connecting '%s'...\n", url);
|
||||
Printf_url(url);
|
||||
|
||||
buffer = malloc(sizeof *buffer);
|
||||
buffer->curl = curl;
|
||||
|
|
|
|||
|
|
@ -2447,7 +2447,7 @@ static void HU_DrawRankings(void)
|
|||
if (circuitmap)
|
||||
{
|
||||
V_DrawCenteredString(64, 8, 0, "LAP COUNT");
|
||||
V_DrawCenteredString(64, 16, hilicol, va("%d", cv_numlaps.value));
|
||||
V_DrawCenteredString(64, 16, hilicol, va("%d", numlaps));
|
||||
}
|
||||
|
||||
V_DrawCenteredString(256, 8, 0, "GAME SPEED");
|
||||
|
|
|
|||
|
|
@ -595,13 +595,13 @@ static boolean SOCK_Get(void)
|
|||
#ifdef USE_STUN
|
||||
if (STUN_got_response(doomcom->data, c))
|
||||
{
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (hole_punch(c))
|
||||
{
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
// find remote node number
|
||||
|
|
|
|||
41
src/info.c
41
src/info.c
|
|
@ -391,6 +391,7 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"SPHR", // Red Horizontal Spring
|
||||
"SPHB", // Blue Horizontal Spring
|
||||
"SPHG", // Grey Horizontal Spring
|
||||
"POGS", // Pogo Spring
|
||||
"BSTY", // Yellow Booster
|
||||
"BSTR", // Red Booster
|
||||
|
||||
|
|
@ -3072,6 +3073,13 @@ state_t states[NUMSTATES] =
|
|||
{SPR_SPVG, 0, 1, {NULL}, 0, 0, S_GREYSPRING4}, // S_GREYSPRING3
|
||||
{SPR_SPVG, 2, 4, {NULL}, 0, 0, S_GREYSPRING1}, // S_GREYSPRING4
|
||||
|
||||
// Orange Spring (Pogo)
|
||||
{SPR_POGS, 0, -1, {NULL}, 0, 0, S_NULL}, // S_POGOSPRING1
|
||||
{SPR_POGS, 1, 2, {A_Pain}, 0, 0, S_POGOSPRING3}, // S_POGOSPRING2
|
||||
{SPR_POGS, 1, 2, {A_PlaySeeSound}, 0, 0, S_POGOSPRING3}, // S_POGOSPRING2B
|
||||
{SPR_POGS, 0, 1, {NULL}, 0, 0, S_POGOSPRING4}, // S_POGOSPRING3
|
||||
{SPR_POGS, 2, 4, {NULL}, 0, 0, S_POGOSPRING1}, // S_POGOSPRING4
|
||||
|
||||
// Yellow Diagonal Spring
|
||||
{SPR_SPDY, 0, -1, {NULL}, 0, 0, S_NULL}, // S_YDIAG1
|
||||
{SPR_SPDY, 1, 1, {A_Pain}, 0, 0, S_YDIAG3}, // S_YDIAG2
|
||||
|
|
@ -8236,6 +8244,33 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_GREYSPRING2 // raisestate
|
||||
},
|
||||
|
||||
{ // MT_POGOSPRING
|
||||
-1, // doomednum
|
||||
S_POGOSPRING1, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_POGOSPRING2B, // seestate
|
||||
sfx_eggspr, // seesound
|
||||
0, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
SKINCOLOR_SUNSLAM, // painchance
|
||||
sfx_s3kb1, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
48*FRACUNIT, // radius
|
||||
32*FRACUNIT, // height
|
||||
0, // display offset
|
||||
32*FRACUNIT, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_SOLID|MF_SPRING|MF_NOGRAVITY|MF_DONTENCOREMAP, // flags
|
||||
S_POGOSPRING2 // raisestate
|
||||
},
|
||||
|
||||
{ // MT_YELLOWDIAG
|
||||
554, // doomednum
|
||||
S_YDIAG1, // spawnstate
|
||||
|
|
@ -18246,7 +18281,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_SPLASH1, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
-72*FRACUNIT, // speed
|
||||
72*FRACUNIT, // speed
|
||||
1*FRACUNIT, // radius
|
||||
8*FRACUNIT, // height
|
||||
0, // display offset
|
||||
|
|
@ -18273,7 +18308,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
-2*FRACUNIT, // speed
|
||||
2*FRACUNIT, // speed
|
||||
4*FRACUNIT, // radius
|
||||
4*FRACUNIT, // height
|
||||
0, // display offset
|
||||
|
|
@ -18300,7 +18335,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
-24*FRACUNIT, // speed
|
||||
24*FRACUNIT, // speed
|
||||
4*FRACUNIT, // radius
|
||||
4*FRACUNIT, // height
|
||||
0, // display offset
|
||||
|
|
|
|||
|
|
@ -937,6 +937,7 @@ typedef enum sprite
|
|||
SPR_SPHR, // Red Horizontal Spring
|
||||
SPR_SPHB, // Blue Horizontal Spring
|
||||
SPR_SPHG, // Grey Horizontal Spring
|
||||
SPR_POGS, // Pogo Spring
|
||||
SPR_BSTY, // Yellow Booster
|
||||
SPR_BSTR, // Red Booster
|
||||
|
||||
|
|
@ -3529,6 +3530,13 @@ typedef enum state
|
|||
S_GREYSPRING3,
|
||||
S_GREYSPRING4,
|
||||
|
||||
// Orange Spring (Pogo)
|
||||
S_POGOSPRING1,
|
||||
S_POGOSPRING2,
|
||||
S_POGOSPRING2B,
|
||||
S_POGOSPRING3,
|
||||
S_POGOSPRING4,
|
||||
|
||||
// Yellow Diagonal Spring
|
||||
S_YDIAG1,
|
||||
S_YDIAG2,
|
||||
|
|
@ -5656,6 +5664,7 @@ typedef enum mobj_type
|
|||
MT_REDSPRING,
|
||||
MT_BLUESPRING,
|
||||
MT_GREYSPRING,
|
||||
MT_POGOSPRING,
|
||||
MT_YELLOWDIAG, // Yellow Diagonal Spring
|
||||
MT_REDDIAG, // Red Diagonal Spring
|
||||
MT_BLUEDIAG, // Blue Diagonal Spring
|
||||
|
|
|
|||
151
src/k_bot.c
151
src/k_bot.c
|
|
@ -489,7 +489,6 @@ fixed_t K_BotRubberband(player_t *player)
|
|||
fixed_t rubberband = FRACUNIT;
|
||||
fixed_t rubbermax, rubbermin;
|
||||
player_t *firstplace = NULL;
|
||||
line_t *botController = NULL;
|
||||
UINT8 i;
|
||||
|
||||
if (player->exiting)
|
||||
|
|
@ -498,14 +497,17 @@ fixed_t K_BotRubberband(player_t *player)
|
|||
return FRACUNIT;
|
||||
}
|
||||
|
||||
botController = K_FindBotController(player->mo);
|
||||
|
||||
if (botController != NULL)
|
||||
if (player->botvars.controller != UINT16_MAX)
|
||||
{
|
||||
// No Climb Flag: Disable rubberbanding
|
||||
if (botController->flags & ML_NOCLIMB)
|
||||
const line_t *botController = &lines[player->botvars.controller];
|
||||
|
||||
if (botController != NULL)
|
||||
{
|
||||
return FRACUNIT;
|
||||
// No Climb Flag: Disable rubberbanding
|
||||
if (botController->flags & ML_NOCLIMB)
|
||||
{
|
||||
return FRACUNIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -556,8 +558,8 @@ fixed_t K_BotRubberband(player_t *player)
|
|||
// Lv. 1: x0.75 min
|
||||
// Lv. 5: x0.875 min
|
||||
// Lv. 9: x1.0 min
|
||||
// Lv. MAX: x1.0 min
|
||||
rubbermin = FRACUNIT - (((FRACUNIT/4) * (DIFFICULTBOT - min(DIFFICULTBOT, player->botvars.difficulty))) / (DIFFICULTBOT - 1));
|
||||
// Lv. MAX: x1.125 min
|
||||
rubbermin = FRACUNIT - (((FRACUNIT/4) * (DIFFICULTBOT - player->botvars.difficulty)) / (DIFFICULTBOT - 1));
|
||||
|
||||
if (rubberband > rubbermax)
|
||||
{
|
||||
|
|
@ -572,94 +574,19 @@ fixed_t K_BotRubberband(player_t *player)
|
|||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
fixed_t K_BotTopSpeedRubberband(player_t *player)
|
||||
fixed_t K_UpdateRubberband(player_t *player)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
fixed_t K_BotTopSpeedRubberband(player_t *player)
|
||||
fixed_t K_UpdateRubberband(player_t *player)
|
||||
{
|
||||
fixed_t rubberband = K_BotRubberband(player);
|
||||
fixed_t dest = K_BotRubberband(player);
|
||||
fixed_t ret = player->botvars.rubberband;
|
||||
|
||||
if (rubberband <= FRACUNIT)
|
||||
{
|
||||
// Never go below your regular top speed
|
||||
rubberband = FRACUNIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Max at +20% for level 9 bots
|
||||
rubberband = FRACUNIT + ((rubberband - FRACUNIT) / 5);
|
||||
}
|
||||
// Ease into the new value.
|
||||
ret += (dest - player->botvars.rubberband) >> 3;
|
||||
|
||||
// Only allow you to go faster than your regular top speed if you're facing the right direction
|
||||
if (rubberband > FRACUNIT && player->mo != NULL && player->nextwaypoint != NULL)
|
||||
{
|
||||
const INT16 mindiff = 30;
|
||||
const INT16 maxdiff = 60;
|
||||
INT16 anglediff = 0;
|
||||
fixed_t amt = rubberband - FRACUNIT;
|
||||
angle_t destangle = R_PointToAngle2(
|
||||
player->mo->x, player->mo->y,
|
||||
player->nextwaypoint->mobj->x, player->nextwaypoint->mobj->y
|
||||
);
|
||||
angle_t angle = player->mo->angle - destangle;
|
||||
|
||||
if (angle < ANGLE_180)
|
||||
{
|
||||
anglediff = AngleFixed(angle) >> FRACBITS;
|
||||
}
|
||||
else
|
||||
{
|
||||
anglediff = 360 - (AngleFixed(angle) >> FRACBITS);
|
||||
}
|
||||
|
||||
anglediff = abs(anglediff);
|
||||
|
||||
if (anglediff >= maxdiff)
|
||||
{
|
||||
rubberband = FRACUNIT;
|
||||
}
|
||||
else if (anglediff > mindiff)
|
||||
{
|
||||
amt = (amt * (maxdiff - anglediff)) / mindiff;
|
||||
rubberband = FRACUNIT + amt;
|
||||
}
|
||||
}
|
||||
|
||||
return rubberband;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
fixed_t K_BotFrictionRubberband(player_t *player, fixed_t frict)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
fixed_t K_BotFrictionRubberband(player_t *player, fixed_t frict)
|
||||
{
|
||||
const fixed_t value = 20776;
|
||||
fixed_t rubberband = K_BotRubberband(player) - FRACUNIT;
|
||||
fixed_t newFrict = frict;
|
||||
|
||||
if (rubberband <= 0)
|
||||
{
|
||||
// Never get weaker than normal friction
|
||||
return frict;
|
||||
}
|
||||
|
||||
if (player->tiregrease > 0)
|
||||
{
|
||||
// Bots will lose all of their momentum without this.
|
||||
return frict;
|
||||
}
|
||||
|
||||
newFrict = frict - FixedMul(value, rubberband);
|
||||
|
||||
if (newFrict < 0)
|
||||
newFrict = 0;
|
||||
if (newFrict > FRACUNIT)
|
||||
newFrict = FRACUNIT;
|
||||
|
||||
return newFrict;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
@ -1148,7 +1075,7 @@ static INT32 K_HandleBotTrack(player_t *player, ticcmd_t *cmd, botprediction_t *
|
|||
|
||||
if (dirdist <= rad)
|
||||
{
|
||||
fixed_t speedmul = FixedDiv(K_BotSpeedScaled(player, player->speed), K_GetKartSpeed(player, false));
|
||||
fixed_t speedmul = FixedDiv(K_BotSpeedScaled(player, player->speed), K_GetKartSpeed(player, false, false));
|
||||
fixed_t speedrad = rad/4;
|
||||
|
||||
if (speedmul > FRACUNIT)
|
||||
|
|
@ -1343,13 +1270,9 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
// Remove any existing controls
|
||||
memset(cmd, 0, sizeof(ticcmd_t));
|
||||
|
||||
if (gamestate != GS_LEVEL
|
||||
|| player->mo->scale <= 1
|
||||
|| player->playerstate == PST_DEAD
|
||||
|| leveltime <= introtime
|
||||
|| !(gametyperules & GTR_BOTS))
|
||||
if (gamestate != GS_LEVEL)
|
||||
{
|
||||
// No need to do anything else.
|
||||
// Not in a level.
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1359,7 +1282,33 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
return;
|
||||
}
|
||||
|
||||
if (!(gametyperules & GTR_BOTS) // No bot behaviors
|
||||
|| K_GetNumWaypoints() == 0 // No waypoints
|
||||
|| leveltime <= introtime // During intro camera
|
||||
|| player->playerstate == PST_DEAD // Dead, respawning.
|
||||
|| player->mo->scale <= 1) // Post-finish "death" animation
|
||||
{
|
||||
// No need to do anything else.
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->exiting && player->nextwaypoint == K_GetFinishLineWaypoint() && ((mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE) == LF_SECTIONRACE))
|
||||
{
|
||||
// Sprint map finish, don't give Sal's children migraines trying to pathfind out
|
||||
return;
|
||||
}
|
||||
|
||||
botController = K_FindBotController(player->mo);
|
||||
if (botController == NULL)
|
||||
{
|
||||
player->botvars.controller = UINT16_MAX;
|
||||
}
|
||||
else
|
||||
{
|
||||
player->botvars.controller = botController - lines;
|
||||
}
|
||||
|
||||
player->botvars.rubberband = K_UpdateRubberband(player);
|
||||
|
||||
if (player->trickpanel != 0)
|
||||
{
|
||||
|
|
@ -1369,6 +1318,12 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd)
|
|||
return;
|
||||
}
|
||||
|
||||
if (botController != NULL && (botController->flags & ML_EFFECT2))
|
||||
{
|
||||
// Disable bot controls entirely.
|
||||
return;
|
||||
}
|
||||
|
||||
destangle = player->mo->angle;
|
||||
|
||||
if (botController != NULL && (botController->flags & ML_EFFECT1))
|
||||
|
|
|
|||
29
src/k_bot.h
29
src/k_bot.h
|
|
@ -88,36 +88,19 @@ fixed_t K_BotRubberband(player_t *player);
|
|||
|
||||
|
||||
/*--------------------------------------------------
|
||||
fixed_t K_BotTopSpeedRubberband(player_t *player);
|
||||
fixed_t K_UpdateRubberband(player_t *player);
|
||||
|
||||
Gives a multiplier for a bot's rubberbanding.
|
||||
Adjusted from K_BotRubberband to be used for top speed.
|
||||
Eases the current rubberbanding value to the
|
||||
new one, calculated by K_BotRubberband.
|
||||
|
||||
Input Arguments:-
|
||||
player - Player to check.
|
||||
player - Player to update.
|
||||
|
||||
Return:-
|
||||
A multiplier in fixed point scale.
|
||||
The new rubberband multiplier, in fixed point scale.
|
||||
--------------------------------------------------*/
|
||||
|
||||
fixed_t K_BotTopSpeedRubberband(player_t *player);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
fixed_t K_BotFrictionRubberband(player_t *player, fixed_t frict);
|
||||
|
||||
Gives a multiplier for a bot's rubberbanding.
|
||||
Adjusted from K_BotRubberband to be used for friction.
|
||||
|
||||
Input Arguments:-
|
||||
player - Player to check.
|
||||
frict - Friction value to adjust.
|
||||
|
||||
Return:-
|
||||
The new friction value.
|
||||
--------------------------------------------------*/
|
||||
|
||||
fixed_t K_BotFrictionRubberband(player_t *player, fixed_t frict);
|
||||
fixed_t K_UpdateRubberband(player_t *player);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -471,7 +471,7 @@ static void K_BotItemSneaker(player_t *player, ticcmd_t *cmd)
|
|||
{
|
||||
if ((player->offroad && K_ApplyOffroad(player)) // Stuck in offroad, use it NOW
|
||||
|| K_GetWaypointIsShortcut(player->nextwaypoint) == true // Going toward a shortcut!
|
||||
|| player->speed < K_GetKartSpeed(player, false)/2 // Being slowed down too much
|
||||
|| player->speed < K_GetKartSpeed(player, false, true) / 2 // Being slowed down too much
|
||||
|| player->speedboost > (FRACUNIT/8) // Have another type of boost (tethering)
|
||||
|| player->botvars.itemconfirm > 4*TICRATE) // Held onto it for too long
|
||||
{
|
||||
|
|
@ -830,7 +830,7 @@ static void K_BotItemEggmanExplosion(player_t *player, ticcmd_t *cmd)
|
|||
--------------------------------------------------*/
|
||||
static void K_BotItemOrbinaut(player_t *player, ticcmd_t *cmd)
|
||||
{
|
||||
const fixed_t topspeed = K_GetKartSpeed(player, false);
|
||||
const fixed_t topspeed = K_GetKartSpeed(player, false, true);
|
||||
fixed_t radius = FixedMul(2560 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed));
|
||||
SINT8 throwdir = -1;
|
||||
boolean tryLookback = false;
|
||||
|
|
@ -888,7 +888,7 @@ static void K_BotItemOrbinaut(player_t *player, ticcmd_t *cmd)
|
|||
--------------------------------------------------*/
|
||||
static void K_BotItemDropTarget(player_t *player, ticcmd_t *cmd)
|
||||
{
|
||||
const fixed_t topspeed = K_GetKartSpeed(player, false);
|
||||
const fixed_t topspeed = K_GetKartSpeed(player, false, true);
|
||||
fixed_t radius = FixedMul(1280 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed));
|
||||
SINT8 throwdir = -1;
|
||||
boolean tryLookback = false;
|
||||
|
|
@ -946,7 +946,7 @@ static void K_BotItemDropTarget(player_t *player, ticcmd_t *cmd)
|
|||
--------------------------------------------------*/
|
||||
static void K_BotItemJawz(player_t *player, ticcmd_t *cmd)
|
||||
{
|
||||
const fixed_t topspeed = K_GetKartSpeed(player, false);
|
||||
const fixed_t topspeed = K_GetKartSpeed(player, false, true);
|
||||
fixed_t radius = FixedMul(2560 * mapobjectscale, K_GetKartGameSpeedScalar(gamespeed));
|
||||
SINT8 throwdir = 1;
|
||||
boolean tryLookback = false;
|
||||
|
|
@ -1165,7 +1165,7 @@ static void K_BotItemRings(player_t *player, ticcmd_t *cmd)
|
|||
{
|
||||
INT32 saferingsval = 16 - K_GetKartRingPower(player, false);
|
||||
|
||||
if (player->speed < K_GetKartSpeed(player, false)/2 // Being slowed down too much
|
||||
if (player->speed < K_GetKartSpeed(player, false, true) / 2 // Being slowed down too much
|
||||
|| player->speedboost > (FRACUNIT/5)) // Have another type of boost (tethering)
|
||||
{
|
||||
saferingsval -= 5;
|
||||
|
|
|
|||
|
|
@ -675,6 +675,12 @@ static inline BlockItReturn_t PIT_LightningShieldAttack(mobj_t *thing)
|
|||
return BMIT_ABORT;
|
||||
}
|
||||
|
||||
if (thing == NULL || P_MobjWasRemoved(thing))
|
||||
{
|
||||
// Invalid?
|
||||
return BMIT_ABORT;
|
||||
}
|
||||
|
||||
if (thing == lightningSource)
|
||||
{
|
||||
// Don't explode yourself!!
|
||||
|
|
@ -856,6 +862,9 @@ boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2)
|
|||
|
||||
boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
const boolean flameT1 = (t1->player->flamedash > 0 && t1->player->itemtype == KITEM_FLAMESHIELD);
|
||||
const boolean flameT2 = (t2->player->flamedash > 0 && t2->player->itemtype == KITEM_FLAMESHIELD);
|
||||
|
||||
boolean t1Condition = false;
|
||||
boolean t2Condition = false;
|
||||
boolean stungT1 = false;
|
||||
|
|
@ -864,7 +873,12 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2)
|
|||
t1Condition = (t1->scale > t2->scale + (mapobjectscale/8)) || (t1->player->invincibilitytimer > 0);
|
||||
t2Condition = (t2->scale > t1->scale + (mapobjectscale/8)) || (t2->player->invincibilitytimer > 0);
|
||||
|
||||
if (t1Condition == true && t2Condition == false)
|
||||
if ((t1Condition == true || flameT1 == true) && (t2Condition == true || flameT2 == true))
|
||||
{
|
||||
K_DoPowerClash(t1->player, t2->player);
|
||||
return false;
|
||||
}
|
||||
else if (t1Condition == true && t2Condition == false)
|
||||
{
|
||||
P_DamageMobj(t2, t1, t1, 1, DMG_TUMBLE);
|
||||
return true;
|
||||
|
|
@ -873,14 +887,11 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2)
|
|||
{
|
||||
P_DamageMobj(t1, t2, t2, 1, DMG_TUMBLE);
|
||||
return true;
|
||||
} else if (t1Condition == true && t2Condition == true) {
|
||||
K_DoPowerClash(t1->player, t2->player);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Flame Shield dash damage
|
||||
t1Condition = (t1->player->flamedash > 0 && t1->player->itemtype == KITEM_FLAMESHIELD);
|
||||
t2Condition = (t2->player->flamedash > 0 && t2->player->itemtype == KITEM_FLAMESHIELD);
|
||||
t1Condition = flameT1;
|
||||
t2Condition = flameT2;
|
||||
|
||||
if (t1Condition == true && t2Condition == false)
|
||||
{
|
||||
|
|
|
|||
133
src/k_follower.c
133
src/k_follower.c
|
|
@ -129,7 +129,6 @@ void K_SetFollowerByNum(INT32 playernum, INT32 skinnum)
|
|||
K_SetFollowerByNum(playernum, -1); // Not found, then set -1 (nothing) as our follower.
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_SetFollowerState(mobj_t *f, statenum_t state)
|
||||
|
||||
|
|
@ -193,6 +192,35 @@ UINT16 K_GetEffectiveFollowerColor(UINT16 followercolor, UINT16 playercolor)
|
|||
return playercolor;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
static void K_UpdateFollowerState(mobj_t *f, statenum_t state, followerstate_t type)
|
||||
|
||||
Sets a follower object's state & current state type tracker.
|
||||
If the state tracker already matches, then this is ignored.
|
||||
|
||||
Input Arguments:-
|
||||
f - The follower's mobj_t.
|
||||
state - The state to set.
|
||||
type - State type tracker.
|
||||
|
||||
Return:-
|
||||
None
|
||||
--------------------------------------------------*/
|
||||
static void K_UpdateFollowerState(mobj_t *f, statenum_t state, followerstate_t type)
|
||||
{
|
||||
if (f == NULL || P_MobjWasRemoved(f) == true)
|
||||
{
|
||||
// safety net
|
||||
return;
|
||||
}
|
||||
|
||||
if (f->extravalue1 != (INT32)type)
|
||||
{
|
||||
K_SetFollowerState(f, state);
|
||||
f->extravalue1 = type;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
void K_HandleFollower(player_t *player)
|
||||
|
||||
|
|
@ -299,8 +327,9 @@ void K_HandleFollower(player_t *player)
|
|||
|
||||
// so let's spawn one!
|
||||
P_SetTarget(&player->follower, P_SpawnMobj(sx, sy, sz, MT_FOLLOWER));
|
||||
K_SetFollowerState(player->follower, fl.idlestate);
|
||||
P_SetTarget(&player->follower->target, player->mo); // we need that to know when we need to disappear
|
||||
K_UpdateFollowerState(player->follower, fl.idlestate, FOLLOWERSTATE_IDLE);
|
||||
|
||||
P_SetTarget(&player->follower->target, player->mo); // we need that to know when we need to disappear
|
||||
P_InitAngle(player->follower, player->mo->angle);
|
||||
|
||||
// This is safe to only spawn it here, the follower is removed then respawned when switched.
|
||||
|
|
@ -314,16 +343,6 @@ void K_HandleFollower(player_t *player)
|
|||
P_SetTarget(&player->follower->hnext->hnext, bmobj); // this seems absolutely stupid, I know, but this will make updating the momentums/flags of these a bit easier.
|
||||
P_SetTarget(&bmobj->target, player->follower); // Ditto
|
||||
}
|
||||
|
||||
player->follower->extravalue1 = 0; // extravalue1 is used to know what "state set" to use.
|
||||
/*
|
||||
0 = idle
|
||||
1 = forwards
|
||||
2 = hurt
|
||||
3 = win
|
||||
4 = lose
|
||||
5 = hitconfirm (< this one uses ->movecount as timer to know when to end, and goes back to normal states afterwards, unless hurt)
|
||||
*/
|
||||
}
|
||||
else // follower exists, woo!
|
||||
{
|
||||
|
|
@ -430,16 +449,32 @@ void K_HandleFollower(player_t *player)
|
|||
if (player->follower->z <= fh)
|
||||
{
|
||||
player->follower->z = fh;
|
||||
if (player->follower->momz < 0)
|
||||
|
||||
if (!(player->mo->eflags & MFE_VERTICALFLIP) && player->follower->momz <= 0 && fl.bobamp != 0)
|
||||
{
|
||||
// Ground bounce
|
||||
player->follower->momz = P_GetMobjZMovement(player->mo) + FixedMul(fl.bobamp, player->follower->scale);
|
||||
player->follower->extravalue1 = FOLLOWERSTATE_RESET;
|
||||
}
|
||||
else if (player->follower->momz < 0)
|
||||
{
|
||||
// Ceiling clip
|
||||
player->follower->momz = 0;
|
||||
}
|
||||
}
|
||||
else if (player->follower->z >= ch)
|
||||
{
|
||||
player->follower->z = ch;
|
||||
if (player->follower->momz > 0)
|
||||
|
||||
if ((player->mo->eflags & MFE_VERTICALFLIP) && player->follower->momz >= 0 && fl.bobamp != 0)
|
||||
{
|
||||
// Ground bounce
|
||||
player->follower->momz = P_GetMobjZMovement(player->mo) - FixedMul(fl.bobamp, player->follower->scale);
|
||||
player->follower->extravalue1 = FOLLOWERSTATE_RESET;
|
||||
}
|
||||
else if (player->follower->momz > 0)
|
||||
{
|
||||
// Ceiling clip
|
||||
player->follower->momz = 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -498,11 +533,7 @@ void K_HandleFollower(player_t *player)
|
|||
// spin out
|
||||
player->follower->angle = player->drawangle;
|
||||
|
||||
if (player->follower->extravalue1 != 2)
|
||||
{
|
||||
player->follower->extravalue1 = 2;
|
||||
K_SetFollowerState(player->follower, fl.hurtstate);
|
||||
}
|
||||
K_UpdateFollowerState(player->follower, fl.hurtstate, FOLLOWERSTATE_HURT);
|
||||
|
||||
if (player->mo->health <= 0)
|
||||
{
|
||||
|
|
@ -510,58 +541,32 @@ void K_HandleFollower(player_t *player)
|
|||
player->follower->momz = player->mo->momz;
|
||||
}
|
||||
}
|
||||
else if (player->exiting)
|
||||
{
|
||||
// win/ loss animations
|
||||
if (K_IsPlayerLosing(player))
|
||||
{
|
||||
// L
|
||||
K_UpdateFollowerState(player->follower, fl.losestate, FOLLOWERSTATE_LOSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
// W
|
||||
K_UpdateFollowerState(player->follower, fl.winstate, FOLLOWERSTATE_WIN);
|
||||
}
|
||||
}
|
||||
else if (player->follower->movecount)
|
||||
{
|
||||
if (player->follower->extravalue1 != 5)
|
||||
{
|
||||
player->follower->extravalue1 = 5;
|
||||
K_SetFollowerState(player->follower, fl.hitconfirmstate);
|
||||
}
|
||||
|
||||
K_UpdateFollowerState(player->follower, fl.hitconfirmstate, FOLLOWERSTATE_HITCONFIRM);
|
||||
player->follower->movecount--;
|
||||
}
|
||||
else if (player->speed > 10*player->mo->scale) // animation for moving fast enough
|
||||
else if (player->speed > 10*player->mo->scale) // animation for moving fast enough
|
||||
{
|
||||
if (player->follower->extravalue1 != 1)
|
||||
{
|
||||
player->follower->extravalue1 = 1;
|
||||
K_SetFollowerState(player->follower, fl.followstate);
|
||||
}
|
||||
K_UpdateFollowerState(player->follower, fl.followstate, FOLLOWERSTATE_FOLLOW);
|
||||
}
|
||||
else
|
||||
{
|
||||
// animations when nearly still. This includes winning and losing.
|
||||
if (player->follower->extravalue1 != 0)
|
||||
{
|
||||
if (player->exiting)
|
||||
{
|
||||
// win/ loss animations
|
||||
if (K_IsPlayerLosing(player))
|
||||
{
|
||||
// L
|
||||
if (player->follower->extravalue1 != 4)
|
||||
{
|
||||
player->follower->extravalue1 = 4;
|
||||
K_SetFollowerState(player->follower, fl.losestate);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// W
|
||||
if (player->follower->extravalue1 != 3)
|
||||
{
|
||||
player->follower->extravalue1 = 3;
|
||||
K_SetFollowerState(player->follower, fl.winstate);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// normal standstill
|
||||
player->follower->extravalue1 = 0;
|
||||
K_SetFollowerState(player->follower, fl.idlestate);
|
||||
}
|
||||
}
|
||||
K_UpdateFollowerState(player->follower, fl.idlestate, FOLLOWERSTATE_IDLE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,18 @@ typedef enum
|
|||
FOLLOWERMODE__MAX
|
||||
} followermode_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FOLLOWERSTATE_RESET, // Set to this to reset the state entirely.
|
||||
FOLLOWERSTATE_IDLE,
|
||||
FOLLOWERSTATE_FOLLOW,
|
||||
FOLLOWERSTATE_HURT,
|
||||
FOLLOWERSTATE_WIN,
|
||||
FOLLOWERSTATE_LOSE,
|
||||
FOLLOWERSTATE_HITCONFIRM, // Uses movecount as a timer for how long to play this state.
|
||||
FOLLOWERSTATE__MAX
|
||||
} followerstate_t;
|
||||
|
||||
//
|
||||
// We'll define these here because they're really just a mobj that'll follow some rules behind a player
|
||||
//
|
||||
|
|
|
|||
22
src/k_hud.c
22
src/k_hud.c
|
|
@ -1708,7 +1708,7 @@ static void K_DrawKartPositionNum(INT32 num)
|
|||
{
|
||||
localpatch = kp_winnernum[(leveltime % (NUMWINFRAMES*3)) / 3];
|
||||
}
|
||||
else if (stplyr->laps >= cv_numlaps.value || stplyr->exiting) // Check for the final lap, or won
|
||||
else if (stplyr->laps >= numlaps || stplyr->exiting) // Check for the final lap, or won
|
||||
{
|
||||
boolean useRedNums = K_IsPlayerLosing(stplyr);
|
||||
|
||||
|
|
@ -2339,7 +2339,7 @@ static void K_drawKartLapsAndRings(void)
|
|||
V_DrawScaledPatch(fx, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_splitlapflag);
|
||||
V_DrawScaledPatch(fx+22, fy, V_HUDTRANS|V_SLIDEIN|splitflags, frameslash);
|
||||
|
||||
if (cv_numlaps.value >= 10)
|
||||
if (numlaps >= 10)
|
||||
{
|
||||
UINT8 ln[2];
|
||||
ln[0] = ((stplyr->laps / 10) % 10);
|
||||
|
|
@ -2348,8 +2348,8 @@ static void K_drawKartLapsAndRings(void)
|
|||
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[0]]);
|
||||
V_DrawScaledPatch(fx+17, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[1]]);
|
||||
|
||||
ln[0] = ((abs(cv_numlaps.value) / 10) % 10);
|
||||
ln[1] = (abs(cv_numlaps.value) % 10);
|
||||
ln[0] = ((numlaps / 10) % 10);
|
||||
ln[1] = (numlaps % 10);
|
||||
|
||||
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[0]]);
|
||||
V_DrawScaledPatch(fx+31, fy, V_HUDTRANS|V_SLIDEIN|splitflags, fontv[PINGNUM_FONT].font[ln[1]]);
|
||||
|
|
@ -2357,7 +2357,7 @@ static void K_drawKartLapsAndRings(void)
|
|||
else
|
||||
{
|
||||
V_DrawScaledPatch(fx+13, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[(stplyr->laps) % 10]);
|
||||
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[(cv_numlaps.value) % 10]);
|
||||
V_DrawScaledPatch(fx+27, fy, V_HUDTRANS|V_SLIDEIN|splitflags, kp_facenum[(numlaps) % 10]);
|
||||
}
|
||||
|
||||
// Rings
|
||||
|
|
@ -2395,7 +2395,7 @@ static void K_drawKartLapsAndRings(void)
|
|||
{
|
||||
// Laps
|
||||
V_DrawScaledPatch(LAPS_X, LAPS_Y, V_HUDTRANS|V_SLIDEIN|splitflags, kp_lapsticker);
|
||||
V_DrawKartString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d", min(stplyr->laps, cv_numlaps.value), cv_numlaps.value));
|
||||
V_DrawKartString(LAPS_X+33, LAPS_Y+3, V_HUDTRANS|V_SLIDEIN|splitflags, va("%d/%d", min(stplyr->laps, numlaps), numlaps));
|
||||
|
||||
// Rings
|
||||
if (!uselives)
|
||||
|
|
@ -2507,19 +2507,19 @@ static void K_drawKartSpeedometer(void)
|
|||
{
|
||||
case 1: // Sonic Drift 2 style percentage
|
||||
default:
|
||||
convSpeed = (stplyr->speed * 100) / K_GetKartSpeed(stplyr, false); // Based on top speed!
|
||||
convSpeed = (stplyr->speed * 100) / K_GetKartSpeed(stplyr, false, true); // Based on top speed!
|
||||
labeln = 0;
|
||||
break;
|
||||
case 2: // Kilometers
|
||||
convSpeed = FixedDiv(FixedMul(stplyr->speed, 142371), mapobjectscale)/FRACUNIT; // 2.172409058
|
||||
convSpeed = FixedDiv(FixedMul(stplyr->speed, 142371), mapobjectscale) / FRACUNIT; // 2.172409058
|
||||
labeln = 1;
|
||||
break;
|
||||
case 3: // Miles
|
||||
convSpeed = FixedDiv(FixedMul(stplyr->speed, 88465), mapobjectscale)/FRACUNIT; // 1.349868774
|
||||
convSpeed = FixedDiv(FixedMul(stplyr->speed, 88465), mapobjectscale) / FRACUNIT; // 1.349868774
|
||||
labeln = 2;
|
||||
break;
|
||||
case 4: // Fracunits
|
||||
convSpeed = FixedDiv(stplyr->speed, mapobjectscale)/FRACUNIT; // 1.0. duh.
|
||||
convSpeed = FixedDiv(stplyr->speed, mapobjectscale) / FRACUNIT; // 1.0. duh.
|
||||
labeln = 3;
|
||||
break;
|
||||
}
|
||||
|
|
@ -4369,7 +4369,7 @@ static void K_drawLapStartAnim(void)
|
|||
kp_lapanim_hand[stplyr->karthud[khud_laphand]-1], NULL);
|
||||
}
|
||||
|
||||
if (stplyr->laps == (UINT8)(cv_numlaps.value))
|
||||
if (stplyr->laps == (UINT8)(numlaps))
|
||||
{
|
||||
newval = (62 - (32 * max(0, progress - 76))) * FRACUNIT;
|
||||
oldval = (62 - (32 * max(0, progressOld - 76))) * FRACUNIT;
|
||||
|
|
|
|||
437
src/k_kart.c
437
src/k_kart.c
|
|
@ -357,15 +357,15 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS-1][8] =
|
|||
/*Invincibility*/ { 0, 0, 0, 0, 3, 4, 6, 9 }, // Invincibility
|
||||
/*Banana*/ { 2, 3, 1, 0, 0, 0, 0, 0 }, // Banana
|
||||
/*Eggman Monitor*/ { 1, 2, 0, 0, 0, 0, 0, 0 }, // Eggman Monitor
|
||||
/*Orbinaut*/ { 5, 4, 2, 2, 0, 0, 0, 0 }, // Orbinaut
|
||||
/*Jawz*/ { 0, 3, 2, 1, 1, 0, 0, 0 }, // Jawz
|
||||
/*Mine*/ { 0, 2, 3, 1, 0, 0, 0, 0 }, // Mine
|
||||
/*Orbinaut*/ { 5, 5, 2, 2, 0, 0, 0, 0 }, // Orbinaut
|
||||
/*Jawz*/ { 0, 4, 2, 1, 0, 0, 0, 0 }, // Jawz
|
||||
/*Mine*/ { 0, 3, 3, 1, 0, 0, 0, 0 }, // Mine
|
||||
/*Land Mine*/ { 3, 0, 0, 0, 0, 0, 0, 0 }, // Land Mine
|
||||
/*Ballhog*/ { 0, 0, 2, 2, 0, 0, 0, 0 }, // Ballhog
|
||||
/*Self-Propelled Bomb*/ { 0, 0, 0, 0, 0, 2, 4, 0 }, // Self-Propelled Bomb
|
||||
/*Grow*/ { 0, 0, 0, 1, 2, 3, 0, 0 }, // Grow
|
||||
/*Shrink*/ { 0, 0, 0, 0, 0, 0, 2, 0 }, // Shrink
|
||||
/*Lightning Shield*/ { 1, 2, 0, 0, 0, 0, 0, 0 }, // Lightning Shield
|
||||
/*Lightning Shield*/ { 1, 0, 0, 0, 0, 0, 0, 0 }, // Lightning Shield
|
||||
/*Bubble Shield*/ { 0, 1, 2, 1, 0, 0, 0, 0 }, // Bubble Shield
|
||||
/*Flame Shield*/ { 0, 0, 0, 0, 0, 1, 3, 5 }, // Flame Shield
|
||||
/*Hyudoro*/ { 3, 0, 0, 0, 0, 0, 0, 0 }, // Hyudoro
|
||||
|
|
@ -373,13 +373,13 @@ static INT32 K_KartItemOddsRace[NUMKARTRESULTS-1][8] =
|
|||
/*Super Ring*/ { 2, 1, 1, 0, 0, 0, 0, 0 }, // Super Ring
|
||||
/*Kitchen Sink*/ { 0, 0, 0, 0, 0, 0, 0, 0 }, // Kitchen Sink
|
||||
/*Drop Target*/ { 3, 0, 0, 0, 0, 0, 0, 0 }, // Drop Target
|
||||
/*Sneaker x2*/ { 0, 0, 2, 2, 1, 0, 0, 0 }, // Sneaker x2
|
||||
/*Sneaker x3*/ { 0, 0, 0, 2, 6,10, 5, 0 }, // Sneaker x3
|
||||
/*Sneaker x2*/ { 0, 0, 2, 2, 2, 0, 0, 0 }, // Sneaker x2
|
||||
/*Sneaker x3*/ { 0, 0, 0, 1, 6,10, 5, 0 }, // Sneaker x3
|
||||
/*Banana x3*/ { 0, 1, 1, 0, 0, 0, 0, 0 }, // Banana x3
|
||||
/*Banana x10*/ { 0, 0, 0, 1, 0, 0, 0, 0 }, // Banana x10
|
||||
/*Orbinaut x3*/ { 0, 0, 1, 0, 0, 0, 0, 0 }, // Orbinaut x3
|
||||
/*Orbinaut x4*/ { 0, 0, 0, 1, 1, 0, 0, 0 }, // Orbinaut x4
|
||||
/*Jawz x2*/ { 0, 0, 1, 2, 0, 0, 0, 0 } // Jawz x2
|
||||
/*Orbinaut x4*/ { 0, 0, 0, 2, 0, 0, 0, 0 }, // Orbinaut x4
|
||||
/*Jawz x2*/ { 0, 0, 1, 2, 1, 0, 0, 0 } // Jawz x2
|
||||
};
|
||||
|
||||
static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][2] =
|
||||
|
|
@ -387,32 +387,32 @@ static INT32 K_KartItemOddsBattle[NUMKARTRESULTS][2] =
|
|||
//P-Odds 0 1
|
||||
/*Sneaker*/ { 2, 1 }, // Sneaker
|
||||
/*Rocket Sneaker*/ { 0, 0 }, // Rocket Sneaker
|
||||
/*Invincibility*/ { 2, 1 }, // Invincibility
|
||||
/*Banana*/ { 1, 0 }, // Banana
|
||||
/*Invincibility*/ { 4, 1 }, // Invincibility
|
||||
/*Banana*/ { 0, 0 }, // Banana
|
||||
/*Eggman Monitor*/ { 1, 0 }, // Eggman Monitor
|
||||
/*Orbinaut*/ { 8, 0 }, // Orbinaut
|
||||
/*Jawz*/ { 8, 1 }, // Jawz
|
||||
/*Mine*/ { 6, 1 }, // Mine
|
||||
/*Land Mine*/ { 0, 0 }, // Land Mine
|
||||
/*Land Mine*/ { 2, 0 }, // Land Mine
|
||||
/*Ballhog*/ { 2, 1 }, // Ballhog
|
||||
/*Self-Propelled Bomb*/ { 0, 0 }, // Self-Propelled Bomb
|
||||
/*Grow*/ { 2, 1 }, // Grow
|
||||
/*Shrink*/ { 0, 0 }, // Shrink
|
||||
/*Lightning Shield*/ { 4, 0 }, // Lightning Shield
|
||||
/*Bubble Shield*/ { 1, 0 }, // Bubble Shield
|
||||
/*Flame Shield*/ { 0, 0 }, // Flame Shield
|
||||
/*Flame Shield*/ { 1, 0 }, // Flame Shield
|
||||
/*Hyudoro*/ { 2, 0 }, // Hyudoro
|
||||
/*Pogo Spring*/ { 2, 0 }, // Pogo Spring
|
||||
/*Pogo Spring*/ { 3, 0 }, // Pogo Spring
|
||||
/*Super Ring*/ { 0, 0 }, // Super Ring
|
||||
/*Kitchen Sink*/ { 0, 0 }, // Kitchen Sink
|
||||
/*Drop Target*/ { 0, 0 }, // Drop Target
|
||||
/*Drop Target*/ { 2, 0 }, // Drop Target
|
||||
/*Sneaker x2*/ { 0, 0 }, // Sneaker x2
|
||||
/*Sneaker x3*/ { 1, 1 }, // Sneaker x3
|
||||
/*Banana x3*/ { 1, 0 }, // Banana x3
|
||||
/*Sneaker x3*/ { 0, 1 }, // Sneaker x3
|
||||
/*Banana x3*/ { 0, 0 }, // Banana x3
|
||||
/*Banana x10*/ { 1, 1 }, // Banana x10
|
||||
/*Orbinaut x3*/ { 2, 0 }, // Orbinaut x3
|
||||
/*Orbinaut x4*/ { 1, 1 }, // Orbinaut x4
|
||||
/*Jawz x2*/ { 2, 1 } // Jawz x2
|
||||
/*Jawz x2*/ { 5, 1 } // Jawz x2
|
||||
};
|
||||
|
||||
#define DISTVAR (2048) // Magic number distance for use with item roulette tiers
|
||||
|
|
@ -1176,9 +1176,15 @@ static fixed_t K_PlayerWeight(mobj_t *mobj, mobj_t *against)
|
|||
}
|
||||
else
|
||||
{
|
||||
// Applies rubberbanding, to prevent rubberbanding bots
|
||||
// from causing super crazy bumps.
|
||||
fixed_t spd = K_GetKartSpeed(mobj->player, false, true);
|
||||
|
||||
weight = (mobj->player->kartweight) * FRACUNIT;
|
||||
if (mobj->player->speed > K_GetKartSpeed(mobj->player, false))
|
||||
weight += (mobj->player->speed - K_GetKartSpeed(mobj->player, false))/8;
|
||||
|
||||
if (mobj->player->speed > spd)
|
||||
weight += (mobj->player->speed - spd) / 8;
|
||||
|
||||
if (mobj->player->itemtype == KITEM_BUBBLESHIELD)
|
||||
weight += 9*FRACUNIT;
|
||||
}
|
||||
|
|
@ -1694,9 +1700,13 @@ static void K_DrawDraftCombiring(player_t *player, player_t *victim, fixed_t cur
|
|||
UINT8 c;
|
||||
|
||||
if (maxdist == 0)
|
||||
c = 0;
|
||||
{
|
||||
c = leveltime % CHAOTIXBANDCOLORS;
|
||||
}
|
||||
else
|
||||
{
|
||||
c = FixedMul(CHAOTIXBANDCOLORS<<FRACBITS, FixedDiv(curdist-minimumdist, maxdist-minimumdist)) >> FRACBITS;
|
||||
}
|
||||
|
||||
stepx = (victim->mo->x - player->mo->x) / CHAOTIXBANDLEN;
|
||||
stepy = (victim->mo->y - player->mo->y) / CHAOTIXBANDLEN;
|
||||
|
|
@ -1715,8 +1725,16 @@ static void K_DrawDraftCombiring(player_t *player, player_t *victim, fixed_t cur
|
|||
curz + (P_RandomRange(24,48)*mapobjectscale),
|
||||
MT_SIGNSPARKLE);
|
||||
|
||||
P_SetMobjState(band, S_SIGNSPARK1 + (leveltime % 11));
|
||||
P_SetScale(band, (band->destscale = (3*player->mo->scale)/2));
|
||||
if (maxdist == 0)
|
||||
{
|
||||
P_SetMobjState(band, S_KSPARK1 + (leveltime % 8));
|
||||
P_SetScale(band, (band->destscale = player->mo->scale));
|
||||
}
|
||||
else
|
||||
{
|
||||
P_SetMobjState(band, S_SIGNSPARK1 + (leveltime % 11));
|
||||
P_SetScale(band, (band->destscale = (3*player->mo->scale)/2));
|
||||
}
|
||||
|
||||
band->color = colors[c];
|
||||
band->colorized = true;
|
||||
|
|
@ -1747,7 +1765,7 @@ static void K_DrawDraftCombiring(player_t *player, player_t *victim, fixed_t cur
|
|||
*/
|
||||
static void K_UpdateDraft(player_t *player)
|
||||
{
|
||||
fixed_t topspd = K_GetKartSpeed(player, false);
|
||||
fixed_t topspd = K_GetKartSpeed(player, false, false);
|
||||
fixed_t draftdistance;
|
||||
fixed_t minDist;
|
||||
UINT8 leniency;
|
||||
|
|
@ -1769,17 +1787,20 @@ static void K_UpdateDraft(player_t *player)
|
|||
draftdistance = FixedMul(draftdistance, K_GetKartGameSpeedScalar(gamespeed));
|
||||
}
|
||||
|
||||
// On the contrary, the leniency period biases toward high weight.
|
||||
// (See also: the leniency variable in K_SpawnDraftDust)
|
||||
leniency = (3*TICRATE)/4 + ((player->kartweight-1) * (TICRATE/4));
|
||||
|
||||
minDist = 640 * player->mo->scale;
|
||||
|
||||
if (gametype == GT_BATTLE)
|
||||
{
|
||||
// TODO: gametyperules
|
||||
minDist /= 4;
|
||||
draftdistance *= 2;
|
||||
leniency *= 4;
|
||||
}
|
||||
|
||||
// On the contrary, the leniency period biases toward high weight.
|
||||
// (See also: the leniency variable in K_SpawnDraftDust)
|
||||
leniency = (3*TICRATE)/4 + ((player->kartweight-1) * (TICRATE/4));
|
||||
|
||||
// Not enough speed to draft.
|
||||
if (player->speed >= 20*player->mo->scale)
|
||||
{
|
||||
|
|
@ -1850,7 +1871,23 @@ static void K_UpdateDraft(player_t *player)
|
|||
// Draft power is used later in K_GetKartBoostPower, ranging from 0 for normal speed and FRACUNIT for max draft speed.
|
||||
// How much this increments every tic biases toward acceleration! (min speed gets 1.5% per tic, max speed gets 0.5% per tic)
|
||||
if (player->draftpower < FRACUNIT)
|
||||
player->draftpower += (FRACUNIT/200) + ((9 - player->kartspeed) * ((3*FRACUNIT)/1600));
|
||||
{
|
||||
fixed_t add = (FRACUNIT/200) + ((9 - player->kartspeed) * ((3*FRACUNIT)/1600));;
|
||||
player->draftpower += add;
|
||||
|
||||
if (player->bot && player->botvars.rival)
|
||||
{
|
||||
// Double speed for the rival!
|
||||
player->draftpower += add;
|
||||
}
|
||||
|
||||
if (gametype == GT_BATTLE)
|
||||
{
|
||||
// TODO: gametyperules
|
||||
// Double speed in Battle
|
||||
player->draftpower += add;
|
||||
}
|
||||
}
|
||||
|
||||
if (player->draftpower > FRACUNIT)
|
||||
player->draftpower = FRACUNIT;
|
||||
|
|
@ -1867,9 +1904,14 @@ static void K_UpdateDraft(player_t *player)
|
|||
}
|
||||
|
||||
// No one to draft off of? Then you can knock that off.
|
||||
if (player->draftleeway) // Prevent small disruptions from stopping your draft.
|
||||
if (player->draftleeway > 0) // Prevent small disruptions from stopping your draft.
|
||||
{
|
||||
player->draftleeway--;
|
||||
if (P_IsObjectOnGround(player->mo) == true)
|
||||
{
|
||||
// Allow maintaining tether in air setpieces.
|
||||
player->draftleeway--;
|
||||
}
|
||||
|
||||
if (player->lastdraft >= 0
|
||||
&& player->lastdraft < MAXPLAYERS
|
||||
&& playeringame[player->lastdraft]
|
||||
|
|
@ -2026,7 +2068,7 @@ void K_SpawnDashDustRelease(player_t *player)
|
|||
static fixed_t K_GetBrakeFXScale(player_t *player, fixed_t maxScale)
|
||||
{
|
||||
fixed_t s = FixedDiv(player->speed,
|
||||
K_GetKartSpeed(player, false));
|
||||
K_GetKartSpeed(player, false, false));
|
||||
|
||||
s = max(s, FRACUNIT);
|
||||
s = min(s, maxScale);
|
||||
|
|
@ -2359,7 +2401,7 @@ void K_KartMoveAnimation(player_t *player)
|
|||
{
|
||||
const INT16 minturn = KART_FULLTURN/8;
|
||||
|
||||
const fixed_t fastspeed = (K_GetKartSpeed(player, false) * 17) / 20; // 85%
|
||||
const fixed_t fastspeed = (K_GetKartSpeed(player, false, true) * 17) / 20; // 85%
|
||||
const fixed_t speedthreshold = player->mo->scale / 8;
|
||||
|
||||
const boolean onground = P_IsObjectOnGround(player->mo);
|
||||
|
|
@ -2910,7 +2952,7 @@ boolean K_TripwirePassConditions(player_t *player)
|
|||
player->growshrinktimer > 0 ||
|
||||
player->flamedash ||
|
||||
player->hyudorotimer ||
|
||||
player->speed > 2 * K_GetKartSpeed(player, false)
|
||||
player->speed > 2 * K_GetKartSpeed(player, false, true)
|
||||
)
|
||||
return true;
|
||||
return false;
|
||||
|
|
@ -2928,7 +2970,7 @@ boolean K_WaterRun(player_t *player)
|
|||
player->sneakertimer ||
|
||||
player->tiregrease ||
|
||||
player->flamedash ||
|
||||
player->speed > 2 * K_GetKartSpeed(player, false)
|
||||
player->speed > 2 * K_GetKartSpeed(player, false, true)
|
||||
)
|
||||
return true;
|
||||
return false;
|
||||
|
|
@ -2950,11 +2992,13 @@ INT16 K_GetSpindashChargeTime(player_t *player)
|
|||
fixed_t K_GetSpindashChargeSpeed(player_t *player)
|
||||
{
|
||||
// more speed for higher weight & speed
|
||||
// Tails = +6.25%, Fang = +20.31%, Mighty = +20.31%, Metal = +25%
|
||||
// Tails = +18.75%, Fang = +46.88%, Mighty = +46.88%, Metal = +56.25%
|
||||
// (can be higher than this value when overcharged)
|
||||
return (player->kartspeed + player->kartweight) * (FRACUNIT/32);
|
||||
}
|
||||
const fixed_t val = ((player->kartspeed + player->kartweight) + 2) * (FRACUNIT/32);
|
||||
|
||||
// TODO: gametyperules
|
||||
return (gametype == GT_BATTLE) ? (4 * val) : val;
|
||||
}
|
||||
|
||||
// sets boostpower, speedboost, accelboost, and handleboost to whatever we need it to be
|
||||
static void K_GetKartBoostPower(player_t *player)
|
||||
|
|
@ -3040,19 +3084,27 @@ static void K_GetKartBoostPower(player_t *player)
|
|||
|
||||
if (player->startboost) // Startup Boost
|
||||
{
|
||||
ADDBOOST(FRACUNIT/2, 4*FRACUNIT, 0); // + 50% top speed, + 400% acceleration, +0% handling
|
||||
ADDBOOST(FRACUNIT, 4*FRACUNIT, sliptidehandling/2); // + 100% top speed, + 400% acceleration, +25% handling
|
||||
}
|
||||
|
||||
if (player->driftboost) // Drift Boost
|
||||
{
|
||||
if (player->strongdriftboost) // Purple/Rainbow drift boost
|
||||
// Rebuff Eggman's stat block corner
|
||||
const INT32 heavyAccel = ((9 - player->kartspeed) * 2) + (player->kartweight - 1);
|
||||
const fixed_t heavyAccelBonus = FRACUNIT + ((heavyAccel * maxmetabolismincrease * 2) / 24);
|
||||
|
||||
fixed_t driftSpeed = FRACUNIT/4; // 25% base
|
||||
|
||||
if (player->strongdriftboost > 0)
|
||||
{
|
||||
ADDBOOST(FRACUNIT/3, 4*FRACUNIT, 0); // + 33% top speed, + 400% acceleration, +0% handling
|
||||
}
|
||||
else
|
||||
{
|
||||
ADDBOOST(FRACUNIT/4, 4*FRACUNIT, 0); // + 25% top speed, + 400% acceleration, +0% handling
|
||||
// Purple/Rainbow drift boost
|
||||
driftSpeed = FixedMul(driftSpeed, 4*FRACUNIT/3); // 25% -> 33%
|
||||
}
|
||||
|
||||
// Bottom-left bonus
|
||||
driftSpeed = FixedMul(driftSpeed, heavyAccelBonus);
|
||||
|
||||
ADDBOOST(driftSpeed, 4*FRACUNIT, 0); // + variable top speed, + 400% acceleration, +0% handling
|
||||
}
|
||||
|
||||
if (player->trickboost) // Trick pannel up-boost
|
||||
|
|
@ -3081,6 +3133,12 @@ static void K_GetKartBoostPower(player_t *player)
|
|||
draftspeed *= 2;
|
||||
}
|
||||
|
||||
if (player->itemtype == KITEM_LIGHTNINGSHIELD)
|
||||
{
|
||||
// infinite tether
|
||||
draftspeed *= 2;
|
||||
}
|
||||
|
||||
speedboost += FixedMul(draftspeed, player->draftpower); // (Drafting suffers no boost stack penalty.)
|
||||
numboosts++;
|
||||
}
|
||||
|
|
@ -3139,14 +3197,17 @@ fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed)
|
|||
return finalspeed;
|
||||
}
|
||||
|
||||
fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower)
|
||||
fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower, boolean dorubberband)
|
||||
{
|
||||
const boolean mobjValid = (player->mo != NULL && P_MobjWasRemoved(player->mo) == false);
|
||||
fixed_t finalspeed = K_GetKartSpeedFromStat(player->kartspeed);
|
||||
|
||||
if (gametyperules & GTR_BUMPERS && player->bumpers <= 0)
|
||||
finalspeed = 3 * finalspeed / 2;
|
||||
|
||||
if (player->spheres > 0)
|
||||
{
|
||||
fixed_t sphereAdd = (FRACUNIT/80); // 50% at max
|
||||
fixed_t sphereAdd = (FRACUNIT/40); // 100% at max
|
||||
finalspeed = FixedMul(finalspeed, FRACUNIT + (sphereAdd * player->spheres));
|
||||
}
|
||||
|
||||
|
|
@ -3156,7 +3217,7 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower)
|
|||
fixed_t add = (player->botvars.difficulty * (FRACUNIT/10)) / DIFFICULTBOT;
|
||||
finalspeed = FixedMul(finalspeed, FRACUNIT + add);
|
||||
|
||||
if (player->botvars.rival == true)
|
||||
if (player->bot && player->botvars.rival)
|
||||
{
|
||||
// +10% top speed for the rival
|
||||
finalspeed = FixedMul(finalspeed, 11*FRACUNIT/10);
|
||||
|
|
@ -3173,14 +3234,14 @@ fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower)
|
|||
finalspeed = FixedMul(finalspeed, K_GrowShrinkSpeedMul(player));
|
||||
}
|
||||
|
||||
if (K_PlayerUsesBotMovement(player))
|
||||
{
|
||||
finalspeed = FixedMul(finalspeed, K_BotTopSpeedRubberband(player));
|
||||
}
|
||||
|
||||
finalspeed = FixedMul(finalspeed, player->boostpower + player->speedboost);
|
||||
}
|
||||
|
||||
if (dorubberband == true && K_PlayerUsesBotMovement(player) == true)
|
||||
{
|
||||
finalspeed = FixedMul(finalspeed, player->botvars.rubberband);
|
||||
}
|
||||
|
||||
return finalspeed;
|
||||
}
|
||||
|
||||
|
|
@ -3190,11 +3251,9 @@ fixed_t K_GetKartAccel(player_t *player)
|
|||
|
||||
k_accel += 17 * (9 - player->kartspeed); // 121 - 257
|
||||
|
||||
if (player->spheres > 0)
|
||||
{
|
||||
fixed_t sphereAdd = (FRACUNIT/10); // 500% at max
|
||||
k_accel = FixedMul(k_accel, FRACUNIT + (sphereAdd * player->spheres));
|
||||
}
|
||||
// karma bomb gets 2x acceleration
|
||||
if (gametype == GT_BATTLE && player->bumpers <= 0)
|
||||
k_accel *= 2;
|
||||
|
||||
return FixedMul(k_accel, (FRACUNIT + player->accelboost) / 4);
|
||||
}
|
||||
|
|
@ -3291,22 +3350,23 @@ SINT8 K_GetForwardMove(player_t *player)
|
|||
fixed_t K_GetNewSpeed(player_t *player)
|
||||
{
|
||||
const fixed_t accelmax = 4000;
|
||||
const fixed_t p_speed = K_GetKartSpeed(player, true);
|
||||
const fixed_t p_accel = K_GetKartAccel(player);
|
||||
const fixed_t p_speed = K_GetKartSpeed(player, true, true);
|
||||
fixed_t p_accel = K_GetKartAccel(player);
|
||||
|
||||
fixed_t newspeed, oldspeed, finalspeed;
|
||||
fixed_t orig = ORIG_FRICTION;
|
||||
|
||||
if (K_PlayerUsesBotMovement(player))
|
||||
if (K_PlayerUsesBotMovement(player) == true && player->botvars.rubberband > 0)
|
||||
{
|
||||
orig = K_BotFrictionRubberband(player, ORIG_FRICTION);
|
||||
// Acceleration is tied to top speed...
|
||||
// so if we want JUST a top speed boost, we have to do this...
|
||||
p_accel = FixedDiv(p_accel, player->botvars.rubberband);
|
||||
}
|
||||
|
||||
oldspeed = R_PointToDist2(0, 0, player->rmomx, player->rmomy); // FixedMul(P_AproxDistance(player->rmomx, player->rmomy), player->mo->scale);
|
||||
oldspeed = R_PointToDist2(0, 0, player->rmomx, player->rmomy);
|
||||
// Don't calculate the acceleration as ever being above top speed
|
||||
if (oldspeed > p_speed)
|
||||
oldspeed = p_speed;
|
||||
newspeed = FixedDiv(FixedDiv(FixedMul(oldspeed, accelmax - p_accel) + FixedMul(p_speed, p_accel), accelmax), orig);
|
||||
newspeed = FixedDiv(FixedDiv(FixedMul(oldspeed, accelmax - p_accel) + FixedMul(p_speed, p_accel), accelmax), ORIG_FRICTION);
|
||||
|
||||
finalspeed = newspeed - oldspeed;
|
||||
|
||||
|
|
@ -3419,6 +3479,27 @@ void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics, boolean fromDam
|
|||
K_AddHitLag(mo2, finalTics, false); // mo2 is the inflictor, so don't use the damage property.
|
||||
}
|
||||
|
||||
void K_AwardPlayerRings(player_t *player, INT32 rings, boolean overload)
|
||||
{
|
||||
UINT16 superring;
|
||||
|
||||
if (!overload)
|
||||
{
|
||||
INT32 totalrings =
|
||||
RINGTOTAL(player) + (player->superring / 3);
|
||||
|
||||
/* capped at 20 rings */
|
||||
if ((totalrings + rings) > 20)
|
||||
rings = (20 - totalrings);
|
||||
}
|
||||
|
||||
superring = player->superring + (rings * 3);
|
||||
|
||||
/* check if not overflow */
|
||||
if (superring > player->superring)
|
||||
player->superring = superring;
|
||||
}
|
||||
|
||||
void K_DoInstashield(player_t *player)
|
||||
{
|
||||
mobj_t *layera;
|
||||
|
|
@ -3524,8 +3605,11 @@ void K_SpinPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 typ
|
|||
if (( player->spinouttype & KSPIN_THRUST ))
|
||||
{
|
||||
// At spinout, player speed is increased to 1/4 their regular speed, moving them forward
|
||||
if (player->speed < K_GetKartSpeed(player, true)/4)
|
||||
P_InstaThrust(player->mo, player->mo->angle, FixedMul(K_GetKartSpeed(player, true)/4, player->mo->scale));
|
||||
fixed_t spd = K_GetKartSpeed(player, true, true) / 4;
|
||||
|
||||
if (player->speed < spd)
|
||||
P_InstaThrust(player->mo, player->mo->angle, FixedMul(spd, player->mo->scale));
|
||||
|
||||
S_StartSound(player->mo, sfx_slip);
|
||||
}
|
||||
|
||||
|
|
@ -3558,9 +3642,25 @@ static void K_RemoveGrowShrink(player_t *player)
|
|||
P_RestoreMusic(player);
|
||||
}
|
||||
|
||||
static fixed_t K_TumbleZ(mobj_t *mo, fixed_t input)
|
||||
{
|
||||
// Scales base tumble gravity to FRACUNIT
|
||||
const fixed_t baseGravity = FixedMul(DEFAULT_GRAVITY, TUMBLEGRAVITY);
|
||||
|
||||
// Adapt momz w/ gravity
|
||||
fixed_t gravityAdjust = FixedDiv(P_GetMobjGravity(mo), baseGravity);
|
||||
|
||||
if (mo->eflags & MFE_UNDERWATER)
|
||||
{
|
||||
// Reverse doubled falling speed.
|
||||
gravityAdjust /= 2;
|
||||
}
|
||||
|
||||
return FixedMul(input, -gravityAdjust);
|
||||
}
|
||||
|
||||
void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source)
|
||||
{
|
||||
fixed_t gravityadjust;
|
||||
(void)source;
|
||||
|
||||
K_DirectorFollowAttack(player, inflictor, source);
|
||||
|
|
@ -3589,16 +3689,7 @@ void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source)
|
|||
|
||||
S_StartSound(player->mo, sfx_s3k9b);
|
||||
|
||||
// adapt momz w/ gravity?
|
||||
// as far as kart goes normal gravity is 2 (FRACUNIT*2)
|
||||
|
||||
gravityadjust = P_GetMobjGravity(player->mo)/2; // so we'll halve it for our calculations.
|
||||
|
||||
if (player->mo->eflags & MFE_UNDERWATER)
|
||||
gravityadjust /= 2; // halve "gravity" underwater
|
||||
|
||||
// and then modulate momz like that...
|
||||
player->mo->momz = -gravityadjust * player->tumbleHeight;
|
||||
player->mo->momz = K_TumbleZ(player->mo, player->tumbleHeight * FRACUNIT);
|
||||
|
||||
P_SetPlayerMobjState(player->mo, S_KART_SPINOUT);
|
||||
|
||||
|
|
@ -3613,8 +3704,6 @@ static boolean K_LastTumbleBounceCondition(player_t *player)
|
|||
|
||||
static void K_HandleTumbleBounce(player_t *player)
|
||||
{
|
||||
fixed_t gravityadjust;
|
||||
|
||||
player->tumbleBounces++;
|
||||
player->tumbleHeight = (player->tumbleHeight * ((player->tumbleHeight > 100) ? 3 : 4)) / 5;
|
||||
player->pflags &= ~PF_TUMBLESOUND;
|
||||
|
|
@ -3647,7 +3736,7 @@ static void K_HandleTumbleBounce(player_t *player)
|
|||
|
||||
// A bit of damage hitlag.
|
||||
// This gives a window for DI!!
|
||||
K_AddHitLag(player->mo, 6, true);
|
||||
K_AddHitLag(player->mo, 3, true);
|
||||
|
||||
if (P_IsDisplayPlayer(player) && player->tumbleHeight >= 40)
|
||||
P_StartQuake((player->tumbleHeight*3/2)<<FRACBITS, 6); // funny earthquakes for the FEEL
|
||||
|
|
@ -3657,16 +3746,8 @@ static void K_HandleTumbleBounce(player_t *player)
|
|||
player->mo->momx = player->mo->momx / 2;
|
||||
player->mo->momy = player->mo->momy / 2;
|
||||
|
||||
// adapt momz w/ gravity?
|
||||
// as far as kart goes normal gravity is 2 (FRACUNIT*2)
|
||||
|
||||
gravityadjust = P_GetMobjGravity(player->mo)/2; // so we'll halve it for our calculations.
|
||||
|
||||
if (player->mo->eflags & MFE_UNDERWATER)
|
||||
gravityadjust /= 2; // halve "gravity" underwater
|
||||
|
||||
// and then modulate momz like that...
|
||||
player->mo->momz = -gravityadjust * player->tumbleHeight;
|
||||
player->mo->momz = K_TumbleZ(player->mo, player->tumbleHeight * FRACUNIT);
|
||||
}
|
||||
|
||||
// Play a falling sound when you start falling while tumbling and you're nowhere near done bouncing
|
||||
|
|
@ -3683,6 +3764,21 @@ static void K_HandleTumbleSound(player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
void K_TumbleInterrupt(player_t *player)
|
||||
{
|
||||
// If player was tumbling, set variables so that they don't tumble like crazy after they're done respawning
|
||||
if (player->tumbleBounces > 0)
|
||||
{
|
||||
player->tumbleBounces = 0; // MAXBOUNCES-1;
|
||||
player->pflags &= ~PF_TUMBLELASTBOUNCE;
|
||||
//players->tumbleHeight = 20;
|
||||
|
||||
players->mo->rollangle = 0;
|
||||
player->spinouttype = KSPIN_WIPEOUT;
|
||||
player->spinouttimer = player->wipeoutslow = TICRATE+2;
|
||||
}
|
||||
}
|
||||
|
||||
void K_ApplyTripWire(player_t *player, tripwirestate_t state)
|
||||
{
|
||||
if (state == TRIP_PASSED)
|
||||
|
|
@ -3694,7 +3790,7 @@ void K_ApplyTripWire(player_t *player, tripwirestate_t state)
|
|||
K_AddHitLag(player->mo, 10, false);
|
||||
|
||||
if (state == TRIP_PASSED && player->spinouttimer &&
|
||||
player->speed > 2* K_GetKartSpeed(player, false))
|
||||
player->speed > 2 * K_GetKartSpeed(player, false, true))
|
||||
{
|
||||
K_TumblePlayer(player, NULL, NULL);
|
||||
}
|
||||
|
|
@ -3764,6 +3860,8 @@ void K_HandleBumperChanges(player_t *player, UINT8 prevBumpers)
|
|||
|
||||
if (player->bumpers > 0 && prevBumpers == 0)
|
||||
{
|
||||
K_DoInvincibility(player, 8 * TICRATE);
|
||||
|
||||
if (netgame)
|
||||
{
|
||||
CONS_Printf(M_GetText("%s is back in the game!\n"), player_names[player-players]);
|
||||
|
|
@ -4026,19 +4124,21 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I
|
|||
{
|
||||
mobj_t *th;
|
||||
fixed_t x, y, z;
|
||||
fixed_t topspeed = K_GetKartSpeed(source->player, false, false);
|
||||
fixed_t finalspeed = speed;
|
||||
fixed_t finalscale = mapobjectscale;
|
||||
mobj_t *throwmo;
|
||||
|
||||
if (source->player != NULL)
|
||||
{
|
||||
|
||||
if (source->player->itemscale == ITEMSCALE_SHRINK)
|
||||
{
|
||||
// Nerf the base item speed a bit.
|
||||
finalspeed = FixedMul(finalspeed, SHRINK_PHYSICS_SCALE);
|
||||
}
|
||||
|
||||
if (source->player->speed > K_GetKartSpeed(source->player, false))
|
||||
if (source->player->speed > topspeed)
|
||||
{
|
||||
angle_t input = source->angle - an;
|
||||
boolean invert = (input > ANGLE_180);
|
||||
|
|
@ -4046,7 +4146,7 @@ static mobj_t *K_SpawnKartMissile(mobj_t *source, mobjtype_t type, angle_t an, I
|
|||
input = InvAngle(input);
|
||||
|
||||
finalspeed = max(speed, FixedMul(speed, FixedMul(
|
||||
FixedDiv(source->player->speed, K_GetKartSpeed(source->player, false)), // Multiply speed to be proportional to your own, boosted maxspeed.
|
||||
FixedDiv(source->player->speed, topspeed), // Multiply speed to be proportional to your own, boosted maxspeed.
|
||||
(((180<<FRACBITS) - AngleFixed(input)) / 180) // multiply speed based on angle diff... i.e: don't do this for firing backward :V
|
||||
)));
|
||||
}
|
||||
|
|
@ -4498,7 +4598,7 @@ static void K_SpawnAIZDust(player_t *player)
|
|||
if (!P_IsObjectOnGround(player->mo))
|
||||
return;
|
||||
|
||||
if (player->speed <= K_GetKartSpeed(player, false))
|
||||
if (player->speed <= K_GetKartSpeed(player, false, true))
|
||||
return;
|
||||
|
||||
travelangle = K_MomentumAngle(player->mo);
|
||||
|
|
@ -4683,6 +4783,9 @@ void K_SpawnDraftDust(mobj_t *mo)
|
|||
{
|
||||
UINT8 leniency = (3*TICRATE)/4 + ((mo->player->kartweight-1) * (TICRATE/4));
|
||||
|
||||
if (gametype == GT_BATTLE)
|
||||
leniency *= 4;
|
||||
|
||||
ang = mo->player->drawangle;
|
||||
|
||||
if (mo->player->drift != 0)
|
||||
|
|
@ -5645,7 +5748,7 @@ void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound)
|
|||
|
||||
mo->player->tricktime = 0; // Reset post-hitlag timer
|
||||
// Setup the boost for potential upwards trick, at worse, make it your regular max speed. (boost = curr speed*1.25)
|
||||
mo->player->trickboostpower = max(FixedDiv(mo->player->speed, K_GetKartSpeed(mo->player, false)) - FRACUNIT, 0)*125/100;
|
||||
mo->player->trickboostpower = max(FixedDiv(mo->player->speed, K_GetKartSpeed(mo->player, false, false)) - FRACUNIT, 0)*125/100;
|
||||
//CONS_Printf("Got boost: %d%\n", mo->player->trickboostpower*100 / FRACUNIT);
|
||||
}
|
||||
|
||||
|
|
@ -5696,6 +5799,30 @@ static void K_ThrowLandMine(player_t *player)
|
|||
throwmo->movecount = 0; // above player
|
||||
}
|
||||
|
||||
void K_DoInvincibility(player_t *player, tic_t time)
|
||||
{
|
||||
if (!player->invincibilitytimer)
|
||||
{
|
||||
mobj_t *overlay = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INVULNFLASH);
|
||||
P_SetTarget(&overlay->target, player->mo);
|
||||
overlay->destscale = player->mo->scale;
|
||||
P_SetScale(overlay, player->mo->scale);
|
||||
}
|
||||
|
||||
player->invincibilitytimer += time;
|
||||
|
||||
if (P_IsLocalPlayer(player) == true)
|
||||
{
|
||||
S_ChangeMusicSpecial("kinvnc");
|
||||
}
|
||||
else //used to be "if (P_IsDisplayPlayer(player) == false)"
|
||||
{
|
||||
S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmi : sfx_kinvnc));
|
||||
}
|
||||
|
||||
P_RestoreMusic(player);
|
||||
}
|
||||
|
||||
void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source)
|
||||
{
|
||||
mobj_t *cachenext;
|
||||
|
|
@ -6528,14 +6655,16 @@ static void K_MoveHeldObjects(player_t *player)
|
|||
|
||||
cur->angle = R_PointToAngle2(cur->x, cur->y, targx, targy);
|
||||
|
||||
/*if (P_IsObjectOnGround(player->mo) && player->speed > 0 && player->bananadrag > TICRATE
|
||||
&& P_RandomChance(min(FRACUNIT/2, FixedDiv(player->speed, K_GetKartSpeed(player, false))/2)))
|
||||
/*
|
||||
if (P_IsObjectOnGround(player->mo) && player->speed > 0 && player->bananadrag > TICRATE
|
||||
&& P_RandomChance(min(FRACUNIT/2, FixedDiv(player->speed, K_GetKartSpeed(player, false, false))/2)))
|
||||
{
|
||||
if (leveltime & 1)
|
||||
targz += 8*(2*FRACUNIT)/7;
|
||||
else
|
||||
targz -= 8*(2*FRACUNIT)/7;
|
||||
}*/
|
||||
}
|
||||
*/
|
||||
|
||||
if (speed > dist)
|
||||
P_InstaThrust(cur, cur->angle, speed-dist);
|
||||
|
|
@ -7169,6 +7298,8 @@ static void K_LookForRings(mobj_t *pmo)
|
|||
*/
|
||||
void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
||||
{
|
||||
const boolean onground = P_IsObjectOnGround(player->mo);
|
||||
|
||||
K_UpdateOffroad(player);
|
||||
K_UpdateDraft(player);
|
||||
K_UpdateEngineSounds(player); // Thanks, VAda!
|
||||
|
|
@ -7440,8 +7571,10 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
if (player->strongdriftboost)
|
||||
player->strongdriftboost--;
|
||||
|
||||
if (player->startboost)
|
||||
if (player->startboost > 0 && onground == true)
|
||||
{
|
||||
player->startboost--;
|
||||
}
|
||||
|
||||
if (player->spindashboost)
|
||||
{
|
||||
|
|
@ -7646,7 +7779,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
|
||||
if (K_GetKartButtons(player) & BT_BRAKE &&
|
||||
P_IsObjectOnGround(player->mo) &&
|
||||
K_GetKartSpeed(player, false) / 2 <= player->speed)
|
||||
K_GetKartSpeed(player, false, false) / 2 <= player->speed)
|
||||
{
|
||||
K_SpawnBrakeVisuals(player);
|
||||
}
|
||||
|
|
@ -7656,7 +7789,6 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
|
||||
void K_KartResetPlayerColor(player_t *player)
|
||||
{
|
||||
boolean forcereset = false;
|
||||
boolean fullbright = false;
|
||||
|
||||
if (!player->mo || P_MobjWasRemoved(player->mo)) // Can't do anything
|
||||
|
|
@ -7672,9 +7804,9 @@ void K_KartResetPlayerColor(player_t *player)
|
|||
if (player->eggmanexplode) // You're gonna diiiiie
|
||||
{
|
||||
const INT32 flashtime = 4<<(player->eggmanexplode/TICRATE);
|
||||
if (player->eggmanexplode == 1 || (player->eggmanexplode % (flashtime/2) != 0))
|
||||
if (player->eggmanexplode % (flashtime/2) != 0)
|
||||
{
|
||||
forcereset = true;
|
||||
;
|
||||
}
|
||||
else if (player->eggmanexplode % flashtime == 0)
|
||||
{
|
||||
|
|
@ -7696,6 +7828,7 @@ void K_KartResetPlayerColor(player_t *player)
|
|||
{
|
||||
const tic_t defaultTime = itemtime+(2*TICRATE);
|
||||
tic_t flicker = 2;
|
||||
boolean skip = false;
|
||||
|
||||
fullbright = true;
|
||||
|
||||
|
|
@ -7703,22 +7836,21 @@ void K_KartResetPlayerColor(player_t *player)
|
|||
{
|
||||
player->mo->color = K_RainbowColor(leveltime / 2);
|
||||
player->mo->colorized = true;
|
||||
forcereset = false;
|
||||
skip = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
flicker += (defaultTime - player->invincibilitytimer) / TICRATE / 2;
|
||||
forcereset = true;
|
||||
}
|
||||
|
||||
if (leveltime % flicker == 0)
|
||||
{
|
||||
player->mo->color = SKINCOLOR_INVINCFLASH;
|
||||
player->mo->colorized = true;
|
||||
forcereset = false;
|
||||
skip = true;
|
||||
}
|
||||
|
||||
if (!forcereset)
|
||||
if (skip)
|
||||
{
|
||||
goto finalise;
|
||||
}
|
||||
|
|
@ -7733,8 +7865,6 @@ void K_KartResetPlayerColor(player_t *player)
|
|||
fullbright = true;
|
||||
goto finalise;
|
||||
}
|
||||
|
||||
forcereset = true;
|
||||
}
|
||||
|
||||
if (player->ringboost && (leveltime & 1)) // ring boosting
|
||||
|
|
@ -7746,10 +7876,7 @@ void K_KartResetPlayerColor(player_t *player)
|
|||
else
|
||||
{
|
||||
player->mo->colorized = (player->dye != 0);
|
||||
if (forcereset)
|
||||
{
|
||||
player->mo->color = player->dye ? player->dye : player->skincolor;
|
||||
}
|
||||
player->mo->color = player->dye ? player->dye : player->skincolor;
|
||||
}
|
||||
|
||||
finalise:
|
||||
|
|
@ -7951,6 +8078,12 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
|
|||
|
||||
if (angledelta < nextbestdelta || momdelta < nextbestmomdelta)
|
||||
{
|
||||
if (P_TraceBlockingLines(player->mo, waypoint->nextwaypoints[i]->mobj) == false)
|
||||
{
|
||||
// Save sight checks when all of the other checks pass, so we only do it if we have to
|
||||
continue;
|
||||
}
|
||||
|
||||
bestwaypoint = waypoint->nextwaypoints[i];
|
||||
|
||||
if (angledelta < nextbestdelta)
|
||||
|
|
@ -7997,6 +8130,12 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player)
|
|||
|
||||
if (angledelta < nextbestdelta && momdelta < nextbestmomdelta)
|
||||
{
|
||||
if (P_TraceBlockingLines(player->mo, waypoint->prevwaypoints[i]->mobj) == false)
|
||||
{
|
||||
// Save sight checks when all of the other checks pass, so we only do it if we have to
|
||||
continue;
|
||||
}
|
||||
|
||||
bestwaypoint = waypoint->prevwaypoints[i];
|
||||
|
||||
nextbestdelta = angledelta;
|
||||
|
|
@ -8168,7 +8307,7 @@ void K_UpdateDistanceFromFinishLine(player_t *const player)
|
|||
// distance calculation to work easily
|
||||
if ((mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE) == 0U)
|
||||
{
|
||||
const UINT8 numfulllapsleft = ((UINT8)cv_numlaps.value - player->laps);
|
||||
const UINT8 numfulllapsleft = ((UINT8)numlaps - player->laps);
|
||||
|
||||
player->distancetofinish += numfulllapsleft * K_GetCircuitLength();
|
||||
|
||||
|
|
@ -8341,14 +8480,13 @@ INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue)
|
|||
return 0;
|
||||
}
|
||||
|
||||
p_maxspeed = K_GetKartSpeed(player, false);
|
||||
p_maxspeed = K_GetKartSpeed(player, false, true);
|
||||
p_speed = min(currentSpeed, (p_maxspeed * 2));
|
||||
weightadjust = FixedDiv((p_maxspeed * 3) - p_speed, (p_maxspeed * 3) + (player->kartweight * FRACUNIT));
|
||||
|
||||
if (K_PlayerUsesBotMovement(player))
|
||||
{
|
||||
turnfixed = FixedMul(turnfixed, 5*FRACUNIT/4); // Base increase to turning
|
||||
turnfixed = FixedMul(turnfixed, K_BotRubberband(player));
|
||||
}
|
||||
|
||||
if (player->drift != 0 && P_IsObjectOnGround(player->mo))
|
||||
|
|
@ -8394,7 +8532,7 @@ INT32 K_GetUnderwaterTurnAdjust(player_t *player)
|
|||
steer = 9 * steer / 5;
|
||||
|
||||
return FixedMul(steer, 8 * FixedDiv(player->speed,
|
||||
2 * K_GetKartSpeed(player, false) / 3));
|
||||
2 * K_GetKartSpeed(player, false, true) / 3));
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
|
@ -8908,9 +9046,10 @@ static INT32 K_FlameShieldMax(player_t *player)
|
|||
disttofinish = players[i].distancetofinish;
|
||||
}
|
||||
|
||||
if (numplayers <= 1)
|
||||
if (numplayers <= 1 || gametype == GT_BATTLE)
|
||||
{
|
||||
return 16; // max when alone, for testing
|
||||
// and when in battle, for chaos
|
||||
}
|
||||
else if (player->position == 1)
|
||||
{
|
||||
|
|
@ -9149,8 +9288,14 @@ static void K_KartSpindash(player_t *player)
|
|||
// if spindash was charged enough, give a small thrust.
|
||||
if (player->spindash >= SPINDASHTHRUSTTIME)
|
||||
{
|
||||
fixed_t thrust = FixedMul(player->mo->scale, player->spindash*FRACUNIT/5);
|
||||
|
||||
// TODO: gametyperules
|
||||
if (gametype == GT_BATTLE)
|
||||
thrust *= 2;
|
||||
|
||||
// Give a bit of a boost depending on charge.
|
||||
P_InstaThrust(player->mo, player->mo->angle, FixedMul(player->mo->scale, player->spindash*FRACUNIT/5));
|
||||
P_InstaThrust(player->mo, player->mo->angle, thrust);
|
||||
}
|
||||
|
||||
if (!player->tiregrease)
|
||||
|
|
@ -9348,13 +9493,6 @@ void K_AdjustPlayerFriction(player_t *player)
|
|||
else
|
||||
player->mo->movefactor = FRACUNIT;
|
||||
}
|
||||
|
||||
// Don't go too far above your top speed when rubberbanding
|
||||
// Down here, because we do NOT want to modify movefactor
|
||||
if (K_PlayerUsesBotMovement(player))
|
||||
{
|
||||
player->mo->friction = K_BotFrictionRubberband(player, player->mo->friction);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -9617,25 +9755,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
case KITEM_INVINCIBILITY:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO) // Doesn't hold your item slot hostage normally, so you're free to waste it if you have multiple
|
||||
{
|
||||
if (!player->invincibilitytimer)
|
||||
{
|
||||
mobj_t *overlay = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_INVULNFLASH);
|
||||
P_SetTarget(&overlay->target, player->mo);
|
||||
overlay->destscale = player->mo->scale;
|
||||
P_SetScale(overlay, player->mo->scale);
|
||||
}
|
||||
player->invincibilitytimer += itemtime+(2*TICRATE); // 10 seconds
|
||||
|
||||
if (P_IsLocalPlayer(player) == true)
|
||||
{
|
||||
S_ChangeMusicSpecial("kinvnc");
|
||||
}
|
||||
else //used to be "if (P_IsDisplayPlayer(player) == false)"
|
||||
{
|
||||
S_StartSound(player->mo, (cv_kartinvinsfx.value ? sfx_alarmi : sfx_kinvnc));
|
||||
}
|
||||
|
||||
P_RestoreMusic(player);
|
||||
K_DoInvincibility(player, 10 * TICRATE);
|
||||
K_PlayPowerGloatSound(player->mo);
|
||||
player->itemamount--;
|
||||
}
|
||||
|
|
@ -9883,7 +10003,8 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
player->mo->destscale = FixedMul(player->mo->destscale, SHRINK_SCALE);
|
||||
}
|
||||
|
||||
player->growshrinktimer = itemtime+(4*TICRATE); // 12 seconds
|
||||
// TODO: gametyperules
|
||||
player->growshrinktimer = (gametype == GT_BATTLE ? 8 : 12) * TICRATE;
|
||||
|
||||
if (player->invincibilitytimer > 0)
|
||||
{
|
||||
|
|
@ -10007,14 +10128,17 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
|
||||
if ((cmd->buttons & BT_ATTACK) && (player->pflags & PF_HOLDREADY))
|
||||
{
|
||||
// TODO: gametyperules
|
||||
const INT32 incr = gametype == GT_BATTLE ? 4 : 2;
|
||||
|
||||
if (player->flamedash == 0)
|
||||
{
|
||||
S_StartSound(player->mo, sfx_s3k43);
|
||||
K_PlayBoostTaunt(player->mo);
|
||||
}
|
||||
|
||||
player->flamedash += 2;
|
||||
player->flamemeter += 2;
|
||||
player->flamedash += incr;
|
||||
player->flamemeter += incr;
|
||||
|
||||
if (!onground)
|
||||
{
|
||||
|
|
@ -10041,8 +10165,12 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
{
|
||||
player->pflags |= PF_HOLDREADY;
|
||||
|
||||
if (player->flamemeter > 0)
|
||||
player->flamemeter--;
|
||||
// TODO: gametyperules
|
||||
if (gametype != GT_BATTLE || leveltime % 6 == 0)
|
||||
{
|
||||
if (player->flamemeter > 0)
|
||||
player->flamemeter--;
|
||||
}
|
||||
|
||||
if (player->flamelength > destlen)
|
||||
{
|
||||
|
|
@ -10071,16 +10199,15 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && onground && NO_HYUDORO && player->trickpanel == 0)
|
||||
{
|
||||
K_PlayBoostTaunt(player->mo);
|
||||
K_DoPogoSpring(player->mo, 32<<FRACBITS, 2);
|
||||
player->trickpanel = 1;
|
||||
player->pflags |= PF_TRICKDELAY;
|
||||
//K_DoPogoSpring(player->mo, 32<<FRACBITS, 2);
|
||||
P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_POGOSPRING);
|
||||
player->itemamount--;
|
||||
}
|
||||
break;
|
||||
case KITEM_SUPERRING:
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO && player->superring < (UINT16_MAX - (10*3)))
|
||||
if (ATTACK_IS_DOWN && !HOLDING_ITEM && NO_HYUDORO)
|
||||
{
|
||||
player->superring += (10*3);
|
||||
K_AwardPlayerRings(player, 10, true);
|
||||
player->itemamount--;
|
||||
}
|
||||
break;
|
||||
|
|
@ -10193,7 +10320,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
const angle_t lr = ANGLE_45;
|
||||
fixed_t momz = FixedDiv(player->mo->momz, mapobjectscale); // bring momz back to scale...
|
||||
fixed_t speedmult = max(0, FRACUNIT - abs(momz)/TRICKMOMZRAMP); // TRICKMOMZRAMP momz is minimum speed (Should be 20)
|
||||
fixed_t basespeed = P_AproxDistance(player->mo->momx, player->mo->momy); // at WORSE, keep your normal speed when tricking.
|
||||
fixed_t basespeed = K_GetKartSpeed(player, false, false); // at WORSE, keep your normal speed when tricking.
|
||||
fixed_t speed = FixedMul(speedmult, P_AproxDistance(player->mo->momx, player->mo->momy));
|
||||
|
||||
K_trickPanelTimingVisual(player, momz);
|
||||
|
|
|
|||
|
|
@ -67,11 +67,13 @@ void K_KartPlayerAfterThink(player_t *player);
|
|||
angle_t K_MomentumAngle(mobj_t *mo);
|
||||
void K_AddHitLag(mobj_t *mo, INT32 tics, boolean fromDamage);
|
||||
void K_SetHitLagForObjects(mobj_t *mo1, mobj_t *mo2, INT32 tics, boolean fromDamage);
|
||||
void K_AwardPlayerRings(player_t *player, INT32 rings, boolean overload);
|
||||
void K_DoInstashield(player_t *player);
|
||||
void K_DoPowerClash(player_t *t1, player_t *t2);
|
||||
void K_BattleAwardHit(player_t *player, player_t *victim, mobj_t *inflictor, UINT8 bumpersRemoved);
|
||||
void K_SpinPlayer(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 type);
|
||||
void K_TumblePlayer(player_t *player, mobj_t *inflictor, mobj_t *source);
|
||||
void K_TumbleInterrupt(player_t *player);
|
||||
INT32 K_ExplodePlayer(player_t *player, mobj_t *inflictor, mobj_t *source);
|
||||
void K_DebtStingPlayer(player_t *player, mobj_t *source);
|
||||
void K_HandleBumperChanges(player_t *player, UINT8 prevBumpers);
|
||||
|
|
@ -91,6 +93,7 @@ mobj_t *K_ThrowKartItem(player_t *player, boolean missile, mobjtype_t mapthing,
|
|||
void K_PuntMine(mobj_t *mine, mobj_t *punter);
|
||||
void K_DoSneaker(player_t *player, INT32 type);
|
||||
void K_DoPogoSpring(mobj_t *mo, fixed_t vertispeed, UINT8 sound);
|
||||
void K_DoInvincibility(player_t *player, tic_t time);
|
||||
void K_KillBananaChain(mobj_t *banana, mobj_t *inflictor, mobj_t *source);
|
||||
void K_UpdateHnextList(player_t *player, boolean clean);
|
||||
void K_DropHnextList(player_t *player, boolean keepshields);
|
||||
|
|
@ -126,7 +129,7 @@ INT16 K_GetSpindashChargeTime(player_t *player);
|
|||
fixed_t K_GetSpindashChargeSpeed(player_t *player);
|
||||
fixed_t K_GrowShrinkSpeedMul(player_t *player);
|
||||
fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed);
|
||||
fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower);
|
||||
fixed_t K_GetKartSpeed(player_t *player, boolean doboostpower, boolean dorubberbanding);
|
||||
fixed_t K_GetKartAccel(player_t *player);
|
||||
UINT16 K_GetKartFlashing(player_t *player);
|
||||
boolean K_PlayerShrinkCheat(player_t *player);
|
||||
|
|
|
|||
426
src/k_pwrlv.c
426
src/k_pwrlv.c
|
|
@ -1,5 +1,12 @@
|
|||
/// \file k_pwrlv.c
|
||||
/// \brief SRB2Kart Power Levels
|
||||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2018-2022 by Sally Cochenour
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
// \brief Power Level system
|
||||
|
||||
#include "k_pwrlv.h"
|
||||
#include "d_netcmd.h"
|
||||
|
|
@ -19,9 +26,12 @@ UINT16 vspowerlevel[PWRLV_NUMTYPES];
|
|||
// This is done so that clients will never be able to hack someone else's score over the server.
|
||||
UINT16 clientpowerlevels[MAXPLAYERS][PWRLV_NUMTYPES];
|
||||
|
||||
// Which players spec-scummed, and their power level before scumming.
|
||||
// On race finish, everyone is considered to have "won" against these people.
|
||||
INT16 nospectategrief[MAXPLAYERS];
|
||||
// Total calculated power add during the match,
|
||||
// totalled at the end of the round.
|
||||
INT16 clientPowerAdd[MAXPLAYERS];
|
||||
|
||||
// Players who spectated mid-race
|
||||
UINT8 spectateGriefed = 0;
|
||||
|
||||
// Game setting scrambles based on server Power Level
|
||||
SINT8 speedscramble = -1;
|
||||
|
|
@ -52,8 +62,14 @@ void K_ClearClientPowerLevels(void)
|
|||
{
|
||||
UINT8 i, j;
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
clientPowerAdd[i] = 0;
|
||||
|
||||
for (j = 0; j < PWRLV_NUMTYPES; j++)
|
||||
{
|
||||
clientpowerlevels[i][j] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adapted from this: http://wiki.tockdom.com/wiki/Player_Rating
|
||||
|
|
@ -71,7 +87,7 @@ INT16 K_CalculatePowerLevelInc(INT16 diff)
|
|||
diff = -MAXDIFF;
|
||||
#undef MAXDIFF
|
||||
|
||||
x = ((diff-2)<<FRACBITS) / PWRLVRECORD_START;
|
||||
x = ((diff-2)<<FRACBITS) / PWRLVRECORD_MEDIAN;
|
||||
|
||||
for (j = 3; j < 10; j++) // Just skipping to 3 since 0 thru 2 will always just add 0...
|
||||
{
|
||||
|
|
@ -98,6 +114,23 @@ INT16 K_CalculatePowerLevelInc(INT16 diff)
|
|||
return (INT16)(increment >> FRACBITS);
|
||||
}
|
||||
|
||||
INT16 K_PowerLevelPlacementScore(player_t *player)
|
||||
{
|
||||
if ((player->pflags & PF_NOCONTEST) || (player->spectator))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (gametyperules & GTR_CIRCUIT)
|
||||
{
|
||||
return MAXPLAYERS - player->position;
|
||||
}
|
||||
else
|
||||
{
|
||||
return player->score;
|
||||
}
|
||||
}
|
||||
|
||||
INT16 K_CalculatePowerLevelAvg(void)
|
||||
{
|
||||
fixed_t avg = 0;
|
||||
|
|
@ -143,7 +176,269 @@ INT16 K_CalculatePowerLevelAvg(void)
|
|||
return (INT16)(avg >> FRACBITS);
|
||||
}
|
||||
|
||||
// -- K_UpdatePowerLevels could not be moved here due to usage of y_data, unfortunately. --
|
||||
void K_UpdatePowerLevels(player_t *player, UINT8 lap, boolean forfeit)
|
||||
{
|
||||
const UINT8 playerNum = player - players;
|
||||
const boolean exitBonus = ((lap > numlaps) || (player->pflags & PF_NOCONTEST));
|
||||
|
||||
SINT8 powerType = K_UsingPowerLevels();
|
||||
|
||||
INT16 yourScore = 0;
|
||||
UINT16 yourPower = 0;
|
||||
|
||||
UINT8 i;
|
||||
|
||||
// Compare every single player against each other for power level increases.
|
||||
// Every player you won against gives you more points, and vice versa.
|
||||
// The amount of points won per match-up depends on the difference between the loser's power and the winner's power.
|
||||
// See K_CalculatePowerLevelInc for more info.
|
||||
|
||||
if (powerType == PWRLV_DISABLED)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!playeringame[playerNum] || player->spectator)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//CONS_Printf("\n========\n");
|
||||
//CONS_Printf("* Power Level change for player %s (LAP %d) *\n", player_names[playerNum], lap);
|
||||
//CONS_Printf("========\n");
|
||||
|
||||
yourPower = clientpowerlevels[playerNum][powerType];
|
||||
if (yourPower == 0)
|
||||
{
|
||||
// Guests don't record power level changes.
|
||||
return;
|
||||
}
|
||||
|
||||
//CONS_Printf("%s's PWR.LV: %d\n", player_names[playerNum], yourPower);
|
||||
|
||||
yourScore = K_PowerLevelPlacementScore(player);
|
||||
//CONS_Printf("%s's gametype score: %d\n", player_names[playerNum], yourScore);
|
||||
|
||||
//CONS_Printf("========\n");
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
UINT16 theirScore = 0;
|
||||
INT16 theirPower = 0;
|
||||
|
||||
INT16 diff = 0; // Loser PWR.LV - Winner PWR.LV
|
||||
INT16 inc = 0; // Total pt increment
|
||||
|
||||
boolean won = false;
|
||||
|
||||
if (i == playerNum) // Same person
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//CONS_Printf("%s VS %s:\n", player_names[playerNum], player_names[i]);
|
||||
|
||||
theirPower = clientpowerlevels[i][powerType];
|
||||
if (theirPower == 0)
|
||||
{
|
||||
// No power level (splitscreen guests, bots)
|
||||
continue;
|
||||
}
|
||||
|
||||
//CONS_Printf("%s's PWR.LV: %d\n", player_names[i], theirPower);
|
||||
|
||||
theirScore = K_PowerLevelPlacementScore(&players[i]);
|
||||
//CONS_Printf("%s's gametype score: %d\n", player_names[i], theirScore);
|
||||
|
||||
if (yourScore == theirScore && forfeit == false) // Tie -- neither get any points for this match up.
|
||||
{
|
||||
//CONS_Printf("TIE, no change.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
won = (yourScore > theirScore);
|
||||
|
||||
if (won == true && forfeit == false) // This player won!
|
||||
{
|
||||
diff = theirPower - yourPower;
|
||||
inc += K_CalculatePowerLevelInc(diff);
|
||||
//CONS_Printf("WON! Diff is %d, increment is %d\n", diff, inc);
|
||||
}
|
||||
else // This player lost...
|
||||
{
|
||||
diff = yourPower - theirPower;
|
||||
inc -= K_CalculatePowerLevelInc(diff);
|
||||
//CONS_Printf("LOST... Diff is %d, increment is %d\n", diff, inc);
|
||||
}
|
||||
|
||||
if (exitBonus == false)
|
||||
{
|
||||
INT16 prevInc = inc;
|
||||
|
||||
inc /= max(numlaps-1, 1);
|
||||
|
||||
if (inc == 0)
|
||||
{
|
||||
if (prevInc > 0)
|
||||
{
|
||||
inc = 1;
|
||||
}
|
||||
else if (prevInc < 0)
|
||||
{
|
||||
inc = -1;
|
||||
}
|
||||
}
|
||||
|
||||
//CONS_Printf("Reduced (%d / %d = %d) because it's not the end of the race\n", prevInc, numlaps, inc);
|
||||
}
|
||||
|
||||
//CONS_Printf("========\n");
|
||||
|
||||
if (inc == 0)
|
||||
{
|
||||
CONS_Printf("Total Result: No increment, no change.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
//CONS_Printf("Total Result:\n");
|
||||
//CONS_Printf("Increment: %d\n", inc);
|
||||
|
||||
//CONS_Printf("%s current: %d\n", player_names[playerNum], clientPowerAdd[playerNum]);
|
||||
clientPowerAdd[playerNum] += inc;
|
||||
//CONS_Printf("%s final: %d\n", player_names[playerNum], clientPowerAdd[playerNum]);
|
||||
|
||||
//CONS_Printf("%s current: %d\n", player_names[i], clientPowerAdd[i]);
|
||||
clientPowerAdd[i] -= inc;
|
||||
//CONS_Printf("%s final: %d\n", player_names[i], clientPowerAdd[i]);
|
||||
|
||||
//CONS_Printf("========\n");
|
||||
}
|
||||
}
|
||||
|
||||
void K_UpdatePowerLevelsOnFailure(player_t *player)
|
||||
{
|
||||
// Update upon spectate / quit / NO CONTEST
|
||||
INT16 lapsLeft = 0;
|
||||
UINT8 i;
|
||||
|
||||
lapsLeft = (numlaps - player->latestlap) + 1;
|
||||
|
||||
if (lapsLeft <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < lapsLeft; i++)
|
||||
{
|
||||
K_UpdatePowerLevels(player, player->latestlap + (i + 1), true);
|
||||
}
|
||||
|
||||
player->latestlap = numlaps+1;
|
||||
}
|
||||
|
||||
INT16 K_FinalPowerIncrement(player_t *player, INT16 yourPower, INT16 baseInc)
|
||||
{
|
||||
INT16 inc = baseInc;
|
||||
UINT8 numPlayers = 0;
|
||||
UINT8 i;
|
||||
|
||||
if (yourPower == 0)
|
||||
{
|
||||
// Guests don't record power level changes.
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
numPlayers++;
|
||||
}
|
||||
|
||||
if (inc <= 0)
|
||||
{
|
||||
if (player->position == 1)
|
||||
{
|
||||
// Won the whole match?
|
||||
// Get at least one point.
|
||||
inc = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// You trade points in 1v1s,
|
||||
// but is more lenient in bigger lobbies.
|
||||
inc /= max(1, numPlayers-1);
|
||||
|
||||
if (inc == 0)
|
||||
{
|
||||
if (baseInc > 0)
|
||||
{
|
||||
inc = 1;
|
||||
}
|
||||
else if (baseInc < 0)
|
||||
{
|
||||
inc = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (yourPower + inc > PWRLVRECORD_MAX)
|
||||
{
|
||||
inc -= ((yourPower + inc) - PWRLVRECORD_MAX);
|
||||
}
|
||||
|
||||
if (yourPower + inc < PWRLVRECORD_MIN)
|
||||
{
|
||||
inc -= ((yourPower + inc) - PWRLVRECORD_MIN);
|
||||
}
|
||||
|
||||
return inc;
|
||||
}
|
||||
|
||||
void K_CashInPowerLevels(void)
|
||||
{
|
||||
SINT8 powerType = K_UsingPowerLevels();
|
||||
UINT8 i;
|
||||
|
||||
//CONS_Printf("\n========\n");
|
||||
//CONS_Printf("Cashing in power level changes...\n");
|
||||
//CONS_Printf("========\n");
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] == true && powerType != PWRLV_DISABLED)
|
||||
{
|
||||
INT16 inc = K_FinalPowerIncrement(&players[i], clientpowerlevels[i][powerType], clientPowerAdd[i]);
|
||||
clientpowerlevels[i][powerType] += inc;
|
||||
|
||||
//CONS_Printf("%s: %d -> %d (%d)\n", player_names[i], clientpowerlevels[i][powerType] - inc, clientpowerlevels[i][powerType], inc);
|
||||
|
||||
if (!demo.playback && i == consoleplayer && inc != 0)
|
||||
{
|
||||
vspowerlevel[powerType] = clientpowerlevels[i][powerType];
|
||||
|
||||
if (M_UpdateUnlockablesAndExtraEmblems())
|
||||
{
|
||||
S_StartSound(NULL, sfx_ncitem);
|
||||
}
|
||||
|
||||
G_SaveGameData();
|
||||
}
|
||||
}
|
||||
|
||||
clientPowerAdd[i] = 0;
|
||||
}
|
||||
|
||||
//CONS_Printf("========\n");
|
||||
}
|
||||
|
||||
void K_SetPowerLevelScrambles(SINT8 powertype)
|
||||
{
|
||||
|
|
@ -227,7 +522,7 @@ void K_SetPowerLevelScrambles(SINT8 powertype)
|
|||
{
|
||||
case 5:
|
||||
speed = KARTSPEED_HARD;
|
||||
encore = true;
|
||||
encore = P_RandomChance(FRACUNIT>>1);
|
||||
break;
|
||||
case 4:
|
||||
speed = P_RandomChance((7<<FRACBITS)/10) ? KARTSPEED_HARD : KARTSPEED_NORMAL;
|
||||
|
|
@ -238,7 +533,7 @@ void K_SetPowerLevelScrambles(SINT8 powertype)
|
|||
encore = P_RandomChance(FRACUNIT>>2);
|
||||
break;
|
||||
case 2:
|
||||
speed = 1;
|
||||
speed = KARTSPEED_NORMAL;
|
||||
encore = P_RandomChance(FRACUNIT>>3);
|
||||
break;
|
||||
case 1: default:
|
||||
|
|
@ -254,7 +549,7 @@ void K_SetPowerLevelScrambles(SINT8 powertype)
|
|||
CONS_Debug(DBG_GAMELOGIC, "Rolled speed: %d\n", speed);
|
||||
CONS_Debug(DBG_GAMELOGIC, "Rolled encore: %s\n", (encore ? "true" : "false"));
|
||||
|
||||
if (cv_kartspeed.value == -1)
|
||||
if (cv_kartspeed.value == KARTSPEED_AUTO)
|
||||
speedscramble = speed;
|
||||
else
|
||||
speedscramble = -1;
|
||||
|
|
@ -270,88 +565,89 @@ void K_SetPowerLevelScrambles(SINT8 powertype)
|
|||
}
|
||||
}
|
||||
|
||||
void K_PlayerForfeit(UINT8 playernum, boolean pointloss)
|
||||
void K_PlayerForfeit(UINT8 playerNum, boolean pointLoss)
|
||||
{
|
||||
UINT8 p = 0;
|
||||
INT32 powertype = PWRLV_DISABLED;
|
||||
UINT16 yourpower = PWRLVRECORD_DEF;
|
||||
UINT16 theirpower = PWRLVRECORD_DEF;
|
||||
INT16 diff = 0; // Loser PWR.LV - Winner PWR.LV
|
||||
|
||||
SINT8 powerType = PWRLV_DISABLED;
|
||||
UINT16 yourPower = 0;
|
||||
INT16 inc = 0;
|
||||
|
||||
UINT8 i;
|
||||
|
||||
// power level & spectating is netgames only
|
||||
if (!netgame)
|
||||
{
|
||||
return;
|
||||
|
||||
// This server isn't using power levels anyway!
|
||||
if (!cv_kartusepwrlv.value)
|
||||
return;
|
||||
}
|
||||
|
||||
// Hey, I just got here!
|
||||
if (players[playernum].jointime <= 1)
|
||||
if (players[playerNum].jointime <= 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 20 sec into the match counts as a forfeit -- automatic loss against every other player in the match.
|
||||
// 20 sec into a match counts as a forfeit -- automatic loss against every other player in the match.
|
||||
if (gamestate != GS_LEVEL || leveltime <= starttime+(20*TICRATE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
spectateGriefed++;
|
||||
|
||||
// This server isn't using power levels, so don't mess with them.
|
||||
if (!cv_kartusepwrlv.value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && !players[i].spectator)
|
||||
if ((playeringame[i] && !players[i].spectator)
|
||||
|| (i == playerNum))
|
||||
{
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
if (p < 2) // no players
|
||||
return;
|
||||
|
||||
if ((gametyperules & GTR_CIRCUIT))
|
||||
powertype = PWRLV_RACE;
|
||||
else if ((gametyperules & GTR_BUMPERS))
|
||||
powertype = PWRLV_BATTLE;
|
||||
|
||||
if (powertype == PWRLV_DISABLED) // No power type?!
|
||||
return;
|
||||
|
||||
if (clientpowerlevels[playernum][powertype] == 0) // splitscreen guests don't record power level changes
|
||||
return;
|
||||
yourpower = clientpowerlevels[playernum][powertype];
|
||||
|
||||
// Set up the point compensation.
|
||||
nospectategrief[playernum] = yourpower;
|
||||
|
||||
if (!pointloss) // This is set for stuff like sync-outs, which shouldn't be so harsh on the victim!
|
||||
return;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (i == playernum)
|
||||
continue;
|
||||
|
||||
if (clientpowerlevels[i][powertype] == 0) // No power level (splitscreen guests, bots)
|
||||
continue;
|
||||
|
||||
theirpower = clientpowerlevels[i][powertype];
|
||||
|
||||
diff = yourpower - theirpower;
|
||||
inc -= K_CalculatePowerLevelInc(diff);
|
||||
return;
|
||||
}
|
||||
|
||||
if (inc == 0) // No change.
|
||||
return;
|
||||
powerType = K_UsingPowerLevels();
|
||||
|
||||
if (yourpower + inc > PWRLVRECORD_MAX) // I mean... we're subtracting... but y'know how it is :V
|
||||
inc -= ((yourpower + inc) - PWRLVRECORD_MAX);
|
||||
if (yourpower + inc < PWRLVRECORD_MIN)
|
||||
inc -= ((yourpower + inc) - PWRLVRECORD_MIN);
|
||||
|
||||
clientpowerlevels[playernum][powertype] += inc;
|
||||
|
||||
if (!demo.playback && playernum == consoleplayer)
|
||||
if (powerType == PWRLV_DISABLED) // No power type?!
|
||||
{
|
||||
vspowerlevel[powertype] = clientpowerlevels[playernum][powertype];
|
||||
return;
|
||||
}
|
||||
|
||||
yourPower = clientpowerlevels[playerNum][powerType];
|
||||
if (yourPower == 0) // splitscreen guests don't record power level changes
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
K_UpdatePowerLevelsOnFailure(&players[playerNum]);
|
||||
inc = K_FinalPowerIncrement(&players[playerNum], yourPower, clientPowerAdd[playerNum]);
|
||||
|
||||
if (inc >= 0)
|
||||
{
|
||||
// Don't record no change or increases.
|
||||
return;
|
||||
}
|
||||
|
||||
// pointLoss isn't set for stuff like sync-outs,
|
||||
// which shouldn't be so harsh on the victim!
|
||||
if (!demo.playback && pointLoss == true && playerNum == consoleplayer)
|
||||
{
|
||||
vspowerlevel[powerType] = yourPower + inc;
|
||||
|
||||
if (M_UpdateUnlockablesAndExtraEmblems())
|
||||
{
|
||||
S_StartSound(NULL, sfx_ncitem);
|
||||
G_SaveGameData(); // save your punishment!
|
||||
}
|
||||
|
||||
G_SaveGameData();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,30 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2018-2022 by Sally Cochenour
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
// \brief Power Level system
|
||||
|
||||
#ifndef __K_PWRLV__
|
||||
#define __K_PWRLV__
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "doomdef.h"
|
||||
#include "d_player.h"
|
||||
|
||||
#define PWRLV_DISABLED -1
|
||||
#define PWRLV_RACE 0
|
||||
#define PWRLV_BATTLE 1
|
||||
#define PWRLV_NUMTYPES 2
|
||||
typedef enum
|
||||
{
|
||||
PWRLV_DISABLED = -1,
|
||||
PWRLV_RACE = 0,
|
||||
PWRLV_BATTLE = 1,
|
||||
PWRLV_NUMTYPES = 2,
|
||||
} pwrlv_type_t;
|
||||
|
||||
#define PWRLVRECORD_START 1000
|
||||
#define PWRLVRECORD_DEF 5000
|
||||
#define PWRLVRECORD_MEDIAN 5000
|
||||
#define PWRLVRECORD_MIN 1
|
||||
#define PWRLVRECORD_MAX 9999
|
||||
|
||||
|
|
@ -19,13 +33,18 @@ extern SINT8 encorescramble;
|
|||
|
||||
extern UINT16 vspowerlevel[PWRLV_NUMTYPES];
|
||||
extern UINT16 clientpowerlevels[MAXPLAYERS][PWRLV_NUMTYPES];
|
||||
extern INT16 nospectategrief[MAXPLAYERS];
|
||||
extern INT16 clientPowerAdd[MAXPLAYERS];
|
||||
extern UINT8 spectateGriefed;
|
||||
|
||||
SINT8 K_UsingPowerLevels(void);
|
||||
void K_ClearClientPowerLevels(void);
|
||||
INT16 K_CalculatePowerLevelInc(INT16 diff);
|
||||
INT16 K_PowerLevelPlacementScore(player_t *player);
|
||||
INT16 K_CalculatePowerLevelAvg(void);
|
||||
//void K_UpdatePowerLevels(void);
|
||||
void K_UpdatePowerLevels(player_t *player, UINT8 lap, boolean forfeit);
|
||||
void K_UpdatePowerLevelsOnFailure(player_t *player);
|
||||
INT16 K_FinalPowerIncrement(player_t *player, INT16 yourPower, INT16 increment);
|
||||
void K_CashInPowerLevels(void);
|
||||
void K_SetPowerLevelScrambles(SINT8 powertype);
|
||||
void K_PlayerForfeit(UINT8 playernum, boolean nopointloss);
|
||||
|
||||
|
|
|
|||
|
|
@ -151,18 +151,8 @@ void K_DoIngameRespawn(player_t *player)
|
|||
|
||||
player->ringboost = 0;
|
||||
player->driftboost = player->strongdriftboost = 0;
|
||||
|
||||
// If player was tumbling, set variables so that they don't tumble like crazy after they're done respawning
|
||||
if (player->tumbleBounces > 0)
|
||||
{
|
||||
player->tumbleBounces = 0; // MAXBOUNCES-1;
|
||||
player->pflags &= ~PF_TUMBLELASTBOUNCE;
|
||||
//players->tumbleHeight = 20;
|
||||
players->mo->rollangle = 0;
|
||||
player->spinouttype = KSPIN_WIPEOUT;
|
||||
player->spinouttimer = player->wipeoutslow = (3*TICRATE/2)+2;
|
||||
}
|
||||
|
||||
K_TumbleInterrupt(player);
|
||||
P_ResetPlayer(player);
|
||||
|
||||
// Set up respawn position if invalid
|
||||
|
|
@ -278,6 +268,7 @@ void K_DoIngameRespawn(player_t *player)
|
|||
player->respawn.state = RESPAWNST_MOVE;
|
||||
|
||||
player->respawn.airtimer = player->airtime;
|
||||
player->respawn.truedeath = false;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
@ -567,7 +558,9 @@ static void K_MovePlayerToRespawnPoint(player_t *player)
|
|||
lasersteps--;
|
||||
}
|
||||
|
||||
if (lasersteps == 0) // Don't spawn them beyond the respawn point.
|
||||
// Respawning after death: everything about the player
|
||||
// is invisible
|
||||
if (!player->respawn.truedeath && lasersteps == 0) // Don't spawn them beyond the respawn point.
|
||||
{
|
||||
mobj_t *lasermo = P_SpawnMobj(laser.x, laser.y, laser.z + (player->mo->height / 2), MT_DEZLASER);
|
||||
|
||||
|
|
|
|||
|
|
@ -361,6 +361,12 @@ waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj)
|
|||
// remember: huge radius
|
||||
if (closestdist <= rad && checkdist <= rad && finishline != NULL)
|
||||
{
|
||||
if (!P_TraceBlockingLines(mobj, checkwaypoint->mobj))
|
||||
{
|
||||
// Save sight checks when all of the other checks pass, so we only do it if we have to
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the mobj is touching multiple waypoints at once,
|
||||
// then solve ties by taking the one closest to the finish line.
|
||||
// Prevents position from flickering wildly when taking turns.
|
||||
|
|
@ -375,7 +381,7 @@ waypoint_t *K_GetBestWaypointForMobj(mobj_t *const mobj)
|
|||
{
|
||||
if (!P_TraceBlockingLines(mobj, checkwaypoint->mobj))
|
||||
{
|
||||
// Save sight checks for the end, so we only do it if we have to
|
||||
// Save sight checks when all of the other checks pass, so we only do it if we have to
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -162,6 +162,7 @@ static const struct {
|
|||
{META_SPRITEINFO, "spriteinfo_t"},
|
||||
{META_PIVOTLIST, "spriteframepivot_t[]"},
|
||||
{META_FRAMEPIVOT, "spriteframepivot_t"},
|
||||
{META_PRECIPPROPS, "precipprops_t"},
|
||||
|
||||
{META_TAGLIST, "taglist"},
|
||||
|
||||
|
|
@ -3704,10 +3705,11 @@ static int lib_kGetKartSpeed(lua_State *L)
|
|||
{
|
||||
player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER));
|
||||
boolean doboostpower = lua_optboolean(L, 2);
|
||||
boolean dorubberbanding = lua_optboolean(L, 3);
|
||||
//HUDSAFE
|
||||
if (!player)
|
||||
return LUA_ErrInvalid(L, "player_t");
|
||||
lua_pushfixed(L, K_GetKartSpeed(player, doboostpower));
|
||||
lua_pushfixed(L, K_GetKartSpeed(player, doboostpower, dorubberbanding));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1758,6 +1758,151 @@ static int colorramp_len(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
//////////////////
|
||||
// PRECIP PROPS //
|
||||
//////////////////
|
||||
|
||||
// Arbitrary precipprops[] table index -> precipprops_t *
|
||||
static int lib_getPrecipProps(lua_State *L)
|
||||
{
|
||||
INT32 i;
|
||||
lua_remove(L, 1);
|
||||
|
||||
i = luaL_checkinteger(L, 1);
|
||||
if (i <= 0 || i >= MAXPRECIP)
|
||||
return luaL_error(L, "precipprops[] index %d out of range (1 - %d)", i, MAXPRECIP-1);
|
||||
LUA_PushUserdata(L, &precipprops[i], META_PRECIPPROPS);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Lua table full of data -> precipprops[]
|
||||
static int lib_setPrecipProps(lua_State *L)
|
||||
{
|
||||
precipprops_t *props;
|
||||
lua_remove(L, 1); // don't care about precipprops[] userdata.
|
||||
{
|
||||
INT32 i = luaL_checkinteger(L, 1);
|
||||
if (i <= 0 || i >= MAXPRECIP)
|
||||
return luaL_error(L, "precipprops[] index %d out of range (1 - %d)", i, MAXPRECIP-1);
|
||||
props = &precipprops[i]; // get the precipprops to assign to.
|
||||
}
|
||||
|
||||
luaL_checktype(L, 2, LUA_TTABLE); // check that we've been passed a table.
|
||||
lua_remove(L, 1); // pop preciptype num, don't need it any more.
|
||||
lua_settop(L, 1); // cut the stack here. the only thing left now is the table of data we're assigning to the precipprops.
|
||||
|
||||
if (hud_running)
|
||||
return luaL_error(L, "Do not alter precipprops in HUD rendering code!");
|
||||
if (hook_cmd_running)
|
||||
return luaL_error(L, "Do not alter precipprops in CMD building code!");
|
||||
|
||||
// clear the precipprops to start with, in case of missing table elements
|
||||
// make sure we do not clear the name
|
||||
memset(props + sizeof(props->name), 0, sizeof(precipprops_t) - sizeof(props->name));
|
||||
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, 1)) {
|
||||
lua_Integer i = 0;
|
||||
const char *str = NULL;
|
||||
lua_Integer value;
|
||||
|
||||
if (lua_isnumber(L, 2))
|
||||
i = lua_tointeger(L, 2);
|
||||
else
|
||||
str = luaL_checkstring(L, 2);
|
||||
|
||||
if (i == 1 || (str && fastcmp(str, "type")))
|
||||
{
|
||||
value = luaL_checkinteger(L, 3);
|
||||
if (value < MT_NULL || value >= NUMMOBJTYPES)
|
||||
return luaL_error(L, "type number %d is invalid.", value);
|
||||
props->type = luaL_checkinteger(L, 3);
|
||||
}
|
||||
else if (i == 2 || (str && fastcmp(str, "effects")))
|
||||
{
|
||||
props->effects = luaL_checkinteger(L, 3);
|
||||
}
|
||||
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// #precipprops -> MAXPRECIP
|
||||
static int lib_precippropslen(lua_State *L)
|
||||
{
|
||||
lua_pushinteger(L, MAXPRECIP);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// precipprops_t *, field -> number
|
||||
static int precipprops_get(lua_State *L)
|
||||
{
|
||||
precipprops_t *props = *((precipprops_t **)luaL_checkudata(L, 1, META_PRECIPPROPS));
|
||||
const char *field = luaL_checkstring(L, 2);
|
||||
|
||||
I_Assert(props != NULL);
|
||||
I_Assert(props >= precipprops);
|
||||
|
||||
if (fastcmp(field, "type"))
|
||||
{
|
||||
lua_pushinteger(L, props->type);
|
||||
}
|
||||
else if (fastcmp(field,"effects"))
|
||||
{
|
||||
lua_pushinteger(L, props->effects);
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Debug(DBG_LUA, M_GetText("'%s' has no field named '%s'; returning nil.\n"), "precipprops_t", field);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// precipprops_t *, field, number -> precipprops[]
|
||||
static int precipprops_set(lua_State *L)
|
||||
{
|
||||
precipprops_t *props = *((precipprops_t **)luaL_checkudata(L, 1, META_PRECIPPROPS));
|
||||
const char *field = luaL_checkstring(L, 2);
|
||||
|
||||
if (hud_running)
|
||||
return luaL_error(L, "Do not alter precipprops in HUD rendering code!");
|
||||
if (hook_cmd_running)
|
||||
return luaL_error(L, "Do not alter precipprops in CMD building code!");
|
||||
|
||||
I_Assert(props != NULL);
|
||||
I_Assert(props >= precipprops);
|
||||
|
||||
if (fastcmp(field, "type"))
|
||||
{
|
||||
props->type = luaL_checkinteger(L, 3);
|
||||
}
|
||||
else if (fastcmp(field, "effects"))
|
||||
{
|
||||
props->effects = luaL_checkinteger(L, 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
return luaL_error(L, LUA_QL("precipprops_t") " has no field named " LUA_QS, field);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// precipprops_t * -> PRECIP_*
|
||||
static int precipprops_num(lua_State *L)
|
||||
{
|
||||
precipprops_t *props = *((precipprops_t **)luaL_checkudata(L, 1, META_PRECIPPROPS));
|
||||
|
||||
I_Assert(props != NULL);
|
||||
I_Assert(props >= precipprops);
|
||||
|
||||
lua_pushinteger(L, props - precipprops);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//
|
||||
// Now push all these functions into the Lua state!
|
||||
|
|
@ -1861,6 +2006,17 @@ int LUA_InfoLib(lua_State *L)
|
|||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
luaL_newmetatable(L, META_PRECIPPROPS);
|
||||
lua_pushcfunction(L, precipprops_get);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, precipprops_set);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, precipprops_num);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_pop(L, 1);
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getSprname);
|
||||
|
|
@ -1961,6 +2117,19 @@ int LUA_InfoLib(lua_State *L)
|
|||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "spriteinfo");
|
||||
|
||||
lua_newuserdata(L, 0);
|
||||
lua_createtable(L, 0, 2);
|
||||
lua_pushcfunction(L, lib_getPrecipProps);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
||||
lua_pushcfunction(L, lib_setPrecipProps);
|
||||
lua_setfield(L, -2, "__newindex");
|
||||
|
||||
lua_pushcfunction(L, lib_precippropslen);
|
||||
lua_setfield(L, -2, "__len");
|
||||
lua_setmetatable(L, -2);
|
||||
lua_setglobal(L, "precipprops");
|
||||
|
||||
luaL_newmetatable(L, META_LUABANKS);
|
||||
lua_pushcfunction(L, lib_getluabanks);
|
||||
lua_setfield(L, -2, "__index");
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ extern lua_State *gL;
|
|||
#define META_SPRITEINFO "SPRITEINFO_T*"
|
||||
#define META_PIVOTLIST "SPRITEFRAMEPIVOT_T[]"
|
||||
#define META_FRAMEPIVOT "SPRITEFRAMEPIVOT_T*"
|
||||
#define META_PRECIPPROPS "PRECIPPROPS_T*"
|
||||
|
||||
#define META_TAGLIST "TAGLIST"
|
||||
|
||||
|
|
|
|||
|
|
@ -446,6 +446,8 @@ static int player_get(lua_State *L)
|
|||
lua_pushinteger(L, plr->realtime);
|
||||
else if (fastcmp(field,"laps"))
|
||||
lua_pushinteger(L, plr->laps);
|
||||
else if (fastcmp(field,"latestlap"))
|
||||
lua_pushinteger(L, plr->latestlap);
|
||||
else if (fastcmp(field,"ctfteam"))
|
||||
lua_pushinteger(L, plr->ctfteam);
|
||||
else if (fastcmp(field,"checkskip"))
|
||||
|
|
@ -786,6 +788,8 @@ static int player_set(lua_State *L)
|
|||
plr->realtime = (tic_t)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"laps"))
|
||||
plr->laps = (UINT8)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"latestlap"))
|
||||
plr->latestlap = (UINT8)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"ctfteam"))
|
||||
plr->ctfteam = (INT32)luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"checkskip"))
|
||||
|
|
|
|||
|
|
@ -391,7 +391,7 @@ int LUA_PushGlobals(lua_State *L, const char *word)
|
|||
lua_pushinteger(L, mapobjectscale);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"numlaps")) {
|
||||
lua_pushinteger(L, cv_numlaps.value);
|
||||
lua_pushinteger(L, numlaps);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"racecountdown")) {
|
||||
lua_pushinteger(L, racecountdown);
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ static CV_PossibleValue_t masterserver_update_rate_cons_t[] = {
|
|||
};
|
||||
|
||||
consvar_t cv_masterserver = CVAR_INIT ("masterserver", "https://ms.kartkrew.org/ms/api", CV_SAVE|CV_CALL, NULL, MasterServer_OnChange);
|
||||
consvar_t cv_rendezvousserver = CVAR_INIT ("rendezvousserver", "relay.kartkrew.org", CV_SAVE|CV_CALL, NULL, RendezvousServer_OnChange);
|
||||
consvar_t cv_rendezvousserver = CVAR_INIT ("holepunchserver", "relay.kartkrew.org", CV_SAVE|CV_CALL, NULL, RendezvousServer_OnChange);
|
||||
consvar_t cv_servername = CVAR_INIT ("servername", "Ring Racers server", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Update_parameters);
|
||||
consvar_t cv_server_contact = CVAR_INIT ("server_contact", "", CV_SAVE|CV_CALL|CV_NOINIT, NULL, Update_parameters);
|
||||
|
||||
|
|
@ -436,7 +436,7 @@ void UnregisterServer(void)
|
|||
static boolean
|
||||
Online (void)
|
||||
{
|
||||
return ( serverrunning && cv_advertise.value );
|
||||
return ( serverrunning && netgame && cv_advertise.value );
|
||||
}
|
||||
|
||||
static inline void SendPingToMasterServer(void)
|
||||
|
|
@ -534,7 +534,7 @@ Advertise_OnChange(void)
|
|||
|
||||
if (cv_advertise.value)
|
||||
{
|
||||
if (serverrunning)
|
||||
if (serverrunning && netgame)
|
||||
{
|
||||
Lock_state();
|
||||
{
|
||||
|
|
|
|||
1
src/objects/CMakeLists.txt
Normal file
1
src/objects/CMakeLists.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
target_sourcefile(c)
|
||||
|
|
@ -179,6 +179,7 @@ move_to_player (mobj_t *hyu)
|
|||
mobj_t *target = hyudoro_target(hyu);
|
||||
|
||||
angle_t angle;
|
||||
fixed_t speed;
|
||||
|
||||
if (!target)
|
||||
return;
|
||||
|
|
@ -186,8 +187,20 @@ move_to_player (mobj_t *hyu)
|
|||
angle = R_PointToAngle2(
|
||||
hyu->x, hyu->y, target->x, target->y);
|
||||
|
||||
P_InstaThrust(hyu, angle, (hyu->radius / 2) +
|
||||
max(hyu->radius, K_GetSpeed(target)));
|
||||
speed = (hyu->radius / 2) +
|
||||
max(hyu->radius, K_GetSpeed(target));
|
||||
|
||||
// For first place only: cap hyudoro speed at 50%
|
||||
// target player's kart speed
|
||||
if (target->player && target->player->position == 1)
|
||||
{
|
||||
const fixed_t normalspeed =
|
||||
K_GetKartSpeed(target->player, false, false) / 2;
|
||||
|
||||
speed = min(speed, normalspeed);
|
||||
}
|
||||
|
||||
P_InstaThrust(hyu, angle, speed);
|
||||
|
||||
hyu->z = target->z; // stay level with target
|
||||
hyu->angle = angle;
|
||||
|
|
|
|||
|
|
@ -4980,7 +4980,7 @@ void A_DetonChase(mobj_t *actor)
|
|||
fixed_t xyspeed, speed;
|
||||
|
||||
if (actor->target->player)
|
||||
speed = K_GetKartSpeed(actor->tracer->player, false);
|
||||
speed = K_GetKartSpeed(actor->tracer->player, false, false);
|
||||
else
|
||||
speed = actor->target->info->speed;
|
||||
|
||||
|
|
@ -13285,7 +13285,7 @@ void A_JawzChase(mobj_t *actor)
|
|||
{
|
||||
if (actor->tracer->player)
|
||||
{
|
||||
fixed_t speeddifference = abs(topspeed - min(actor->tracer->player->speed, K_GetKartSpeed(actor->tracer->player, false)));
|
||||
fixed_t speeddifference = abs(topspeed - min(actor->tracer->player->speed, K_GetKartSpeed(actor->tracer->player, false, false)));
|
||||
topspeed = topspeed - FixedMul(speeddifference, FRACUNIT-FixedDiv(distaway, distbarrier));
|
||||
}
|
||||
}
|
||||
|
|
@ -13607,6 +13607,12 @@ void A_SPBChase(mobj_t *actor)
|
|||
actor->lastlook = actor->tracer->player-players; // Save the player num for death scumming...
|
||||
actor->tracer->player->pflags |= PF_RINGLOCK; // set ring lock
|
||||
|
||||
if (actor->tracer->hitlag)
|
||||
{
|
||||
// If the player is frozen through no fault of their own, the SPB should be too.
|
||||
actor->hitlag = actor->tracer->hitlag;
|
||||
}
|
||||
|
||||
if (!P_IsObjectOnGround(actor->tracer))
|
||||
{
|
||||
// In the air you have no control; basically don't hit unless you make a near complete stop
|
||||
|
|
@ -13615,7 +13621,7 @@ void A_SPBChase(mobj_t *actor)
|
|||
else
|
||||
{
|
||||
// 7/8ths max speed for Knuckles, 3/4ths max speed for min accel, exactly max speed for max accel
|
||||
defspeed = FixedMul(((fracmax+1)<<FRACBITS) - easiness, K_GetKartSpeed(actor->tracer->player, false)) / fracmax;
|
||||
defspeed = FixedMul(((fracmax+1)<<FRACBITS) - easiness, K_GetKartSpeed(actor->tracer->player, false, false)) / fracmax;
|
||||
}
|
||||
|
||||
// Be fairer on conveyors
|
||||
|
|
@ -13695,7 +13701,7 @@ void A_SPBChase(mobj_t *actor)
|
|||
// Red speed lines for when it's gaining on its target. A tell for when you're starting to lose too much speed!
|
||||
if (R_PointToDist2(0, 0, actor->momx, actor->momy) > (actor->tracer->player ? (16*actor->tracer->player->speed)/15
|
||||
: (16*R_PointToDist2(0, 0, actor->tracer->momx, actor->tracer->momy))/15) // Going faster than the target
|
||||
&& xyspeed > K_GetKartSpeed(actor->tracer->player, false)/4) // Don't display speedup lines at pitifully low speeds
|
||||
&& xyspeed > K_GetKartSpeed(actor->tracer->player, false, false) / 4) // Don't display speedup lines at pitifully low speeds
|
||||
SpawnSPBSpeedLines(actor);
|
||||
|
||||
return;
|
||||
|
|
@ -14026,21 +14032,21 @@ void A_LightningFollowPlayer(mobj_t *actor)
|
|||
if (!actor->target)
|
||||
return;
|
||||
|
||||
if (actor->extravalue1) // Make the radius also follow the player somewhat accuratly
|
||||
{
|
||||
if (actor->extravalue1) // Make the radius also follow the player somewhat accuratly
|
||||
{
|
||||
sx = actor->target->x + FixedMul((actor->target->scale*actor->extravalue1), FINECOSINE((actor->angle)>>ANGLETOFINESHIFT));
|
||||
sy = actor->target->y + FixedMul((actor->target->scale*actor->extravalue1), FINESINE((actor->angle)>>ANGLETOFINESHIFT));
|
||||
P_MoveOrigin(actor, sx, sy, actor->target->z);
|
||||
}
|
||||
else // else just teleport to player directly
|
||||
P_MoveOrigin(actor, actor->target->x, actor->target->y, actor->target->z);
|
||||
|
||||
K_MatchGenericExtraFlags(actor, actor->target); // copy our target for graviflip
|
||||
actor->momx = actor->target->momx;
|
||||
actor->momy = actor->target->momy;
|
||||
actor->momz = actor->target->momz; // Give momentum since we don't teleport to our player literally every frame.
|
||||
sx = actor->target->x + FixedMul((actor->target->scale*actor->extravalue1), FINECOSINE((actor->angle)>>ANGLETOFINESHIFT));
|
||||
sy = actor->target->y + FixedMul((actor->target->scale*actor->extravalue1), FINESINE((actor->angle)>>ANGLETOFINESHIFT));
|
||||
P_MoveOrigin(actor, sx, sy, actor->target->z);
|
||||
}
|
||||
else // else just teleport to player directly
|
||||
{
|
||||
P_MoveOrigin(actor, actor->target->x, actor->target->y, actor->target->z);
|
||||
}
|
||||
|
||||
K_MatchGenericExtraFlags(actor, actor->target); // copy our target for graviflip
|
||||
actor->momx = actor->target->momx;
|
||||
actor->momy = actor->target->momy;
|
||||
actor->momz = actor->target->momz; // Give momentum since we don't teleport to our player literally every frame.
|
||||
}
|
||||
|
||||
// A_FZBoomFlash:
|
||||
|
|
|
|||
|
|
@ -792,16 +792,11 @@ boolean P_CheckRacers(void)
|
|||
boolean eliminatelast = cv_karteliminatelast.value;
|
||||
boolean everyonedone = true;
|
||||
boolean eliminatebots = false;
|
||||
boolean griefed = false;
|
||||
const boolean griefed = (spectateGriefed > 0);
|
||||
|
||||
// Check if all the players in the race have finished. If so, end the level.
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (nospectategrief[i] != -1) // prevent spectate griefing
|
||||
{
|
||||
griefed = true;
|
||||
}
|
||||
|
||||
if (!playeringame[i] || players[i].spectator || players[i].lives <= 0) // Not playing
|
||||
{
|
||||
// Y'all aren't even playing
|
||||
|
|
@ -922,7 +917,7 @@ boolean P_CheckRacers(void)
|
|||
// We're still playing, but no one else is, so we need to reset spectator griefing.
|
||||
if (numplayersingame <= 1)
|
||||
{
|
||||
memset(nospectategrief, -1, sizeof (nospectategrief));
|
||||
spectateGriefed = 0;
|
||||
}
|
||||
|
||||
// Turns out we're still having a good time & playing the game, we didn't have to do anything :)
|
||||
|
|
@ -1076,6 +1071,11 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
|
||||
target->player->playerstate = PST_DEAD;
|
||||
|
||||
// respawn from where you died
|
||||
target->player->respawn.pointx = target->x;
|
||||
target->player->respawn.pointy = target->y;
|
||||
target->player->respawn.pointz = target->z;
|
||||
|
||||
if (target->player == &players[consoleplayer])
|
||||
{
|
||||
// don't die in auto map,
|
||||
|
|
@ -1403,7 +1403,7 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget
|
|||
// special behavior for ring capsules
|
||||
if (target->threshold == KITEM_SUPERRING)
|
||||
{
|
||||
player->superring = min(player->superring + 5*target->movecount*3, UINT16_MAX);
|
||||
K_AwardPlayerRings(player, 5 * target->movecount, true);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1828,7 +1828,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
boolean force = false;
|
||||
|
||||
INT32 laglength = 6;
|
||||
INT32 kinvextend = 0;
|
||||
|
||||
if (objectplacing)
|
||||
return false;
|
||||
|
|
@ -2001,9 +2000,14 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
// Extend the invincibility if the hit was a direct hit.
|
||||
if (inflictor == source && source->player->invincibilitytimer)
|
||||
{
|
||||
kinvextend = (source->player->invincibilitytimer)+5*TICRATE;
|
||||
//CONS_Printf("extend k_invincibilitytimer for %s - old value %d new value %d\n", player_names[source->player - players], source->player->invincibilitytimer/TICRATE, kinvextend/TICRATE);
|
||||
source->player->invincibilitytimer = kinvextend;
|
||||
tic_t kinvextend;
|
||||
|
||||
if (gametype == GT_BATTLE)
|
||||
kinvextend = 2*TICRATE;
|
||||
else
|
||||
kinvextend = 5*TICRATE;
|
||||
|
||||
source->player->invincibilitytimer += kinvextend;
|
||||
}
|
||||
|
||||
K_PlayHitEmSound(source, target);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@
|
|||
|
||||
//#define VIEWHEIGHTS "41"
|
||||
|
||||
// Maximum laps per map.
|
||||
#define MAX_LAPS 99
|
||||
|
||||
// Maximum player score.
|
||||
#define MAXSCORE 99999990 // 999999990
|
||||
|
||||
|
|
@ -277,6 +280,7 @@ void P_RespawnSpecials(void);
|
|||
|
||||
mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type);
|
||||
|
||||
void P_CalculatePrecipFloor(precipmobj_t *mobj);
|
||||
void P_RecalcPrecipInSector(sector_t *sector);
|
||||
void P_PrecipitationEffects(void);
|
||||
|
||||
|
|
|
|||
50
src/p_map.c
50
src/p_map.c
|
|
@ -263,9 +263,6 @@ static boolean P_SpecialIsLinedefCrossType(line_t *ld)
|
|||
{
|
||||
boolean linedefcrossspecial = false;
|
||||
|
||||
if (P_IsLineTripWire(ld))
|
||||
return true;
|
||||
|
||||
switch (ld->special)
|
||||
{
|
||||
case 2001: // Finish line
|
||||
|
|
@ -301,6 +298,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
UINT16 starcolor = (spring->info->painchance % numskincolors);
|
||||
fixed_t savemomx = 0;
|
||||
fixed_t savemomy = 0;
|
||||
statenum_t raisestate = spring->info->raisestate;
|
||||
|
||||
// Object was already sprung this tic
|
||||
if (object->eflags & MFE_SPRUNG)
|
||||
|
|
@ -412,8 +410,6 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
// Re-solidify
|
||||
spring->flags |= (spring->info->flags & (MF_SPRING|MF_SPECIAL));
|
||||
|
||||
P_SetMobjState(spring, spring->info->raisestate);
|
||||
|
||||
if (object->player)
|
||||
{
|
||||
if (spring->flags & MF_ENEMY) // Spring shells
|
||||
|
|
@ -421,6 +417,7 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
P_SetTarget(&spring->target, object);
|
||||
}
|
||||
|
||||
K_TumbleInterrupt(object->player);
|
||||
P_ResetPlayer(object->player);
|
||||
|
||||
object->player->springstars = max(vertispeed, horizspeed) / FRACUNIT / 2;
|
||||
|
|
@ -444,8 +441,37 @@ boolean P_DoSpring(mobj_t *spring, mobj_t *object)
|
|||
{
|
||||
object->player->tiregrease = greasetics;
|
||||
}
|
||||
|
||||
if (spring->type == MT_POGOSPRING)
|
||||
{
|
||||
if (spring->reactiontime == 0)
|
||||
{
|
||||
object->player->tricktime = 0; // Reset post-hitlag timer
|
||||
// Setup the boost for potential upwards trick, at worse, make it your regular max speed. (boost = curr speed*1.25)
|
||||
object->player->trickboostpower = max(FixedDiv(object->player->speed, K_GetKartSpeed(object->player, false, false)) - FRACUNIT, 0)*125/100;
|
||||
//CONS_Printf("Got boost: %d%\n", mo->player->trickboostpower*100 / FRACUNIT);
|
||||
object->player->trickpanel = 1;
|
||||
object->player->pflags |= PF_TRICKDELAY;
|
||||
}
|
||||
else
|
||||
{
|
||||
raisestate = spring->info->seestate;
|
||||
|
||||
object->player->tumbleBounces = 1;
|
||||
object->player->pflags &= ~PF_TUMBLESOUND;
|
||||
object->player->tumbleHeight = 50;
|
||||
P_SetPlayerMobjState(object->player->mo, S_KART_SPINOUT);
|
||||
|
||||
// FIXME: try to compensate tumbling gravity
|
||||
object->momz = 3 * object->momz / 2;
|
||||
}
|
||||
|
||||
spring->reactiontime++;
|
||||
}
|
||||
}
|
||||
|
||||
P_SetMobjState(spring, raisestate);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1675,6 +1701,20 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld)
|
|||
{
|
||||
add_spechit(ld);
|
||||
}
|
||||
else if (P_IsLineTripWire(ld))
|
||||
{
|
||||
fixed_t textop, texbottom;
|
||||
|
||||
P_GetMidtextureTopBottom(ld, tmx, tmy,
|
||||
&textop, &texbottom);
|
||||
|
||||
/* The effect handling is done later but it won't
|
||||
know the height values anymore. So don't even add
|
||||
this line to the list unless this thing clips the
|
||||
tripwire's midtexture. */
|
||||
if (tmthing->z <= textop && thingtop >= texbottom)
|
||||
add_spechit(ld);
|
||||
}
|
||||
|
||||
return BMIT_CONTINUE;
|
||||
}
|
||||
|
|
|
|||
117
src/p_maputl.c
117
src/p_maputl.c
|
|
@ -485,6 +485,83 @@ void P_CameraLineOpening(line_t *linedef)
|
|||
}
|
||||
}
|
||||
|
||||
boolean
|
||||
P_GetMidtextureTopBottom
|
||||
( line_t * linedef,
|
||||
fixed_t x,
|
||||
fixed_t y,
|
||||
fixed_t * return_top,
|
||||
fixed_t * return_bottom)
|
||||
{
|
||||
side_t *side = &sides[linedef->sidenum[0]];
|
||||
fixed_t textop, texbottom, texheight;
|
||||
INT32 texnum = R_GetTextureNum(side->midtexture); // make sure the texture is actually valid
|
||||
|
||||
sector_t *front = linedef->frontsector;
|
||||
sector_t *back = linedef->backsector;
|
||||
fixed_t z;
|
||||
|
||||
if (!texnum)
|
||||
return false;
|
||||
|
||||
textop = P_GetSectorCeilingZAt(front, x, y);
|
||||
texbottom = P_GetSectorFloorZAt(front, x, y);
|
||||
|
||||
if (back)
|
||||
{
|
||||
z = P_GetSectorCeilingZAt(back, x, y);
|
||||
|
||||
if (z < textop)
|
||||
textop = z;
|
||||
|
||||
z = P_GetSectorFloorZAt(back, x, y);
|
||||
|
||||
if (z > texbottom)
|
||||
texbottom = z;
|
||||
}
|
||||
|
||||
// Get the midtexture's height
|
||||
texheight = textures[texnum]->height << FRACBITS;
|
||||
|
||||
// Set texbottom and textop to the Z coordinates of the texture's boundaries
|
||||
#if 0
|
||||
// don't remove this code unless solid midtextures
|
||||
// on non-solid polyobjects should NEVER happen in the future
|
||||
if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) {
|
||||
if (linedef->flags & ML_EFFECT5 && !side->repeatcnt) { // "infinite" repeat
|
||||
texbottom = back->floorheight + side->rowoffset;
|
||||
textop = back->ceilingheight + side->rowoffset;
|
||||
} else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) {
|
||||
texbottom = back->floorheight + side->rowoffset;
|
||||
textop = texbottom + texheight*(side->repeatcnt+1);
|
||||
} else {
|
||||
textop = back->ceilingheight + side->rowoffset;
|
||||
texbottom = textop - texheight*(side->repeatcnt+1);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (linedef->flags & ML_EFFECT5 && !side->repeatcnt) { // "infinite" repeat
|
||||
texbottom += side->rowoffset;
|
||||
textop += side->rowoffset;
|
||||
} else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) {
|
||||
texbottom += side->rowoffset;
|
||||
textop = texbottom + texheight*(side->repeatcnt+1);
|
||||
} else {
|
||||
textop += side->rowoffset;
|
||||
texbottom = textop - texheight*(side->repeatcnt+1);
|
||||
}
|
||||
}
|
||||
|
||||
if (return_top)
|
||||
*return_top = textop;
|
||||
|
||||
if (return_bottom)
|
||||
*return_bottom = texbottom;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void P_LineOpening(line_t *linedef, mobj_t *mobj)
|
||||
{
|
||||
enum { FRONT, BACK };
|
||||
|
|
@ -596,45 +673,11 @@ void P_LineOpening(line_t *linedef, mobj_t *mobj)
|
|||
if ((linedef->flags & ML_EFFECT4 || (mobj->player && P_IsLineTripWire(linedef) && !K_TripwirePass(mobj->player)))
|
||||
&& !linedef->polyobj // don't do anything for polyobjects! ...for now
|
||||
) {
|
||||
side_t *side = &sides[linedef->sidenum[0]];
|
||||
fixed_t textop, texbottom, texheight;
|
||||
fixed_t textop, texbottom;
|
||||
fixed_t texmid, delta1, delta2;
|
||||
INT32 texnum = R_GetTextureNum(side->midtexture); // make sure the texture is actually valid
|
||||
|
||||
if (texnum) {
|
||||
// Get the midtexture's height
|
||||
texheight = textures[texnum]->height << FRACBITS;
|
||||
|
||||
// Set texbottom and textop to the Z coordinates of the texture's boundaries
|
||||
#if 0
|
||||
// don't remove this code unless solid midtextures
|
||||
// on non-solid polyobjects should NEVER happen in the future
|
||||
if (linedef->polyobj && (linedef->polyobj->flags & POF_TESTHEIGHT)) {
|
||||
if (linedef->flags & ML_EFFECT5 && !side->repeatcnt) { // "infinite" repeat
|
||||
texbottom = back->floorheight + side->rowoffset;
|
||||
textop = back->ceilingheight + side->rowoffset;
|
||||
} else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) {
|
||||
texbottom = back->floorheight + side->rowoffset;
|
||||
textop = texbottom + texheight*(side->repeatcnt+1);
|
||||
} else {
|
||||
textop = back->ceilingheight + side->rowoffset;
|
||||
texbottom = textop - texheight*(side->repeatcnt+1);
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (linedef->flags & ML_EFFECT5 && !side->repeatcnt) { // "infinite" repeat
|
||||
texbottom = openbottom + side->rowoffset;
|
||||
textop = opentop + side->rowoffset;
|
||||
} else if (!!(linedef->flags & ML_DONTPEGBOTTOM) ^ !!(linedef->flags & ML_EFFECT3)) {
|
||||
texbottom = openbottom + side->rowoffset;
|
||||
textop = texbottom + texheight*(side->repeatcnt+1);
|
||||
} else {
|
||||
textop = opentop + side->rowoffset;
|
||||
texbottom = textop - texheight*(side->repeatcnt+1);
|
||||
}
|
||||
}
|
||||
|
||||
if (P_GetMidtextureTopBottom(linedef, cross.x, cross.y, &textop, &texbottom))
|
||||
{
|
||||
texmid = texbottom+(textop-texbottom)/2;
|
||||
|
||||
delta1 = abs(mobj->z - texmid);
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@ void P_CreatePrecipSecNodeList(precipmobj_t *thing, fixed_t x,fixed_t y);
|
|||
boolean P_SceneryTryMove(mobj_t *thing, fixed_t x, fixed_t y);
|
||||
void P_HitSpecialLines(mobj_t *thing, fixed_t x, fixed_t y, fixed_t momx, fixed_t momy);
|
||||
|
||||
boolean P_GetMidtextureTopBottom(line_t *linedef, fixed_t x, fixed_t y, fixed_t *return_top, fixed_t *return_bottom);
|
||||
|
||||
extern fixed_t opentop, openbottom, openrange, lowfloor, highceiling;
|
||||
extern pslope_t *opentopslope, *openbottomslope;
|
||||
extern ffloor_t *openfloorrover, *openceilingrover;
|
||||
|
|
|
|||
317
src/p_mobj.c
317
src/p_mobj.c
|
|
@ -88,6 +88,15 @@ void P_AddCachedAction(mobj_t *mobj, INT32 statenum)
|
|||
actioncachehead.prev = newaction;
|
||||
}
|
||||
|
||||
static inline INT32 randomframe (mobj_t *mobj, INT32 n)
|
||||
{
|
||||
// Only mobj thinkers should use synced RNG
|
||||
if (mobj->thinker.function.acp1 == (actionf_p1)P_MobjThinker)
|
||||
return P_RandomKey(n);
|
||||
else
|
||||
return M_RandomKey(n);
|
||||
}
|
||||
|
||||
//
|
||||
// P_SetupStateAnimation
|
||||
//
|
||||
|
|
@ -118,8 +127,8 @@ static void P_SetupStateAnimation(mobj_t *mobj, state_t *st)
|
|||
}
|
||||
else if (st->frame & FF_RANDOMANIM)
|
||||
{
|
||||
mobj->frame += P_RandomKey(animlength + 1); // Random starting frame
|
||||
mobj->anim_duration -= P_RandomKey(st->var2); // Random duration for first frame
|
||||
mobj->frame += randomframe(mobj, animlength + 1); // Random starting frame
|
||||
mobj->anim_duration -= randomframe(mobj, st->var2); // Random duration for first frame
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1121,7 +1130,7 @@ fixed_t P_GetMobjGravity(mobj_t *mo)
|
|||
|
||||
if (mo->player->tumbleBounces > 0)
|
||||
{
|
||||
gravityadd = (5*gravityadd)/2;
|
||||
gravityadd = FixedMul(TUMBLEGRAVITY, gravityadd);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -2999,7 +3008,7 @@ boolean P_CanRunOnWater(player_t *player, ffloor_t *rover)
|
|||
clip > -(player->mo->height / 2) &&
|
||||
span > player->mo->height &&
|
||||
player->speed / 5 > abs(player->mo->momz) &&
|
||||
player->speed > K_GetKartSpeed(player, false) &&
|
||||
player->speed > K_GetKartSpeed(player, false, false) &&
|
||||
K_WaterRun(player) &&
|
||||
(rover->flags & FF_SWIMMABLE);
|
||||
}
|
||||
|
|
@ -3753,19 +3762,25 @@ animonly:
|
|||
P_CyclePlayerMobjState(mobj);
|
||||
}
|
||||
|
||||
static void CalculatePrecipFloor(precipmobj_t *mobj)
|
||||
void P_CalculatePrecipFloor(precipmobj_t *mobj)
|
||||
{
|
||||
// recalculate floorz each time
|
||||
const sector_t *mobjsecsubsec;
|
||||
boolean setWater = false;
|
||||
|
||||
if (mobj && mobj->subsector && mobj->subsector->sector)
|
||||
mobjsecsubsec = mobj->subsector->sector;
|
||||
else
|
||||
return;
|
||||
|
||||
mobj->precipflags &= ~PCF_INVISIBLE;
|
||||
mobj->floorz = P_GetSectorFloorZAt(mobjsecsubsec, mobj->x, mobj->y);
|
||||
mobj->ceilingz = P_GetSectorCeilingZAt(mobjsecsubsec, mobj->x, mobj->y);
|
||||
|
||||
if (mobjsecsubsec->ffloors)
|
||||
{
|
||||
ffloor_t *rover;
|
||||
fixed_t topheight;
|
||||
fixed_t height;
|
||||
|
||||
for (rover = mobjsecsubsec->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
|
|
@ -3773,14 +3788,44 @@ static void CalculatePrecipFloor(precipmobj_t *mobj)
|
|||
if (!(rover->flags & FF_EXISTS))
|
||||
continue;
|
||||
|
||||
if (!(rover->flags & FF_BLOCKOTHERS) && !(rover->flags & FF_SWIMMABLE))
|
||||
continue;
|
||||
if (precipprops[curWeather].effects & PRECIPFX_WATERPARTICLES)
|
||||
{
|
||||
if (!(rover->flags & FF_SWIMMABLE))
|
||||
continue;
|
||||
|
||||
topheight = P_GetFFloorTopZAt(rover, mobj->x, mobj->y);
|
||||
if (topheight > mobj->floorz)
|
||||
mobj->floorz = topheight;
|
||||
if (setWater == false)
|
||||
{
|
||||
mobj->ceilingz = P_GetFFloorTopZAt(rover, mobj->x, mobj->y);
|
||||
mobj->floorz = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y);
|
||||
setWater = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
height = P_GetFFloorTopZAt(rover, mobj->x, mobj->y);
|
||||
if (height > mobj->ceilingz)
|
||||
mobj->ceilingz = height;
|
||||
|
||||
height = P_GetFFloorBottomZAt(rover, mobj->x, mobj->y);
|
||||
if (height < mobj->floorz)
|
||||
mobj->floorz = height;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!(rover->flags & FF_BLOCKOTHERS) && !(rover->flags & FF_SWIMMABLE))
|
||||
continue;
|
||||
|
||||
height = P_GetFFloorTopZAt(rover, mobj->x, mobj->y);
|
||||
if (height > mobj->floorz)
|
||||
mobj->floorz = height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((precipprops[curWeather].effects & PRECIPFX_WATERPARTICLES) && setWater == false)
|
||||
{
|
||||
mobj->precipflags |= PCF_INVISIBLE;
|
||||
}
|
||||
}
|
||||
|
||||
void P_RecalcPrecipInSector(sector_t *sector)
|
||||
|
|
@ -3793,7 +3838,7 @@ void P_RecalcPrecipInSector(sector_t *sector)
|
|||
sector->moved = true; // Recalc lighting and things too, maybe
|
||||
|
||||
for (psecnode = sector->touching_preciplist; psecnode; psecnode = psecnode->m_thinglist_next)
|
||||
CalculatePrecipFloor(psecnode->m_thing);
|
||||
P_CalculatePrecipFloor(psecnode->m_thing);
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -3805,11 +3850,12 @@ void P_NullPrecipThinker(precipmobj_t *mobj)
|
|||
{
|
||||
//(void)mobj;
|
||||
mobj->precipflags &= ~PCF_THUNK;
|
||||
R_ResetPrecipitationMobjInterpolationState(mobj);
|
||||
}
|
||||
|
||||
void P_PrecipThinker(precipmobj_t *mobj)
|
||||
{
|
||||
R_ResetPrecipitationMobjInterpolationState(mobj);
|
||||
boolean flip = (mobj->precipflags & PCF_FLIP);
|
||||
|
||||
P_CycleStateAnimation((mobj_t *)mobj);
|
||||
|
||||
|
|
@ -3817,9 +3863,10 @@ void P_PrecipThinker(precipmobj_t *mobj)
|
|||
{
|
||||
// Reset to ceiling!
|
||||
P_SetPrecipMobjState(mobj, mobj->info->spawnstate);
|
||||
mobj->z = mobj->ceilingz;
|
||||
mobj->momz = mobj->info->speed;
|
||||
mobj->z = (flip) ? (mobj->floorz) : (mobj->ceilingz);
|
||||
mobj->momz = FixedMul(-mobj->info->speed, mapobjectscale);
|
||||
mobj->precipflags &= ~PCF_SPLASH;
|
||||
R_ResetPrecipitationMobjInterpolationState(mobj);
|
||||
}
|
||||
|
||||
if (mobj->tics != -1)
|
||||
|
|
@ -3851,18 +3898,20 @@ void P_PrecipThinker(precipmobj_t *mobj)
|
|||
if (mobj->precipflags & PCF_SPLASH)
|
||||
return;
|
||||
|
||||
mobj->z += mobj->momz;
|
||||
|
||||
// adjust height
|
||||
if ((mobj->z += mobj->momz) <= mobj->floorz)
|
||||
if ((flip) ? (mobj->z >= mobj->ceilingz) : (mobj->z <= mobj->floorz))
|
||||
{
|
||||
if ((mobj->info->deathstate == S_NULL) || (mobj->precipflags & PCF_PIT)) // no splashes on sky or bottomless pits
|
||||
{
|
||||
mobj->z = mobj->ceilingz;
|
||||
mobj->z = (flip) ? (mobj->floorz) : (mobj->ceilingz);
|
||||
R_ResetPrecipitationMobjInterpolationState(mobj);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_SetPrecipMobjState(mobj, mobj->info->deathstate);
|
||||
mobj->z = mobj->floorz;
|
||||
mobj->z = (flip) ? (mobj->ceilingz) : (mobj->floorz);
|
||||
mobj->precipflags |= PCF_SPLASH;
|
||||
R_ResetPrecipitationMobjInterpolationState(mobj);
|
||||
}
|
||||
|
|
@ -9716,6 +9765,7 @@ static void P_DefaultMobjShadowScale(mobj_t *thing)
|
|||
case MT_BLUESPHERE:
|
||||
case MT_EMERALD:
|
||||
case MT_ITEMCAPSULE:
|
||||
case MT_POGOSPRING:
|
||||
thing->shadowscale = FRACUNIT/2;
|
||||
break;
|
||||
case MT_DRIFTCLIP:
|
||||
|
|
@ -9966,6 +10016,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
mobj->color = BALLOONCOLORS[P_RandomKey(sizeof(BALLOONCOLORS))];
|
||||
}
|
||||
break;
|
||||
case MT_POGOSPRING:
|
||||
P_SetScale(mobj, (mobj->destscale = 3 * mobj->destscale / 2));
|
||||
break;
|
||||
case MT_KART_LEFTOVER:
|
||||
mobj->color = SKINCOLOR_RED;
|
||||
break;
|
||||
|
|
@ -10334,8 +10387,8 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
|
|||
{
|
||||
const mobjinfo_t *info = &mobjinfo[type];
|
||||
state_t *st;
|
||||
fixed_t start_z = INT32_MIN;
|
||||
precipmobj_t *mobj = Z_Calloc(sizeof (*mobj), PU_LEVEL, NULL);
|
||||
fixed_t starting_floorz;
|
||||
|
||||
mobj->type = type;
|
||||
mobj->info = info;
|
||||
|
|
@ -10357,26 +10410,43 @@ static precipmobj_t *P_SpawnPrecipMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype
|
|||
// set subsector and/or block links
|
||||
P_SetPrecipitationThingPosition(mobj);
|
||||
|
||||
mobj->floorz = starting_floorz = P_GetSectorFloorZAt (mobj->subsector->sector, x, y);
|
||||
mobj->ceilingz = P_GetSectorCeilingZAt(mobj->subsector->sector, x, y);
|
||||
mobj->floorz = P_GetSectorFloorZAt (mobj->subsector->sector, x, y);
|
||||
mobj->ceilingz = P_GetSectorCeilingZAt(mobj->subsector->sector, x, y);
|
||||
|
||||
mobj->floorrover = NULL;
|
||||
mobj->ceilingrover = NULL;
|
||||
|
||||
mobj->z = z;
|
||||
mobj->momz = info->speed;
|
||||
mobj->momz = FixedMul(-info->speed, mapobjectscale);
|
||||
|
||||
if (info->speed < 0)
|
||||
{
|
||||
mobj->precipflags |= PCF_FLIP;
|
||||
}
|
||||
|
||||
start_z = mobj->floorz;
|
||||
|
||||
mobj->thinker.function.acp1 = (actionf_p1)P_NullPrecipThinker;
|
||||
P_AddThinker(THINK_PRECIP, &mobj->thinker);
|
||||
|
||||
CalculatePrecipFloor(mobj);
|
||||
P_CalculatePrecipFloor(mobj);
|
||||
|
||||
if (mobj->floorz != starting_floorz)
|
||||
mobj->precipflags |= PCF_FOF;
|
||||
else if (GETSECSPECIAL(mobj->subsector->sector->special, 1) == 7
|
||||
|| GETSECSPECIAL(mobj->subsector->sector->special, 1) == 6
|
||||
|| mobj->subsector->sector->floorpic == skyflatnum)
|
||||
mobj->precipflags |= PCF_PIT;
|
||||
if (mobj->floorz != start_z)
|
||||
{
|
||||
; //mobj->precipflags |= PCF_FOF;
|
||||
}
|
||||
else
|
||||
{
|
||||
INT32 special = GETSECSPECIAL(mobj->subsector->sector->special, 1);
|
||||
boolean sFlag = (mobj->precipflags & PCF_FLIP) ? (mobj->subsector->sector->flags & SF_FLIPSPECIAL_CEILING) : (mobj->subsector->sector->flags & SF_FLIPSPECIAL_FLOOR);
|
||||
boolean pitFloor = ((special == 6 || special == 7) && sFlag);
|
||||
boolean skyFloor = (mobj->precipflags & PCF_FLIP) ? (mobj->subsector->sector->ceilingpic == skyflatnum) : (mobj->subsector->sector->floorpic == skyflatnum);
|
||||
|
||||
if (pitFloor || skyFloor)
|
||||
{
|
||||
mobj->precipflags |= PCF_PIT;
|
||||
}
|
||||
}
|
||||
|
||||
R_ResetPrecipitationMobjInterpolationState(mobj);
|
||||
|
||||
|
|
@ -10578,16 +10648,121 @@ static CV_PossibleValue_t respawnitemtime_cons_t[] = {{1, "MIN"}, {300, "MAX"},
|
|||
consvar_t cv_itemrespawntime = CVAR_INIT ("respawnitemtime", "2", CV_NETVAR|CV_CHEAT, respawnitemtime_cons_t, NULL);
|
||||
consvar_t cv_itemrespawn = CVAR_INIT ("respawnitem", "On", CV_NETVAR, CV_OnOff, NULL);
|
||||
|
||||
void P_SpawnPrecipitation(void)
|
||||
static void P_SpawnPrecipitationAt(fixed_t basex, fixed_t basey)
|
||||
{
|
||||
INT32 i, j, k;
|
||||
mobjtype_t type = precipprops[curWeather].type;
|
||||
UINT8 randomstates = (UINT8)mobjinfo[type].damage;
|
||||
fixed_t basex, basey, x, y, z, height;
|
||||
INT32 j, k;
|
||||
|
||||
const mobjtype_t type = precipprops[curWeather].type;
|
||||
const UINT8 randomstates = (UINT8)mobjinfo[type].damage;
|
||||
const boolean flip = (mobjinfo[type].speed < 0);
|
||||
|
||||
fixed_t i, x, y, z, height;
|
||||
|
||||
UINT16 numparticles = 0;
|
||||
boolean condition = false;
|
||||
|
||||
subsector_t *precipsector = NULL;
|
||||
precipmobj_t *rainmo = NULL;
|
||||
|
||||
if (dedicated || !cv_drawdist_precip.value || curWeather == PRECIP_NONE) // SRB2Kart
|
||||
// If mobjscale < FRACUNIT, each blockmap cell covers
|
||||
// more area so spawn more precipitation in that area.
|
||||
for (i = 0; i < FRACUNIT; i += mapobjectscale)
|
||||
{
|
||||
x = basex + ((M_RandomKey(MAPBLOCKUNITS << 3) << FRACBITS) >> 3);
|
||||
y = basey + ((M_RandomKey(MAPBLOCKUNITS << 3) << FRACBITS) >> 3);
|
||||
|
||||
precipsector = R_PointInSubsectorOrNull(x, y);
|
||||
|
||||
// No sector? Stop wasting time,
|
||||
// move on to the next entry in the blockmap
|
||||
if (!precipsector)
|
||||
continue;
|
||||
|
||||
// Not in a sector with visible sky?
|
||||
if (precipprops[curWeather].effects & PRECIPFX_WATERPARTICLES)
|
||||
{
|
||||
condition = false;
|
||||
|
||||
if (precipsector->sector->ffloors)
|
||||
{
|
||||
ffloor_t *rover;
|
||||
|
||||
for (rover = precipsector->sector->ffloors; rover; rover = rover->next)
|
||||
{
|
||||
if (!(rover->flags & FF_EXISTS))
|
||||
continue;
|
||||
|
||||
if (!(rover->flags & FF_SWIMMABLE))
|
||||
continue;
|
||||
|
||||
condition = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
condition = (precipsector->sector->ceilingpic == skyflatnum);
|
||||
}
|
||||
|
||||
if (precipsector->sector->flags & SF_INVERTPRECIP)
|
||||
{
|
||||
condition = !condition;
|
||||
}
|
||||
|
||||
if (!condition)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
height = precipsector->sector->ceilingheight - precipsector->sector->floorheight;
|
||||
height = FixedDiv(height, mapobjectscale);
|
||||
|
||||
// Exists, but is too small for reasonable precipitation.
|
||||
if (height < 64<<FRACBITS)
|
||||
continue;
|
||||
|
||||
// Hack around a quirk of this entire system, where taller sectors look like they get less precipitation.
|
||||
numparticles = 1 + (height / (MAPBLOCKUNITS<<4<<FRACBITS));
|
||||
|
||||
// Don't set z properly yet...
|
||||
z = (flip) ? (precipsector->sector->floorheight) : (precipsector->sector->ceilingheight);
|
||||
|
||||
for (j = 0; j < numparticles; j++)
|
||||
{
|
||||
rainmo = P_SpawnPrecipMobj(x, y, z, type);
|
||||
|
||||
if (randomstates > 0)
|
||||
{
|
||||
UINT8 mrand = M_RandomByte();
|
||||
UINT8 threshold = UINT8_MAX / (randomstates + 1);
|
||||
statenum_t st = mobjinfo[type].spawnstate;
|
||||
|
||||
for (k = 0; k < randomstates; k++)
|
||||
{
|
||||
if (mrand < (threshold * (k+1)))
|
||||
{
|
||||
P_SetPrecipMobjState(rainmo, st+k+1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Randomly assign a height, now that floorz is set.
|
||||
rainmo->z = M_RandomRange(rainmo->floorz >> FRACBITS, rainmo->ceilingz >> FRACBITS) << FRACBITS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void P_SpawnPrecipitation(void)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
const mobjtype_t type = precipprops[curWeather].type;
|
||||
|
||||
fixed_t basex, basey;
|
||||
|
||||
if (dedicated || !cv_drawdist_precip.value || type == MT_NULL)
|
||||
return;
|
||||
|
||||
// Use the blockmap to narrow down our placing patterns
|
||||
|
|
@ -10596,59 +10771,7 @@ void P_SpawnPrecipitation(void)
|
|||
basex = bmaporgx + (i % bmapwidth) * MAPBLOCKSIZE;
|
||||
basey = bmaporgy + (i / bmapwidth) * MAPBLOCKSIZE;
|
||||
|
||||
{
|
||||
UINT16 numparticles = 0;
|
||||
|
||||
x = basex + ((M_RandomKey(MAPBLOCKUNITS<<3)<<FRACBITS)>>3);
|
||||
y = basey + ((M_RandomKey(MAPBLOCKUNITS<<3)<<FRACBITS)>>3);
|
||||
|
||||
precipsector = R_PointInSubsectorOrNull(x, y);
|
||||
|
||||
// No sector? Stop wasting time,
|
||||
// move on to the next entry in the blockmap
|
||||
if (!precipsector)
|
||||
continue;
|
||||
|
||||
// Not in a sector with visible sky?
|
||||
if (precipsector->sector->ceilingpic != skyflatnum)
|
||||
continue;
|
||||
|
||||
height = precipsector->sector->ceilingheight - precipsector->sector->floorheight;
|
||||
|
||||
// Exists, but is too small for reasonable precipitation.
|
||||
if (height < 64<<FRACBITS)
|
||||
continue;
|
||||
|
||||
// Hack around a quirk of this entire system, where taller sectors look like they get less precipitation.
|
||||
numparticles = 1 + (height / (MAPBLOCKUNITS<<4<<FRACBITS));
|
||||
|
||||
// Don't set z properly yet...
|
||||
z = precipsector->sector->ceilingheight;
|
||||
|
||||
for (j = 0; j < numparticles; j++)
|
||||
{
|
||||
rainmo = P_SpawnPrecipMobj(x, y, z, type);
|
||||
|
||||
if (randomstates > 0)
|
||||
{
|
||||
UINT8 mrand = M_RandomByte();
|
||||
UINT8 threshold = UINT8_MAX / (randomstates + 1);
|
||||
statenum_t st = mobjinfo[type].spawnstate;
|
||||
|
||||
for (k = 0; k < randomstates; k++)
|
||||
{
|
||||
if (mrand < (threshold * (k+1)))
|
||||
{
|
||||
P_SetPrecipMobjState(rainmo, st+k+1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Randomly assign a height, now that floorz is set.
|
||||
rainmo->z = M_RandomRange(rainmo->floorz>>FRACBITS, rainmo->ceilingz>>FRACBITS)<<FRACBITS;
|
||||
}
|
||||
}
|
||||
P_SpawnPrecipitationAt(basex, basey);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -10878,16 +11001,20 @@ void P_RespawnSpecials(void)
|
|||
else
|
||||
{
|
||||
if (pcount == 1) // No respawn when alone
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (pcount > 1)
|
||||
{
|
||||
time = (120 - ((pcount-2) * 10)) * TICRATE;
|
||||
time = (120 - ((pcount-2) * 20)) * TICRATE;
|
||||
|
||||
// If the map is longer or shorter than 3 laps, then adjust ring respawn to account for this.
|
||||
// 5 lap courses would have more retreaded ground, while 2 lap courses would have less.
|
||||
if ((mapheaderinfo[gamemap-1]->numlaps != 3)
|
||||
&& !(mapheaderinfo[gamemap-1]->levelflags & LF_SECTIONRACE))
|
||||
&& !(mapheaderinfo[gamemap-1]->levelflags & LF_SECTIONRACE))
|
||||
{
|
||||
time = (time * 3) / max(1, mapheaderinfo[gamemap-1]->numlaps);
|
||||
}
|
||||
|
||||
if (time < 10*TICRATE)
|
||||
{
|
||||
|
|
@ -11243,8 +11370,6 @@ void P_MovePlayerToStarpost(INT32 playernum)
|
|||
mobj_t *mobj = p->mo;
|
||||
I_Assert(mobj != NULL);
|
||||
|
||||
K_DoIngameRespawn(p);
|
||||
|
||||
P_UnsetThingPosition(mobj);
|
||||
mobj->x = p->respawn.pointx;
|
||||
mobj->y = p->respawn.pointy;
|
||||
|
|
@ -11286,6 +11411,11 @@ void P_MovePlayerToStarpost(INT32 playernum)
|
|||
else
|
||||
p->drawangle = mobj->angle; // default to the camera angle
|
||||
|
||||
K_DoIngameRespawn(p);
|
||||
p->respawn.truedeath = true;
|
||||
|
||||
mobj->renderflags |= RF_DONTDRAW;
|
||||
|
||||
P_AfterPlayerSpawn(playernum);
|
||||
}
|
||||
|
||||
|
|
@ -13482,9 +13612,6 @@ mobj_t *P_SpawnMobjFromMobj(mobj_t *mobj, fixed_t xofs, fixed_t yofs, fixed_t zo
|
|||
newmobj->old_z2 = mobj->old_z2 + zofs;
|
||||
}
|
||||
|
||||
newmobj->destscale = mobj->destscale;
|
||||
P_SetScale(newmobj, mobj->scale);
|
||||
|
||||
newmobj->old_x2 = mobj->old_x2 + xofs;
|
||||
newmobj->old_y2 = mobj->old_y2 + yofs;
|
||||
newmobj->old_x = mobj->old_x + xofs;
|
||||
|
|
|
|||
15
src/p_mobj.h
15
src/p_mobj.h
|
|
@ -262,12 +262,11 @@ typedef enum
|
|||
// PRECIPITATION flags ?! ?! ?!
|
||||
//
|
||||
typedef enum {
|
||||
PCF_INVISIBLE = 1, // Don't draw.
|
||||
PCF_PIT = 1<<1, // Above pit.
|
||||
PCF_FOF = 1<<2, // Above FOF.
|
||||
PCF_MOVINGFOF = 1<<3, // Above MOVING FOF (this means we need to keep floorz up to date...)
|
||||
PCF_SPLASH = 1<<4, // Splashed on the ground, return to the ceiling after the animation's over
|
||||
PCF_THUNK = 1<<5, // Ran the thinker this tic.
|
||||
PCF_THUNK = 1, // Ran the thinker this tic.
|
||||
PCF_SPLASH = 1<<1, // Splashed on the ground, return to the ceiling after the animation's over
|
||||
PCF_INVISIBLE = 1<<2, // Don't draw.
|
||||
PCF_PIT = 1<<3, // Above pit.
|
||||
PCF_FLIP = 1<<4, // Spawning from floor, moving upwards.
|
||||
} precipflag_t;
|
||||
|
||||
// Map Object definition.
|
||||
|
|
@ -462,6 +461,8 @@ typedef struct precipmobj_s
|
|||
fixed_t ceilingz; // Nearest ceiling above.
|
||||
struct ffloor_s *floorrover; // FOF referred by floorz
|
||||
struct ffloor_s *ceilingrover; // FOF referred by ceilingz
|
||||
fixed_t floordrop;
|
||||
fixed_t ceilingdrop;
|
||||
|
||||
// For movement checking.
|
||||
fixed_t radius; // Fixed at 2*FRACUNIT
|
||||
|
|
@ -473,7 +474,7 @@ typedef struct precipmobj_s
|
|||
|
||||
INT32 tics; // state tic counter
|
||||
state_t *state;
|
||||
INT32 flags; // flags from mobjinfo tables
|
||||
UINT32 flags; // flags from mobjinfo tables
|
||||
} precipmobj_t;
|
||||
|
||||
typedef struct actioncache_s
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ static void P_NetArchivePlayers(void)
|
|||
{
|
||||
WRITEINT16(save_p, clientpowerlevels[i][j]);
|
||||
}
|
||||
WRITEINT16(save_p, clientPowerAdd[i]);
|
||||
|
||||
if (!playeringame[i])
|
||||
continue;
|
||||
|
|
@ -167,6 +168,7 @@ static void P_NetArchivePlayers(void)
|
|||
WRITEINT16(save_p, players[i].totalring);
|
||||
WRITEUINT32(save_p, players[i].realtime);
|
||||
WRITEUINT8(save_p, players[i].laps);
|
||||
WRITEUINT8(save_p, players[i].latestlap);
|
||||
WRITEINT32(save_p, players[i].starpostnum);
|
||||
|
||||
WRITEUINT8(save_p, players[i].ctfteam);
|
||||
|
|
@ -373,11 +375,14 @@ static void P_NetArchivePlayers(void)
|
|||
WRITEUINT32(save_p, players[i].respawn.airtimer);
|
||||
WRITEUINT32(save_p, players[i].respawn.distanceleft);
|
||||
WRITEUINT32(save_p, players[i].respawn.dropdash);
|
||||
WRITEUINT8(save_p, players[i].respawn.truedeath);
|
||||
|
||||
// botvars_t
|
||||
WRITEUINT8(save_p, players[i].botvars.difficulty);
|
||||
WRITEUINT8(save_p, players[i].botvars.diffincrease);
|
||||
WRITEUINT8(save_p, players[i].botvars.rival);
|
||||
WRITEFIXED(save_p, players[i].botvars.rubberband);
|
||||
WRITEUINT16(save_p, players[i].botvars.controller);
|
||||
WRITEUINT32(save_p, players[i].botvars.itemdelay);
|
||||
WRITEUINT32(save_p, players[i].botvars.itemconfirm);
|
||||
WRITESINT8(save_p, players[i].botvars.turnconfirm);
|
||||
|
|
@ -401,6 +406,7 @@ static void P_NetUnArchivePlayers(void)
|
|||
{
|
||||
clientpowerlevels[i][j] = READINT16(save_p);
|
||||
}
|
||||
clientPowerAdd[i] = READINT16(save_p);
|
||||
|
||||
// Do NOT memset player struct to 0
|
||||
// other areas may initialize data elsewhere
|
||||
|
|
@ -463,6 +469,7 @@ static void P_NetUnArchivePlayers(void)
|
|||
players[i].totalring = READINT16(save_p); // Total number of rings obtained for GP
|
||||
players[i].realtime = READUINT32(save_p); // integer replacement for leveltime
|
||||
players[i].laps = READUINT8(save_p); // Number of laps (optional)
|
||||
players[i].latestlap = READUINT8(save_p);
|
||||
players[i].starpostnum = READINT32(save_p);
|
||||
|
||||
players[i].ctfteam = READUINT8(save_p); // 1 == Red, 2 == Blue
|
||||
|
|
@ -652,11 +659,14 @@ static void P_NetUnArchivePlayers(void)
|
|||
players[i].respawn.airtimer = READUINT32(save_p);
|
||||
players[i].respawn.distanceleft = READUINT32(save_p);
|
||||
players[i].respawn.dropdash = READUINT32(save_p);
|
||||
players[i].respawn.truedeath = READUINT8(save_p);
|
||||
|
||||
// botvars_t
|
||||
players[i].botvars.difficulty = READUINT8(save_p);
|
||||
players[i].botvars.diffincrease = READUINT8(save_p);
|
||||
players[i].botvars.rival = (boolean)READUINT8(save_p);
|
||||
players[i].botvars.rubberband = READFIXED(save_p);
|
||||
players[i].botvars.controller = READUINT16(save_p);
|
||||
players[i].botvars.itemdelay = READUINT32(save_p);
|
||||
players[i].botvars.itemconfirm = READUINT32(save_p);
|
||||
players[i].botvars.turnconfirm = READSINT8(save_p);
|
||||
|
|
@ -3137,6 +3147,8 @@ static thinker_t* LoadMobjThinker(actionf_p1 thinker)
|
|||
slope->normal.x = READFIXED(save_p);
|
||||
slope->normal.y = READFIXED(save_p);
|
||||
slope->normal.z = READFIXED(save_p);
|
||||
|
||||
P_UpdateSlopeLightOffset(slope);
|
||||
}
|
||||
if (diff2 & MD2_HITLAG)
|
||||
{
|
||||
|
|
@ -4487,6 +4499,7 @@ static void P_NetArchiveMisc(boolean resending)
|
|||
WRITEUINT8(save_p, battlecapsules);
|
||||
|
||||
WRITEUINT8(save_p, gamespeed);
|
||||
WRITEUINT8(save_p, numlaps);
|
||||
WRITEUINT8(save_p, franticitems);
|
||||
WRITEUINT8(save_p, comeback);
|
||||
|
||||
|
|
@ -4507,8 +4520,7 @@ static void P_NetArchiveMisc(boolean resending)
|
|||
WRITEUINT32(save_p, indirectitemcooldown);
|
||||
WRITEUINT32(save_p, mapreset);
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
WRITEINT16(save_p, nospectategrief[i]);
|
||||
WRITEUINT8(save_p, spectateGriefed);
|
||||
|
||||
WRITEUINT8(save_p, thwompsactive);
|
||||
WRITEUINT8(save_p, lastLowestLap);
|
||||
|
|
@ -4636,6 +4648,7 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
|
|||
battlecapsules = (boolean)READUINT8(save_p);
|
||||
|
||||
gamespeed = READUINT8(save_p);
|
||||
numlaps = READUINT8(save_p);
|
||||
franticitems = (boolean)READUINT8(save_p);
|
||||
comeback = (boolean)READUINT8(save_p);
|
||||
|
||||
|
|
@ -4656,8 +4669,7 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
|
|||
indirectitemcooldown = READUINT32(save_p);
|
||||
mapreset = READUINT32(save_p);
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
nospectategrief[i] = READINT16(save_p);
|
||||
spectateGriefed = READUINT8(save_p);
|
||||
|
||||
thwompsactive = (boolean)READUINT8(save_p);
|
||||
lastLowestLap = READUINT8(save_p);
|
||||
|
|
|
|||
|
|
@ -391,7 +391,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
|
|||
mapheaderinfo[num]->muspostbossfadein = 0;
|
||||
mapheaderinfo[num]->musforcereset = -1;
|
||||
mapheaderinfo[num]->forcecharacter[0] = '\0';
|
||||
mapheaderinfo[num]->weather = 0;
|
||||
mapheaderinfo[num]->weather = PRECIP_NONE;
|
||||
snprintf(mapheaderinfo[num]->skytexture, 5, "SKY1");
|
||||
mapheaderinfo[num]->skytexture[4] = 0;
|
||||
mapheaderinfo[num]->skybox_scalex = 16;
|
||||
|
|
@ -414,6 +414,9 @@ static void P_ClearSingleMapHeaderInfo(INT16 i)
|
|||
mapheaderinfo[num]->menuflags = 0;
|
||||
mapheaderinfo[num]->mobj_scale = FRACUNIT;
|
||||
mapheaderinfo[num]->default_waypoint_radius = 0;
|
||||
mapheaderinfo[num]->light_contrast = 16;
|
||||
mapheaderinfo[num]->use_light_angle = false;
|
||||
mapheaderinfo[num]->light_angle = 0;
|
||||
#if 1 // equivalent to "FlickyList = DEMO"
|
||||
P_SetDemoFlickies(num);
|
||||
#else // equivalent to "FlickyList = NONE"
|
||||
|
|
@ -2323,13 +2326,25 @@ static inline float P_SegLengthFloat(seg_t *seg)
|
|||
*/
|
||||
void P_UpdateSegLightOffset(seg_t *li)
|
||||
{
|
||||
const UINT8 contrast = 16;
|
||||
const UINT8 contrast = maplighting.contrast;
|
||||
const fixed_t contrastFixed = ((fixed_t)contrast) * FRACUNIT;
|
||||
fixed_t light = FRACUNIT;
|
||||
fixed_t extralight = 0;
|
||||
|
||||
extralight = -((fixed_t)contrast*FRACUNIT) +
|
||||
FixedDiv(AngleFixed(R_PointToAngle2(0, 0,
|
||||
abs(li->v1->x - li->v2->x),
|
||||
abs(li->v1->y - li->v2->y))), 90*FRACUNIT) * ((fixed_t)contrast * 2);
|
||||
if (maplighting.directional == true)
|
||||
{
|
||||
angle_t liAngle = R_PointToAngle2(0, 0, (li->v1->x - li->v2->x), (li->v1->y - li->v2->y)) - ANGLE_90;
|
||||
|
||||
light = FixedMul(FINECOSINE(liAngle >> ANGLETOFINESHIFT), FINECOSINE(maplighting.angle >> ANGLETOFINESHIFT))
|
||||
+ FixedMul(FINESINE(liAngle >> ANGLETOFINESHIFT), FINESINE(maplighting.angle >> ANGLETOFINESHIFT));
|
||||
light = (light + FRACUNIT) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
light = FixedDiv(R_PointToAngle2(0, 0, abs(li->v1->x - li->v2->x), abs(li->v1->y - li->v2->y)), ANGLE_90);
|
||||
}
|
||||
|
||||
extralight = -contrastFixed + FixedMul(light, contrastFixed * 2);
|
||||
|
||||
// Between -2 and 2 for software, -16 and 16 for hardware
|
||||
li->lightOffset = FixedFloor((extralight / 8) + (FRACUNIT / 2)) / FRACUNIT;
|
||||
|
|
@ -2338,6 +2353,20 @@ void P_UpdateSegLightOffset(seg_t *li)
|
|||
#endif
|
||||
}
|
||||
|
||||
boolean P_ApplyLightOffset(UINT8 baselightnum)
|
||||
{
|
||||
// Don't apply light offsets at full bright or full dark.
|
||||
// Is in steps of light num .
|
||||
return (baselightnum < LIGHTLEVELS-1 && baselightnum > 0);
|
||||
}
|
||||
|
||||
boolean P_ApplyLightOffsetFine(UINT8 baselightlevel)
|
||||
{
|
||||
// Don't apply light offsets at full bright or full dark.
|
||||
// Uses exact light levels for more smoothness.
|
||||
return (baselightlevel < 255 && baselightlevel > 0);
|
||||
}
|
||||
|
||||
static void P_InitializeSeg(seg_t *seg)
|
||||
{
|
||||
if (seg->linedef)
|
||||
|
|
@ -4035,25 +4064,37 @@ static void P_InitPlayers(void)
|
|||
|
||||
static void P_InitGametype(void)
|
||||
{
|
||||
spectateGriefed = 0;
|
||||
K_CashInPowerLevels(); // Pushes power level changes even if intermission was skipped
|
||||
|
||||
P_InitPlayers();
|
||||
|
||||
if (modeattacking && !demo.playback)
|
||||
P_LoadRecordGhosts();
|
||||
|
||||
if ((gametyperules & GTR_CIRCUIT) && server)
|
||||
numlaps = 0;
|
||||
if (gametyperules & GTR_CIRCUIT)
|
||||
{
|
||||
if ((netgame || multiplayer) && cv_basenumlaps.value
|
||||
if ((netgame || multiplayer) && cv_numlaps.value
|
||||
&& (!(mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE)
|
||||
|| (mapheaderinfo[gamemap - 1]->numlaps > cv_basenumlaps.value)))
|
||||
|| (mapheaderinfo[gamemap - 1]->numlaps > cv_numlaps.value)))
|
||||
{
|
||||
CV_StealthSetValue(&cv_numlaps, cv_basenumlaps.value);
|
||||
numlaps = cv_numlaps.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
CV_StealthSetValue(&cv_numlaps, mapheaderinfo[gamemap - 1]->numlaps);
|
||||
numlaps = mapheaderinfo[gamemap - 1]->numlaps;
|
||||
}
|
||||
}
|
||||
|
||||
wantedcalcdelay = wantedfrequency*2;
|
||||
indirectitemcooldown = 0;
|
||||
mapreset = 0;
|
||||
|
||||
thwompsactive = false;
|
||||
lastLowestLap = 0;
|
||||
spbplace = -1;
|
||||
|
||||
// Start recording replay in multiplayer with a temp filename
|
||||
//@TODO I'd like to fix dedis crashing when recording replays for the future too...
|
||||
if (!demo.playback && multiplayer && !dedicated)
|
||||
|
|
@ -4089,6 +4130,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
// Map header should always be in place at this point
|
||||
INT32 i, ranspecialwipe = 0;
|
||||
sector_t *ss;
|
||||
|
||||
levelloading = true;
|
||||
|
||||
// This is needed. Don't touch.
|
||||
|
|
@ -4341,8 +4383,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
|
||||
P_SpawnSlopes(fromnetsave);
|
||||
|
||||
P_SpawnSpecialsAfterSlopes();
|
||||
|
||||
P_SpawnMapThings(!fromnetsave);
|
||||
|
||||
for (numcoopstarts = 0; numcoopstarts < MAXPLAYERS; numcoopstarts++)
|
||||
|
|
@ -4404,17 +4444,6 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
K_InitDirector();
|
||||
}
|
||||
|
||||
wantedcalcdelay = wantedfrequency*2;
|
||||
indirectitemcooldown = 0;
|
||||
mapreset = 0;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
nospectategrief[i] = -1;
|
||||
|
||||
thwompsactive = false;
|
||||
lastLowestLap = 0;
|
||||
spbplace = -1;
|
||||
|
||||
// clear special respawning que
|
||||
iquehead = iquetail = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -113,6 +113,8 @@ void P_LoadSoundsRange(UINT16 wadnum, UINT16 first, UINT16 num);
|
|||
void P_LoadMusicsRange(UINT16 wadnum, UINT16 first, UINT16 num);
|
||||
void P_WriteThings(void);
|
||||
void P_UpdateSegLightOffset(seg_t *li);
|
||||
boolean P_ApplyLightOffset(UINT8 baselightnum);
|
||||
boolean P_ApplyLightOffsetFine(UINT8 baselightlevel);
|
||||
size_t P_PrecacheLevelFlats(void);
|
||||
void P_AllocMapHeader(INT16 i);
|
||||
|
||||
|
|
|
|||
|
|
@ -578,6 +578,15 @@ static boolean P_CrossBlockingSubsector(size_t num, register traceblocking_t *tb
|
|||
// This line will always block us
|
||||
return false;
|
||||
}
|
||||
|
||||
if (tb->compareThing->player != NULL)
|
||||
{
|
||||
if (P_IsLineTripWire(line) == true && K_TripwirePass(tb->compareThing->player) == false)
|
||||
{
|
||||
// Can't go through trip wire.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// passed the subsector ok
|
||||
|
|
@ -728,7 +737,18 @@ static boolean P_CrossBotTraversalSubsector(size_t num, register traceblocking_t
|
|||
return false;
|
||||
}
|
||||
|
||||
if (tb->compareThing->player != NULL)
|
||||
{
|
||||
if (P_IsLineTripWire(line) == true && K_TripwirePass(tb->compareThing->player) == false)
|
||||
{
|
||||
// Can't go through trip wire.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// set openrange, opentop, openbottom
|
||||
tmx = tb->compareThing->x;
|
||||
tmy = tb->compareThing->y;
|
||||
P_LineOpening(line, tb->compareThing);
|
||||
maxstep = P_GetThingStepUp(tb->compareThing);
|
||||
|
||||
|
|
@ -740,10 +760,13 @@ static boolean P_CrossBotTraversalSubsector(size_t num, register traceblocking_t
|
|||
return false;
|
||||
}
|
||||
|
||||
// Treat damage sectors like walls
|
||||
if (tb->compareThing->player != NULL)
|
||||
{
|
||||
boolean alreadyHates = K_BotHatesThisSector(tb->compareThing->player, tb->compareThing->subsector->sector, tb->compareThing->x, tb->compareThing->y);
|
||||
// Treat damage sectors like walls
|
||||
boolean alreadyHates = K_BotHatesThisSector(
|
||||
tb->compareThing->player, tb->compareThing->subsector->sector,
|
||||
tb->compareThing->x, tb->compareThing->y
|
||||
);
|
||||
|
||||
if (alreadyHates == false)
|
||||
{
|
||||
|
|
@ -753,18 +776,16 @@ static boolean P_CrossBotTraversalSubsector(size_t num, register traceblocking_t
|
|||
P_ClosestPointOnLine(tb->compareThing->x, tb->compareThing->y, line, &pos);
|
||||
lineside = P_PointOnLineSide(tb->compareThing->x, tb->compareThing->y, line);
|
||||
|
||||
if (K_BotHatesThisSector(tb->compareThing->player, ((lineside == 1) ? line->frontsector : line->backsector), pos.x, pos.y))
|
||||
if (K_BotHatesThisSector(
|
||||
tb->compareThing->player,
|
||||
((lineside == 1) ? line->frontsector : line->backsector),
|
||||
pos.x, pos.y
|
||||
))
|
||||
{
|
||||
// This line does not block us, but we don't want to be in it.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (P_IsLineTripWire(line) == true && K_TripwirePass(tb->compareThing->player) == false)
|
||||
{
|
||||
// Can't go through trip wire.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,11 +31,74 @@ UINT16 slopecount = 0;
|
|||
static void P_BuildSlopeAnchorList (void);
|
||||
static void P_SetupAnchoredSlopes (void);
|
||||
|
||||
// Calculate light
|
||||
void P_UpdateSlopeLightOffset(pslope_t *slope)
|
||||
{
|
||||
const UINT8 contrast = maplighting.contrast;
|
||||
|
||||
fixed_t contrastFixed = ((fixed_t)contrast) * FRACUNIT;
|
||||
fixed_t zMul = FRACUNIT;
|
||||
fixed_t light = FRACUNIT;
|
||||
fixed_t extralight = 0;
|
||||
|
||||
if (slope->normal.z == 0)
|
||||
{
|
||||
slope->lightOffset = slope->hwLightOffset = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (maplighting.directional == true)
|
||||
{
|
||||
fixed_t nX = -slope->normal.x;
|
||||
fixed_t nY = -slope->normal.y;
|
||||
fixed_t nLen = FixedHypot(nX, nY);
|
||||
|
||||
if (nLen == 0)
|
||||
{
|
||||
slope->lightOffset = slope->hwLightOffset = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
nX = FixedDiv(nX, nLen);
|
||||
nY = FixedDiv(nY, nLen);
|
||||
|
||||
/*
|
||||
if (slope is ceiling)
|
||||
{
|
||||
// There is no good way to calculate this condition here.
|
||||
// We reverse it in R_FindPlane now.
|
||||
nX = -nX;
|
||||
nY = -nY;
|
||||
}
|
||||
*/
|
||||
|
||||
light = FixedMul(nX, FINECOSINE(maplighting.angle >> ANGLETOFINESHIFT))
|
||||
+ FixedMul(nY, FINESINE(maplighting.angle >> ANGLETOFINESHIFT));
|
||||
light = (light + FRACUNIT) / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
light = FixedDiv(R_PointToAngle2(0, 0, abs(slope->normal.y), abs(slope->normal.x)), ANGLE_90);
|
||||
}
|
||||
|
||||
zMul = min(FRACUNIT, abs(slope->zdelta)*3/2); // *3/2, to make 60 degree slopes match walls.
|
||||
contrastFixed = FixedMul(contrastFixed, zMul);
|
||||
|
||||
extralight = -contrastFixed + FixedMul(light, contrastFixed * 2);
|
||||
|
||||
// Between -2 and 2 for software, -16 and 16 for hardware
|
||||
slope->lightOffset = FixedFloor((extralight / 8) + (FRACUNIT / 2)) / FRACUNIT;
|
||||
#ifdef HWRENDER
|
||||
slope->hwLightOffset = FixedFloor(extralight + (FRACUNIT / 2)) / FRACUNIT;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Calculate line normal
|
||||
void P_CalculateSlopeNormal(pslope_t *slope) {
|
||||
slope->normal.z = FINECOSINE(slope->zangle>>ANGLETOFINESHIFT);
|
||||
slope->normal.x = FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.x);
|
||||
slope->normal.y = FixedMul(FINESINE(slope->zangle>>ANGLETOFINESHIFT), slope->d.y);
|
||||
P_UpdateSlopeLightOffset(slope);
|
||||
}
|
||||
|
||||
// Calculate slope's high & low z
|
||||
|
|
@ -128,8 +191,10 @@ void P_ReconfigureViaVertexes (pslope_t *slope, const vector3_t v1, const vector
|
|||
|
||||
// Get angles
|
||||
slope->xydirection = R_PointToAngle2(0, 0, slope->d.x, slope->d.y)+ANGLE_180;
|
||||
slope->zangle = InvAngle(R_PointToAngle2(0, 0, FRACUNIT, slope->zdelta));
|
||||
slope->zangle = R_PointToAngle2(0, 0, FRACUNIT, -slope->zdelta);
|
||||
}
|
||||
|
||||
P_UpdateSlopeLightOffset(slope);
|
||||
}
|
||||
|
||||
/// Setup slope via constants.
|
||||
|
|
@ -159,7 +224,9 @@ static void ReconfigureViaConstants (pslope_t *slope, const fixed_t a, const fix
|
|||
|
||||
// Get angles
|
||||
slope->xydirection = R_PointToAngle2(0, 0, slope->d.x, slope->d.y)+ANGLE_180;
|
||||
slope->zangle = InvAngle(R_PointToAngle2(0, 0, FRACUNIT, slope->zdelta));
|
||||
slope->zangle = R_PointToAngle2(0, 0, FRACUNIT, -slope->zdelta);
|
||||
|
||||
P_UpdateSlopeLightOffset(slope);
|
||||
}
|
||||
|
||||
/// Recalculate dynamic slopes.
|
||||
|
|
@ -544,6 +611,7 @@ static void line_SpawnViaMapthingVertexes(const int linenum, const boolean spawn
|
|||
UINT16 tag2 = line->args[2];
|
||||
UINT16 tag3 = line->args[3];
|
||||
UINT8 flags = 0; // Slope flags
|
||||
|
||||
if (line->args[4] & TMSL_NOPHYSICS)
|
||||
flags |= SL_NOPHYSICS;
|
||||
if (line->args[4] & TMSL_DYNAMIC)
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@ typedef enum
|
|||
|
||||
void P_LinkSlopeThinkers (void);
|
||||
|
||||
void P_UpdateSlopeLightOffset(pslope_t *slope);
|
||||
void P_CalculateSlopeNormal(pslope_t *slope);
|
||||
void P_ReconfigureViaVertexes(pslope_t *slope, const vector3_t v1, const vector3_t v2, const vector3_t v3);
|
||||
void P_InitSlopes(void);
|
||||
|
|
|
|||
118
src/p_spec.c
118
src/p_spec.c
|
|
@ -1769,10 +1769,18 @@ void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller)
|
|||
//
|
||||
// Switches the weather!
|
||||
//
|
||||
void P_SwitchWeather(UINT8 newWeather)
|
||||
void P_SwitchWeather(preciptype_t newWeather)
|
||||
{
|
||||
boolean purge = false;
|
||||
mobjtype_t swap = MT_NULL;
|
||||
INT32 oldEffects = precipprops[curWeather].effects;
|
||||
|
||||
if (newWeather >= precip_freeslot)
|
||||
{
|
||||
// Weather type invalid, set to no weather.
|
||||
CONS_Debug(DBG_SETUP, "Weather ID %d out of bounds\n", newWeather);
|
||||
newWeather = PRECIP_NONE;
|
||||
}
|
||||
|
||||
if (precipprops[newWeather].type == MT_NULL)
|
||||
{
|
||||
|
|
@ -1790,6 +1798,8 @@ void P_SwitchWeather(UINT8 newWeather)
|
|||
}
|
||||
}
|
||||
|
||||
curWeather = newWeather;
|
||||
|
||||
if (purge == true)
|
||||
{
|
||||
thinker_t *think;
|
||||
|
|
@ -1844,14 +1854,22 @@ void P_SwitchWeather(UINT8 newWeather)
|
|||
precipmobj->sprite = precipmobj->state->sprite;
|
||||
precipmobj->frame = precipmobj->state->frame;
|
||||
|
||||
precipmobj->momz = mobjinfo[swap].speed;
|
||||
precipmobj->precipflags &= ~PCF_INVISIBLE;
|
||||
precipmobj->momz = FixedMul(-mobjinfo[swap].speed, mapobjectscale);
|
||||
precipmobj->precipflags &= ~(PCF_INVISIBLE|PCF_FLIP);
|
||||
|
||||
if (precipmobj->momz > 0)
|
||||
{
|
||||
precipmobj->precipflags |= PCF_FLIP;
|
||||
}
|
||||
|
||||
if ((oldEffects & PRECIPFX_WATERPARTICLES) != (precipprops[curWeather].effects & PRECIPFX_WATERPARTICLES))
|
||||
{
|
||||
P_CalculatePrecipFloor(precipmobj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
curWeather = newWeather;
|
||||
|
||||
if (swap == MT_NULL && precipprops[newWeather].type != MT_NULL)
|
||||
if (swap == MT_NULL && precipprops[curWeather].type != MT_NULL)
|
||||
P_SpawnPrecipitation();
|
||||
}
|
||||
|
||||
|
|
@ -1899,14 +1917,6 @@ static void K_HandleLapIncrement(player_t *player)
|
|||
player->karthud[khud_laphand] = 0; // No hands in FREE PLAY
|
||||
|
||||
player->karthud[khud_lapanimation] = 80;
|
||||
|
||||
// save best lap for record attack
|
||||
if (player == &players[consoleplayer])
|
||||
{
|
||||
if (curlap < bestlap || bestlap == 0)
|
||||
bestlap = curlap;
|
||||
curlap = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (rainbowstartavailable == true)
|
||||
|
|
@ -1920,18 +1930,18 @@ static void K_HandleLapIncrement(player_t *player)
|
|||
rainbowstartavailable = false;
|
||||
}
|
||||
|
||||
if (netgame && player->laps >= (UINT8)cv_numlaps.value)
|
||||
if (netgame && player->laps >= numlaps)
|
||||
CON_LogMessage(va(M_GetText("%s has finished the race.\n"), player_names[player-players]));
|
||||
|
||||
player->starpostnum = 0;
|
||||
|
||||
if (P_IsDisplayPlayer(player))
|
||||
{
|
||||
if (player->laps == (UINT8)(cv_numlaps.value)) // final lap
|
||||
if (player->laps == numlaps) // final lap
|
||||
S_StartSound(NULL, sfx_s3k68);
|
||||
else if ((player->laps > 1) && (player->laps < (UINT8)(cv_numlaps.value))) // non-final lap
|
||||
else if ((player->laps > 1) && (player->laps < numlaps)) // non-final lap
|
||||
S_StartSound(NULL, sfx_s221);
|
||||
else if (player->laps > (UINT8)(cv_numlaps.value))
|
||||
else if (player->laps > numlaps)
|
||||
{
|
||||
// finished
|
||||
S_StartSound(NULL, sfx_s3k6a);
|
||||
|
|
@ -1940,7 +1950,7 @@ static void K_HandleLapIncrement(player_t *player)
|
|||
}
|
||||
else
|
||||
{
|
||||
if ((player->laps > (UINT8)(cv_numlaps.value)) && (player->position == 1))
|
||||
if ((player->laps > numlaps) && (player->position == 1))
|
||||
{
|
||||
// opponent finished
|
||||
S_StartSound(NULL, sfx_s253);
|
||||
|
|
@ -1948,12 +1958,34 @@ static void K_HandleLapIncrement(player_t *player)
|
|||
}
|
||||
|
||||
// finished race exit setup
|
||||
if (player->laps > (unsigned)cv_numlaps.value)
|
||||
if (player->laps > numlaps)
|
||||
{
|
||||
P_DoPlayerExit(player);
|
||||
P_SetupSignExit(player);
|
||||
}
|
||||
|
||||
if (player->laps > player->latestlap)
|
||||
{
|
||||
if (player->laps > 1)
|
||||
{
|
||||
// save best lap for record attack
|
||||
if (modeattacking && player == &players[consoleplayer])
|
||||
{
|
||||
if (curlap < bestlap || bestlap == 0)
|
||||
{
|
||||
bestlap = curlap;
|
||||
}
|
||||
|
||||
curlap = 0;
|
||||
}
|
||||
|
||||
// Update power levels for this lap.
|
||||
K_UpdatePowerLevels(player, player->laps, false);
|
||||
}
|
||||
|
||||
player->latestlap = player->laps;
|
||||
}
|
||||
|
||||
thwompsactive = true; // Lap 2 effects
|
||||
|
||||
lowestLap = P_FindLowestLap();
|
||||
|
|
@ -3641,7 +3673,11 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec)
|
|||
return;
|
||||
|
||||
if (delay <= 0 || !(leveltime % delay))
|
||||
P_GivePlayerRings(mo->player, rings);
|
||||
{
|
||||
// No Climb: don't cap rings to 20
|
||||
K_AwardPlayerRings(mo->player, rings,
|
||||
(line->flags & ML_NOCLIMB) == ML_NOCLIMB);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
@ -4040,8 +4076,10 @@ sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number, b
|
|||
msecnode_t *node;
|
||||
ffloor_t *rover;
|
||||
|
||||
if (!mo)
|
||||
if (mo == NULL || P_MobjWasRemoved(mo) == true)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Check default case first
|
||||
if (GETSECSPECIAL(mo->subsector->sector->special, section) == number)
|
||||
|
|
@ -5884,6 +5922,11 @@ void P_InitSpecials(void)
|
|||
// Set the default gravity. Custom gravity overrides this setting.
|
||||
gravity = mapheaderinfo[gamemap-1]->gravity;
|
||||
|
||||
// Set map lighting settings.
|
||||
maplighting.contrast = mapheaderinfo[gamemap-1]->light_contrast;
|
||||
maplighting.directional = mapheaderinfo[gamemap-1]->use_light_angle;
|
||||
maplighting.angle = mapheaderinfo[gamemap-1]->light_angle;
|
||||
|
||||
// Defaults in case levels don't have them set.
|
||||
sstimer = mapheaderinfo[gamemap-1]->sstimer*TICRATE + 6;
|
||||
ssspheres = mapheaderinfo[gamemap-1]->ssspheres;
|
||||
|
|
@ -6950,6 +6993,12 @@ void P_SpawnSpecialsThatRequireObjects(boolean fromnetsave)
|
|||
|
||||
for (i = 0; i < numlines; i++)
|
||||
{
|
||||
if (P_IsLineDisabled(&lines[i]))
|
||||
{
|
||||
/* remove the special so it can't even be found during the level */
|
||||
lines[i].special = 0;
|
||||
}
|
||||
|
||||
switch (lines[i].special)
|
||||
{
|
||||
case 30: // Polyobj_Flag
|
||||
|
|
@ -6963,29 +7012,7 @@ void P_SpawnSpecialsThatRequireObjects(boolean fromnetsave)
|
|||
case 32: // Polyobj_RotDisplace
|
||||
PolyRotDisplace(&lines[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fromnetsave)
|
||||
P_RunLevelLoadExecutors();
|
||||
}
|
||||
|
||||
/** Fuck ML_NONET
|
||||
*/
|
||||
void P_SpawnSpecialsAfterSlopes(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < numlines; ++i)
|
||||
{
|
||||
if (P_IsLineDisabled(&lines[i]))
|
||||
{
|
||||
/* remove the special so it can't even be found during the level */
|
||||
lines[i].special = 0;
|
||||
}
|
||||
|
||||
switch (lines[i].special)
|
||||
{
|
||||
case 80: // Raise tagged things by type to this FOF
|
||||
{
|
||||
mtag_t tag = Tag_FGet(&lines[i].tags);
|
||||
|
|
@ -6998,6 +7025,9 @@ void P_SpawnSpecialsAfterSlopes(void)
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fromnetsave)
|
||||
P_RunLevelLoadExecutors();
|
||||
}
|
||||
|
||||
/** Adds 3Dfloors as appropriate based on a common control linedef.
|
||||
|
|
|
|||
|
|
@ -42,7 +42,6 @@ void P_SetupLevelFlatAnims(void);
|
|||
// at map load
|
||||
void P_InitSpecials(void);
|
||||
void P_SpawnSpecials(boolean fromnetsave);
|
||||
void P_SpawnSpecialsAfterSlopes(void);
|
||||
void P_SpawnSpecialsThatRequireObjects(boolean fromnetsave);
|
||||
|
||||
// every tic
|
||||
|
|
@ -67,7 +66,7 @@ void P_CrossSpecialLine(line_t *ld, INT32 side, mobj_t *thing);
|
|||
void P_SetupSignExit(player_t *player);
|
||||
boolean P_IsFlagAtBase(mobjtype_t flag);
|
||||
|
||||
void P_SwitchWeather(UINT8 newWeather);
|
||||
void P_SwitchWeather(preciptype_t newWeather);
|
||||
|
||||
boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller);
|
||||
void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller);
|
||||
|
|
|
|||
20
src/p_user.c
20
src/p_user.c
|
|
@ -198,7 +198,7 @@ void P_CalcHeight(player_t *player)
|
|||
fixed_t bob = 0;
|
||||
fixed_t pviewheight;
|
||||
mobj_t *mo = player->mo;
|
||||
fixed_t bobmul = FRACUNIT - FixedDiv(FixedHypot(player->rmomx, player->rmomy), K_GetKartSpeed(player, false));
|
||||
fixed_t bobmul = FRACUNIT - FixedDiv(FixedHypot(player->rmomx, player->rmomy), K_GetKartSpeed(player, false, false));
|
||||
|
||||
// Regular movement bobbing.
|
||||
// Should not be calculated when not on ground (FIXTHIS?)
|
||||
|
|
@ -873,7 +873,7 @@ void P_RestoreMusic(player_t *player)
|
|||
#if 0
|
||||
// Event - Final Lap
|
||||
// Still works for GME, but disabled for consistency
|
||||
if ((gametyperules & GTR_CIRCUIT) && player->laps >= (UINT8)(cv_numlaps.value))
|
||||
if ((gametyperules & GTR_CIRCUIT) && player->laps >= numlaps)
|
||||
S_SpeedMusic(1.2f);
|
||||
#endif
|
||||
if (mapmusresume && cv_resume.value)
|
||||
|
|
@ -1939,7 +1939,7 @@ static void P_3dMovement(player_t *player)
|
|||
// Make rubberbanding bots slow down faster
|
||||
if (K_PlayerUsesBotMovement(player))
|
||||
{
|
||||
fixed_t rubberband = K_BotRubberband(player) - FRACUNIT;
|
||||
fixed_t rubberband = player->botvars.rubberband - FRACUNIT;
|
||||
|
||||
if (rubberband > 0)
|
||||
{
|
||||
|
|
@ -1969,11 +1969,12 @@ static void P_3dMovement(player_t *player)
|
|||
// allow for being able to change direction on spring jumps without being accelerated into the void - Sryder
|
||||
if (!P_IsObjectOnGround(player->mo))
|
||||
{
|
||||
fixed_t topspeed = K_GetKartSpeed(player, true, true);
|
||||
newMagnitude = R_PointToDist2(player->mo->momx - player->cmomx, player->mo->momy - player->cmomy, 0, 0);
|
||||
if (newMagnitude > K_GetKartSpeed(player, true)) //topspeed)
|
||||
if (newMagnitude > topspeed)
|
||||
{
|
||||
fixed_t tempmomx, tempmomy;
|
||||
if (oldMagnitude > K_GetKartSpeed(player, true))
|
||||
if (oldMagnitude > topspeed)
|
||||
{
|
||||
if (newMagnitude > oldMagnitude)
|
||||
{
|
||||
|
|
@ -1986,8 +1987,8 @@ static void P_3dMovement(player_t *player)
|
|||
}
|
||||
else
|
||||
{
|
||||
tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), K_GetKartSpeed(player, true)); //topspeed)
|
||||
tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), K_GetKartSpeed(player, true)); //topspeed)
|
||||
tempmomx = FixedMul(FixedDiv(player->mo->momx - player->cmomx, newMagnitude), topspeed);
|
||||
tempmomy = FixedMul(FixedDiv(player->mo->momy - player->cmomy, newMagnitude), topspeed);
|
||||
player->mo->momx = tempmomx + player->cmomx;
|
||||
player->mo->momy = tempmomy + player->cmomy;
|
||||
}
|
||||
|
|
@ -2256,8 +2257,8 @@ void P_MovePlayer(player_t *player)
|
|||
&& (player->speed > runspd)
|
||||
&& player->mo->momz == 0 && player->carry != CR_SLIDING && !player->spectator)
|
||||
{
|
||||
fixed_t trailScale = FixedMul(FixedDiv(player->speed - runspd, K_GetKartSpeed(player, false) - runspd), mapobjectscale);
|
||||
fixed_t playerTopSpeed = K_GetKartSpeed(player, false);
|
||||
fixed_t playerTopSpeed = K_GetKartSpeed(player, false, false);
|
||||
fixed_t trailScale = FixedMul(FixedDiv(player->speed - runspd, playerTopSpeed - runspd), mapobjectscale);
|
||||
|
||||
if (playerTopSpeed > runspd)
|
||||
trailScale = FixedMul(FixedDiv(player->speed - runspd, playerTopSpeed - runspd), mapobjectscale);
|
||||
|
|
@ -3852,6 +3853,7 @@ void P_DoTimeOver(player_t *player)
|
|||
}
|
||||
|
||||
player->pflags |= PF_NOCONTEST;
|
||||
K_UpdatePowerLevelsOnFailure(player);
|
||||
|
||||
if (G_GametypeUsesLives())
|
||||
{
|
||||
|
|
|
|||
110
src/r_bsp.c
110
src/r_bsp.c
|
|
@ -67,40 +67,6 @@ boolean R_IsRipplePlane(sector_t *sector, ffloor_t *rover, int ceiling)
|
|||
sector->flags & (SF_RIPPLE_FLOOR << ceiling);
|
||||
}
|
||||
|
||||
static void R_PlaneLightOverride(sector_t *sector, boolean ceiling, INT32 *lightlevel)
|
||||
{
|
||||
terrain_t *t = NULL;
|
||||
|
||||
if (ceiling == true)
|
||||
{
|
||||
t = K_GetTerrainForFlatNum(sector->ceilingpic);
|
||||
}
|
||||
else
|
||||
{
|
||||
t = K_GetTerrainForFlatNum(sector->floorpic);
|
||||
}
|
||||
|
||||
if (t != NULL)
|
||||
{
|
||||
if (t->flags & TRF_SNEAKERPANEL)
|
||||
{
|
||||
*lightlevel = 255;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sector effect sneaker panels (DEPRECATED)
|
||||
if (GETSECSPECIAL(sector->special, 4) == 6)
|
||||
{
|
||||
if ((ceiling && (sector->flags & SF_FLIPSPECIAL_CEILING))
|
||||
|| (!ceiling && (sector->flags & SF_FLIPSPECIAL_FLOOR)))
|
||||
{
|
||||
*lightlevel = 255;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// R_ClearDrawSegs
|
||||
//
|
||||
|
|
@ -968,16 +934,18 @@ static void R_Subsector(size_t num)
|
|||
|
||||
sub->sector->extra_colormap = frontsector->extra_colormap;
|
||||
|
||||
R_PlaneLightOverride(frontsector, false, &floorlightlevel);
|
||||
R_PlaneLightOverride(frontsector, true, &ceilinglightlevel);
|
||||
|
||||
if (P_GetSectorFloorZAt(frontsector, viewx, viewy) < viewz
|
||||
|| frontsector->floorpic == skyflatnum
|
||||
|| (frontsector->heightsec != -1 && sectors[frontsector->heightsec].ceilingpic == skyflatnum))
|
||||
{
|
||||
floorplane = R_FindPlane(frontsector->floorheight, frontsector->floorpic, floorlightlevel,
|
||||
frontsector->floor_xoffs, frontsector->floor_yoffs, frontsector->floorpic_angle, floorcolormap, NULL, NULL, frontsector->f_slope,
|
||||
R_NoEncore(frontsector, false), R_IsRipplePlane(frontsector, NULL, false));
|
||||
floorplane = R_FindPlane(
|
||||
frontsector->floorheight, frontsector->floorpic, floorlightlevel,
|
||||
frontsector->floor_xoffs, frontsector->floor_yoffs, frontsector->floorpic_angle,
|
||||
floorcolormap, NULL, NULL, frontsector->f_slope,
|
||||
R_NoEncore(frontsector, false),
|
||||
R_IsRipplePlane(frontsector, NULL, false),
|
||||
false
|
||||
);
|
||||
}
|
||||
else
|
||||
floorplane = NULL;
|
||||
|
|
@ -986,10 +954,14 @@ static void R_Subsector(size_t num)
|
|||
|| frontsector->ceilingpic == skyflatnum
|
||||
|| (frontsector->heightsec != -1 && sectors[frontsector->heightsec].floorpic == skyflatnum))
|
||||
{
|
||||
ceilingplane = R_FindPlane(frontsector->ceilingheight, frontsector->ceilingpic,
|
||||
ceilinglightlevel, frontsector->ceiling_xoffs, frontsector->ceiling_yoffs, frontsector->ceilingpic_angle,
|
||||
ceilingplane = R_FindPlane(
|
||||
frontsector->ceilingheight, frontsector->ceilingpic, ceilinglightlevel,
|
||||
frontsector->ceiling_xoffs, frontsector->ceiling_yoffs, frontsector->ceilingpic_angle,
|
||||
ceilingcolormap, NULL, NULL, frontsector->c_slope,
|
||||
R_NoEncore(frontsector, true), R_IsRipplePlane(frontsector, NULL, true));
|
||||
R_NoEncore(frontsector, true),
|
||||
R_IsRipplePlane(frontsector, NULL, true),
|
||||
true
|
||||
);
|
||||
}
|
||||
else
|
||||
ceilingplane = NULL;
|
||||
|
|
@ -1027,19 +999,17 @@ static void R_Subsector(size_t num)
|
|||
&& ((viewz < heightcheck && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES)))
|
||||
|| (viewz > heightcheck && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES))))
|
||||
{
|
||||
INT32 newlightlevel;
|
||||
|
||||
light = R_GetPlaneLight(frontsector, planecenterz,
|
||||
viewz < heightcheck);
|
||||
|
||||
newlightlevel = *frontsector->lightlist[light].lightlevel;
|
||||
R_PlaneLightOverride(rover->master->frontsector, true, &newlightlevel);
|
||||
|
||||
ffloor[numffloors].plane = R_FindPlane(*rover->bottomheight, *rover->bottompic,
|
||||
newlightlevel, *rover->bottomxoffs,
|
||||
ffloor[numffloors].plane = R_FindPlane(
|
||||
*rover->bottomheight, *rover->bottompic,
|
||||
*frontsector->lightlist[light].lightlevel, *rover->bottomxoffs,
|
||||
*rover->bottomyoffs, *rover->bottomangle, *frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->b_slope,
|
||||
R_NoEncore(rover->master->frontsector, true),
|
||||
R_IsRipplePlane(rover->master->frontsector, rover, true));
|
||||
R_IsRipplePlane(rover->master->frontsector, rover, true),
|
||||
true
|
||||
);
|
||||
|
||||
ffloor[numffloors].slope = *rover->b_slope;
|
||||
|
||||
|
|
@ -1064,18 +1034,16 @@ static void R_Subsector(size_t num)
|
|||
&& ((viewz > heightcheck && (rover->flags & FF_BOTHPLANES || !(rover->flags & FF_INVERTPLANES)))
|
||||
|| (viewz < heightcheck && (rover->flags & FF_BOTHPLANES || rover->flags & FF_INVERTPLANES))))
|
||||
{
|
||||
INT32 newlightlevel;
|
||||
|
||||
light = R_GetPlaneLight(frontsector, planecenterz, viewz < heightcheck);
|
||||
|
||||
newlightlevel = *frontsector->lightlist[light].lightlevel;
|
||||
R_PlaneLightOverride(rover->master->frontsector, false, &newlightlevel);
|
||||
|
||||
ffloor[numffloors].plane = R_FindPlane(*rover->topheight, *rover->toppic,
|
||||
ffloor[numffloors].plane = R_FindPlane(
|
||||
*rover->topheight, *rover->toppic,
|
||||
*frontsector->lightlist[light].lightlevel, *rover->topxoffs, *rover->topyoffs, *rover->topangle,
|
||||
*frontsector->lightlist[light].extra_colormap, rover, NULL, *rover->t_slope,
|
||||
R_NoEncore(rover->master->frontsector, false),
|
||||
R_IsRipplePlane(rover->master->frontsector, rover, false));
|
||||
R_IsRipplePlane(rover->master->frontsector, rover, false),
|
||||
false
|
||||
);
|
||||
|
||||
ffloor[numffloors].slope = *rover->t_slope;
|
||||
|
||||
|
|
@ -1114,19 +1082,18 @@ static void R_Subsector(size_t num)
|
|||
&& polysec->floorheight >= floorcenterz
|
||||
&& (viewz < polysec->floorheight))
|
||||
{
|
||||
INT32 newlightlevel;
|
||||
|
||||
light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight);
|
||||
|
||||
newlightlevel = (light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel);
|
||||
R_PlaneLightOverride(polysec, false, &newlightlevel);
|
||||
|
||||
ffloor[numffloors].plane = R_FindPlane(polysec->floorheight, polysec->floorpic,
|
||||
ffloor[numffloors].plane = R_FindPlane(
|
||||
polysec->floorheight, polysec->floorpic,
|
||||
(light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->floor_xoffs, polysec->floor_yoffs,
|
||||
polysec->floorpic_angle-po->angle,
|
||||
(light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po,
|
||||
NULL, // will ffloors be slopable eventually?
|
||||
R_NoEncore(polysec, false), false);/* TODO: wet polyobjects? */
|
||||
R_NoEncore(polysec, false),
|
||||
false, /* TODO: wet polyobjects? */
|
||||
true
|
||||
);
|
||||
|
||||
ffloor[numffloors].height = polysec->floorheight;
|
||||
ffloor[numffloors].polyobj = po;
|
||||
|
|
@ -1145,18 +1112,17 @@ static void R_Subsector(size_t num)
|
|||
&& polysec->ceilingheight <= ceilingcenterz
|
||||
&& (viewz > polysec->ceilingheight))
|
||||
{
|
||||
INT32 newlightlevel;
|
||||
|
||||
light = R_GetPlaneLight(frontsector, polysec->floorheight, viewz < polysec->floorheight);
|
||||
|
||||
newlightlevel = (light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel);
|
||||
R_PlaneLightOverride(polysec, true, &newlightlevel);
|
||||
|
||||
ffloor[numffloors].plane = R_FindPlane(polysec->ceilingheight, polysec->ceilingpic,
|
||||
ffloor[numffloors].plane = R_FindPlane(
|
||||
polysec->ceilingheight, polysec->ceilingpic,
|
||||
(light == -1 ? frontsector->lightlevel : *frontsector->lightlist[light].lightlevel), polysec->ceiling_xoffs, polysec->ceiling_yoffs, polysec->ceilingpic_angle-po->angle,
|
||||
(light == -1 ? frontsector->extra_colormap : *frontsector->lightlist[light].extra_colormap), NULL, po,
|
||||
NULL, // will ffloors be slopable eventually?
|
||||
R_NoEncore(polysec, true), false);/* TODO: wet polyobjects? */
|
||||
R_NoEncore(polysec, true),
|
||||
false, /* TODO: wet polyobjects? */
|
||||
false
|
||||
);
|
||||
|
||||
ffloor[numffloors].polyobj = po;
|
||||
ffloor[numffloors].height = polysec->ceilingheight;
|
||||
|
|
|
|||
|
|
@ -251,6 +251,12 @@ typedef struct pslope_s
|
|||
// SRB2Kart: For P_VeryTopOfFOF & P_VeryBottomOfFOF
|
||||
fixed_t lowz;
|
||||
fixed_t highz;
|
||||
|
||||
// Light offsets (see seg_t)
|
||||
SINT8 lightOffset;
|
||||
#ifdef HWRENDER
|
||||
INT16 hwLightOffset;
|
||||
#endif
|
||||
} pslope_t;
|
||||
|
||||
typedef enum
|
||||
|
|
|
|||
|
|
@ -836,13 +836,14 @@ void R_DrawSpan_8 (void)
|
|||
bit = (((UINT32)yposition >> nflatyshift) & nflatmask) | ((UINT32)xposition >> nflatxshift);
|
||||
if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL)
|
||||
{
|
||||
*dest++ = fullbright[source[bit]];
|
||||
*dest = fullbright[source[bit]];
|
||||
}
|
||||
else
|
||||
{
|
||||
*dest++ = colormap[source[bit]];
|
||||
*dest = colormap[source[bit]];
|
||||
}
|
||||
|
||||
dest++;
|
||||
xposition += xstep;
|
||||
yposition += ystep;
|
||||
}
|
||||
|
|
@ -933,10 +934,11 @@ void R_DrawTiltedSpan_8(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
|
||||
colormap = planezlight[tiltlighting[ds_x1]] + (ds_colormap - colormaps);
|
||||
*dest = colormap[source[bit]];
|
||||
}
|
||||
dest++;
|
||||
ds_x1++;
|
||||
iz += ds_szp->x;
|
||||
uz += ds_sup->x;
|
||||
vz += ds_svp->x;
|
||||
|
|
@ -975,10 +977,11 @@ void R_DrawTiltedSpan_8(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
|
||||
colormap = planezlight[tiltlighting[ds_x1]] + (ds_colormap - colormaps);
|
||||
*dest = colormap[source[bit]];
|
||||
}
|
||||
dest++;
|
||||
ds_x1++;
|
||||
u += stepu;
|
||||
v += stepv;
|
||||
}
|
||||
|
|
@ -999,9 +1002,10 @@ void R_DrawTiltedSpan_8(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
|
||||
colormap = planezlight[tiltlighting[ds_x1]] + (ds_colormap - colormaps);
|
||||
*dest = colormap[source[bit]];
|
||||
}
|
||||
ds_x1++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1028,10 +1032,11 @@ void R_DrawTiltedSpan_8(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
|
||||
colormap = planezlight[tiltlighting[ds_x1]] + (ds_colormap - colormaps);
|
||||
*dest = colormap[source[bit]];
|
||||
}
|
||||
dest++;
|
||||
ds_x1++;
|
||||
u += stepu;
|
||||
v += stepv;
|
||||
}
|
||||
|
|
@ -1103,10 +1108,11 @@ void R_DrawTiltedTranslucentSpan_8(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
|
||||
colormap = planezlight[tiltlighting[ds_x1]] + (ds_colormap - colormaps);
|
||||
*dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest);
|
||||
}
|
||||
dest++;
|
||||
ds_x1++;
|
||||
iz += ds_szp->x;
|
||||
uz += ds_sup->x;
|
||||
vz += ds_svp->x;
|
||||
|
|
@ -1145,10 +1151,11 @@ void R_DrawTiltedTranslucentSpan_8(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
|
||||
colormap = planezlight[tiltlighting[ds_x1]] + (ds_colormap - colormaps);
|
||||
*dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest);
|
||||
}
|
||||
dest++;
|
||||
ds_x1++;
|
||||
u += stepu;
|
||||
v += stepv;
|
||||
}
|
||||
|
|
@ -1169,9 +1176,10 @@ void R_DrawTiltedTranslucentSpan_8(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
|
||||
colormap = planezlight[tiltlighting[ds_x1]] + (ds_colormap - colormaps);
|
||||
*dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest);
|
||||
}
|
||||
ds_x1++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1198,10 +1206,11 @@ void R_DrawTiltedTranslucentSpan_8(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
|
||||
colormap = planezlight[tiltlighting[ds_x1]] + (ds_colormap - colormaps);
|
||||
*dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dest);
|
||||
}
|
||||
dest++;
|
||||
ds_x1++;
|
||||
u += stepu;
|
||||
v += stepv;
|
||||
}
|
||||
|
|
@ -1270,14 +1279,16 @@ void R_DrawTiltedTranslucentWaterSpan_8(void)
|
|||
bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift);
|
||||
if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL)
|
||||
{
|
||||
*dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dsrc++);
|
||||
*dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dsrc);
|
||||
}
|
||||
else
|
||||
{
|
||||
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
|
||||
*dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dsrc++);
|
||||
colormap = planezlight[tiltlighting[ds_x1]] + (ds_colormap - colormaps);
|
||||
*dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dsrc);
|
||||
}
|
||||
dest++;
|
||||
ds_x1++;
|
||||
dsrc++;
|
||||
iz += ds_szp->x;
|
||||
uz += ds_sup->x;
|
||||
vz += ds_svp->x;
|
||||
|
|
@ -1312,14 +1323,16 @@ void R_DrawTiltedTranslucentWaterSpan_8(void)
|
|||
bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift);
|
||||
if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL)
|
||||
{
|
||||
*dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dsrc++);
|
||||
*dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dsrc);
|
||||
}
|
||||
else
|
||||
{
|
||||
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
|
||||
*dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dsrc++);
|
||||
colormap = planezlight[tiltlighting[ds_x1]] + (ds_colormap - colormaps);
|
||||
*dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dsrc);
|
||||
}
|
||||
dest++;
|
||||
ds_x1++;
|
||||
dsrc++;
|
||||
u += stepu;
|
||||
v += stepv;
|
||||
}
|
||||
|
|
@ -1336,13 +1349,14 @@ void R_DrawTiltedTranslucentWaterSpan_8(void)
|
|||
bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift);
|
||||
if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL)
|
||||
{
|
||||
*dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dsrc++);
|
||||
*dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dsrc);
|
||||
}
|
||||
else
|
||||
{
|
||||
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
|
||||
*dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dsrc++);
|
||||
colormap = planezlight[tiltlighting[ds_x1]] + (ds_colormap - colormaps);
|
||||
*dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dsrc);
|
||||
}
|
||||
ds_x1++;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1365,14 +1379,16 @@ void R_DrawTiltedTranslucentWaterSpan_8(void)
|
|||
bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift);
|
||||
if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL)
|
||||
{
|
||||
*dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dsrc++);
|
||||
*dest = *(ds_transmap + (fullbright[source[bit]] << 8) + *dsrc);
|
||||
}
|
||||
else
|
||||
{
|
||||
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
|
||||
*dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dsrc++);
|
||||
colormap = planezlight[tiltlighting[ds_x1]] + (ds_colormap - colormaps);
|
||||
*dest = *(ds_transmap + (colormap[source[bit]] << 8) + *dsrc);
|
||||
}
|
||||
dest++;
|
||||
ds_x1++;
|
||||
dsrc++;
|
||||
u += stepu;
|
||||
v += stepv;
|
||||
}
|
||||
|
|
@ -1446,12 +1462,13 @@ void R_DrawTiltedSplat_8(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
|
||||
colormap = planezlight[tiltlighting[ds_x1]] + (ds_colormap - colormaps);
|
||||
*dest = colormap[val];
|
||||
}
|
||||
}
|
||||
|
||||
dest++;
|
||||
ds_x1++;
|
||||
iz += ds_szp->x;
|
||||
uz += ds_sup->x;
|
||||
vz += ds_svp->x;
|
||||
|
|
@ -1493,11 +1510,12 @@ void R_DrawTiltedSplat_8(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
|
||||
colormap = planezlight[tiltlighting[ds_x1]] + (ds_colormap - colormaps);
|
||||
*dest = colormap[val];
|
||||
}
|
||||
}
|
||||
dest++;
|
||||
ds_x1++;
|
||||
u += stepu;
|
||||
v += stepv;
|
||||
}
|
||||
|
|
@ -1521,9 +1539,10 @@ void R_DrawTiltedSplat_8(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
|
||||
colormap = planezlight[tiltlighting[ds_x1]] + (ds_colormap - colormaps);
|
||||
*dest = colormap[val];
|
||||
}
|
||||
ds_x1++;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
@ -1554,11 +1573,12 @@ void R_DrawTiltedSplat_8(void)
|
|||
}
|
||||
else
|
||||
{
|
||||
colormap = planezlight[tiltlighting[ds_x1++]] + (ds_colormap - colormaps);
|
||||
colormap = planezlight[tiltlighting[ds_x1]] + (ds_colormap - colormaps);
|
||||
*dest = colormap[val];
|
||||
}
|
||||
}
|
||||
dest++;
|
||||
ds_x1++;
|
||||
u += stepu;
|
||||
v += stepv;
|
||||
}
|
||||
|
|
@ -2338,17 +2358,18 @@ void R_DrawTranslucentWaterSpan_8(void)
|
|||
bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift);
|
||||
if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL)
|
||||
{
|
||||
dest[i] = fullbright[*(ds_transmap + (source[bit] << 8) + *dsrc++)];
|
||||
dest[i] = fullbright[*(ds_transmap + (source[bit] << 8) + dsrc[i])];
|
||||
}
|
||||
else
|
||||
{
|
||||
dest[i] = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)];
|
||||
dest[i] = colormap[*(ds_transmap + (source[bit] << 8) + dsrc[i])];
|
||||
}
|
||||
xposition += xstep;
|
||||
yposition += ystep;
|
||||
}
|
||||
|
||||
dest += 8;
|
||||
dsrc += 8;
|
||||
count -= 8;
|
||||
}
|
||||
while (count--)
|
||||
|
|
@ -2356,12 +2377,14 @@ void R_DrawTranslucentWaterSpan_8(void)
|
|||
bit = ((yposition >> nflatyshift) & nflatmask) | (xposition >> nflatxshift);
|
||||
if (brightmap != NULL && brightmap[bit] == BRIGHTPIXEL)
|
||||
{
|
||||
*dest++ = fullbright[*(ds_transmap + (source[bit] << 8) + *dsrc++)];
|
||||
*dest = fullbright[*(ds_transmap + (source[bit] << 8) + *dsrc)];
|
||||
}
|
||||
else
|
||||
{
|
||||
*dest++ = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc++)];
|
||||
*dest = colormap[*(ds_transmap + (source[bit] << 8) + *dsrc)];
|
||||
}
|
||||
dest++;
|
||||
dsrc++;
|
||||
xposition += xstep;
|
||||
yposition += ystep;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -316,7 +316,7 @@ void R_InterpolatePrecipMobjState(precipmobj_t *mobj, fixed_t frac, interpmobjst
|
|||
out->x = mobj->x;
|
||||
out->y = mobj->y;
|
||||
out->z = mobj->z;
|
||||
out->scale = FRACUNIT;
|
||||
out->scale = mapobjectscale;
|
||||
out->subsector = mobj->subsector;
|
||||
out->angle = mobj->angle;
|
||||
out->spritexscale = mobj->spritexscale;
|
||||
|
|
@ -329,7 +329,7 @@ void R_InterpolatePrecipMobjState(precipmobj_t *mobj, fixed_t frac, interpmobjst
|
|||
out->x = R_LerpFixed(mobj->old_x, mobj->x, frac);
|
||||
out->y = R_LerpFixed(mobj->old_y, mobj->y, frac);
|
||||
out->z = R_LerpFixed(mobj->old_z, mobj->z, frac);
|
||||
out->scale = FRACUNIT;
|
||||
out->scale = mapobjectscale;
|
||||
out->spritexscale = R_LerpFixed(mobj->old_spritexscale, mobj->spritexscale, frac);
|
||||
out->spriteyscale = R_LerpFixed(mobj->old_spriteyscale, mobj->spriteyscale, frac);
|
||||
out->spritexoffset = R_LerpFixed(mobj->old_spritexoffset, mobj->spritexoffset, frac);
|
||||
|
|
|
|||
|
|
@ -1322,6 +1322,8 @@ void R_SkyboxFrame(int s)
|
|||
|
||||
R_SetupAimingFrame(s);
|
||||
|
||||
newview->angle += r_viewmobj->angle;
|
||||
|
||||
newview->x = r_viewmobj->x;
|
||||
newview->y = r_viewmobj->y;
|
||||
newview->z = r_viewmobj->z; // 26/04/17: use actual Z position instead of spawnpoint angle!
|
||||
|
|
|
|||
|
|
@ -349,7 +349,7 @@ static visplane_t *new_visplane(unsigned hash)
|
|||
visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
|
||||
fixed_t xoff, fixed_t yoff, angle_t plangle, extracolormap_t *planecolormap,
|
||||
ffloor_t *pfloor, polyobj_t *polyobj, pslope_t *slope, boolean noencore,
|
||||
boolean ripple)
|
||||
boolean ripple, boolean reverseLight)
|
||||
{
|
||||
visplane_t *check;
|
||||
unsigned hash;
|
||||
|
|
@ -386,6 +386,18 @@ visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel,
|
|||
}
|
||||
}
|
||||
|
||||
if (slope != NULL && P_ApplyLightOffset(lightlevel >> LIGHTSEGSHIFT))
|
||||
{
|
||||
if (reverseLight && maplighting.directional == true)
|
||||
{
|
||||
lightlevel -= slope->lightOffset * 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
lightlevel += slope->lightOffset * 8;
|
||||
}
|
||||
}
|
||||
|
||||
// This appears to fix the Nimbus Ruins sky bug.
|
||||
if (picnum == skyflatnum && pfloor)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ void R_ClearFFloorClips (void);
|
|||
void R_DrawPlanes(void);
|
||||
visplane_t *R_FindPlane(fixed_t height, INT32 picnum, INT32 lightlevel, fixed_t xoff, fixed_t yoff, angle_t plangle,
|
||||
extracolormap_t *planecolormap, ffloor_t *ffloor, polyobj_t *polyobj, pslope_t *slope, boolean noencore,
|
||||
boolean ripple);
|
||||
boolean ripple, boolean reverseLight);
|
||||
visplane_t *R_CheckPlane(visplane_t *pl, INT32 start, INT32 stop);
|
||||
void R_ExpandPlane(visplane_t *pl, INT32 start, INT32 stop);
|
||||
void R_PlaneBounds(visplane_t *plane);
|
||||
|
|
|
|||
13
src/r_segs.c
13
src/r_segs.c
|
|
@ -286,7 +286,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
|
|||
|
||||
if (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG))
|
||||
;
|
||||
else
|
||||
else if (P_ApplyLightOffset(lightnum))
|
||||
lightnum += curline->lightOffset;
|
||||
|
||||
rlight->lightnum = lightnum;
|
||||
|
|
@ -303,7 +303,7 @@ void R_RenderMaskedSegRange(drawseg_t *ds, INT32 x1, INT32 x2)
|
|||
if ((R_CheckColumnFunc(COLDRAWFUNC_FOG) == true)
|
||||
|| (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)))
|
||||
;
|
||||
else
|
||||
else if (P_ApplyLightOffset(lightnum))
|
||||
lightnum += curline->lightOffset;
|
||||
|
||||
if (lightnum < 0)
|
||||
|
|
@ -770,7 +770,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
|
||||
if (pfloor->flags & FF_FOG || rlight->flags & FF_FOG || (rlight->extra_colormap && (rlight->extra_colormap->flags & CMF_FOG)))
|
||||
;
|
||||
else
|
||||
else if (P_ApplyLightOffset(rlight->lightnum))
|
||||
rlight->lightnum += curline->lightOffset;
|
||||
|
||||
p++;
|
||||
|
|
@ -793,7 +793,7 @@ void R_RenderThickSideRange(drawseg_t *ds, INT32 x1, INT32 x2, ffloor_t *pfloor)
|
|||
|
||||
if (pfloor->flags & FF_FOG || (frontsector->extra_colormap && (frontsector->extra_colormap->flags & CMF_FOG)))
|
||||
;
|
||||
else
|
||||
else if (P_ApplyLightOffset(lightnum))
|
||||
lightnum += curline->lightOffset;
|
||||
|
||||
if (lightnum < 0)
|
||||
|
|
@ -1383,7 +1383,7 @@ static void R_RenderSegLoop (void)
|
|||
|
||||
if (dc_lightlist[i].extra_colormap)
|
||||
;
|
||||
else
|
||||
else if (P_ApplyLightOffset(lightnum))
|
||||
lightnum += curline->lightOffset;
|
||||
|
||||
if (lightnum < 0)
|
||||
|
|
@ -2436,7 +2436,8 @@ void R_StoreWallRange(INT32 start, INT32 stop)
|
|||
// OPTIMIZE: get rid of LIGHTSEGSHIFT globally
|
||||
lightnum = (frontsector->lightlevel >> LIGHTSEGSHIFT);
|
||||
|
||||
lightnum += curline->lightOffset;
|
||||
if (P_ApplyLightOffset(lightnum))
|
||||
lightnum += curline->lightOffset;
|
||||
|
||||
if (lightnum < 0)
|
||||
walllights = scalelight[0];
|
||||
|
|
|
|||
321
src/r_things.c
321
src/r_things.c
|
|
@ -86,6 +86,35 @@ static spriteframe_t sprtemp[64];
|
|||
static size_t maxframe;
|
||||
static const char *spritename;
|
||||
|
||||
//
|
||||
// Clipping against drawsegs optimization, from prboom-plus
|
||||
//
|
||||
// TODO: This should be done with proper subsector pass through
|
||||
// sprites which would ideally remove the need to do it at all.
|
||||
// Unfortunately, SRB2's drawing loop has lots of annoying
|
||||
// changes from Doom for portals, which make it hard to implement.
|
||||
|
||||
typedef struct drawseg_xrange_item_s
|
||||
{
|
||||
INT16 x1, x2;
|
||||
drawseg_t *user;
|
||||
} drawseg_xrange_item_t;
|
||||
|
||||
typedef struct drawsegs_xrange_s
|
||||
{
|
||||
drawseg_xrange_item_t *items;
|
||||
INT32 count;
|
||||
} drawsegs_xrange_t;
|
||||
|
||||
#define DS_RANGES_COUNT 3
|
||||
static drawsegs_xrange_t drawsegs_xranges[DS_RANGES_COUNT];
|
||||
|
||||
static drawseg_xrange_item_t *drawsegs_xrange;
|
||||
static size_t drawsegs_xrange_size = 0;
|
||||
static INT32 drawsegs_xrange_count = 0;
|
||||
|
||||
#define CLIP_UNDEF -2
|
||||
|
||||
// ==========================================================================
|
||||
//
|
||||
// Sprite loading routines: support sprites in pwad, dehacked sprite renaming,
|
||||
|
|
@ -1034,6 +1063,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis)
|
|||
#endif
|
||||
fixed_t frac;
|
||||
patch_t *patch;
|
||||
fixed_t this_scale = vis->thingscale;
|
||||
INT64 overflow_test;
|
||||
|
||||
//Fab : R_InitSprites now sets a wad lump number
|
||||
|
|
@ -1061,7 +1091,7 @@ static void R_DrawPrecipitationVisSprite(vissprite_t *vis)
|
|||
}
|
||||
|
||||
dc_iscale = FixedDiv(FRACUNIT, vis->scale);
|
||||
dc_texturemid = vis->texturemid;
|
||||
dc_texturemid = FixedDiv(vis->texturemid, this_scale);
|
||||
dc_texheight = 0;
|
||||
|
||||
frac = vis->startfrac;
|
||||
|
|
@ -2187,6 +2217,10 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
|
||||
//SoM: 3/17/2000
|
||||
fixed_t gz, gzt;
|
||||
fixed_t this_scale;
|
||||
|
||||
UINT32 blendmode;
|
||||
UINT32 trans;
|
||||
|
||||
// uncapped/interpolation
|
||||
interpmobjstate_t interp = {0};
|
||||
|
|
@ -2201,6 +2235,8 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
R_InterpolatePrecipMobjState(thing, FRACUNIT, &interp);
|
||||
}
|
||||
|
||||
this_scale = interp.scale;
|
||||
|
||||
// transform the origin point
|
||||
tr_x = interp.x - viewx;
|
||||
tr_y = interp.y - viewy;
|
||||
|
|
@ -2208,7 +2244,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
tz = FixedMul(tr_x, viewcos) + FixedMul(tr_y, viewsin); // near/far distance
|
||||
|
||||
// thing is behind view plane?
|
||||
if (tz < MINZ)
|
||||
if (tz < FixedMul(MINZ, this_scale))
|
||||
return;
|
||||
|
||||
tx = FixedMul(tr_x, viewsin) - FixedMul(tr_y, viewcos); // sideways distance
|
||||
|
|
@ -2247,14 +2283,14 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
lump = sprframe->lumpid[0]; //Fab: see note above
|
||||
|
||||
// calculate edges of the shape
|
||||
tx -= spritecachedinfo[lump].offset;
|
||||
tx -= FixedMul(spritecachedinfo[lump].offset, this_scale);
|
||||
x1 = (centerxfrac + FixedMul (tx,xscale)) >>FRACBITS;
|
||||
|
||||
// off the right side?
|
||||
if (x1 > viewwidth)
|
||||
return;
|
||||
|
||||
tx += spritecachedinfo[lump].width;
|
||||
tx += FixedMul(spritecachedinfo[lump].width, this_scale);
|
||||
x2 = ((centerxfrac + FixedMul (tx,xscale)) >>FRACBITS) - 1;
|
||||
|
||||
// off the left side
|
||||
|
|
@ -2272,8 +2308,8 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
}
|
||||
|
||||
//SoM: 3/17/2000: Disregard sprites that are out of view..
|
||||
gzt = interp.z + spritecachedinfo[lump].topoffset;
|
||||
gz = gzt - spritecachedinfo[lump].height;
|
||||
gzt = interp.z + FixedMul(spritecachedinfo[lump].topoffset, this_scale);
|
||||
gz = gzt - FixedMul(spritecachedinfo[lump].height, this_scale);
|
||||
|
||||
if (thing->subsector->sector->cullheight)
|
||||
{
|
||||
|
|
@ -2281,9 +2317,22 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
goto weatherthink;
|
||||
}
|
||||
|
||||
// Determine the blendmode and translucency value
|
||||
{
|
||||
blendmode = (thing->frame & FF_BLENDMASK) >> FF_BLENDSHIFT;
|
||||
if (blendmode)
|
||||
blendmode++; // realign to constants
|
||||
|
||||
trans = (thing->frame & FF_TRANSMASK) >> FF_TRANSSHIFT;
|
||||
if (trans >= NUMTRANSMAPS)
|
||||
goto weatherthink; // cap
|
||||
}
|
||||
|
||||
// store information in a vissprite
|
||||
vis = R_NewVisSprite();
|
||||
vis->scale = vis->sortscale = yscale; //<<detailshift;
|
||||
vis->scale = FixedMul(yscale, this_scale);
|
||||
vis->sortscale = yscale; //<<detailshift;
|
||||
vis->thingscale = interp.scale;
|
||||
vis->dispoffset = 0; // Monster Iestyn: 23/11/15
|
||||
vis->gx = interp.x;
|
||||
vis->gy = interp.y;
|
||||
|
|
@ -2309,7 +2358,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
iscale = FixedDiv(FRACUNIT, xscale);
|
||||
|
||||
vis->startfrac = 0;
|
||||
vis->xiscale = iscale;
|
||||
vis->xiscale = FixedDiv(iscale, this_scale);
|
||||
|
||||
if (vis->x1 > x1)
|
||||
vis->startfrac += vis->xiscale*(vis->x1-x1);
|
||||
|
|
@ -2318,12 +2367,7 @@ static void R_ProjectPrecipitationSprite(precipmobj_t *thing)
|
|||
// than lumpid for sprites-in-pwad : the graphics are patched
|
||||
vis->patch = W_CachePatchNum(sprframe->lumppat[0], PU_SPRITE);
|
||||
|
||||
// specific translucency
|
||||
// (no draw flags)
|
||||
if (thing->frame & FF_TRANSMASK)
|
||||
vis->transmap = ((thing->frame & FF_TRANSMASK) - FF_TRANS10) + transtables;
|
||||
else
|
||||
vis->transmap = NULL;
|
||||
vis->transmap = R_GetBlendTable(blendmode, trans);
|
||||
|
||||
vis->mobj = (mobj_t *)thing;
|
||||
vis->mobjflags = 0;
|
||||
|
|
@ -2918,7 +2962,7 @@ static void R_DrawPrecipitationSprite(vissprite_t *spr)
|
|||
|
||||
// R_ClipVisSprite
|
||||
// Clips vissprites without drawing, so that portals can work. -Red
|
||||
void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, portal_t* portal)
|
||||
void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* portal)
|
||||
{
|
||||
drawseg_t *ds;
|
||||
INT32 x;
|
||||
|
|
@ -2929,7 +2973,9 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, p
|
|||
INT32 silhouette;
|
||||
|
||||
for (x = x1; x <= x2; x++)
|
||||
spr->clipbot[x] = spr->cliptop[x] = -2;
|
||||
{
|
||||
spr->clipbot[x] = spr->cliptop[x] = CLIP_UNDEF;
|
||||
}
|
||||
|
||||
// Scan drawsegs from end to start for obscuring segs.
|
||||
// The first drawseg that has a greater scale
|
||||
|
|
@ -2938,82 +2984,90 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, p
|
|||
// Pointer check was originally nonportable
|
||||
// and buggy, by going past LEFT end of array:
|
||||
|
||||
// for (ds = ds_p-1; ds >= drawsegs; ds--) old buggy code
|
||||
for (ds = ds_p; ds-- > dsstart;)
|
||||
// e6y: optimization
|
||||
if (drawsegs_xrange_size)
|
||||
{
|
||||
// determine if the drawseg obscures the sprite
|
||||
if (ds->x1 > x2 ||
|
||||
ds->x2 < x1 ||
|
||||
(!ds->silhouette
|
||||
&& !ds->maskedtexturecol))
|
||||
const drawseg_xrange_item_t *last = &drawsegs_xrange[drawsegs_xrange_count - 1];
|
||||
drawseg_xrange_item_t *curr = &drawsegs_xrange[-1];
|
||||
|
||||
while (++curr <= last)
|
||||
{
|
||||
// does not cover sprite
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ds->portalpass != 66)
|
||||
{
|
||||
if (ds->portalpass > 0 && ds->portalpass <= portalrender)
|
||||
continue; // is a portal
|
||||
|
||||
if (ds->scale1 > ds->scale2)
|
||||
// determine if the drawseg obscures the sprite
|
||||
if (curr->x1 > spr->x2 || curr->x2 < spr->x1)
|
||||
{
|
||||
lowscale = ds->scale2;
|
||||
scale = ds->scale1;
|
||||
}
|
||||
else
|
||||
{
|
||||
lowscale = ds->scale1;
|
||||
scale = ds->scale2;
|
||||
}
|
||||
|
||||
if (scale < spr->sortscale ||
|
||||
(lowscale < spr->sortscale &&
|
||||
!R_PointOnSegSide (spr->gx, spr->gy, ds->curline)))
|
||||
{
|
||||
// masked mid texture?
|
||||
/*if (ds->maskedtexturecol)
|
||||
R_RenderMaskedSegRange (ds, r1, r2);*/
|
||||
// seg is behind sprite
|
||||
// does not cover sprite
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
r1 = ds->x1 < x1 ? x1 : ds->x1;
|
||||
r2 = ds->x2 > x2 ? x2 : ds->x2;
|
||||
ds = curr->user;
|
||||
|
||||
// clip this piece of the sprite
|
||||
silhouette = ds->silhouette;
|
||||
|
||||
if (spr->gz >= ds->bsilheight)
|
||||
silhouette &= ~SIL_BOTTOM;
|
||||
|
||||
if (spr->gzt <= ds->tsilheight)
|
||||
silhouette &= ~SIL_TOP;
|
||||
|
||||
if (silhouette == SIL_BOTTOM)
|
||||
{
|
||||
// bottom sil
|
||||
for (x = r1; x <= r2; x++)
|
||||
if (spr->clipbot[x] == -2)
|
||||
spr->clipbot[x] = ds->sprbottomclip[x];
|
||||
}
|
||||
else if (silhouette == SIL_TOP)
|
||||
{
|
||||
// top sil
|
||||
for (x = r1; x <= r2; x++)
|
||||
if (spr->cliptop[x] == -2)
|
||||
spr->cliptop[x] = ds->sprtopclip[x];
|
||||
}
|
||||
else if (silhouette == (SIL_TOP|SIL_BOTTOM))
|
||||
{
|
||||
// both
|
||||
for (x = r1; x <= r2; x++)
|
||||
if (ds->portalpass != 66) // unused?
|
||||
{
|
||||
if (spr->clipbot[x] == -2)
|
||||
spr->clipbot[x] = ds->sprbottomclip[x];
|
||||
if (spr->cliptop[x] == -2)
|
||||
spr->cliptop[x] = ds->sprtopclip[x];
|
||||
if (ds->portalpass > 0 && ds->portalpass <= portalrender)
|
||||
continue; // is a portal
|
||||
|
||||
if (ds->scale1 > ds->scale2)
|
||||
{
|
||||
lowscale = ds->scale2;
|
||||
scale = ds->scale1;
|
||||
}
|
||||
else
|
||||
{
|
||||
lowscale = ds->scale1;
|
||||
scale = ds->scale2;
|
||||
}
|
||||
|
||||
if (scale < spr->sortscale ||
|
||||
(lowscale < spr->sortscale &&
|
||||
!R_PointOnSegSide (spr->gx, spr->gy, ds->curline)))
|
||||
{
|
||||
// masked mid texture?
|
||||
/*
|
||||
if (ds->maskedtexturecol)
|
||||
R_RenderMaskedSegRange (ds, r1, r2);
|
||||
*/
|
||||
|
||||
// seg is behind sprite
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
r1 = ds->x1 < x1 ? x1 : ds->x1;
|
||||
r2 = ds->x2 > x2 ? x2 : ds->x2;
|
||||
|
||||
// clip this piece of the sprite
|
||||
silhouette = ds->silhouette;
|
||||
|
||||
if (spr->gz >= ds->bsilheight)
|
||||
silhouette &= ~SIL_BOTTOM;
|
||||
|
||||
if (spr->gzt <= ds->tsilheight)
|
||||
silhouette &= ~SIL_TOP;
|
||||
|
||||
if (silhouette == SIL_BOTTOM)
|
||||
{
|
||||
// bottom sil
|
||||
for (x = r1; x <= r2; x++)
|
||||
if (spr->clipbot[x] == CLIP_UNDEF)
|
||||
spr->clipbot[x] = ds->sprbottomclip[x];
|
||||
}
|
||||
else if (silhouette == SIL_TOP)
|
||||
{
|
||||
// top sil
|
||||
for (x = r1; x <= r2; x++)
|
||||
if (spr->cliptop[x] == CLIP_UNDEF)
|
||||
spr->cliptop[x] = ds->sprtopclip[x];
|
||||
}
|
||||
else if (silhouette == (SIL_TOP|SIL_BOTTOM))
|
||||
{
|
||||
// both
|
||||
for (x = r1; x <= r2; x++)
|
||||
{
|
||||
if (spr->clipbot[x] == CLIP_UNDEF)
|
||||
spr->clipbot[x] = ds->sprbottomclip[x];
|
||||
if (spr->cliptop[x] == CLIP_UNDEF)
|
||||
spr->cliptop[x] = ds->sprtopclip[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3029,13 +3083,13 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, p
|
|||
if (mh <= 0 || (phs != -1 && viewz > sectors[phs].floorheight))
|
||||
{ // clip bottom
|
||||
for (x = x1; x <= x2; x++)
|
||||
if (spr->clipbot[x] == -2 || h < spr->clipbot[x])
|
||||
if (spr->clipbot[x] == CLIP_UNDEF || h < spr->clipbot[x])
|
||||
spr->clipbot[x] = (INT16)h;
|
||||
}
|
||||
else // clip top
|
||||
{
|
||||
for (x = x1; x <= x2; x++)
|
||||
if (spr->cliptop[x] == -2 || h > spr->cliptop[x])
|
||||
if (spr->cliptop[x] == CLIP_UNDEF || h > spr->cliptop[x])
|
||||
spr->cliptop[x] = (INT16)h;
|
||||
}
|
||||
}
|
||||
|
|
@ -3047,13 +3101,13 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, p
|
|||
if (phs != -1 && viewz >= sectors[phs].ceilingheight)
|
||||
{ // clip bottom
|
||||
for (x = x1; x <= x2; x++)
|
||||
if (spr->clipbot[x] == -2 || h < spr->clipbot[x])
|
||||
if (spr->clipbot[x] == CLIP_UNDEF || h < spr->clipbot[x])
|
||||
spr->clipbot[x] = (INT16)h;
|
||||
}
|
||||
else // clip top
|
||||
{
|
||||
for (x = x1; x <= x2; x++)
|
||||
if (spr->cliptop[x] == -2 || h > spr->cliptop[x])
|
||||
if (spr->cliptop[x] == CLIP_UNDEF || h > spr->cliptop[x])
|
||||
spr->cliptop[x] = (INT16)h;
|
||||
}
|
||||
}
|
||||
|
|
@ -3062,10 +3116,10 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, p
|
|||
{
|
||||
for (x = x1; x <= x2; x++)
|
||||
{
|
||||
if (spr->cliptop[x] == -2 || spr->szt > spr->cliptop[x])
|
||||
if (spr->cliptop[x] == CLIP_UNDEF || spr->szt > spr->cliptop[x])
|
||||
spr->cliptop[x] = spr->szt;
|
||||
|
||||
if (spr->clipbot[x] == -2 || spr->sz < spr->clipbot[x])
|
||||
if (spr->clipbot[x] == CLIP_UNDEF || spr->sz < spr->clipbot[x])
|
||||
spr->clipbot[x] = spr->sz;
|
||||
}
|
||||
}
|
||||
|
|
@ -3073,7 +3127,7 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, p
|
|||
{
|
||||
for (x = x1; x <= x2; x++)
|
||||
{
|
||||
if (spr->cliptop[x] == -2 || spr->szt > spr->cliptop[x])
|
||||
if (spr->cliptop[x] == CLIP_UNDEF || spr->szt > spr->cliptop[x])
|
||||
spr->cliptop[x] = spr->szt;
|
||||
}
|
||||
}
|
||||
|
|
@ -3081,7 +3135,7 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, p
|
|||
{
|
||||
for (x = x1; x <= x2; x++)
|
||||
{
|
||||
if (spr->clipbot[x] == -2 || spr->sz < spr->clipbot[x])
|
||||
if (spr->clipbot[x] == CLIP_UNDEF || spr->sz < spr->clipbot[x])
|
||||
spr->clipbot[x] = spr->sz;
|
||||
}
|
||||
}
|
||||
|
|
@ -3091,10 +3145,10 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, p
|
|||
// check for unclipped columns
|
||||
for (x = x1; x <= x2; x++)
|
||||
{
|
||||
if (spr->clipbot[x] == -2)
|
||||
if (spr->clipbot[x] == CLIP_UNDEF)
|
||||
spr->clipbot[x] = (INT16)viewheight;
|
||||
|
||||
if (spr->cliptop[x] == -2)
|
||||
if (spr->cliptop[x] == CLIP_UNDEF)
|
||||
//Fab : 26-04-98: was -1, now clips against console bottom
|
||||
spr->cliptop[x] = (INT16)con_clipviewtop;
|
||||
}
|
||||
|
|
@ -3125,12 +3179,89 @@ void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, p
|
|||
|
||||
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal)
|
||||
{
|
||||
const size_t maxdrawsegs = ds_p - dsstart;
|
||||
const INT32 cx = viewwidth / 2;
|
||||
drawseg_t* ds;
|
||||
INT32 i;
|
||||
|
||||
// e6y
|
||||
// Reducing of cache misses in the following R_DrawSprite()
|
||||
// Makes sense for scenes with huge amount of drawsegs.
|
||||
// ~12% of speed improvement on epic.wad map05
|
||||
for (i = 0; i < DS_RANGES_COUNT; i++)
|
||||
{
|
||||
drawsegs_xranges[i].count = 0;
|
||||
}
|
||||
|
||||
if (visspritecount - clippedvissprites <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (drawsegs_xrange_size < maxdrawsegs)
|
||||
{
|
||||
drawsegs_xrange_size = 2 * maxdrawsegs;
|
||||
|
||||
for (i = 0; i < DS_RANGES_COUNT; i++)
|
||||
{
|
||||
drawsegs_xranges[i].items = Z_Realloc(
|
||||
drawsegs_xranges[i].items,
|
||||
drawsegs_xrange_size * sizeof(drawsegs_xranges[i].items[0]),
|
||||
PU_STATIC, NULL
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (ds = ds_p; ds-- > dsstart;)
|
||||
{
|
||||
if (ds->silhouette || ds->maskedtexturecol)
|
||||
{
|
||||
drawsegs_xranges[0].items[drawsegs_xranges[0].count].x1 = ds->x1;
|
||||
drawsegs_xranges[0].items[drawsegs_xranges[0].count].x2 = ds->x2;
|
||||
drawsegs_xranges[0].items[drawsegs_xranges[0].count].user = ds;
|
||||
|
||||
// e6y: ~13% of speed improvement on sunder.wad map10
|
||||
if (ds->x1 < cx)
|
||||
{
|
||||
drawsegs_xranges[1].items[drawsegs_xranges[1].count] =
|
||||
drawsegs_xranges[0].items[drawsegs_xranges[0].count];
|
||||
drawsegs_xranges[1].count++;
|
||||
}
|
||||
|
||||
if (ds->x2 >= cx)
|
||||
{
|
||||
drawsegs_xranges[2].items[drawsegs_xranges[2].count] =
|
||||
drawsegs_xranges[0].items[drawsegs_xranges[0].count];
|
||||
drawsegs_xranges[2].count++;
|
||||
}
|
||||
|
||||
drawsegs_xranges[0].count++;
|
||||
}
|
||||
}
|
||||
|
||||
for (; clippedvissprites < visspritecount; clippedvissprites++)
|
||||
{
|
||||
vissprite_t *spr = R_GetVisSprite(clippedvissprites);
|
||||
INT32 x1 = (spr->cut & SC_SPLAT) ? 0 : spr->x1;
|
||||
INT32 x2 = (spr->cut & SC_SPLAT) ? viewwidth : spr->x2;
|
||||
R_ClipVisSprite(spr, x1, x2, dsstart, portal);
|
||||
|
||||
if (x2 < cx)
|
||||
{
|
||||
drawsegs_xrange = drawsegs_xranges[1].items;
|
||||
drawsegs_xrange_count = drawsegs_xranges[1].count;
|
||||
}
|
||||
else if (x1 >= cx)
|
||||
{
|
||||
drawsegs_xrange = drawsegs_xranges[2].items;
|
||||
drawsegs_xrange_count = drawsegs_xranges[2].count;
|
||||
}
|
||||
else
|
||||
{
|
||||
drawsegs_xrange = drawsegs_xranges[0].items;
|
||||
drawsegs_xrange_count = drawsegs_xranges[0].count;
|
||||
}
|
||||
|
||||
R_ClipVisSprite(spr, x1, x2, portal);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ typedef struct vissprite_s
|
|||
extern UINT32 visspritecount;
|
||||
|
||||
void R_ClipSprites(drawseg_t* dsstart, portal_t* portal);
|
||||
void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, drawseg_t* dsstart, portal_t* portal);
|
||||
void R_ClipVisSprite(vissprite_t *spr, INT32 x1, INT32 x2, portal_t* portal);
|
||||
|
||||
UINT8 *R_GetSpriteTranslation(vissprite_t *vis);
|
||||
|
||||
|
|
|
|||
|
|
@ -678,6 +678,14 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
|
|||
if (!sfx->data)
|
||||
{
|
||||
sfx->data = I_GetSfx(sfx);
|
||||
|
||||
if (!sfx->data)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING,
|
||||
"Tried to load invalid sfx_%s\n",
|
||||
sfx->name);
|
||||
return;/* don't play it */
|
||||
}
|
||||
}
|
||||
|
||||
// increase the usefulness
|
||||
|
|
|
|||
|
|
@ -79,11 +79,11 @@ if(${SDL2_FOUND})
|
|||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM} MATCHES Windows)
|
||||
set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME srb2win)
|
||||
set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME srb2kart)
|
||||
elseif(${CMAKE_SYSTEM} MATCHES Linux)
|
||||
set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME lsdlsrb2)
|
||||
set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME lsdlsrb2kart)
|
||||
else()
|
||||
set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME srb2)
|
||||
set_target_properties(SRB2SDL2 PROPERTIES OUTPUT_NAME srb2kart)
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM} MATCHES Darwin)
|
||||
|
|
@ -124,6 +124,14 @@ if(${SDL2_FOUND})
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM} MATCHES Windows AND ${CMAKE_C_COMPILER_ID} MATCHES "GNU" AND ${SRB2_SYSTEM_BITS} EQUAL 32)
|
||||
target_link_libraries(SRB2SDL2 PRIVATE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../libs/drmingw/lib/win32/libexchndl.a"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../libs/drmingw/lib/win32/libmgwhelp.a"
|
||||
)
|
||||
target_include_directories(SRB2SDL2 PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../libs/drmingw/include")
|
||||
endif()
|
||||
|
||||
#target_link_libraries(SRB2SDL2 PRIVATE SRB2Core)
|
||||
|
||||
if(${SRB2_USEASM})
|
||||
|
|
@ -168,24 +176,9 @@ if(${SDL2_FOUND})
|
|||
|
||||
target_compile_definitions(SRB2SDL2 PRIVATE
|
||||
-DDIRECTFULLSCREEN -DHAVE_SDL
|
||||
-DHAVE_THREADS
|
||||
)
|
||||
|
||||
## strip debug symbols into separate file when using gcc.
|
||||
## to be consistent with Makefile, don't generate for OS X.
|
||||
if((CMAKE_COMPILER_IS_GNUCC) AND NOT (${CMAKE_SYSTEM} MATCHES Darwin))
|
||||
if((${CMAKE_BUILD_TYPE} MATCHES Debug) OR (${CMAKE_BUILD_TYPE} MATCHES RelWithDebInfo))
|
||||
if(${CMAKE_BUILD_TYPE} MATCHES Debug)
|
||||
set(OBJCOPY_ONLY_KEEP_DEBUG "--only-keep-debug")
|
||||
endif()
|
||||
message(STATUS "Will make separate debug symbols in *.debug")
|
||||
add_custom_command(TARGET SRB2SDL2 POST_BUILD
|
||||
COMMAND ${OBJCOPY} ${OBJCOPY_ONLY_KEEP_DEBUG} $<TARGET_FILE:SRB2SDL2> $<TARGET_FILE:SRB2SDL2>.debug
|
||||
COMMAND ${OBJCOPY} --strip-debug $<TARGET_FILE:SRB2SDL2>
|
||||
COMMAND ${OBJCOPY} --add-gnu-debuglink=$<TARGET_FILE:SRB2SDL2>.debug $<TARGET_FILE:SRB2SDL2>
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#### Installation ####
|
||||
if(${CMAKE_SYSTEM} MATCHES Darwin)
|
||||
install(TARGETS SRB2SDL2
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue